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'; |
11 import 'package:analyzer/dart/ast/standard_ast_factory.dart'; | 11 import 'package:analyzer/dart/ast/standard_ast_factory.dart'; |
12 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; | 12 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; |
| 13 import 'package:analyzer/dart/ast/resolution_accessors.dart'; |
13 import 'package:analyzer/dart/element/element.dart'; | 14 import 'package:analyzer/dart/element/element.dart'; |
14 import 'package:analyzer/dart/element/type.dart'; | 15 import 'package:analyzer/dart/element/type.dart'; |
15 import 'package:analyzer/src/dart/ast/token.dart' show StringToken; | 16 import 'package:analyzer/src/dart/ast/token.dart' show StringToken; |
16 import 'package:analyzer/src/dart/element/element.dart' | 17 import 'package:analyzer/src/dart/element/element.dart' |
17 show LocalVariableElementImpl; | 18 show LocalVariableElementImpl; |
18 import 'package:analyzer/src/dart/element/type.dart' show DynamicTypeImpl; | 19 import 'package:analyzer/src/dart/element/type.dart' show DynamicTypeImpl; |
19 import 'package:analyzer/src/dart/sdk/sdk.dart'; | 20 import 'package:analyzer/src/dart/sdk/sdk.dart'; |
20 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; | 21 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; |
21 import 'package:analyzer/src/generated/resolver.dart' | 22 import 'package:analyzer/src/generated/resolver.dart' |
22 show TypeProvider, NamespaceBuilder; | 23 show TypeProvider, NamespaceBuilder; |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 | 186 |
186 var module = _emitModule(compilationUnits); | 187 var module = _emitModule(compilationUnits); |
187 var dartApiSummary = _summarizeModule(compilationUnits); | 188 var dartApiSummary = _summarizeModule(compilationUnits); |
188 | 189 |
189 return new JSModuleFile(unit.name, errors, options, module, dartApiSummary); | 190 return new JSModuleFile(unit.name, errors, options, module, dartApiSummary); |
190 } | 191 } |
191 | 192 |
192 List<int> _summarizeModule(List<CompilationUnit> units) { | 193 List<int> _summarizeModule(List<CompilationUnit> units) { |
193 if (!options.summarizeApi) return null; | 194 if (!options.summarizeApi) return null; |
194 | 195 |
195 if (!units.any((u) => u.element.librarySource.isInSystemLibrary)) { | 196 if (!units.any((u) => elementForCompilationUnit(u).librarySource.isInSystemL
ibrary)) { |
196 var sdk = context.sourceFactory.dartSdk; | 197 var sdk = context.sourceFactory.dartSdk; |
197 summaryData.addBundle( | 198 summaryData.addBundle( |
198 null, | 199 null, |
199 sdk is SummaryBasedDartSdk | 200 sdk is SummaryBasedDartSdk |
200 ? sdk.bundle | 201 ? sdk.bundle |
201 : (sdk as FolderBasedDartSdk).getSummarySdkBundle(true)); | 202 : (sdk as FolderBasedDartSdk).getSummarySdkBundle(true)); |
202 } | 203 } |
203 | 204 |
204 var assembler = new PackageBundleAssembler(); | 205 var assembler = new PackageBundleAssembler(); |
205 assembler.recordDependencies(summaryData); | 206 assembler.recordDependencies(summaryData); |
(...skipping 21 matching lines...) Expand all Loading... |
227 } | 228 } |
228 | 229 |
229 JS.Program _emitModule(List<CompilationUnit> compilationUnits) { | 230 JS.Program _emitModule(List<CompilationUnit> compilationUnits) { |
230 if (_moduleItems.isNotEmpty) { | 231 if (_moduleItems.isNotEmpty) { |
231 throw new StateError('Can only call emitModule once.'); | 232 throw new StateError('Can only call emitModule once.'); |
232 } | 233 } |
233 | 234 |
234 // Transform the AST to make coercions explicit. | 235 // Transform the AST to make coercions explicit. |
235 compilationUnits = CoercionReifier.reify(compilationUnits); | 236 compilationUnits = CoercionReifier.reify(compilationUnits); |
236 | 237 |
237 if (compilationUnits.any((u) => _isDartRuntime(u.element.library))) { | 238 if (compilationUnits.any((u) => _isDartRuntime(elementForCompilationUnit(u).
library))) { |
238 // Don't allow these to be renamed when we're building the SDK. | 239 // Don't allow these to be renamed when we're building the SDK. |
239 // There is JS code in dart:* that depends on their names. | 240 // There is JS code in dart:* that depends on their names. |
240 _runtimeModule = new JS.Identifier('dart'); | 241 _runtimeModule = new JS.Identifier('dart'); |
241 _extensionSymbolsModule = new JS.Identifier('dartx'); | 242 _extensionSymbolsModule = new JS.Identifier('dartx'); |
242 } else { | 243 } else { |
243 // Otherwise allow these to be renamed so users can write them. | 244 // Otherwise allow these to be renamed so users can write them. |
244 _runtimeModule = new JS.TemporaryId('dart'); | 245 _runtimeModule = new JS.TemporaryId('dart'); |
245 _extensionSymbolsModule = new JS.TemporaryId('dartx'); | 246 _extensionSymbolsModule = new JS.TemporaryId('dartx'); |
246 } | 247 } |
247 _typeTable = new TypeTable(_runtimeModule); | 248 _typeTable = new TypeTable(_runtimeModule); |
248 | 249 |
249 // Initialize our library variables. | 250 // Initialize our library variables. |
250 var items = <JS.ModuleItem>[]; | 251 var items = <JS.ModuleItem>[]; |
251 for (var unit in compilationUnits) { | 252 for (var unit in compilationUnits) { |
252 var library = unit.element.library; | 253 var library = elementForCompilationUnit(unit).library; |
253 if (unit.element != library.definingCompilationUnit) continue; | 254 if (unit.element != library.definingCompilationUnit) continue; |
254 | 255 |
255 var libraryTemp = _isDartRuntime(library) | 256 var libraryTemp = _isDartRuntime(library) |
256 ? _runtimeModule | 257 ? _runtimeModule |
257 : new JS.TemporaryId(jsLibraryName(_libraryRoot, library)); | 258 : new JS.TemporaryId(jsLibraryName(_libraryRoot, library)); |
258 _libraries[library] = libraryTemp; | 259 _libraries[library] = libraryTemp; |
259 items.add(new JS.ExportDeclaration( | 260 items.add(new JS.ExportDeclaration( |
260 js.call('const # = Object.create(null)', [libraryTemp]))); | 261 js.call('const # = Object.create(null)', [libraryTemp]))); |
261 | 262 |
262 // dart:_runtime has a magic module that holds extension method symbols. | 263 // dart:_runtime has a magic module that holds extension method symbols. |
263 // TODO(jmesserly): find a cleaner design for this. | 264 // TODO(jmesserly): find a cleaner design for this. |
264 if (_isDartRuntime(library)) { | 265 if (_isDartRuntime(library)) { |
265 items.add(new JS.ExportDeclaration(js | 266 items.add(new JS.ExportDeclaration(js |
266 .call('const # = Object.create(null)', [_extensionSymbolsModule]))); | 267 .call('const # = Object.create(null)', [_extensionSymbolsModule]))); |
267 } | 268 } |
268 } | 269 } |
269 | 270 |
270 // Collect all Element -> Node mappings, in case we need to forward declare | 271 // Collect all Element -> Node mappings, in case we need to forward declare |
271 // any nodes. | 272 // any nodes. |
272 var nodes = new HashMap<Element, AstNode>.identity(); | 273 var nodes = new HashMap<Element, AstNode>.identity(); |
273 var sdkBootstrappingFns = new List<FunctionElement>(); | 274 var sdkBootstrappingFns = new List<FunctionElement>(); |
274 for (var unit in compilationUnits) { | 275 for (var unit in compilationUnits) { |
275 if (_isDartRuntime(unit.element.library)) { | 276 if (_isDartRuntime(elementForCompilationUnit(unit).library)) { |
276 sdkBootstrappingFns.addAll(unit.element.functions); | 277 sdkBootstrappingFns.addAll(elementForCompilationUnit(unit).functions); |
277 } | 278 } |
278 _collectElements(unit, nodes); | 279 _collectElements(unit, nodes); |
279 } | 280 } |
280 _loader = new ElementLoader(nodes); | 281 _loader = new ElementLoader(nodes); |
281 if (compilationUnits.isNotEmpty) { | 282 if (compilationUnits.isNotEmpty) { |
282 _constants = new ConstFieldVisitor(context, | 283 _constants = new ConstFieldVisitor(context, |
283 dummySource: compilationUnits.first.element.source); | 284 dummySource: elementForCompilationUnit(compilationUnits.first).source)
; |
284 } | 285 } |
285 | 286 |
286 // Add implicit dart:core dependency so it is first. | 287 // Add implicit dart:core dependency so it is first. |
287 emitLibraryName(dartCoreLibrary); | 288 emitLibraryName(dartCoreLibrary); |
288 | 289 |
289 // Emit SDK bootstrapping functions first, if any. | 290 // Emit SDK bootstrapping functions first, if any. |
290 sdkBootstrappingFns.forEach(_emitDeclaration); | 291 sdkBootstrappingFns.forEach(_emitDeclaration); |
291 | 292 |
292 // Visit each compilation unit and emit its code. | 293 // Visit each compilation unit and emit its code. |
293 // | 294 // |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
721 | 722 |
722 // We export the JS type as if it was a Dart type. For example this allows | 723 // We export the JS type as if it was a Dart type. For example this allows |
723 // `dom.InputElement` to actually be HTMLInputElement. | 724 // `dom.InputElement` to actually be HTMLInputElement. |
724 // TODO(jmesserly): if we had the JS name on the Element, we could just | 725 // TODO(jmesserly): if we had the JS name on the Element, we could just |
725 // generate it correctly when we refer to it. | 726 // generate it correctly when we refer to it. |
726 return js.statement('# = #;', [_emitTopLevelName(e), jsTypeName]); | 727 return js.statement('# = #;', [_emitTopLevelName(e), jsTypeName]); |
727 } | 728 } |
728 | 729 |
729 @override | 730 @override |
730 JS.Statement visitClassDeclaration(ClassDeclaration node) { | 731 JS.Statement visitClassDeclaration(ClassDeclaration node) { |
731 var classElem = node.element; | 732 var classElem = elementForClassDeclaration(node); |
732 | 733 |
733 // If this class is annotated with `@JS`, then there is nothing to emit. | 734 // If this class is annotated with `@JS`, then there is nothing to emit. |
734 if (findAnnotation(classElem, isPublicJSAnnotation) != null) return null; | 735 if (findAnnotation(classElem, isPublicJSAnnotation) != null) return null; |
735 | 736 |
736 // If this is a JavaScript type, emit it now and then exit. | 737 // If this is a JavaScript type, emit it now and then exit. |
737 var jsTypeDef = _emitJsType(classElem); | 738 var jsTypeDef = _emitJsType(classElem); |
738 if (jsTypeDef != null) return jsTypeDef; | 739 if (jsTypeDef != null) return jsTypeDef; |
739 | 740 |
740 var ctors = <ConstructorDeclaration>[]; | 741 var ctors = <ConstructorDeclaration>[]; |
741 var fields = <FieldDeclaration>[]; | 742 var fields = <FieldDeclaration>[]; |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 /// Emits a field declaration for TypeScript & Closure's ES6_TYPED | 1104 /// Emits a field declaration for TypeScript & Closure's ES6_TYPED |
1104 /// (e.g. `class Foo { i: string; }`) | 1105 /// (e.g. `class Foo { i: string; }`) |
1105 JS.VariableDeclarationList _emitTypeScriptField(FieldDeclaration field) { | 1106 JS.VariableDeclarationList _emitTypeScriptField(FieldDeclaration field) { |
1106 return new JS.VariableDeclarationList( | 1107 return new JS.VariableDeclarationList( |
1107 field.isStatic ? 'static' : null, | 1108 field.isStatic ? 'static' : null, |
1108 field.fields.variables | 1109 field.fields.variables |
1109 .map((decl) => new JS.VariableInitialization( | 1110 .map((decl) => new JS.VariableInitialization( |
1110 new JS.Identifier( | 1111 new JS.Identifier( |
1111 // TODO(ochafik): use a refactored _emitMemberName instead. | 1112 // TODO(ochafik): use a refactored _emitMemberName instead. |
1112 decl.name.name, | 1113 decl.name.name, |
1113 type: emitTypeRef(decl.element.type)), | 1114 type: emitTypeRef(elementForVariableDeclaration(decl).type))
, |
1114 null)) | 1115 null)) |
1115 .toList(growable: false)); | 1116 .toList(growable: false)); |
1116 } | 1117 } |
1117 | 1118 |
1118 @override | 1119 @override |
1119 JS.Statement visitEnumDeclaration(EnumDeclaration node) { | 1120 JS.Statement visitEnumDeclaration(EnumDeclaration node) { |
1120 var element = node.element; | 1121 var element = elementForEnumDeclaration(node); |
1121 var type = element.type; | 1122 var type = element.type; |
1122 | 1123 |
1123 // Generate a class per section 13 of the spec. | 1124 // Generate a class per section 13 of the spec. |
1124 // TODO(vsm): Generate any accompanying metadata | 1125 // TODO(vsm): Generate any accompanying metadata |
1125 | 1126 |
1126 // Create constructor and initialize index | 1127 // Create constructor and initialize index |
1127 var constructor = new JS.Method(_propertyName('new'), | 1128 var constructor = new JS.Method(_propertyName('new'), |
1128 js.call('function(index) { this.index = index; }') as JS.Fun); | 1129 js.call('function(index) { this.index = index; }') as JS.Fun); |
1129 var fields = new List<FieldElement>.from( | 1130 var fields = new List<FieldElement>.from( |
1130 element.fields.where((f) => f.type == type)); | 1131 element.fields.where((f) => f.type == type)); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1281 } | 1282 } |
1282 return jsMethods; | 1283 return jsMethods; |
1283 } | 1284 } |
1284 | 1285 |
1285 List<JS.Method> _emitClassMethods( | 1286 List<JS.Method> _emitClassMethods( |
1286 ClassDeclaration node, | 1287 ClassDeclaration node, |
1287 List<ConstructorDeclaration> ctors, | 1288 List<ConstructorDeclaration> ctors, |
1288 List<FieldDeclaration> fields, | 1289 List<FieldDeclaration> fields, |
1289 List<ClassElement> superclasses, | 1290 List<ClassElement> superclasses, |
1290 Map<FieldElement, JS.TemporaryId> virtualFields) { | 1291 Map<FieldElement, JS.TemporaryId> virtualFields) { |
1291 var element = node.element; | 1292 var element = elementForClassDeclaration(node); |
1292 var type = element.type; | 1293 var type = element.type; |
1293 var isObject = type.isObject; | 1294 var isObject = type.isObject; |
1294 | 1295 |
1295 // Iff no constructor is specified for a class C, it implicitly has a | 1296 // Iff no constructor is specified for a class C, it implicitly has a |
1296 // default constructor `C() : super() {}`, unless C is class Object. | 1297 // default constructor `C() : super() {}`, unless C is class Object. |
1297 var jsMethods = <JS.Method>[]; | 1298 var jsMethods = <JS.Method>[]; |
1298 if (isObject) { | 1299 if (isObject) { |
1299 // Implements Dart constructor behavior. | 1300 // Implements Dart constructor behavior. |
1300 // | 1301 // |
1301 // Because of ES6 constructor restrictions (`this` is not available until | 1302 // Because of ES6 constructor restrictions (`this` is not available until |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1761 | 1762 |
1762 var tStaticMethods = <JS.Property>[]; | 1763 var tStaticMethods = <JS.Property>[]; |
1763 var tInstanceMethods = <JS.Property>[]; | 1764 var tInstanceMethods = <JS.Property>[]; |
1764 var tStaticGetters = <JS.Property>[]; | 1765 var tStaticGetters = <JS.Property>[]; |
1765 var tInstanceGetters = <JS.Property>[]; | 1766 var tInstanceGetters = <JS.Property>[]; |
1766 var tStaticSetters = <JS.Property>[]; | 1767 var tStaticSetters = <JS.Property>[]; |
1767 var tInstanceSetters = <JS.Property>[]; | 1768 var tInstanceSetters = <JS.Property>[]; |
1768 var sNames = <JS.Expression>[]; | 1769 var sNames = <JS.Expression>[]; |
1769 for (MethodDeclaration node in methods) { | 1770 for (MethodDeclaration node in methods) { |
1770 var name = node.name.name; | 1771 var name = node.name.name; |
1771 var element = node.element; | 1772 var element = elementForMethodDeclaration(node); |
1772 // TODO(vsm): Clean up all the nasty duplication. | 1773 // TODO(vsm): Clean up all the nasty duplication. |
1773 if (node.isAbstract) { | 1774 if (node.isAbstract) { |
1774 continue; | 1775 continue; |
1775 } | 1776 } |
1776 | 1777 |
1777 Function lookup; | 1778 Function lookup; |
1778 List<JS.Property> tMember; | 1779 List<JS.Property> tMember; |
1779 JS.Expression type; | 1780 JS.Expression type; |
1780 if (node.isGetter) { | 1781 if (node.isGetter) { |
1781 lookup = classElem.lookUpInheritedConcreteGetter; | 1782 lookup = classElem.lookUpInheritedConcreteGetter; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1816 var memberName = _declareMemberName(element.getter); | 1817 var memberName = _declareMemberName(element.getter); |
1817 var type = _emitAnnotatedType(element.type, node.metadata); | 1818 var type = _emitAnnotatedType(element.type, node.metadata); |
1818 var property = new JS.Property(memberName, type); | 1819 var property = new JS.Property(memberName, type); |
1819 (node.isStatic ? tStaticFields : tInstanceFields).add(property); | 1820 (node.isStatic ? tStaticFields : tInstanceFields).add(property); |
1820 } | 1821 } |
1821 } | 1822 } |
1822 | 1823 |
1823 var tCtors = <JS.Property>[]; | 1824 var tCtors = <JS.Property>[]; |
1824 for (ConstructorDeclaration node in ctors) { | 1825 for (ConstructorDeclaration node in ctors) { |
1825 var memberName = _constructorName(node.element); | 1826 var memberName = _constructorName(node.element); |
1826 var element = node.element; | 1827 var element = elementForConstructorDeclaration(node); |
1827 var type = _emitAnnotatedFunctionType(element.type, node.metadata, | 1828 var type = _emitAnnotatedFunctionType(element.type, node.metadata, |
1828 parameters: node.parameters.parameters, | 1829 parameters: node.parameters.parameters, |
1829 nameType: options.hoistSignatureTypes, | 1830 nameType: options.hoistSignatureTypes, |
1830 hoistType: options.hoistSignatureTypes, | 1831 hoistType: options.hoistSignatureTypes, |
1831 definite: true); | 1832 definite: true); |
1832 var property = new JS.Property(memberName, type); | 1833 var property = new JS.Property(memberName, type); |
1833 tCtors.add(property); | 1834 tCtors.add(property); |
1834 } | 1835 } |
1835 | 1836 |
1836 JS.Property build(String name, List<JS.Property> elements) { | 1837 JS.Property build(String name, List<JS.Property> elements) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1888 | 1889 |
1889 /// Ensure `dartx.` symbols we will use are present. | 1890 /// Ensure `dartx.` symbols we will use are present. |
1890 void _initExtensionSymbols( | 1891 void _initExtensionSymbols( |
1891 ClassElement classElem, | 1892 ClassElement classElem, |
1892 List<MethodDeclaration> methods, | 1893 List<MethodDeclaration> methods, |
1893 List<FieldDeclaration> fields, | 1894 List<FieldDeclaration> fields, |
1894 List<JS.Statement> body) { | 1895 List<JS.Statement> body) { |
1895 if (_extensionTypes.hasNativeSubtype(classElem.type)) { | 1896 if (_extensionTypes.hasNativeSubtype(classElem.type)) { |
1896 var dartxNames = <JS.Expression>[]; | 1897 var dartxNames = <JS.Expression>[]; |
1897 for (var m in methods) { | 1898 for (var m in methods) { |
1898 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { | 1899 if (!m.isAbstract && !m.isStatic && elementForMethodDeclaration(m).isPub
lic) { |
1899 dartxNames.add(_declareMemberName(m.element, useExtension: false)); | 1900 dartxNames.add(_declareMemberName(m.element, useExtension: false)); |
1900 } | 1901 } |
1901 } | 1902 } |
1902 for (var fieldDecl in fields) { | 1903 for (var fieldDecl in fields) { |
1903 if (!fieldDecl.isStatic) { | 1904 if (!fieldDecl.isStatic) { |
1904 for (var field in fieldDecl.fields.variables) { | 1905 for (var field in fieldDecl.fields.variables) { |
1905 var e = field.element as FieldElement; | 1906 var e = field.element as FieldElement; |
1906 if (e.isPublic) { | 1907 if (e.isPublic) { |
1907 dartxNames.add(_declareMemberName(e.getter, useExtension: false)); | 1908 dartxNames.add(_declareMemberName(e.getter, useExtension: false)); |
1908 } | 1909 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1950 Map<FieldElement, JS.TemporaryId> virtualFields) { | 1951 Map<FieldElement, JS.TemporaryId> virtualFields) { |
1951 // If we don't have a method body, skip this. | 1952 // If we don't have a method body, skip this. |
1952 var superCall = _superConstructorCall(node.element); | 1953 var superCall = _superConstructorCall(node.element); |
1953 if (fields.isEmpty && superCall == null) return null; | 1954 if (fields.isEmpty && superCall == null) return null; |
1954 | 1955 |
1955 var initFields = _initializeFields(node, fields, virtualFields); | 1956 var initFields = _initializeFields(node, fields, virtualFields); |
1956 List<JS.Statement> body = [initFields]; | 1957 List<JS.Statement> body = [initFields]; |
1957 if (superCall != null) { | 1958 if (superCall != null) { |
1958 body.add(superCall); | 1959 body.add(superCall); |
1959 } | 1960 } |
1960 var name = _constructorName(node.element.unnamedConstructor); | 1961 var name = _constructorName(elementForClassDeclaration(node).unnamedConstruc
tor); |
1961 return annotate( | 1962 return annotate( |
1962 new JS.Method(name, js.call('function() { #; }', [body]) as JS.Fun), | 1963 new JS.Method(name, js.call('function() { #; }', [body]) as JS.Fun), |
1963 node, | 1964 node, |
1964 node.element); | 1965 node.element); |
1965 } | 1966 } |
1966 | 1967 |
1967 JS.Method _emitConstructor( | 1968 JS.Method _emitConstructor( |
1968 ConstructorDeclaration node, | 1969 ConstructorDeclaration node, |
1969 InterfaceType type, | 1970 InterfaceType type, |
1970 List<FieldDeclaration> fields, | 1971 List<FieldDeclaration> fields, |
1971 Map<FieldElement, JS.TemporaryId> virtualFields, | 1972 Map<FieldElement, JS.TemporaryId> virtualFields, |
1972 bool isObject) { | 1973 bool isObject) { |
1973 if (_externalOrNative(node)) return null; | 1974 if (_externalOrNative(node)) return null; |
1974 | 1975 |
1975 var name = _constructorName(node.element); | 1976 var name = _constructorName(node.element); |
1976 var returnType = emitTypeRef(node.element.enclosingElement.type); | 1977 var returnType = emitTypeRef(elementForConstructorDeclaration(node).enclosin
gElement.type); |
1977 | 1978 |
1978 // Wacky factory redirecting constructors: factory Foo.q(x, y) = Bar.baz; | 1979 // Wacky factory redirecting constructors: factory Foo.q(x, y) = Bar.baz; |
1979 var redirect = node.redirectedConstructor; | 1980 var redirect = node.redirectedConstructor; |
1980 if (redirect != null) { | 1981 if (redirect != null) { |
1981 var newKeyword = redirect.staticElement.isFactory ? '' : 'new'; | 1982 var newKeyword = staticElementForConstructorReference(redirect).isFactory
? '' : 'new'; |
1982 // Pass along all arguments verbatim, and let the callee handle them. | 1983 // Pass along all arguments verbatim, and let the callee handle them. |
1983 // TODO(jmesserly): we'll need something different once we have | 1984 // TODO(jmesserly): we'll need something different once we have |
1984 // rest/spread support, but this should work for now. | 1985 // rest/spread support, but this should work for now. |
1985 var params = | 1986 var params = |
1986 visitFormalParameterList(node.parameters, destructure: false); | 1987 visitFormalParameterList(node.parameters, destructure: false); |
1987 | 1988 |
1988 var fun = new JS.Fun( | 1989 var fun = new JS.Fun( |
1989 params, | 1990 params, |
1990 js.statement('{ return $newKeyword #(#); }', | 1991 js.statement('{ return $newKeyword #(#); }', |
1991 [_visit(redirect) as JS.Node, params]), | 1992 [_visit(redirect) as JS.Node, params]), |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2080 var jsSuper = _superConstructorCall(cls.element, superCall); | 2081 var jsSuper = _superConstructorCall(cls.element, superCall); |
2081 if (jsSuper != null) body.add(jsSuper); | 2082 if (jsSuper != null) body.add(jsSuper); |
2082 | 2083 |
2083 body.add(_visit(node.body)); | 2084 body.add(_visit(node.body)); |
2084 return new JS.Block(body)..sourceInformation = node; | 2085 return new JS.Block(body)..sourceInformation = node; |
2085 } | 2086 } |
2086 | 2087 |
2087 @override | 2088 @override |
2088 JS.Statement visitRedirectingConstructorInvocation( | 2089 JS.Statement visitRedirectingConstructorInvocation( |
2089 RedirectingConstructorInvocation node) { | 2090 RedirectingConstructorInvocation node) { |
2090 var ctor = node.staticElement; | 2091 var ctor = staticElementForConstructorReference(node); |
2091 var cls = ctor.enclosingElement; | 2092 var cls = ctor.enclosingElement; |
2092 // We can't dispatch to the constructor with `this.new` as that might hit a | 2093 // We can't dispatch to the constructor with `this.new` as that might hit a |
2093 // derived class constructor with the same name. | 2094 // derived class constructor with the same name. |
2094 return js.statement('#.prototype.#.call(this, #);', [ | 2095 return js.statement('#.prototype.#.call(this, #);', [ |
2095 new JS.Identifier(cls.name), | 2096 new JS.Identifier(cls.name), |
2096 _constructorName(ctor), | 2097 _constructorName(ctor), |
2097 _visit(node.argumentList) | 2098 _visit(node.argumentList) |
2098 ]); | 2099 ]); |
2099 } | 2100 } |
2100 | 2101 |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2257 _defaultParamValue(param), | 2258 _defaultParamValue(param), |
2258 ])); | 2259 ])); |
2259 } else if (param.kind == ParameterKind.POSITIONAL) { | 2260 } else if (param.kind == ParameterKind.POSITIONAL) { |
2260 body.add(js.statement('if (# === void 0) # = #;', | 2261 body.add(js.statement('if (# === void 0) # = #;', |
2261 [jsParam, jsParam, _defaultParamValue(param)])); | 2262 [jsParam, jsParam, _defaultParamValue(param)])); |
2262 } | 2263 } |
2263 } | 2264 } |
2264 | 2265 |
2265 // TODO(jmesserly): various problems here, see: | 2266 // TODO(jmesserly): various problems here, see: |
2266 // https://github.com/dart-lang/dev_compiler/issues/116 | 2267 // https://github.com/dart-lang/dev_compiler/issues/116 |
2267 var paramType = param.element.type; | 2268 var paramType = elementForFormalParameter(param).type; |
2268 if (node is MethodDeclaration && | 2269 if (node is MethodDeclaration && |
2269 (param.element.isCovariant || _unsoundCovariant(paramType, true)) && | 2270 (elementForFormalParameter(param).isCovariant || _unsoundCovariant(par
amType, true)) && |
2270 !_inWhitelistCode(node)) { | 2271 !_inWhitelistCode(node)) { |
2271 var castType = _emitType(paramType, | 2272 var castType = _emitType(paramType, |
2272 nameType: options.nameTypeTests || options.hoistTypeTests, | 2273 nameType: options.nameTypeTests || options.hoistTypeTests, |
2273 hoistType: options.hoistTypeTests); | 2274 hoistType: options.hoistTypeTests); |
2274 body.add(js.statement('#._check(#);', [castType, jsParam])); | 2275 body.add(js.statement('#._check(#);', [castType, jsParam])); |
2275 } | 2276 } |
2276 } | 2277 } |
2277 return body.isEmpty ? null : _statement(body); | 2278 return body.isEmpty ? null : _statement(body); |
2278 } | 2279 } |
2279 | 2280 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2404 } | 2405 } |
2405 | 2406 |
2406 var body = <JS.Statement>[]; | 2407 var body = <JS.Statement>[]; |
2407 var fn = _emitFunction(node.functionExpression); | 2408 var fn = _emitFunction(node.functionExpression); |
2408 | 2409 |
2409 if (currentLibrary.source.isInSystemLibrary && | 2410 if (currentLibrary.source.isInSystemLibrary && |
2410 _isInlineJSFunction(node.functionExpression)) { | 2411 _isInlineJSFunction(node.functionExpression)) { |
2411 fn = _simplifyPassThroughArrowFunCallBody(fn); | 2412 fn = _simplifyPassThroughArrowFunCallBody(fn); |
2412 } | 2413 } |
2413 | 2414 |
2414 var element = node.element; | 2415 var element = elementForFunctionDeclaration(node); |
2415 var nameExpr = _emitTopLevelName(element); | 2416 var nameExpr = _emitTopLevelName(element); |
2416 body.add(annotate(js.statement('# = #', [nameExpr, fn]), node, element)); | 2417 body.add(annotate(js.statement('# = #', [nameExpr, fn]), node, element)); |
2417 if (!_isDartRuntime(element.library)) { | 2418 if (!_isDartRuntime(element.library)) { |
2418 body.add(_emitFunctionTagged(nameExpr, element.type, topLevel: true) | 2419 body.add(_emitFunctionTagged(nameExpr, element.type, topLevel: true) |
2419 .toStatement()); | 2420 .toStatement()); |
2420 } | 2421 } |
2421 | 2422 |
2422 return _statement(body); | 2423 return _statement(body); |
2423 } | 2424 } |
2424 | 2425 |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2672 JS.Statement declareFn; | 2673 JS.Statement declareFn; |
2673 if (JS.This.foundIn(fn)) { | 2674 if (JS.This.foundIn(fn)) { |
2674 declareFn = js.statement('const # = #.bind(this);', [name, fn]); | 2675 declareFn = js.statement('const # = #.bind(this);', [name, fn]); |
2675 } else { | 2676 } else { |
2676 declareFn = new JS.FunctionDeclaration(name, fn); | 2677 declareFn = new JS.FunctionDeclaration(name, fn); |
2677 } | 2678 } |
2678 declareFn = annotate(declareFn, node, node.functionDeclaration.element); | 2679 declareFn = annotate(declareFn, node, node.functionDeclaration.element); |
2679 | 2680 |
2680 return new JS.Block([ | 2681 return new JS.Block([ |
2681 declareFn, | 2682 declareFn, |
2682 _emitFunctionTagged(name, func.element.type).toStatement() | 2683 _emitFunctionTagged(name, elementForFunctionDeclaration(func).type).toStat
ement() |
2683 ]); | 2684 ]); |
2684 } | 2685 } |
2685 | 2686 |
2686 /// Emits a simple identifier, including handling an inferred generic | 2687 /// Emits a simple identifier, including handling an inferred generic |
2687 /// function instantiation. | 2688 /// function instantiation. |
2688 @override | 2689 @override |
2689 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { | 2690 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { |
2690 var typeArgs = _getTypeArgs(node.staticElement, node.staticType); | 2691 var typeArgs = _getTypeArgs(node.staticElement, node.staticType); |
2691 var simpleId = _emitSimpleIdentifier(node); | 2692 var simpleId = _emitSimpleIdentifier(node); |
2692 if (typeArgs == null) { | 2693 if (typeArgs == null) { |
2693 return simpleId; | 2694 return simpleId; |
2694 } | 2695 } |
2695 return _callHelper('gbind(#, #)', [simpleId, typeArgs]); | 2696 return _callHelper('gbind(#, #)', [simpleId, typeArgs]); |
2696 } | 2697 } |
2697 | 2698 |
2698 /// Emits a simple identifier, handling implicit `this` as well as | 2699 /// Emits a simple identifier, handling implicit `this` as well as |
2699 /// going through the qualified library name if necessary, but *not* handling | 2700 /// going through the qualified library name if necessary, but *not* handling |
2700 /// inferred generic function instantiation. | 2701 /// inferred generic function instantiation. |
2701 JS.Expression _emitSimpleIdentifier(SimpleIdentifier node) { | 2702 JS.Expression _emitSimpleIdentifier(SimpleIdentifier node) { |
2702 var accessor = node.staticElement; | 2703 var accessor = staticElementForIdentifier(node); |
2703 if (accessor == null) { | 2704 if (accessor == null) { |
2704 return js.commentExpression( | 2705 return js.commentExpression( |
2705 'Unimplemented unknown name', new JS.Identifier(node.name)); | 2706 'Unimplemented unknown name', new JS.Identifier(node.name)); |
2706 } | 2707 } |
2707 | 2708 |
2708 // Get the original declaring element. If we had a property accessor, this | 2709 // Get the original declaring element. If we had a property accessor, this |
2709 // indirects back to a (possibly synthetic) field. | 2710 // indirects back to a (possibly synthetic) field. |
2710 var element = accessor; | 2711 var element = accessor; |
2711 if (accessor is PropertyAccessorElement) element = accessor.variable; | 2712 if (accessor is PropertyAccessorElement) element = accessor.variable; |
2712 | 2713 |
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3223 | 3224 |
3224 /// Emits assignment to a simple identifier. Handles all legal simple | 3225 /// Emits assignment to a simple identifier. Handles all legal simple |
3225 /// identifier assignment targets (local, top level library member, implicit | 3226 /// identifier assignment targets (local, top level library member, implicit |
3226 /// `this` or class, etc.) | 3227 /// `this` or class, etc.) |
3227 JS.Expression _emitSetSimpleIdentifier( | 3228 JS.Expression _emitSetSimpleIdentifier( |
3228 SimpleIdentifier node, Expression rhs) { | 3229 SimpleIdentifier node, Expression rhs) { |
3229 JS.Expression unimplemented() { | 3230 JS.Expression unimplemented() { |
3230 return _badAssignment("Unimplemented: unknown name '$node'", node, rhs); | 3231 return _badAssignment("Unimplemented: unknown name '$node'", node, rhs); |
3231 } | 3232 } |
3232 | 3233 |
3233 var accessor = node.staticElement; | 3234 var accessor = staticElementForIdentifier(node); |
3234 if (accessor == null) return unimplemented(); | 3235 if (accessor == null) return unimplemented(); |
3235 | 3236 |
3236 // Get the original declaring element. If we had a property accessor, this | 3237 // Get the original declaring element. If we had a property accessor, this |
3237 // indirects back to a (possibly synthetic) field. | 3238 // indirects back to a (possibly synthetic) field. |
3238 var element = accessor; | 3239 var element = accessor; |
3239 if (accessor is PropertyAccessorElement) element = accessor.variable; | 3240 if (accessor is PropertyAccessorElement) element = accessor.variable; |
3240 | 3241 |
3241 _declareBeforeUse(element); | 3242 _declareBeforeUse(element); |
3242 | 3243 |
3243 if (element is LocalVariableElement || element is ParameterElement) { | 3244 if (element is LocalVariableElement || element is ParameterElement) { |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3385 } | 3386 } |
3386 | 3387 |
3387 var result = _emitForeignJS(node); | 3388 var result = _emitForeignJS(node); |
3388 if (result != null) return result; | 3389 if (result != null) return result; |
3389 | 3390 |
3390 var target = _getTarget(node); | 3391 var target = _getTarget(node); |
3391 if (target == null || isLibraryPrefix(target)) { | 3392 if (target == null || isLibraryPrefix(target)) { |
3392 return _emitFunctionCall(node); | 3393 return _emitFunctionCall(node); |
3393 } | 3394 } |
3394 if (node.methodName.name == 'call') { | 3395 if (node.methodName.name == 'call') { |
3395 var targetType = target.staticType; | 3396 var targetType = staticTypeForExpression(target); |
3396 if (targetType is FunctionType) { | 3397 if (targetType is FunctionType) { |
3397 // Call methods on function types should be handled as regular function | 3398 // Call methods on function types should be handled as regular function |
3398 // invocations. | 3399 // invocations. |
3399 return _emitFunctionCall(node, node.target); | 3400 return _emitFunctionCall(node, node.target); |
3400 } | 3401 } |
3401 if (targetType.isDartCoreFunction || targetType.isDynamic) { | 3402 if (targetType.isDartCoreFunction || targetType.isDynamic) { |
3402 // TODO(vsm): Can a call method take generic type parameters? | 3403 // TODO(vsm): Can a call method take generic type parameters? |
3403 return _emitDynamicInvoke(node, _visit(target), | 3404 return _emitDynamicInvoke(node, _visit(target), |
3404 _visit(node.argumentList) as List<JS.Expression>); | 3405 _visit(node.argumentList) as List<JS.Expression>); |
3405 } | 3406 } |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3860 | 3861 |
3861 @override | 3862 @override |
3862 visitVariableDeclaration(VariableDeclaration node) { | 3863 visitVariableDeclaration(VariableDeclaration node) { |
3863 if (node.element is PropertyInducingElement) { | 3864 if (node.element is PropertyInducingElement) { |
3864 // Static and instance fields are handled elsewhere. | 3865 // Static and instance fields are handled elsewhere. |
3865 assert(node.element is TopLevelVariableElement); | 3866 assert(node.element is TopLevelVariableElement); |
3866 return _emitTopLevelField(node); | 3867 return _emitTopLevelField(node); |
3867 } | 3868 } |
3868 | 3869 |
3869 var name = | 3870 var name = |
3870 new JS.Identifier(node.name.name, type: emitTypeRef(node.element.type)); | 3871 new JS.Identifier(node.name.name, type: emitTypeRef(elementForVariableDe
claration(node).type)); |
3871 return new JS.VariableInitialization(name, _visitInitializer(node)); | 3872 return new JS.VariableInitialization(name, _visitInitializer(node)); |
3872 } | 3873 } |
3873 | 3874 |
3874 /// Try to emit a constant static field. | 3875 /// Try to emit a constant static field. |
3875 /// | 3876 /// |
3876 /// If the field's initializer does not cause side effects, and if all of | 3877 /// If the field's initializer does not cause side effects, and if all of |
3877 /// dependencies are safe to refer to while we are initializing the class, | 3878 /// dependencies are safe to refer to while we are initializing the class, |
3878 /// then we can initialize it eagerly: | 3879 /// then we can initialize it eagerly: |
3879 /// | 3880 /// |
3880 /// // Baz must be const constructor, and the name "Baz" must be defined | 3881 /// // Baz must be const constructor, and the name "Baz" must be defined |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4077 var args = _visit(argumentList) as List<JS.Expression>; | 4078 var args = _visit(argumentList) as List<JS.Expression>; |
4078 if (args.isEmpty) { | 4079 if (args.isEmpty) { |
4079 return js.call('{}'); | 4080 return js.call('{}'); |
4080 } | 4081 } |
4081 assert(args.single is JS.ObjectInitializer); | 4082 assert(args.single is JS.ObjectInitializer); |
4082 return args.single; | 4083 return args.single; |
4083 } | 4084 } |
4084 | 4085 |
4085 @override | 4086 @override |
4086 visitInstanceCreationExpression(InstanceCreationExpression node) { | 4087 visitInstanceCreationExpression(InstanceCreationExpression node) { |
4087 var element = node.staticElement; | 4088 var element = staticElementForConstructorReference(node); |
4088 var constructor = node.constructorName; | 4089 var constructor = node.constructorName; |
4089 var name = constructor.name; | 4090 var name = constructor.name; |
4090 var type = constructor.type.type; | 4091 var type = constructor.type.type; |
4091 if (node.isConst && | 4092 if (node.isConst && |
4092 element?.name == 'fromEnvironment' && | 4093 element?.name == 'fromEnvironment' && |
4093 element.library.isDartCore) { | 4094 element.library.isDartCore) { |
4094 var value = node.accept(_constants.constantVisitor); | 4095 var value = node.accept(_constants.constantVisitor); |
4095 | 4096 |
4096 if (value == null || value.isNull) { | 4097 if (value == null || value.isNull) { |
4097 return new JS.LiteralNull(); | 4098 return new JS.LiteralNull(); |
(...skipping 1668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5766 bool _isDeferredLoadLibrary(Expression target, SimpleIdentifier name) { | 5767 bool _isDeferredLoadLibrary(Expression target, SimpleIdentifier name) { |
5767 if (name.name != "loadLibrary") return false; | 5768 if (name.name != "loadLibrary") return false; |
5768 | 5769 |
5769 if (target is! SimpleIdentifier) return false; | 5770 if (target is! SimpleIdentifier) return false; |
5770 var targetIdentifier = target as SimpleIdentifier; | 5771 var targetIdentifier = target as SimpleIdentifier; |
5771 | 5772 |
5772 if (targetIdentifier.staticElement is! PrefixElement) return false; | 5773 if (targetIdentifier.staticElement is! PrefixElement) return false; |
5773 var prefix = targetIdentifier.staticElement as PrefixElement; | 5774 var prefix = targetIdentifier.staticElement as PrefixElement; |
5774 | 5775 |
5775 // The library the prefix is referring to must come from a deferred import. | 5776 // The library the prefix is referring to must come from a deferred import. |
5776 var containingLibrary = (target.root as CompilationUnit).element.library; | 5777 var containingLibrary = elementForCompilationUnit(target.root as CompilationUn
it).library; |
5777 var imports = containingLibrary.getImportsWithPrefix(prefix); | 5778 var imports = containingLibrary.getImportsWithPrefix(prefix); |
5778 return imports.length == 1 && imports[0].isDeferred; | 5779 return imports.length == 1 && imports[0].isDeferred; |
5779 } | 5780 } |
OLD | NEW |