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

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

Issue 1530563003: Generate all runtime files from dart. (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years 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/typed_data.js ('k') | lib/src/codegen/js_interop.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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 final _privateNames = new HashMap<String, JS.TemporaryId>(); 87 final _privateNames = new HashMap<String, JS.TemporaryId>();
88 final _moduleItems = <JS.Statement>[]; 88 final _moduleItems = <JS.Statement>[];
89 final _temps = new HashMap<Element, JS.TemporaryId>(); 89 final _temps = new HashMap<Element, JS.TemporaryId>();
90 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>(); 90 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>();
91 91
92 /// The name for the library's exports inside itself. 92 /// The name for the library's exports inside itself.
93 /// `exports` was chosen as the most similar to ES module patterns. 93 /// `exports` was chosen as the most similar to ES module patterns.
94 final _dartxVar = new JS.Identifier('dartx'); 94 final _dartxVar = new JS.Identifier('dartx');
95 final _exportsVar = new JS.TemporaryId('exports'); 95 final _exportsVar = new JS.TemporaryId('exports');
96 final _runtimeLibVar = new JS.Identifier('dart'); 96 final _runtimeLibVar = new JS.Identifier('dart');
97 final _utilsLibVar = new JS.TemporaryId('utils');
98 final _classesLibVar = new JS.TemporaryId('classes');
99 final _rttiLibVar = new JS.TemporaryId('rtti');
97 final _namedArgTemp = new JS.TemporaryId('opts'); 100 final _namedArgTemp = new JS.TemporaryId('opts');
98 101
99 final TypeProvider _types; 102 final TypeProvider _types;
100 103
101 ConstFieldVisitor _constField; 104 ConstFieldVisitor _constField;
102 105
103 ModuleItemLoadOrder _loader; 106 ModuleItemLoadOrder _loader;
104 107
105 /// _interceptors.JSArray<E>, used for List literals. 108 /// _interceptors.JSArray<E>, used for List literals.
106 ClassElement _jsArray; 109 ClassElement _jsArray;
107 110
108 /// The default value of the module object. See [visitLibraryDirective]. 111 /// The default value of the module object. See [visitLibraryDirective].
109 String _jsModuleValue; 112 String _jsModuleValue;
110 113
111 bool _isDartUtils; 114 bool _isDartRuntime;
112 115
113 Map<String, DartType> _objectMembers; 116 Map<String, DartType> _objectMembers;
114 117
115 JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary, 118 JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary,
116 this._extensionTypes, this._fieldsNeedingStorage) 119 this._extensionTypes, this._fieldsNeedingStorage)
117 : compiler = compiler, 120 : compiler = compiler,
118 options = compiler.options.codegenOptions, 121 options = compiler.options.codegenOptions,
119 _types = compiler.context.typeProvider { 122 _types = compiler.context.typeProvider {
120 _loader = new ModuleItemLoadOrder(_emitModuleItem); 123 _loader = new ModuleItemLoadOrder(_emitModuleItem);
121 124
122 var context = compiler.context; 125 var context = compiler.context;
123 var src = context.sourceFactory.forUri('dart:_interceptors'); 126 var src = context.sourceFactory.forUri('dart:_interceptors');
124 var interceptors = context.computeLibraryElement(src); 127 var interceptors = context.computeLibraryElement(src);
125 _jsArray = interceptors.getType('JSArray'); 128 _jsArray = interceptors.getType('JSArray');
126 _isDartUtils = currentLibrary.source.uri.toString() == 'dart:_utils'; 129
130 _isDartRuntime = _runtimeLibUris.contains(_getLibUri(currentLibrary));
127 131
128 _objectMembers = getObjectMemberMap(types); 132 _objectMembers = getObjectMemberMap(types);
129 } 133 }
134 String _getLibUri(LibraryElement lib) => lib.source.uri.toString();
135
136 static final _runtimeLibUris = new Set<String>.from([
137 'dart:_utils',
138 'dart:_runtime',
139 'dart:_operations',
140 'dart:_errors',
141 'dart:_classes',
142 'dart:_generators',
143 'dart:_operations',
144 'dart:_types',
145 'dart:_rtti'
146 ]);
130 147
131 TypeProvider get types => rules.provider; 148 TypeProvider get types => rules.provider;
132 149
133 JS.Program emitLibrary(LibraryUnit library) { 150 JS.Program emitLibrary(LibraryUnit library) {
134 // Modify the AST to make coercions explicit. 151 // Modify the AST to make coercions explicit.
135 new CoercionReifier(library, rules).reify(); 152 new CoercionReifier(library, rules).reify();
136 153
137 // Build the public namespace for this library. This allows us to do 154 // Build the public namespace for this library. This allows us to do
138 // constant time lookups (contrast with `Element.getChild(name)`). 155 // constant time lookups (contrast with `Element.getChild(name)`).
139 if (currentLibrary.publicNamespace == null) { 156 if (currentLibrary.publicNamespace == null) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 // TODO(jmesserly): make these immutable in JS? 206 // TODO(jmesserly): make these immutable in JS?
190 for (var name in _exports) { 207 for (var name in _exports) {
191 _moduleItems.add(js.statement('#.# = #;', [_exportsVar, name, name])); 208 _moduleItems.add(js.statement('#.# = #;', [_exportsVar, name, name]));
192 } 209 }
193 210
194 var jsPath = compiler.getModuleName(currentLibrary.source.uri); 211 var jsPath = compiler.getModuleName(currentLibrary.source.uri);
195 212
196 // TODO(jmesserly): it would be great to run the renamer on the body, 213 // TODO(jmesserly): it would be great to run the renamer on the body,
197 // then figure out if we really need each of these parameters. 214 // then figure out if we really need each of these parameters.
198 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34 215 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34
199 var params = [_exportsVar, _runtimeLibVar]; 216 var params = [_exportsVar];
200 var processImport = 217 var lazyParams = [];
201 (LibraryElement library, JS.TemporaryId temp, List list) {
202 params.add(temp);
203 list.add(js.string(compiler.getModuleName(library.source.uri), "'"));
204 };
205 218
206 var needsDartRuntime = !_isDartUtils; 219 var libUri = _getLibUri(currentLibrary);
207 220
208 var imports = <JS.Expression>[]; 221 var imports = <JS.Expression>[];
222 var lazyImports = <JS.Expression>[];
209 var moduleStatements = <JS.Statement>[]; 223 var moduleStatements = <JS.Statement>[];
210 if (needsDartRuntime) { 224
211 imports.add(js.string('dart/_runtime')); 225 addImport(String name, JS.Expression libVar, {bool eager: true}) {
226 (eager ? imports : lazyImports).add(js.string(name, "'"));
227 (eager ? params : lazyParams).add(libVar);
228 }
229
230 if (!_isDartRuntime) {
231 addImport('dart/_runtime', _runtimeLibVar);
212 232
213 var dartxImport = 233 var dartxImport =
214 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); 234 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]);
215 moduleStatements.add(dartxImport); 235 moduleStatements.add(dartxImport);
236 } else {
237 if (libUri == 'dart:_generators') {
238 addImport('dart/_classes', _classesLibVar);
239 }
216 } 240 }
217 moduleStatements.addAll(_moduleItems); 241 moduleStatements.addAll(_moduleItems);
218 242
219 _imports.forEach((library, temp) { 243 bool shouldImportEagerly(lib) {
220 if (_loader.libraryIsLoaded(library)) { 244 var otherLibUri = _getLibUri(lib);
221 processImport(library, temp, imports); 245 if (otherLibUri == 'dart:_utils') return true;
222 } 246 if (libUri == 'dart:_types' && otherLibUri == 'dart:_rtti') return true;
247 if (libUri == 'dart:_runtime') return otherLibUri != 'dart:_js_helper';
248 return !_isDartRuntime && _loader.libraryIsLoaded(lib);
249 }
250
251 var importsEagerness = new Map<LibraryElement, bool>.fromIterable(
252 _imports.keys, value: shouldImportEagerly);
253
254 _imports.forEach((LibraryElement lib, JS.TemporaryId temp) {
255 bool eager = importsEagerness[lib];
256 addImport(compiler.getModuleName(lib.source.uri), temp, eager: eager);
223 }); 257 });
224 258
225 var lazyImports = <JS.Expression>[]; 259 params.addAll(lazyParams);
226 _imports.forEach((library, temp) {
227 if (!_loader.libraryIsLoaded(library)) {
228 processImport(library, temp, lazyImports);
229 }
230 });
231 260
232 var module = 261 var module =
233 js.call("function(#) { 'use strict'; #; }", [params, moduleStatements]); 262 js.call("function(#) { 'use strict'; #; }", [params, moduleStatements]);
234 263
235 var moduleDef = js.statement("dart_library.library(#, #, #, #, #)", [ 264 var moduleDef = js.statement("dart_library.library(#, #, #, #, #)", [
236 js.string(jsPath, "'"), 265 js.string(jsPath, "'"),
237 _jsModuleValue ?? new JS.LiteralNull(), 266 _jsModuleValue ?? new JS.LiteralNull(),
238 js.commentExpression( 267 js.commentExpression(
239 "Imports", new JS.ArrayInitializer(imports, multiline: true)), 268 "Imports", new JS.ArrayInitializer(imports, multiline: true)),
240 js.commentExpression("Lazy imports", 269 js.commentExpression("Lazy imports",
(...skipping 16 matching lines...) Expand all
257 if (node is! FunctionDeclaration) _flushLibraryProperties(_moduleItems); 286 if (node is! FunctionDeclaration) _flushLibraryProperties(_moduleItems);
258 287
259 var code = _visit(node); 288 var code = _visit(node);
260 if (code != null) _moduleItems.add(code); 289 if (code != null) _moduleItems.add(code);
261 } 290 }
262 291
263 @override 292 @override
264 void visitLibraryDirective(LibraryDirective node) { 293 void visitLibraryDirective(LibraryDirective node) {
265 assert(_jsModuleValue == null); 294 assert(_jsModuleValue == null);
266 295
267 var jsName = findAnnotation(node.element, isJSAnnotation); 296 _jsModuleValue = _getJsName(node.element);
268 _jsModuleValue = 297 }
269 getConstantField(jsName, 'name', types.stringType)?.toStringValue(); 298
299 String _getJsName(Element e) {
300 var jsName = findAnnotation(e, isJSAnnotation);
301 return getConstantField(jsName, 'name', types.stringType)?.toStringValue();
270 } 302 }
271 303
272 @override 304 @override
273 void visitImportDirective(ImportDirective node) { 305 void visitImportDirective(ImportDirective node) {
274 // Nothing to do yet, but we'll want to convert this to an ES6 import once 306 // Nothing to do yet, but we'll want to convert this to an ES6 import once
275 // we have support for modules. 307 // we have support for modules.
276 } 308 }
277 309
278 @override void visitPartDirective(PartDirective node) {} 310 @override void visitPartDirective(PartDirective node) {}
279 @override void visitPartOfDirective(PartOfDirective node) {} 311 @override void visitPartOfDirective(PartOfDirective node) {}
280 312
281 @override 313 @override
282 void visitExportDirective(ExportDirective node) { 314 void visitExportDirective(ExportDirective node) {
283 var exportName = _libraryName(node.uriElement); 315 var exportName = _libraryName(node.uriElement);
284 316
285 var currentLibNames = currentLibrary.publicNamespace.definedNames; 317 var currentLibNames = currentLibrary.publicNamespace.definedNames;
286 318
287 var args = [_exportsVar, exportName]; 319 var args = [_exportsVar, exportName];
288 if (node.combinators.isNotEmpty) { 320 if (node.combinators.isNotEmpty) {
289 var shownNames = <JS.Expression>[]; 321 var shownNames = <JS.Expression>[];
290 var hiddenNames = <JS.Expression>[]; 322 var hiddenNames = <JS.Expression>[];
291 323
292 var show = node.combinators.firstWhere((c) => c is ShowCombinator, 324 var show = node.combinators.firstWhere((c) => c is ShowCombinator,
293 orElse: () => null) as ShowCombinator; 325 orElse: () => null) as ShowCombinator;
294 var hide = node.combinators.firstWhere((c) => c is HideCombinator, 326 var hide = node.combinators.firstWhere((c) => c is HideCombinator,
295 orElse: () => null) as HideCombinator; 327 orElse: () => null) as HideCombinator;
296 if (show != null) { 328 if (show != null) {
329 var singleName = _getJsName(node.element);
330 if (singleName != null && show.shownNames.length != 1) {
331 throw new StateError('Cannot set js name on more than one name');
332 }
297 shownNames.addAll(show.shownNames 333 shownNames.addAll(show.shownNames
298 .map((i) => i.name) 334 .map((i) => singleName ?? i.name)
299 .where((s) => !currentLibNames.containsKey(s)) 335 .where((s) => !currentLibNames.containsKey(s))
300 .map((s) => js.string(s, "'"))); 336 .map((s) => js.string(s, "'")));
301 } 337 }
302 if (hide != null) { 338 if (hide != null) {
303 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); 339 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'")));
304 } 340 }
305 args.add(new JS.ArrayInitializer(shownNames)); 341 args.add(new JS.ArrayInitializer(shownNames));
306 args.add(new JS.ArrayInitializer(hiddenNames)); 342 args.add(new JS.ArrayInitializer(hiddenNames));
307 } 343 }
308 _moduleItems.add(js.statement('dart.export_(#);', [args])); 344
345 // When we compile _runtime.js, we need to source export_ from _utils.js:
346 _moduleItems.add(js.statement('#.export(#);',
347 [_isDartRuntime ? _utilsLibVar : _runtimeLibVar, args]));
309 } 348 }
310 349
311 JS.Identifier _initSymbol(JS.Identifier id) { 350 JS.Identifier _initSymbol(JS.Identifier id) {
312 var s = 351 var s =
313 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); 352 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]);
314 _moduleItems.add(s); 353 _moduleItems.add(s);
315 return id; 354 return id;
316 } 355 }
317 356
318 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, 357 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core,
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); 611 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]);
573 } 612 }
574 return body; 613 return body;
575 } 614 }
576 615
577 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { 616 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) {
578 var name = type.name; 617 var name = type.name;
579 var genericName = '$name\$'; 618 var genericName = '$name\$';
580 var typeParams = type.typeParameters.map((p) => p.name); 619 var typeParams = type.typeParameters.map((p) => p.name);
581 if (isPublic(name)) _exports.add(genericName); 620 if (isPublic(name)) _exports.add(genericName);
582 return js.statement('const # = dart.generic(function(#) { #; return #; });', 621
583 [genericName, typeParams, body, name]); 622 return js.statement('const # = #(function(#) { #; return #; });',
623 [genericName, _dartGeneric, typeParams, body, name]);
584 } 624 }
585 625
626 get _dartGeneric =>
627 js.call('#.generic', [_isDartRuntime ? _classesLibVar : _runtimeLibVar]);
628
586 final _hasDeferredSupertype = new HashSet<ClassElement>(); 629 final _hasDeferredSupertype = new HashSet<ClassElement>();
587 630
588 bool _deferIfNeeded(DartType type, ClassElement current) { 631 bool _deferIfNeeded(DartType type, ClassElement current) {
589 if (type is ParameterizedType) { 632 if (type is ParameterizedType) {
590 var typeArguments = type.typeArguments; 633 var typeArguments = type.typeArguments;
591 for (var typeArg in typeArguments) { 634 for (var typeArg in typeArguments) {
592 var typeElement = typeArg.element; 635 var typeElement = typeArg.element;
593 // FIXME(vsm): This does not track mutual recursive dependences. 636 // FIXME(vsm): This does not track mutual recursive dependences.
594 if (current == typeElement || _deferIfNeeded(typeArg, current)) { 637 if (current == typeElement || _deferIfNeeded(typeArg, current)) {
595 return true; 638 return true;
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
825 if (!tStatics.isEmpty) { 868 if (!tStatics.isEmpty) {
826 assert(!sNames.isEmpty); 869 assert(!sNames.isEmpty);
827 var aNames = new JS.Property( 870 var aNames = new JS.Property(
828 _propertyName('names'), new JS.ArrayInitializer(sNames)); 871 _propertyName('names'), new JS.ArrayInitializer(sNames));
829 sigFields.add(build('statics', tStatics)); 872 sigFields.add(build('statics', tStatics));
830 sigFields.add(aNames); 873 sigFields.add(aNames);
831 } 874 }
832 if (!sigFields.isEmpty || extensions.isNotEmpty) { 875 if (!sigFields.isEmpty || extensions.isNotEmpty) {
833 var sig = new JS.ObjectInitializer(sigFields); 876 var sig = new JS.ObjectInitializer(sigFields);
834 var classExpr = new JS.Identifier(name); 877 var classExpr = new JS.Identifier(name);
835 body.add(js.statement('dart.setSignature(#, #);', [classExpr, sig])); 878 body.add(js.statement('#(#, #);', [_dartSetSignature, classExpr, sig]));
836 } 879 }
837 } 880 }
838 881
839 // If a concrete class implements one of our extensions, we might need to 882 // If a concrete class implements one of our extensions, we might need to
840 // add forwarders. 883 // add forwarders.
841 if (extensions.isNotEmpty) { 884 if (extensions.isNotEmpty) {
842 var methodNames = <JS.Expression>[]; 885 var methodNames = <JS.Expression>[];
843 for (var e in extensions) { 886 for (var e in extensions) {
844 methodNames.add(_elementMemberName(e)); 887 methodNames.add(_elementMemberName(e));
845 } 888 }
846 body.add(js.statement('dart.defineExtensionMembers(#, #);', [ 889 body.add(js.statement('dart.defineExtensionMembers(#, #);', [
847 name, 890 name,
848 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) 891 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4)
849 ])); 892 ]));
850 } 893 }
851 894
852 // TODO(vsm): Make this optional per #268. 895 // TODO(vsm): Make this optional per #268.
853 // Metadata 896 // Metadata
854 if (metadata.isNotEmpty) { 897 if (metadata.isNotEmpty) {
855 body.add(js.statement('#[dart.metadata] = () => #;', [ 898 body.add(js.statement('#[dart.metadata] = () => #;', [
856 name, 899 name,
857 new JS.ArrayInitializer( 900 new JS.ArrayInitializer(
858 new List<JS.Expression>.from(metadata.map(_instantiateAnnotation))) 901 new List<JS.Expression>.from(metadata.map(_instantiateAnnotation)))
859 ])); 902 ]));
860 } 903 }
861 904
862 return _statement(body); 905 return _statement(body);
863 } 906 }
864 907
908 get _dartSetSignature =>
909 js.call('#.setSignature', [_isDartRuntime ? _classesLibVar : _runtimeLibVa r]);
910
865 List<ExecutableElement> _extensionsToImplement(ClassElement element) { 911 List<ExecutableElement> _extensionsToImplement(ClassElement element) {
866 var members = <ExecutableElement>[]; 912 var members = <ExecutableElement>[];
867 if (_extensionTypes.contains(element)) return members; 913 if (_extensionTypes.contains(element)) return members;
868 914
869 // Collect all extension types we implement. 915 // Collect all extension types we implement.
870 var type = element.type; 916 var type = element.type;
871 var types = new Set<ClassElement>(); 917 var types = new Set<ClassElement>();
872 _collectExtensions(type, types); 918 _collectExtensions(type, types);
873 if (types.isEmpty) return members; 919 if (types.isEmpty) return members;
874 920
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 1341
1296 if (node.isGetter || node.isSetter) { 1342 if (node.isGetter || node.isSetter) {
1297 // Add these later so we can use getter/setter syntax. 1343 // Add these later so we can use getter/setter syntax.
1298 _properties.add(node); 1344 _properties.add(node);
1299 return null; 1345 return null;
1300 } 1346 }
1301 1347
1302 var body = <JS.Statement>[]; 1348 var body = <JS.Statement>[];
1303 _flushLibraryProperties(body); 1349 _flushLibraryProperties(body);
1304 1350
1305 var name = node.name.name; 1351 var name = _getJsName(node.element) ?? node.name.name;
1306 1352
1307 var fn = _visit(node.functionExpression); 1353 var fn = _visit(node.functionExpression);
1308 bool needsTagging = true; 1354 bool needsTagging = !_isDartRuntime;
1309 1355
1310 if (currentLibrary.source.isInSystemLibrary && 1356 if (currentLibrary.source.isInSystemLibrary &&
1311 _isInlineJSFunction(node.functionExpression)) { 1357 _isInlineJSFunction(node.functionExpression)) {
1312 fn = _simplifyPassThroughArrowFunCallBody(fn); 1358 fn = _simplifyPassThroughArrowFunCallBody(fn);
1313 needsTagging = !_isDartUtils;
1314 } 1359 }
1315 1360
1316 var id = new JS.Identifier(name); 1361 var id = new JS.Identifier(name);
1317 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element)); 1362 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element));
1318 if (needsTagging) { 1363 if (needsTagging) {
1319 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) 1364 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true)
1320 .toStatement()); 1365 .toStatement());
1321 } 1366 }
1322 1367
1323 if (isPublic(name)) _addExport(name); 1368 if (isPublic(name)) _addExport(name);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1399 JS.Expression _emitFunctionTagged(JS.Expression clos, DartType type, 1444 JS.Expression _emitFunctionTagged(JS.Expression clos, DartType type,
1400 {topLevel: false}) { 1445 {topLevel: false}) {
1401 var name = type.name; 1446 var name = type.name;
1402 var lazy = topLevel && !_typeIsLoaded(type); 1447 var lazy = topLevel && !_typeIsLoaded(type);
1403 1448
1404 if (type is FunctionType && (name == '' || name == null)) { 1449 if (type is FunctionType && (name == '' || name == null)) {
1405 if (type.returnType.isDynamic && 1450 if (type.returnType.isDynamic &&
1406 type.optionalParameterTypes.isEmpty && 1451 type.optionalParameterTypes.isEmpty &&
1407 type.namedParameterTypes.isEmpty && 1452 type.namedParameterTypes.isEmpty &&
1408 type.normalParameterTypes.every((t) => t.isDynamic)) { 1453 type.normalParameterTypes.every((t) => t.isDynamic)) {
1409 return js.call('dart.fn(#)', [clos]); 1454 return js.call('#(#)', [_dartFn, clos]);
1410 } 1455 }
1411 if (lazy) { 1456 if (lazy) {
1412 return js.call('dart.fn(#, () => #)', [clos, _emitFunctionRTTI(type)]); 1457 return js.call('#(#, () => #)', [_dartFn, clos, _emitFunctionRTTI(type)] );
1413 } 1458 }
1414 return js.call('dart.fn(#, #)', [clos, _emitFunctionTypeParts(type)]); 1459 return js.call('#(#, #)', [_dartFn, clos, _emitFunctionTypeParts(type)]);
1415 } 1460 }
1416 throw 'Function has non function type: $type'; 1461 throw 'Function has non function type: $type';
1417 } 1462 }
1418 1463
1464 get _dartFn => js.call('#.fn', _isDartRuntime ? _rttiLibVar : _runtimeLibVar);
1465
1419 @override 1466 @override
1420 JS.Expression visitFunctionExpression(FunctionExpression node) { 1467 JS.Expression visitFunctionExpression(FunctionExpression node) {
1421 var params = _visit(node.parameters) as List<JS.Parameter>; 1468 var params = _visit(node.parameters) as List<JS.Parameter>;
1422 if (params == null) params = <JS.Parameter>[]; 1469 if (params == null) params = <JS.Parameter>[];
1423 1470
1424 var parent = node.parent; 1471 var parent = node.parent;
1425 var inStmt = parent.parent is FunctionDeclarationStatement; 1472 var inStmt = parent.parent is FunctionDeclarationStatement;
1426 if (parent is FunctionDeclaration) { 1473 if (parent is FunctionDeclaration) {
1427 return _emitFunctionBody(params, node.body); 1474 return _emitFunctionBody(params, node.body);
1428 } else { 1475 } else {
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1559 'Unimplemented unknown name', new JS.Identifier(node.name)); 1606 'Unimplemented unknown name', new JS.Identifier(node.name));
1560 } 1607 }
1561 1608
1562 // Get the original declaring element. If we had a property accessor, this 1609 // Get the original declaring element. If we had a property accessor, this
1563 // indirects back to a (possibly synthetic) field. 1610 // indirects back to a (possibly synthetic) field.
1564 var element = accessor; 1611 var element = accessor;
1565 if (accessor is PropertyAccessorElement) element = accessor.variable; 1612 if (accessor is PropertyAccessorElement) element = accessor.variable;
1566 1613
1567 _loader.declareBeforeUse(element); 1614 _loader.declareBeforeUse(element);
1568 1615
1569 var name = element.name; 1616 var name = _getJsName(element) ?? element.name;
1570 1617
1571 // type literal 1618 // type literal
1572 if (element is ClassElement || 1619 if (element is ClassElement ||
1573 element is DynamicElementImpl || 1620 element is DynamicElementImpl ||
1574 element is FunctionTypeAliasElement) { 1621 element is FunctionTypeAliasElement) {
1575 return _emitTypeName( 1622 return _emitTypeName(
1576 fillDynamicTypeArgs((element as dynamic).type, types)); 1623 fillDynamicTypeArgs((element as dynamic).type, types));
1577 } 1624 }
1578 1625
1579 // library member 1626 // library member
1580 if (element.enclosingElement is CompilationUnitElement) { 1627 if (element.enclosingElement is CompilationUnitElement) {
1581 return _maybeQualifiedName(element); 1628 return _maybeQualifiedName(element, name);
1582 } 1629 }
1583 1630
1584 // Unqualified class member. This could mean implicit-this, or implicit 1631 // Unqualified class member. This could mean implicit-this, or implicit
1585 // call to a static from the same class. 1632 // call to a static from the same class.
1586 if (element is ClassMemberElement && element is! ConstructorElement) { 1633 if (element is ClassMemberElement && element is! ConstructorElement) {
1587 bool isStatic = element.isStatic; 1634 bool isStatic = element.isStatic;
1588 var type = element.enclosingElement.type; 1635 var type = element.enclosingElement.type;
1589 var member = _emitMemberName(name, isStatic: isStatic, type: type); 1636 var member = _emitMemberName(name, isStatic: isStatic, type: type);
1590 1637
1591 // For static methods, we add the raw type name, without generics or 1638 // For static methods, we add the raw type name, without generics or
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1874 var stmts = _visitList(node.block.statements) as List<JS.Statement>; 1921 var stmts = _visitList(node.block.statements) as List<JS.Statement>;
1875 if (initArgs != null) stmts.insert(0, initArgs); 1922 if (initArgs != null) stmts.insert(0, initArgs);
1876 return new JS.Block(stmts); 1923 return new JS.Block(stmts);
1877 } 1924 }
1878 1925
1879 @override 1926 @override
1880 JS.Block visitBlock(Block node) => 1927 JS.Block visitBlock(Block node) =>
1881 new JS.Block(_visitList(node.statements) as List<JS.Statement>, 1928 new JS.Block(_visitList(node.statements) as List<JS.Statement>,
1882 isScope: true); 1929 isScope: true);
1883 1930
1931 /// Return the type constructor `_foolib.Bar$` given `Bar` from lib `_foolib`.
1932 JS.Expression _emitGenericTypeConstructor(Expression typeExpression) {
1933 var ref = _visit(typeExpression);
1934 if (ref is JS.PropertyAccess) {
1935 var name = (ref.selector as JS.LiteralString).valueWithoutQuotes;
1936 return new JS.PropertyAccess(
1937 ref.receiver, new JS.LiteralString("'$name\$'"));
1938 } else if (ref is JS.MaybeQualifiedId) {
1939 var name = (ref.name as JS.Identifier).name;
1940 return new JS.PropertyAccess(
1941 ref.qualifier, new JS.Identifier('$name\$'));
1942 } else {
1943 throw new ArgumentError('Invalid type ref: $ref (${ref?.runtimeType})');
1944 }
1945 }
1946
1884 @override 1947 @override
1885 visitMethodInvocation(MethodInvocation node) { 1948 visitMethodInvocation(MethodInvocation node) {
1886 if (node.operator != null && node.operator.lexeme == '?.') { 1949 if (node.operator != null && node.operator.lexeme == '?.') {
1887 return _emitNullSafe(node); 1950 return _emitNullSafe(node);
1888 } 1951 }
1952 if (isGenericTypeConstructorInvocation(node)) {
1953 return _emitGenericTypeConstructor(node.argumentList.arguments.single);
1954 }
1889 1955
1890 var target = _getTarget(node); 1956 var target = _getTarget(node);
1891 var result = _emitForeignJS(node); 1957 var result = _emitForeignJS(node);
1892 if (result != null) return result; 1958 if (result != null) return result;
1893 1959
1894 String code; 1960 String code;
1895 if (target == null || isLibraryPrefix(target)) { 1961 if (target == null || isLibraryPrefix(target)) {
1896 if (DynamicInvoke.get(node.methodName)) { 1962 if (DynamicInvoke.get(node.methodName)) {
1897 code = 'dart.$DCALL(#, #)'; 1963 code = 'dart.$DCALL(#, #)';
1898 } else { 1964 } else {
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
2204 } else { 2270 } else {
2205 jsInit = _visitInitializer(field); 2271 jsInit = _visitInitializer(field);
2206 eagerInit = false; 2272 eagerInit = false;
2207 } 2273 }
2208 2274
2209 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile 2275 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile
2210 // runtime helpers. 2276 // runtime helpers.
2211 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field); 2277 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field);
2212 if (isJSTopLevel) eagerInit = true; 2278 if (isJSTopLevel) eagerInit = true;
2213 2279
2214 var fieldName = field.name.name; 2280 var fieldName = _getJsName(element) ?? field.name.name;
2281
2215 if ((field.isConst && eagerInit && element is TopLevelVariableElement) || 2282 if ((field.isConst && eagerInit && element is TopLevelVariableElement) ||
2216 isJSTopLevel) { 2283 isJSTopLevel) {
2217 // constant fields don't change, so we can generate them as `let` 2284 // constant fields don't change, so we can generate them as `let`
2218 // but add them to the module's exports. However, make sure we generate 2285 // but add them to the module's exports. However, make sure we generate
2219 // anything they depend on first. 2286 // anything they depend on first.
2220 2287
2221 if (isPublic(fieldName)) _addExport(fieldName); 2288 if (isPublic(fieldName)) _addExport(fieldName);
2222 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; 2289 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let';
2223 return annotateVariable( 2290 return annotateVariable(
2224 js.statement( 2291 js.statement(
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after
2840 } 2907 }
2841 2908
2842 String code; 2909 String code;
2843 if (member != null && member is MethodElement && !isStatic) { 2910 if (member != null && member is MethodElement && !isStatic) {
2844 // Tear-off methods: explicitly bind it. 2911 // Tear-off methods: explicitly bind it.
2845 if (target is SuperExpression) { 2912 if (target is SuperExpression) {
2846 return js.call('dart.bind(this, #, #.#)', [name, _visit(target), name]); 2913 return js.call('dart.bind(this, #, #.#)', [name, _visit(target), name]);
2847 } else if (_requiresStaticDispatch(target, memberId.name)) { 2914 } else if (_requiresStaticDispatch(target, memberId.name)) {
2848 var type = member.type; 2915 var type = member.type;
2849 var clos = js.call('dart.#.bind(#)', [name, _visit(target)]); 2916 var clos = js.call('dart.#.bind(#)', [name, _visit(target)]);
2850 return js.call('dart.fn(#, #)', [clos, _emitFunctionTypeParts(type)]); 2917 return js.call('#(#, #)', [_dartFn, clos, _emitFunctionTypeParts(type)]) ;
2851 } 2918 }
2852 code = 'dart.bind(#, #)'; 2919 code = 'dart.bind(#, #)';
2853 } else if (_requiresStaticDispatch(target, memberId.name)) { 2920 } else if (_requiresStaticDispatch(target, memberId.name)) {
2854 return js.call('dart.#(#)', [name, _visit(target)]); 2921 return js.call('dart.#(#)', [name, _visit(target)]);
2855 } else { 2922 } else {
2856 code = '#.#'; 2923 code = '#.#';
2857 } 2924 }
2858 2925
2859 return js.call(code, [_visit(target), name]); 2926 return js.call(code, [_visit(target), name]);
2860 } 2927 }
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after
3409 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; 3476 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody;
3410 3477
3411 FunctionBody _functionBody(node) => 3478 FunctionBody _functionBody(node) =>
3412 node is FunctionDeclaration ? node.functionExpression.body : node.body; 3479 node is FunctionDeclaration ? node.functionExpression.body : node.body;
3413 3480
3414 /// Choose a canonical name from the library element. 3481 /// Choose a canonical name from the library element.
3415 /// This never uses the library's name (the identifier in the `library` 3482 /// This never uses the library's name (the identifier in the `library`
3416 /// declaration) as it doesn't have any meaningful rules enforced. 3483 /// declaration) as it doesn't have any meaningful rules enforced.
3417 JS.Identifier _libraryName(LibraryElement library) { 3484 JS.Identifier _libraryName(LibraryElement library) {
3418 if (library == currentLibrary) return _exportsVar; 3485 if (library == currentLibrary) return _exportsVar;
3419 return _imports.putIfAbsent( 3486 return _imports.putIfAbsent(library, () {
3420 library, () => new JS.TemporaryId(jsLibraryName(library))); 3487 var name = library.name;
3488 if (name == 'dart._utils') return _utilsLibVar;
3489 else if (name == 'dart._classes') return _classesLibVar;
3490 else if (name == 'dart._rtti') return _rttiLibVar;
3491 else return new JS.TemporaryId(jsLibraryName(library));
3492 });
3421 } 3493 }
3422 3494
3423 DartType getStaticType(Expression e) => rules.getStaticType(e); 3495 DartType getStaticType(Expression e) => rules.getStaticType(e);
3424 3496
3425 @override 3497 @override
3426 String getQualifiedName(TypeDefiningElement type) { 3498 String getQualifiedName(TypeDefiningElement type) {
3427 JS.TemporaryId id = _imports[type.library]; 3499 JS.TemporaryId id = _imports[type.library];
3428 return id == null ? type.name : '${id.name}.${type.name}'; 3500 return id == null ? type.name : '${id.name}.${type.name}';
3429 } 3501 }
3430 3502
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
3521 3593
3522 /// A special kind of element created by the compiler, signifying a temporary 3594 /// A special kind of element created by the compiler, signifying a temporary
3523 /// variable. These objects use instance equality, and should be shared 3595 /// variable. These objects use instance equality, and should be shared
3524 /// everywhere in the tree where they are treated as the same variable. 3596 /// everywhere in the tree where they are treated as the same variable.
3525 class TemporaryVariableElement extends LocalVariableElementImpl { 3597 class TemporaryVariableElement extends LocalVariableElementImpl {
3526 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3598 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3527 3599
3528 int get hashCode => identityHashCode(this); 3600 int get hashCode => identityHashCode(this);
3529 bool operator ==(Object other) => identical(this, other); 3601 bool operator ==(Object other) => identical(this, other);
3530 } 3602 }
OLDNEW
« no previous file with comments | « lib/runtime/dart/typed_data.js ('k') | lib/src/codegen/js_interop.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698