Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 21 matching lines...) Expand all Loading... | |
| 32 | 32 |
| 33 import 'code_generator.dart'; | 33 import 'code_generator.dart'; |
| 34 import 'js_field_storage.dart'; | 34 import 'js_field_storage.dart'; |
| 35 import 'js_interop.dart'; | 35 import 'js_interop.dart'; |
| 36 import 'js_names.dart' as JS; | 36 import 'js_names.dart' as JS; |
| 37 import 'js_metalet.dart' as JS; | 37 import 'js_metalet.dart' as JS; |
| 38 import 'js_module_item_order.dart'; | 38 import 'js_module_item_order.dart'; |
| 39 import 'js_names.dart'; | 39 import 'js_names.dart'; |
| 40 import 'js_printer.dart' show writeJsLibrary; | 40 import 'js_printer.dart' show writeJsLibrary; |
| 41 import 'side_effect_analysis.dart'; | 41 import 'side_effect_analysis.dart'; |
| 42 import 'package:collection/equality.dart'; | |
| 43 | 42 |
| 44 // Various dynamic helpers we call. | 43 // Various dynamic helpers we call. |
| 45 // If renaming these, make sure to check other places like the | 44 // If renaming these, make sure to check other places like the |
| 46 // _runtime.js file and comments. | 45 // _runtime.js file and comments. |
| 47 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can | 46 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can |
| 48 // import and generate calls to, rather than dart_runtime.js | 47 // import and generate calls to, rather than dart_runtime.js |
| 49 const DPUT = 'dput'; | 48 const DPUT = 'dput'; |
| 50 const DLOAD = 'dload'; | 49 const DLOAD = 'dload'; |
| 51 const DINDEX = 'dindex'; | 50 const DINDEX = 'dindex'; |
| 52 const DSETINDEX = 'dsetindex'; | 51 const DSETINDEX = 'dsetindex'; |
| 53 const DCALL = 'dcall'; | 52 const DCALL = 'dcall'; |
| 54 const DSEND = 'dsend'; | 53 const DSEND = 'dsend'; |
| 55 | 54 |
| 56 const ListEquality _listEquality = const ListEquality(); | |
| 57 | |
| 58 class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator { | 55 class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator { |
| 59 final AbstractCompiler compiler; | 56 final AbstractCompiler compiler; |
| 60 final CodegenOptions options; | 57 final CodegenOptions options; |
| 61 final LibraryElement currentLibrary; | 58 final LibraryElement currentLibrary; |
| 62 final StrongTypeSystemImpl rules; | 59 final StrongTypeSystemImpl rules; |
| 63 | 60 |
| 64 /// The global extension type table. | 61 /// The global extension type table. |
| 65 final HashSet<ClassElement> _extensionTypes; | 62 final HashSet<ClassElement> _extensionTypes; |
| 66 | 63 |
| 67 /// Information that is precomputed for this library, indicates which fields | 64 /// Information that is precomputed for this library, indicates which fields |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 102 ConstFieldVisitor _constField; | 99 ConstFieldVisitor _constField; |
| 103 | 100 |
| 104 ModuleItemLoadOrder _loader; | 101 ModuleItemLoadOrder _loader; |
| 105 | 102 |
| 106 /// _interceptors.JSArray<E>, used for List literals. | 103 /// _interceptors.JSArray<E>, used for List literals. |
| 107 ClassElement _jsArray; | 104 ClassElement _jsArray; |
| 108 | 105 |
| 109 /// The default value of the module object. See [visitLibraryDirective]. | 106 /// The default value of the module object. See [visitLibraryDirective]. |
| 110 String _jsModuleValue; | 107 String _jsModuleValue; |
| 111 | 108 |
| 112 bool _isDartUtils; | 109 bool _isDartRuntime; |
| 113 | 110 |
| 114 JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary, | 111 JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary, |
| 115 this._extensionTypes, this._fieldsNeedingStorage) | 112 this._extensionTypes, this._fieldsNeedingStorage) |
| 116 : compiler = compiler, | 113 : compiler = compiler, |
| 117 options = compiler.options.codegenOptions, | 114 options = compiler.options.codegenOptions, |
| 118 _types = compiler.context.typeProvider { | 115 _types = compiler.context.typeProvider { |
| 119 _loader = new ModuleItemLoadOrder(_emitModuleItem); | 116 _loader = new ModuleItemLoadOrder(_emitModuleItem); |
| 120 | 117 |
| 121 var context = compiler.context; | 118 var context = compiler.context; |
| 122 var src = context.sourceFactory.forUri('dart:_interceptors'); | 119 var src = context.sourceFactory.forUri('dart:_interceptors'); |
| 123 var interceptors = context.computeLibraryElement(src); | 120 var interceptors = context.computeLibraryElement(src); |
| 124 _jsArray = interceptors.getType('JSArray'); | 121 _jsArray = interceptors.getType('JSArray'); |
| 125 _isDartUtils = currentLibrary.source.uri.toString() == 'dart:_utils'; | 122 _isDartRuntime = currentLibrary.source.uri.toString() == 'dart:_runtime'; |
| 126 } | 123 } |
| 127 | 124 |
| 128 TypeProvider get types => _types; | 125 TypeProvider get types => _types; |
| 129 | 126 |
| 130 JS.Program emitLibrary(LibraryUnit library) { | 127 JS.Program emitLibrary(LibraryUnit library) { |
| 131 // Modify the AST to make coercions explicit. | 128 // Modify the AST to make coercions explicit. |
| 132 new CoercionReifier(library, rules).reify(); | 129 new CoercionReifier(library, rules).reify(); |
| 133 | 130 |
| 134 // Build the public namespace for this library. This allows us to do | 131 // Build the public namespace for this library. This allows us to do |
| 135 // constant time lookups (contrast with `Element.getChild(name)`). | 132 // constant time lookups (contrast with `Element.getChild(name)`). |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 // TODO(jmesserly): make these immutable in JS? | 183 // TODO(jmesserly): make these immutable in JS? |
| 187 for (var name in _exports) { | 184 for (var name in _exports) { |
| 188 _moduleItems.add(js.statement('#.# = #;', [_exportsVar, name, name])); | 185 _moduleItems.add(js.statement('#.# = #;', [_exportsVar, name, name])); |
| 189 } | 186 } |
| 190 | 187 |
| 191 var jsPath = compiler.getModuleName(currentLibrary.source.uri); | 188 var jsPath = compiler.getModuleName(currentLibrary.source.uri); |
| 192 | 189 |
| 193 // TODO(jmesserly): it would be great to run the renamer on the body, | 190 // TODO(jmesserly): it would be great to run the renamer on the body, |
| 194 // then figure out if we really need each of these parameters. | 191 // then figure out if we really need each of these parameters. |
| 195 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34 | 192 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34 |
| 196 var params = [_exportsVar, _runtimeLibVar]; | 193 var params = [_exportsVar]; |
| 197 var processImport = | 194 var lazyParams = []; |
| 198 (LibraryElement library, JS.TemporaryId temp, List list) { | |
| 199 params.add(temp); | |
| 200 list.add(js.string(compiler.getModuleName(library.source.uri), "'")); | |
| 201 }; | |
| 202 | |
| 203 var needsDartRuntime = !_isDartUtils; | |
| 204 | 195 |
| 205 var imports = <JS.Expression>[]; | 196 var imports = <JS.Expression>[]; |
| 197 var lazyImports = <JS.Expression>[]; | |
| 206 var moduleStatements = <JS.Statement>[]; | 198 var moduleStatements = <JS.Statement>[]; |
| 207 if (needsDartRuntime) { | 199 |
| 208 imports.add(js.string('dart/_runtime')); | 200 addImport(String name, JS.Expression libVar, {bool lazy: false}) { |
| 201 (lazy ? lazyImports : imports).add(js.string(name, "'")); | |
| 202 (lazy ? lazyParams : params).add(libVar); | |
| 203 } | |
| 204 | |
| 205 if (!_isDartRuntime) { | |
| 206 addImport('dart/_runtime', _runtimeLibVar); | |
| 209 | 207 |
| 210 var dartxImport = | 208 var dartxImport = |
| 211 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); | 209 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); |
| 212 moduleStatements.add(dartxImport); | 210 moduleStatements.add(dartxImport); |
| 213 } | 211 } |
| 212 _imports.forEach((LibraryElement lib, JS.TemporaryId temp) { | |
| 213 addImport(compiler.getModuleName(lib.source.uri), temp, | |
| 214 lazy: _isDartRuntime || !_loader.libraryIsLoaded(lib)); | |
| 215 }); | |
| 216 params.addAll(lazyParams); | |
| 217 | |
| 214 moduleStatements.addAll(_moduleItems); | 218 moduleStatements.addAll(_moduleItems); |
| 215 | 219 |
| 216 _imports.forEach((library, temp) { | |
| 217 if (_loader.libraryIsLoaded(library)) { | |
| 218 processImport(library, temp, imports); | |
| 219 } | |
| 220 }); | |
| 221 | |
| 222 var lazyImports = <JS.Expression>[]; | |
| 223 _imports.forEach((library, temp) { | |
| 224 if (!_loader.libraryIsLoaded(library)) { | |
| 225 processImport(library, temp, lazyImports); | |
| 226 } | |
| 227 }); | |
| 228 | 220 |
| 229 var module = | 221 var module = |
| 230 js.call("function(#) { 'use strict'; #; }", [params, moduleStatements]); | 222 js.call("function(#) { 'use strict'; #; }", [params, moduleStatements]); |
| 231 | 223 |
| 232 var moduleDef = js.statement("dart_library.library(#, #, #, #, #)", [ | 224 var moduleDef = js.statement("dart_library.library(#, #, #, #, #)", [ |
| 233 js.string(jsPath, "'"), | 225 js.string(jsPath, "'"), |
| 234 _jsModuleValue ?? new JS.LiteralNull(), | 226 _jsModuleValue ?? new JS.LiteralNull(), |
| 235 js.commentExpression( | 227 js.commentExpression( |
| 236 "Imports", new JS.ArrayInitializer(imports, multiline: true)), | 228 "Imports", new JS.ArrayInitializer(imports, multiline: true)), |
| 237 js.commentExpression("Lazy imports", | 229 js.commentExpression("Lazy imports", |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 295 .map((i) => i.name) | 287 .map((i) => i.name) |
| 296 .where((s) => !currentLibNames.containsKey(s)) | 288 .where((s) => !currentLibNames.containsKey(s)) |
| 297 .map((s) => js.string(s, "'"))); | 289 .map((s) => js.string(s, "'"))); |
| 298 } | 290 } |
| 299 if (hide != null) { | 291 if (hide != null) { |
| 300 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); | 292 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); |
| 301 } | 293 } |
| 302 args.add(new JS.ArrayInitializer(shownNames)); | 294 args.add(new JS.ArrayInitializer(shownNames)); |
| 303 args.add(new JS.ArrayInitializer(hiddenNames)); | 295 args.add(new JS.ArrayInitializer(hiddenNames)); |
| 304 } | 296 } |
| 305 _moduleItems.add(js.statement('dart.export_(#);', [args])); | 297 |
| 298 // When we compile _runtime.js, we need to source export_ from _utils.js: | |
| 299 _moduleItems.add(js.statement('dart.export(#);', [args])); | |
| 306 } | 300 } |
| 307 | 301 |
| 308 JS.Identifier _initSymbol(JS.Identifier id) { | 302 JS.Identifier _initSymbol(JS.Identifier id) { |
| 309 var s = | 303 var s = |
| 310 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); | 304 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); |
| 311 _moduleItems.add(s); | 305 _moduleItems.add(s); |
| 312 return id; | 306 return id; |
| 313 } | 307 } |
| 314 | 308 |
| 315 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, | 309 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, |
| (...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1291 isGetter: node.isGetter, | 1285 isGetter: node.isGetter, |
| 1292 isSetter: node.isSetter, | 1286 isSetter: node.isSetter, |
| 1293 isStatic: node.isStatic), | 1287 isStatic: node.isStatic), |
| 1294 node.element); | 1288 node.element); |
| 1295 } | 1289 } |
| 1296 | 1290 |
| 1297 /// Returns the name value of the `JSExportName` annotation (when compiling | 1291 /// Returns the name value of the `JSExportName` annotation (when compiling |
| 1298 /// the SDK), or `null` if there's none. This is used to control the name | 1292 /// the SDK), or `null` if there's none. This is used to control the name |
| 1299 /// under which functions are compiled and exported. | 1293 /// under which functions are compiled and exported. |
| 1300 String _getJSExportName(Element e) { | 1294 String _getJSExportName(Element e) { |
| 1301 if (e is! FunctionElement || !currentLibrary.source.isInSystemLibrary) { | 1295 if (!currentLibrary.source.isInSystemLibrary) { |
| 1302 return null; | 1296 return null; |
| 1303 } | 1297 } |
| 1304 var jsName = findAnnotation(e, isJSExportNameAnnotation); | 1298 var jsName = findAnnotation(e, isJSExportNameAnnotation); |
| 1305 return getConstantField(jsName, 'name', types.stringType)?.toStringValue(); | 1299 return getConstantField(jsName, 'name', types.stringType)?.toStringValue(); |
| 1306 } | 1300 } |
| 1307 | 1301 |
| 1308 @override | 1302 @override |
| 1309 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { | 1303 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { |
| 1310 assert(node.parent is CompilationUnit); | 1304 assert(node.parent is CompilationUnit); |
| 1311 | 1305 |
| 1312 if (_externalOrNative(node)) return null; | 1306 if (_externalOrNative(node)) return null; |
| 1313 | 1307 |
| 1314 if (node.isGetter || node.isSetter) { | 1308 if (node.isGetter || node.isSetter) { |
| 1315 // Add these later so we can use getter/setter syntax. | 1309 // Add these later so we can use getter/setter syntax. |
| 1316 _properties.add(node); | 1310 _properties.add(node); |
| 1317 return null; | 1311 return null; |
| 1318 } | 1312 } |
| 1319 | 1313 |
| 1320 var body = <JS.Statement>[]; | 1314 var body = <JS.Statement>[]; |
| 1321 _flushLibraryProperties(body); | 1315 _flushLibraryProperties(body); |
| 1322 | 1316 |
| 1323 var name = _getJSExportName(node.element) ?? node.name.name; | 1317 var name = _getJSExportName(node.element) ?? node.name.name; |
| 1324 | 1318 |
| 1325 var fn = _visit(node.functionExpression); | 1319 var fn = _visit(node.functionExpression); |
| 1326 bool needsTagging = true; | |
| 1327 | 1320 |
| 1328 if (currentLibrary.source.isInSystemLibrary && | 1321 if (currentLibrary.source.isInSystemLibrary && |
| 1329 _isInlineJSFunction(node.functionExpression)) { | 1322 _isInlineJSFunction(node.functionExpression)) { |
| 1330 fn = _simplifyPassThroughArrowFunCallBody(fn); | 1323 fn = _simplifyPassThroughArrowFunCallBody(fn); |
| 1331 needsTagging = !_isDartUtils; | |
| 1332 } | 1324 } |
| 1333 | 1325 |
| 1334 var id = new JS.Identifier(name); | 1326 var id = new JS.Identifier(name); |
| 1335 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element)); | 1327 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element)); |
| 1336 if (needsTagging) { | 1328 if (!_isDartRuntime) { |
| 1337 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) | 1329 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) |
| 1338 .toStatement()); | 1330 .toStatement()); |
| 1339 } | 1331 } |
| 1340 | 1332 |
| 1341 if (isPublic(name)) _addExport(name); | 1333 if (isPublic(name)) _addExport(name); |
| 1342 return _statement(body); | 1334 return _statement(body); |
| 1343 } | 1335 } |
| 1344 | 1336 |
| 1345 bool _isInlineJSFunction(FunctionExpression functionExpression) { | 1337 bool _isInlineJSFunction(FunctionExpression functionExpression) { |
| 1346 var body = functionExpression.body; | 1338 var body = functionExpression.body; |
| 1347 if (body is ExpressionFunctionBody) { | 1339 if (body is ExpressionFunctionBody) { |
| 1348 return _isJSInvocation(body.expression); | 1340 return _isJSInvocation(body.expression); |
| 1349 } else if (body is BlockFunctionBody) { | 1341 } else if (body is BlockFunctionBody) { |
| 1350 if (body.block.statements.length == 1) { | 1342 if (body.block.statements.length == 1) { |
| 1351 var stat = body.block.statements.single; | 1343 var stat = body.block.statements.single; |
| 1352 if (stat is ReturnStatement) { | 1344 if (stat is ReturnStatement) { |
| 1353 return _isJSInvocation(stat.expression); | 1345 return _isJSInvocation(stat.expression); |
| 1354 } | 1346 } |
| 1355 } | 1347 } |
| 1356 } | 1348 } |
| 1357 return false; | 1349 return false; |
| 1358 } | 1350 } |
| 1359 | 1351 |
| 1360 bool _isJSInvocation(Expression expr) => | 1352 bool _isJSInvocation(Expression expr) => |
| 1361 expr is MethodInvocation && isInlineJS(expr.methodName.staticElement); | 1353 expr is MethodInvocation && isInlineJS(expr.methodName.staticElement); |
| 1362 | 1354 |
| 1363 // Simplify `(args) => ((x, y) => { ... })(x, y)` to `(args) => { ... }`. | 1355 // Simplify `(args) => (() => { ... })()` to `(args) => { ... }`. |
| 1364 // Note: we don't check if the top-level args match the ones passed through | 1356 // Note: this allows silently passing args through to the body, which only |
| 1365 // the arrow function, which allows silently passing args through to the | 1357 // works if we don't do weird renamings of Dart params. |
| 1366 // body (which only works if we don't do weird renamings of Dart params). | |
| 1367 JS.Fun _simplifyPassThroughArrowFunCallBody(JS.Fun fn) { | 1358 JS.Fun _simplifyPassThroughArrowFunCallBody(JS.Fun fn) { |
| 1368 String getIdent(JS.Node node) => node is JS.Identifier ? node.name : null; | |
| 1369 List<String> getIdents(List params) => | |
| 1370 params.map(getIdent).toList(growable: false); | |
| 1371 | |
| 1372 if (fn.body is JS.Block && fn.body.statements.length == 1) { | 1359 if (fn.body is JS.Block && fn.body.statements.length == 1) { |
| 1373 var stat = fn.body.statements.single; | 1360 var stat = fn.body.statements.single; |
| 1374 if (stat is JS.Return && stat.value is JS.Call) { | 1361 if (stat is JS.Return && stat.value is JS.Call) { |
| 1375 JS.Call call = stat.value; | 1362 JS.Call call = stat.value; |
| 1376 if (call.target is JS.ArrowFun) { | 1363 if (call.target is JS.ArrowFun && call.arguments.isEmpty) { |
| 1377 var passedArgs = getIdents(call.arguments); | |
| 1378 JS.ArrowFun innerFun = call.target; | 1364 JS.ArrowFun innerFun = call.target; |
| 1379 if (_listEquality.equals(getIdents(innerFun.params), passedArgs)) { | 1365 if (innerFun.params.isEmpty) { |
| 1380 return new JS.Fun(fn.params, innerFun.body); | 1366 return new JS.Fun(fn.params, innerFun.body); |
| 1381 } | 1367 } |
| 1382 } | 1368 } |
| 1383 } | 1369 } |
| 1384 } | 1370 } |
| 1385 return fn; | 1371 return fn; |
| 1386 } | 1372 } |
| 1387 | 1373 |
| 1388 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { | 1374 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { |
| 1389 var name = node.name.name; | 1375 var name = node.name.name; |
| (...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1904 var stmts = _visitList(node.block.statements) as List<JS.Statement>; | 1890 var stmts = _visitList(node.block.statements) as List<JS.Statement>; |
| 1905 if (initArgs != null) stmts.insert(0, initArgs); | 1891 if (initArgs != null) stmts.insert(0, initArgs); |
| 1906 return new JS.Block(stmts); | 1892 return new JS.Block(stmts); |
| 1907 } | 1893 } |
| 1908 | 1894 |
| 1909 @override | 1895 @override |
| 1910 JS.Block visitBlock(Block node) => | 1896 JS.Block visitBlock(Block node) => |
| 1911 new JS.Block(_visitList(node.statements) as List<JS.Statement>, | 1897 new JS.Block(_visitList(node.statements) as List<JS.Statement>, |
| 1912 isScope: true); | 1898 isScope: true); |
| 1913 | 1899 |
| 1900 /// Return the type constructor `_foolib.Bar$` given `Bar` from lib `_foolib`. | |
| 1901 /// | |
| 1902 /// This implements / expands the `genericTypeConstructor` intrinsic defined | |
| 1903 /// in `foreign_helper.dart`: | |
| 1904 /// `JS('', '#(type)', genericTypeConstructor(List))` will generate | |
| 1905 /// `core.List$(type)`. | |
| 1906 JS.Expression _emitGenericTypeConstructor(Expression typeExpression) { | |
|
Jennifer Messerly
2016/01/20 23:44:58
we chatted about moving this hack into the generat
ochafik
2016/01/21 00:11:35
So actually, JS('', '$Future\$($type)') is just JS
| |
| 1907 var ref = _visit(typeExpression); | |
| 1908 if (ref is JS.PropertyAccess) { | |
| 1909 var name = (ref.selector as JS.LiteralString).valueWithoutQuotes; | |
| 1910 return new JS.PropertyAccess( | |
| 1911 ref.receiver, new JS.LiteralString("'$name\$'")); | |
| 1912 } else if (ref is JS.MaybeQualifiedId) { | |
| 1913 var name = (ref.name as JS.Identifier).name; | |
| 1914 return new JS.PropertyAccess(ref.qualifier, new JS.Identifier('$name\$')); | |
| 1915 } else { | |
| 1916 throw new ArgumentError('Invalid type ref: $ref (${ref?.runtimeType})'); | |
| 1917 } | |
| 1918 } | |
| 1919 | |
| 1914 @override | 1920 @override |
| 1915 visitMethodInvocation(MethodInvocation node) { | 1921 visitMethodInvocation(MethodInvocation node) { |
| 1916 if (node.operator != null && node.operator.lexeme == '?.') { | 1922 if (node.operator != null && node.operator.lexeme == '?.') { |
| 1917 return _emitNullSafe(node); | 1923 return _emitNullSafe(node); |
| 1918 } | 1924 } |
| 1925 if (isGenericTypeConstructorIntrinsic(node)) { | |
| 1926 assert(currentLibrary.source.isInSystemLibrary); | |
| 1927 return _emitGenericTypeConstructor(node.argumentList.arguments.single); | |
| 1928 } | |
| 1919 | 1929 |
| 1920 var target = _getTarget(node); | 1930 var target = _getTarget(node); |
| 1921 var result = _emitForeignJS(node); | 1931 var result = _emitForeignJS(node); |
| 1922 if (result != null) return result; | 1932 if (result != null) return result; |
| 1923 | 1933 |
| 1924 String code; | 1934 String code; |
| 1925 if (target == null || isLibraryPrefix(target)) { | 1935 if (target == null || isLibraryPrefix(target)) { |
| 1926 if (DynamicInvoke.get(node.methodName)) { | 1936 if (DynamicInvoke.get(node.methodName)) { |
| 1927 code = 'dart.$DCALL(#, #)'; | 1937 code = 'dart.$DCALL(#, #)'; |
| 1928 } else { | 1938 } else { |
| (...skipping 1525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3454 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; | 3464 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; |
| 3455 | 3465 |
| 3456 FunctionBody _functionBody(node) => | 3466 FunctionBody _functionBody(node) => |
| 3457 node is FunctionDeclaration ? node.functionExpression.body : node.body; | 3467 node is FunctionDeclaration ? node.functionExpression.body : node.body; |
| 3458 | 3468 |
| 3459 /// Choose a canonical name from the library element. | 3469 /// Choose a canonical name from the library element. |
| 3460 /// This never uses the library's name (the identifier in the `library` | 3470 /// This never uses the library's name (the identifier in the `library` |
| 3461 /// declaration) as it doesn't have any meaningful rules enforced. | 3471 /// declaration) as it doesn't have any meaningful rules enforced. |
| 3462 JS.Identifier _libraryName(LibraryElement library) { | 3472 JS.Identifier _libraryName(LibraryElement library) { |
| 3463 if (library == currentLibrary) return _exportsVar; | 3473 if (library == currentLibrary) return _exportsVar; |
| 3474 if (library.name == 'dart._runtime') return _runtimeLibVar; | |
| 3464 return _imports.putIfAbsent( | 3475 return _imports.putIfAbsent( |
| 3465 library, () => new JS.TemporaryId(jsLibraryName(library))); | 3476 library, () => new JS.TemporaryId(jsLibraryName(library))); |
| 3466 } | 3477 } |
| 3467 | 3478 |
| 3468 DartType getStaticType(Expression e) => | 3479 DartType getStaticType(Expression e) => |
| 3469 e.staticType ?? DynamicTypeImpl.instance; | 3480 e.staticType ?? DynamicTypeImpl.instance; |
| 3470 | 3481 |
| 3471 @override | 3482 @override |
| 3472 String getQualifiedName(TypeDefiningElement type) { | 3483 String getQualifiedName(TypeDefiningElement type) { |
| 3473 JS.TemporaryId id = _imports[type.library]; | 3484 JS.TemporaryId id = _imports[type.library]; |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3634 | 3645 |
| 3635 /// A special kind of element created by the compiler, signifying a temporary | 3646 /// A special kind of element created by the compiler, signifying a temporary |
| 3636 /// variable. These objects use instance equality, and should be shared | 3647 /// variable. These objects use instance equality, and should be shared |
| 3637 /// everywhere in the tree where they are treated as the same variable. | 3648 /// everywhere in the tree where they are treated as the same variable. |
| 3638 class TemporaryVariableElement extends LocalVariableElementImpl { | 3649 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 3639 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3650 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 3640 | 3651 |
| 3641 int get hashCode => identityHashCode(this); | 3652 int get hashCode => identityHashCode(this); |
| 3642 bool operator ==(Object other) => identical(this, other); | 3653 bool operator ==(Object other) => identical(this, other); |
| 3643 } | 3654 } |
| OLD | NEW |