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 28 matching lines...) Expand all Loading... |
39 SimpleIdentifier _cascadeTarget; | 39 SimpleIdentifier _cascadeTarget; |
40 /// The variable for the current catch clause | 40 /// The variable for the current catch clause |
41 String _catchParameter; | 41 String _catchParameter; |
42 | 42 |
43 ClassDeclaration currentClass; | 43 ClassDeclaration currentClass; |
44 ConstantEvaluator _constEvaluator; | 44 ConstantEvaluator _constEvaluator; |
45 | 45 |
46 final _exports = <String>[]; | 46 final _exports = <String>[]; |
47 final _lazyFields = <VariableDeclaration>[]; | 47 final _lazyFields = <VariableDeclaration>[]; |
48 final _properties = <FunctionDeclaration>[]; | 48 final _properties = <FunctionDeclaration>[]; |
| 49 final _privateNames = new Set<String>(); |
49 | 50 |
50 JSCodegenVisitor(LibraryInfo libraryInfo, TypeRules rules) | 51 JSCodegenVisitor(LibraryInfo libraryInfo, TypeRules rules) |
51 : libraryInfo = libraryInfo, | 52 : libraryInfo = libraryInfo, |
52 rules = rules; | 53 rules = rules; |
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) { |
58 var body = <JS.Statement>[]; | 59 var body = <JS.Statement>[]; |
(...skipping 11 matching lines...) Expand all Loading... |
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('$_EXPORTS.# = #;', [name, name])); | 75 body.add(js.statement('$_EXPORTS.# = #;', [name, name])); |
75 } | 76 } |
76 | 77 |
77 var name = jsLibraryName(libraryInfo.library); | 78 var name = jsLibraryName(libraryInfo.library); |
78 return new JS.Block([ | 79 return new JS.Block([ |
79 js.statement('var #;', name), | 80 js.statement('var #;', name), |
80 js.statement(''' | 81 js.statement("(function($_EXPORTS){'use strict'; #; #;})(# || (# = {}));", |
81 (function ($_EXPORTS) { | 82 [_privateNames.map(_initPrivateSymbol), body, name, name]) |
82 'use strict'; | |
83 #; | |
84 })(# || (# = {})); | |
85 ''', [body, name, name]) | |
86 ]); | 83 ]); |
87 } | 84 } |
88 | 85 |
| 86 JS.Statement _initPrivateSymbol(String name) => |
| 87 js.statement('let # = Symbol(#);', [name, js.string(name, "'")]); |
| 88 |
89 @override | 89 @override |
90 JS.Statement visitCompilationUnit(CompilationUnit node) { | 90 JS.Statement visitCompilationUnit(CompilationUnit node) { |
91 // TODO(jmesserly): scriptTag, directives. | 91 // TODO(jmesserly): scriptTag, directives. |
92 var body = <JS.Statement>[]; | 92 var body = <JS.Statement>[]; |
93 for (var child in node.declarations) { | 93 for (var child in node.declarations) { |
94 // Attempt to group adjacent fields/properties. | 94 // Attempt to group adjacent fields/properties. |
95 if (child is! TopLevelVariableDeclaration) _flushLazyFields(body); | 95 if (child is! TopLevelVariableDeclaration) _flushLazyFields(body); |
96 if (child is! FunctionDeclaration) _flushLibraryProperties(body); | 96 if (child is! FunctionDeclaration) _flushLibraryProperties(body); |
97 | 97 |
98 var code = _visit(child); | 98 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; | 395 return new JS.Block(body)..sourceInformation = node; |
396 } | 396 } |
397 | 397 |
398 @override | 398 @override |
399 JS.Statement visitRedirectingConstructorInvocation( | 399 JS.Statement visitRedirectingConstructorInvocation( |
400 RedirectingConstructorInvocation node) { | 400 RedirectingConstructorInvocation node) { |
401 ClassDeclaration classDecl = node.parent.parent; | 401 ClassDeclaration classDecl = node.parent.parent; |
402 var className = classDecl.name.name; | 402 var className = classDecl.name.name; |
403 | 403 |
404 var name = _constructorName(className, node.constructorName); | 404 var name = _constructorName(className, node.constructorName); |
405 return js.statement('this.#(#);', [name, _visit(node.argumentList)]); | 405 return js.statement( |
| 406 'this.#(#);', [_jsMemberName(name), _visit(node.argumentList)]); |
406 } | 407 } |
407 | 408 |
408 JS.Statement _superConstructorCall(ClassDeclaration clazz, | 409 JS.Statement _superConstructorCall(ClassDeclaration clazz, |
409 [SuperConstructorInvocation node]) { | 410 [SuperConstructorInvocation node]) { |
410 var superCtorName = node != null ? node.constructorName : null; | 411 var superCtorName = node != null ? node.constructorName : null; |
411 | 412 |
412 var element = clazz.element; | 413 var element = clazz.element; |
413 if (superCtorName == null && | 414 if (superCtorName == null && |
414 (element.type.isObject || element.supertype.isObject)) { | 415 (element.type.isObject || element.supertype.isObject)) { |
415 return null; | 416 return null; |
(...skipping 29 matching lines...) Expand all Loading... |
445 } | 446 } |
446 } | 447 } |
447 } | 448 } |
448 | 449 |
449 // Initialize fields from `this.fieldName` parameters. | 450 // Initialize fields from `this.fieldName` parameters. |
450 if (parameters != null) { | 451 if (parameters != null) { |
451 for (var p in parameters.parameters) { | 452 for (var p in parameters.parameters) { |
452 if (p is DefaultFormalParameter) p = p.parameter; | 453 if (p is DefaultFormalParameter) p = p.parameter; |
453 if (p is FieldFormalParameter) { | 454 if (p is FieldFormalParameter) { |
454 var name = p.identifier.name; | 455 var name = p.identifier.name; |
455 body.add(js.statement('this.# = #;', [name, name])); | 456 body.add( |
| 457 js.statement('this.# = #;', [_jsMemberName(name), _visit(p)])); |
456 unsetFields.remove(name); | 458 unsetFields.remove(name); |
457 } | 459 } |
458 } | 460 } |
459 } | 461 } |
460 | 462 |
461 // Run constructor field initializers such as `: foo = bar.baz` | 463 // Run constructor field initializers such as `: foo = bar.baz` |
462 if (initializers != null) { | 464 if (initializers != null) { |
463 for (var init in initializers) { | 465 for (var init in initializers) { |
464 if (init is ConstructorFieldInitializer) { | 466 if (init is ConstructorFieldInitializer) { |
465 body.add(js.statement( | 467 body.add(js.statement( |
466 '# = #;', [_visit(init.fieldName), _visit(init.expression)])); | 468 '# = #;', [_visit(init.fieldName), _visit(init.expression)])); |
467 unsetFields.remove(init.fieldName.name); | 469 unsetFields.remove(init.fieldName.name); |
468 } | 470 } |
469 } | 471 } |
470 } | 472 } |
471 | 473 |
472 // Initialize all remaining fields | 474 // Initialize all remaining fields |
473 unsetFields.forEach((name, field) { | 475 unsetFields.forEach((name, field) { |
474 JS.Expression value; | 476 JS.Expression value; |
475 if (field.initializer != null) { | 477 if (field.initializer != null) { |
476 value = _visit(field.initializer); | 478 value = _visit(field.initializer); |
477 } else { | 479 } else { |
478 var type = rules.elementType(field.element); | 480 var type = rules.elementType(field.element); |
479 if (rules.maybeNonNullableType(type)) { | 481 if (rules.maybeNonNullableType(type)) { |
480 value = js.call('dart.as(null, #)', _emitTypeName(type)); | 482 value = js.call('dart.as(null, #)', _emitTypeName(type)); |
481 } else { | 483 } else { |
482 value = new JS.LiteralNull(); | 484 value = new JS.LiteralNull(); |
483 } | 485 } |
484 } | 486 } |
485 body.add(js.statement('this.# = #;', [name, value])); | 487 body.add(js.statement('this.# = #;', [_jsMemberName(name), value])); |
486 }); | 488 }); |
487 | 489 |
488 return _statement(body); | 490 return _statement(body); |
489 } | 491 } |
490 | 492 |
491 FormalParameterList _parametersOf(node) { | 493 FormalParameterList _parametersOf(node) { |
492 // Note: ConstructorDeclaration is intentionally skipped here so we can | 494 // Note: ConstructorDeclaration is intentionally skipped here so we can |
493 // emit the argument initializers in a different place. | 495 // emit the argument initializers in a different place. |
494 // TODO(jmesserly): clean this up. If we can model ES6 spread/rest args, we | 496 // TODO(jmesserly): clean this up. If we can model ES6 spread/rest args, we |
495 // could handle argument initializers more consistently in a separate | 497 // could handle argument initializers more consistently in a separate |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 | 545 |
544 @override | 546 @override |
545 JS.Method visitMethodDeclaration(MethodDeclaration node) { | 547 JS.Method visitMethodDeclaration(MethodDeclaration node) { |
546 if (node.isAbstract || _externalOrNative(node)) { | 548 if (node.isAbstract || _externalOrNative(node)) { |
547 return null; | 549 return null; |
548 } | 550 } |
549 | 551 |
550 var params = _visit(node.parameters); | 552 var params = _visit(node.parameters); |
551 if (params == null) params = []; | 553 if (params == null) params = []; |
552 | 554 |
553 return new JS.Method(new JS.PropertyName(_jsMethodName(node.name.name)), | 555 return new JS.Method( |
554 new JS.Fun(params, _visit(node.body)), | 556 _jsMemberName(node.name.name), new JS.Fun(params, _visit(node.body)), |
555 isGetter: node.isGetter, | 557 isGetter: node.isGetter, |
556 isSetter: node.isSetter, | 558 isSetter: node.isSetter, |
557 isStatic: node.isStatic); | 559 isStatic: node.isStatic); |
558 } | 560 } |
559 | 561 |
560 @override | 562 @override |
561 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { | 563 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { |
562 assert(node.parent is CompilationUnit); | 564 assert(node.parent is CompilationUnit); |
563 | 565 |
564 if (_externalOrNative(node)) return null; | 566 if (_externalOrNative(node)) return null; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
636 var e = node.staticElement; | 638 var e = node.staticElement; |
637 if (e == null) { | 639 if (e == null) { |
638 return js.commentExpression( | 640 return js.commentExpression( |
639 'Unimplemented unknown name', new JS.VariableUse(node.name)); | 641 'Unimplemented unknown name', new JS.VariableUse(node.name)); |
640 } | 642 } |
641 var name = node.name; | 643 var name = node.name; |
642 if (e.enclosingElement is CompilationUnitElement && | 644 if (e.enclosingElement is CompilationUnitElement && |
643 (e.library != libraryInfo.library || _needsModuleGetter(e))) { | 645 (e.library != libraryInfo.library || _needsModuleGetter(e))) { |
644 return js.call('#.#', [_libraryName(e.library), name]); | 646 return js.call('#.#', [_libraryName(e.library), name]); |
645 } else if (currentClass != null && _needsImplicitThis(e)) { | 647 } else if (currentClass != null && _needsImplicitThis(e)) { |
646 return js.call('this.#', name); | 648 return js.call('this.#', _jsMemberName(name)); |
| 649 } else if (e is ParameterElement && e.isInitializingFormal) { |
| 650 name = _fieldParameterName(name); |
647 } | 651 } |
648 return new JS.VariableUse(name); | 652 return new JS.VariableUse(name); |
649 } | 653 } |
650 | 654 |
651 JS.Expression _emitTypeName(DartType type) { | 655 JS.Expression _emitTypeName(DartType type) { |
652 var name = type.name; | 656 var name = type.name; |
653 var lib = type.element.library; | 657 var lib = type.element.library; |
654 if (name == '') { | 658 if (name == '') { |
655 // TODO(jmesserly): remove when we're using coercion reifier. | 659 // TODO(jmesserly): remove when we're using coercion reifier. |
656 return _unimplementedCall('Unimplemented type $type'); | 660 return _unimplementedCall('Unimplemented type $type'); |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 } | 847 } |
844 | 848 |
845 @override | 849 @override |
846 List<JS.Parameter> visitFormalParameterList(FormalParameterList node) { | 850 List<JS.Parameter> visitFormalParameterList(FormalParameterList node) { |
847 var result = <JS.Parameter>[]; | 851 var result = <JS.Parameter>[]; |
848 for (FormalParameter param in node.parameters) { | 852 for (FormalParameter param in node.parameters) { |
849 if (param.kind == ParameterKind.NAMED) { | 853 if (param.kind == ParameterKind.NAMED) { |
850 result.add(new JS.Parameter(_jsNamedParameterName)); | 854 result.add(new JS.Parameter(_jsNamedParameterName)); |
851 break; | 855 break; |
852 } | 856 } |
853 result.add(new JS.Parameter(param.identifier.name)); | 857 result.add(_visit(param)); |
854 } | 858 } |
855 return result; | 859 return result; |
856 } | 860 } |
857 | 861 |
858 @override | 862 @override |
859 JS.Statement visitExpressionStatement(ExpressionStatement node) => | 863 JS.Statement visitExpressionStatement(ExpressionStatement node) => |
860 _expressionStatement(_visit(node.expression)); | 864 _expressionStatement(_visit(node.expression)); |
861 | 865 |
862 // Some expressions may choose to generate themselves as JS statements | 866 // Some expressions may choose to generate themselves as JS statements |
863 // if their parent is in a statement context. | 867 // if their parent is in a statement context. |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1206 } | 1210 } |
1207 return false; | 1211 return false; |
1208 } | 1212 } |
1209 | 1213 |
1210 @override | 1214 @override |
1211 visitParenthesizedExpression(ParenthesizedExpression node) => | 1215 visitParenthesizedExpression(ParenthesizedExpression node) => |
1212 // The printer handles precedence so we don't need to. | 1216 // The printer handles precedence so we don't need to. |
1213 _visit(node.expression); | 1217 _visit(node.expression); |
1214 | 1218 |
1215 @override | 1219 @override |
1216 visitSimpleFormalParameter(SimpleFormalParameter node) => | 1220 visitFormalParameter(FormalParameter node) => |
1217 _visit(node.identifier); | 1221 new JS.Parameter(node.identifier.name); |
1218 | 1222 |
1219 @override | 1223 @override |
1220 visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) => | 1224 visitFieldFormalParameter(FieldFormalParameter node) => |
1221 _visit(node.identifier); | 1225 new JS.Parameter(_fieldParameterName(node.identifier.name)); |
| 1226 |
| 1227 /// Rename private names so they don't shadow the private field symbol. |
| 1228 // TODO(jmesserly): replace this ad-hoc rename with a general strategy. |
| 1229 _fieldParameterName(name) => name.startsWith('_') ? '\$$name' : name; |
1222 | 1230 |
1223 @override | 1231 @override |
1224 JS.This visitThisExpression(ThisExpression node) => new JS.This(); | 1232 JS.This visitThisExpression(ThisExpression node) => new JS.This(); |
1225 | 1233 |
1226 @override | 1234 @override |
1227 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super(); | 1235 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super(); |
1228 | 1236 |
1229 @override | 1237 @override |
1230 visitPrefixedIdentifier(PrefixedIdentifier node) { | 1238 visitPrefixedIdentifier(PrefixedIdentifier node) { |
1231 if (node.prefix.staticElement is PrefixElement) { | 1239 if (node.prefix.staticElement is PrefixElement) { |
1232 return _visit(node.identifier); | 1240 return _visit(node.identifier); |
1233 } else { | 1241 } else { |
1234 return _visitGet(node.prefix, node.identifier); | 1242 return _visitGet(node.prefix, node.identifier); |
1235 } | 1243 } |
1236 } | 1244 } |
1237 | 1245 |
1238 @override | 1246 @override |
1239 visitPropertyAccess(PropertyAccess node) => | 1247 visitPropertyAccess(PropertyAccess node) => |
1240 _visitGet(_getTarget(node), node.propertyName); | 1248 _visitGet(_getTarget(node), node.propertyName); |
1241 | 1249 |
1242 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. | 1250 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. |
1243 _visitGet(Expression target, SimpleIdentifier name) { | 1251 _visitGet(Expression target, SimpleIdentifier name) { |
1244 if (rules.isDynamicTarget(target)) { | 1252 if (rules.isDynamicTarget(target)) { |
1245 return js.call( | 1253 return js.call( |
1246 'dart.dload(#, #)', [_visit(target), js.string(name.name, "'")]); | 1254 'dart.dload(#, #)', [_visit(target), js.string(name.name, "'")]); |
1247 } else { | 1255 } else { |
1248 return js.call('#.#', [_visit(target), name.name]); | 1256 return js.call('#.#', [_visit(target), _jsMemberName(name.name)]); |
1249 } | 1257 } |
1250 } | 1258 } |
1251 | 1259 |
1252 @override | 1260 @override |
1253 visitIndexExpression(IndexExpression node) { | 1261 visitIndexExpression(IndexExpression node) { |
1254 var target = _getTarget(node); | 1262 var target = _getTarget(node); |
1255 var code; | 1263 var code; |
1256 if (rules.isDynamicTarget(target)) { | 1264 if (rules.isDynamicTarget(target)) { |
1257 code = 'dart.dindex(#, #)'; | 1265 code = 'dart.dindex(#, #)'; |
1258 } else { | 1266 } else { |
(...skipping 23 matching lines...) Expand all Loading... |
1282 visitThrowExpression(ThrowExpression node) { | 1290 visitThrowExpression(ThrowExpression node) { |
1283 var expr = _visit(node.expression); | 1291 var expr = _visit(node.expression); |
1284 if (node.parent is ExpressionStatement) { | 1292 if (node.parent is ExpressionStatement) { |
1285 return js.statement('throw #;', expr); | 1293 return js.statement('throw #;', expr); |
1286 } else { | 1294 } else { |
1287 return js.call('dart.throw_(#)', expr); | 1295 return js.call('dart.throw_(#)', expr); |
1288 } | 1296 } |
1289 } | 1297 } |
1290 | 1298 |
1291 @override | 1299 @override |
1292 visitRethrowExpression(RethrowExpression node){ | 1300 visitRethrowExpression(RethrowExpression node) { |
1293 if (node.parent is ExpressionStatement) { | 1301 if (node.parent is ExpressionStatement) { |
1294 return js.statement('throw #;', _catchParameter); | 1302 return js.statement('throw #;', _catchParameter); |
1295 } else { | 1303 } else { |
1296 return js.call('dart.throw_(#)', _catchParameter); | 1304 return js.call('dart.throw_(#)', _catchParameter); |
1297 } | 1305 } |
1298 } | 1306 } |
1299 | 1307 |
1300 @override | 1308 @override |
1301 JS.If visitIfStatement(IfStatement node) { | 1309 JS.If visitIfStatement(IfStatement node) { |
1302 return new JS.If(_visit(node.condition), _visit(node.thenStatement), | 1310 return new JS.If(_visit(node.condition), _visit(node.thenStatement), |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1604 var jsExpr = _visit(node); | 1612 var jsExpr = _visit(node); |
1605 if (result == null) { | 1613 if (result == null) { |
1606 result = jsExpr; | 1614 result = jsExpr; |
1607 } else { | 1615 } else { |
1608 result = new JS.Binary(operator, result, jsExpr); | 1616 result = new JS.Binary(operator, result, jsExpr); |
1609 } | 1617 } |
1610 } | 1618 } |
1611 return result; | 1619 return result; |
1612 } | 1620 } |
1613 | 1621 |
1614 /// The following names are allowed for user-defined operators: | 1622 /// This handles member renaming for private names and operators. |
| 1623 /// |
| 1624 /// Private names are generated using ES6 symbols: |
| 1625 /// |
| 1626 /// // At the top of the module: |
| 1627 /// let _x = Symbol('_x'); |
| 1628 /// let _y = Symbol('_y'); |
| 1629 /// ... |
| 1630 /// |
| 1631 /// class Point { |
| 1632 /// Point(x, y) { |
| 1633 /// this[_x] = x; |
| 1634 /// this[_y] = y; |
| 1635 /// } |
| 1636 /// get x() { return this[_x]; } |
| 1637 /// get y() { return this[_y]; } |
| 1638 /// } |
| 1639 /// |
| 1640 /// For user-defined operators the following names are allowed: |
1615 /// | 1641 /// |
1616 /// <, >, <=, >=, ==, -, +, /, ˜/, *, %, |, ˆ, &, <<, >>, []=, [], ˜ | 1642 /// <, >, <=, >=, ==, -, +, /, ˜/, *, %, |, ˆ, &, <<, >>, []=, [], ˜ |
1617 /// | 1643 /// |
1618 /// For the indexing operators, we use `get` and `set` instead: | 1644 /// They generate code like: |
| 1645 /// |
| 1646 /// x['+'](y) |
| 1647 /// |
| 1648 /// There are three exceptions: [], []= and unary -. |
| 1649 /// The indexing operators we use `get` and `set` instead: |
1619 /// | 1650 /// |
1620 /// x.get('hi') | 1651 /// x.get('hi') |
1621 /// x.set('hi', 123) | 1652 /// x.set('hi', 123) |
1622 /// | 1653 /// |
1623 /// This follows the same pattern as EcmaScript 6 Map: | 1654 /// This follows the same pattern as EcmaScript 6 Map: |
1624 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_
Objects/Map> | 1655 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_
Objects/Map> |
1625 /// | 1656 /// |
1626 /// For all others we use the operator name: | 1657 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed |
1627 /// | 1658 /// for this transformation to happen, otherwise binary minus is assumed. |
1628 /// x['+'](y) | |
1629 /// | 1659 /// |
1630 /// Equality is a bit special, it is generated via the Dart `equals` runtime | 1660 /// Equality is a bit special, it is generated via the Dart `equals` runtime |
1631 /// helper, that checks for null. The user defined method is called '=='. | 1661 /// helper, that checks for null. The user defined method is called '=='. |
1632 String _jsMethodName(String name) { | 1662 /// |
1633 if (name == '[]') return 'get'; | 1663 JS.Expression _jsMemberName(String name, {bool unary: false}) { |
1634 if (name == '[]=') return 'set'; | 1664 if (name.startsWith('_')) { |
1635 return name; | 1665 _privateNames.add(name); |
| 1666 return new JS.VariableUse(name); |
| 1667 } |
| 1668 if (name == '[]') { |
| 1669 name = 'get'; |
| 1670 } else if (name == '[]=') { |
| 1671 name = 'set'; |
| 1672 } else if (unary && name == '-') { |
| 1673 name = 'unary-'; |
| 1674 } |
| 1675 return new JS.PropertyName(name); |
1636 } | 1676 } |
1637 | 1677 |
1638 bool _externalOrNative(node) => | 1678 bool _externalOrNative(node) => |
1639 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; | 1679 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; |
1640 | 1680 |
1641 FunctionBody _functionBody(node) => | 1681 FunctionBody _functionBody(node) => |
1642 node is FunctionDeclaration ? node.functionExpression.body : node.body; | 1682 node is FunctionDeclaration ? node.functionExpression.body : node.body; |
1643 | 1683 |
1644 /// Choose a canonical name from the library element. | 1684 /// Choose a canonical name from the library element. |
1645 /// This never uses the library's name (the identifier in the `library` | 1685 /// This never uses the library's name (the identifier in the `library` |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1852 | 1892 |
1853 // TODO(jmesserly): in many cases marking the end will be unncessary. | 1893 // TODO(jmesserly): in many cases marking the end will be unncessary. |
1854 printer.mark(_location(node.end)); | 1894 printer.mark(_location(node.end)); |
1855 } | 1895 } |
1856 | 1896 |
1857 String _getIdentifier(AstNode node) { | 1897 String _getIdentifier(AstNode node) { |
1858 if (node is SimpleIdentifier) return node.name; | 1898 if (node is SimpleIdentifier) return node.name; |
1859 return null; | 1899 return null; |
1860 } | 1900 } |
1861 } | 1901 } |
OLD | NEW |