| 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 Compiler, | 8 Compiler, |
| 9 CompilerTask, | 9 CompilerTask, |
| 10 Constant, | 10 Constant, |
| 11 ConstructedConstant, | 11 ConstructedConstant, |
| 12 MessageKind, | 12 MessageKind, |
| 13 StringConstant, | 13 StringConstant, |
| 14 invariant; | 14 invariant; |
| 15 | 15 |
| 16 import 'dart_backend/dart_backend.dart' show | |
| 17 DartBackend; | |
| 18 | |
| 19 import 'elements/elements.dart' show | 16 import 'elements/elements.dart' show |
| 20 Element, | 17 Element, |
| 21 ClassElement, | 18 ClassElement, |
| 22 ElementKind, | 19 ElementKind, |
| 23 Elements, | 20 Elements, |
| 24 FunctionElement, | 21 FunctionElement, |
| 25 LibraryElement, | 22 LibraryElement, |
| 26 MetadataAnnotation, | 23 MetadataAnnotation, |
| 27 ScopeContainerElement, | 24 ScopeContainerElement, |
| 28 PrefixElement, | |
| 29 ClosureContainer; | 25 ClosureContainer; |
| 30 | 26 |
| 31 import 'util/util.dart' show | 27 import 'util/util.dart' show |
| 32 Link; | 28 Link; |
| 33 | 29 |
| 34 import 'util/setlet.dart' show | 30 import 'util/setlet.dart' show |
| 35 Setlet; | 31 Setlet; |
| 36 | 32 |
| 37 import 'tree/tree.dart' show | 33 import 'tree/tree.dart' show |
| 38 LibraryTag, | 34 LibraryTag, |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 // sure that only one OutputUnit is created for [fakeMainImport]. | 179 // sure that only one OutputUnit is created for [fakeMainImport]. |
| 184 if (import == _fakeMainImport) { | 180 if (import == _fakeMainImport) { |
| 185 _constantToOutputUnit[constant] = mainOutputUnit; | 181 _constantToOutputUnit[constant] = mainOutputUnit; |
| 186 } | 182 } |
| 187 _constantToOutputUnit.putIfAbsent(constant, () => new OutputUnit()) | 183 _constantToOutputUnit.putIfAbsent(constant, () => new OutputUnit()) |
| 188 .imports.add(import); | 184 .imports.add(import); |
| 189 } | 185 } |
| 190 | 186 |
| 191 /// Answers whether the [import] has a [DeferredLibrary] annotation. | 187 /// Answers whether the [import] has a [DeferredLibrary] annotation. |
| 192 bool _isImportDeferred(Import import) { | 188 bool _isImportDeferred(Import import) { |
| 193 return _allDeferredImports.containsKey(import); | 189 Link<MetadataAnnotation> metadatalist = import.metadata; |
| 194 } | 190 if (metadatalist == null) return false; |
| 195 | 191 for (MetadataAnnotation metadata in metadatalist) { |
| 196 /// Checks whether the [import] has a [DeferredLibrary] annotation and stores | |
| 197 /// the information in [_allDeferredImports] and on the corresponding | |
| 198 /// prefixElement. | |
| 199 void _markIfDeferred(Import import, LibraryElement library) { | |
| 200 Link<MetadataAnnotation> metadataList = import.metadata; | |
| 201 if (metadataList == null) return; | |
| 202 for (MetadataAnnotation metadata in metadataList) { | |
| 203 metadata.ensureResolved(compiler); | 192 metadata.ensureResolved(compiler); |
| 204 Element element = metadata.value.computeType(compiler).element; | 193 Element element = metadata.value.computeType(compiler).element; |
| 205 if (element == deferredLibraryClass) { | 194 if (metadata.value.computeType(compiler).element |
| 206 _allDeferredImports[import] = library.getLibraryFromTag(import); | 195 == deferredLibraryClass) { |
| 207 // On encountering a deferred library without a prefix we report an | 196 return true; |
| 208 // error, but continue the compilation to possibly give more | |
| 209 // information. Therefore it is neccessary to check if there is a prefix | |
| 210 // here. | |
| 211 Element maybePrefix = library.find(import.prefix.toString()); | |
| 212 if (maybePrefix != null && maybePrefix.isPrefix()) { | |
| 213 PrefixElement prefix = maybePrefix; | |
| 214 prefix.markAsDeferred(); | |
| 215 } | |
| 216 } | 197 } |
| 217 } | 198 } |
| 199 return false; |
| 218 } | 200 } |
| 219 | 201 |
| 220 /// Answers whether [element] is explicitly deferred when referred to from | 202 /// Answers whether [element] is explicitly deferred when referred to from |
| 221 /// [library]. | 203 /// [library]. |
| 222 bool _isExplicitlyDeferred(Element element, LibraryElement library) { | 204 bool _isExplicitlyDeferred(Element element, LibraryElement library) { |
| 223 Link<Import> imports = _getImports(element, library); | 205 Link<Import> imports = _getImports(element, library); |
| 224 // If the element is not imported explicitly, it is implicitly imported | 206 // If the element is not imported explicitly, it is implicitly imported |
| 225 // not deferred. | 207 // not deferred. |
| 226 if (imports.isEmpty) return false; | 208 if (imports.isEmpty) return false; |
| 227 // An element could potentially be loaded by several imports. If all of them | 209 // An element could potentially be loaded by several imports. If all of them |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 // 2. | 645 // 2. |
| 664 // @DeferredLibrary("a") import "lib.dart" as a; | 646 // @DeferredLibrary("a") import "lib.dart" as a; |
| 665 // import "lib2.dart" as a; | 647 // import "lib2.dart" as a; |
| 666 // 3. | 648 // 3. |
| 667 // import "lib.dart" as a; | 649 // import "lib.dart" as a; |
| 668 // @DeferredLibrary("a") import "lib2.dart" as a; | 650 // @DeferredLibrary("a") import "lib2.dart" as a; |
| 669 // 4. | 651 // 4. |
| 670 // import "lib.dart" as a; | 652 // import "lib.dart" as a; |
| 671 // import "lib2.dart" as a; | 653 // import "lib2.dart" as a; |
| 672 // We must be able to signal error for case 1, 2, 3, but accept case 4. | 654 // We must be able to signal error for case 1, 2, 3, but accept case 4. |
| 673 | 655 |
| 674 // The prefixes that have been used by any imports in this library. | 656 // The prefixes that have been used by any imports in this library. |
| 675 Setlet<String> usedPrefixes = new Setlet<String>(); | 657 Setlet<String> usedPrefixes = new Setlet<String>(); |
| 676 // The last deferred import we saw with a given prefix (if any). | 658 // The last deferred import we saw with a given prefix (if any). |
| 677 Map<String, Import> prefixDeferredImport = new Map<String, Import>(); | 659 Map<String, Import> prefixDeferredImport = new Map<String, Import>(); |
| 678 for (LibraryElement library in compiler.libraries.values) { | 660 for (LibraryElement library in compiler.libraries.values) { |
| 679 compiler.withCurrentElement(library, () { | 661 compiler.withCurrentElement(library, () { |
| 680 prefixDeferredImport.clear(); | 662 prefixDeferredImport.clear(); |
| 681 usedPrefixes.clear(); | 663 usedPrefixes.clear(); |
| 682 // TODO(sigurdm): Make helper getLibraryImportTags when tags is a List | 664 // TODO(sigurdm): Make helper getLibraryImportTags when tags is a List |
| 683 // instead of a Link. | 665 // instead of a Link. |
| 684 for (LibraryTag tag in library.tags) { | 666 for (LibraryTag tag in library.tags) { |
| 685 if (tag is! Import) continue; | 667 if (tag is! Import) continue; |
| 686 Import import = tag; | 668 Import import = tag; |
| 687 _markIfDeferred(import, library); | |
| 688 String prefix = (import.prefix != null) | 669 String prefix = (import.prefix != null) |
| 689 ? import.prefix.toString() | 670 ? import.prefix.toString() |
| 690 : null; | 671 : null; |
| 691 // The last import we saw with the same prefix. | 672 // The last import we saw with the same prefix. |
| 692 Import previousDeferredImport = prefixDeferredImport[prefix]; | 673 Import previousDeferredImport = prefixDeferredImport[prefix]; |
| 693 bool isDeferred = _isImportDeferred(import); | 674 bool isDeferred = _isImportDeferred(import); |
| 694 if (isDeferred) { | 675 if (isDeferred) { |
| 695 if (prefix == null) { | 676 if (prefix == null) { |
| 696 compiler.reportError(import, | 677 compiler.reportError(import, |
| 697 MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX); | 678 MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX); |
| 698 } else { | 679 } else { |
| 699 prefixDeferredImport[prefix] = import; | 680 prefixDeferredImport[prefix] = import; |
| 700 } | 681 } |
| 701 splitProgram = true; | 682 splitProgram = true; |
| 683 _allDeferredImports[tag] = library.getLibraryFromTag(tag); |
| 702 lastDeferred = import.metadata.first; | 684 lastDeferred = import.metadata.first; |
| 703 if (library == compiler.mainApp) { | 685 if (library == compiler.mainApp) { |
| 704 deferredUsedFromMain = true; | 686 deferredUsedFromMain = true; |
| 705 } | 687 } |
| 706 } | 688 } |
| 707 if (prefix != null) { | 689 if (prefix != null) { |
| 708 if (previousDeferredImport != null || | 690 if (previousDeferredImport != null || |
| 709 (isDeferred && usedPrefixes.contains(prefix))) { | 691 (isDeferred && usedPrefixes.contains(prefix))) { |
| 710 Import failingImport = (previousDeferredImport != null) | 692 Import failingImport = (previousDeferredImport != null) |
| 711 ? previousDeferredImport | 693 ? previousDeferredImport |
| 712 : import; | 694 : import; |
| 713 compiler.reportError(failingImport.prefix, | 695 compiler.reportError(failingImport.prefix, |
| 714 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX); | 696 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX); |
| 715 } | 697 } |
| 716 usedPrefixes.add(prefix); | 698 usedPrefixes.add(prefix); |
| 717 } | 699 } |
| 718 } | 700 } |
| 719 }); | 701 }); |
| 720 } | 702 } |
| 721 if (splitProgram && compiler.backend is DartBackend) { | |
| 722 // TODO(sigurdm): Implement deferred loading for dart2dart. | |
| 723 splitProgram = false; | |
| 724 compiler.reportInfo( | |
| 725 lastDeferred, | |
| 726 MessageKind.DEFERRED_LIBRARY_DART_2_DART); | |
| 727 } | |
| 728 if (splitProgram && !deferredUsedFromMain) { | 703 if (splitProgram && !deferredUsedFromMain) { |
| 729 compiler.reportInfo( | 704 compiler.reportInfo( |
| 730 lastDeferred, | 705 lastDeferred, |
| 731 MessageKind.DEFERRED_LIBRARY_NOT_FROM_MAIN); | 706 MessageKind.DEFERRED_LIBRARY_NOT_FROM_MAIN); |
| 732 splitProgram = false; | 707 splitProgram = false; |
| 733 } | 708 } |
| 734 } | 709 } |
| 735 } | 710 } |
| OLD | NEW |