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

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

Issue 1630963003: Use a symbol for static length/name (conflicts with Function properties in ES5: cannot redefine Fun… (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 10 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/codegen/js_names.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 dev_compiler.src.codegen.js_codegen; 5 library dev_compiler.src.codegen.js_codegen;
6 6
7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet;
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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 JS.TemporaryId _asyncStarController; 79 JS.TemporaryId _asyncStarController;
80 80
81 /// Imported libraries, and the temporaries used to refer to them. 81 /// Imported libraries, and the temporaries used to refer to them.
82 final _imports = new Map<LibraryElement, JS.TemporaryId>(); 82 final _imports = new Map<LibraryElement, JS.TemporaryId>();
83 final _exports = new Set<String>(); 83 final _exports = new Set<String>();
84 final _properties = <FunctionDeclaration>[]; 84 final _properties = <FunctionDeclaration>[];
85 final _privateNames = new HashMap<String, JS.TemporaryId>(); 85 final _privateNames = new HashMap<String, JS.TemporaryId>();
86 final _moduleItems = <JS.Statement>[]; 86 final _moduleItems = <JS.Statement>[];
87 final _temps = new HashMap<Element, JS.TemporaryId>(); 87 final _temps = new HashMap<Element, JS.TemporaryId>();
88 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>(); 88 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>();
89 final _topLevelExtensionNames = new Set<String>();
89 90
90 /// The name for the library's exports inside itself. 91 /// The name for the library's exports inside itself.
91 /// `exports` was chosen as the most similar to ES module patterns. 92 /// `exports` was chosen as the most similar to ES module patterns.
92 final _dartxVar = new JS.Identifier('dartx'); 93 final _dartxVar = new JS.Identifier('dartx');
93 final _exportsVar = new JS.TemporaryId('exports'); 94 final _exportsVar = new JS.TemporaryId('exports');
94 final _runtimeLibVar = new JS.Identifier('dart'); 95 final _runtimeLibVar = new JS.Identifier('dart');
95 final _namedArgTemp = new JS.TemporaryId('opts'); 96 final _namedArgTemp = new JS.TemporaryId('opts');
96 97
97 final TypeProvider _types; 98 final TypeProvider _types;
98 99
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 if (decl is TopLevelVariableDeclaration) { 153 if (decl is TopLevelVariableDeclaration) {
153 visitTopLevelVariableDeclaration(decl); 154 visitTopLevelVariableDeclaration(decl);
154 } else { 155 } else {
155 _loader.loadDeclaration(decl, decl.element); 156 _loader.loadDeclaration(decl, decl.element);
156 } 157 }
157 } 158 }
158 } 159 }
159 160
160 // Flush any unwritten fields/properties. 161 // Flush any unwritten fields/properties.
161 _flushLibraryProperties(_moduleItems); 162 _flushLibraryProperties(_moduleItems);
163 if (_topLevelExtensionNames.isNotEmpty) {
Jennifer Messerly 2016/02/02 00:22:56 I don't think this should be needed at the top-lev
ochafik 2016/02/03 19:58:49 Great point! Leaving todo for follow up refactorin
164 _moduleItems.add(_emitExtensionNamesDeclaration(
165 _topLevelExtensionNames.map(js.string).toList()));
166 }
162 167
163 // Mark all qualified names as qualified or not, depending on if they need 168 // Mark all qualified names as qualified or not, depending on if they need
164 // to be loaded lazily or not. 169 // to be loaded lazily or not.
165 for (var elementIdPairs in _qualifiedIds) { 170 for (var elementIdPairs in _qualifiedIds) {
166 var element = elementIdPairs.e0; 171 var element = elementIdPairs.e0;
167 var id = elementIdPairs.e1; 172 var id = elementIdPairs.e1;
168 id.setQualified(!_loader.isLoaded(element)); 173 id.setQualified(!_loader.isLoaded(element));
169 } 174 }
170 175
171 var moduleBuilder = new ModuleBuilder(options.moduleFormat); 176 var moduleBuilder = new ModuleBuilder(options.moduleFormat);
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 JS.Expression _instantiateAnnotation(Annotation node) { 656 JS.Expression _instantiateAnnotation(Annotation node) {
652 var element = node.element; 657 var element = node.element;
653 if (element is ConstructorElement) { 658 if (element is ConstructorElement) {
654 return _emitInstanceCreationExpression(element, element.returnType, 659 return _emitInstanceCreationExpression(element, element.returnType,
655 node.constructorName, node.arguments, true); 660 node.constructorName, node.arguments, true);
656 } else { 661 } else {
657 return _visit(node.name); 662 return _visit(node.name);
658 } 663 }
659 } 664 }
660 665
666 JS.Statement _emitExtensionNamesDeclaration(List<JS.Expression> names) =>
667 js.statement('dart.defineExtensionNames(#)',
668 [new JS.ArrayInitializer(names.toList(), multiline: true)]);
669
670 JS.Expression _emitExtensionName(String name) =>
671 js.call('dartx.#', _propertyName(name));
672
661 /// Emit class members that need to come after the class declaration, such 673 /// Emit class members that need to come after the class declaration, such
662 /// as static fields. See [_emitClassMethods] for things that are emitted 674 /// as static fields. See [_emitClassMethods] for things that are emitted
663 /// inside the ES6 `class { ... }` node. 675 /// inside the ES6 `class { ... }` node.
664 JS.Statement _finishClassMembers( 676 JS.Statement _finishClassMembers(
665 ClassElement classElem, 677 ClassElement classElem,
666 JS.ClassExpression cls, 678 JS.ClassExpression cls,
667 List<ConstructorDeclaration> ctors, 679 List<ConstructorDeclaration> ctors,
668 List<FieldDeclaration> fields, 680 List<FieldDeclaration> fields,
669 List<FieldDeclaration> staticFields, 681 List<FieldDeclaration> staticFields,
670 List<MethodDeclaration> methods, 682 List<MethodDeclaration> methods,
671 List<Annotation> metadata, 683 List<Annotation> metadata,
672 String jsPeerName) { 684 String jsPeerName) {
673 var name = classElem.name; 685 var name = classElem.name;
674 var body = <JS.Statement>[]; 686 var body = <JS.Statement>[];
675 687
676 if (_extensionTypes.contains(classElem)) { 688 if (_extensionTypes.contains(classElem)) {
677 var dartxNames = <JS.Expression>[]; 689 var dartxNames = <JS.Expression>[];
678 for (var m in methods) { 690 for (var m in methods) {
679 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { 691 if (!m.isAbstract && !m.isStatic && m.element.isPublic) {
680 dartxNames.add(_elementMemberName(m.element, allowExtensions: false)); 692 dartxNames.add(_elementMemberName(m.element, allowExtensions: false));
681 } 693 }
682 } 694 }
683 if (dartxNames.isNotEmpty) { 695 if (dartxNames.isNotEmpty) {
684 body.add(js.statement('dart.defineExtensionNames(#)', 696 body.add(_emitExtensionNamesDeclaration(dartxNames));
685 [new JS.ArrayInitializer(dartxNames, multiline: true)]));
686 } 697 }
687 } 698 }
688 699
689 body.add(new JS.ClassDeclaration(cls)); 700 body.add(new JS.ClassDeclaration(cls));
690 701
691 // TODO(jmesserly): we should really just extend native Array. 702 // TODO(jmesserly): we should really just extend native Array.
692 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { 703 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) {
693 body.add(js.statement('dart.setBaseClass(#, dart.global.#);', 704 body.add(js.statement('dart.setBaseClass(#, dart.global.#);',
694 [classElem.name, _propertyName(jsPeerName)])); 705 [classElem.name, _propertyName(jsPeerName)]));
695 } 706 }
(...skipping 2688 matching lines...) Expand 10 before | Expand all | Expand 10 after
3384 /// for this transformation to happen, otherwise binary minus is assumed. 3395 /// for this transformation to happen, otherwise binary minus is assumed.
3385 /// 3396 ///
3386 /// Equality is a bit special, it is generated via the Dart `equals` runtime 3397 /// Equality is a bit special, it is generated via the Dart `equals` runtime
3387 /// helper, that checks for null. The user defined method is called '=='. 3398 /// helper, that checks for null. The user defined method is called '=='.
3388 /// 3399 ///
3389 JS.Expression _emitMemberName(String name, 3400 JS.Expression _emitMemberName(String name,
3390 {DartType type, 3401 {DartType type,
3391 bool unary: false, 3402 bool unary: false,
3392 bool isStatic: false, 3403 bool isStatic: false,
3393 bool allowExtensions: true}) { 3404 bool allowExtensions: true}) {
3394 // Static members skip the rename steps. 3405 // Static members skip the rename steps, except for Function properties.
3395 if (isStatic) return _propertyName(name); 3406 if (isStatic) {
3407 if (options.closure) {
3408 // Avoid colliding with Function properties, which might be desirable
3409 // in general but is critical to work around a Closure ES6->ES5 bug
3410 // (https://github.com/google/closure-compiler/issues/1460).
3411 if (invalidStaticFieldName(name, closureCompiler: true)) {
Jennifer Messerly 2016/01/28 20:03:36 I still don't understand why were are using extens
Jennifer Messerly 2016/02/02 00:22:56 We chatted about this, decided extension method sy
ochafik 2016/02/03 19:58:49 Done.
ochafik 2016/02/03 19:58:49 Acknowledged.
3412 _topLevelExtensionNames.add(name);
3413 return _emitExtensionName(name);
3414 }
3415 }
3416 return _propertyName(name);
3417 }
3396 3418
3397 if (name.startsWith('_')) { 3419 if (name.startsWith('_')) {
3398 return _privateNames.putIfAbsent( 3420 return _privateNames.putIfAbsent(
3399 name, () => _initSymbol(new JS.TemporaryId(name)) as JS.TemporaryId); 3421 name, () => _initSymbol(new JS.TemporaryId(name)) as JS.TemporaryId);
3400 } 3422 }
3401 3423
3402 if (name == '[]') { 3424 if (name == '[]') {
3403 name = 'get'; 3425 name = 'get';
3404 } else if (name == '[]=') { 3426 } else if (name == '[]=') {
3405 name = 'set'; 3427 name = 'set';
3406 } else if (name == '-' && unary) { 3428 } else if (name == '-' && unary) {
3407 name = 'unary-'; 3429 name = 'unary-';
3408 } else if (name == 'constructor' || name == 'prototype') { 3430 } else if (name == 'constructor' || name == 'prototype') {
3409 // This uses an illegal (in Dart) character for a member, avoiding the 3431 // This uses an illegal (in Dart) character for a member, avoiding the
3410 // conflict. We could use practically any character for this. 3432 // conflict. We could use practically any character for this.
3411 name = '+$name'; 3433 name = '+$name';
3412 } 3434 }
3413 3435
3414 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. 3436 // Dart "extension" methods. Used for JS Array, Boolean, Number, String.
3415 var baseType = type; 3437 var baseType = type;
3416 while (baseType is TypeParameterType) { 3438 while (baseType is TypeParameterType) {
3417 baseType = baseType.element.bound; 3439 baseType = baseType.element.bound;
3418 } 3440 }
3419 if (allowExtensions && 3441 if (allowExtensions &&
3420 _extensionTypes.contains(baseType.element) && 3442 _extensionTypes.contains(baseType.element) &&
3421 !_isObjectProperty(name)) { 3443 !_isObjectProperty(name)) {
3422 return js.call('dartx.#', _propertyName(name)); 3444 return _emitExtensionName(name);
3423 } 3445 }
3424 3446
3425 return _propertyName(name); 3447 return _propertyName(name);
3426 } 3448 }
3427 3449
3428 bool _externalOrNative(node) => 3450 bool _externalOrNative(node) =>
3429 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; 3451 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody;
3430 3452
3431 FunctionBody _functionBody(node) => 3453 FunctionBody _functionBody(node) =>
3432 node is FunctionDeclaration ? node.functionExpression.body : node.body; 3454 node is FunctionDeclaration ? node.functionExpression.body : node.body;
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
3610 3632
3611 /// A special kind of element created by the compiler, signifying a temporary 3633 /// A special kind of element created by the compiler, signifying a temporary
3612 /// variable. These objects use instance equality, and should be shared 3634 /// variable. These objects use instance equality, and should be shared
3613 /// everywhere in the tree where they are treated as the same variable. 3635 /// everywhere in the tree where they are treated as the same variable.
3614 class TemporaryVariableElement extends LocalVariableElementImpl { 3636 class TemporaryVariableElement extends LocalVariableElementImpl {
3615 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3637 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3616 3638
3617 int get hashCode => identityHashCode(this); 3639 int get hashCode => identityHashCode(this);
3618 bool operator ==(Object other) => identical(this, other); 3640 bool operator ==(Object other) => identical(this, other);
3619 } 3641 }
OLDNEW
« no previous file with comments | « no previous file | lib/src/codegen/js_names.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698