| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 dart2js.library_loader; | 5 library dart2js.library_loader; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart2jslib.dart' | 8 |
| 9 show Compiler, | 9 import 'dart2jslib.dart' show |
| 10 CompilerTask, | 10 Compiler, |
| 11 MessageKind, | 11 CompilerTask, |
| 12 Script, | 12 DiagnosticListener, |
| 13 invariant; | 13 MessageKind, |
| 14 import 'elements/elements.dart' | 14 Script, |
| 15 show CompilationUnitElement, | 15 invariant; |
| 16 Element, | 16 |
| 17 LibraryElement, | 17 import 'elements/elements.dart' show |
| 18 PrefixElement; | 18 CompilationUnitElement, |
| 19 import 'elements/modelx.dart' | 19 Element, |
| 20 show CompilationUnitElementX, | 20 LibraryElement, |
| 21 DeferredLoaderGetterElementX, | 21 PrefixElement; |
| 22 ErroneousElementX, | 22 |
| 23 LibraryElementX, | 23 import 'elements/modelx.dart' show |
| 24 PrefixElementX; | 24 CompilationUnitElementX, |
| 25 DeferredLoaderGetterElementX, |
| 26 ErroneousElementX, |
| 27 LibraryElementX, |
| 28 PrefixElementX; |
| 29 |
| 25 import 'helpers/helpers.dart'; // Included for debug helpers. | 30 import 'helpers/helpers.dart'; // Included for debug helpers. |
| 31 |
| 26 import 'native/native.dart' as native; | 32 import 'native/native.dart' as native; |
| 33 |
| 27 import 'tree/tree.dart'; | 34 import 'tree/tree.dart'; |
| 28 import 'util/util.dart' show Link, LinkBuilder; | 35 |
| 36 import 'util/util.dart' show |
| 37 Link, |
| 38 LinkBuilder; |
| 29 | 39 |
| 30 /** | 40 /** |
| 31 * [CompilerTask] for loading libraries and setting up the import/export scopes. | 41 * [CompilerTask] for loading libraries and setting up the import/export scopes. |
| 32 * | 42 * |
| 33 * The library loader uses four different kinds of URIs in different parts of | 43 * The library loader uses four different kinds of URIs in different parts of |
| 34 * the loading process. | 44 * the loading process. |
| 35 * | 45 * |
| 36 * ## User URI ## | 46 * ## User URI ## |
| 37 * | 47 * |
| 38 * A 'user URI' is a URI provided by the user in code and as the main entry URI | 48 * A 'user URI' is a URI provided by the user in code and as the main entry URI |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 } | 365 } |
| 356 | 366 |
| 357 /** | 367 /** |
| 358 * Processes the library tags in [library]. | 368 * Processes the library tags in [library]. |
| 359 * | 369 * |
| 360 * The imported/exported libraries are loaded and processed recursively but | 370 * The imported/exported libraries are loaded and processed recursively but |
| 361 * the import/export scopes are not set up. | 371 * the import/export scopes are not set up. |
| 362 */ | 372 */ |
| 363 Future processLibraryTags(LibraryDependencyHandler handler, | 373 Future processLibraryTags(LibraryDependencyHandler handler, |
| 364 LibraryElement library) { | 374 LibraryElement library) { |
| 365 int tagState = TagState.NO_TAG_SEEN; | 375 TagState tagState = new TagState(); |
| 366 | |
| 367 /** | |
| 368 * If [value] is less than [tagState] complain and return | |
| 369 * [tagState]. Otherwise return the new value for [tagState] | |
| 370 * (transition function for state machine). | |
| 371 */ | |
| 372 int checkTag(int value, LibraryTag tag) { | |
| 373 if (tagState > value) { | |
| 374 compiler.reportFatalError( | |
| 375 tag, | |
| 376 MessageKind.GENERIC, {'text': 'Error: Out of order.'}); | |
| 377 return tagState; | |
| 378 } | |
| 379 return TagState.NEXT[value]; | |
| 380 } | |
| 381 | 376 |
| 382 bool importsDartCore = false; | 377 bool importsDartCore = false; |
| 383 var libraryDependencies = new LinkBuilder<LibraryDependency>(); | 378 var libraryDependencies = new LinkBuilder<LibraryDependency>(); |
| 384 Uri base = library.entryCompilationUnit.script.readableUri; | 379 Uri base = library.entryCompilationUnit.script.readableUri; |
| 385 | 380 |
| 386 return Future.forEach(library.tags, (LibraryTag tag) { | 381 return Future.forEach(library.tags, (LibraryTag tag) { |
| 387 return compiler.withCurrentElement(library, () { | 382 return compiler.withCurrentElement(library, () { |
| 388 if (tag.isImport) { | 383 if (tag.isImport) { |
| 389 Import import = tag; | 384 Import import = tag; |
| 390 tagState = checkTag(TagState.IMPORT_OR_EXPORT, import); | 385 tagState.checkTag(TagState.IMPORT_OR_EXPORT, import, compiler); |
| 391 if (import.uri.dartString.slowToString() == 'dart:core') { | 386 if (import.uri.dartString.slowToString() == 'dart:core') { |
| 392 importsDartCore = true; | 387 importsDartCore = true; |
| 393 } | 388 } |
| 394 libraryDependencies.addLast(import); | 389 libraryDependencies.addLast(import); |
| 395 } else if (tag.isExport) { | 390 } else if (tag.isExport) { |
| 396 tagState = checkTag(TagState.IMPORT_OR_EXPORT, tag); | 391 tagState.checkTag(TagState.IMPORT_OR_EXPORT, tag, compiler); |
| 397 libraryDependencies.addLast(tag); | 392 libraryDependencies.addLast(tag); |
| 398 } else if (tag.isLibraryName) { | 393 } else if (tag.isLibraryName) { |
| 399 tagState = checkTag(TagState.LIBRARY, tag); | 394 tagState.checkTag(TagState.LIBRARY, tag, compiler); |
| 400 if (library.libraryTag != null) { | 395 if (library.libraryTag == null) { |
| 401 compiler.internalError(tag, "Duplicated library declaration."); | 396 // Use the first if there are multiple (which is reported as an |
| 402 } else { | 397 // error in [TagState.checkTag]). |
| 403 library.libraryTag = tag; | 398 library.libraryTag = tag; |
| 404 } | 399 } |
| 405 } else if (tag.isPart) { | 400 } else if (tag.isPart) { |
| 406 Part part = tag; | 401 Part part = tag; |
| 407 StringNode uri = part.uri; | 402 StringNode uri = part.uri; |
| 408 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); | 403 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); |
| 409 tagState = checkTag(TagState.SOURCE, part); | 404 tagState.checkTag(TagState.PART, part, compiler); |
| 410 return scanPart(part, resolvedUri, library); | 405 return scanPart(part, resolvedUri, library); |
| 411 } else { | 406 } else { |
| 412 compiler.internalError(tag, "Unhandled library tag."); | 407 compiler.internalError(tag, "Unhandled library tag."); |
| 413 } | 408 } |
| 414 }); | 409 }); |
| 415 }).then((_) { | 410 }).then((_) { |
| 416 return compiler.onLibraryScanned(library, handler); | 411 return compiler.onLibraryScanned(library, handler); |
| 417 }).then((_) { | 412 }).then((_) { |
| 418 return compiler.withCurrentElement(library, () { | 413 return compiler.withCurrentElement(library, () { |
| 419 checkDuplicatedLibraryName(library); | 414 checkDuplicatedLibraryName(library); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 libraryCanonicalUriMap[resolvedUri] = element; | 560 libraryCanonicalUriMap[resolvedUri] = element; |
| 566 } | 561 } |
| 567 native.maybeEnableNative(compiler, element); | 562 native.maybeEnableNative(compiler, element); |
| 568 compiler.scanner.scanLibrary(element); | 563 compiler.scanner.scanLibrary(element); |
| 569 return element; | 564 return element; |
| 570 }); | 565 }); |
| 571 } | 566 } |
| 572 } | 567 } |
| 573 | 568 |
| 574 | 569 |
| 575 /** | 570 /// A state machine for checking script tags come in the correct order. |
| 576 * The fields of this class models a state machine for checking script | |
| 577 * tags come in the correct order. | |
| 578 */ | |
| 579 class TagState { | 571 class TagState { |
| 580 static const int NO_TAG_SEEN = 0; | 572 static const int NO_TAG_SEEN = 0; |
| 581 static const int LIBRARY = 1; | 573 static const int LIBRARY = 1; |
| 582 static const int IMPORT_OR_EXPORT = 2; | 574 static const int IMPORT_OR_EXPORT = 2; |
| 583 static const int SOURCE = 3; | 575 static const int PART = 3; |
| 584 static const int RESOURCE = 4; | |
| 585 | 576 |
| 586 /** Next state. */ | 577 /// Encodes transition function for state machine. |
| 587 static const List<int> NEXT = | 578 static const List<int> NEXT = const <int>[ |
| 588 const <int>[NO_TAG_SEEN, | 579 NO_TAG_SEEN, |
| 589 IMPORT_OR_EXPORT, // Only one library tag is allowed. | 580 IMPORT_OR_EXPORT, // Only one library tag is allowed. |
| 590 IMPORT_OR_EXPORT, | 581 IMPORT_OR_EXPORT, |
| 591 SOURCE, | 582 PART, |
| 592 RESOURCE]; | 583 ]; |
| 584 |
| 585 int tagState = TagState.NO_TAG_SEEN; |
| 586 |
| 587 bool hasLibraryDeclaration = false; |
| 588 |
| 589 /// If [value] is less than [tagState] complain. Regardless, update |
| 590 /// [tagState] using transition function for state machine. |
| 591 void checkTag(int value, LibraryTag tag, DiagnosticListener listener) { |
| 592 if (tagState > value) { |
| 593 MessageKind kind; |
| 594 switch (value) { |
| 595 case LIBRARY: |
| 596 if (hasLibraryDeclaration) { |
| 597 kind = MessageKind.ONLY_ONE_LIBRARY_TAG; |
| 598 } else { |
| 599 kind = MessageKind.LIBRARY_TAG_MUST_BE_FIRST; |
| 600 } |
| 601 break; |
| 602 |
| 603 case IMPORT_OR_EXPORT: |
| 604 if (tag.isImport) { |
| 605 kind = MessageKind.IMPORT_BEFORE_PARTS; |
| 606 } else if (tag.isExport) { |
| 607 kind = MessageKind.EXPORT_BEFORE_PARTS; |
| 608 } else { |
| 609 listener.internalError(tag, "Expected import or export."); |
| 610 } |
| 611 break; |
| 612 |
| 613 default: |
| 614 listener.internalError(tag, "Unexpected order of library tags."); |
| 615 } |
| 616 listener.reportError(tag, kind); |
| 617 } |
| 618 if (value == LIBRARY) { |
| 619 hasLibraryDeclaration = true; |
| 620 } |
| 621 tagState = NEXT[value]; |
| 622 } |
| 593 } | 623 } |
| 594 | 624 |
| 595 /** | 625 /** |
| 596 * An [import] tag and the [importedLibrary] imported through [import]. | 626 * An [import] tag and the [importedLibrary] imported through [import]. |
| 597 */ | 627 */ |
| 598 class ImportLink { | 628 class ImportLink { |
| 599 final Import import; | 629 final Import import; |
| 600 final LibraryElement importedLibrary; | 630 final LibraryElement importedLibrary; |
| 601 | 631 |
| 602 ImportLink(this.import, this.importedLibrary); | 632 ImportLink(this.import, this.importedLibrary); |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1141 } | 1171 } |
| 1142 suffixes.add(const Link<Uri>().prepend(canonicalUri)); | 1172 suffixes.add(const Link<Uri>().prepend(canonicalUri)); |
| 1143 } | 1173 } |
| 1144 suffixChainMap[library] = suffixes; | 1174 suffixChainMap[library] = suffixes; |
| 1145 return; | 1175 return; |
| 1146 } | 1176 } |
| 1147 | 1177 |
| 1148 computeSuffixes(rootLibrary, const Link<Uri>()); | 1178 computeSuffixes(rootLibrary, const Link<Uri>()); |
| 1149 } | 1179 } |
| 1150 } | 1180 } |
| OLD | NEW |