| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 dart2js.js_emitter.full_emitter; | 5 library dart2js.js_emitter.full_emitter; |
| 6 | 6 |
| 7 import 'dart:convert'; | 7 import 'dart:convert'; |
| 8 import 'dart:collection' show HashMap; | 8 import 'dart:collection' show HashMap; |
| 9 | 9 |
| 10 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; | 10 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; |
| 11 import 'package:js_runtime/shared/embedded_names.dart' show | 11 import 'package:js_runtime/shared/embedded_names.dart' show |
| 12 JsBuiltin, | 12 JsBuiltin, |
| 13 JsGetName; | 13 JsGetName; |
| 14 | 14 |
| 15 import '../headers.dart'; | 15 import '../headers.dart'; |
| 16 | 16 |
| 17 import '../js_emitter.dart' hide Emitter; | 17 import '../js_emitter.dart' hide Emitter; |
| 18 import '../js_emitter.dart' as js_emitter show Emitter; | 18 import '../js_emitter.dart' as js_emitter show Emitter; |
| 19 | 19 |
| 20 import '../model.dart'; | 20 import '../model.dart'; |
| 21 import '../program_builder/program_builder.dart'; | 21 import '../program_builder/program_builder.dart'; |
| 22 | 22 |
| 23 import '../../common.dart'; | 23 import '../../common.dart'; |
| 24 | 24 |
| 25 import '../../constants/values.dart'; | 25 import '../../constants/values.dart'; |
| 26 | 26 |
| 27 import '../../deferred_load.dart' show OutputUnit; | 27 import '../../deferred_load.dart' show OutputUnit; |
| 28 | 28 |
| 29 import '../../diagnostics/messages.dart' show MessageKind; | 29 import '../../diagnostics/diagnostic_listener.dart' show |
| 30 DiagnosticReporter; |
| 31 |
| 32 import '../../diagnostics/messages.dart' show |
| 33 MessageKind; |
| 30 | 34 |
| 31 import '../../diagnostics/spannable.dart' show | 35 import '../../diagnostics/spannable.dart' show |
| 32 NO_LOCATION_SPANNABLE; | 36 NO_LOCATION_SPANNABLE; |
| 33 | 37 |
| 34 import '../../elements/elements.dart' show | 38 import '../../elements/elements.dart' show |
| 35 ConstructorBodyElement, | 39 ConstructorBodyElement, |
| 36 ElementKind, | 40 ElementKind, |
| 37 FieldElement, | 41 FieldElement, |
| 38 Name, | 42 Name, |
| 39 ParameterElement, | 43 ParameterElement, |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 cachedClassBuilders = compiler.cacheStrategy.newMap(), | 189 cachedClassBuilders = compiler.cacheStrategy.newMap(), |
| 186 cachedElements = compiler.cacheStrategy.newSet() { | 190 cachedElements = compiler.cacheStrategy.newSet() { |
| 187 constantEmitter = new ConstantEmitter( | 191 constantEmitter = new ConstantEmitter( |
| 188 compiler, namer, this.constantReference, constantListGenerator); | 192 compiler, namer, this.constantReference, constantListGenerator); |
| 189 containerBuilder.emitter = this; | 193 containerBuilder.emitter = this; |
| 190 classEmitter.emitter = this; | 194 classEmitter.emitter = this; |
| 191 nsmEmitter.emitter = this; | 195 nsmEmitter.emitter = this; |
| 192 interceptorEmitter.emitter = this; | 196 interceptorEmitter.emitter = this; |
| 193 } | 197 } |
| 194 | 198 |
| 199 DiagnosticReporter get reporter => compiler.reporter; |
| 200 |
| 195 List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) { | 201 List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) { |
| 196 return _cspPrecompiledFunctions.putIfAbsent( | 202 return _cspPrecompiledFunctions.putIfAbsent( |
| 197 outputUnit, | 203 outputUnit, |
| 198 () => new List<jsAst.Node>()); | 204 () => new List<jsAst.Node>()); |
| 199 } | 205 } |
| 200 | 206 |
| 201 List<jsAst.Expression> cspPrecompiledConstructorNamesFor( | 207 List<jsAst.Expression> cspPrecompiledConstructorNamesFor( |
| 202 OutputUnit outputUnit) { | 208 OutputUnit outputUnit) { |
| 203 return _cspPrecompiledConstructorNames.putIfAbsent( | 209 return _cspPrecompiledConstructorNames.putIfAbsent( |
| 204 outputUnit, | 210 outputUnit, |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 return jsAst.js.expressionTemplateFor("$typesAccess[#]"); | 414 return jsAst.js.expressionTemplateFor("$typesAccess[#]"); |
| 409 | 415 |
| 410 case JsBuiltin.createDartClosureFromNameOfStaticFunction: | 416 case JsBuiltin.createDartClosureFromNameOfStaticFunction: |
| 411 // The global-functions map contains a map from name to tear-off | 417 // The global-functions map contains a map from name to tear-off |
| 412 // getters. | 418 // getters. |
| 413 String functionGettersMap = | 419 String functionGettersMap = |
| 414 generateEmbeddedGlobalAccessString(embeddedNames.GLOBAL_FUNCTIONS); | 420 generateEmbeddedGlobalAccessString(embeddedNames.GLOBAL_FUNCTIONS); |
| 415 return jsAst.js.expressionTemplateFor("$functionGettersMap[#]()"); | 421 return jsAst.js.expressionTemplateFor("$functionGettersMap[#]()"); |
| 416 | 422 |
| 417 default: | 423 default: |
| 418 compiler.internalError(NO_LOCATION_SPANNABLE, | 424 reporter.internalError(NO_LOCATION_SPANNABLE, |
| 419 "Unhandled Builtin: $builtin"); | 425 "Unhandled Builtin: $builtin"); |
| 420 return null; | 426 return null; |
| 421 } | 427 } |
| 422 } | 428 } |
| 423 | 429 |
| 424 List<jsAst.Statement> buildTrivialNsmHandlers(){ | 430 List<jsAst.Statement> buildTrivialNsmHandlers(){ |
| 425 return nsmEmitter.buildTrivialNsmHandlers(); | 431 return nsmEmitter.buildTrivialNsmHandlers(); |
| 426 } | 432 } |
| 427 | 433 |
| 428 jsAst.Statement buildNativeInfoHandler( | 434 jsAst.Statement buildNativeInfoHandler( |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 Element element = elementOrSelector; | 553 Element element = elementOrSelector; |
| 548 if (element.isGenerativeConstructorBody) { | 554 if (element.isGenerativeConstructorBody) { |
| 549 return null; | 555 return null; |
| 550 } else if (element.isClass) { | 556 } else if (element.isClass) { |
| 551 ClassElement cls = element; | 557 ClassElement cls = element; |
| 552 if (cls.isUnnamedMixinApplication) return null; | 558 if (cls.isUnnamedMixinApplication) return null; |
| 553 return cls.name; | 559 return cls.name; |
| 554 } else if (element.isTypedef) { | 560 } else if (element.isTypedef) { |
| 555 return element.name; | 561 return element.name; |
| 556 } | 562 } |
| 557 throw compiler.internalError(element, | 563 throw reporter.internalError(element, |
| 558 'Do not know how to reflect on this $element.'); | 564 'Do not know how to reflect on this $element.'); |
| 559 } | 565 } |
| 560 | 566 |
| 561 String namedParametersAsReflectionNames(CallStructure structure) { | 567 String namedParametersAsReflectionNames(CallStructure structure) { |
| 562 if (structure.isUnnamed) return ''; | 568 if (structure.isUnnamed) return ''; |
| 563 String names = structure.getOrderedNamedArguments().join(':'); | 569 String names = structure.getOrderedNamedArguments().join(':'); |
| 564 return ':$names'; | 570 return ':$names'; |
| 565 } | 571 } |
| 566 | 572 |
| 567 jsAst.Statement buildCspPrecompiledFunctionFor( | 573 jsAst.Statement buildCspPrecompiledFunctionFor( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 585 'result': new jsAst.ArrayInitializer( | 591 'result': new jsAst.ArrayInitializer( |
| 586 cspPrecompiledConstructorNamesFor(outputUnit))}); | 592 cspPrecompiledConstructorNamesFor(outputUnit))}); |
| 587 } else { | 593 } else { |
| 588 return js.comment("Constructors are generated at runtime."); | 594 return js.comment("Constructors are generated at runtime."); |
| 589 } | 595 } |
| 590 } | 596 } |
| 591 | 597 |
| 592 void assembleClass(Class cls, ClassBuilder enclosingBuilder, | 598 void assembleClass(Class cls, ClassBuilder enclosingBuilder, |
| 593 Fragment fragment) { | 599 Fragment fragment) { |
| 594 ClassElement classElement = cls.element; | 600 ClassElement classElement = cls.element; |
| 595 compiler.withCurrentElement(classElement, () { | 601 reporter.withCurrentElement(classElement, () { |
| 596 if (compiler.hasIncrementalSupport) { | 602 if (compiler.hasIncrementalSupport) { |
| 597 ClassBuilder cachedBuilder = | 603 ClassBuilder cachedBuilder = |
| 598 cachedClassBuilders.putIfAbsent(classElement, () { | 604 cachedClassBuilders.putIfAbsent(classElement, () { |
| 599 ClassBuilder builder = | 605 ClassBuilder builder = |
| 600 new ClassBuilder.forClass(classElement, namer); | 606 new ClassBuilder.forClass(classElement, namer); |
| 601 classEmitter.emitClass(cls, builder, fragment); | 607 classEmitter.emitClass(cls, builder, fragment); |
| 602 return builder; | 608 return builder; |
| 603 }); | 609 }); |
| 604 invariant(classElement, cachedBuilder.fields.isEmpty); | 610 invariant(classElement, cachedBuilder.fields.isEmpty); |
| 605 invariant(classElement, cachedBuilder.superName == null); | 611 invariant(classElement, cachedBuilder.superName == null); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 | 644 |
| 639 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit); | 645 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit); |
| 640 JavaScriptConstantCompiler handler = backend.constants; | 646 JavaScriptConstantCompiler handler = backend.constants; |
| 641 List<jsAst.Statement> parts = <jsAst.Statement>[]; | 647 List<jsAst.Statement> parts = <jsAst.Statement>[]; |
| 642 | 648 |
| 643 Iterable<Element> fields = outputStaticNonFinalFieldLists[outputUnit]; | 649 Iterable<Element> fields = outputStaticNonFinalFieldLists[outputUnit]; |
| 644 // If the outputUnit does not contain any static non-final fields, then | 650 // If the outputUnit does not contain any static non-final fields, then |
| 645 // [fields] is `null`. | 651 // [fields] is `null`. |
| 646 if (fields != null) { | 652 if (fields != null) { |
| 647 for (Element element in fields) { | 653 for (Element element in fields) { |
| 648 compiler.withCurrentElement(element, () { | 654 reporter.withCurrentElement(element, () { |
| 649 ConstantValue constant = handler.getInitialValueFor(element); | 655 ConstantValue constant = handler.getInitialValueFor(element); |
| 650 parts.add(buildInitialization(element, constantReference(constant))); | 656 parts.add(buildInitialization(element, constantReference(constant))); |
| 651 }); | 657 }); |
| 652 } | 658 } |
| 653 } | 659 } |
| 654 | 660 |
| 655 if (inMainUnit && outputStaticNonFinalFieldLists.length > 1) { | 661 if (inMainUnit && outputStaticNonFinalFieldLists.length > 1) { |
| 656 // In the main output-unit we output a stub initializer for deferred | 662 // In the main output-unit we output a stub initializer for deferred |
| 657 // variables, so that `isolateProperties` stays a fast object. | 663 // variables, so that `isolateProperties` stays a fast object. |
| 658 outputStaticNonFinalFieldLists.forEach( | 664 outputStaticNonFinalFieldLists.forEach( |
| 659 (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) { | 665 (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) { |
| 660 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit. | 666 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit. |
| 661 for (Element element in fields) { | 667 for (Element element in fields) { |
| 662 compiler.withCurrentElement(element, () { | 668 reporter.withCurrentElement(element, () { |
| 663 parts.add(buildInitialization(element, jsAst.number(0))); | 669 parts.add(buildInitialization(element, jsAst.number(0))); |
| 664 }); | 670 }); |
| 665 } | 671 } |
| 666 }); | 672 }); |
| 667 } | 673 } |
| 668 | 674 |
| 669 return new jsAst.Block(parts); | 675 return new jsAst.Block(parts); |
| 670 } | 676 } |
| 671 | 677 |
| 672 jsAst.Statement buildLazilyInitializedStaticFields() { | 678 jsAst.Statement buildLazilyInitializedStaticFields() { |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 return js.statement(''' | 899 return js.statement(''' |
| 894 function init() { | 900 function init() { |
| 895 $isolatePropertiesName = Object.create(null); | 901 $isolatePropertiesName = Object.create(null); |
| 896 #allClasses = map(); | 902 #allClasses = map(); |
| 897 #getTypeFromName = function(name) {return #allClasses[name];}; | 903 #getTypeFromName = function(name) {return #allClasses[name];}; |
| 898 #interceptorsByTag = map(); | 904 #interceptorsByTag = map(); |
| 899 #leafTags = map(); | 905 #leafTags = map(); |
| 900 #finishedClasses = map(); | 906 #finishedClasses = map(); |
| 901 | 907 |
| 902 if (#needsLazyInitializer) { | 908 if (#needsLazyInitializer) { |
| 903 // [staticName] is only provided in non-minified mode. If missing, we | 909 // [staticName] is only provided in non-minified mode. If missing, we |
| 904 // fall back to [fieldName]. Likewise, [prototype] is optional and | 910 // fall back to [fieldName]. Likewise, [prototype] is optional and |
| 905 // defaults to the isolateProperties object. | 911 // defaults to the isolateProperties object. |
| 906 $lazyInitializerName = function (fieldName, getterName, lazyValue, | 912 $lazyInitializerName = function (fieldName, getterName, lazyValue, |
| 907 staticName, prototype) { | 913 staticName, prototype) { |
| 908 if (!#lazies) #lazies = Object.create(null); | 914 if (!#lazies) #lazies = Object.create(null); |
| 909 #lazies[fieldName] = getterName; | 915 #lazies[fieldName] = getterName; |
| 910 | 916 |
| 911 // 'prototype' will be undefined except if we are doing an update | 917 // 'prototype' will be undefined except if we are doing an update |
| 912 // during incremental compilation. In this case we put the lazy | 918 // during incremental compilation. In this case we put the lazy |
| 913 // field directly on the isolate instead of the isolateProperties. | 919 // field directly on the isolate instead of the isolateProperties. |
| 914 prototype = prototype || $isolatePropertiesName; | 920 prototype = prototype || $isolatePropertiesName; |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1325 return new jsAst.Block(parts); | 1331 return new jsAst.Block(parts); |
| 1326 } | 1332 } |
| 1327 | 1333 |
| 1328 void checkEverythingEmitted(Iterable<Element> elements) { | 1334 void checkEverythingEmitted(Iterable<Element> elements) { |
| 1329 List<Element> pendingStatics; | 1335 List<Element> pendingStatics; |
| 1330 if (!compiler.hasIncrementalSupport) { | 1336 if (!compiler.hasIncrementalSupport) { |
| 1331 pendingStatics = | 1337 pendingStatics = |
| 1332 Elements.sortedByPosition(elements.where((e) => !e.isLibrary)); | 1338 Elements.sortedByPosition(elements.where((e) => !e.isLibrary)); |
| 1333 | 1339 |
| 1334 pendingStatics.forEach((element) => | 1340 pendingStatics.forEach((element) => |
| 1335 compiler.reportInfo( | 1341 reporter.reportInfo( |
| 1336 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); | 1342 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); |
| 1337 } | 1343 } |
| 1338 | 1344 |
| 1339 if (pendingStatics != null && !pendingStatics.isEmpty) { | 1345 if (pendingStatics != null && !pendingStatics.isEmpty) { |
| 1340 compiler.internalError(pendingStatics.first, | 1346 reporter.internalError(pendingStatics.first, |
| 1341 'Pending statics (see above).'); | 1347 'Pending statics (see above).'); |
| 1342 } | 1348 } |
| 1343 } | 1349 } |
| 1344 | 1350 |
| 1345 void assembleLibrary(Library library, Fragment fragment) { | 1351 void assembleLibrary(Library library, Fragment fragment) { |
| 1346 LibraryElement libraryElement = library.element; | 1352 LibraryElement libraryElement = library.element; |
| 1347 | 1353 |
| 1348 assembleStaticFunctions(library.statics, fragment); | 1354 assembleStaticFunctions(library.statics, fragment); |
| 1349 | 1355 |
| 1350 ClassBuilder libraryBuilder = | 1356 ClassBuilder libraryBuilder = |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1805 Map<OutputUnit, String> deferredLoadHashes = | 1811 Map<OutputUnit, String> deferredLoadHashes = |
| 1806 emitDeferredOutputUnits(deferredParts); | 1812 emitDeferredOutputUnits(deferredParts); |
| 1807 | 1813 |
| 1808 deferredHashTokens.forEach((OutputUnit key, _DeferredOutputUnitHash token) { | 1814 deferredHashTokens.forEach((OutputUnit key, _DeferredOutputUnitHash token) { |
| 1809 token.setHash(deferredLoadHashes[key]); | 1815 token.setHash(deferredLoadHashes[key]); |
| 1810 }); | 1816 }); |
| 1811 emitMainOutputUnit(program.mainFragment.outputUnit, mainOutput); | 1817 emitMainOutputUnit(program.mainFragment.outputUnit, mainOutput); |
| 1812 | 1818 |
| 1813 if (backend.requiresPreamble && | 1819 if (backend.requiresPreamble && |
| 1814 !backend.htmlLibraryIsLoaded) { | 1820 !backend.htmlLibraryIsLoaded) { |
| 1815 compiler.reportHintMessage( | 1821 reporter.reportHintMessage( |
| 1816 NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE); | 1822 NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE); |
| 1817 } | 1823 } |
| 1818 // Return the total program size. | 1824 // Return the total program size. |
| 1819 return outputBuffers.values.fold(0, (a, b) => a + b.length); | 1825 return outputBuffers.values.fold(0, (a, b) => a + b.length); |
| 1820 } | 1826 } |
| 1821 | 1827 |
| 1822 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) { | 1828 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) { |
| 1823 if (sourceMapUri != null && fileUri != null) { | 1829 if (sourceMapUri != null && fileUri != null) { |
| 1824 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); | 1830 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); |
| 1825 return ''' | 1831 return ''' |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1839 ClassElement cls = | 1845 ClassElement cls = |
| 1840 element.enclosingClassOrCompilationUnit.declaration; | 1846 element.enclosingClassOrCompilationUnit.declaration; |
| 1841 if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls) && | 1847 if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls) && |
| 1842 !cls.isNative && | 1848 !cls.isNative && |
| 1843 compiler.deferredLoadTask.outputUnitForElement(element) == | 1849 compiler.deferredLoadTask.outputUnitForElement(element) == |
| 1844 compiler.deferredLoadTask.outputUnitForElement(cls)) { | 1850 compiler.deferredLoadTask.outputUnitForElement(cls)) { |
| 1845 owner = cls; | 1851 owner = cls; |
| 1846 } | 1852 } |
| 1847 } | 1853 } |
| 1848 if (owner == null) { | 1854 if (owner == null) { |
| 1849 compiler.internalError(element, 'Owner is null.'); | 1855 reporter.internalError(element, 'Owner is null.'); |
| 1850 } | 1856 } |
| 1851 return elementDescriptors | 1857 return elementDescriptors |
| 1852 .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>()) | 1858 .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>()) |
| 1853 .putIfAbsent(owner, () { | 1859 .putIfAbsent(owner, () { |
| 1854 return new ClassBuilder(owner, namer, owner.isClass); | 1860 return new ClassBuilder(owner, namer, owner.isClass); |
| 1855 }); | 1861 }); |
| 1856 } | 1862 } |
| 1857 | 1863 |
| 1858 /// Emits support-code for deferred loading into [output]. | 1864 /// Emits support-code for deferred loading into [output]. |
| 1859 jsAst.Statement buildDeferredBoilerPlate( | 1865 jsAst.Statement buildDeferredBoilerPlate( |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2119 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2125 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
| 2120 if (element.isInstanceMember) { | 2126 if (element.isInstanceMember) { |
| 2121 cachedClassBuilders.remove(element.enclosingClass); | 2127 cachedClassBuilders.remove(element.enclosingClass); |
| 2122 | 2128 |
| 2123 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2129 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
| 2124 | 2130 |
| 2125 } | 2131 } |
| 2126 } | 2132 } |
| 2127 } | 2133 } |
| 2128 } | 2134 } |
| OLD | NEW |