| 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 | 2 |
| 3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
| 4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
| 5 | 5 |
| 6 import 'dart:collection' show HashMap, HashSet; | 6 import 'dart:collection' show HashMap, HashSet; |
| 7 import 'dart:math' show min, max; | 7 import 'dart:math' show min, max; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 /// In an async* function, this represents the stream controller parameter. | 111 /// In an async* function, this represents the stream controller parameter. |
| 112 JS.TemporaryId _asyncStarController; | 112 JS.TemporaryId _asyncStarController; |
| 113 | 113 |
| 114 // TODO(jmesserly): fuse this with notNull check. | 114 // TODO(jmesserly): fuse this with notNull check. |
| 115 final _privateNames = | 115 final _privateNames = |
| 116 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); | 116 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); |
| 117 final _initializingFormalTemps = | 117 final _initializingFormalTemps = |
| 118 new HashMap<ParameterElement, JS.TemporaryId>(); | 118 new HashMap<ParameterElement, JS.TemporaryId>(); |
| 119 | 119 |
| 120 JS.Identifier _extensionSymbolsModule; | 120 JS.Identifier _extensionSymbolsModule; |
| 121 final _extensionSymbols = new Map<String, JS.TemporaryId>(); |
| 122 |
| 121 JS.Identifier _runtimeModule; | 123 JS.Identifier _runtimeModule; |
| 122 final namedArgumentTemp = new JS.TemporaryId('opts'); | 124 final namedArgumentTemp = new JS.TemporaryId('opts'); |
| 123 | 125 |
| 124 final _hasDeferredSupertype = new HashSet<ClassElement>(); | 126 final _hasDeferredSupertype = new HashSet<ClassElement>(); |
| 125 | 127 |
| 126 /// The type provider from the current Analysis [context]. | 128 /// The type provider from the current Analysis [context]. |
| 127 final TypeProvider types; | 129 final TypeProvider types; |
| 128 | 130 |
| 129 final LibraryElement dartCoreLibrary; | 131 final LibraryElement dartCoreLibrary; |
| 130 final LibraryElement dartJSLibrary; | 132 final LibraryElement dartJSLibrary; |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 _extensionSymbolsModule = new JS.Identifier('dartx'); | 313 _extensionSymbolsModule = new JS.Identifier('dartx'); |
| 312 } else { | 314 } else { |
| 313 // Otherwise allow these to be renamed so users can write them. | 315 // Otherwise allow these to be renamed so users can write them. |
| 314 _runtimeModule = new JS.TemporaryId('dart'); | 316 _runtimeModule = new JS.TemporaryId('dart'); |
| 315 _extensionSymbolsModule = new JS.TemporaryId('dartx'); | 317 _extensionSymbolsModule = new JS.TemporaryId('dartx'); |
| 316 } | 318 } |
| 317 _typeTable = new TypeTable(_runtimeModule); | 319 _typeTable = new TypeTable(_runtimeModule); |
| 318 | 320 |
| 319 // Initialize our library variables. | 321 // Initialize our library variables. |
| 320 var items = <JS.ModuleItem>[]; | 322 var items = <JS.ModuleItem>[]; |
| 323 var isBuildingSdk = false; |
| 321 for (var unit in compilationUnits) { | 324 for (var unit in compilationUnits) { |
| 322 var library = | 325 var library = |
| 323 resolutionMap.elementDeclaredByCompilationUnit(unit).library; | 326 resolutionMap.elementDeclaredByCompilationUnit(unit).library; |
| 324 if (unit.element != library.definingCompilationUnit) continue; | 327 if (unit.element != library.definingCompilationUnit) continue; |
| 325 | 328 |
| 326 var libraryTemp = isSdkInternalRuntime(library) | 329 var libraryTemp = isSdkInternalRuntime(library) |
| 327 ? _runtimeModule | 330 ? _runtimeModule |
| 328 : new JS.TemporaryId(jsLibraryName(_libraryRoot, library)); | 331 : new JS.TemporaryId(jsLibraryName(_libraryRoot, library)); |
| 329 _libraries[library] = libraryTemp; | 332 _libraries[library] = libraryTemp; |
| 330 items.add(new JS.ExportDeclaration( | 333 items.add(new JS.ExportDeclaration( |
| 331 js.call('const # = Object.create(null)', [libraryTemp]))); | 334 js.call('const # = Object.create(null)', [libraryTemp]))); |
| 332 | 335 |
| 333 // dart:_runtime has a magic module that holds extension method symbols. | 336 // dart:_runtime has a magic module that holds extension method symbols. |
| 334 // TODO(jmesserly): find a cleaner design for this. | 337 // TODO(jmesserly): find a cleaner design for this. |
| 335 if (isSdkInternalRuntime(library)) { | 338 if (isSdkInternalRuntime(library)) { |
| 339 isBuildingSdk = true; |
| 336 items.add(new JS.ExportDeclaration(js | 340 items.add(new JS.ExportDeclaration(js |
| 337 .call('const # = Object.create(null)', [_extensionSymbolsModule]))); | 341 .call('const # = Object.create(null)', [_extensionSymbolsModule]))); |
| 338 } | 342 } |
| 339 } | 343 } |
| 340 | 344 |
| 341 // Collect all class/type Element -> Node mappings | 345 // Collect all class/type Element -> Node mappings |
| 342 // in case we need to forward declare any classes. | 346 // in case we need to forward declare any classes. |
| 343 _declarationNodes = new HashMap<TypeDefiningElement, AstNode>.identity(); | 347 _declarationNodes = new HashMap<TypeDefiningElement, AstNode>.identity(); |
| 344 for (var unit in compilationUnits) { | 348 for (var unit in compilationUnits) { |
| 345 for (var declaration in unit.declarations) { | 349 for (var declaration in unit.declarations) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 365 // Order will be changed as needed so the resulting code can execute. | 369 // Order will be changed as needed so the resulting code can execute. |
| 366 // This is done by forward declaring items. | 370 // This is done by forward declaring items. |
| 367 compilationUnits.forEach(visitCompilationUnit); | 371 compilationUnits.forEach(visitCompilationUnit); |
| 368 assert(_deferredProperties.isEmpty); | 372 assert(_deferredProperties.isEmpty); |
| 369 | 373 |
| 370 // Visit directives (for exports) | 374 // Visit directives (for exports) |
| 371 compilationUnits.forEach(_emitExportDirectives); | 375 compilationUnits.forEach(_emitExportDirectives); |
| 372 | 376 |
| 373 // Declare imports | 377 // Declare imports |
| 374 _finishImports(items); | 378 _finishImports(items); |
| 379 // Initialize extension symbols |
| 380 _extensionSymbols.forEach((name, id) { |
| 381 var value = |
| 382 new JS.PropertyAccess(_extensionSymbolsModule, _propertyName(name)); |
| 383 if (isBuildingSdk) { |
| 384 value = js.call('# = Symbol(#)', [value, js.string("dartx.$name")]); |
| 385 } |
| 386 items.add(js.statement('const # = #;', [id, value])); |
| 387 }); |
| 375 | 388 |
| 376 // Discharge the type table cache variables and | 389 // Discharge the type table cache variables and |
| 377 // hoisted definitions. | 390 // hoisted definitions. |
| 378 items.addAll(_typeTable.discharge()); | 391 items.addAll(_typeTable.discharge()); |
| 379 items.addAll(_internalSdkFunctions); | 392 items.addAll(_internalSdkFunctions); |
| 380 | 393 |
| 381 // Track the module name for each library in the module. | 394 // Track the module name for each library in the module. |
| 382 // This data is only required for debugging. | 395 // This data is only required for debugging. |
| 383 _moduleItems.add(js.statement( | 396 _moduleItems.add(js.statement( |
| 384 '#.trackLibraries(#, #, ${JSModuleFile.sourceMapHoleID});', | 397 '#.trackLibraries(#, #, ${JSModuleFile.sourceMapHoleID});', |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 virtualFields, | 939 virtualFields, |
| 927 classElem, | 940 classElem, |
| 928 getClassCovariantParameters(node), | 941 getClassCovariantParameters(node), |
| 929 _usedCovariantPrivateMembers); | 942 _usedCovariantPrivateMembers); |
| 930 | 943 |
| 931 var jsCtors = _defineConstructors(classElem, className, fields, ctors); | 944 var jsCtors = _defineConstructors(classElem, className, fields, ctors); |
| 932 var classExpr = _emitClassExpression(classElem, _emitClassMethods(node), | 945 var classExpr = _emitClassExpression(classElem, _emitClassMethods(node), |
| 933 fields: allFields); | 946 fields: allFields); |
| 934 | 947 |
| 935 var body = <JS.Statement>[]; | 948 var body = <JS.Statement>[]; |
| 936 _initExtensionSymbols(classElem, methods, fields, body); | |
| 937 _emitSuperHelperSymbols(body); | 949 _emitSuperHelperSymbols(body); |
| 938 | 950 |
| 939 // Emit the class, e.g. `core.Object = class Object { ... }` | 951 // Emit the class, e.g. `core.Object = class Object { ... }` |
| 940 _defineClass(classElem, className, classExpr, body); | 952 _defineClass(classElem, className, classExpr, body); |
| 941 body.addAll(jsCtors); | 953 body.addAll(jsCtors); |
| 942 | 954 |
| 943 // Emit things that come after the ES6 `class ... { ... }`. | 955 // Emit things that come after the ES6 `class ... { ... }`. |
| 944 var jsPeerNames = _getJSPeerNames(classElem); | 956 var jsPeerNames = _getJSPeerNames(classElem); |
| 945 JS.Statement deferredBaseClass = | 957 JS.Statement deferredBaseClass = |
| 946 _setBaseClass(classElem, className, jsPeerNames, body); | 958 _setBaseClass(classElem, className, jsPeerNames, body); |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1171 // Define the type tests on the default instantiation to check for that | 1183 // Define the type tests on the default instantiation to check for that |
| 1172 // marker. | 1184 // marker. |
| 1173 var defaultInst = _emitTopLevelName(classElem); | 1185 var defaultInst = _emitTopLevelName(classElem); |
| 1174 | 1186 |
| 1175 // Return this `addTypeTests` call so we can emit it outside of the generic | 1187 // Return this `addTypeTests` call so we can emit it outside of the generic |
| 1176 // type parameter scope. | 1188 // type parameter scope. |
| 1177 return _callHelperStatement( | 1189 return _callHelperStatement( |
| 1178 'addTypeTests(#, #);', [defaultInst, isClassSymbol]); | 1190 'addTypeTests(#, #);', [defaultInst, isClassSymbol]); |
| 1179 } | 1191 } |
| 1180 | 1192 |
| 1181 void _emitSuperHelperSymbols(List<JS.Statement> body) { | 1193 void _emitSymbols(Iterable<JS.TemporaryId> vars, List<JS.ModuleItem> body) { |
| 1182 for (var id in _superHelpers.values.map((m) => m.name as JS.TemporaryId)) { | 1194 for (var id in vars) { |
| 1183 body.add(js.statement('const # = Symbol(#)', [id, js.string(id.name)])); | 1195 body.add(js.statement('const # = Symbol(#)', [id, js.string(id.name)])); |
| 1184 } | 1196 } |
| 1197 } |
| 1198 |
| 1199 void _emitSuperHelperSymbols(List<JS.Statement> body) { |
| 1200 _emitSymbols( |
| 1201 _superHelpers.values.map((m) => m.name as JS.TemporaryId), body); |
| 1185 _superHelpers.clear(); | 1202 _superHelpers.clear(); |
| 1186 } | 1203 } |
| 1187 | 1204 |
| 1188 void _emitVirtualFieldSymbols( | 1205 void _emitVirtualFieldSymbols( |
| 1189 ClassElement classElement, List<JS.Statement> body) { | 1206 ClassElement classElement, List<JS.Statement> body) { |
| 1190 _classProperties.virtualFields.forEach((field, virtualField) { | 1207 _classProperties.virtualFields.forEach((field, virtualField) { |
| 1191 body.add(js.statement('const # = Symbol(#);', | 1208 body.add(js.statement('const # = Symbol(#);', |
| 1192 [virtualField, js.string('${classElement.name}.${field.name}')])); | 1209 [virtualField, js.string('${classElement.name}.${field.name}')])); |
| 1193 }); | 1210 }); |
| 1194 } | 1211 } |
| (...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2148 body.add(_callHelperStatement('setSignature(#, #);', [className, sig])); | 2165 body.add(_callHelperStatement('setSignature(#, #);', [className, sig])); |
| 2149 } | 2166 } |
| 2150 // Add static property dart._runtimeType to Object. | 2167 // Add static property dart._runtimeType to Object. |
| 2151 // All other Dart classes will (statically) inherit this property. | 2168 // All other Dart classes will (statically) inherit this property. |
| 2152 if (classElem == objectClass) { | 2169 if (classElem == objectClass) { |
| 2153 body.add(_callHelperStatement('tagComputed(#, () => #.#);', | 2170 body.add(_callHelperStatement('tagComputed(#, () => #.#);', |
| 2154 [className, emitLibraryName(dartCoreLibrary), 'Type'])); | 2171 [className, emitLibraryName(dartCoreLibrary), 'Type'])); |
| 2155 } | 2172 } |
| 2156 } | 2173 } |
| 2157 | 2174 |
| 2158 /// Ensure `dartx.` symbols we will use are present. | |
| 2159 void _initExtensionSymbols( | |
| 2160 ClassElement classElem, | |
| 2161 List<MethodDeclaration> methods, | |
| 2162 List<FieldDeclaration> fields, | |
| 2163 List<JS.Statement> body) { | |
| 2164 if (_extensionTypes.hasNativeSubtype(classElem.type)) { | |
| 2165 var dartxNames = <JS.Expression>[]; | |
| 2166 for (var m in methods) { | |
| 2167 if (!m.isAbstract && | |
| 2168 !m.isStatic && | |
| 2169 resolutionMap.elementDeclaredByMethodDeclaration(m).isPublic) { | |
| 2170 dartxNames.add(_declareMemberName(m.element, useExtension: false)); | |
| 2171 } | |
| 2172 } | |
| 2173 for (var fieldDecl in fields) { | |
| 2174 if (!fieldDecl.isStatic) { | |
| 2175 for (var field in fieldDecl.fields.variables) { | |
| 2176 var e = field.element as FieldElement; | |
| 2177 if (e.isPublic) { | |
| 2178 dartxNames.add(_declareMemberName(e.getter, useExtension: false)); | |
| 2179 } | |
| 2180 } | |
| 2181 } | |
| 2182 } | |
| 2183 if (dartxNames.isNotEmpty) { | |
| 2184 body.add(_callHelperStatement('defineExtensionNames(#)', | |
| 2185 [new JS.ArrayInitializer(dartxNames, multiline: true)])); | |
| 2186 } | |
| 2187 } | |
| 2188 } | |
| 2189 | |
| 2190 JS.Expression _emitConstructor(ConstructorDeclaration node, | 2175 JS.Expression _emitConstructor(ConstructorDeclaration node, |
| 2191 List<FieldDeclaration> fields, bool isCallable, JS.Expression className) { | 2176 List<FieldDeclaration> fields, bool isCallable, JS.Expression className) { |
| 2192 var params = _emitFormalParameterList(node.parameters); | 2177 var params = _emitFormalParameterList(node.parameters); |
| 2193 | 2178 |
| 2194 var savedFunction = _currentFunction; | 2179 var savedFunction = _currentFunction; |
| 2195 _currentFunction = node.body; | 2180 _currentFunction = node.body; |
| 2196 | 2181 |
| 2197 var savedSuperAllowed = _superAllowed; | 2182 var savedSuperAllowed = _superAllowed; |
| 2198 _superAllowed = false; | 2183 _superAllowed = false; |
| 2199 var body = _emitConstructorBody(node, fields, className); | 2184 var body = _emitConstructorBody(node, fields, className); |
| (...skipping 3447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5647 break; | 5632 break; |
| 5648 case 'unary-': | 5633 case 'unary-': |
| 5649 name = '_negate'; | 5634 name = '_negate'; |
| 5650 break; | 5635 break; |
| 5651 case 'constructor': | 5636 case 'constructor': |
| 5652 case 'prototype': | 5637 case 'prototype': |
| 5653 name = '_$name'; | 5638 name = '_$name'; |
| 5654 break; | 5639 break; |
| 5655 } | 5640 } |
| 5656 | 5641 |
| 5657 var result = _propertyName(name); | 5642 if (useExtension ?? _isSymbolizedMember(type, name)) { |
| 5658 | 5643 return _extensionSymbols.putIfAbsent(name, |
| 5659 useExtension ??= _isSymbolizedMember(type, name); | 5644 () => new JS.TemporaryId('\$${_friendlyOperatorName[name] ?? name}')); |
| 5660 | 5645 } |
| 5661 return useExtension | 5646 return _propertyName(name); |
| 5662 ? js.call('#.#', [_extensionSymbolsModule, result]) | |
| 5663 : result; | |
| 5664 } | 5647 } |
| 5665 | 5648 |
| 5666 var _forwardingCache = new HashMap<Element, Map<String, ExecutableElement>>(); | 5649 var _forwardingCache = new HashMap<Element, Map<String, ExecutableElement>>(); |
| 5667 | 5650 |
| 5668 Element _lookupForwardedMember(ClassElement element, String name) { | 5651 Element _lookupForwardedMember(ClassElement element, String name) { |
| 5669 // We only care about public methods. | 5652 // We only care about public methods. |
| 5670 if (name.startsWith('_')) return null; | 5653 if (name.startsWith('_')) return null; |
| 5671 | 5654 |
| 5672 var map = _forwardingCache.putIfAbsent(element, () => {}); | 5655 var map = _forwardingCache.putIfAbsent(element, () => {}); |
| 5673 if (map.containsKey(name)) return map[name]; | 5656 if (map.containsKey(name)) return map[name]; |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6065 // The library the prefix is referring to must come from a deferred import. | 6048 // The library the prefix is referring to must come from a deferred import. |
| 6066 var containingLibrary = resolutionMap | 6049 var containingLibrary = resolutionMap |
| 6067 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) | 6050 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) |
| 6068 .library; | 6051 .library; |
| 6069 var imports = containingLibrary.getImportsWithPrefix(prefix); | 6052 var imports = containingLibrary.getImportsWithPrefix(prefix); |
| 6070 return imports.length == 1 && imports[0].isDeferred; | 6053 return imports.length == 1 && imports[0].isDeferred; |
| 6071 } | 6054 } |
| 6072 | 6055 |
| 6073 bool _annotatedNullCheck(Element e) => | 6056 bool _annotatedNullCheck(Element e) => |
| 6074 e != null && findAnnotation(e, isNullCheckAnnotation) != null; | 6057 e != null && findAnnotation(e, isNullCheckAnnotation) != null; |
| 6058 |
| 6059 final _friendlyOperatorName = { |
| 6060 '<': 'lessThan', |
| 6061 '>': 'greaterThan', |
| 6062 '<=': 'lessOrEquals', |
| 6063 '>=': 'greaterOrEquals', |
| 6064 '==': 'equals', |
| 6065 '-': 'minus', |
| 6066 '+': 'plus', |
| 6067 '/': 'divide', |
| 6068 '~/': 'floorDivide', |
| 6069 '*': 'times', |
| 6070 '%': 'modulo', |
| 6071 '|': 'bitOr', |
| 6072 '^': 'bitXor', |
| 6073 '&': 'bitAnd', |
| 6074 '<<': 'leftShift', |
| 6075 '>>': 'rightShift', |
| 6076 '~': 'bitNot' |
| 6077 }; |
| OLD | NEW |