 Chromium Code Reviews
 Chromium Code Reviews Issue 963343002:
  implement private members, fixes #74  (Closed) 
  Base URL: git@github.com:dart-lang/dev_compiler.git@master
    
  
    Issue 963343002:
  implement private members, fixes #74  (Closed) 
  Base URL: git@github.com:dart-lang/dev_compiler.git@master| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a | 
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. | 
| 4 | 4 | 
| 5 library ddc.src.codegen.js_codegen; | 5 library ddc.src.codegen.js_codegen; | 
| 6 | 6 | 
| 7 import 'dart:io' show Directory, File; | 7 import 'dart:io' show Directory, File; | 
| 8 | 8 | 
| 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 
| 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 
| (...skipping 27 matching lines...) Expand all Loading... | |
| 38 | 38 | 
| 39 /// The variable for the target of the current `..` cascade expression. | 39 /// The variable for the target of the current `..` cascade expression. | 
| 40 SimpleIdentifier _cascadeTarget; | 40 SimpleIdentifier _cascadeTarget; | 
| 41 | 41 | 
| 42 ClassDeclaration currentClass; | 42 ClassDeclaration currentClass; | 
| 43 ConstantEvaluator _constEvaluator; | 43 ConstantEvaluator _constEvaluator; | 
| 44 | 44 | 
| 45 final _exports = <String>[]; | 45 final _exports = <String>[]; | 
| 46 final _lazyFields = <VariableDeclaration>[]; | 46 final _lazyFields = <VariableDeclaration>[]; | 
| 47 final _properties = <FunctionDeclaration>[]; | 47 final _properties = <FunctionDeclaration>[]; | 
| 48 final _privateNames = new Set<String>(); | |
| 
Jennifer Messerly
2015/03/02 18:48:16
hmmm, another thought ... we could emit these as w
 | |
