| 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 | |
| 229 var module = | 220 var module = |
| 230 js.call("function(#) { 'use strict'; #; }", [params, moduleStatements]); | 221 js.call("function(#) { 'use strict'; #; }", [params, moduleStatements]); |
| 231 | 222 |
| 232 var moduleDef = js.statement("dart_library.library(#, #, #, #, #)", [ | 223 var moduleDef = js.statement("dart_library.library(#, #, #, #, #)", [ |
| 233 js.string(jsPath, "'"), | 224 js.string(jsPath, "'"), |
| 234 _jsModuleValue ?? new JS.LiteralNull(), | 225 _jsModuleValue ?? new JS.LiteralNull(), |
| 235 js.commentExpression( | 226 js.commentExpression( |
| 236 "Imports", new JS.ArrayInitializer(imports, multiline: true)), | 227 "Imports", new JS.ArrayInitializer(imports, multiline: true)), |
| 237 js.commentExpression("Lazy imports", | 228 js.commentExpression("Lazy imports", |
| 238 new JS.ArrayInitializer(lazyImports, multiline: true)), | 229 new JS.ArrayInitializer(lazyImports, multiline: true)), |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 .map((i) => i.name) | 286 .map((i) => i.name) |
| 296 .where((s) => !currentLibNames.containsKey(s)) | 287 .where((s) => !currentLibNames.containsKey(s)) |
| 297 .map((s) => js.string(s, "'"))); | 288 .map((s) => js.string(s, "'"))); |
| 298 } | 289 } |
| 299 if (hide != null) { | 290 if (hide != null) { |
| 300 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); | 291 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); |
| 301 } | 292 } |
| 302 args.add(new JS.ArrayInitializer(shownNames)); | 293 args.add(new JS.ArrayInitializer(shownNames)); |
| 303 args.add(new JS.ArrayInitializer(hiddenNames)); | 294 args.add(new JS.ArrayInitializer(hiddenNames)); |
| 304 } | 295 } |
| 305 _moduleItems.add(js.statement('dart.export_(#);', [args])); | 296 |
| 297 // When we compile _runtime.js, we need to source export_ from _utils.js: |
| 298 _moduleItems.add(js.statement('dart.export(#);', [args])); |
| 306 } | 299 } |
| 307 | 300 |
| 308 JS.Identifier _initSymbol(JS.Identifier id) { | 301 JS.Identifier _initSymbol(JS.Identifier id) { |
| 309 var s = | 302 var s = |
| 310 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); | 303 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); |
| 311 _moduleItems.add(s); | 304 _moduleItems.add(s); |
| 312 return id; | 305 return id; |
| 313 } | 306 } |
| 314 | 307 |
| 315 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, | 308 // 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, | 1284 isGetter: node.isGetter, |
| 1292 isSetter: node.isSetter, | 1285 isSetter: node.isSetter, |
| 1293 isStatic: node.isStatic), | 1286 isStatic: node.isStatic), |
| 1294 node.element); | 1287 node.element); |
| 1295 } | 1288 } |
| 1296 | 1289 |
| 1297 /// Returns the name value of the `JSExportName` annotation (when compiling | 1290 /// 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 | 1291 /// the SDK), or `null` if there's none. This is used to control the name |
| 1299 /// under which functions are compiled and exported. | 1292 /// under which functions are compiled and exported. |
| 1300 String _getJSExportName(Element e) { | 1293 String _getJSExportName(Element e) { |
| 1301 if (e is! FunctionElement || !currentLibrary.source.isInSystemLibrary) { | 1294 if (!currentLibrary.source.isInSystemLibrary) { |
| 1302 return null; | 1295 return null; |
| 1303 } | 1296 } |
| 1304 var jsName = findAnnotation(e, isJSExportNameAnnotation); | 1297 var jsName = findAnnotation(e, isJSExportNameAnnotation); |
| 1305 return getConstantField(jsName, 'name', types.stringType)?.toStringValue(); | 1298 return getConstantField(jsName, 'name', types.stringType)?.toStringValue(); |
| 1306 } | 1299 } |
| 1307 | 1300 |
| 1308 @override | 1301 @override |
| 1309 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { | 1302 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { |
| 1310 assert(node.parent is CompilationUnit); | 1303 assert(node.parent is CompilationUnit); |
| 1311 | 1304 |
| 1312 if (_externalOrNative(node)) return null; | 1305 if (_externalOrNative(node)) return null; |
| 1313 | 1306 |
| 1314 if (node.isGetter || node.isSetter) { | 1307 if (node.isGetter || node.isSetter) { |
| 1315 // Add these later so we can use getter/setter syntax. | 1308 // Add these later so we can use getter/setter syntax. |
| 1316 _properties.add(node); | 1309 _properties.add(node); |
| 1317 return null; | 1310 return null; |
| 1318 } | 1311 } |
| 1319 | 1312 |
| 1320 var body = <JS.Statement>[]; | 1313 var body = <JS.Statement>[]; |
| 1321 _flushLibraryProperties(body); | 1314 _flushLibraryProperties(body); |
| 1322 | 1315 |
| 1323 var name = _getJSExportName(node.element) ?? node.name.name; | 1316 var name = _getJSExportName(node.element) ?? node.name.name; |
| 1324 | 1317 |
| 1325 var fn = _visit(node.functionExpression); | 1318 var fn = _visit(node.functionExpression); |
| 1326 bool needsTagging = true; | |
| 1327 | 1319 |
| 1328 if (currentLibrary.source.isInSystemLibrary && | 1320 if (currentLibrary.source.isInSystemLibrary && |
| 1329 _isInlineJSFunction(node.functionExpression)) { | 1321 _isInlineJSFunction(node.functionExpression)) { |
| 1330 fn = _simplifyPassThroughArrowFunCallBody(fn); | 1322 fn = _simplifyPassThroughArrowFunCallBody(fn); |
| 1331 needsTagging = !_isDartUtils; | |
| 1332 } | 1323 } |
| 1333 | 1324 |
| 1334 var id = new JS.Identifier(name); | 1325 var id = new JS.Identifier(name); |
| 1335 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element)); | 1326 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element)); |
| 1336 if (needsTagging) { | 1327 if (!_isDartRuntime) { |
| 1337 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) | 1328 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) |
| 1338 .toStatement()); | 1329 .toStatement()); |
| 1339 } | 1330 } |
| 1340 | 1331 |
| 1341 if (isPublic(name)) _addExport(name); | 1332 if (isPublic(name)) _addExport(name); |
| 1342 return _statement(body); | 1333 return _statement(body); |
| 1343 } | 1334 } |
| 1344 | 1335 |
| 1345 bool _isInlineJSFunction(FunctionExpression functionExpression) { | 1336 bool _isInlineJSFunction(FunctionExpression functionExpression) { |
| 1346 var body = functionExpression.body; | 1337 var body = functionExpression.body; |
| 1347 if (body is ExpressionFunctionBody) { | 1338 if (body is ExpressionFunctionBody) { |
| 1348 return _isJSInvocation(body.expression); | 1339 return _isJSInvocation(body.expression); |
| 1349 } else if (body is BlockFunctionBody) { | 1340 } else if (body is BlockFunctionBody) { |
| 1350 if (body.block.statements.length == 1) { | 1341 if (body.block.statements.length == 1) { |
| 1351 var stat = body.block.statements.single; | 1342 var stat = body.block.statements.single; |
| 1352 if (stat is ReturnStatement) { | 1343 if (stat is ReturnStatement) { |
| 1353 return _isJSInvocation(stat.expression); | 1344 return _isJSInvocation(stat.expression); |
| 1354 } | 1345 } |
| 1355 } | 1346 } |
| 1356 } | 1347 } |
| 1357 return false; | 1348 return false; |
| 1358 } | 1349 } |
| 1359 | 1350 |
| 1360 bool _isJSInvocation(Expression expr) => | 1351 bool _isJSInvocation(Expression expr) => |
| 1361 expr is MethodInvocation && isInlineJS(expr.methodName.staticElement); | 1352 expr is MethodInvocation && isInlineJS(expr.methodName.staticElement); |
| 1362 | 1353 |
| 1363 // Simplify `(args) => ((x, y) => { ... })(x, y)` to `(args) => { ... }`. | 1354 // Simplify `(args) => (() => { ... })()` to `(args) => { ... }`. |
| 1364 // Note: we don't check if the top-level args match the ones passed through | 1355 // Note: this allows silently passing args through to the body, which only |
| 1365 // the arrow function, which allows silently passing args through to the | 1356 // 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) { | 1357 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) { | 1358 if (fn.body is JS.Block && fn.body.statements.length == 1) { |
| 1373 var stat = fn.body.statements.single; | 1359 var stat = fn.body.statements.single; |
| 1374 if (stat is JS.Return && stat.value is JS.Call) { | 1360 if (stat is JS.Return && stat.value is JS.Call) { |
| 1375 JS.Call call = stat.value; | 1361 JS.Call call = stat.value; |
| 1376 if (call.target is JS.ArrowFun) { | 1362 if (call.target is JS.ArrowFun && call.arguments.isEmpty) { |
| 1377 var passedArgs = getIdents(call.arguments); | |
| 1378 JS.ArrowFun innerFun = call.target; | 1363 JS.ArrowFun innerFun = call.target; |
| 1379 if (_listEquality.equals(getIdents(innerFun.params), passedArgs)) { | 1364 if (innerFun.params.isEmpty) { |
| 1380 return new JS.Fun(fn.params, innerFun.body); | 1365 return new JS.Fun(fn.params, innerFun.body); |
| 1381 } | 1366 } |
| 1382 } | 1367 } |
| 1383 } | 1368 } |
| 1384 } | 1369 } |
| 1385 return fn; | 1370 return fn; |
| 1386 } | 1371 } |
| 1387 | 1372 |
| 1388 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { | 1373 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { |
| 1389 var name = node.name.name; | 1374 var name = node.name.name; |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1769 } | 1754 } |
| 1770 if (jsArgs != null) { | 1755 if (jsArgs != null) { |
| 1771 var genericName = _emitTopLevelName(element, suffix: '\$'); | 1756 var genericName = _emitTopLevelName(element, suffix: '\$'); |
| 1772 return js.call('#(#)', [genericName, jsArgs]); | 1757 return js.call('#(#)', [genericName, jsArgs]); |
| 1773 } | 1758 } |
| 1774 } | 1759 } |
| 1775 | 1760 |
| 1776 return _emitTopLevelName(element); | 1761 return _emitTopLevelName(element); |
| 1777 } | 1762 } |
| 1778 | 1763 |
| 1779 JS.Expression _emitTopLevelName(Element e, {String suffix : ''}) { | 1764 JS.Expression _emitTopLevelName(Element e, {String suffix: ''}) { |
| 1780 var libName = _libraryName(e.library); | 1765 var libName = _libraryName(e.library); |
| 1781 var nameExpr = _propertyName((_getJSExportName(e) ?? e.name) + suffix); | 1766 var nameExpr = _propertyName((_getJSExportName(e) ?? e.name) + suffix); |
| 1782 | 1767 |
| 1783 // Always qualify: | 1768 // Always qualify: |
| 1784 // * mutable top-level fields | 1769 // * mutable top-level fields |
| 1785 // * elements from other libraries | 1770 // * elements from other libraries |
| 1786 bool mutableTopLevel = e is TopLevelVariableElement && | 1771 bool mutableTopLevel = e is TopLevelVariableElement && |
| 1787 !e.isConst && | 1772 !e.isConst && |
| 1788 !_isFinalJSDecl(e.computeNode()); | 1773 !_isFinalJSDecl(e.computeNode()); |
| 1789 bool fromAnotherLibrary = e.library != currentLibrary; | 1774 bool fromAnotherLibrary = e.library != currentLibrary; |
| (...skipping 1664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3454 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; | 3439 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; |
| 3455 | 3440 |
| 3456 FunctionBody _functionBody(node) => | 3441 FunctionBody _functionBody(node) => |
| 3457 node is FunctionDeclaration ? node.functionExpression.body : node.body; | 3442 node is FunctionDeclaration ? node.functionExpression.body : node.body; |
| 3458 | 3443 |
| 3459 /// Choose a canonical name from the library element. | 3444 /// Choose a canonical name from the library element. |
| 3460 /// This never uses the library's name (the identifier in the `library` | 3445 /// This never uses the library's name (the identifier in the `library` |
| 3461 /// declaration) as it doesn't have any meaningful rules enforced. | 3446 /// declaration) as it doesn't have any meaningful rules enforced. |
| 3462 JS.Identifier _libraryName(LibraryElement library) { | 3447 JS.Identifier _libraryName(LibraryElement library) { |
| 3463 if (library == currentLibrary) return _exportsVar; | 3448 if (library == currentLibrary) return _exportsVar; |
| 3449 if (library.name == 'dart._runtime') return _runtimeLibVar; |
| 3464 return _imports.putIfAbsent( | 3450 return _imports.putIfAbsent( |
| 3465 library, () => new JS.TemporaryId(jsLibraryName(library))); | 3451 library, () => new JS.TemporaryId(jsLibraryName(library))); |
| 3466 } | 3452 } |
| 3467 | 3453 |
| 3468 DartType getStaticType(Expression e) => | 3454 DartType getStaticType(Expression e) => |
| 3469 e.staticType ?? DynamicTypeImpl.instance; | 3455 e.staticType ?? DynamicTypeImpl.instance; |
| 3470 | 3456 |
| 3471 @override | 3457 @override |
| 3472 String getQualifiedName(TypeDefiningElement type) { | 3458 String getQualifiedName(TypeDefiningElement type) { |
| 3473 JS.TemporaryId id = _imports[type.library]; | 3459 JS.TemporaryId id = _imports[type.library]; |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3634 | 3620 |
| 3635 /// A special kind of element created by the compiler, signifying a temporary | 3621 /// A special kind of element created by the compiler, signifying a temporary |
| 3636 /// variable. These objects use instance equality, and should be shared | 3622 /// variable. These objects use instance equality, and should be shared |
| 3637 /// everywhere in the tree where they are treated as the same variable. | 3623 /// everywhere in the tree where they are treated as the same variable. |
| 3638 class TemporaryVariableElement extends LocalVariableElementImpl { | 3624 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 3639 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3625 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 3640 | 3626 |
| 3641 int get hashCode => identityHashCode(this); | 3627 int get hashCode => identityHashCode(this); |
| 3642 bool operator ==(Object other) => identical(this, other); | 3628 bool operator ==(Object other) => identical(this, other); |
| 3643 } | 3629 } |
| OLD | NEW |