Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Unified Diff: sdk/lib/_internal/compiler/implementation/deferred_load.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/deferred_load.dart
diff --git a/sdk/lib/_internal/compiler/implementation/deferred_load.dart b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
deleted file mode 100644
index ae262b7764f8f59e467b5ca0755d744d3678155e..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/compiler/implementation/deferred_load.dart
+++ /dev/null
@@ -1,767 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library deferred_load;
-
-import 'constants/expressions.dart';
-import 'constants/values.dart' show
- ConstantValue,
- ConstructedConstantValue,
- DeferredConstantValue,
- StringConstantValue;
-
-import 'dart2jslib.dart' show
- Backend,
- Compiler,
- CompilerTask,
- invariant,
- MessageKind;
-
-import 'dart_backend/dart_backend.dart' show
- DartBackend;
-
-import 'js_backend/js_backend.dart' show
- JavaScriptBackend;
-
-import 'elements/elements.dart' show
- AstElement,
- ClassElement,
- Element,
- ElementKind,
- Elements,
- FunctionElement,
- LibraryElement,
- MetadataAnnotation,
- PrefixElement,
- ScopeContainerElement,
- TypedefElement,
- VoidElement;
-
-import 'util/util.dart' show
- Link, makeUnique;
-
-import 'util/setlet.dart' show
- Setlet;
-
-import 'tree/tree.dart' show
- Import,
- LibraryTag,
- LibraryDependency,
- LiteralDartString,
- LiteralString,
- NewExpression,
- Node;
-
-import 'tree/tree.dart' as ast;
-
-import 'resolution/resolution.dart' show
- AnalyzableElementX,
- TreeElements;
-
-/// A "hunk" of the program that will be loaded whenever one of its [imports]
-/// are loaded.
-///
-/// Elements that are only used in one deferred import, is in an OutputUnit with
-/// the deferred import as single element in the [imports] set.
-///
-/// Whenever a deferred Element is shared between several deferred imports it is
-/// in an output unit with those imports in the [imports] Set.
-///
-/// OutputUnits are equal if their [imports] are equal.
-class OutputUnit {
- /// The deferred imports that will load this output unit when one of them is
- /// loaded.
- final Setlet<Import> imports = new Setlet<Import>();
-
- /// A unique name representing this [OutputUnit].
- /// Based on the set of [imports].
- String name;
-
- String toString() => "OutputUnit($name)";
-
- bool operator==(OutputUnit other) {
- return imports.length == other.imports.length &&
- imports.containsAll(other.imports);
- }
-
- int get hashCode {
- int sum = 0;
- for (Import import in imports) {
- sum = (sum + import.hashCode) & 0x3FFFFFFF; // Stay in 30 bit range.
- }
- return sum;
- }
-}
-
-/// For each deferred import, find elements and constants to be loaded when that
-/// import is loaded. Elements that are used by several deferred imports are in
-/// shared OutputUnits.
-class DeferredLoadTask extends CompilerTask {
- /// The name of this task.
- String get name => 'Deferred Loading';
-
- /// DeferredLibrary from dart:async
- ClassElement get deferredLibraryClass => compiler.deferredLibraryClass;
-
- /// A synthetic [Import] representing the loading of the main
- /// program.
- final Import _fakeMainImport = new Import(null, new LiteralString(null,
- new LiteralDartString("main")), null, null, null);
-
- /// The OutputUnit that will be loaded when the program starts.
- final OutputUnit mainOutputUnit = new OutputUnit();
-
- /// A set containing (eventually) all output units that will result from the
- /// program.
- final Set<OutputUnit> allOutputUnits = new Set<OutputUnit>();
-
- /// Will be `true` if the program contains deferred libraries.
- bool isProgramSplit = false;
-
- /// A mapping from the name of a defer import to all the output units it
- /// depends on in a list of lists to be loaded in the order they appear.
- ///
- /// For example {"lib1": [[lib1_lib2_lib3], [lib1_lib2, lib1_lib3],
- /// [lib1]]} would mean that in order to load "lib1" first the hunk
- /// lib1_lib2_lib2 should be loaded, then the hunks lib1_lib2 and lib1_lib3
- /// can be loaded in parallel. And finally lib1 can be loaded.
- final Map<String, List<OutputUnit>> hunksToLoad =
- new Map<String, List<OutputUnit>>();
- final Map<Import, String> importDeferName = new Map<Import, String>();
-
- /// A mapping from elements and constants to their output unit. Query this via
- /// [outputUnitForElement]
- final Map<Element, OutputUnit> _elementToOutputUnit =
- new Map<Element, OutputUnit>();
-
- /// A mapping from constants to their output unit. Query this via
- /// [outputUnitForConstant]
- final Map<ConstantValue, OutputUnit> _constantToOutputUnit =
- new Map<ConstantValue, OutputUnit>();
-
- /// All the imports with a [DeferredLibrary] annotation, mapped to the
- /// [LibraryElement] they import.
- /// The main library is included in this set for convenience.
- final Map<Import, LibraryElement> _allDeferredImports =
- new Map<Import, LibraryElement>();
-
- // For each deferred import we want to know exactly what elements have to
- // be loaded.
- Map<Import, Set<Element>> _importedDeferredBy = null;
- Map<Import, Set<ConstantValue>> _constantsDeferredBy = null;
-
- Set<Element> _mainElements = new Set<Element>();
-
- DeferredLoadTask(Compiler compiler) : super(compiler) {
- mainOutputUnit.imports.add(_fakeMainImport);
- }
-
- Backend get backend => compiler.backend;
-
- /// Returns the [OutputUnit] where [element] belongs.
- OutputUnit outputUnitForElement(Element element) {
- if (!isProgramSplit) return mainOutputUnit;
-
- element = element.implementation;
- while (!_elementToOutputUnit.containsKey(element)) {
- // TODO(21051): workaround: it looks like we output annotation constants
- // for classes that we don't include in the output. This seems to happen
- // when we have reflection but can see that some classes are not needed.
- // We still add the annotation but don't run through it below (where we
- // assign every element to its output unit).
- if (element.enclosingElement == null) {
- _elementToOutputUnit[element] = mainOutputUnit;
- break;
- }
- element = element.enclosingElement.implementation;
- }
- return _elementToOutputUnit[element];
- }
-
- /// Returns the [OutputUnit] where [constant] belongs.
- OutputUnit outputUnitForConstant(ConstantValue constant) {
- if (!isProgramSplit) return mainOutputUnit;
-
- return _constantToOutputUnit[constant];
- }
-
- bool isDeferred(Element element) {
- return outputUnitForElement(element) != mainOutputUnit;
- }
-
- /// Returns true if e1 and e2 are in the same output unit.
- bool inSameOutputUnit(Element e1, Element e2) {
- return outputUnitForElement(e1) == outputUnitForElement(e2);
- }
-
- void registerConstantDeferredUse(DeferredConstantValue constant,
- PrefixElement prefix) {
- OutputUnit outputUnit = new OutputUnit();
- outputUnit.imports.add(prefix.deferredImport);
- _constantToOutputUnit[constant] = outputUnit;
- }
-
- /// Answers whether [element] is explicitly deferred when referred to from
- /// [library].
- bool _isExplicitlyDeferred(Element element, LibraryElement library) {
- Link<Import> imports = _getImports(element, library);
- // If the element is not imported explicitly, it is implicitly imported
- // not deferred.
- if (imports.isEmpty) return false;
- // An element could potentially be loaded by several imports. If all of them
- // is explicitly deferred, we say the element is explicitly deferred.
- // TODO(sigurdm): We might want to give a warning if the imports do not
- // agree.
- return imports.every((Import import) => import.isDeferred);
- }
-
- /// Returns a [Link] of every [Import] that imports [element] into [library].
- Link<Import> _getImports(Element element, LibraryElement library) {
- if (element.isClassMember) {
- element = element.enclosingClass;
- }
- if (element.isAccessor) {
- element = (element as FunctionElement).abstractField;
- }
- return library.getImportsFor(element);
- }
-
- /// Finds all elements and constants that [element] depends directly on.
- /// (not the transitive closure.)
- ///
- /// Adds the results to [elements] and [constants].
- void _collectAllElementsAndConstantsResolvedFrom(
- Element element,
- Set<Element> elements,
- Set<ConstantValue> constants,
- isMirrorUsage) {
-
- /// Recursively add the constant and its dependencies to [constants].
- void addConstants(ConstantValue constant) {
- if (constants.contains(constant)) return;
- constants.add(constant);
- if (constant is ConstructedConstantValue) {
- elements.add(constant.type.element);
- }
- constant.getDependencies().forEach(addConstants);
- }
-
- /// Collects all direct dependencies of [element].
- ///
- /// The collected dependent elements and constants are are added to
- /// [elements] and [constants] respectively.
- void collectDependencies(Element element) {
- // TODO(johnniwinther): Remove this when [AbstractFieldElement] has been
- // removed.
- if (element is! AstElement) return;
- AstElement astElement = element;
-
- // TODO(sigurdm): We want to be more specific about this - need a better
- // way to query "liveness".
- if (astElement is! TypedefElement &&
- !compiler.enqueuer.resolution.hasBeenResolved(astElement)) {
- return;
- }
-
- TreeElements treeElements = astElement.resolvedAst.elements;
-
- assert(treeElements != null);
-
- for (Element dependency in treeElements.allElements) {
- if (dependency.isLocal && !dependency.isFunction) continue;
- if (dependency.isErroneous) continue;
- if (dependency.isTypeVariable) continue;
-
- elements.add(dependency);
- }
- treeElements.forEachConstantNode((Node node, _) {
- // Explicitly depend on the backend constants.
- addConstants(
- backend.constants.getConstantForNode(node, treeElements).value);
- });
- elements.addAll(treeElements.otherDependencies);
- }
-
- // TODO(sigurdm): How is metadata on a patch-class handled?
- for (MetadataAnnotation metadata in element.metadata) {
- ConstantExpression constant =
- backend.constants.getConstantForMetadata(metadata);
- if (constant != null) {
- addConstants(constant.value);
- }
- }
- if (element.isClass) {
- // If we see a class, add everything its live instance members refer
- // to. Static members are not relevant, unless we are processing
- // extra dependencies due to mirrors.
- void addLiveInstanceMember(Element element) {
- if (!compiler.enqueuer.resolution.hasBeenResolved(element)) return;
- if (!isMirrorUsage && !element.isInstanceMember) return;
- collectDependencies(element.implementation);
- }
- ClassElement cls = element.declaration;
- cls.forEachLocalMember(addLiveInstanceMember);
- if (cls.implementation != cls) {
- // TODO(ahe): Why doesn't ClassElement.forEachLocalMember do this?
- cls.implementation.forEachLocalMember(addLiveInstanceMember);
- }
- for (var type in cls.implementation.allSupertypes) {
- elements.add(type.element.implementation);
- }
- elements.add(cls.implementation);
- } else if (Elements.isStaticOrTopLevel(element) ||
- element.isConstructor) {
- collectDependencies(element);
- }
- if (element.isGenerativeConstructor) {
- // When instantiating a class, we record a reference to the
- // constructor, not the class itself. We must add all the
- // instance members of the constructor's class.
- ClassElement implementation =
- element.enclosingClass.implementation;
- _collectAllElementsAndConstantsResolvedFrom(
- implementation, elements, constants, isMirrorUsage);
- }
-
- // Other elements, in particular instance members, are ignored as
- // they are processed as part of the class.
- }
-
- /// Returns the transitive closure of all libraries that are imported
- /// from root without DeferredLibrary annotations.
- Set<LibraryElement> _nonDeferredReachableLibraries(LibraryElement root) {
- Set<LibraryElement> result = new Set<LibraryElement>();
-
- void traverseLibrary(LibraryElement library) {
- if (result.contains(library)) return;
- result.add(library);
-
- iterateTags(LibraryElement library) {
- // TODO(sigurdm): Make helper getLibraryDependencyTags when tags is
- // changed to be a List instead of a Link.
- for (LibraryTag tag in library.tags) {
- if (tag is! LibraryDependency) continue;
- LibraryDependency libraryDependency = tag;
- if (!(libraryDependency is Import && libraryDependency.isDeferred)) {
- LibraryElement importedLibrary = library.getLibraryFromTag(tag);
- traverseLibrary(importedLibrary);
- }
- }
- }
-
- iterateTags(library);
- if (library.isPatched) {
- iterateTags(library.implementation);
- }
- }
- traverseLibrary(root);
- result.add(compiler.coreLibrary);
- return result;
- }
-
- /// Recursively traverses the graph of dependencies from [element], mapping
- /// deferred imports to each dependency it needs in the sets
- /// [_importedDeferredBy] and [_constantsDeferredBy].
- void _mapDependencies(Element element, Import import,
- {isMirrorUsage: false}) {
- Set<Element> elements = _importedDeferredBy.putIfAbsent(import,
- () => new Set<Element>());
- Set<ConstantValue> constants = _constantsDeferredBy.putIfAbsent(import,
- () => new Set<ConstantValue>());
-
- // Only process elements once, unless we are doing dependencies due to
- // mirrors, which are added in additional traversals.
- if (!isMirrorUsage && elements.contains(element)) return;
- // Anything used directly by main will be loaded from the start
- // We do not need to traverse it again.
- if (import != _fakeMainImport && _mainElements.contains(element)) return;
-
- // Here we modify [_importedDeferredBy].
- elements.add(element);
-
- Set<Element> dependentElements = new Set<Element>();
-
- // This call can modify [_importedDeferredBy] and [_constantsDeferredBy].
- _collectAllElementsAndConstantsResolvedFrom(
- element, dependentElements, constants, isMirrorUsage);
-
- LibraryElement library = element.library;
- for (Element dependency in dependentElements) {
- if (_isExplicitlyDeferred(dependency, library)) {
- for (Import deferredImport in _getImports(dependency, library)) {
- _mapDependencies(dependency, deferredImport);
- };
- } else {
- _mapDependencies(dependency, import);
- }
- }
- }
-
- /// Adds extra dependencies coming from mirror usage.
- ///
- /// The elements are added with [_mapDependencies].
- void _addMirrorElements() {
- void mapDependenciesIfResolved(Element element, Import deferredImport) {
- // If an element is the target of a MirrorsUsed annotation but never used
- // It will not be resolved, and we should not call isNeededForReflection.
- // TODO(sigurdm): Unresolved elements should just answer false when
- // asked isNeededForReflection. Instead an internal error is triggered.
- // So we have to filter them out here.
- if (element is AnalyzableElementX && !element.hasTreeElements) return;
- if (compiler.backend.isAccessibleByReflection(element)) {
- _mapDependencies(element, deferredImport, isMirrorUsage: true);
- }
- }
-
- // For each deferred import we analyze all elements reachable from the
- // imported library through non-deferred imports.
- handleLibrary(LibraryElement library, Import deferredImport) {
- library.implementation.forEachLocalMember((Element element) {
- mapDependenciesIfResolved(element, deferredImport);
- });
-
- for (MetadataAnnotation metadata in library.metadata) {
- ConstantExpression constant =
- backend.constants.getConstantForMetadata(metadata);
- if (constant != null) {
- _mapDependencies(constant.value.computeType(compiler).element,
- deferredImport);
- }
- }
- for (LibraryTag tag in library.tags) {
- for (MetadataAnnotation metadata in tag.metadata) {
- ConstantExpression constant =
- backend.constants.getConstantForMetadata(metadata);
- if (constant != null) {
- _mapDependencies(constant.value.computeType(compiler).element,
- deferredImport);
- }
- }
- }
- }
-
- for (Import deferredImport in _allDeferredImports.keys) {
- LibraryElement deferredLibrary = _allDeferredImports[deferredImport];
- for (LibraryElement library in
- _nonDeferredReachableLibraries(deferredLibrary)) {
- handleLibrary(library, deferredImport);
- }
- }
- }
-
- /// Computes a unique string for the name field for each outputUnit.
- ///
- /// Also sets up the [hunksToLoad] mapping.
- void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) {
- Set<String> usedImportNames = new Set<String>();
-
- // Finds the first argument to the [DeferredLibrary] annotation
- void computeImportDeferName(Import import) {
- String result;
- if (import == _fakeMainImport) {
- result = "main";
- } else if (import.isDeferred) {
- result = import.prefix.toString();
- } else {
- Link<MetadataAnnotation> metadatas = import.metadata;
- assert(metadatas != null);
- for (MetadataAnnotation metadata in metadatas) {
- metadata.ensureResolved(compiler);
- Element element =
- metadata.constant.value.computeType(compiler).element;
- if (element == deferredLibraryClass) {
- ConstructedConstantValue constant = metadata.constant.value;
- StringConstantValue s = constant.fields[0];
- result = s.primitiveValue.slowToString();
- break;
- }
- }
- }
- assert(result != null);
- importDeferName[import] = makeUnique(result, usedImportNames);;
- }
-
- int counter = 1;
-
- for (Import import in _allDeferredImports.keys) {
- computeImportDeferName(import);
- }
-
- for (OutputUnit outputUnit in allOutputUnits) {
- if (outputUnit == mainOutputUnit) {
- outputUnit.name = "main";
- } else {
- outputUnit.name = "$counter";
- ++counter;
- }
- }
-
- List sortedOutputUnits = new List.from(allOutputUnits);
- // Sort the output units in descending order of the number of imports they
- // include.
-
- // The loading of the output units mut be ordered because a superclass needs
- // to be initialized before its subclass.
- // But a class can only depend on another class in an output unit shared by
- // a strict superset of the imports:
- // By contradiction: Assume a class C in output unit shared by imports in
- // the set S1 = (lib1,.., lib_n) depends on a class D in an output unit
- // shared by S2 such that S2 not a superset of S1. Let lib_s be a library in
- // S1 not in S2. lib_s must depend on C, and then in turn on D therefore D
- // is not in the right output unit.
- sortedOutputUnits.sort((a, b) => b.imports.length - a.imports.length);
-
- // For each deferred import we find out which outputUnits to load.
- for (Import import in _allDeferredImports.keys) {
- if (import == _fakeMainImport) continue;
- hunksToLoad[importDeferName[import]] = new List<OutputUnit>();
- for (OutputUnit outputUnit in sortedOutputUnits) {
- if (outputUnit == mainOutputUnit) continue;
- if (outputUnit.imports.contains(import)) {
- hunksToLoad[importDeferName[import]].add(outputUnit);
- }
- }
- }
- }
-
- void onResolutionComplete(FunctionElement main) {
- if (!isProgramSplit) {
- allOutputUnits.add(mainOutputUnit);
- return;
- }
- if (main == null) return;
- LibraryElement mainLibrary = main.library;
- _importedDeferredBy = new Map<Import, Set<Element>>();
- _constantsDeferredBy = new Map<Import, Set<ConstantValue>>();
- _importedDeferredBy[_fakeMainImport] = _mainElements;
-
- measureElement(mainLibrary, () {
-
- // Starting from main, traverse the program and find all dependencies.
- _mapDependencies(compiler.mainFunction, _fakeMainImport);
-
- // Also add "global" dependencies to the main OutputUnit. These are
- // things that the backend need but cannot associate with a particular
- // element, for example, startRootIsolate. This set also contains
- // elements for which we lack precise information.
- for (Element element in compiler.globalDependencies.otherDependencies) {
- _mapDependencies(element, _fakeMainImport);
- }
-
- // Now check to see if we have to add more elements due to mirrors.
- if (compiler.mirrorsLibrary != null) {
- _addMirrorElements();
- }
-
- // Build the OutputUnits using these two maps.
- Map<Element, OutputUnit> elementToOutputUnitBuilder =
- new Map<Element, OutputUnit>();
- Map<ConstantValue, OutputUnit> constantToOutputUnitBuilder =
- new Map<ConstantValue, OutputUnit>();
-
- // Reverse the mappings. For each element record an OutputUnit collecting
- // all deferred imports mapped to this element. Same for constants.
- for (Import import in _importedDeferredBy.keys) {
- for (Element element in _importedDeferredBy[import]) {
- // Only one file should be loaded when the program starts, so make
- // sure that only one OutputUnit is created for [fakeMainImport].
- if (import == _fakeMainImport) {
- elementToOutputUnitBuilder[element] = mainOutputUnit;
- } else {
- elementToOutputUnitBuilder
- .putIfAbsent(element, () => new OutputUnit())
- .imports.add(import);
- }
- }
- for (ConstantValue constant in _constantsDeferredBy[import]) {
- // Only one file should be loaded when the program starts, so make
- // sure that only one OutputUnit is created for [fakeMainImport].
- if (import == _fakeMainImport) {
- constantToOutputUnitBuilder[constant] = mainOutputUnit;
- } else {
- constantToOutputUnitBuilder
- .putIfAbsent(constant, () => new OutputUnit())
- .imports.add(import);
- }
- }
- }
-
- // Release maps;
- _importedDeferredBy = null;
- _constantsDeferredBy = null;
-
- // Find all the output units elements/constants have been mapped to, and
- // canonicalize them.
- elementToOutputUnitBuilder.forEach(
- (Element element, OutputUnit outputUnit) {
- OutputUnit representative = allOutputUnits.lookup(outputUnit);
- if (representative == null) {
- representative = outputUnit;
- allOutputUnits.add(representative);
- }
- _elementToOutputUnit[element] = representative;
- });
- constantToOutputUnitBuilder.forEach(
- (ConstantValue constant, OutputUnit outputUnit) {
- OutputUnit representative = allOutputUnits.lookup(outputUnit);
- if (representative == null) {
- representative = outputUnit;
- allOutputUnits.add(representative);
- }
- _constantToOutputUnit[constant] = representative;
- });
-
- // Generate a unique name for each OutputUnit.
- _assignNamesToOutputUnits(allOutputUnits);
- });
- }
-
- void ensureMetadataResolved(Compiler compiler) {
- if (compiler.mainApp == null) return;
- _allDeferredImports[_fakeMainImport] = compiler.mainApp;
- var lastDeferred;
- // When detecting duplicate prefixes of deferred libraries there are 4
- // cases of duplicate prefixes:
- // 1.
- // import "lib.dart" deferred as a;
- // import "lib2.dart" deferred as a;
- // 2.
- // import "lib.dart" deferred as a;
- // import "lib2.dart" as a;
- // 3.
- // import "lib.dart" as a;
- // import "lib2.dart" deferred as a;
- // 4.
- // import "lib.dart" as a;
- // import "lib2.dart" as a;
- // We must be able to signal error for case 1, 2, 3, but accept case 4.
-
- // The prefixes that have been used by any imports in this library.
- Setlet<String> usedPrefixes = new Setlet<String>();
- // The last deferred import we saw with a given prefix (if any).
- Map<String, Import> prefixDeferredImport = new Map<String, Import>();
- for (LibraryElement library in compiler.libraryLoader.libraries) {
- compiler.withCurrentElement(library, () {
- prefixDeferredImport.clear();
- usedPrefixes.clear();
- // TODO(sigurdm): Make helper getLibraryImportTags when tags is a List
- // instead of a Link.
- for (LibraryTag tag in library.tags) {
- if (tag is! Import) continue;
- Import import = tag;
-
- /// Give an error if the old annotation-based syntax has been used.
- Link<MetadataAnnotation> metadataList = import.metadata;
- if (metadataList != null) {
- for (MetadataAnnotation metadata in metadataList) {
- metadata.ensureResolved(compiler);
- Element element =
- metadata.constant.value.computeType(compiler).element;
- if (element == deferredLibraryClass) {
- compiler.reportFatalError(
- import, MessageKind.DEFERRED_OLD_SYNTAX);
- }
- }
- }
-
- String prefix = (import.prefix != null)
- ? import.prefix.toString()
- : null;
- // The last import we saw with the same prefix.
- Import previousDeferredImport = prefixDeferredImport[prefix];
- if (import.isDeferred) {
- _allDeferredImports[import] = library.getLibraryFromTag(import);
-
- if (prefix == null) {
- compiler.reportError(import,
- MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX);
- } else {
- prefixDeferredImport[prefix] = import;
- }
- isProgramSplit = true;
- lastDeferred = import;
- }
- if (prefix != null) {
- if (previousDeferredImport != null ||
- (import.isDeferred && usedPrefixes.contains(prefix))) {
- Import failingImport = (previousDeferredImport != null)
- ? previousDeferredImport
- : import;
- compiler.reportError(failingImport.prefix,
- MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX);
- }
- usedPrefixes.add(prefix);
- }
- }
- });
- }
- Backend backend = compiler.backend;
- if (isProgramSplit && backend is JavaScriptBackend) {
- backend.registerCheckDeferredIsLoaded(compiler.globalDependencies);
- }
- if (isProgramSplit && backend is DartBackend) {
- // TODO(sigurdm): Implement deferred loading for dart2dart.
- compiler.reportWarning(
- lastDeferred,
- MessageKind.DEFERRED_LIBRARY_DART_2_DART);
- isProgramSplit = false;
- }
- }
-
- /// If [send] is a static send with a deferred element, returns the
- /// [PrefixElement] that the first prefix of the send resolves to.
- /// Otherwise returns null.
- ///
- /// Precondition: send must be static.
- ///
- /// Example:
- ///
- /// import "a.dart" deferred as a;
- ///
- /// main() {
- /// print(a.loadLibrary.toString());
- /// a.loadLibrary().then((_) {
- /// a.run();
- /// a.foo.method();
- /// });
- /// }
- ///
- /// Returns null for a.loadLibrary() (the special
- /// function loadLibrary is not deferred). And returns the PrefixElement for
- /// a.run() and a.foo.
- /// a.loadLibrary.toString() and a.foo.method() are dynamic sends - and
- /// this functions should not be called on them.
- PrefixElement deferredPrefixElement(ast.Send send, TreeElements elements) {
- Element element = elements[send];
- // The DeferredLoaderGetter is not deferred, therefore we do not return the
- // prefix.
- if (element != null && element.isDeferredLoaderGetter) return null;
-
- ast.Node firstNode(ast.Node node) {
- if (node is! ast.Send) {
- return node;
- } else {
- ast.Send send = node;
- ast.Node receiver = send.receiver;
- ast.Node receiverFirst = firstNode(receiver);
- if (receiverFirst != null) {
- return receiverFirst;
- } else {
- return firstNode(send.selector);
- }
- }
- }
- ast.Node first = firstNode(send);
- ast.Node identifier = first.asIdentifier();
- if (identifier == null) return null;
- Element maybePrefix = elements[identifier];
- if (maybePrefix != null && maybePrefix.isPrefix) {
- PrefixElement prefixElement = maybePrefix;
- if (prefixElement.isDeferred) {
- return prefixElement;
- }
- }
- return null;
- }
-}

Powered by Google App Engine
This is Rietveld 408576698