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

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

Issue 1633003002: Add --modules=node support (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: merged master 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 | « lib/runtime/dart/html.js ('k') | lib/src/codegen/module_builder.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;
11 import 'package:analyzer/src/generated/constant.dart'; 11 import 'package:analyzer/src/generated/constant.dart';
12 import 'package:analyzer/src/generated/element.dart'; 12 import 'package:analyzer/src/generated/element.dart';
13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; 13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
14 import 'package:analyzer/src/generated/scanner.dart' 14 import 'package:analyzer/src/generated/scanner.dart'
15 show StringToken, Token, TokenType; 15 show StringToken, Token, TokenType;
16 import 'package:analyzer/src/generated/type_system.dart' 16 import 'package:analyzer/src/generated/type_system.dart'
17 show StrongTypeSystemImpl; 17 show StrongTypeSystemImpl;
18 import 'package:analyzer/src/task/dart.dart' show PublicNamespaceBuilder; 18 import 'package:analyzer/src/task/dart.dart' show PublicNamespaceBuilder;
19 19
20 import 'ast_builder.dart' show AstBuilder; 20 import 'ast_builder.dart' show AstBuilder;
21 import 'reify_coercions.dart' show CoercionReifier, Tuple2; 21 import 'reify_coercions.dart' show CoercionReifier, Tuple2;
22 22
23 // TODO(jmesserly): import from its own package 23 // TODO(jmesserly): import from its own package
24 import '../js/js_ast.dart' as JS; 24 import '../js/js_ast.dart' as JS;
25 import '../js/js_ast.dart' show js; 25 import '../js/js_ast.dart' show js;
26 26
27 import '../closure/closure_annotator.dart' show ClosureAnnotator; 27 import '../closure/closure_annotator.dart' show ClosureAnnotator;
28 import '../compiler.dart' show AbstractCompiler; 28 import '../compiler.dart'
29 show AbstractCompiler, corelibOrder, getCorelibModuleName;
29 import '../info.dart'; 30 import '../info.dart';
30 import '../options.dart' show CodegenOptions; 31 import '../options.dart' show CodegenOptions;
31 import '../utils.dart'; 32 import '../utils.dart';
32 33
33 import 'code_generator.dart'; 34 import 'code_generator.dart';
34 import 'js_field_storage.dart'; 35 import 'js_field_storage.dart';
35 import 'js_interop.dart'; 36 import 'js_interop.dart';
36 import 'js_names.dart' as JS; 37 import 'js_names.dart' as JS;
37 import 'js_metalet.dart' as JS; 38 import 'js_metalet.dart' as JS;
38 import 'js_module_item_order.dart'; 39 import 'js_module_item_order.dart';
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 Expression _cascadeTarget; 75 Expression _cascadeTarget;
75 76
76 /// The variable for the current catch clause 77 /// The variable for the current catch clause
77 SimpleIdentifier _catchParameter; 78 SimpleIdentifier _catchParameter;
78 79
79 /// In an async* function, this represents the stream controller parameter. 80 /// In an async* function, this represents the stream controller parameter.
80 JS.TemporaryId _asyncStarController; 81 JS.TemporaryId _asyncStarController;
81 82
82 /// Imported libraries, and the temporaries used to refer to them. 83 /// Imported libraries, and the temporaries used to refer to them.
83 final _imports = new Map<LibraryElement, JS.TemporaryId>(); 84 final _imports = new Map<LibraryElement, JS.TemporaryId>();
84 final _exports = new Set<String>(); 85 final _exports = <String, String>{};
85 final _properties = <FunctionDeclaration>[]; 86 final _properties = <FunctionDeclaration>[];
86 final _privateNames = new HashMap<String, JS.TemporaryId>(); 87 final _privateNames = new HashMap<String, JS.TemporaryId>();
87 final _moduleItems = <JS.Statement>[]; 88 final _moduleItems = <JS.Statement>[];
88 final _temps = new HashMap<Element, JS.TemporaryId>(); 89 final _temps = new HashMap<Element, JS.TemporaryId>();
89 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>(); 90 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>();
90 91
91 /// The name for the library's exports inside itself. 92 /// The name for the library's exports inside itself.
92 /// `exports` was chosen as the most similar to ES module patterns. 93 /// `exports` was chosen as the most similar to ES module patterns.
93 final _dartxVar = new JS.Identifier('dartx'); 94 final _dartxVar = new JS.Identifier('dartx');
94 final _exportsVar = new JS.TemporaryId('exports'); 95 final _exportsVar = new JS.TemporaryId('exports');
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 var id = elementIdPairs.e1; 178 var id = elementIdPairs.e1;
178 id.setQualified(!_loader.isLoaded(element)); 179 id.setQualified(!_loader.isLoaded(element));
179 } 180 }
180 181
181 var moduleBuilder = new ModuleBuilder(options.moduleFormat); 182 var moduleBuilder = new ModuleBuilder(options.moduleFormat);
182 183
183 _exports.forEach(moduleBuilder.addExport); 184 _exports.forEach(moduleBuilder.addExport);
184 185
185 var items = <JS.ModuleItem>[]; 186 var items = <JS.ModuleItem>[];
186 if (!_isDartRuntime) { 187 if (!_isDartRuntime) {
188 if (currentLibrary.source.isInSystemLibrary) {
189 // Force the import order of runtime libs.
190 // TODO(ochafik): Reduce this to a minimum.
191 for (var lib in corelibOrder.reversed) {
192 // TODO(ochafik): Use uris instead in corelibOrder.
193 moduleBuilder.addImport(getCorelibModuleName(lib), null);
194 }
195 }
187 moduleBuilder.addImport('dart/_runtime', _runtimeLibVar); 196 moduleBuilder.addImport('dart/_runtime', _runtimeLibVar);
188 197
189 var dartxImport = 198 var dartxImport =
190 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); 199 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]);
191 items.add(dartxImport); 200 items.add(dartxImport);
192 } 201 }
193 items.addAll(_moduleItems); 202 items.addAll(_moduleItems);
194 203
195 _imports.forEach((LibraryElement lib, JS.TemporaryId temp) { 204 _imports.forEach((LibraryElement lib, JS.TemporaryId temp) {
196 moduleBuilder.addImport(compiler.getModuleName(lib.source.uri), temp, 205 moduleBuilder.addImport(compiler.getModuleName(lib.source.uri), temp,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 .where((s) => !currentLibNames.containsKey(s)) 266 .where((s) => !currentLibNames.containsKey(s))
258 .map((s) => js.string(s, "'"))); 267 .map((s) => js.string(s, "'")));
259 } 268 }
260 if (hide != null) { 269 if (hide != null) {
261 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); 270 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'")));
262 } 271 }
263 args.add(new JS.ArrayInitializer(shownNames)); 272 args.add(new JS.ArrayInitializer(shownNames));
264 args.add(new JS.ArrayInitializer(hiddenNames)); 273 args.add(new JS.ArrayInitializer(hiddenNames));
265 } 274 }
266 275
267 // When we compile _runtime.js, we need to source export_ from _utils.js:
268 _moduleItems.add(js.statement('dart.export(#);', [args])); 276 _moduleItems.add(js.statement('dart.export(#);', [args]));
269 } 277 }
270 278
271 JS.Identifier _initSymbol(JS.Identifier id) { 279 JS.Identifier _initSymbol(JS.Identifier id) {
272 var s = 280 var s =
273 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); 281 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]);
274 _moduleItems.add(s); 282 _moduleItems.add(s);
275 return id; 283 return id;
276 } 284 }
277 285
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 var genericInst = _emitTypeName(dynType, lowerGeneric: true); 539 var genericInst = _emitTypeName(dynType, lowerGeneric: true);
532 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); 540 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]);
533 } 541 }
534 return body; 542 return body;
535 } 543 }
536 544
537 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { 545 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) {
538 var name = type.name; 546 var name = type.name;
539 var genericName = '$name\$'; 547 var genericName = '$name\$';
540 var typeParams = _typeFormalsOf(type).map((p) => p.name); 548 var typeParams = _typeFormalsOf(type).map((p) => p.name);
541 if (isPublic(name)) _exports.add(genericName); 549 if (isPublic(name)) _addExport(genericName);
542 return js.statement('const # = dart.generic(function(#) { #; return #; });', 550 return js.statement('const # = dart.generic(function(#) { #; return #; });',
543 [genericName, typeParams, body, name]); 551 [genericName, typeParams, body, name]);
544 } 552 }
545 553
546 final _hasDeferredSupertype = new HashSet<ClassElement>(); 554 final _hasDeferredSupertype = new HashSet<ClassElement>();
547 555
548 bool _deferIfNeeded(DartType type, ClassElement current) { 556 bool _deferIfNeeded(DartType type, ClassElement current) {
549 if (type is ParameterizedType) { 557 if (type is ParameterizedType) {
550 var typeArguments = type.typeArguments; 558 var typeArguments = type.typeArguments;
551 for (var typeArg in typeArguments) { 559 for (var typeArg in typeArguments) {
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 1303
1296 if (node.isGetter || node.isSetter) { 1304 if (node.isGetter || node.isSetter) {
1297 // Add these later so we can use getter/setter syntax. 1305 // Add these later so we can use getter/setter syntax.
1298 _properties.add(node); 1306 _properties.add(node);
1299 return null; 1307 return null;
1300 } 1308 }
1301 1309
1302 var body = <JS.Statement>[]; 1310 var body = <JS.Statement>[];
1303 _flushLibraryProperties(body); 1311 _flushLibraryProperties(body);
1304 1312
1305 var name = _getJSExportName(node.element) ?? node.name.name; 1313 var name = node.name.name;
1306 1314
1307 var fn = _visit(node.functionExpression); 1315 var fn = _visit(node.functionExpression);
1308 1316
1309 if (currentLibrary.source.isInSystemLibrary && 1317 if (currentLibrary.source.isInSystemLibrary &&
1310 _isInlineJSFunction(node.functionExpression)) { 1318 _isInlineJSFunction(node.functionExpression)) {
1311 fn = _simplifyPassThroughArrowFunCallBody(fn); 1319 fn = _simplifyPassThroughArrowFunCallBody(fn);
1312 } 1320 }
1313 1321
1314 var id = new JS.Identifier(name); 1322 var id = new JS.Identifier(name);
1315 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element)); 1323 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element));
1316 if (!_isDartRuntime) { 1324 if (!_isDartRuntime) {
1317 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) 1325 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true)
1318 .toStatement()); 1326 .toStatement());
1319 } 1327 }
1320 1328
1321 if (isPublic(name)) _addExport(name); 1329 if (isPublic(name)) {
1330 _addExport(name, _getJSExportName(node.element) ?? name);
1331 }
1322 return _statement(body); 1332 return _statement(body);
1323 } 1333 }
1324 1334
1325 bool _isInlineJSFunction(FunctionExpression functionExpression) { 1335 bool _isInlineJSFunction(FunctionExpression functionExpression) {
1326 var body = functionExpression.body; 1336 var body = functionExpression.body;
1327 if (body is ExpressionFunctionBody) { 1337 if (body is ExpressionFunctionBody) {
1328 return _isJSInvocation(body.expression); 1338 return _isJSInvocation(body.expression);
1329 } else if (body is BlockFunctionBody) { 1339 } else if (body is BlockFunctionBody) {
1330 if (body.block.statements.length == 1) { 1340 if (body.block.statements.length == 1) {
1331 var stat = body.block.statements.single; 1341 var stat = body.block.statements.single;
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
1744 var genericName = _emitTopLevelName(element, suffix: '\$'); 1754 var genericName = _emitTopLevelName(element, suffix: '\$');
1745 return js.call('#(#)', [genericName, jsArgs]); 1755 return js.call('#(#)', [genericName, jsArgs]);
1746 } 1756 }
1747 } 1757 }
1748 1758
1749 return _emitTopLevelName(element); 1759 return _emitTopLevelName(element);
1750 } 1760 }
1751 1761
1752 JS.Expression _emitTopLevelName(Element e, {String suffix: ''}) { 1762 JS.Expression _emitTopLevelName(Element e, {String suffix: ''}) {
1753 var libName = _libraryName(e.library); 1763 var libName = _libraryName(e.library);
1754 var nameExpr = _propertyName((_getJSExportName(e) ?? e.name) + suffix);
1755 1764
1756 // Always qualify: 1765 // Always qualify:
1757 // * mutable top-level fields 1766 // * mutable top-level fields
1758 // * elements from other libraries 1767 // * elements from other libraries
1759 bool mutableTopLevel = e is TopLevelVariableElement && 1768 bool mutableTopLevel = e is TopLevelVariableElement &&
1760 !e.isConst && 1769 !e.isConst &&
1761 !_isFinalJSDecl(e.computeNode()); 1770 !_isFinalJSDecl(e.computeNode());
1762 bool fromAnotherLibrary = e.library != currentLibrary; 1771 bool fromAnotherLibrary = e.library != currentLibrary;
1772 var nameExpr;
1773 if (fromAnotherLibrary) {
1774 nameExpr = _propertyName((_getJSExportName(e) ?? e.name) + suffix);
1775 } else {
1776 nameExpr = _propertyName(e.name + suffix);
1777 }
1763 if (mutableTopLevel || fromAnotherLibrary) { 1778 if (mutableTopLevel || fromAnotherLibrary) {
1764 return new JS.PropertyAccess(libName, nameExpr); 1779 return new JS.PropertyAccess(libName, nameExpr);
1765 } 1780 }
1766 1781
1767 var id = new JS.MaybeQualifiedId(libName, nameExpr); 1782 var id = new JS.MaybeQualifiedId(libName, nameExpr);
1768 _qualifiedIds.add(new Tuple2(e, id)); 1783 _qualifiedIds.add(new Tuple2(e, id));
1769 return id; 1784 return id;
1770 } 1785 }
1771 1786
1772 @override 1787 @override
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
2130 return new JS.Yield(_visit(node.expression)); 2145 return new JS.Yield(_visit(node.expression));
2131 } 2146 }
2132 2147
2133 @override 2148 @override
2134 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { 2149 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
2135 for (var v in node.variables.variables) { 2150 for (var v in node.variables.variables) {
2136 _loader.loadDeclaration(v, v.element); 2151 _loader.loadDeclaration(v, v.element);
2137 } 2152 }
2138 } 2153 }
2139 2154
2140 _addExport(String name) { 2155 /// Emits static fields.
2141 if (!_exports.add(name)) throw 'Duplicate top level name found: $name'; 2156 ///
2157 /// Instance fields are emitted in [_initializeFields].
2158 ///
2159 /// These are generally treated the same as top-level fields, see
2160 /// [visitTopLevelVariableDeclaration].
2161 @override
2162 visitFieldDeclaration(FieldDeclaration node) {
2163 if (!node.isStatic) return;
2164
2165 for (var f in node.fields.variables) {
2166 _loader.loadDeclaration(f, f.element);
2167 }
2168 }
2169
2170 _addExport(String name, [String exportName]) {
2171 if (_exports.containsKey(name)) {
2172 throw 'Duplicate top level name found: $name';
2173 }
2174 _exports[name] = exportName ?? name;
2142 } 2175 }
2143 2176
2144 @override 2177 @override
2145 JS.Statement visitVariableDeclarationStatement( 2178 JS.Statement visitVariableDeclarationStatement(
2146 VariableDeclarationStatement node) { 2179 VariableDeclarationStatement node) {
2147 // Special case a single variable with an initializer. 2180 // Special case a single variable with an initializer.
2148 // This helps emit cleaner code for things like: 2181 // This helps emit cleaner code for things like:
2149 // var result = []..add(1)..add(2); 2182 // var result = []..add(1)..add(2);
2150 if (node.variables.variables.length == 1) { 2183 if (node.variables.variables.length == 1) {
2151 var v = node.variables.variables.single; 2184 var v = node.variables.variables.single;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2240 // later on when we emit lazy fields. That seems busted. 2273 // later on when we emit lazy fields. That seems busted.
2241 jsInit = _visitInitializer(field); 2274 jsInit = _visitInitializer(field);
2242 eagerInit = false; 2275 eagerInit = false;
2243 } 2276 }
2244 2277
2245 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile 2278 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile
2246 // runtime helpers. 2279 // runtime helpers.
2247 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field); 2280 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field);
2248 if (isJSTopLevel) eagerInit = true; 2281 if (isJSTopLevel) eagerInit = true;
2249 2282
2250 var fieldName = _getJSExportName(element) ?? field.name.name; 2283 var fieldName = field.name.name;
2251 if (field.isConst && eagerInit || isJSTopLevel) { 2284 var exportName = fieldName;
2285 if (element is TopLevelVariableElement) {
2286 exportName = _getJSExportName(element) ?? fieldName;
2287 }
2288 if ((field.isConst && eagerInit && element is TopLevelVariableElement) ||
2289 isJSTopLevel) {
2252 // constant fields don't change, so we can generate them as `let` 2290 // constant fields don't change, so we can generate them as `let`
2253 // but add them to the module's exports. However, make sure we generate 2291 // but add them to the module's exports. However, make sure we generate
2254 // anything they depend on first. 2292 // anything they depend on first.
2255 if (isPublic(fieldName)) _addExport(fieldName); 2293
2294 if (isPublic(fieldName)) _addExport(fieldName, exportName);
2256 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; 2295 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let';
2257 return annotateVariable( 2296 return annotateVariable(
2258 js.statement( 2297 js.statement(
2259 '$declKeyword # = #;', [new JS.Identifier(fieldName), jsInit]), 2298 '$declKeyword # = #;', [new JS.Identifier(fieldName), jsInit]),
2260 field.element); 2299 field.element);
2261 } 2300 }
2262 2301
2263 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) { 2302 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) {
2264 return annotateVariable( 2303 return annotateVariable(
2265 js.statement('# = #;', [_visit(field.name), jsInit]), field.element); 2304 js.statement('# = #;', [_visit(field.name), jsInit]), field.element);
(...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after
3549 3588
3550 /// A special kind of element created by the compiler, signifying a temporary 3589 /// A special kind of element created by the compiler, signifying a temporary
3551 /// variable. These objects use instance equality, and should be shared 3590 /// variable. These objects use instance equality, and should be shared
3552 /// everywhere in the tree where they are treated as the same variable. 3591 /// everywhere in the tree where they are treated as the same variable.
3553 class TemporaryVariableElement extends LocalVariableElementImpl { 3592 class TemporaryVariableElement extends LocalVariableElementImpl {
3554 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3593 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3555 3594
3556 int get hashCode => identityHashCode(this); 3595 int get hashCode => identityHashCode(this);
3557 bool operator ==(Object other) => identical(this, other); 3596 bool operator ==(Object other) => identical(this, other);
3558 } 3597 }
OLDNEW
« no previous file with comments | « lib/runtime/dart/html.js ('k') | lib/src/codegen/module_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698