| 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; |
| 16 | 17 |
| 17 import 'dart_backend/dart_backend.dart' show | 18 import 'dart_backend/dart_backend.dart' show |
| 18 DartBackend; | 19 DartBackend; |
| 19 | 20 |
| 21 import 'js_backend/js_backend.dart' show |
| 22 JavaScriptBackend; |
| 23 |
| 20 import 'elements/elements.dart' show | 24 import 'elements/elements.dart' show |
| 21 Element, | 25 Element, |
| 22 ClassElement, | 26 ClassElement, |
| 23 ElementKind, | 27 ElementKind, |
| 24 Elements, | 28 Elements, |
| 25 FunctionElement, | 29 FunctionElement, |
| 26 LibraryElement, | 30 LibraryElement, |
| 27 MetadataAnnotation, | 31 MetadataAnnotation, |
| 28 ScopeContainerElement, | 32 ScopeContainerElement, |
| 29 PrefixElement, | 33 PrefixElement, |
| 30 ClosureContainer; | 34 ClosureContainer; |
| 31 | 35 |
| 32 import 'util/util.dart' show | 36 import 'util/util.dart' show |
| 33 Link; | 37 Link; |
| 34 | 38 |
| 35 import 'util/setlet.dart' show | 39 import 'util/setlet.dart' show |
| 36 Setlet; | 40 Setlet; |
| 37 | 41 |
| 38 import 'tree/tree.dart' show | 42 import 'tree/tree.dart' show |
| 39 LibraryTag, | 43 LibraryTag, |
| 40 Node, | 44 Node, |
| 41 NewExpression, | 45 NewExpression, |
| 42 Import, | 46 Import, |
| 43 LiteralString, | 47 LiteralString, |
| 44 LiteralDartString; | 48 LiteralDartString; |
| 45 | 49 |
| 50 import 'tree/tree.dart' as ast; |
| 51 |
| 46 import 'resolution/resolution.dart' show | 52 import 'resolution/resolution.dart' show |
| 47 TreeElements; | 53 TreeElements; |
| 48 | 54 |
| 49 import 'mirrors_used.dart' show | 55 import 'mirrors_used.dart' show |
| 50 MirrorUsageAnalyzer, | 56 MirrorUsageAnalyzer, |
| 51 MirrorUsageAnalyzerTask, | 57 MirrorUsageAnalyzerTask, |
| 52 MirrorUsage; | 58 MirrorUsage; |
| 53 | 59 |
| 54 /// A "hunk" of the program that will be loaded whenever one of its [imports] | 60 /// A "hunk" of the program that will be loaded whenever one of its [imports] |
| 55 /// are loaded. | 61 /// are loaded. |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 OutputUnit outputUnitForConstant(Constant constant) { | 179 OutputUnit outputUnitForConstant(Constant constant) { |
| 174 if (!splitProgram) return mainOutputUnit; | 180 if (!splitProgram) return mainOutputUnit; |
| 175 | 181 |
| 176 return _constantToOutputUnit[constant]; | 182 return _constantToOutputUnit[constant]; |
| 177 } | 183 } |
| 178 | 184 |
| 179 bool isDeferred(Element element) { | 185 bool isDeferred(Element element) { |
| 180 return outputUnitForElement(element) != mainOutputUnit; | 186 return outputUnitForElement(element) != mainOutputUnit; |
| 181 } | 187 } |
| 182 | 188 |
| 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 |
| 183 /// Mark that [import] is part of the [OutputputUnit] for [element]. | 194 /// Mark that [import] is part of the [OutputputUnit] for [element]. |
| 184 /// | 195 /// |
| 185 /// [element] can be either a [Constant] or an [Element]. | 196 /// [element] can be either a [Constant] or an [Element]. |
| 186 void _addImportToOutputUnitOfElement(Element element, Import import) { | 197 void _addImportToOutputUnitOfElement(Element element, Import import) { |
| 187 // Only one file should be loaded when the program starts, so make | 198 // Only one file should be loaded when the program starts, so make |
| 188 // sure that only one OutputUnit is created for [fakeMainImport]. | 199 // sure that only one OutputUnit is created for [fakeMainImport]. |
| 189 if (import == _fakeMainImport) { | 200 if (import == _fakeMainImport) { |
| 190 _elementToOutputUnit[element] = mainOutputUnit; | 201 _elementToOutputUnit[element] = mainOutputUnit; |
| 191 } | 202 } |
| 192 _elementToOutputUnit.putIfAbsent(element, () => new OutputUnit()) | 203 _elementToOutputUnit.putIfAbsent(element, () => new OutputUnit()) |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 if (imports.isEmpty) return false; | 261 if (imports.isEmpty) return false; |
| 251 // An element could potentially be loaded by several imports. If all of them | 262 // An element could potentially be loaded by several imports. If all of them |
| 252 // is explicitly deferred, we say the element is explicitly deferred. | 263 // is explicitly deferred, we say the element is explicitly deferred. |
| 253 // TODO(sigurdm): We might want to give a warning if the imports do not | 264 // TODO(sigurdm): We might want to give a warning if the imports do not |
| 254 // agree. | 265 // agree. |
| 255 return imports.every(_isImportDeferred); | 266 return imports.every(_isImportDeferred); |
| 256 } | 267 } |
| 257 | 268 |
| 258 /// Returns a [Link] of every [Import] that imports [element] into [library]. | 269 /// Returns a [Link] of every [Import] that imports [element] into [library]. |
| 259 Link<Import> _getImports(Element element, LibraryElement library) { | 270 Link<Import> _getImports(Element element, LibraryElement library) { |
| 260 if (!element.isTopLevel()) { | 271 if (element.isMember()) { |
| 261 element = element.getEnclosingClass(); | 272 element = element.getEnclosingClass(); |
| 262 } | 273 } |
| 263 | 274 if (element.isAccessor()) { |
| 275 element = (element as FunctionElement).abstractField; |
| 276 } |
| 264 return library.getImportsFor(element); | 277 return library.getImportsFor(element); |
| 265 } | 278 } |
| 266 | 279 |
| 267 /// Replaces the imports of [outputUnit] with those in | 280 /// Replaces the imports of [outputUnit] with those in |
| 268 /// [replacementImports]. Because mainOutputUnit has a special handling we | 281 /// [replacementImports]. Because mainOutputUnit has a special handling we |
| 269 /// create a new outputUnit instead, and update the mapping from the | 282 /// create a new outputUnit instead, and update the mapping from the |
| 270 /// dependency to its outputUnit. | 283 /// dependency to its outputUnit. |
| 271 void _replaceOutputUnitImports(dynamic dependency, | 284 void _replaceOutputUnitImports(dynamic dependency, |
| 272 OutputUnit outputUnit, | 285 OutputUnit outputUnit, |
| 273 Iterable<Import> replacementImports) { | 286 Iterable<Import> replacementImports) { |
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 ? previousDeferredImport | 808 ? previousDeferredImport |
| 796 : import; | 809 : import; |
| 797 compiler.reportError(failingImport.prefix, | 810 compiler.reportError(failingImport.prefix, |
| 798 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX); | 811 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX); |
| 799 } | 812 } |
| 800 usedPrefixes.add(prefix); | 813 usedPrefixes.add(prefix); |
| 801 } | 814 } |
| 802 } | 815 } |
| 803 }); | 816 }); |
| 804 } | 817 } |
| 818 Backend backend = compiler.backend; |
| 819 if (splitProgram && backend is JavaScriptBackend) { |
| 820 backend.registerCheckDeferredIsLoaded(compiler.globalDependencies); |
| 821 } |
| 805 if (splitProgram && backend is DartBackend) { | 822 if (splitProgram && backend is DartBackend) { |
| 806 // TODO(sigurdm): Implement deferred loading for dart2dart. | 823 // TODO(sigurdm): Implement deferred loading for dart2dart. |
| 807 splitProgram = false; | 824 splitProgram = false; |
| 808 compiler.reportInfo( | 825 compiler.reportInfo( |
| 809 lastDeferred, | 826 lastDeferred, |
| 810 MessageKind.DEFERRED_LIBRARY_DART_2_DART); | 827 MessageKind.DEFERRED_LIBRARY_DART_2_DART); |
| 811 } | 828 } |
| 812 } | 829 } |
| 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 } |
| 813 } | 886 } |
| OLD | NEW |