| 48 | 49 | 
| 49 JSCodegenVisitor(LibraryInfo libraryInfo, TypeRules rules) | 50 JSCodegenVisitor(LibraryInfo libraryInfo, TypeRules rules) | 
| 50 : libraryInfo = libraryInfo, | 51 : libraryInfo = libraryInfo, | 
| 51 rules = rules, | 52 rules = rules, | 
| 52 _libraryName = jsLibraryName(libraryInfo.library); | 53 _libraryName = jsLibraryName(libraryInfo.library); | 
| 53 | 54 | 
| 54 Element get currentLibrary => libraryInfo.library; | 55 Element get currentLibrary => libraryInfo.library; | 
| 55 | 56 | 
| 56 JS.Block generateLibrary( | 57 JS.Block generateLibrary( | 
| 57 Iterable<CompilationUnit> units, CheckerReporter reporter) { | 58 Iterable<CompilationUnit> units, CheckerReporter reporter) { | 
| (...skipping 10 matching lines...) Expand all Loading... | |
| 68 } | 69 } | 
| 69 | 70 | 
| 70 if (_exports.isNotEmpty) body.add(js.comment('Exports:')); | 71 if (_exports.isNotEmpty) body.add(js.comment('Exports:')); | 
| 71 | 72 | 
| 72 // TODO(jmesserly): make these immutable in JS? | 73 // TODO(jmesserly): make these immutable in JS? | 
| 73 for (var name in _exports) { | 74 for (var name in _exports) { | 
| 74 body.add(js.statement('#.# = #;', [_libraryName, name, name])); | 75 body.add(js.statement('#.# = #;', [_libraryName, name, name])); | 
| 75 } | 76 } | 
| 76 | 77 | 
| 77 var name = _libraryName; | 78 var name = _libraryName; | 
| 79 var symbolInit = _privateNames.map(_initPrivateSymbol); | |
| 78 return new JS.Block([ | 80 return new JS.Block([ | 
| 79 js.statement('var #;', name), | 81 js.statement('var #;', name), | 
| 80 js.statement(''' | 82 js.statement("(function (#) { 'use strict'; #; #; })(# || (# = {}));", | 
| 81 (function (#) { | 83 [name, symbolInit, body, name, name]) | 
| 82 'use strict'; | |
| 83 #; | |
| 84 })(# || (# = {})); | |
| 85 ''', [name, body, name, name]) | |
| 86 ]); | 84 ]); | 
| 87 } | 85 } | 
| 88 | 86 | 
| 87 JS.Statement _initPrivateSymbol(String name) => | |
| 88 js.statement('let # = Symbol(#);', [name, js.string(name, "'")]); | |
| 89 | |
| 89 @override | 90 @override | 
| 90 JS.Statement visitCompilationUnit(CompilationUnit node) { | 91 JS.Statement visitCompilationUnit(CompilationUnit node) { | 
| 91 // TODO(jmesserly): scriptTag, directives. | 92 // TODO(jmesserly): scriptTag, directives. | 
| 92 var body = <JS.Statement>[]; | 93 var body = <JS.Statement>[]; | 
| 93 for (var child in node.declarations) { | 94 for (var child in node.declarations) { | 
| 94 // Attempt to group adjacent fields/properties. | 95 // Attempt to group adjacent fields/properties. | 
| 95 if (child is! TopLevelVariableDeclaration) _flushLazyFields(body); | 96 if (child is! TopLevelVariableDeclaration) _flushLazyFields(body); | 
| 96 if (child is! FunctionDeclaration) _flushLibraryProperties(body); | 97 if (child is! FunctionDeclaration) _flushLibraryProperties(body); | 
| 97 | 98 | 
| 98 var code = _visit(child); | 99 var code = _visit(child); | 
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 395 return new JS.Block(body)..sourceInformation = node; | 396 return new JS.Block(body)..sourceInformation = node; | 
| 396 } | 397 } | 
| 397 | 398 | 
| 398 @override | 399 @override | 
| 399 JS.Statement visitRedirectingConstructorInvocation( | 400 JS.Statement visitRedirectingConstructorInvocation( | 
| 400 RedirectingConstructorInvocation node) { | 401 RedirectingConstructorInvocation node) { | 
| 401 ClassDeclaration classDecl = node.parent.parent; | 402 ClassDeclaration classDecl = node.parent.parent; | 
| 402 var className = classDecl.name.name; | 403 var className = classDecl.name.name; | 
| 403 | 404 | 
| 404 var name = _constructorName(className, node.constructorName); | 405 var name = _constructorName(className, node.constructorName); | 
| 405 return js.statement('this.#(#);', [name, _visit(node.argumentList)]); | 406 return js.statement('this.#(#);', | 
| 407 [_jsMemberName(name), _visit(node.argumentList)]); | |
| 406 } | 408 } | 
| 407 | 409 | 
| 408 JS.Statement _superConstructorCall(ClassDeclaration clazz, | 410 JS.Statement _superConstructorCall(ClassDeclaration clazz, | 
| 409 [SuperConstructorInvocation node]) { | 411 [SuperConstructorInvocation node]) { | 
| 410 var superCtorName = node != null ? node.constructorName : null; | 412 var superCtorName = node != null ? node.constructorName : null; | 
| 411 | 413 | 
| 412 var element = clazz.element; | 414 var element = clazz.element; | 
| 413 if (superCtorName == null && | 415 if (superCtorName == null && | 
| 414 (element.type.isObject || element.supertype.isObject)) { | 416 (element.type.isObject || element.supertype.isObject)) { | 
| 415 return null; | 417 return null; | 
| (...skipping 29 matching lines...) Expand all Loading... | |
| 445 } | 447 } | 
| 446 } | 448 } | 
| 447 } | 449 } | 
| 448 | 450 | 
| 449 // Initialize fields from `this.fieldName` parameters. | 451 // Initialize fields from `this.fieldName` parameters. | 
| 450 if (parameters != null) { | 452 if (parameters != null) { | 
| 451 for (var p in parameters.parameters) { | 453 for (var p in parameters.parameters) { | 
| 452 if (p is DefaultFormalParameter) p = p.parameter; | 454 if (p is DefaultFormalParameter) p = p.parameter; | 
| 453 if (p is FieldFormalParameter) { | 455 if (p is FieldFormalParameter) { | 
| 454 var name = p.identifier.name; | 456 var name = p.identifier.name; | 
| 455 body.add(js.statement('this.# = #;', [name, name])); | 457 body.add(js.statement('this.# = #;', | 
| 458 [_jsMemberName(name), _visit(p)])); | |
| 456 unsetFields.remove(name); | 459 unsetFields.remove(name); | 
| 457 } | 460 } | 
| 458 } | 461 } | 
| 459 } | 462 } | 
| 460 | 463 | 
| 461 // Run constructor field initializers such as `: foo = bar.baz` | 464 // Run constructor field initializers such as `: foo = bar.baz` | 
| 462 if (initializers != null) { | 465 if (initializers != null) { | 
| 463 for (var init in initializers) { | 466 for (var init in initializers) { | 
| 464 if (init is ConstructorFieldInitializer) { | 467 if (init is ConstructorFieldInitializer) { | 
| 465 body.add(js.statement( | 468 body.add(js.statement( | 
| 466 '# = #;', [_visit(init.fieldName), _visit(init.expression)])); | 469 '# = #;', [_visit(init.fieldName), _visit(init.expression)])); | 
| 467 unsetFields.remove(init.fieldName.name); | 470 unsetFields.remove(init.fieldName.name); | 
| 468 } | 471 } | 
| 469 } | 472 } | 
| 470 } | 473 } | 
| 471 | 474 | 
| 472 // Initialize all remaining fields | 475 // Initialize all remaining fields | 
| 473 unsetFields.forEach((name, field) { | 476 unsetFields.forEach((name, field) { | 
| 474 JS.Expression value; | 477 JS.Expression value; | 
| 475 if (field.initializer != null) { | 478 if (field.initializer != null) { | 
| 476 value = _visit(field.initializer); | 479 value = _visit(field.initializer); | 
| 477 } else { | 480 } else { | 
| 478 var type = rules.elementType(field.element); | 481 var type = rules.elementType(field.element); | 
| 479 if (rules.maybeNonNullableType(type)) { | 482 if (rules.maybeNonNullableType(type)) { | 
| 480 value = js.call('dart.as(null, #)', _emitTypeName(type)); | 483 value = js.call('dart.as(null, #)', _emitTypeName(type)); | 
| 481 } else { | 484 } else { | 
| 482 value = new JS.LiteralNull(); | 485 value = new JS.LiteralNull(); | 
| 483 } | 486 } | 
| 484 } | 487 } | 
| 485 body.add(js.statement('this.# = #;', [name, value])); | 488 body.add(js.statement('this.# = #;', [_jsMemberName(name), value])); | 
| 486 }); | 489 }); | 
| 487 | 490 | 
| 488 return _statement(body); | 491 return _statement(body); | 
| 489 } | 492 } | 
| 490 | 493 | 
| 491 FormalParameterList _parametersOf(node) { | 494 FormalParameterList _parametersOf(node) { | 
| 492 // Note: ConstructorDeclaration is intentionally skipped here so we can | 495 // Note: ConstructorDeclaration is intentionally skipped here so we can | 
| 493 // emit the argument initializers in a different place. | 496 // emit the argument initializers in a different place. | 
| 494 // TODO(jmesserly): clean this up. If we can model ES6 spread/rest args, we | 497 // TODO(jmesserly): clean this up. If we can model ES6 spread/rest args, we | 
| 495 // could handle argument initializers more consistently in a separate | 498 // could handle argument initializers more consistently in a separate | 
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 543 | 546 | 
| 544 @override | 547 @override | 
| 545 JS.Method visitMethodDeclaration(MethodDeclaration node) { | 548 JS.Method visitMethodDeclaration(MethodDeclaration node) { | 
| 546 if (node.isAbstract || _externalOrNative(node)) { | 549 if (node.isAbstract || _externalOrNative(node)) { | 
| 547 return null; | 550 return null; | 
| 548 } | 551 } | 
| 549 | 552 | 
| 550 var params = _visit(node.parameters); | 553 var params = _visit(node.parameters); | 
| 551 if (params == null) params = []; | 554 if (params == null) params = []; | 
| 552 | 555 | 
| 553 return new JS.Method(new JS.PropertyName(_jsMethodName(node.name.name)), | 556 return new JS.Method(_jsMemberName(node.name.name), | 
| 554 new JS.Fun(params, _visit(node.body)), | 557 new JS.Fun(params, _visit(node.body)), | 
| 555 isGetter: node.isGetter, | 558 isGetter: node.isGetter, | 
| 556 isSetter: node.isSetter, | 559 isSetter: node.isSetter, | 
| 557 isStatic: node.isStatic); | 560 isStatic: node.isStatic); | 
| 558 } | 561 } | 
| 559 | 562 | 
| 560 @override | 563 @override | 
| 561 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { | 564 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { | 
| 562 assert(node.parent is CompilationUnit); | 565 assert(node.parent is CompilationUnit); | 
| 563 | 566 | 
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 636 var e = node.staticElement; | 639 var e = node.staticElement; | 
| 637 if (e == null) { | 640 if (e == null) { | 
| 638 return js.commentExpression( | 641 return js.commentExpression( | 
| 639 'Unimplemented unknown name', new JS.VariableUse(node.name)); | 642 'Unimplemented unknown name', new JS.VariableUse(node.name)); | 
| 640 } | 643 } | 
| 641 var name = node.name; | 644 var name = node.name; | 
| 642 if (e.enclosingElement is CompilationUnitElement && | 645 if (e.enclosingElement is CompilationUnitElement && | 
| 643 (e.library != libraryInfo.library || _needsModuleGetter(e))) { | 646 (e.library != libraryInfo.library || _needsModuleGetter(e))) { | 
| 644 return js.call('#.#', [jsLibraryName(e.library), name]); | 647 return js.call('#.#', [jsLibraryName(e.library), name]); | 
| 645 } else if (currentClass != null && _needsImplicitThis(e)) { | 648 } else if (currentClass != null && _needsImplicitThis(e)) { | 
| 646 return js.call('this.#', name); | 649 return js.call('this.#', _jsMemberName(name)); | 
| 650 } else if (e is ParameterElement && e.isInitializingFormal) { | |
| 651 name = _fieldParameterName(name); | |
| 647 } | 652 } | 
| 648 return new JS.VariableUse(name); | 653 return new JS.VariableUse(name); | 
| 649 } | 654 } | 
| 650 | 655 | 
| 651 JS.Expression _emitTypeName(DartType type) { | 656 JS.Expression _emitTypeName(DartType type) { | 
| 652 var name = type.name; | 657 var name = type.name; | 
| 653 var lib = type.element.library; | 658 var lib = type.element.library; | 
| 654 if (name == '') { | 659 if (name == '') { | 
| 655 // TODO(jmesserly): remove when we're using coercion reifier. | 660 // TODO(jmesserly): remove when we're using coercion reifier. | 
| 656 return _unimplementedCall('Unimplemented type $type'); | 661 return _unimplementedCall('Unimplemented type $type'); | 
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 843 } | 848 } | 
| 844 | 849 | 
| 845 @override | 850 @override | 
| 846 List<JS.Parameter> visitFormalParameterList(FormalParameterList node) { | 851 List<JS.Parameter> visitFormalParameterList(FormalParameterList node) { | 
| 847 var result = <JS.Parameter>[]; | 852 var result = <JS.Parameter>[]; | 
| 848 for (FormalParameter param in node.parameters) { | 853 for (FormalParameter param in node.parameters) { | 
| 849 if (param.kind == ParameterKind.NAMED) { | 854 if (param.kind == ParameterKind.NAMED) { | 
| 850 result.add(new JS.Parameter(_jsNamedParameterName)); | 855 result.add(new JS.Parameter(_jsNamedParameterName)); | 
| 851 break; | 856 break; | 
| 852 } | 857 } | 
| 853 result.add(new JS.Parameter(param.identifier.name)); | 858 result.add(_visit(param)); | 
| 854 } | 859 } | 
| 855 return result; | 860 return result; | 
| 856 } | 861 } | 
| 857 | 862 | 
| 858 @override | 863 @override | 
| 859 JS.Statement visitExpressionStatement(ExpressionStatement node) => | 864 JS.Statement visitExpressionStatement(ExpressionStatement node) => | 
| 860 _expressionStatement(_visit(node.expression)); | 865 _expressionStatement(_visit(node.expression)); | 
| 861 | 866 | 
| 862 // Some expressions may choose to generate themselves as JS statements | 867 // Some expressions may choose to generate themselves as JS statements | 
| 863 // if their parent is in a statement context. | 868 // if their parent is in a statement context. | 
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1207 } | 1212 } | 
| 1208 return false; | 1213 return false; | 
| 1209 } | 1214 } | 
| 1210 | 1215 | 
| 1211 @override | 1216 @override | 
| 1212 visitParenthesizedExpression(ParenthesizedExpression node) => | 1217 visitParenthesizedExpression(ParenthesizedExpression node) => | 
| 1213 // The printer handles precedence so we don't need to. | 1218 // The printer handles precedence so we don't need to. | 
| 1214 _visit(node.expression); | 1219 _visit(node.expression); | 
| 1215 | 1220 | 
| 1216 @override | 1221 @override | 
| 1217 visitSimpleFormalParameter(SimpleFormalParameter node) => | 1222 visitFormalParameter(FormalParameter node) => | 
| 1218 _visit(node.identifier); | 1223 new JS.Parameter(node.identifier.name); | 
| 1219 | 1224 | 
| 1220 @override | 1225 @override | 
| 1221 visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) => | 1226 visitFieldFormalParameter(FieldFormalParameter node) => | 
| 1222 _visit(node.identifier); | 1227 new JS.Parameter(_fieldParameterName(node.identifier.name)); | 
| 1228 | |
| 1229 /// Rename private names so they don't shadow the private field symbol. | |
| 1230 // TODO(jmesserly): replace this ad-hoc rename with a general strategy. | |
| 1231 _fieldParameterName(name) => name.startsWith('_') ? '\$$name' : name; | |
| 1223 | 1232 | 
| 1224 @override | 1233 @override | 
| 1225 JS.This visitThisExpression(ThisExpression node) => new JS.This(); | 1234 JS.This visitThisExpression(ThisExpression node) => new JS.This(); | 
| 1226 | 1235 | 
| 1227 @override | 1236 @override | 
| 1228 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super(); | 1237 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super(); | 
| 1229 | 1238 | 
| 1230 @override | 1239 @override | 
| 1231 visitPrefixedIdentifier(PrefixedIdentifier node) { | 1240 visitPrefixedIdentifier(PrefixedIdentifier node) { | 
| 1232 if (node.prefix.staticElement is PrefixElement) { | 1241 if (node.prefix.staticElement is PrefixElement) { | 
| 1233 return _visit(node.identifier); | 1242 return _visit(node.identifier); | 
| 1234 } else { | 1243 } else { | 
| 1235 return _visitGet(node.prefix, node.identifier); | 1244 return _visitGet(node.prefix, node.identifier); | 
| 1236 } | 1245 } | 
| 1237 } | 1246 } | 
| 1238 | 1247 | 
| 1239 @override | 1248 @override | 
| 1240 visitPropertyAccess(PropertyAccess node) => | 1249 visitPropertyAccess(PropertyAccess node) => | 
| 1241 _visitGet(_getTarget(node), node.propertyName); | 1250 _visitGet(_getTarget(node), node.propertyName); | 
| 1242 | 1251 | 
| 1243 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. | 1252 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. | 
| 1244 _visitGet(Expression target, SimpleIdentifier name) { | 1253 _visitGet(Expression target, SimpleIdentifier name) { | 
| 1245 if (rules.isDynamicTarget(target)) { | 1254 if (rules.isDynamicTarget(target)) { | 
| 1246 return js.call( | 1255 return js.call( | 
| 1247 'dart.dload(#, #)', [_visit(target), js.string(name.name, "'")]); | 1256 'dart.dload(#, #)', [_visit(target), js.string(name.name, "'")]); | 
| 1248 } else { | 1257 } else { | 
| 1249 return js.call('#.#', [_visit(target), name.name]); | 1258 return js.call('#.#', [_visit(target), _jsMemberName(name.name)]); | 
| 1250 } | 1259 } | 
| 1251 } | 1260 } | 
| 1252 | 1261 | 
| 1253 @override | 1262 @override | 
| 1254 visitIndexExpression(IndexExpression node) { | 1263 visitIndexExpression(IndexExpression node) { | 
| 1255 var target = _getTarget(node); | 1264 var target = _getTarget(node); | 
| 1256 var code; | 1265 var code; | 
| 1257 if (rules.isDynamicTarget(target)) { | 1266 if (rules.isDynamicTarget(target)) { | 
| 1258 code = 'dart.dindex(#, #)'; | 1267 code = 'dart.dindex(#, #)'; | 
| 1259 } else { | 1268 } else { | 
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1587 var jsExpr = _visit(node); | 1596 var jsExpr = _visit(node); | 
| 1588 if (result == null) { | 1597 if (result == null) { | 
| 1589 result = jsExpr; | 1598 result = jsExpr; | 
| 1590 } else { | 1599 } else { | 
| 1591 result = new JS.Binary(operator, result, jsExpr); | 1600 result = new JS.Binary(operator, result, jsExpr); | 
| 1592 } | 1601 } | 
| 1593 } | 1602 } | 
| 1594 return result; | 1603 return result; | 
| 1595 } | 1604 } | 
| 1596 | 1605 | 
| 1597 /// The following names are allowed for user-defined operators: | 1606 /// This handles member renaming for private names and operators. | 
| 1607 /// | |
| 1608 /// Private names are generated using ES6 symbols: | |
| 1609 /// | |
| 1610 /// // At the top of the module: | |
| 1611 /// let _x = Symbol('_x'); | |
| 1612 /// let _y = Symbol('_y'); | |
| 1613 /// ... | |
| 1614 /// | |
| 1615 /// class Point { | |
| 1616 /// Point(x, y) { | |
| 1617 /// this[_x] = x; | |
| 1618 /// this[_y] = y; | |
| 1619 /// } | |
| 1620 /// get x() { return this[_x]; } | |
| 1621 /// get y() { return this[_y]; } | |
| 1622 /// } | |
| 1623 /// | |
| 1624 /// For user-defined operators the following names are allowed: | |
| 1598 /// | 1625 /// | 
| 1599 /// <, >, <=, >=, ==, -, +, /, ˜/, *, %, |, ˆ, &, <<, >>, []=, [], ˜ | 1626 /// <, >, <=, >=, ==, -, +, /, ˜/, *, %, |, ˆ, &, <<, >>, []=, [], ˜ | 
| 1600 /// | 1627 /// | 
| 1601 /// For the indexing operators, we use `get` and `set` instead: | 1628 /// They generate code like: | 
| 1629 /// | |
| 1630 /// x['+'](y) | |
| 1631 /// | |
| 1632 /// There are three exceptions: [], []= and unary -. | |
| 1633 /// The indexing operators we use `get` and `set` instead: | |
| 1602 /// | 1634 /// | 
| 1603 /// x.get('hi') | 1635 /// x.get('hi') | 
| 1604 /// x.set('hi', 123) | 1636 /// x.set('hi', 123) | 
| 1605 /// | 1637 /// | 
| 1606 /// This follows the same pattern as EcmaScript 6 Map: | 1638 /// This follows the same pattern as EcmaScript 6 Map: | 
| 1607 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_ Objects/Map> | 1639 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_ Objects/Map> | 
| 1608 /// | 1640 /// | 
| 1609 /// For all others we use the operator name: | 1641 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed | 
| 1610 /// | 1642 /// for this transformation to happen, otherwise binary minus is assumed. | 
| 1611 /// x['+'](y) | |
| 1612 /// | 1643 /// | 
| 1613 /// Equality is a bit special, it is generated via the Dart `equals` runtime | 1644 /// Equality is a bit special, it is generated via the Dart `equals` runtime | 
| 1614 /// helper, that checks for null. The user defined method is called '=='. | 1645 /// helper, that checks for null. The user defined method is called '=='. | 
| 1615 String _jsMethodName(String name) { | 1646 /// | 
| 1616 if (name == '[]') return 'get'; | 1647 JS.Expression _jsMemberName(String name, {bool unary: false}) { | 
| 1617 if (name == '[]=') return 'set'; | 1648 if (name.startsWith('_')) { | 
| 1618 return name; | 1649 _privateNames.add(name); | 
| 1650 return new JS.VariableUse(name); | |
| 1651 } | |
| 1652 if (name == '[]') { | |
| 1653 name = 'get'; | |
| 1654 } else if (name == '[]=') { | |
| 1655 name = 'set'; | |
| 1656 } else if (unary && name == '-') { | |
| 1657 name = 'unary-'; | |
| 1658 } | |
| 1659 return new JS.PropertyName(name); | |
| 1619 } | 1660 } | 
| 1620 | 1661 | 
| 1621 bool _externalOrNative(node) => | 1662 bool _externalOrNative(node) => | 
| 1622 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; | 1663 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; | 
| 1623 | 1664 | 
| 1624 FunctionBody _functionBody(node) => | 1665 FunctionBody _functionBody(node) => | 
| 1625 node is FunctionDeclaration ? node.functionExpression.body : node.body; | 1666 node is FunctionDeclaration ? node.functionExpression.body : node.body; | 
| 1626 | 1667 | 
| 1627 String _maybeBindThis(node) { | 1668 String _maybeBindThis(node) { | 
| 1628 if (currentClass == null) return ''; | 1669 if (currentClass == null) return ''; | 
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1821 | 1862 | 
| 1822 // TODO(jmesserly): in many cases marking the end will be unncessary. | 1863 // TODO(jmesserly): in many cases marking the end will be unncessary. | 
| 1823 printer.mark(_location(node.end)); | 1864 printer.mark(_location(node.end)); | 
| 1824 } | 1865 } | 
| 1825 | 1866 | 
| 1826 String _getIdentifier(AstNode node) { | 1867 String _getIdentifier(AstNode node) { | 
| 1827 if (node is SimpleIdentifier) return node.name; | 1868 if (node is SimpleIdentifier) return node.name; | 
| 1828 return null; | 1869 return null; | 
| 1829 } | 1870 } | 
| 1830 } | 1871 } | 
| OLD | NEW |