| 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 deferred_load; | 5 library deferred_load; |
| 6 | 6 |
| 7 import 'dart2jslib.dart' show | 7 import 'dart2jslib.dart' show |
| 8 Backend, | 8 Backend, |
| 9 Compiler, | 9 Compiler, |
| 10 CompilerTask, | 10 CompilerTask, |
| 11 Constant, | 11 Constant, |
| 12 ConstructedConstant, | 12 ConstructedConstant, |
| 13 MessageKind, | 13 MessageKind, |
| 14 StringConstant, | 14 StringConstant, |
| 15 invariant, | 15 invariant; |
| 16 Backend; | |
| 17 | 16 |
| 18 import 'dart_backend/dart_backend.dart' show | 17 import 'dart_backend/dart_backend.dart' show |
| 19 DartBackend; | 18 DartBackend; |
| 20 | 19 |
| 21 import 'js_backend/js_backend.dart' show | |
| 22 JavaScriptBackend; | |
| 23 | |
| 24 import 'elements/elements.dart' show | 20 import 'elements/elements.dart' show |
| 25 Element, | 21 Element, |
| 26 ClassElement, | 22 ClassElement, |
| 27 ElementKind, | 23 ElementKind, |
| 28 Elements, | 24 Elements, |
| 29 FunctionElement, | 25 FunctionElement, |
| 30 LibraryElement, | 26 LibraryElement, |
| 31 MetadataAnnotation, | 27 MetadataAnnotation, |
| 32 ScopeContainerElement, | 28 ScopeContainerElement, |
| 33 PrefixElement, | 29 PrefixElement, |
| 34 ClosureContainer; | 30 ClosureContainer; |
| 35 | 31 |
| 36 import 'util/util.dart' show | 32 import 'util/util.dart' show |
| 37 Link; | 33 Link; |
| 38 | 34 |
| 39 import 'util/setlet.dart' show | 35 import 'util/setlet.dart' show |
| 40 Setlet; | 36 Setlet; |
| 41 | 37 |
| 42 import 'tree/tree.dart' show | 38 import 'tree/tree.dart' show |
| 43 LibraryTag, | 39 LibraryTag, |
| 44 Node, | 40 Node, |
| 45 NewExpression, | 41 NewExpression, |
| 46 Import, | 42 Import, |
| 47 LiteralString, | 43 LiteralString, |
| 48 LiteralDartString; | 44 LiteralDartString; |
| 49 | 45 |
| 50 import 'tree/tree.dart' as ast; | |
| 51 | |
| 52 import 'resolution/resolution.dart' show | 46 import 'resolution/resolution.dart' show |
| 53 TreeElements; | 47 TreeElements; |
| 54 | 48 |
| 55 import 'mirrors_used.dart' show | 49 import 'mirrors_used.dart' show |
| 56 MirrorUsageAnalyzer, | 50 MirrorUsageAnalyzer, |
| 57 MirrorUsageAnalyzerTask, | 51 MirrorUsageAnalyzerTask, |
| 58 MirrorUsage; | 52 MirrorUsage; |
| 59 | 53 |
| 60 /// A "hunk" of the program that will be loaded whenever one of its [imports] | 54 /// A "hunk" of the program that will be loaded whenever one of its [imports] |
| 61 /// are loaded. | 55 /// are loaded. |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 OutputUnit outputUnitForConstant(Constant constant) { | 173 OutputUnit outputUnitForConstant(Constant constant) { |
| 180 if (!splitProgram) return mainOutputUnit; | 174 if (!splitProgram) return mainOutputUnit; |
| 181 | 175 |
| 182 return _constantToOutputUnit[constant]; | 176 return _constantToOutputUnit[constant]; |
| 183 } | 177 } |
| 184 | 178 |
| 185 bool isDeferred(Element element) { | 179 bool isDeferred(Element element) { |
| 186 return outputUnitForElement(element) != mainOutputUnit; | 180 return outputUnitForElement(element) != mainOutputUnit; |
| 187 } | 181 } |
| 188 | 182 |
| 189 /// Returns true if e1 and e2 are in the same output unit. | |
| 190 bool inSameOutputUnit(Element e1, Element e2) { | |
| 191 return outputUnitForElement(e1) == outputUnitForElement(e2); | |
| 192 } | |
| 193 | |
| 194 /// Mark that [import] is part of the [OutputputUnit] for [element]. | 183 /// Mark that [import] is part of the [OutputputUnit] for [element]. |
| 195 /// | 184 /// |
| 196 /// [element] can be either a [Constant] or an [Element]. | 185 /// [element] can be either a [Constant] or an [Element]. |
| 197 void _addImportToOutputUnitOfElement(Element element, Import import) { | 186 void _addImportToOutputUnitOfElement(Element element, Import import) { |
| 198 // Only one file should be loaded when the program starts, so make | 187 // Only one file should be loaded when the program starts, so make |
| 199 // sure that only one OutputUnit is created for [fakeMainImport]. | 188 // sure that only one OutputUnit is created for [fakeMainImport]. |
| 200 if (import == _fakeMainImport) { | 189 if (import == _fakeMainImport) { |
| 201 _elementToOutputUnit[element] = mainOutputUnit; | 190 _elementToOutputUnit[element] = mainOutputUnit; |
| 202 } | 191 } |
| 203 _elementToOutputUnit.putIfAbsent(element, () => new OutputUnit()) | 192 _elementToOutputUnit.putIfAbsent(element, () => new OutputUnit()) |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 if (imports.isEmpty) return false; | 250 if (imports.isEmpty) return false; |
| 262 // An element could potentially be loaded by several imports. If all of them | 251 // An element could potentially be loaded by several imports. If all of them |
| 263 // is explicitly deferred, we say the element is explicitly deferred. | 252 // is explicitly deferred, we say the element is explicitly deferred. |
| 264 // TODO(sigurdm): We might want to give a warning if the imports do not | 253 // TODO(sigurdm): We might want to give a warning if the imports do not |
| 265 // agree. | 254 // agree. |
| 266 return imports.every(_isImportDeferred); | 255 return imports.every(_isImportDeferred); |
| 267 } | 256 } |
| 268 | 257 |
| 269 /// Returns a [Link] of every [Import] that imports [element] into [library]. | 258 /// Returns a [Link] of every [Import] that imports [element] into [library]. |
| 270 Link<Import> _getImports(Element element, LibraryElement library) { | 259 Link<Import> _getImports(Element element, LibraryElement library) { |
| 271 if (element.isMember()) { | 260 if (!element.isTopLevel()) { |
| 272 element = element.getEnclosingClass(); | 261 element = element.getEnclosingClass(); |
| 273 } | 262 } |
| 274 if (element.isAccessor()) { | 263 |
| 275 element = (element as FunctionElement).abstractField; | |
| 276 } | |
| 277 return library.getImportsFor(element); | 264 return library.getImportsFor(element); |
| 278 } | 265 } |
| 279 | 266 |
| 280 /// Replaces the imports of [outputUnit] with those in | 267 /// Replaces the imports of [outputUnit] with those in |
| 281 /// [replacementImports]. Because mainOutputUnit has a special handling we | 268 /// [replacementImports]. Because mainOutputUnit has a special handling we |
| 282 /// create a new outputUnit instead, and update the mapping from the | 269 /// create a new outputUnit instead, and update the mapping from the |
| 283 /// dependency to its outputUnit. | 270 /// dependency to its outputUnit. |
| 284 void _replaceOutputUnitImports(dynamic dependency, | 271 void _replaceOutputUnitImports(dynamic dependency, |
| 285 OutputUnit outputUnit, | 272 OutputUnit outputUnit, |
| 286 Iterable<Import> replacementImports) { | 273 Iterable<Import> replacementImports) { |
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 808 ? previousDeferredImport | 795 ? previousDeferredImport |
| 809 : import; | 796 : import; |
| 810 compiler.reportError(failingImport.prefix, | 797 compiler.reportError(failingImport.prefix, |
| 811 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX); | 798 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX); |
| 812 } | 799 } |
| 813 usedPrefixes.add(prefix); | 800 usedPrefixes.add(prefix); |
| 814 } | 801 } |
| 815 } | 802 } |
| 816 }); | 803 }); |
| 817 } | 804 } |
| 818 Backend backend = compiler.backend; | |
| 819 if (splitProgram && backend is JavaScriptBackend) { | |
| 820 backend.registerCheckDeferredIsLoaded(compiler.globalDependencies); | |
| 821 } | |
| 822 if (splitProgram && backend is DartBackend) { | 805 if (splitProgram && backend is DartBackend) { |
| 823 // TODO(sigurdm): Implement deferred loading for dart2dart. | 806 // TODO(sigurdm): Implement deferred loading for dart2dart. |
| 824 splitProgram = false; | 807 splitProgram = false; |
| 825 compiler.reportInfo( | 808 compiler.reportInfo( |
| 826 lastDeferred, | 809 lastDeferred, |
| 827 MessageKind.DEFERRED_LIBRARY_DART_2_DART); | 810 MessageKind.DEFERRED_LIBRARY_DART_2_DART); |
| 828 } | 811 } |
| 829 } | 812 } |
| 830 | |
| 831 /// If [send] is a static send with a deferred element, returns the | |
| 832 /// [PrefixElement] that the first prefix of the send resolves to. | |
| 833 /// Otherwise returns null. | |
| 834 /// | |
| 835 /// Precondition: send must be static. | |
| 836 /// | |
| 837 /// Example: | |
| 838 /// | |
| 839 /// import "a.dart" deferred as a; | |
| 840 /// | |
| 841 /// main() { | |
| 842 /// print(a.loadLibrary.toString()); | |
| 843 /// a.loadLibrary().then((_) { | |
| 844 /// a.run(); | |
| 845 /// a.foo.method(); | |
| 846 /// }); | |
| 847 /// } | |
| 848 /// | |
| 849 /// Returns null for a.loadLibrary() (the special | |
| 850 /// function loadLibrary is not deferred). And returns the PrefixElement for | |
| 851 /// a.run() and a.foo. | |
| 852 /// a.loadLibrary.toString() and a.foo.method() are dynamic sends - and | |
| 853 /// this functions should not be called on them. | |
| 854 PrefixElement deferredPrefixElement(ast.Send send, TreeElements elements) { | |
| 855 Element element = elements[send]; | |
| 856 // The DeferredLoaderGetter is not deferred, therefore we do not return the | |
| 857 // prefix. | |
| 858 if (element != null && element.isDeferredLoaderGetter()) return null; | |
| 859 | |
| 860 ast.Node firstNode(ast.Node node) { | |
| 861 if (node is! ast.Send) { | |
| 862 return node; | |
| 863 } else { | |
| 864 ast.Send send = node; | |
| 865 ast.Node receiver = send.receiver; | |
| 866 ast.Node receiverFirst = firstNode(receiver); | |
| 867 if (receiverFirst != null) { | |
| 868 return receiverFirst; | |
| 869 } else { | |
| 870 return firstNode(send.selector); | |
| 871 } | |
| 872 } | |
| 873 } | |
| 874 ast.Node first = firstNode(send); | |
| 875 ast.Node identifier = first.asIdentifier(); | |
| 876 if (identifier == null) return null; | |
| 877 Element maybePrefix = elements[identifier]; | |
| 878 if (maybePrefix != null && maybePrefix.isPrefix()) { | |
| 879 PrefixElement prefixElement = maybePrefix; | |
| 880 if (prefixElement.isDeferred) { | |
| 881 return prefixElement; | |
| 882 } | |
| 883 } | |
| 884 return null; | |
| 885 } | |
| 886 } | 813 } |
| OLD | NEW |