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

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: left todo 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 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; 5 import 'dart:collection' show HashSet, HashMap, SplayTreeSet;
6 6
7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
8 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; 8 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
9 import 'package:analyzer/src/generated/constant.dart'; 9 import 'package:analyzer/src/generated/constant.dart';
10 import 'package:analyzer/src/generated/element.dart'; 10 import 'package:analyzer/src/generated/element.dart';
(...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 = <String, String>{}; 83 final _exports = <String, 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 if (decl is TopLevelVariableDeclaration) { 162 if (decl is TopLevelVariableDeclaration) {
162 visitTopLevelVariableDeclaration(decl); 163 visitTopLevelVariableDeclaration(decl);
163 } else { 164 } else {
164 _loader.loadDeclaration(decl, decl.element); 165 _loader.loadDeclaration(decl, decl.element);
165 } 166 }
166 } 167 }
167 } 168 }
168 169
169 // Flush any unwritten fields/properties. 170 // Flush any unwritten fields/properties.
170 _flushLibraryProperties(_moduleItems); 171 _flushLibraryProperties(_moduleItems);
172 // TODO(ochafik): Refactor to merge this with the dartxNames codepath.
173 if (_topLevelExtensionNames.isNotEmpty) {
174 _moduleItems.add(_emitExtensionNamesDeclaration(
175 _topLevelExtensionNames.map(js.string).toList()));
176 }
171 177
172 // Mark all qualified names as qualified or not, depending on if they need 178 // Mark all qualified names as qualified or not, depending on if they need
173 // to be loaded lazily or not. 179 // to be loaded lazily or not.
174 for (var elementIdPairs in _qualifiedIds) { 180 for (var elementIdPairs in _qualifiedIds) {
175 var element = elementIdPairs.e0; 181 var element = elementIdPairs.e0;
176 var id = elementIdPairs.e1; 182 var id = elementIdPairs.e1;
177 id.setQualified(!_loader.isLoaded(element)); 183 id.setQualified(!_loader.isLoaded(element));
178 } 184 }
179 185
180 var moduleBuilder = new ModuleBuilder(options.moduleFormat); 186 var moduleBuilder = new ModuleBuilder(options.moduleFormat);
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 JS.Expression _instantiateAnnotation(Annotation node) { 673 JS.Expression _instantiateAnnotation(Annotation node) {
668 var element = node.element; 674 var element = node.element;
669 if (element is ConstructorElement) { 675 if (element is ConstructorElement) {
670 return _emitInstanceCreationExpression(element, element.returnType, 676 return _emitInstanceCreationExpression(element, element.returnType,
671 node.constructorName, node.arguments, true); 677 node.constructorName, node.arguments, true);
672 } else { 678 } else {
673 return _visit(node.name); 679 return _visit(node.name);
674 } 680 }
675 } 681 }
676 682
683 JS.Statement _emitExtensionNamesDeclaration(List<JS.Expression> names) =>
684 js.statement('dart.defineExtensionNames(#)',
685 [new JS.ArrayInitializer(names.toList(), multiline: true)]);
686
687 JS.Expression _emitExtensionName(String name) =>
688 js.call('dartx.#', _propertyName(name));
689
677 /// Emit class members that need to come after the class declaration, such 690 /// Emit class members that need to come after the class declaration, such
678 /// as static fields. See [_emitClassMethods] for things that are emitted 691 /// as static fields. See [_emitClassMethods] for things that are emitted
679 /// inside the ES6 `class { ... }` node. 692 /// inside the ES6 `class { ... }` node.
680 JS.Statement _finishClassMembers( 693 JS.Statement _finishClassMembers(
681 ClassElement classElem, 694 ClassElement classElem,
682 JS.ClassExpression cls, 695 JS.ClassExpression cls,
683 List<ConstructorDeclaration> ctors, 696 List<ConstructorDeclaration> ctors,
684 List<FieldDeclaration> fields, 697 List<FieldDeclaration> fields,
685 List<FieldDeclaration> staticFields, 698 List<FieldDeclaration> staticFields,
686 List<MethodDeclaration> methods, 699 List<MethodDeclaration> methods,
687 List<Annotation> metadata, 700 List<Annotation> metadata,
688 String jsPeerName) { 701 String jsPeerName) {
689 var name = classElem.name; 702 var name = classElem.name;
690 var body = <JS.Statement>[]; 703 var body = <JS.Statement>[];
691 704
692 if (_extensionTypes.contains(classElem)) { 705 if (_extensionTypes.contains(classElem)) {
693 var dartxNames = <JS.Expression>[]; 706 var dartxNames = <JS.Expression>[];
694 for (var m in methods) { 707 for (var m in methods) {
695 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { 708 if (!m.isAbstract && !m.isStatic && m.element.isPublic) {
696 dartxNames.add(_elementMemberName(m.element, allowExtensions: false)); 709 dartxNames.add(_elementMemberName(m.element, allowExtensions: false));
697 } 710 }
698 } 711 }
699 if (dartxNames.isNotEmpty) { 712 if (dartxNames.isNotEmpty) {
700 body.add(js.statement('dart.defineExtensionNames(#)', 713 body.add(_emitExtensionNamesDeclaration(dartxNames));
701 [new JS.ArrayInitializer(dartxNames, multiline: true)]));
702 } 714 }
703 } 715 }
704 716
705 body.add(new JS.ClassDeclaration(cls)); 717 body.add(new JS.ClassDeclaration(cls));
706 718
707 // TODO(jmesserly): we should really just extend native Array. 719 // TODO(jmesserly): we should really just extend native Array.
708 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { 720 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) {
709 body.add(js.statement('dart.setBaseClass(#, dart.global.#);', 721 body.add(js.statement('dart.setBaseClass(#, dart.global.#);',
710 [classElem.name, _propertyName(jsPeerName)])); 722 [classElem.name, _propertyName(jsPeerName)]));
711 } 723 }
(...skipping 1518 matching lines...) Expand 10 before | Expand all | Expand 10 after
2230 assert(element.isStatic); 2242 assert(element.isStatic);
2231 2243
2232 _loader.startCheckingReferences(); 2244 _loader.startCheckingReferences();
2233 JS.Expression jsInit = _visitInitializer(field); 2245 JS.Expression jsInit = _visitInitializer(field);
2234 bool isLoaded = _loader.finishCheckingReferences(); 2246 bool isLoaded = _loader.finishCheckingReferences();
2235 2247
2236 bool eagerInit = 2248 bool eagerInit =
2237 isLoaded && (field.isConst || _constField.isFieldInitConstant(field)); 2249 isLoaded && (field.isConst || _constField.isFieldInitConstant(field));
2238 2250
2239 var fieldName = field.name.name; 2251 var fieldName = field.name.name;
2240 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) { 2252 if (eagerInit && !JS.invalidStaticFieldName(fieldName, options)) {
2241 return annotateVariable( 2253 return annotateVariable(
2242 js.statement('#.# = #;', [ 2254 js.statement('#.# = #;', [
2243 classElem.name, 2255 classElem.name,
2244 _emitMemberName(fieldName, isStatic: true), 2256 _emitMemberName(fieldName, isStatic: true),
2245 jsInit 2257 jsInit
2246 ]), 2258 ]),
2247 field.element); 2259 field.element);
2248 } 2260 }
2249 2261
2250 // This means it should be treated as a lazy field. 2262 // This means it should be treated as a lazy field.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2290 // anything they depend on first. 2302 // anything they depend on first.
2291 2303
2292 if (isPublic(fieldName)) _addExport(fieldName, exportName); 2304 if (isPublic(fieldName)) _addExport(fieldName, exportName);
2293 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; 2305 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let';
2294 return annotateVariable( 2306 return annotateVariable(
2295 js.statement( 2307 js.statement(
2296 '$declKeyword # = #;', [new JS.Identifier(fieldName), jsInit]), 2308 '$declKeyword # = #;', [new JS.Identifier(fieldName), jsInit]),
2297 field.element); 2309 field.element);
2298 } 2310 }
2299 2311
2300 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) { 2312 if (eagerInit && !JS.invalidStaticFieldName(fieldName, options)) {
2301 return annotateVariable( 2313 return annotateVariable(
2302 js.statement('# = #;', [_visit(field.name), jsInit]), field.element); 2314 js.statement('# = #;', [_visit(field.name), jsInit]), field.element);
2303 } 2315 }
2304 2316
2305 return _emitLazyFields(currentLibrary, [field]); 2317 return _emitLazyFields(currentLibrary, [field]);
2306 } 2318 }
2307 2319
2308 JS.Expression _visitInitializer(VariableDeclaration node) { 2320 JS.Expression _visitInitializer(VariableDeclaration node) {
2309 var value = _visit(node.initializer); 2321 var value = _visit(node.initializer);
2310 // explicitly initialize to null, to avoid getting `undefined`. 2322 // explicitly initialize to null, to avoid getting `undefined`.
(...skipping 1053 matching lines...) Expand 10 before | Expand all | Expand 10 after
3364 /// for this transformation to happen, otherwise binary minus is assumed. 3376 /// for this transformation to happen, otherwise binary minus is assumed.
3365 /// 3377 ///
3366 /// Equality is a bit special, it is generated via the Dart `equals` runtime 3378 /// Equality is a bit special, it is generated via the Dart `equals` runtime
3367 /// helper, that checks for null. The user defined method is called '=='. 3379 /// helper, that checks for null. The user defined method is called '=='.
3368 /// 3380 ///
3369 JS.Expression _emitMemberName(String name, 3381 JS.Expression _emitMemberName(String name,
3370 {DartType type, 3382 {DartType type,
3371 bool unary: false, 3383 bool unary: false,
3372 bool isStatic: false, 3384 bool isStatic: false,
3373 bool allowExtensions: true}) { 3385 bool allowExtensions: true}) {
3374 // Static members skip the rename steps. 3386 // Static members skip the rename steps, except for Function properties.
3375 if (isStatic) return _propertyName(name); 3387 if (isStatic) {
3388 // Avoid colliding with names on Function that are disallowed in ES6,
3389 // or where we need to work around transpilers.
3390 if (invalidStaticFieldName(name, options)) {
3391 _topLevelExtensionNames.add(name);
3392 return _emitExtensionName(name);
3393 } else {
3394 return _propertyName(name);
3395 }
3396 }
3376 3397
3377 if (name.startsWith('_')) { 3398 if (name.startsWith('_')) {
3378 return _privateNames.putIfAbsent( 3399 return _privateNames.putIfAbsent(
3379 name, () => _initSymbol(new JS.TemporaryId(name)) as JS.TemporaryId); 3400 name, () => _initSymbol(new JS.TemporaryId(name)) as JS.TemporaryId);
3380 } 3401 }
3381 3402
3382 if (name == '[]') { 3403 if (name == '[]') {
3383 name = 'get'; 3404 name = 'get';
3384 } else if (name == '[]=') { 3405 } else if (name == '[]=') {
3385 name = 'set'; 3406 name = 'set';
3386 } else if (name == '-' && unary) { 3407 } else if (name == '-' && unary) {
3387 name = 'unary-'; 3408 name = 'unary-';
3388 } else if (name == 'constructor' || name == 'prototype') { 3409 } else if (name == 'constructor' || name == 'prototype') {
3389 // This uses an illegal (in Dart) character for a member, avoiding the 3410 // This uses an illegal (in Dart) character for a member, avoiding the
3390 // conflict. We could use practically any character for this. 3411 // conflict. We could use practically any character for this.
3391 name = '+$name'; 3412 name = '+$name';
3392 } 3413 }
3393 3414
3394 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. 3415 // Dart "extension" methods. Used for JS Array, Boolean, Number, String.
3395 var baseType = type; 3416 var baseType = type;
3396 while (baseType is TypeParameterType) { 3417 while (baseType is TypeParameterType) {
3397 baseType = baseType.element.bound; 3418 baseType = baseType.element.bound;
3398 } 3419 }
3399 if (allowExtensions && 3420 if (allowExtensions &&
3400 _extensionTypes.contains(baseType.element) && 3421 _extensionTypes.contains(baseType.element) &&
3401 !_isObjectProperty(name)) { 3422 !_isObjectProperty(name)) {
3402 return js.call('dartx.#', _propertyName(name)); 3423 return _emitExtensionName(name);
3403 } 3424 }
3404 3425
3405 return _propertyName(name); 3426 return _propertyName(name);
3406 } 3427 }
3407 3428
3408 bool _externalOrNative(node) => 3429 bool _externalOrNative(node) =>
3409 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; 3430 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody;
3410 3431
3411 FunctionBody _functionBody(node) => 3432 FunctionBody _functionBody(node) =>
3412 node is FunctionDeclaration ? node.functionExpression.body : node.body; 3433 node is FunctionDeclaration ? node.functionExpression.body : node.body;
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
3589 3610
3590 /// A special kind of element created by the compiler, signifying a temporary 3611 /// A special kind of element created by the compiler, signifying a temporary
3591 /// variable. These objects use instance equality, and should be shared 3612 /// variable. These objects use instance equality, and should be shared
3592 /// everywhere in the tree where they are treated as the same variable. 3613 /// everywhere in the tree where they are treated as the same variable.
3593 class TemporaryVariableElement extends LocalVariableElementImpl { 3614 class TemporaryVariableElement extends LocalVariableElementImpl {
3594 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3615 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3595 3616
3596 int get hashCode => identityHashCode(this); 3617 int get hashCode => identityHashCode(this);
3597 bool operator ==(Object other) => identical(this, other); 3618 bool operator ==(Object other) => identical(this, other);
3598 } 3619 }
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