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

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

Issue 1122133003: fixes #157, renaming local library identifiers if needed. (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: rebase and format Created 5 years, 7 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 | « lib/runtime/dart_runtime.js ('k') | test/codegen/expect/8invalid-chars.in+file_name.js » ('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; 7 import 'dart:collection' show HashSet, HashMap;
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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 final HashSet<FieldElement> _fieldsNeedingStorage; 61 final HashSet<FieldElement> _fieldsNeedingStorage;
62 62
63 /// The variable for the target of the current `..` cascade expression. 63 /// The variable for the target of the current `..` cascade expression.
64 SimpleIdentifier _cascadeTarget; 64 SimpleIdentifier _cascadeTarget;
65 65
66 /// The variable for the current catch clause 66 /// The variable for the current catch clause
67 SimpleIdentifier _catchParameter; 67 SimpleIdentifier _catchParameter;
68 68
69 ConstantEvaluator _constEvaluator; 69 ConstantEvaluator _constEvaluator;
70 70
71 /// Imported libraries, and the temporaries used to refer to them.
72 final _imports = new Map<LibraryElement, JS.TemporaryId>();
71 final _exports = new Set<String>(); 73 final _exports = new Set<String>();
72 final _lazyFields = <VariableDeclaration>[]; 74 final _lazyFields = <VariableDeclaration>[];
73 final _properties = <FunctionDeclaration>[]; 75 final _properties = <FunctionDeclaration>[];
74 final _privateNames = new HashMap<String, JS.TemporaryId>(); 76 final _privateNames = new HashMap<String, JS.TemporaryId>();
75 final _extensionMethodNames = new HashSet<String>(); 77 final _extensionMethodNames = new HashSet<String>();
76 final _pendingStatements = <JS.Statement>[]; 78 final _pendingStatements = <JS.Statement>[];
77 final _temps = new HashMap<Element, JS.TemporaryId>(); 79 final _temps = new HashMap<Element, JS.TemporaryId>();
78 80
79 /// The name for the library's exports inside itself. 81 /// The name for the library's exports inside itself.
80 /// This much be a constant because we interpolate it into template strings,
81 /// and otherwise it would break caching for them.
82 /// `exports` was chosen as the most similar to ES module patterns. 82 /// `exports` was chosen as the most similar to ES module patterns.
83 final _exportsVar = new JS.TemporaryId('exports'); 83 final _exportsVar = new JS.TemporaryId('exports');
84 final _namedArgTemp = new JS.TemporaryId('opts'); 84 final _namedArgTemp = new JS.TemporaryId('opts');
85 85
86 /// Classes we have not emitted yet. Values can be [ClassDeclaration] or 86 /// Classes we have not emitted yet. Values can be [ClassDeclaration] or
87 /// [ClassTypeAlias]. 87 /// [ClassTypeAlias].
88 final _pendingClasses = new HashMap<Element, CompilationUnitMember>(); 88 final _pendingClasses = new HashMap<Element, CompilationUnitMember>();
89 89
90 /// Memoized results of [_lazyClass]. 90 /// Memoized results of [_lazyClass].
91 final _lazyClassMemo = new HashMap<Element, bool>(); 91 final _lazyClassMemo = new HashMap<Element, bool>();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 134
135 assert(_pendingClasses.isEmpty); 135 assert(_pendingClasses.isEmpty);
136 136
137 if (_exports.isNotEmpty) body.add(js.comment('Exports:')); 137 if (_exports.isNotEmpty) body.add(js.comment('Exports:'));
138 138
139 // TODO(jmesserly): make these immutable in JS? 139 // TODO(jmesserly): make these immutable in JS?
140 for (var name in _exports) { 140 for (var name in _exports) {
141 body.add(js.statement('#.# = #;', [_exportsVar, name, name])); 141 body.add(js.statement('#.# = #;', [_exportsVar, name, name]));
142 } 142 }
143 143
144 var name = jsLibraryName(libraryInfo.library); 144 var name = new JS.Identifier(jsLibraryName(currentLibrary));
145 145
146 var defaultValue = js.call(jsDefaultValue); 146 // TODO(jmesserly): it would be great to run the renamer on the body,
147 return new JS.Program([ 147 // then figure out if we really need each of these parameters.
148 js.statement('var #;', name), 148 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34
149 js.statement("(function(#) { 'use strict'; #; })(# || (# = #));", [ 149 var program = [
150 _exportsVar, 150 js.statement('var # = dart.defineLibrary(#, #);', [
151 body,
152 name, 151 name,
153 name, 152 name,
154 defaultValue 153 js.call(jsDefaultValue)
155 ]) 154 ])
156 ]); 155 ];
156
157 var params = [_exportsVar];
158 var args = [name];
159 _imports.forEach((library, temp) {
160 var name = new JS.Identifier(temp.name);
161 params.add(temp);
162 args.add(name);
163 var helper = _libraryMightNotBeLoaded(library) ? 'lazyImport' : 'import';
164 program.add(js.statement('var # = dart.#(#);', [name, helper, name]));
165 });
166
167 program.add(js.statement(
168 "(function(#) { 'use strict'; #; })(#);", [params, body, args]));
169
170 return new JS.Program(program);
157 } 171 }
158 172
159 JS.Identifier _initSymbol(JS.Identifier id) { 173 JS.Identifier _initSymbol(JS.Identifier id) {
160 var s = js.statement('let # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); 174 var s = js.statement('let # = $_SYMBOL(#);', [id, js.string(id.name, "'")]);
161 _pendingStatements.add(s); 175 _pendingStatements.add(s);
162 return id; 176 return id;
163 } 177 }
164 178
165 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, 179 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core,
166 // until we have better name tracking. 180 // until we have better name tracking.
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 /// on this library via some transitive import path. 484 /// on this library via some transitive import path.
471 /// 485 ///
472 /// If we could control the global import ordering, we could eliminate some 486 /// If we could control the global import ordering, we could eliminate some
473 /// of these cases, by ordering the imports of the cyclic libraries in an 487 /// of these cases, by ordering the imports of the cyclic libraries in an
474 /// optimal way. For example, we could order the libraries in a cycle to 488 /// optimal way. For example, we could order the libraries in a cycle to
475 /// minimize laziness. However, we currently assume we cannot control the 489 /// minimize laziness. However, we currently assume we cannot control the
476 /// order that the cycle of libraries will be loaded in. 490 /// order that the cycle of libraries will be loaded in.
477 bool _typeMightNotBeLoaded(DartType type) { 491 bool _typeMightNotBeLoaded(DartType type) {
478 var library = type.element.library; 492 var library = type.element.library;
479 if (library == currentLibrary) return _lazyClass(type); 493 if (library == currentLibrary) return _lazyClass(type);
494 return _libraryMightNotBeLoaded(library);
495 }
480 496
497 bool _libraryMightNotBeLoaded(LibraryElement library) {
481 // The SDK is a special case: we optimize the order to prevent laziness. 498 // The SDK is a special case: we optimize the order to prevent laziness.
482 if (library.isInSdk) { 499 if (library.isInSdk) {
483 // SDK is loaded before non-SDK libraies 500 // SDK is loaded before non-SDK libraies
484 if (!currentLibrary.isInSdk) return false; 501 if (!currentLibrary.isInSdk) return false;
485 502
486 // Compute the order of both SDK libraries. If unknown, assume it's after. 503 // Compute the order of both SDK libraries. If unknown, assume it's after.
487 var classOrder = corelibOrder.indexOf(library.name); 504 var classOrder = corelibOrder.indexOf(library.name);
488 if (classOrder == -1) classOrder = corelibOrder.length; 505 if (classOrder == -1) classOrder = corelibOrder.length;
489 506
490 var currentOrder = corelibOrder.indexOf(currentLibrary.name); 507 var currentOrder = corelibOrder.indexOf(currentLibrary.name);
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 } 1111 }
1095 1112
1096 // Get the original declaring element. If we had a property accessor, this 1113 // Get the original declaring element. If we had a property accessor, this
1097 // indirects back to a (possibly synthetic) field. 1114 // indirects back to a (possibly synthetic) field.
1098 var element = accessor; 1115 var element = accessor;
1099 if (element is PropertyAccessorElement) element = accessor.variable; 1116 if (element is PropertyAccessorElement) element = accessor.variable;
1100 var name = element.name; 1117 var name = element.name;
1101 1118
1102 // library member 1119 // library member
1103 if (element.enclosingElement is CompilationUnitElement && 1120 if (element.enclosingElement is CompilationUnitElement &&
1104 (element.library != libraryInfo.library || 1121 (element.library != currentLibrary ||
1105 element is TopLevelVariableElement && !element.isConst)) { 1122 element is TopLevelVariableElement && !element.isConst)) {
1106 var memberName = _emitMemberName(name, isStatic: true); 1123 var memberName = _emitMemberName(name, isStatic: true);
1107 return js.call('#.#', [_libraryName(element.library), memberName]); 1124 return js.call('#.#', [_libraryName(element.library), memberName]);
1108 } 1125 }
1109 1126
1110 // Unqualified class member. This could mean implicit-this, or implicit 1127 // Unqualified class member. This could mean implicit-this, or implicit
1111 // call to a static from the same class. 1128 // call to a static from the same class.
1112 if (element is ClassMemberElement && element is! ConstructorElement) { 1129 if (element is ClassMemberElement && element is! ConstructorElement) {
1113 bool isStatic = element.isStatic; 1130 bool isStatic = element.isStatic;
1114 var type = element.enclosingElement.type; 1131 var type = element.enclosingElement.type;
(...skipping 1121 matching lines...) Expand 10 before | Expand all | Expand 10 after
2236 2253
2237 @override 2254 @override
2238 visitNullLiteral(NullLiteral node) => new JS.LiteralNull(); 2255 visitNullLiteral(NullLiteral node) => new JS.LiteralNull();
2239 2256
2240 @override 2257 @override
2241 visitSymbolLiteral(SymbolLiteral node) { 2258 visitSymbolLiteral(SymbolLiteral node) {
2242 // TODO(vsm): When we canonicalize, we need to treat private symbols 2259 // TODO(vsm): When we canonicalize, we need to treat private symbols
2243 // correctly. 2260 // correctly.
2244 var name = js.string(node.components.join('.'), "'"); 2261 var name = js.string(node.components.join('.'), "'");
2245 var nameHint = 'symbol_' + node.components.join('_'); 2262 var nameHint = 'symbol_' + node.components.join('_');
2246 return _const(node, js.call('new core.Symbol(#)', name), nameHint); 2263 return _const(
2264 node, new JS.New(_emitTypeName(types.symbolType), [name]), nameHint);
2247 } 2265 }
2248 2266
2249 @override 2267 @override
2250 visitListLiteral(ListLiteral node) { 2268 visitListLiteral(ListLiteral node) {
2251 JS.Expression list = new JS.ArrayInitializer(_visitList(node.elements)); 2269 JS.Expression list = new JS.ArrayInitializer(_visitList(node.elements));
2252 2270
2253 ParameterizedType type = node.staticType; 2271 ParameterizedType type = node.staticType;
2254 if (type.typeArguments.any((a) => a != types.dynamicType)) { 2272 if (type.typeArguments.any((a) => a != types.dynamicType)) {
2255 list = js.call('dart.setType(#, #)', [list, _emitTypeName(type)]); 2273 list = js.call('dart.setType(#, #)', [list, _emitTypeName(type)]);
2256 } 2274 }
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
2485 bool _externalOrNative(node) => 2503 bool _externalOrNative(node) =>
2486 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; 2504 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody;
2487 2505
2488 FunctionBody _functionBody(node) => 2506 FunctionBody _functionBody(node) =>
2489 node is FunctionDeclaration ? node.functionExpression.body : node.body; 2507 node is FunctionDeclaration ? node.functionExpression.body : node.body;
2490 2508
2491 /// Choose a canonical name from the library element. 2509 /// Choose a canonical name from the library element.
2492 /// This never uses the library's name (the identifier in the `library` 2510 /// This never uses the library's name (the identifier in the `library`
2493 /// declaration) as it doesn't have any meaningful rules enforced. 2511 /// declaration) as it doesn't have any meaningful rules enforced.
2494 JS.Identifier _libraryName(LibraryElement library) { 2512 JS.Identifier _libraryName(LibraryElement library) {
2495 if (library == libraryInfo.library) return _exportsVar; 2513 if (library == currentLibrary) return _exportsVar;
2496 return new JS.Identifier(jsLibraryName(library)); 2514 return _imports.putIfAbsent(
2515 library, () => new JS.TemporaryId(jsLibraryName(library)));
2497 } 2516 }
2498 2517
2499 DartType getStaticType(Expression e) => rules.getStaticType(e); 2518 DartType getStaticType(Expression e) => rules.getStaticType(e);
2500 } 2519 }
2501 2520
2502 class JSGenerator extends CodeGenerator { 2521 class JSGenerator extends CodeGenerator {
2503 final CompilerOptions options; 2522 final CompilerOptions options;
2504 2523
2505 /// For fast lookup of extension methods, we first check the name, then do a 2524 /// For fast lookup of extension methods, we first check the name, then do a
2506 /// (possibly expensive) subtype test to see if it matches one of the types 2525 /// (possibly expensive) subtype test to see if it matches one of the types
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2570 // TODO(jmesserly): validate the library. See issue #135. 2589 // TODO(jmesserly): validate the library. See issue #135.
2571 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; 2590 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName';
2572 2591
2573 bool _isJsPeerInterface(DartObjectImpl value) => 2592 bool _isJsPeerInterface(DartObjectImpl value) =>
2574 value.type.name == 'JsPeerInterface'; 2593 value.type.name == 'JsPeerInterface';
2575 2594
2576 // TODO(jacobr): we would like to do something like the following 2595 // TODO(jacobr): we would like to do something like the following
2577 // but we don't have summary support yet. 2596 // but we don't have summary support yet.
2578 // bool _supportJsExtensionMethod(AnnotatedNode node) => 2597 // bool _supportJsExtensionMethod(AnnotatedNode node) =>
2579 // _getAnnotation(node, "SupportJsExtensionMethod") != null; 2598 // _getAnnotation(node, "SupportJsExtensionMethod") != null;
OLDNEW
« no previous file with comments | « lib/runtime/dart_runtime.js ('k') | test/codegen/expect/8invalid-chars.in+file_name.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698