| 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, |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 void _addImportToOutputUnitOfConstant(Constant constant, Import import) { | 231 void _addImportToOutputUnitOfConstant(Constant constant, Import import) { |
| 232 // Only one file should be loaded when the program starts, so make | 232 // Only one file should be loaded when the program starts, so make |
| 233 // sure that only one OutputUnit is created for [fakeMainImport]. | 233 // sure that only one OutputUnit is created for [fakeMainImport]. |
| 234 if (import == _fakeMainImport) { | 234 if (import == _fakeMainImport) { |
| 235 _constantToOutputUnit[constant] = mainOutputUnit; | 235 _constantToOutputUnit[constant] = mainOutputUnit; |
| 236 } | 236 } |
| 237 _constantToOutputUnit.putIfAbsent(constant, () => new OutputUnit()) | 237 _constantToOutputUnit.putIfAbsent(constant, () => new OutputUnit()) |
| 238 .imports.add(import); | 238 .imports.add(import); |
| 239 } | 239 } |
| 240 | 240 |
| 241 /// Answers whether the [import] has a [DeferredLibrary] annotation. | |
| 242 bool _isImportDeferred(Import import) { | |
| 243 return _allDeferredImports.containsKey(import); | |
| 244 } | |
| 245 | |
| 246 /// Checks whether the [import] has a [DeferredLibrary] annotation and stores | |
| 247 /// the information in [_allDeferredImports] and on the corresponding | |
| 248 /// prefixElement. | |
| 249 void _markIfDeferred(Import import, LibraryElement library) { | |
| 250 // Check if the import is deferred by a keyword. | |
| 251 if (import.isDeferred) { | |
| 252 _allDeferredImports[import] = library.getLibraryFromTag(import); | |
| 253 return; | |
| 254 } | |
| 255 // Check if the import is deferred by a metadata annotation. | |
| 256 Link<MetadataAnnotation> metadataList = import.metadata; | |
| 257 if (metadataList == null) return; | |
| 258 for (MetadataAnnotation metadata in metadataList) { | |
| 259 metadata.ensureResolved(compiler); | |
| 260 Element element = metadata.value.computeType(compiler).element; | |
| 261 if (element == deferredLibraryClass) { | |
| 262 _allDeferredImports[import] = library.getLibraryFromTag(import); | |
| 263 // On encountering a deferred library without a prefix we report an | |
| 264 // error, but continue the compilation to possibly give more | |
| 265 // information. Therefore it is neccessary to check if there is a prefix | |
| 266 // here. | |
| 267 Element maybePrefix = library.find(import.prefix.toString()); | |
| 268 if (maybePrefix != null && maybePrefix.isPrefix) { | |
| 269 PrefixElement prefix = maybePrefix; | |
| 270 prefix.markAsDeferred(import); | |
| 271 } | |
| 272 } | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 /// Answers whether [element] is explicitly deferred when referred to from | 241 /// Answers whether [element] is explicitly deferred when referred to from |
| 277 /// [library]. | 242 /// [library]. |
| 278 bool _isExplicitlyDeferred(Element element, LibraryElement library) { | 243 bool _isExplicitlyDeferred(Element element, LibraryElement library) { |
| 279 Link<Import> imports = _getImports(element, library); | 244 Link<Import> imports = _getImports(element, library); |
| 280 // If the element is not imported explicitly, it is implicitly imported | 245 // If the element is not imported explicitly, it is implicitly imported |
| 281 // not deferred. | 246 // not deferred. |
| 282 if (imports.isEmpty) return false; | 247 if (imports.isEmpty) return false; |
| 283 // An element could potentially be loaded by several imports. If all of them | 248 // An element could potentially be loaded by several imports. If all of them |
| 284 // is explicitly deferred, we say the element is explicitly deferred. | 249 // is explicitly deferred, we say the element is explicitly deferred. |
| 285 // TODO(sigurdm): We might want to give a warning if the imports do not | 250 // TODO(sigurdm): We might want to give a warning if the imports do not |
| 286 // agree. | 251 // agree. |
| 287 return imports.every(_isImportDeferred); | 252 return imports.every((Import import) => import.isDeferred); |
| 288 } | 253 } |
| 289 | 254 |
| 290 /// Returns a [Link] of every [Import] that imports [element] into [library]. | 255 /// Returns a [Link] of every [Import] that imports [element] into [library]. |
| 291 Link<Import> _getImports(Element element, LibraryElement library) { | 256 Link<Import> _getImports(Element element, LibraryElement library) { |
| 292 if (element.isClassMember) { | 257 if (element.isClassMember) { |
| 293 element = element.enclosingClass; | 258 element = element.enclosingClass; |
| 294 } | 259 } |
| 295 if (element.isAccessor) { | 260 if (element.isAccessor) { |
| 296 element = (element as FunctionElement).abstractField; | 261 element = (element as FunctionElement).abstractField; |
| 297 } | 262 } |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 void traverseLibrary(LibraryElement library) { | 371 void traverseLibrary(LibraryElement library) { |
| 407 if (result.contains(library)) return; | 372 if (result.contains(library)) return; |
| 408 result.add(library); | 373 result.add(library); |
| 409 | 374 |
| 410 iterateTags(LibraryElement library) { | 375 iterateTags(LibraryElement library) { |
| 411 // TODO(sigurdm): Make helper getLibraryDependencyTags when tags is | 376 // TODO(sigurdm): Make helper getLibraryDependencyTags when tags is |
| 412 // changed to be a List instead of a Link. | 377 // changed to be a List instead of a Link. |
| 413 for (LibraryTag tag in library.tags) { | 378 for (LibraryTag tag in library.tags) { |
| 414 if (tag is! LibraryDependency) continue; | 379 if (tag is! LibraryDependency) continue; |
| 415 LibraryDependency libraryDependency = tag; | 380 LibraryDependency libraryDependency = tag; |
| 416 if (!(libraryDependency is Import | 381 if (!(libraryDependency is Import && libraryDependency.isDeferred)) { |
| 417 && _isImportDeferred(libraryDependency))) { | |
| 418 LibraryElement importedLibrary = library.getLibraryFromTag(tag); | 382 LibraryElement importedLibrary = library.getLibraryFromTag(tag); |
| 419 traverseLibrary(importedLibrary); | 383 traverseLibrary(importedLibrary); |
| 420 } | 384 } |
| 421 } | 385 } |
| 422 } | 386 } |
| 423 | 387 |
| 424 iterateTags(library); | 388 iterateTags(library); |
| 425 if (library.isPatched) { | 389 if (library.isPatched) { |
| 426 iterateTags(library.implementation); | 390 iterateTags(library.implementation); |
| 427 } | 391 } |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 Map<String, Import> prefixDeferredImport = new Map<String, Import>(); | 651 Map<String, Import> prefixDeferredImport = new Map<String, Import>(); |
| 688 for (LibraryElement library in compiler.libraryLoader.libraries) { | 652 for (LibraryElement library in compiler.libraryLoader.libraries) { |
| 689 compiler.withCurrentElement(library, () { | 653 compiler.withCurrentElement(library, () { |
| 690 prefixDeferredImport.clear(); | 654 prefixDeferredImport.clear(); |
| 691 usedPrefixes.clear(); | 655 usedPrefixes.clear(); |
| 692 // TODO(sigurdm): Make helper getLibraryImportTags when tags is a List | 656 // TODO(sigurdm): Make helper getLibraryImportTags when tags is a List |
| 693 // instead of a Link. | 657 // instead of a Link. |
| 694 for (LibraryTag tag in library.tags) { | 658 for (LibraryTag tag in library.tags) { |
| 695 if (tag is! Import) continue; | 659 if (tag is! Import) continue; |
| 696 Import import = tag; | 660 Import import = tag; |
| 697 _markIfDeferred(import, library); | 661 |
| 662 /// Give an error if the old annotation-based syntax has been used. |
| 663 Link<MetadataAnnotation> metadataList = import.metadata; |
| 664 if (metadataList != null) { |
| 665 for (MetadataAnnotation metadata in metadataList) { |
| 666 metadata.ensureResolved(compiler); |
| 667 Element element = metadata.value.computeType(compiler).element; |
| 668 if (element == deferredLibraryClass) { |
| 669 compiler.reportFatalError(import, MessageKind.DEFERRED_OLD_SYNT
AX); |
| 670 } |
| 671 } |
| 672 } |
| 673 |
| 698 String prefix = (import.prefix != null) | 674 String prefix = (import.prefix != null) |
| 699 ? import.prefix.toString() | 675 ? import.prefix.toString() |
| 700 : null; | 676 : null; |
| 701 // The last import we saw with the same prefix. | 677 // The last import we saw with the same prefix. |
| 702 Import previousDeferredImport = prefixDeferredImport[prefix]; | 678 Import previousDeferredImport = prefixDeferredImport[prefix]; |
| 703 bool isDeferred = _isImportDeferred(import); | 679 if (import.isDeferred) { |
| 704 if (isDeferred) { | 680 _allDeferredImports[import] = library.getLibraryFromTag(import); |
| 681 |
| 705 if (prefix == null) { | 682 if (prefix == null) { |
| 706 compiler.reportError(import, | 683 compiler.reportError(import, |
| 707 MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX); | 684 MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX); |
| 708 } else { | 685 } else { |
| 709 prefixDeferredImport[prefix] = import; | 686 prefixDeferredImport[prefix] = import; |
| 710 } | 687 } |
| 711 isProgramSplit = true; | 688 isProgramSplit = true; |
| 712 lastDeferred = import; | 689 lastDeferred = import; |
| 713 } | 690 } |
| 714 if (prefix != null) { | 691 if (prefix != null) { |
| 715 if (previousDeferredImport != null || | 692 if (previousDeferredImport != null || |
| 716 (isDeferred && usedPrefixes.contains(prefix))) { | 693 (import.isDeferred && usedPrefixes.contains(prefix))) { |
| 717 Import failingImport = (previousDeferredImport != null) | 694 Import failingImport = (previousDeferredImport != null) |
| 718 ? previousDeferredImport | 695 ? previousDeferredImport |
| 719 : import; | 696 : import; |
| 720 compiler.reportError(failingImport.prefix, | 697 compiler.reportError(failingImport.prefix, |
| 721 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX); | 698 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX); |
| 722 } | 699 } |
| 723 usedPrefixes.add(prefix); | 700 usedPrefixes.add(prefix); |
| 724 } | 701 } |
| 725 } | 702 } |
| 726 }); | 703 }); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 Element maybePrefix = elements[identifier]; | 764 Element maybePrefix = elements[identifier]; |
| 788 if (maybePrefix != null && maybePrefix.isPrefix) { | 765 if (maybePrefix != null && maybePrefix.isPrefix) { |
| 789 PrefixElement prefixElement = maybePrefix; | 766 PrefixElement prefixElement = maybePrefix; |
| 790 if (prefixElement.isDeferred) { | 767 if (prefixElement.isDeferred) { |
| 791 return prefixElement; | 768 return prefixElement; |
| 792 } | 769 } |
| 793 } | 770 } |
| 794 return null; | 771 return null; |
| 795 } | 772 } |
| 796 } | 773 } |
| OLD | NEW |