| 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; |
| 11 import 'package:analyzer/src/generated/constant.dart'; | 11 import 'package:analyzer/src/generated/constant.dart'; |
| 12 import 'package:analyzer/src/generated/element.dart'; | 12 import 'package:analyzer/src/generated/element.dart'; |
| 13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; | 13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
| 14 import 'package:analyzer/src/generated/scanner.dart' | 14 import 'package:analyzer/src/generated/scanner.dart' |
| 15 show StringToken, Token, TokenType; | 15 show StringToken, Token, TokenType; |
| 16 import 'package:analyzer/src/generated/type_system.dart' | 16 import 'package:analyzer/src/generated/type_system.dart' |
| 17 show StrongTypeSystemImpl; | 17 show StrongTypeSystemImpl; |
| 18 import 'package:analyzer/src/task/dart.dart' show PublicNamespaceBuilder; | 18 import 'package:analyzer/src/task/dart.dart' show PublicNamespaceBuilder; |
| 19 | 19 |
| 20 import 'ast_builder.dart' show AstBuilder; | 20 import 'ast_builder.dart' show AstBuilder; |
| 21 import 'reify_coercions.dart' show CoercionReifier, Tuple2; | 21 import 'reify_coercions.dart' show CoercionReifier, Tuple2; |
| 22 | 22 |
| 23 // TODO(jmesserly): import from its own package | 23 // TODO(jmesserly): import from its own package |
| 24 import '../js/js_ast.dart' as JS; | 24 import '../js/js_ast.dart' as JS; |
| 25 import '../js/js_ast.dart' show js; | 25 import '../js/js_ast.dart' show js; |
| 26 | 26 |
| 27 import '../closure/closure_annotator.dart' show ClosureAnnotator; | 27 import '../closure/closure_annotator.dart' show ClosureAnnotator; |
| 28 import '../compiler.dart' show AbstractCompiler; | 28 import '../compiler.dart' show AbstractCompiler, corelibUriOrder; |
| 29 import '../info.dart'; | 29 import '../info.dart'; |
| 30 import '../options.dart' show CodegenOptions; | 30 import '../options.dart' show CodegenOptions; |
| 31 import '../utils.dart'; | 31 import '../utils.dart'; |
| 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'; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 Expression _cascadeTarget; | 73 Expression _cascadeTarget; |
| 74 | 74 |
| 75 /// The variable for the current catch clause | 75 /// The variable for the current catch clause |
| 76 SimpleIdentifier _catchParameter; | 76 SimpleIdentifier _catchParameter; |
| 77 | 77 |
| 78 /// In an async* function, this represents the stream controller parameter. | 78 /// In an async* function, this represents the stream controller parameter. |
| 79 JS.TemporaryId _asyncStarController; | 79 JS.TemporaryId _asyncStarController; |
| 80 | 80 |
| 81 /// Imported libraries, and the temporaries used to refer to them. | 81 /// Imported libraries, and the temporaries used to refer to them. |
| 82 final _imports = new Map<LibraryElement, JS.TemporaryId>(); | 82 final _imports = new Map<LibraryElement, JS.TemporaryId>(); |
| 83 final _exports = new Set<String>(); | 83 final _exports = <String, String>{}; |
| 84 final _lazyFields = <VariableDeclaration>[]; | 84 final _lazyFields = <VariableDeclaration>[]; |
| 85 final _properties = <FunctionDeclaration>[]; | 85 final _properties = <FunctionDeclaration>[]; |
| 86 final _privateNames = new HashMap<String, JS.TemporaryId>(); | 86 final _privateNames = new HashMap<String, JS.TemporaryId>(); |
| 87 final _moduleItems = <JS.Statement>[]; | 87 final _moduleItems = <JS.Statement>[]; |
| 88 final _temps = new HashMap<Element, JS.TemporaryId>(); | 88 final _temps = new HashMap<Element, JS.TemporaryId>(); |
| 89 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>(); | 89 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>(); |
| 90 | 90 |
| 91 /// The name for the library's exports inside itself. | 91 /// The name for the library's exports inside itself. |
| 92 /// `exports` was chosen as the most similar to ES module patterns. | 92 /// `exports` was chosen as the most similar to ES module patterns. |
| 93 final _dartxVar = new JS.Identifier('dartx'); | 93 final _dartxVar = new JS.Identifier('dartx'); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 _flushLibraryProperties(_moduleItems); | 172 _flushLibraryProperties(_moduleItems); |
| 173 | 173 |
| 174 // Mark all qualified names as qualified or not, depending on if they need | 174 // Mark all qualified names as qualified or not, depending on if they need |
| 175 // to be loaded lazily or not. | 175 // to be loaded lazily or not. |
| 176 for (var elementIdPairs in _qualifiedIds) { | 176 for (var elementIdPairs in _qualifiedIds) { |
| 177 var element = elementIdPairs.e0; | 177 var element = elementIdPairs.e0; |
| 178 var id = elementIdPairs.e1; | 178 var id = elementIdPairs.e1; |
| 179 id.setQualified(!_loader.isLoaded(element)); | 179 id.setQualified(!_loader.isLoaded(element)); |
| 180 } | 180 } |
| 181 | 181 |
| 182 var moduleBuilder = new ModuleBuilder( | 182 var moduleBuilder = new ModuleBuilder(options.moduleFormat); |
| 183 compiler.getModuleName(currentLibrary.source.uri), | |
| 184 _jsModuleValue, | |
| 185 _exportsVar, | |
| 186 options.moduleFormat); | |
| 187 | |
| 188 _exports.forEach(moduleBuilder.addExport); | 183 _exports.forEach(moduleBuilder.addExport); |
| 189 | 184 |
| 190 var items = <JS.ModuleItem>[]; | 185 var items = <JS.ModuleItem>[]; |
| 191 if (!_isDartRuntime) { | 186 if (!_isDartRuntime) { |
| 187 if (currentLibrary.source.isInSystemLibrary) { |
| 188 // Force the import order of runtime libs. |
| 189 // TODO(ochafik): Reduce this to a minimum. |
| 190 for (var lib in corelibUriOrder.reversed) { |
| 191 moduleBuilder.addImport(lib.replaceAll(':', '/'), null); |
| 192 } |
| 193 } |
| 192 moduleBuilder.addImport('dart/_runtime', _runtimeLibVar); | 194 moduleBuilder.addImport('dart/_runtime', _runtimeLibVar); |
| 193 | 195 |
| 194 var dartxImport = | 196 var dartxImport = |
| 195 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); | 197 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); |
| 196 items.add(dartxImport); | 198 items.add(dartxImport); |
| 197 } | 199 } |
| 198 items.addAll(_moduleItems); | 200 items.addAll(_moduleItems); |
| 199 | 201 |
| 200 _imports.forEach((LibraryElement lib, JS.TemporaryId temp) { | 202 _imports.forEach((LibraryElement lib, JS.TemporaryId temp) { |
| 201 moduleBuilder.addImport(compiler.getModuleName(lib.source.uri), temp, | 203 moduleBuilder.addImport(compiler.getModuleName(lib.source.uri), temp, |
| 202 isLazy: _isDartRuntime || !_loader.libraryIsLoaded(lib)); | 204 isLazy: _isDartRuntime || !_loader.libraryIsLoaded(lib)); |
| 203 }); | 205 }); |
| 204 | 206 |
| 205 // TODO(jmesserly): scriptTag support. | 207 // TODO(jmesserly): scriptTag support. |
| 206 // Enable this if we know we're targetting command line environment? | 208 // Enable this if we know we're targetting command line environment? |
| 207 // It doesn't work in browser. | 209 // It doesn't work in browser. |
| 208 // var jsBin = compiler.options.runnerOptions.v8Binary; | 210 // var jsBin = compiler.options.runnerOptions.v8Binary; |
| 209 // String scriptTag = null; | 211 // String scriptTag = null; |
| 210 // if (library.library.scriptTag != null) scriptTag = '/usr/bin/env $jsBin'; | 212 // if (library.library.scriptTag != null) scriptTag = '/usr/bin/env $jsBin'; |
| 211 return moduleBuilder.build(items); | 213 return moduleBuilder.build( |
| 214 compiler.getModuleName(currentLibrary.source.uri), |
| 215 _jsModuleValue, |
| 216 _exportsVar, |
| 217 items); |
| 212 } | 218 } |
| 213 | 219 |
| 214 void _emitModuleItem(AstNode node) { | 220 void _emitModuleItem(AstNode node) { |
| 215 // Attempt to group adjacent fields/properties. | 221 // Attempt to group adjacent fields/properties. |
| 216 if (node is! VariableDeclaration) _flushLazyFields(_moduleItems); | 222 if (node is! VariableDeclaration) _flushLazyFields(_moduleItems); |
| 217 if (node is! FunctionDeclaration) _flushLibraryProperties(_moduleItems); | 223 if (node is! FunctionDeclaration) _flushLibraryProperties(_moduleItems); |
| 218 | 224 |
| 219 var code = _visit(node); | 225 var code = _visit(node); |
| 220 if (code != null) _moduleItems.add(code); | 226 if (code != null) _moduleItems.add(code); |
| 221 } | 227 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 .where((s) => !currentLibNames.containsKey(s)) | 265 .where((s) => !currentLibNames.containsKey(s)) |
| 260 .map((s) => js.string(s, "'"))); | 266 .map((s) => js.string(s, "'"))); |
| 261 } | 267 } |
| 262 if (hide != null) { | 268 if (hide != null) { |
| 263 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); | 269 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); |
| 264 } | 270 } |
| 265 args.add(new JS.ArrayInitializer(shownNames)); | 271 args.add(new JS.ArrayInitializer(shownNames)); |
| 266 args.add(new JS.ArrayInitializer(hiddenNames)); | 272 args.add(new JS.ArrayInitializer(hiddenNames)); |
| 267 } | 273 } |
| 268 | 274 |
| 269 // When we compile _runtime.js, we need to source export_ from _utils.js: | 275 _moduleItems.add(js.statement('dart.export_(#);', [args])); |
| 270 _moduleItems.add(js.statement('dart.export(#);', [args])); | |
| 271 } | 276 } |
| 272 | 277 |
| 273 JS.Identifier _initSymbol(JS.Identifier id) { | 278 JS.Identifier _initSymbol(JS.Identifier id) { |
| 274 var s = | 279 var s = |
| 275 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); | 280 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); |
| 276 _moduleItems.add(s); | 281 _moduleItems.add(s); |
| 277 return id; | 282 return id; |
| 278 } | 283 } |
| 279 | 284 |
| 280 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, | 285 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 return js.statement( | 528 return js.statement( |
| 524 'dart.defineLazyClass(#, { get #() { #; return #; } });', | 529 'dart.defineLazyClass(#, { get #() { #; return #; } });', |
| 525 [_exportsVar, _propertyName(name), body, name]); | 530 [_exportsVar, _propertyName(name), body, name]); |
| 526 } | 531 } |
| 527 | 532 |
| 528 if (isPublic(name)) _addExport(name); | 533 if (isPublic(name)) _addExport(name); |
| 529 | 534 |
| 530 if (genericDef != null) { | 535 if (genericDef != null) { |
| 531 var dynType = fillDynamicTypeArgs(type, types); | 536 var dynType = fillDynamicTypeArgs(type, types); |
| 532 var genericInst = _emitTypeName(dynType, lowerGeneric: true); | 537 var genericInst = _emitTypeName(dynType, lowerGeneric: true); |
| 533 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); | 538 return js |
| 539 .statement('{ #; const # = #; }', [genericDef, name, genericInst]); |
| 534 } | 540 } |
| 535 return body; | 541 return body; |
| 536 } | 542 } |
| 537 | 543 |
| 538 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { | 544 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { |
| 539 var name = type.name; | 545 var name = type.name; |
| 540 var genericName = '$name\$'; | 546 var genericName = '$name\$'; |
| 541 var typeParams = _boundTypeParametersOf(type).map((p) => p.name); | 547 var typeParams = _boundTypeParametersOf(type).map((p) => p.name); |
| 542 if (isPublic(name)) _exports.add(genericName); | 548 if (isPublic(name)) _addExport(genericName); |
| 543 return js.statement('const # = dart.generic(function(#) { #; return #; });', | 549 return js.statement('const # = dart.generic(function(#) { #; return #; });', |
| 544 [genericName, typeParams, body, name]); | 550 [genericName, typeParams, body, name]); |
| 545 } | 551 } |
| 546 | 552 |
| 547 final _hasDeferredSupertype = new HashSet<ClassElement>(); | 553 final _hasDeferredSupertype = new HashSet<ClassElement>(); |
| 548 | 554 |
| 549 bool _deferIfNeeded(DartType type, ClassElement current) { | 555 bool _deferIfNeeded(DartType type, ClassElement current) { |
| 550 if (type is ParameterizedType) { | 556 if (type is ParameterizedType) { |
| 551 var typeArguments = type.typeArguments; | 557 var typeArguments = type.typeArguments; |
| 552 for (var typeArg in typeArguments) { | 558 for (var typeArg in typeArguments) { |
| (...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1278 | 1284 |
| 1279 if (node.isGetter || node.isSetter) { | 1285 if (node.isGetter || node.isSetter) { |
| 1280 // Add these later so we can use getter/setter syntax. | 1286 // Add these later so we can use getter/setter syntax. |
| 1281 _properties.add(node); | 1287 _properties.add(node); |
| 1282 return null; | 1288 return null; |
| 1283 } | 1289 } |
| 1284 | 1290 |
| 1285 var body = <JS.Statement>[]; | 1291 var body = <JS.Statement>[]; |
| 1286 _flushLibraryProperties(body); | 1292 _flushLibraryProperties(body); |
| 1287 | 1293 |
| 1288 var name = _getJSExportName(node.element) ?? node.name.name; | 1294 var name = node.name.name; |
| 1289 | 1295 |
| 1290 var fn = _visit(node.functionExpression); | 1296 var fn = _visit(node.functionExpression); |
| 1291 | 1297 |
| 1292 if (currentLibrary.source.isInSystemLibrary && | 1298 if (currentLibrary.source.isInSystemLibrary && |
| 1293 _isInlineJSFunction(node.functionExpression)) { | 1299 _isInlineJSFunction(node.functionExpression)) { |
| 1294 fn = _simplifyPassThroughArrowFunCallBody(fn); | 1300 fn = _simplifyPassThroughArrowFunCallBody(fn); |
| 1295 } | 1301 } |
| 1296 | 1302 |
| 1297 var id = new JS.Identifier(name); | 1303 var id = new JS.Identifier(name); |
| 1298 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element)); | 1304 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element)); |
| 1299 if (!_isDartRuntime) { | 1305 if (!_isDartRuntime) { |
| 1300 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) | 1306 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) |
| 1301 .toStatement()); | 1307 .toStatement()); |
| 1302 } | 1308 } |
| 1303 | 1309 |
| 1304 if (isPublic(name)) _addExport(name); | 1310 if (isPublic(name)) { |
| 1311 _addExport(name, _getJSExportName(node.element) ?? name); |
| 1312 } |
| 1305 return _statement(body); | 1313 return _statement(body); |
| 1306 } | 1314 } |
| 1307 | 1315 |
| 1308 bool _isInlineJSFunction(FunctionExpression functionExpression) { | 1316 bool _isInlineJSFunction(FunctionExpression functionExpression) { |
| 1309 var body = functionExpression.body; | 1317 var body = functionExpression.body; |
| 1310 if (body is ExpressionFunctionBody) { | 1318 if (body is ExpressionFunctionBody) { |
| 1311 return _isJSInvocation(body.expression); | 1319 return _isJSInvocation(body.expression); |
| 1312 } else if (body is BlockFunctionBody) { | 1320 } else if (body is BlockFunctionBody) { |
| 1313 if (body.block.statements.length == 1) { | 1321 if (body.block.statements.length == 1) { |
| 1314 var stat = body.block.statements.single; | 1322 var stat = body.block.statements.single; |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1728 var genericName = _emitTopLevelName(element, suffix: '\$'); | 1736 var genericName = _emitTopLevelName(element, suffix: '\$'); |
| 1729 return js.call('#(#)', [genericName, jsArgs]); | 1737 return js.call('#(#)', [genericName, jsArgs]); |
| 1730 } | 1738 } |
| 1731 } | 1739 } |
| 1732 | 1740 |
| 1733 return _emitTopLevelName(element); | 1741 return _emitTopLevelName(element); |
| 1734 } | 1742 } |
| 1735 | 1743 |
| 1736 JS.Expression _emitTopLevelName(Element e, {String suffix: ''}) { | 1744 JS.Expression _emitTopLevelName(Element e, {String suffix: ''}) { |
| 1737 var libName = _libraryName(e.library); | 1745 var libName = _libraryName(e.library); |
| 1738 var nameExpr = _propertyName((_getJSExportName(e) ?? e.name) + suffix); | |
| 1739 | 1746 |
| 1740 // Always qualify: | 1747 // Always qualify: |
| 1741 // * mutable top-level fields | 1748 // * mutable top-level fields |
| 1742 // * elements from other libraries | 1749 // * elements from other libraries |
| 1743 bool mutableTopLevel = e is TopLevelVariableElement && | 1750 bool mutableTopLevel = e is TopLevelVariableElement && |
| 1744 !e.isConst && | 1751 !e.isConst && |
| 1745 !_isFinalJSDecl(e.computeNode()); | 1752 !_isFinalJSDecl(e.computeNode()); |
| 1746 bool fromAnotherLibrary = e.library != currentLibrary; | 1753 bool fromAnotherLibrary = e.library != currentLibrary; |
| 1754 var nameExpr; |
| 1755 if (fromAnotherLibrary) { |
| 1756 nameExpr = _propertyName((_getJSExportName(e) ?? e.name) + suffix); |
| 1757 } else { |
| 1758 nameExpr = _propertyName(e.name + suffix); |
| 1759 } |
| 1747 if (mutableTopLevel || fromAnotherLibrary) { | 1760 if (mutableTopLevel || fromAnotherLibrary) { |
| 1748 return new JS.PropertyAccess(libName, nameExpr); | 1761 return new JS.PropertyAccess(libName, nameExpr); |
| 1749 } | 1762 } |
| 1750 | 1763 |
| 1751 var id = new JS.MaybeQualifiedId(libName, nameExpr); | 1764 var id = new JS.MaybeQualifiedId(libName, nameExpr); |
| 1752 _qualifiedIds.add(new Tuple2(e, id)); | 1765 _qualifiedIds.add(new Tuple2(e, id)); |
| 1753 return id; | 1766 return id; |
| 1754 } | 1767 } |
| 1755 | 1768 |
| 1756 @override | 1769 @override |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2129 /// [visitTopLevelVariableDeclaration]. | 2142 /// [visitTopLevelVariableDeclaration]. |
| 2130 @override | 2143 @override |
| 2131 visitFieldDeclaration(FieldDeclaration node) { | 2144 visitFieldDeclaration(FieldDeclaration node) { |
| 2132 if (!node.isStatic) return; | 2145 if (!node.isStatic) return; |
| 2133 | 2146 |
| 2134 for (var f in node.fields.variables) { | 2147 for (var f in node.fields.variables) { |
| 2135 _loader.loadDeclaration(f, f.element); | 2148 _loader.loadDeclaration(f, f.element); |
| 2136 } | 2149 } |
| 2137 } | 2150 } |
| 2138 | 2151 |
| 2139 _addExport(String name) { | 2152 _addExport(String name, [String exportName]) { |
| 2140 if (!_exports.add(name)) throw 'Duplicate top level name found: $name'; | 2153 if (_exports.containsKey(name)) |
| 2154 throw 'Duplicate top level name found: $name'; |
| 2155 _exports[name] = exportName ?? name; |
| 2141 } | 2156 } |
| 2142 | 2157 |
| 2143 @override | 2158 @override |
| 2144 JS.Statement visitVariableDeclarationStatement( | 2159 JS.Statement visitVariableDeclarationStatement( |
| 2145 VariableDeclarationStatement node) { | 2160 VariableDeclarationStatement node) { |
| 2146 // Special case a single variable with an initializer. | 2161 // Special case a single variable with an initializer. |
| 2147 // This helps emit cleaner code for things like: | 2162 // This helps emit cleaner code for things like: |
| 2148 // var result = []..add(1)..add(2); | 2163 // var result = []..add(1)..add(2); |
| 2149 if (node.variables.variables.length == 1) { | 2164 if (node.variables.variables.length == 1) { |
| 2150 var v = node.variables.variables.single; | 2165 var v = node.variables.variables.single; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2192 jsInit = _visitInitializer(field); | 2207 jsInit = _visitInitializer(field); |
| 2193 eagerInit = false; | 2208 eagerInit = false; |
| 2194 } | 2209 } |
| 2195 | 2210 |
| 2196 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile | 2211 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile |
| 2197 // runtime helpers. | 2212 // runtime helpers. |
| 2198 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field); | 2213 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field); |
| 2199 if (isJSTopLevel) eagerInit = true; | 2214 if (isJSTopLevel) eagerInit = true; |
| 2200 | 2215 |
| 2201 var fieldName = field.name.name; | 2216 var fieldName = field.name.name; |
| 2217 var exportName = fieldName; |
| 2202 if (element is TopLevelVariableElement) { | 2218 if (element is TopLevelVariableElement) { |
| 2203 fieldName = _getJSExportName(element) ?? fieldName; | 2219 exportName = _getJSExportName(element) ?? fieldName; |
| 2204 } | 2220 } |
| 2205 if ((field.isConst && eagerInit && element is TopLevelVariableElement) || | 2221 if ((field.isConst && eagerInit && element is TopLevelVariableElement) || |
| 2206 isJSTopLevel) { | 2222 isJSTopLevel) { |
| 2207 // constant fields don't change, so we can generate them as `let` | 2223 // constant fields don't change, so we can generate them as `let` |
| 2208 // but add them to the module's exports. However, make sure we generate | 2224 // but add them to the module's exports. However, make sure we generate |
| 2209 // anything they depend on first. | 2225 // anything they depend on first. |
| 2210 | 2226 |
| 2211 if (isPublic(fieldName)) _addExport(fieldName); | 2227 if (isPublic(fieldName)) _addExport(fieldName, exportName); |
| 2212 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; | 2228 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; |
| 2213 return annotateVariable( | 2229 return annotateVariable( |
| 2214 js.statement( | 2230 js.statement( |
| 2215 '$declKeyword # = #;', [new JS.Identifier(fieldName), jsInit]), | 2231 '$declKeyword # = #;', [new JS.Identifier(fieldName), jsInit]), |
| 2216 field.element); | 2232 field.element); |
| 2217 } | 2233 } |
| 2218 | 2234 |
| 2219 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) { | 2235 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) { |
| 2220 return annotateVariable( | 2236 return annotateVariable( |
| 2221 js.statement('# = #;', [_visit(field.name), jsInit]), field.element); | 2237 js.statement('# = #;', [_visit(field.name), jsInit]), field.element); |
| (...skipping 1370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3592 | 3608 |
| 3593 /// A special kind of element created by the compiler, signifying a temporary | 3609 /// A special kind of element created by the compiler, signifying a temporary |
| 3594 /// variable. These objects use instance equality, and should be shared | 3610 /// variable. These objects use instance equality, and should be shared |
| 3595 /// everywhere in the tree where they are treated as the same variable. | 3611 /// everywhere in the tree where they are treated as the same variable. |
| 3596 class TemporaryVariableElement extends LocalVariableElementImpl { | 3612 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 3597 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3613 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 3598 | 3614 |
| 3599 int get hashCode => identityHashCode(this); | 3615 int get hashCode => identityHashCode(this); |
| 3600 bool operator ==(Object other) => identical(this, other); | 3616 bool operator ==(Object other) => identical(this, other); |
| 3601 } | 3617 } |
| OLD | NEW |