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 |