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 20 matching lines...) Expand all Loading... | |
| 31 | 31 |
| 32 import 'code_generator.dart'; | 32 import 'code_generator.dart'; |
| 33 import 'js_field_storage.dart'; | 33 import 'js_field_storage.dart'; |
| 34 import 'js_interop.dart'; | 34 import 'js_interop.dart'; |
| 35 import 'js_names.dart' as JS; | 35 import 'js_names.dart' as JS; |
| 36 import 'js_metalet.dart' as JS; | 36 import 'js_metalet.dart' as JS; |
| 37 import 'js_module_item_order.dart'; | 37 import 'js_module_item_order.dart'; |
| 38 import 'js_names.dart'; | 38 import 'js_names.dart'; |
| 39 import 'js_printer.dart' show writeJsLibrary; | 39 import 'js_printer.dart' show writeJsLibrary; |
| 40 import 'side_effect_analysis.dart'; | 40 import 'side_effect_analysis.dart'; |
| 41 import 'package:collection/equality.dart'; | |
| 42 | 41 |
| 43 // Various dynamic helpers we call. | 42 // Various dynamic helpers we call. |
| 44 // If renaming these, make sure to check other places like the | 43 // If renaming these, make sure to check other places like the |
| 45 // _runtime.js file and comments. | 44 // _runtime.js file and comments. |
| 46 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can | 45 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can |
| 47 // import and generate calls to, rather than dart_runtime.js | 46 // import and generate calls to, rather than dart_runtime.js |
| 48 const DPUT = 'dput'; | 47 const DPUT = 'dput'; |
| 49 const DLOAD = 'dload'; | 48 const DLOAD = 'dload'; |
| 50 const DINDEX = 'dindex'; | 49 const DINDEX = 'dindex'; |
| 51 const DSETINDEX = 'dsetindex'; | 50 const DSETINDEX = 'dsetindex'; |
| 52 const DCALL = 'dcall'; | 51 const DCALL = 'dcall'; |
| 53 const DSEND = 'dsend'; | 52 const DSEND = 'dsend'; |
| 54 | 53 |
| 55 const ListEquality _listEquality = const ListEquality(); | |
| 56 | |
| 57 class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator { | 54 class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator { |
| 58 final AbstractCompiler compiler; | 55 final AbstractCompiler compiler; |
| 59 final CodegenOptions options; | 56 final CodegenOptions options; |
| 60 final TypeRules rules; | 57 final TypeRules rules; |
| 61 final LibraryElement currentLibrary; | 58 final LibraryElement currentLibrary; |
| 62 | 59 |
| 63 /// The global extension type table. | 60 /// The global extension type table. |
| 64 final HashSet<ClassElement> _extensionTypes; | 61 final HashSet<ClassElement> _extensionTypes; |
| 65 | 62 |
| 66 /// Information that is precomputed for this library, indicates which fields | 63 /// Information that is precomputed for this library, indicates which fields |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 87 final _privateNames = new HashMap<String, JS.TemporaryId>(); | 84 final _privateNames = new HashMap<String, JS.TemporaryId>(); |
| 88 final _moduleItems = <JS.Statement>[]; | 85 final _moduleItems = <JS.Statement>[]; |
| 89 final _temps = new HashMap<Element, JS.TemporaryId>(); | 86 final _temps = new HashMap<Element, JS.TemporaryId>(); |
| 90 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>(); | 87 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>(); |
| 91 | 88 |
| 92 /// The name for the library's exports inside itself. | 89 /// The name for the library's exports inside itself. |
| 93 /// `exports` was chosen as the most similar to ES module patterns. | 90 /// `exports` was chosen as the most similar to ES module patterns. |
| 94 final _dartxVar = new JS.Identifier('dartx'); | 91 final _dartxVar = new JS.Identifier('dartx'); |
| 95 final _exportsVar = new JS.TemporaryId('exports'); | 92 final _exportsVar = new JS.TemporaryId('exports'); |
| 96 final _runtimeLibVar = new JS.Identifier('dart'); | 93 final _runtimeLibVar = new JS.Identifier('dart'); |
| 94 final _utilsLibVar = new JS.TemporaryId('utils'); | |
| 95 final _classesLibVar = new JS.TemporaryId('classes'); | |
| 96 final _rttiLibVar = new JS.TemporaryId('rtti'); | |
| 97 final _namedArgTemp = new JS.TemporaryId('opts'); | 97 final _namedArgTemp = new JS.TemporaryId('opts'); |
| 98 | 98 |
| 99 final TypeProvider _types; | 99 final TypeProvider _types; |
| 100 | 100 |
| 101 ConstFieldVisitor _constField; | 101 ConstFieldVisitor _constField; |
| 102 | 102 |
| 103 ModuleItemLoadOrder _loader; | 103 ModuleItemLoadOrder _loader; |
| 104 | 104 |
| 105 /// _interceptors.JSArray<E>, used for List literals. | 105 /// _interceptors.JSArray<E>, used for List literals. |
| 106 ClassElement _jsArray; | 106 ClassElement _jsArray; |
| 107 | 107 |
| 108 /// The default value of the module object. See [visitLibraryDirective]. | 108 /// The default value of the module object. See [visitLibraryDirective]. |
| 109 String _jsModuleValue; | 109 String _jsModuleValue; |
| 110 | 110 |
| 111 bool _isDartUtils; | 111 bool _isDartRuntime; |
| 112 | 112 |
| 113 Map<String, DartType> _objectMembers; | 113 Map<String, DartType> _objectMembers; |
| 114 | 114 |
| 115 JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary, | 115 JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary, |
| 116 this._extensionTypes, this._fieldsNeedingStorage) | 116 this._extensionTypes, this._fieldsNeedingStorage) |
| 117 : compiler = compiler, | 117 : compiler = compiler, |
| 118 options = compiler.options.codegenOptions, | 118 options = compiler.options.codegenOptions, |
| 119 _types = compiler.context.typeProvider { | 119 _types = compiler.context.typeProvider { |
| 120 _loader = new ModuleItemLoadOrder(_emitModuleItem); | 120 _loader = new ModuleItemLoadOrder(_emitModuleItem); |
| 121 | 121 |
| 122 var context = compiler.context; | 122 var context = compiler.context; |
| 123 var src = context.sourceFactory.forUri('dart:_interceptors'); | 123 var src = context.sourceFactory.forUri('dart:_interceptors'); |
| 124 var interceptors = context.computeLibraryElement(src); | 124 var interceptors = context.computeLibraryElement(src); |
| 125 _jsArray = interceptors.getType('JSArray'); | 125 _jsArray = interceptors.getType('JSArray'); |
| 126 _isDartUtils = currentLibrary.source.uri.toString() == 'dart:_utils'; | 126 |
| 127 _isDartRuntime = _runtimeLibUris.contains(_getLibUri(currentLibrary)); | |
| 127 | 128 |
| 128 _objectMembers = getObjectMemberMap(types); | 129 _objectMembers = getObjectMemberMap(types); |
| 129 } | 130 } |
| 131 String _getLibUri(LibraryElement lib) => lib.source.uri.toString(); | |
| 132 | |
| 133 static final _runtimeLibUris = new Set<String>.from([ | |
|
Jennifer Messerly
2016/01/07 20:18:04
ideally we wouldn't need to hard code these, or ge
ochafik
2016/01/13 13:13:20
Dropped this but kept _isDartRuntime (testing on d
| |
| 134 'dart:_utils', | |
| 135 'dart:_runtime', | |
| 136 'dart:_operations', | |
| 137 'dart:_errors', | |
| 138 'dart:_classes', | |
| 139 'dart:_generators', | |
| 140 'dart:_operations', | |
| 141 'dart:_types', | |
| 142 'dart:_rtti' | |
| 143 ]); | |
| 130 | 144 |
| 131 TypeProvider get types => rules.provider; | 145 TypeProvider get types => rules.provider; |
| 132 | 146 |
| 133 JS.Program emitLibrary(LibraryUnit library) { | 147 JS.Program emitLibrary(LibraryUnit library) { |
| 134 // Modify the AST to make coercions explicit. | 148 // Modify the AST to make coercions explicit. |
| 135 new CoercionReifier(library, rules).reify(); | 149 new CoercionReifier(library, rules).reify(); |
| 136 | 150 |
| 137 // Build the public namespace for this library. This allows us to do | 151 // Build the public namespace for this library. This allows us to do |
| 138 // constant time lookups (contrast with `Element.getChild(name)`). | 152 // constant time lookups (contrast with `Element.getChild(name)`). |
| 139 if (currentLibrary.publicNamespace == null) { | 153 if (currentLibrary.publicNamespace == null) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 189 // TODO(jmesserly): make these immutable in JS? | 203 // TODO(jmesserly): make these immutable in JS? |
| 190 for (var name in _exports) { | 204 for (var name in _exports) { |
| 191 _moduleItems.add(js.statement('#.# = #;', [_exportsVar, name, name])); | 205 _moduleItems.add(js.statement('#.# = #;', [_exportsVar, name, name])); |
| 192 } | 206 } |
| 193 | 207 |
| 194 var jsPath = compiler.getModuleName(currentLibrary.source.uri); | 208 var jsPath = compiler.getModuleName(currentLibrary.source.uri); |
| 195 | 209 |
| 196 // TODO(jmesserly): it would be great to run the renamer on the body, | 210 // TODO(jmesserly): it would be great to run the renamer on the body, |
| 197 // then figure out if we really need each of these parameters. | 211 // then figure out if we really need each of these parameters. |
| 198 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34 | 212 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34 |
| 199 var params = [_exportsVar, _runtimeLibVar]; | 213 var params = [_exportsVar]; |
| 200 var processImport = | 214 var lazyParams = []; |
| 201 (LibraryElement library, JS.TemporaryId temp, List list) { | |
| 202 params.add(temp); | |
| 203 list.add(js.string(compiler.getModuleName(library.source.uri), "'")); | |
| 204 }; | |
| 205 | 215 |
| 206 var needsDartRuntime = !_isDartUtils; | 216 var libUri = _getLibUri(currentLibrary); |
| 207 | 217 |
| 208 var imports = <JS.Expression>[]; | 218 var imports = <JS.Expression>[]; |
| 219 var lazyImports = <JS.Expression>[]; | |
| 209 var moduleStatements = <JS.Statement>[]; | 220 var moduleStatements = <JS.Statement>[]; |
| 210 if (needsDartRuntime) { | 221 |
| 211 imports.add(js.string('dart/_runtime')); | 222 addImport(String name, JS.Expression libVar, {bool eager: true}) { |
| 223 (eager ? imports : lazyImports).add(js.string(name, "'")); | |
| 224 (eager ? params : lazyParams).add(libVar); | |
| 225 } | |
| 226 | |
| 227 if (!_isDartRuntime) { | |
| 228 addImport('dart/_runtime', _runtimeLibVar); | |
|
Jennifer Messerly
2016/01/07 20:18:04
can we just import this library explicitly?
/
ochafik
2016/01/13 13:13:20
That's mainly for the "mere mortal" files
| |
| 212 | 229 |
| 213 var dartxImport = | 230 var dartxImport = |
| 214 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); | 231 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); |
| 215 moduleStatements.add(dartxImport); | 232 moduleStatements.add(dartxImport); |
| 233 } else { | |
| 234 if (libUri == 'dart:_generators') { | |
| 235 addImport('dart/_classes', _classesLibVar); | |
|
Jennifer Messerly
2016/01/07 20:18:04
same here, can we import this explicitly?
ochafik
2016/01/13 13:13:20
Dropped now that all runtime is in dart:_runtime
| |
| 236 } | |
| 216 } | 237 } |
| 217 moduleStatements.addAll(_moduleItems); | 238 moduleStatements.addAll(_moduleItems); |
| 218 | 239 |
| 219 _imports.forEach((library, temp) { | 240 bool shouldImportEagerly(lib) { |
| 220 if (_loader.libraryIsLoaded(library)) { | 241 var otherLibUri = _getLibUri(lib); |
| 221 processImport(library, temp, imports); | 242 |
| 222 } | 243 // utils.dart contains very low-level utils and doesn't import anyone. |
| 244 if (otherLibUri == 'dart:_utils') return true; | |
|
Jennifer Messerly
2016/01/07 20:18:05
can we just add these cases to the existing coreli
ochafik
2016/01/13 13:13:20
Ack
| |
| 245 // Types in types.dart extend rtti.LazyTagged in a way that isn't | |
| 246 // recognized by the loader: we help it out here. | |
|
Jennifer Messerly
2016/01/07 20:18:04
can you explain the problem with this? I'm not fol
ochafik
2016/01/13 13:13:20
Dropped special logic
| |
| 247 if (libUri == 'dart:_types' && otherLibUri == 'dart:_rtti') return true; | |
| 248 if (libUri == 'dart:_runtime') return otherLibUri != 'dart:_js_helper'; | |
| 249 // runtime.dart needs to import everything but utils.dart lazily. | |
| 250 if (_isDartRuntime) return false; | |
| 251 | |
| 252 return _loader.libraryIsLoaded(lib); | |
| 253 } | |
| 254 | |
| 255 var importsEagerness = new Map<LibraryElement, bool>.fromIterable( | |
| 256 _imports.keys, | |
| 257 value: shouldImportEagerly); | |
| 258 | |
| 259 _imports.forEach((LibraryElement lib, JS.TemporaryId temp) { | |
| 260 bool eager = importsEagerness[lib]; | |
| 261 addImport(compiler.getModuleName(lib.source.uri), temp, eager: eager); | |
| 223 }); | 262 }); |
| 224 | 263 |
| 225 var lazyImports = <JS.Expression>[]; | 264 params.addAll(lazyParams); |
| 226 _imports.forEach((library, temp) { | |
| 227 if (!_loader.libraryIsLoaded(library)) { | |
| 228 processImport(library, temp, lazyImports); | |
| 229 } | |
| 230 }); | |
| 231 | 265 |
| 232 var module = | 266 var module = |
| 233 js.call("function(#) { 'use strict'; #; }", [params, moduleStatements]); | 267 js.call("function(#) { 'use strict'; #; }", [params, moduleStatements]); |
| 234 | 268 |
| 235 var moduleDef = js.statement("dart_library.library(#, #, #, #, #)", [ | 269 var moduleDef = js.statement("dart_library.library(#, #, #, #, #)", [ |
| 236 js.string(jsPath, "'"), | 270 js.string(jsPath, "'"), |
| 237 _jsModuleValue ?? new JS.LiteralNull(), | 271 _jsModuleValue ?? new JS.LiteralNull(), |
| 238 js.commentExpression( | 272 js.commentExpression( |
| 239 "Imports", new JS.ArrayInitializer(imports, multiline: true)), | 273 "Imports", new JS.ArrayInitializer(imports, multiline: true)), |
| 240 js.commentExpression("Lazy imports", | 274 js.commentExpression("Lazy imports", |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 257 if (node is! FunctionDeclaration) _flushLibraryProperties(_moduleItems); | 291 if (node is! FunctionDeclaration) _flushLibraryProperties(_moduleItems); |
| 258 | 292 |
| 259 var code = _visit(node); | 293 var code = _visit(node); |
| 260 if (code != null) _moduleItems.add(code); | 294 if (code != null) _moduleItems.add(code); |
| 261 } | 295 } |
| 262 | 296 |
| 263 @override | 297 @override |
| 264 void visitLibraryDirective(LibraryDirective node) { | 298 void visitLibraryDirective(LibraryDirective node) { |
| 265 assert(_jsModuleValue == null); | 299 assert(_jsModuleValue == null); |
| 266 | 300 |
| 267 var jsName = findAnnotation(node.element, isJSAnnotation); | 301 _jsModuleValue = _getJsName(node.element); |
| 268 _jsModuleValue = | 302 } |
| 269 getConstantField(jsName, 'name', types.stringType)?.toStringValue(); | 303 |
| 304 String _getJsName(Element e) { | |
|
Jennifer Messerly
2016/01/07 20:18:04
I'm a little confused about this function. It coul
ochafik
2016/01/13 13:13:20
Spun this out in https://codereview.chromium.org/1
| |
| 305 var jsName = findAnnotation(e, isJSAnnotation); | |
| 306 return getConstantField(jsName, 'name', types.stringType)?.toStringValue(); | |
| 270 } | 307 } |
| 271 | 308 |
| 272 @override | 309 @override |
| 273 void visitImportDirective(ImportDirective node) { | 310 void visitImportDirective(ImportDirective node) { |
| 274 // Nothing to do yet, but we'll want to convert this to an ES6 import once | 311 // Nothing to do yet, but we'll want to convert this to an ES6 import once |
| 275 // we have support for modules. | 312 // we have support for modules. |
| 276 } | 313 } |
| 277 | 314 |
| 278 @override void visitPartDirective(PartDirective node) {} | 315 @override void visitPartDirective(PartDirective node) {} |
| 279 @override void visitPartOfDirective(PartOfDirective node) {} | 316 @override void visitPartOfDirective(PartOfDirective node) {} |
| 280 | 317 |
| 281 @override | 318 @override |
| 282 void visitExportDirective(ExportDirective node) { | 319 void visitExportDirective(ExportDirective node) { |
| 283 var exportName = _libraryName(node.uriElement); | 320 var exportName = _libraryName(node.uriElement); |
| 284 | 321 |
| 285 var currentLibNames = currentLibrary.publicNamespace.definedNames; | 322 var currentLibNames = currentLibrary.publicNamespace.definedNames; |
| 286 | 323 |
| 287 var args = [_exportsVar, exportName]; | 324 var args = [_exportsVar, exportName]; |
| 288 if (node.combinators.isNotEmpty) { | 325 if (node.combinators.isNotEmpty) { |
| 289 var shownNames = <JS.Expression>[]; | 326 var shownNames = <JS.Expression>[]; |
| 290 var hiddenNames = <JS.Expression>[]; | 327 var hiddenNames = <JS.Expression>[]; |
| 291 | 328 |
| 292 var show = node.combinators.firstWhere((c) => c is ShowCombinator, | 329 var show = node.combinators.firstWhere((c) => c is ShowCombinator, |
| 293 orElse: () => null) as ShowCombinator; | 330 orElse: () => null) as ShowCombinator; |
| 294 var hide = node.combinators.firstWhere((c) => c is HideCombinator, | 331 var hide = node.combinators.firstWhere((c) => c is HideCombinator, |
| 295 orElse: () => null) as HideCombinator; | 332 orElse: () => null) as HideCombinator; |
| 296 if (show != null) { | 333 if (show != null) { |
| 334 // If the import has a single shown name + a JsName(jsName) annotation, | |
| 335 // then we use that jsName as the exported name. | |
| 336 var singleJsName = _getJsName(node.element); | |
| 337 if (singleJsName != null && show.shownNames.length != 1) { | |
| 338 throw new StateError('Cannot set js name on more than one export'); | |
|
Jennifer Messerly
2016/01/07 20:18:04
Can this error be triggered by user code?
If so,
ochafik
2016/01/13 13:13:20
Dropped that (no need to re-export anymore with th
| |
| 339 } | |
| 297 shownNames.addAll(show.shownNames | 340 shownNames.addAll(show.shownNames |
| 298 .map((i) => i.name) | 341 .map((i) => singleJsName ?? i.name) |
| 299 .where((s) => !currentLibNames.containsKey(s)) | 342 .where((s) => !currentLibNames.containsKey(s)) |
| 300 .map((s) => js.string(s, "'"))); | 343 .map((s) => js.string(s, "'"))); |
| 301 } | 344 } |
| 302 if (hide != null) { | 345 if (hide != null) { |
| 303 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); | 346 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); |
| 304 } | 347 } |
| 305 args.add(new JS.ArrayInitializer(shownNames)); | 348 args.add(new JS.ArrayInitializer(shownNames)); |
| 306 args.add(new JS.ArrayInitializer(hiddenNames)); | 349 args.add(new JS.ArrayInitializer(hiddenNames)); |
| 307 } | 350 } |
| 308 _moduleItems.add(js.statement('dart.export_(#);', [args])); | 351 |
| 352 // When we compile _runtime.js, we need to source export_ from _utils.js: | |
| 353 _moduleItems.add(js.statement('#(#);', [_dartExport, args])); | |
| 309 } | 354 } |
| 310 | 355 |
| 311 JS.Identifier _initSymbol(JS.Identifier id) { | 356 JS.Identifier _initSymbol(JS.Identifier id) { |
| 312 var s = | 357 var s = |
| 313 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); | 358 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); |
| 314 _moduleItems.add(s); | 359 _moduleItems.add(s); |
| 315 return id; | 360 return id; |
| 316 } | 361 } |
| 317 | 362 |
| 318 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, | 363 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 572 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); | 617 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); |
| 573 } | 618 } |
| 574 return body; | 619 return body; |
| 575 } | 620 } |
| 576 | 621 |
| 577 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { | 622 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { |
| 578 var name = type.name; | 623 var name = type.name; |
| 579 var genericName = '$name\$'; | 624 var genericName = '$name\$'; |
| 580 var typeParams = type.typeParameters.map((p) => p.name); | 625 var typeParams = type.typeParameters.map((p) => p.name); |
| 581 if (isPublic(name)) _exports.add(genericName); | 626 if (isPublic(name)) _exports.add(genericName); |
| 582 return js.statement('const # = dart.generic(function(#) { #; return #; });', | 627 |
| 583 [genericName, typeParams, body, name]); | 628 return js.statement('const # = #(function(#) { #; return #; });', |
| 629 [genericName, _dartGeneric, typeParams, body, name]); | |
| 584 } | 630 } |
| 585 | 631 |
| 632 get _dartGeneric => | |
| 633 js.call('#.generic', [_isDartRuntime ? _classesLibVar : _runtimeLibVar]); | |
|
Jennifer Messerly
2016/01/07 20:18:05
I made this comment elsewhere, but I don't think w
ochafik
2016/01/13 13:13:20
Parts FTW!
| |
| 634 | |
| 635 get _dartExport => | |
| 636 js.call('#.export', [_isDartRuntime ? _utilsLibVar : _runtimeLibVar]); | |
| 637 | |
| 638 get _dartFn => js.call('#.fn', _isDartRuntime ? _rttiLibVar : _runtimeLibVar); | |
| 639 | |
| 640 get _dartSetSignature => js.call( | |
| 641 '#.setSignature', [_isDartRuntime ? _classesLibVar : _runtimeLibVar]); | |
| 642 | |
| 586 final _hasDeferredSupertype = new HashSet<ClassElement>(); | 643 final _hasDeferredSupertype = new HashSet<ClassElement>(); |
| 587 | 644 |
| 588 bool _deferIfNeeded(DartType type, ClassElement current) { | 645 bool _deferIfNeeded(DartType type, ClassElement current) { |
| 589 if (type is ParameterizedType) { | 646 if (type is ParameterizedType) { |
| 590 var typeArguments = type.typeArguments; | 647 var typeArguments = type.typeArguments; |
| 591 for (var typeArg in typeArguments) { | 648 for (var typeArg in typeArguments) { |
| 592 var typeElement = typeArg.element; | 649 var typeElement = typeArg.element; |
| 593 // FIXME(vsm): This does not track mutual recursive dependences. | 650 // FIXME(vsm): This does not track mutual recursive dependences. |
| 594 if (current == typeElement || _deferIfNeeded(typeArg, current)) { | 651 if (current == typeElement || _deferIfNeeded(typeArg, current)) { |
| 595 return true; | 652 return true; |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 825 if (!tStatics.isEmpty) { | 882 if (!tStatics.isEmpty) { |
| 826 assert(!sNames.isEmpty); | 883 assert(!sNames.isEmpty); |
| 827 var aNames = new JS.Property( | 884 var aNames = new JS.Property( |
| 828 _propertyName('names'), new JS.ArrayInitializer(sNames)); | 885 _propertyName('names'), new JS.ArrayInitializer(sNames)); |
| 829 sigFields.add(build('statics', tStatics)); | 886 sigFields.add(build('statics', tStatics)); |
| 830 sigFields.add(aNames); | 887 sigFields.add(aNames); |
| 831 } | 888 } |
| 832 if (!sigFields.isEmpty || extensions.isNotEmpty) { | 889 if (!sigFields.isEmpty || extensions.isNotEmpty) { |
| 833 var sig = new JS.ObjectInitializer(sigFields); | 890 var sig = new JS.ObjectInitializer(sigFields); |
| 834 var classExpr = new JS.Identifier(name); | 891 var classExpr = new JS.Identifier(name); |
| 835 body.add(js.statement('dart.setSignature(#, #);', [classExpr, sig])); | 892 body.add(js.statement('#(#, #);', [_dartSetSignature, classExpr, sig])); |
| 836 } | 893 } |
| 837 } | 894 } |
| 838 | 895 |
| 839 // If a concrete class implements one of our extensions, we might need to | 896 // If a concrete class implements one of our extensions, we might need to |
| 840 // add forwarders. | 897 // add forwarders. |
| 841 if (extensions.isNotEmpty) { | 898 if (extensions.isNotEmpty) { |
| 842 var methodNames = <JS.Expression>[]; | 899 var methodNames = <JS.Expression>[]; |
| 843 for (var e in extensions) { | 900 for (var e in extensions) { |
| 844 methodNames.add(_elementMemberName(e)); | 901 methodNames.add(_elementMemberName(e)); |
| 845 } | 902 } |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1298 | 1355 |
| 1299 if (node.isGetter || node.isSetter) { | 1356 if (node.isGetter || node.isSetter) { |
| 1300 // Add these later so we can use getter/setter syntax. | 1357 // Add these later so we can use getter/setter syntax. |
| 1301 _properties.add(node); | 1358 _properties.add(node); |
| 1302 return null; | 1359 return null; |
| 1303 } | 1360 } |
| 1304 | 1361 |
| 1305 var body = <JS.Statement>[]; | 1362 var body = <JS.Statement>[]; |
| 1306 _flushLibraryProperties(body); | 1363 _flushLibraryProperties(body); |
| 1307 | 1364 |
| 1308 var name = node.name.name; | 1365 var name = _getJsName(node.element) ?? node.name.name; |
| 1309 | 1366 |
| 1310 var fn = _visit(node.functionExpression); | 1367 var fn = _visit(node.functionExpression); |
| 1311 bool needsTagging = true; | 1368 // Don't tag functions defined in the low-level runtime. |
| 1369 bool needsTagging = !_isDartRuntime; | |
| 1312 | 1370 |
| 1313 if (currentLibrary.source.isInSystemLibrary && | 1371 if (currentLibrary.source.isInSystemLibrary && |
| 1314 _isInlineJSFunction(node.functionExpression)) { | 1372 _isInlineJSFunction(node.functionExpression)) { |
| 1315 fn = _simplifyPassThroughArrowFunCallBody(fn); | 1373 fn = _simplifyPassThroughArrowFunCallBody(fn); |
| 1316 needsTagging = !_isDartUtils; | |
| 1317 } | 1374 } |
| 1318 | 1375 |
| 1319 var id = new JS.Identifier(name); | 1376 var id = new JS.Identifier(name); |
| 1320 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element)); | 1377 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element)); |
| 1321 if (needsTagging) { | 1378 if (needsTagging) { |
| 1322 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) | 1379 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) |
| 1323 .toStatement()); | 1380 .toStatement()); |
| 1324 } | 1381 } |
| 1325 | 1382 |
| 1326 if (isPublic(name)) _addExport(name); | 1383 if (isPublic(name)) _addExport(name); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1338 return _isJSInvocation(stat.expression); | 1395 return _isJSInvocation(stat.expression); |
| 1339 } | 1396 } |
| 1340 } | 1397 } |
| 1341 } | 1398 } |
| 1342 return false; | 1399 return false; |
| 1343 } | 1400 } |
| 1344 | 1401 |
| 1345 bool _isJSInvocation(Expression expr) => | 1402 bool _isJSInvocation(Expression expr) => |
| 1346 expr is MethodInvocation && isInlineJS(expr.methodName.staticElement); | 1403 expr is MethodInvocation && isInlineJS(expr.methodName.staticElement); |
| 1347 | 1404 |
| 1348 // Simplify `(args) => ((x, y) => { ... })(x, y)` to `(args) => { ... }`. | 1405 // Simplify `(args) => (() => { ... })()` to `(args) => { ... }`. |
| 1349 // Note: we don't check if the top-level args match the ones passed through | 1406 // Note: this allows silently passing args through to the body, which only |
|
Jennifer Messerly
2016/01/07 20:18:05
I don't think you need the "Note" anymore?
ochafik
2016/01/13 13:13:20
Done.
| |
| 1350 // the arrow function, which allows silently passing args through to the | 1407 // works if we don't do weird renamings of Dart params. |
| 1351 // body (which only works if we don't do weird renamings of Dart params). | |
| 1352 JS.Fun _simplifyPassThroughArrowFunCallBody(JS.Fun fn) { | 1408 JS.Fun _simplifyPassThroughArrowFunCallBody(JS.Fun fn) { |
| 1353 String getIdent(JS.Node node) => node is JS.Identifier ? node.name : null; | |
| 1354 List<String> getIdents(List params) => | |
| 1355 params.map(getIdent).toList(growable: false); | |
| 1356 | |
| 1357 if (fn.body is JS.Block && fn.body.statements.length == 1) { | 1409 if (fn.body is JS.Block && fn.body.statements.length == 1) { |
| 1358 var stat = fn.body.statements.single; | 1410 var stat = fn.body.statements.single; |
| 1359 if (stat is JS.Return && stat.value is JS.Call) { | 1411 if (stat is JS.Return && stat.value is JS.Call) { |
| 1360 JS.Call call = stat.value; | 1412 JS.Call call = stat.value; |
| 1361 if (call.target is JS.ArrowFun) { | 1413 if (call.target is JS.ArrowFun && call.arguments.isEmpty) { |
| 1362 var passedArgs = getIdents(call.arguments); | |
| 1363 JS.ArrowFun innerFun = call.target; | 1414 JS.ArrowFun innerFun = call.target; |
| 1364 if (_listEquality.equals(getIdents(innerFun.params), passedArgs)) { | 1415 if (innerFun.params.isEmpty) { |
| 1365 return new JS.Fun(fn.params, innerFun.body); | 1416 return new JS.Fun(fn.params, innerFun.body); |
| 1366 } | 1417 } |
| 1367 } | 1418 } |
| 1368 } | 1419 } |
| 1369 } | 1420 } |
| 1370 return fn; | 1421 return fn; |
| 1371 } | 1422 } |
| 1372 | 1423 |
| 1373 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { | 1424 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { |
| 1374 var name = node.name.name; | 1425 var name = node.name.name; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1402 JS.Expression _emitFunctionTagged(JS.Expression clos, DartType type, | 1453 JS.Expression _emitFunctionTagged(JS.Expression clos, DartType type, |
| 1403 {topLevel: false}) { | 1454 {topLevel: false}) { |
| 1404 var name = type.name; | 1455 var name = type.name; |
| 1405 var lazy = topLevel && !_typeIsLoaded(type); | 1456 var lazy = topLevel && !_typeIsLoaded(type); |
| 1406 | 1457 |
| 1407 if (type is FunctionType && (name == '' || name == null)) { | 1458 if (type is FunctionType && (name == '' || name == null)) { |
| 1408 if (type.returnType.isDynamic && | 1459 if (type.returnType.isDynamic && |
| 1409 type.optionalParameterTypes.isEmpty && | 1460 type.optionalParameterTypes.isEmpty && |
| 1410 type.namedParameterTypes.isEmpty && | 1461 type.namedParameterTypes.isEmpty && |
| 1411 type.normalParameterTypes.every((t) => t.isDynamic)) { | 1462 type.normalParameterTypes.every((t) => t.isDynamic)) { |
| 1412 return js.call('dart.fn(#)', [clos]); | 1463 return js.call('#(#)', [_dartFn, clos]); |
| 1413 } | 1464 } |
| 1414 if (lazy) { | 1465 if (lazy) { |
| 1415 return js.call('dart.fn(#, () => #)', [clos, _emitFunctionRTTI(type)]); | 1466 return js.call( |
| 1467 '#(#, () => #)', [_dartFn, clos, _emitFunctionRTTI(type)]); | |
| 1416 } | 1468 } |
| 1417 return js.call('dart.fn(#, #)', [clos, _emitFunctionTypeParts(type)]); | 1469 return js.call('#(#, #)', [_dartFn, clos, _emitFunctionTypeParts(type)]); |
| 1418 } | 1470 } |
| 1419 throw 'Function has non function type: $type'; | 1471 throw 'Function has non function type: $type'; |
| 1420 } | 1472 } |
| 1421 | 1473 |
| 1422 @override | 1474 @override |
| 1423 JS.Expression visitFunctionExpression(FunctionExpression node) { | 1475 JS.Expression visitFunctionExpression(FunctionExpression node) { |
| 1424 var params = _visit(node.parameters) as List<JS.Parameter>; | 1476 var params = _visit(node.parameters) as List<JS.Parameter>; |
| 1425 if (params == null) params = <JS.Parameter>[]; | 1477 if (params == null) params = <JS.Parameter>[]; |
| 1426 | 1478 |
| 1427 var parent = node.parent; | 1479 var parent = node.parent; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1562 'Unimplemented unknown name', new JS.Identifier(node.name)); | 1614 'Unimplemented unknown name', new JS.Identifier(node.name)); |
| 1563 } | 1615 } |
| 1564 | 1616 |
| 1565 // Get the original declaring element. If we had a property accessor, this | 1617 // Get the original declaring element. If we had a property accessor, this |
| 1566 // indirects back to a (possibly synthetic) field. | 1618 // indirects back to a (possibly synthetic) field. |
| 1567 var element = accessor; | 1619 var element = accessor; |
| 1568 if (accessor is PropertyAccessorElement) element = accessor.variable; | 1620 if (accessor is PropertyAccessorElement) element = accessor.variable; |
| 1569 | 1621 |
| 1570 _loader.declareBeforeUse(element); | 1622 _loader.declareBeforeUse(element); |
| 1571 | 1623 |
| 1572 var name = element.name; | 1624 var name = _getJsName(element) ?? element.name; |
|
Jennifer Messerly
2016/01/07 20:18:04
This is related to my other comment on _getJsName,
ochafik
2016/01/13 13:13:20
Moved the exported name resolution logic to down t
| |
| 1573 | 1625 |
| 1574 // type literal | 1626 // type literal |
| 1575 if (element is ClassElement || | 1627 if (element is ClassElement || |
| 1576 element is DynamicElementImpl || | 1628 element is DynamicElementImpl || |
| 1577 element is FunctionTypeAliasElement) { | 1629 element is FunctionTypeAliasElement) { |
| 1578 return _emitTypeName( | 1630 return _emitTypeName( |
| 1579 fillDynamicTypeArgs((element as dynamic).type, types)); | 1631 fillDynamicTypeArgs((element as dynamic).type, types)); |
| 1580 } | 1632 } |
| 1581 | 1633 |
| 1582 // library member | 1634 // library member |
| 1583 if (element.enclosingElement is CompilationUnitElement) { | 1635 if (element.enclosingElement is CompilationUnitElement) { |
| 1584 return _maybeQualifiedName(element); | 1636 return _maybeQualifiedName(element, name); |
| 1585 } | 1637 } |
| 1586 | 1638 |
| 1587 // Unqualified class member. This could mean implicit-this, or implicit | 1639 // Unqualified class member. This could mean implicit-this, or implicit |
| 1588 // call to a static from the same class. | 1640 // call to a static from the same class. |
| 1589 if (element is ClassMemberElement && element is! ConstructorElement) { | 1641 if (element is ClassMemberElement && element is! ConstructorElement) { |
| 1590 bool isStatic = element.isStatic; | 1642 bool isStatic = element.isStatic; |
| 1591 var type = element.enclosingElement.type; | 1643 var type = element.enclosingElement.type; |
| 1592 var member = _emitMemberName(name, isStatic: isStatic, type: type); | 1644 var member = _emitMemberName(name, isStatic: isStatic, type: type); |
| 1593 | 1645 |
| 1594 // For static methods, we add the raw type name, without generics or | 1646 // For static methods, we add the raw type name, without generics or |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1877 var stmts = _visitList(node.block.statements) as List<JS.Statement>; | 1929 var stmts = _visitList(node.block.statements) as List<JS.Statement>; |
| 1878 if (initArgs != null) stmts.insert(0, initArgs); | 1930 if (initArgs != null) stmts.insert(0, initArgs); |
| 1879 return new JS.Block(stmts); | 1931 return new JS.Block(stmts); |
| 1880 } | 1932 } |
| 1881 | 1933 |
| 1882 @override | 1934 @override |
| 1883 JS.Block visitBlock(Block node) => | 1935 JS.Block visitBlock(Block node) => |
| 1884 new JS.Block(_visitList(node.statements) as List<JS.Statement>, | 1936 new JS.Block(_visitList(node.statements) as List<JS.Statement>, |
| 1885 isScope: true); | 1937 isScope: true); |
| 1886 | 1938 |
| 1939 /// Return the type constructor `_foolib.Bar$` given `Bar` from lib `_foolib`. | |
| 1940 /// | |
| 1941 /// This implements / expands the `genericTypeConstructor` intrinsic defined | |
| 1942 /// in `foreign_helper.dart`. | |
| 1943 JS.Expression _emitGenericTypeConstructor(Expression typeExpression) { | |
|
Jennifer Messerly
2016/01/07 20:18:04
I don't understand why this is needed. Given a typ
ochafik
2016/01/13 13:13:20
This implements the new intrinsic used in the foll
| |
| 1944 var ref = _visit(typeExpression); | |
| 1945 if (ref is JS.PropertyAccess) { | |
| 1946 var name = (ref.selector as JS.LiteralString).valueWithoutQuotes; | |
| 1947 return new JS.PropertyAccess( | |
| 1948 ref.receiver, new JS.LiteralString("'$name\$'")); | |
| 1949 } else if (ref is JS.MaybeQualifiedId) { | |
| 1950 var name = (ref.name as JS.Identifier).name; | |
| 1951 return new JS.PropertyAccess(ref.qualifier, new JS.Identifier('$name\$')); | |
| 1952 } else { | |
| 1953 throw new ArgumentError('Invalid type ref: $ref (${ref?.runtimeType})'); | |
| 1954 } | |
| 1955 } | |
| 1956 | |
| 1887 @override | 1957 @override |
| 1888 visitMethodInvocation(MethodInvocation node) { | 1958 visitMethodInvocation(MethodInvocation node) { |
| 1889 if (node.operator != null && node.operator.lexeme == '?.') { | 1959 if (node.operator != null && node.operator.lexeme == '?.') { |
| 1890 return _emitNullSafe(node); | 1960 return _emitNullSafe(node); |
| 1891 } | 1961 } |
| 1962 if (isGenericTypeConstructorInvocation(node)) { | |
| 1963 return _emitGenericTypeConstructor(node.argumentList.arguments.single); | |
|
Jennifer Messerly
2016/01/07 20:18:04
I don't understand why this case is needed. It see
ochafik
2016/01/13 13:13:20
Sorry for the lacking doc, this is a new intrinsic
| |
| 1964 } | |
| 1892 | 1965 |
| 1893 var target = _getTarget(node); | 1966 var target = _getTarget(node); |
| 1894 var result = _emitForeignJS(node); | 1967 var result = _emitForeignJS(node); |
| 1895 if (result != null) return result; | 1968 if (result != null) return result; |
| 1896 | 1969 |
| 1897 String code; | 1970 String code; |
| 1898 if (target == null || isLibraryPrefix(target)) { | 1971 if (target == null || isLibraryPrefix(target)) { |
| 1899 if (DynamicInvoke.get(node.methodName)) { | 1972 if (DynamicInvoke.get(node.methodName)) { |
| 1900 code = 'dart.$DCALL(#, #)'; | 1973 code = 'dart.$DCALL(#, #)'; |
| 1901 } else { | 1974 } else { |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2207 } else { | 2280 } else { |
| 2208 jsInit = _visitInitializer(field); | 2281 jsInit = _visitInitializer(field); |
| 2209 eagerInit = false; | 2282 eagerInit = false; |
| 2210 } | 2283 } |
| 2211 | 2284 |
| 2212 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile | 2285 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile |
| 2213 // runtime helpers. | 2286 // runtime helpers. |
| 2214 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field); | 2287 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field); |
| 2215 if (isJSTopLevel) eagerInit = true; | 2288 if (isJSTopLevel) eagerInit = true; |
| 2216 | 2289 |
| 2217 var fieldName = field.name.name; | 2290 var fieldName = _getJsName(element) ?? field.name.name; |
| 2291 | |
| 2218 if ((field.isConst && eagerInit && element is TopLevelVariableElement) || | 2292 if ((field.isConst && eagerInit && element is TopLevelVariableElement) || |
| 2219 isJSTopLevel) { | 2293 isJSTopLevel) { |
| 2220 // constant fields don't change, so we can generate them as `let` | 2294 // constant fields don't change, so we can generate them as `let` |
| 2221 // but add them to the module's exports. However, make sure we generate | 2295 // but add them to the module's exports. However, make sure we generate |
| 2222 // anything they depend on first. | 2296 // anything they depend on first. |
| 2223 | 2297 |
| 2224 if (isPublic(fieldName)) _addExport(fieldName); | 2298 if (isPublic(fieldName)) _addExport(fieldName); |
| 2225 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; | 2299 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; |
| 2226 return annotateVariable( | 2300 return annotateVariable( |
| 2227 js.statement( | 2301 js.statement( |
| (...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2843 } | 2917 } |
| 2844 | 2918 |
| 2845 String code; | 2919 String code; |
| 2846 if (member != null && member is MethodElement && !isStatic) { | 2920 if (member != null && member is MethodElement && !isStatic) { |
| 2847 // Tear-off methods: explicitly bind it. | 2921 // Tear-off methods: explicitly bind it. |
| 2848 if (target is SuperExpression) { | 2922 if (target is SuperExpression) { |
| 2849 return js.call('dart.bind(this, #, #.#)', [name, _visit(target), name]); | 2923 return js.call('dart.bind(this, #, #.#)', [name, _visit(target), name]); |
| 2850 } else if (_requiresStaticDispatch(target, memberId.name)) { | 2924 } else if (_requiresStaticDispatch(target, memberId.name)) { |
| 2851 var type = member.type; | 2925 var type = member.type; |
| 2852 var clos = js.call('dart.#.bind(#)', [name, _visit(target)]); | 2926 var clos = js.call('dart.#.bind(#)', [name, _visit(target)]); |
| 2853 return js.call('dart.fn(#, #)', [clos, _emitFunctionTypeParts(type)]); | 2927 return js.call( |
| 2928 '#(#, #)', [_dartFn, clos, _emitFunctionTypeParts(type)]); | |
| 2854 } | 2929 } |
| 2855 code = 'dart.bind(#, #)'; | 2930 code = 'dart.bind(#, #)'; |
| 2856 } else if (_requiresStaticDispatch(target, memberId.name)) { | 2931 } else if (_requiresStaticDispatch(target, memberId.name)) { |
| 2857 return js.call('dart.#(#)', [name, _visit(target)]); | 2932 return js.call('dart.#(#)', [name, _visit(target)]); |
| 2858 } else { | 2933 } else { |
| 2859 code = '#.#'; | 2934 code = '#.#'; |
| 2860 } | 2935 } |
| 2861 | 2936 |
| 2862 return js.call(code, [_visit(target), name]); | 2937 return js.call(code, [_visit(target), name]); |
| 2863 } | 2938 } |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3412 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; | 3487 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; |
| 3413 | 3488 |
| 3414 FunctionBody _functionBody(node) => | 3489 FunctionBody _functionBody(node) => |
| 3415 node is FunctionDeclaration ? node.functionExpression.body : node.body; | 3490 node is FunctionDeclaration ? node.functionExpression.body : node.body; |
| 3416 | 3491 |
| 3417 /// Choose a canonical name from the library element. | 3492 /// Choose a canonical name from the library element. |
| 3418 /// This never uses the library's name (the identifier in the `library` | 3493 /// This never uses the library's name (the identifier in the `library` |
| 3419 /// declaration) as it doesn't have any meaningful rules enforced. | 3494 /// declaration) as it doesn't have any meaningful rules enforced. |
| 3420 JS.Identifier _libraryName(LibraryElement library) { | 3495 JS.Identifier _libraryName(LibraryElement library) { |
| 3421 if (library == currentLibrary) return _exportsVar; | 3496 if (library == currentLibrary) return _exportsVar; |
| 3422 return _imports.putIfAbsent( | 3497 return _imports.putIfAbsent(library, () { |
| 3423 library, () => new JS.TemporaryId(jsLibraryName(library))); | 3498 var name = library.name; |
| 3499 if (name == 'dart._utils') return _utilsLibVar; | |
|
Jennifer Messerly
2016/01/07 20:18:04
I don't think these special cases could be needed.
ochafik
2016/01/13 13:13:20
Done.
| |
| 3500 else if (name == 'dart._classes') return _classesLibVar; | |
|
Jennifer Messerly
2016/01/07 20:18:04
also, relying on the library name is super risky.
ochafik
2016/01/13 13:13:20
Acknowledged.
| |
| 3501 else if (name == 'dart._rtti') return _rttiLibVar; | |
| 3502 else return new JS.TemporaryId(jsLibraryName(library)); | |
| 3503 }); | |
| 3424 } | 3504 } |
| 3425 | 3505 |
| 3426 DartType getStaticType(Expression e) => rules.getStaticType(e); | 3506 DartType getStaticType(Expression e) => rules.getStaticType(e); |
| 3427 | 3507 |
| 3428 @override | 3508 @override |
| 3429 String getQualifiedName(TypeDefiningElement type) { | 3509 String getQualifiedName(TypeDefiningElement type) { |
| 3430 JS.TemporaryId id = _imports[type.library]; | 3510 JS.TemporaryId id = _imports[type.library]; |
| 3431 return id == null ? type.name : '${id.name}.${type.name}'; | 3511 return id == null ? type.name : '${id.name}.${type.name}'; |
| 3432 } | 3512 } |
| 3433 | 3513 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3524 | 3604 |
| 3525 /// A special kind of element created by the compiler, signifying a temporary | 3605 /// A special kind of element created by the compiler, signifying a temporary |
| 3526 /// variable. These objects use instance equality, and should be shared | 3606 /// variable. These objects use instance equality, and should be shared |
| 3527 /// everywhere in the tree where they are treated as the same variable. | 3607 /// everywhere in the tree where they are treated as the same variable. |
| 3528 class TemporaryVariableElement extends LocalVariableElementImpl { | 3608 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 3529 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3609 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 3530 | 3610 |
| 3531 int get hashCode => identityHashCode(this); | 3611 int get hashCode => identityHashCode(this); |
| 3532 bool operator ==(Object other) => identical(this, other); | 3612 bool operator ==(Object other) => identical(this, other); |
| 3533 } | 3613 } |
| OLD | NEW |