Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(528)

Side by Side Diff: lib/src/codegen/js_codegen.dart

Issue 963343002: implement private members, fixes #74 (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | lib/src/js/printer.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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:collection' show HashSet;
7 import 'dart:io' show Directory, File; 8 import 'dart:io' show Directory, File;
8 9
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; 11 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
11 import 'package:analyzer/src/generated/constant.dart'; 12 import 'package:analyzer/src/generated/constant.dart';
12 import 'package:analyzer/src/generated/element.dart'; 13 import 'package:analyzer/src/generated/element.dart';
13 import 'package:analyzer/src/generated/scanner.dart' 14 import 'package:analyzer/src/generated/scanner.dart'
14 show StringToken, Token, TokenType; 15 show StringToken, Token, TokenType;
15 import 'package:source_maps/source_maps.dart' as srcmaps show Printer; 16 import 'package:source_maps/source_maps.dart' as srcmaps show Printer;
16 import 'package:source_maps/source_maps.dart' show SourceMapSpan; 17 import 'package:source_maps/source_maps.dart' show SourceMapSpan;
(...skipping 22 matching lines...) Expand all
39 SimpleIdentifier _cascadeTarget; 40 SimpleIdentifier _cascadeTarget;
40 /// The variable for the current catch clause 41 /// The variable for the current catch clause
41 String _catchParameter; 42 String _catchParameter;
42 43
43 ClassDeclaration currentClass; 44 ClassDeclaration currentClass;
44 ConstantEvaluator _constEvaluator; 45 ConstantEvaluator _constEvaluator;
45 46
46 final _exports = <String>[]; 47 final _exports = <String>[];
47 final _lazyFields = <VariableDeclaration>[]; 48 final _lazyFields = <VariableDeclaration>[];
48 final _properties = <FunctionDeclaration>[]; 49 final _properties = <FunctionDeclaration>[];
50 final _privateNames = new HashSet<String>();
51 final _pendingPrivateNames = <String>[];
49 52
50 JSCodegenVisitor(LibraryInfo libraryInfo, TypeRules rules) 53 JSCodegenVisitor(LibraryInfo libraryInfo, TypeRules rules)
51 : libraryInfo = libraryInfo, 54 : libraryInfo = libraryInfo,
52 rules = rules; 55 rules = rules;
53 56
54 Element get currentLibrary => libraryInfo.library; 57 Element get currentLibrary => libraryInfo.library;
55 58
56 JS.Block generateLibrary( 59 JS.Block generateLibrary(
57 Iterable<CompilationUnit> units, CheckerReporter reporter) { 60 Iterable<CompilationUnit> units, CheckerReporter reporter) {
58 var body = <JS.Statement>[]; 61 var body = <JS.Statement>[];
(...skipping 11 matching lines...) Expand all
70 if (_exports.isNotEmpty) body.add(js.comment('Exports:')); 73 if (_exports.isNotEmpty) body.add(js.comment('Exports:'));
71 74
72 // TODO(jmesserly): make these immutable in JS? 75 // TODO(jmesserly): make these immutable in JS?
73 for (var name in _exports) { 76 for (var name in _exports) {
74 body.add(js.statement('$_EXPORTS.# = #;', [name, name])); 77 body.add(js.statement('$_EXPORTS.# = #;', [name, name]));
75 } 78 }
76 79
77 var name = jsLibraryName(libraryInfo.library); 80 var name = jsLibraryName(libraryInfo.library);
78 return new JS.Block([ 81 return new JS.Block([
79 js.statement('var #;', name), 82 js.statement('var #;', name),
80 js.statement(''' 83 js.statement("(function($_EXPORTS) { 'use strict'; #; })(# || (# = {}));",
81 (function ($_EXPORTS) { 84 [body, name, name])
82 'use strict';
83 #;
84 })(# || (# = {}));
85 ''', [body, name, name])
86 ]); 85 ]);
87 } 86 }
88 87
88 JS.Statement _initPrivateSymbol(String name) =>
89 js.statement('let # = Symbol(#);', [name, js.string(name, "'")]);
90
89 @override 91 @override
90 JS.Statement visitCompilationUnit(CompilationUnit node) { 92 JS.Statement visitCompilationUnit(CompilationUnit node) {
91 // TODO(jmesserly): scriptTag, directives. 93 // TODO(jmesserly): scriptTag, directives.
92 var body = <JS.Statement>[]; 94 var body = <JS.Statement>[];
93 for (var child in node.declarations) { 95 for (var child in node.declarations) {
94 // Attempt to group adjacent fields/properties. 96 // Attempt to group adjacent fields/properties.
95 if (child is! TopLevelVariableDeclaration) _flushLazyFields(body); 97 if (child is! TopLevelVariableDeclaration) _flushLazyFields(body);
96 if (child is! FunctionDeclaration) _flushLibraryProperties(body); 98 if (child is! FunctionDeclaration) _flushLibraryProperties(body);
97 99
98 var code = _visit(child); 100 var code = _visit(child);
99 if (code != null) body.add(code); 101
102 if (code != null) {
103 if (_pendingPrivateNames.isNotEmpty) {
104 body.addAll(_pendingPrivateNames.map(_initPrivateSymbol));
105 _pendingPrivateNames.clear();
106 }
107 body.add(code);
108 }
100 } 109 }
110
101 // Flush any unwritten fields/properties. 111 // Flush any unwritten fields/properties.
102 _flushLazyFields(body); 112 _flushLazyFields(body);
103 _flushLibraryProperties(body); 113 _flushLibraryProperties(body);
114
115 assert(_pendingPrivateNames.isEmpty);
104 return _statement(body); 116 return _statement(body);
105 } 117 }
106 118
107 bool isPublic(String name) => !name.startsWith('_'); 119 bool isPublic(String name) => !name.startsWith('_');
108 120
109 /// Conversions that we don't handle end up here. 121 /// Conversions that we don't handle end up here.
110 @override 122 @override
111 visitConversion(Conversion node) { 123 visitConversion(Conversion node) {
112 var from = node.baseType; 124 var from = node.baseType;
113 var to = node.convertedType; 125 var to = node.convertedType;
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 return new JS.Block(body)..sourceInformation = node; 407 return new JS.Block(body)..sourceInformation = node;
396 } 408 }
397 409
398 @override 410 @override
399 JS.Statement visitRedirectingConstructorInvocation( 411 JS.Statement visitRedirectingConstructorInvocation(
400 RedirectingConstructorInvocation node) { 412 RedirectingConstructorInvocation node) {
401 ClassDeclaration classDecl = node.parent.parent; 413 ClassDeclaration classDecl = node.parent.parent;
402 var className = classDecl.name.name; 414 var className = classDecl.name.name;
403 415
404 var name = _constructorName(className, node.constructorName); 416 var name = _constructorName(className, node.constructorName);
405 return js.statement('this.#(#);', [name, _visit(node.argumentList)]); 417 return js.statement(
418 'this.#(#);', [_jsMemberName(name), _visit(node.argumentList)]);
406 } 419 }
407 420
408 JS.Statement _superConstructorCall(ClassDeclaration clazz, 421 JS.Statement _superConstructorCall(ClassDeclaration clazz,
409 [SuperConstructorInvocation node]) { 422 [SuperConstructorInvocation node]) {
410 var superCtorName = node != null ? node.constructorName : null; 423 var superCtorName = node != null ? node.constructorName : null;
411 424
412 var element = clazz.element; 425 var element = clazz.element;
413 if (superCtorName == null && 426 if (superCtorName == null &&
414 (element.type.isObject || element.supertype.isObject)) { 427 (element.type.isObject || element.supertype.isObject)) {
415 return null; 428 return null;
(...skipping 29 matching lines...) Expand all
445 } 458 }
446 } 459 }
447 } 460 }
448 461
449 // Initialize fields from `this.fieldName` parameters. 462 // Initialize fields from `this.fieldName` parameters.
450 if (parameters != null) { 463 if (parameters != null) {
451 for (var p in parameters.parameters) { 464 for (var p in parameters.parameters) {
452 if (p is DefaultFormalParameter) p = p.parameter; 465 if (p is DefaultFormalParameter) p = p.parameter;
453 if (p is FieldFormalParameter) { 466 if (p is FieldFormalParameter) {
454 var name = p.identifier.name; 467 var name = p.identifier.name;
455 body.add(js.statement('this.# = #;', [name, name])); 468 body.add(
469 js.statement('this.# = #;', [_jsMemberName(name), _visit(p)]));
456 unsetFields.remove(name); 470 unsetFields.remove(name);
457 } 471 }
458 } 472 }
459 } 473 }
460 474
461 // Run constructor field initializers such as `: foo = bar.baz` 475 // Run constructor field initializers such as `: foo = bar.baz`
462 if (initializers != null) { 476 if (initializers != null) {
463 for (var init in initializers) { 477 for (var init in initializers) {
464 if (init is ConstructorFieldInitializer) { 478 if (init is ConstructorFieldInitializer) {
465 body.add(js.statement( 479 body.add(js.statement(
466 '# = #;', [_visit(init.fieldName), _visit(init.expression)])); 480 '# = #;', [_visit(init.fieldName), _visit(init.expression)]));
467 unsetFields.remove(init.fieldName.name); 481 unsetFields.remove(init.fieldName.name);
468 } 482 }
469 } 483 }
470 } 484 }
471 485
472 // Initialize all remaining fields 486 // Initialize all remaining fields
473 unsetFields.forEach((name, field) { 487 unsetFields.forEach((name, field) {
474 JS.Expression value; 488 JS.Expression value;
475 if (field.initializer != null) { 489 if (field.initializer != null) {
476 value = _visit(field.initializer); 490 value = _visit(field.initializer);
477 } else { 491 } else {
478 var type = rules.elementType(field.element); 492 var type = rules.elementType(field.element);
479 if (rules.maybeNonNullableType(type)) { 493 if (rules.maybeNonNullableType(type)) {
480 value = js.call('dart.as(null, #)', _emitTypeName(type)); 494 value = js.call('dart.as(null, #)', _emitTypeName(type));
481 } else { 495 } else {
482 value = new JS.LiteralNull(); 496 value = new JS.LiteralNull();
483 } 497 }
484 } 498 }
485 body.add(js.statement('this.# = #;', [name, value])); 499 body.add(js.statement('this.# = #;', [_jsMemberName(name), value]));
486 }); 500 });
487 501
488 return _statement(body); 502 return _statement(body);
489 } 503 }
490 504
491 FormalParameterList _parametersOf(node) { 505 FormalParameterList _parametersOf(node) {
492 // Note: ConstructorDeclaration is intentionally skipped here so we can 506 // Note: ConstructorDeclaration is intentionally skipped here so we can
493 // emit the argument initializers in a different place. 507 // emit the argument initializers in a different place.
494 // TODO(jmesserly): clean this up. If we can model ES6 spread/rest args, we 508 // TODO(jmesserly): clean this up. If we can model ES6 spread/rest args, we
495 // could handle argument initializers more consistently in a separate 509 // could handle argument initializers more consistently in a separate
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 557
544 @override 558 @override
545 JS.Method visitMethodDeclaration(MethodDeclaration node) { 559 JS.Method visitMethodDeclaration(MethodDeclaration node) {
546 if (node.isAbstract || _externalOrNative(node)) { 560 if (node.isAbstract || _externalOrNative(node)) {
547 return null; 561 return null;
548 } 562 }
549 563
550 var params = _visit(node.parameters); 564 var params = _visit(node.parameters);
551 if (params == null) params = []; 565 if (params == null) params = [];
552 566
553 return new JS.Method(new JS.PropertyName(_jsMethodName(node.name.name)), 567 return new JS.Method(
554 new JS.Fun(params, _visit(node.body)), 568 _jsMemberName(node.name.name), new JS.Fun(params, _visit(node.body)),
555 isGetter: node.isGetter, 569 isGetter: node.isGetter,
556 isSetter: node.isSetter, 570 isSetter: node.isSetter,
557 isStatic: node.isStatic); 571 isStatic: node.isStatic);
558 } 572 }
559 573
560 @override 574 @override
561 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { 575 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
562 assert(node.parent is CompilationUnit); 576 assert(node.parent is CompilationUnit);
563 577
564 if (_externalOrNative(node)) return null; 578 if (_externalOrNative(node)) return null;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 var e = node.staticElement; 650 var e = node.staticElement;
637 if (e == null) { 651 if (e == null) {
638 return js.commentExpression( 652 return js.commentExpression(
639 'Unimplemented unknown name', new JS.VariableUse(node.name)); 653 'Unimplemented unknown name', new JS.VariableUse(node.name));
640 } 654 }
641 var name = node.name; 655 var name = node.name;
642 if (e.enclosingElement is CompilationUnitElement && 656 if (e.enclosingElement is CompilationUnitElement &&
643 (e.library != libraryInfo.library || _needsModuleGetter(e))) { 657 (e.library != libraryInfo.library || _needsModuleGetter(e))) {
644 return js.call('#.#', [_libraryName(e.library), name]); 658 return js.call('#.#', [_libraryName(e.library), name]);
645 } else if (currentClass != null && _needsImplicitThis(e)) { 659 } else if (currentClass != null && _needsImplicitThis(e)) {
646 return js.call('this.#', name); 660 return js.call('this.#', _jsMemberName(name));
661 } else if (e is ParameterElement && e.isInitializingFormal) {
662 name = _fieldParameterName(name);
647 } 663 }
648 return new JS.VariableUse(name); 664 return new JS.VariableUse(name);
649 } 665 }
650 666
651 JS.Expression _emitTypeName(DartType type) { 667 JS.Expression _emitTypeName(DartType type) {
652 var name = type.name; 668 var name = type.name;
653 var lib = type.element.library; 669 var lib = type.element.library;
654 if (name == '') { 670 if (name == '') {
655 // TODO(jmesserly): remove when we're using coercion reifier. 671 // TODO(jmesserly): remove when we're using coercion reifier.
656 return _unimplementedCall('Unimplemented type $type'); 672 return _unimplementedCall('Unimplemented type $type');
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 } 859 }
844 860
845 @override 861 @override
846 List<JS.Parameter> visitFormalParameterList(FormalParameterList node) { 862 List<JS.Parameter> visitFormalParameterList(FormalParameterList node) {
847 var result = <JS.Parameter>[]; 863 var result = <JS.Parameter>[];
848 for (FormalParameter param in node.parameters) { 864 for (FormalParameter param in node.parameters) {
849 if (param.kind == ParameterKind.NAMED) { 865 if (param.kind == ParameterKind.NAMED) {
850 result.add(new JS.Parameter(_jsNamedParameterName)); 866 result.add(new JS.Parameter(_jsNamedParameterName));
851 break; 867 break;
852 } 868 }
853 result.add(new JS.Parameter(param.identifier.name)); 869 result.add(_visit(param));
854 } 870 }
855 return result; 871 return result;
856 } 872 }
857 873
858 @override 874 @override
859 JS.Statement visitExpressionStatement(ExpressionStatement node) => 875 JS.Statement visitExpressionStatement(ExpressionStatement node) =>
860 _expressionStatement(_visit(node.expression)); 876 _expressionStatement(_visit(node.expression));
861 877
862 // Some expressions may choose to generate themselves as JS statements 878 // Some expressions may choose to generate themselves as JS statements
863 // if their parent is in a statement context. 879 // if their parent is in a statement context.
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
1206 } 1222 }
1207 return false; 1223 return false;
1208 } 1224 }
1209 1225
1210 @override 1226 @override
1211 visitParenthesizedExpression(ParenthesizedExpression node) => 1227 visitParenthesizedExpression(ParenthesizedExpression node) =>
1212 // The printer handles precedence so we don't need to. 1228 // The printer handles precedence so we don't need to.
1213 _visit(node.expression); 1229 _visit(node.expression);
1214 1230
1215 @override 1231 @override
1216 visitSimpleFormalParameter(SimpleFormalParameter node) => 1232 visitFormalParameter(FormalParameter node) =>
1217 _visit(node.identifier); 1233 new JS.Parameter(node.identifier.name);
1218 1234
1219 @override 1235 @override
1220 visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) => 1236 visitFieldFormalParameter(FieldFormalParameter node) =>
1221 _visit(node.identifier); 1237 new JS.Parameter(_fieldParameterName(node.identifier.name));
1238
1239 /// Rename private names so they don't shadow the private field symbol.
1240 // TODO(jmesserly): replace this ad-hoc rename with a general strategy.
1241 _fieldParameterName(name) => name.startsWith('_') ? '\$$name' : name;
1222 1242
1223 @override 1243 @override
1224 JS.This visitThisExpression(ThisExpression node) => new JS.This(); 1244 JS.This visitThisExpression(ThisExpression node) => new JS.This();
1225 1245
1226 @override 1246 @override
1227 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super(); 1247 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super();
1228 1248
1229 @override 1249 @override
1230 visitPrefixedIdentifier(PrefixedIdentifier node) { 1250 visitPrefixedIdentifier(PrefixedIdentifier node) {
1231 if (node.prefix.staticElement is PrefixElement) { 1251 if (node.prefix.staticElement is PrefixElement) {
1232 return _visit(node.identifier); 1252 return _visit(node.identifier);
1233 } else { 1253 } else {
1234 return _visitGet(node.prefix, node.identifier); 1254 return _visitGet(node.prefix, node.identifier);
1235 } 1255 }
1236 } 1256 }
1237 1257
1238 @override 1258 @override
1239 visitPropertyAccess(PropertyAccess node) => 1259 visitPropertyAccess(PropertyAccess node) =>
1240 _visitGet(_getTarget(node), node.propertyName); 1260 _visitGet(_getTarget(node), node.propertyName);
1241 1261
1242 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. 1262 /// Shared code for [PrefixedIdentifier] and [PropertyAccess].
1243 _visitGet(Expression target, SimpleIdentifier name) { 1263 _visitGet(Expression target, SimpleIdentifier name) {
1244 if (rules.isDynamicTarget(target)) { 1264 if (rules.isDynamicTarget(target)) {
1245 return js.call( 1265 return js.call(
1246 'dart.dload(#, #)', [_visit(target), js.string(name.name, "'")]); 1266 'dart.dload(#, #)', [_visit(target), js.string(name.name, "'")]);
1247 } else { 1267 } else {
1248 return js.call('#.#', [_visit(target), name.name]); 1268 return js.call('#.#', [_visit(target), _jsMemberName(name.name)]);
1249 } 1269 }
1250 } 1270 }
1251 1271
1252 @override 1272 @override
1253 visitIndexExpression(IndexExpression node) { 1273 visitIndexExpression(IndexExpression node) {
1254 var target = _getTarget(node); 1274 var target = _getTarget(node);
1255 var code; 1275 var code;
1256 if (rules.isDynamicTarget(target)) { 1276 if (rules.isDynamicTarget(target)) {
1257 code = 'dart.dindex(#, #)'; 1277 code = 'dart.dindex(#, #)';
1258 } else { 1278 } else {
(...skipping 23 matching lines...) Expand all
1282 visitThrowExpression(ThrowExpression node) { 1302 visitThrowExpression(ThrowExpression node) {
1283 var expr = _visit(node.expression); 1303 var expr = _visit(node.expression);
1284 if (node.parent is ExpressionStatement) { 1304 if (node.parent is ExpressionStatement) {
1285 return js.statement('throw #;', expr); 1305 return js.statement('throw #;', expr);
1286 } else { 1306 } else {
1287 return js.call('dart.throw_(#)', expr); 1307 return js.call('dart.throw_(#)', expr);
1288 } 1308 }
1289 } 1309 }
1290 1310
1291 @override 1311 @override
1292 visitRethrowExpression(RethrowExpression node){ 1312 visitRethrowExpression(RethrowExpression node) {
1293 if (node.parent is ExpressionStatement) { 1313 if (node.parent is ExpressionStatement) {
1294 return js.statement('throw #;', _catchParameter); 1314 return js.statement('throw #;', _catchParameter);
1295 } else { 1315 } else {
1296 return js.call('dart.throw_(#)', _catchParameter); 1316 return js.call('dart.throw_(#)', _catchParameter);
1297 } 1317 }
1298 } 1318 }
1299 1319
1300 @override 1320 @override
1301 JS.If visitIfStatement(IfStatement node) { 1321 JS.If visitIfStatement(IfStatement node) {
1302 return new JS.If(_visit(node.condition), _visit(node.thenStatement), 1322 return new JS.If(_visit(node.condition), _visit(node.thenStatement),
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
1604 var jsExpr = _visit(node); 1624 var jsExpr = _visit(node);
1605 if (result == null) { 1625 if (result == null) {
1606 result = jsExpr; 1626 result = jsExpr;
1607 } else { 1627 } else {
1608 result = new JS.Binary(operator, result, jsExpr); 1628 result = new JS.Binary(operator, result, jsExpr);
1609 } 1629 }
1610 } 1630 }
1611 return result; 1631 return result;
1612 } 1632 }
1613 1633
1614 /// The following names are allowed for user-defined operators: 1634 /// This handles member renaming for private names and operators.
1635 ///
1636 /// Private names are generated using ES6 symbols:
1637 ///
1638 /// // At the top of the module:
1639 /// let _x = Symbol('_x');
1640 /// let _y = Symbol('_y');
1641 /// ...
1642 ///
1643 /// class Point {
1644 /// Point(x, y) {
1645 /// this[_x] = x;
1646 /// this[_y] = y;
1647 /// }
1648 /// get x() { return this[_x]; }
1649 /// get y() { return this[_y]; }
1650 /// }
1651 ///
1652 /// For user-defined operators the following names are allowed:
1615 /// 1653 ///
1616 /// <, >, <=, >=, ==, -, +, /, ˜/, *, %, |, ˆ, &, <<, >>, []=, [], ˜ 1654 /// <, >, <=, >=, ==, -, +, /, ˜/, *, %, |, ˆ, &, <<, >>, []=, [], ˜
1617 /// 1655 ///
1618 /// For the indexing operators, we use `get` and `set` instead: 1656 /// They generate code like:
1657 ///
1658 /// x['+'](y)
1659 ///
1660 /// There are three exceptions: [], []= and unary -.
1661 /// The indexing operators we use `get` and `set` instead:
1619 /// 1662 ///
1620 /// x.get('hi') 1663 /// x.get('hi')
1621 /// x.set('hi', 123) 1664 /// x.set('hi', 123)
1622 /// 1665 ///
1623 /// This follows the same pattern as EcmaScript 6 Map: 1666 /// This follows the same pattern as EcmaScript 6 Map:
1624 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_ Objects/Map> 1667 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_ Objects/Map>
1625 /// 1668 ///
1626 /// For all others we use the operator name: 1669 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed
1627 /// 1670 /// for this transformation to happen, otherwise binary minus is assumed.
1628 /// x['+'](y)
1629 /// 1671 ///
1630 /// Equality is a bit special, it is generated via the Dart `equals` runtime 1672 /// 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 '=='. 1673 /// helper, that checks for null. The user defined method is called '=='.
1632 String _jsMethodName(String name) { 1674 ///
1633 if (name == '[]') return 'get'; 1675 JS.Expression _jsMemberName(String name, {bool unary: false}) {
1634 if (name == '[]=') return 'set'; 1676 if (name.startsWith('_')) {
1635 return name; 1677 if (_privateNames.add(name)) _pendingPrivateNames.add(name);
1678 return new JS.VariableUse(name);
1679 }
1680 if (name == '[]') {
1681 name = 'get';
1682 } else if (name == '[]=') {
1683 name = 'set';
1684 } else if (unary && name == '-') {
1685 name = 'unary-';
1686 }
1687 return new JS.PropertyName(name);
1636 } 1688 }
1637 1689
1638 bool _externalOrNative(node) => 1690 bool _externalOrNative(node) =>
1639 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; 1691 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody;
1640 1692
1641 FunctionBody _functionBody(node) => 1693 FunctionBody _functionBody(node) =>
1642 node is FunctionDeclaration ? node.functionExpression.body : node.body; 1694 node is FunctionDeclaration ? node.functionExpression.body : node.body;
1643 1695
1644 /// Choose a canonical name from the library element. 1696 /// Choose a canonical name from the library element.
1645 /// This never uses the library's name (the identifier in the `library` 1697 /// This never uses the library's name (the identifier in the `library`
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
1852 1904
1853 // TODO(jmesserly): in many cases marking the end will be unncessary. 1905 // TODO(jmesserly): in many cases marking the end will be unncessary.
1854 printer.mark(_location(node.end)); 1906 printer.mark(_location(node.end));
1855 } 1907 }
1856 1908
1857 String _getIdentifier(AstNode node) { 1909 String _getIdentifier(AstNode node) {
1858 if (node is SimpleIdentifier) return node.name; 1910 if (node is SimpleIdentifier) return node.name;
1859 return null; 1911 return null;
1860 } 1912 }
1861 } 1913 }
OLDNEW
« no previous file with comments | « no previous file | lib/src/js/printer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698