| 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 part of dart2js; | 5 part of dart2js; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * [CompilerTask] for loading libraries and setting up the import/export scopes. | 8 * [CompilerTask] for loading libraries and setting up the import/export scopes. |
| 9 * | 9 * |
| 10 * The library loader uses four different kinds of URIs in different parts of | 10 * The library loader uses four different kinds of URIs in different parts of |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 * Loads the library specified by the [resolvedUri] and returns its | 104 * Loads the library specified by the [resolvedUri] and returns its |
| 105 * [LibraryElement]. | 105 * [LibraryElement]. |
| 106 * | 106 * |
| 107 * If the library is not already loaded, the method creates the | 107 * If the library is not already loaded, the method creates the |
| 108 * [LibraryElement] for the library and computes the import/export scope, | 108 * [LibraryElement] for the library and computes the import/export scope, |
| 109 * loading and computing the import/export scopes of all required libraries in | 109 * loading and computing the import/export scopes of all required libraries in |
| 110 * the process. The method handles cyclic dependency between libraries. | 110 * the process. The method handles cyclic dependency between libraries. |
| 111 * | 111 * |
| 112 * This is the main entry point for [LibraryLoader]. | 112 * This is the main entry point for [LibraryLoader]. |
| 113 */ | 113 */ |
| 114 // TODO(johnniwinther): Remove [canonicalUri] together with | 114 Future<LibraryElement> loadLibrary(Uri resolvedUri); |
| 115 // [Compiler.scanBuiltinLibrary]. | |
| 116 Future<LibraryElement> loadLibrary(Uri resolvedUri, Node node, | |
| 117 Uri canonicalUri); | |
| 118 | 115 |
| 119 // TODO(johnniwinther): Remove this when patches don't need special parsing. | 116 // TODO(johnniwinther): Remove this when patches don't need special parsing. |
| 120 Future registerLibraryFromTag(LibraryDependencyHandler handler, | 117 Future registerLibraryFromTag(LibraryDependencyHandler handler, |
| 121 LibraryElement library, | 118 LibraryElement library, |
| 122 LibraryDependency tag); | 119 LibraryDependency tag); |
| 123 | |
| 124 /** | |
| 125 * Adds the elements in the export scope of [importedLibrary] to the import | |
| 126 * scope of [importingLibrary]. | |
| 127 */ | |
| 128 // TODO(johnniwinther): Move handling of 'js_helper' to the library loader | |
| 129 // to remove this method from the [LibraryLoader] interface. | |
| 130 void importLibrary(LibraryElement importingLibrary, | |
| 131 LibraryElement importedLibrary, | |
| 132 Import tag); | |
| 133 } | 120 } |
| 134 | 121 |
| 135 /** | 122 /** |
| 136 * [CombinatorFilter] is a succinct representation of a list of combinators from | 123 * [CombinatorFilter] is a succinct representation of a list of combinators from |
| 137 * a library dependency tag. | 124 * a library dependency tag. |
| 138 */ | 125 */ |
| 139 class CombinatorFilter { | 126 class CombinatorFilter { |
| 140 const CombinatorFilter(); | 127 const CombinatorFilter(); |
| 141 | 128 |
| 142 /** | 129 /** |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 } | 201 } |
| 215 | 202 |
| 216 /** | 203 /** |
| 217 * Implementation class for [LibraryLoader]. The distinction between | 204 * Implementation class for [LibraryLoader]. The distinction between |
| 218 * [LibraryLoader] and [LibraryLoaderTask] is made to hide internal members from | 205 * [LibraryLoader] and [LibraryLoaderTask] is made to hide internal members from |
| 219 * the [LibraryLoader] interface. | 206 * the [LibraryLoader] interface. |
| 220 */ | 207 */ |
| 221 class LibraryLoaderTask extends LibraryLoader { | 208 class LibraryLoaderTask extends LibraryLoader { |
| 222 LibraryLoaderTask(Compiler compiler) : super(compiler); | 209 LibraryLoaderTask(Compiler compiler) : super(compiler); |
| 223 String get name => 'LibraryLoader'; | 210 String get name => 'LibraryLoader'; |
| 224 List onLibraryLoadedCallbacks = []; | |
| 225 | 211 |
| 226 final Map<Uri, LibraryElement> libraryResourceUriMap = | 212 final Map<Uri, LibraryElement> libraryResourceUriMap = |
| 227 new Map<Uri, LibraryElement>(); | 213 new Map<Uri, LibraryElement>(); |
| 228 final Map<String, LibraryElement> libraryNames = | 214 final Map<String, LibraryElement> libraryNames = |
| 229 new Map<String, LibraryElement>(); | 215 new Map<String, LibraryElement>(); |
| 230 | 216 |
| 231 LibraryDependencyHandler currentHandler; | 217 LibraryDependencyHandler currentHandler; |
| 232 | 218 |
| 233 Future<LibraryElement> loadLibrary(Uri resolvedUri, Node node, | 219 Future<LibraryElement> loadLibrary(Uri resolvedUri) { |
| 234 Uri canonicalUri) { | |
| 235 return measure(() { | 220 return measure(() { |
| 236 assert(currentHandler == null); | 221 assert(currentHandler == null); |
| 237 // TODO(johnniwinther): Ensure that currentHandler correctly encloses the | 222 // TODO(johnniwinther): Ensure that currentHandler correctly encloses the |
| 238 // loading of a library cluster. | 223 // loading of a library cluster. |
| 239 currentHandler = new LibraryDependencyHandler(compiler); | 224 currentHandler = new LibraryDependencyHandler(compiler); |
| 240 return createLibrary(currentHandler, null, resolvedUri, node, | 225 return createLibrary(currentHandler, null, resolvedUri) |
| 241 canonicalUri).then((LibraryElement library) { | 226 .then((LibraryElement library) { |
| 242 return compiler.withCurrentElement(library, () { | 227 return compiler.withCurrentElement(library, () { |
| 243 return measure(() { | 228 return measure(() { |
| 244 currentHandler.computeExports(); | 229 currentHandler.computeExports(); |
| 230 Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{}; |
| 231 currentHandler.loadedLibraries.forEach( |
| 232 (LibraryElement loadedLibrary) { |
| 233 loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary; |
| 234 }); |
| 245 currentHandler = null; | 235 currentHandler = null; |
| 246 var workList = onLibraryLoadedCallbacks; | 236 return compiler.onLibrariesLoaded(loadedLibraries) |
| 247 onLibraryLoadedCallbacks = []; | 237 .then((_) => library); |
| 248 return Future.forEach(workList, (f) => f()).then((_) => library); | |
| 249 }); | 238 }); |
| 250 }); | 239 }); |
| 251 }); | 240 }); |
| 252 }); | 241 }); |
| 253 } | 242 } |
| 254 | 243 |
| 255 /** | 244 /** |
| 256 * Processes the library tags in [library]. | 245 * Processes the library tags in [library]. |
| 257 * | 246 * |
| 258 * The imported/exported libraries are loaded and processed recursively but | 247 * The imported/exported libraries are loaded and processed recursively but |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 Part part = tag; | 294 Part part = tag; |
| 306 StringNode uri = part.uri; | 295 StringNode uri = part.uri; |
| 307 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); | 296 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); |
| 308 tagState = checkTag(TagState.SOURCE, part); | 297 tagState = checkTag(TagState.SOURCE, part); |
| 309 return scanPart(part, resolvedUri, library); | 298 return scanPart(part, resolvedUri, library); |
| 310 } else { | 299 } else { |
| 311 compiler.internalError(tag, "Unhandled library tag."); | 300 compiler.internalError(tag, "Unhandled library tag."); |
| 312 } | 301 } |
| 313 }); | 302 }); |
| 314 }).then((_) { | 303 }).then((_) { |
| 304 // TODO(johnniwinther): Move callback to after patching. |
| 305 compiler.onLibraryScanned(library); |
| 315 return compiler.withCurrentElement(library, () { | 306 return compiler.withCurrentElement(library, () { |
| 316 checkDuplicatedLibraryName(library); | 307 checkDuplicatedLibraryName(library); |
| 317 // Apply patch, if any. | 308 // Apply patch, if any. |
| 318 if (library.isPlatformLibrary) { | 309 if (library.isPlatformLibrary) { |
| 319 return patchDartLibrary(handler, library, library.canonicalUri.path); | 310 return patchDartLibrary(handler, library, library.canonicalUri.path); |
| 320 } | 311 } |
| 321 }); | 312 }); |
| 322 }).then((_) { | 313 }).then((_) { |
| 323 return compiler.withCurrentElement(library, () { | 314 return compiler.withCurrentElement(library, () { |
| 324 // Import dart:core if not already imported. | 315 // Import dart:core if not already imported. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 | 373 |
| 383 /** | 374 /** |
| 384 * Lazily loads and returns the [LibraryElement] for the dart:core library. | 375 * Lazily loads and returns the [LibraryElement] for the dart:core library. |
| 385 */ | 376 */ |
| 386 Future<LibraryElement> loadCoreLibrary(LibraryDependencyHandler handler) { | 377 Future<LibraryElement> loadCoreLibrary(LibraryDependencyHandler handler) { |
| 387 if (compiler.coreLibrary != null) { | 378 if (compiler.coreLibrary != null) { |
| 388 return new Future.value(compiler.coreLibrary); | 379 return new Future.value(compiler.coreLibrary); |
| 389 } | 380 } |
| 390 | 381 |
| 391 Uri coreUri = new Uri(scheme: 'dart', path: 'core'); | 382 Uri coreUri = new Uri(scheme: 'dart', path: 'core'); |
| 392 return createLibrary(handler, null, coreUri, null, coreUri) | 383 return createLibrary(handler, null, coreUri).then((LibraryElement library) { |
| 393 .then((LibraryElement library) { | |
| 394 compiler.coreLibrary = library; | 384 compiler.coreLibrary = library; |
| 395 return library; | 385 return library; |
| 396 }); | 386 }); |
| 397 } | 387 } |
| 398 | 388 |
| 399 Future patchDartLibrary(LibraryDependencyHandler handler, | 389 Future patchDartLibrary(LibraryDependencyHandler handler, |
| 400 LibraryElement library, String dartLibraryPath) { | 390 LibraryElement library, |
| 391 String dartLibraryPath) { |
| 401 if (library.isPatched) return new Future.value(); | 392 if (library.isPatched) return new Future.value(); |
| 402 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath); | 393 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath); |
| 403 if (patchUri == null) return new Future.value(); | 394 if (patchUri == null) return new Future.value(); |
| 404 | 395 |
| 405 return compiler.patchParser.patchLibrary(handler, patchUri, library); | 396 return compiler.patchParser.patchLibrary(handler, patchUri, library); |
| 406 } | 397 } |
| 407 | 398 |
| 408 /** | 399 /** |
| 409 * Handle a part tag in the scope of [library]. The [resolvedUri] given is | 400 * Handle a part tag in the scope of [library]. The [resolvedUri] given is |
| 410 * used as is, any URI resolution should be done beforehand. | 401 * used as is, any URI resolution should be done beforehand. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 433 /** | 424 /** |
| 434 * Handle an import/export tag by loading the referenced library and | 425 * Handle an import/export tag by loading the referenced library and |
| 435 * registering its dependency in [handler] for the computation of the import/ | 426 * registering its dependency in [handler] for the computation of the import/ |
| 436 * export scope. | 427 * export scope. |
| 437 */ | 428 */ |
| 438 Future registerLibraryFromTag(LibraryDependencyHandler handler, | 429 Future registerLibraryFromTag(LibraryDependencyHandler handler, |
| 439 LibraryElement library, | 430 LibraryElement library, |
| 440 LibraryDependency tag) { | 431 LibraryDependency tag) { |
| 441 Uri base = library.entryCompilationUnit.script.readableUri; | 432 Uri base = library.entryCompilationUnit.script.readableUri; |
| 442 Uri resolvedUri = base.resolve(tag.uri.dartString.slowToString()); | 433 Uri resolvedUri = base.resolve(tag.uri.dartString.slowToString()); |
| 443 return createLibrary(handler, library, resolvedUri, tag.uri, resolvedUri) | 434 return createLibrary(handler, library, resolvedUri, tag.uri) |
| 444 .then((LibraryElement loadedLibrary) { | 435 .then((LibraryElement loadedLibrary) { |
| 445 if (loadedLibrary == null) return; | 436 if (loadedLibrary == null) return; |
| 446 compiler.withCurrentElement(library, () { | 437 compiler.withCurrentElement(library, () { |
| 447 handler.registerDependency(library, tag, loadedLibrary); | 438 handler.registerDependency(library, tag, loadedLibrary); |
| 448 }); | 439 }); |
| 449 }); | 440 }); |
| 450 } | 441 } |
| 451 | 442 |
| 452 /** | 443 /** |
| 453 * Create (or reuse) a library element for the library specified by the | 444 * Create (or reuse) a library element for the library specified by the |
| 454 * [resolvedUri]. | 445 * [resolvedUri]. |
| 455 * | 446 * |
| 456 * If a new library is created, the [handler] is notified. | 447 * If a new library is created, the [handler] is notified. |
| 457 */ | 448 */ |
| 458 // TODO(johnniwinther): Remove [canonicalUri] and make [resolvedUri] the | |
| 459 // canonical uri when [Compiler.scanBuiltinLibrary] is removed. | |
| 460 Future<LibraryElement> createLibrary(LibraryDependencyHandler handler, | 449 Future<LibraryElement> createLibrary(LibraryDependencyHandler handler, |
| 461 LibraryElement importingLibrary, | 450 LibraryElement importingLibrary, |
| 462 Uri resolvedUri, | 451 Uri resolvedUri, |
| 463 Node node, | 452 [Node node]) { |
| 464 Uri canonicalUri) { | |
| 465 // TODO(johnniwinther): Create erroneous library elements for missing | 453 // TODO(johnniwinther): Create erroneous library elements for missing |
| 466 // libraries. | 454 // libraries. |
| 467 Uri readableUri = | 455 Uri readableUri = |
| 468 compiler.translateResolvedUri(importingLibrary, resolvedUri, node); | 456 compiler.translateResolvedUri(importingLibrary, resolvedUri, node); |
| 469 if (readableUri == null) return new Future.value(); | 457 if (readableUri == null) return new Future.value(); |
| 470 LibraryElement library; | 458 LibraryElement library = compiler.libraries[resolvedUri.toString()]; |
| 471 if (canonicalUri != null) { | |
| 472 library = compiler.libraries[canonicalUri.toString()]; | |
| 473 } | |
| 474 if (library != null) { | 459 if (library != null) { |
| 475 return new Future.value(library); | 460 return new Future.value(library); |
| 476 } | 461 } |
| 477 return compiler.withCurrentElement(importingLibrary, () { | 462 return compiler.withCurrentElement(importingLibrary, () { |
| 478 return compiler.readScript(node, readableUri) | 463 return compiler.readScript(node, readableUri) |
| 479 .then((Script script) { | 464 .then((Script script) { |
| 480 if (script == null) return null; | 465 if (script == null) return null; |
| 481 LibraryElement element = new LibraryElementX(script, canonicalUri); | 466 LibraryElement element = new LibraryElementX(script, resolvedUri); |
| 482 compiler.withCurrentElement(element, () { | 467 compiler.withCurrentElement(element, () { |
| 468 compiler.onLibraryCreated(element); |
| 483 handler.registerNewLibrary(element); | 469 handler.registerNewLibrary(element); |
| 484 native.maybeEnableNative(compiler, element); | 470 native.maybeEnableNative(compiler, element); |
| 485 if (canonicalUri != null) { | 471 compiler.libraries[resolvedUri.toString()] = element; |
| 486 compiler.libraries[canonicalUri.toString()] = element; | |
| 487 } | |
| 488 compiler.scanner.scanLibrary(element); | 472 compiler.scanner.scanLibrary(element); |
| 489 }); | 473 }); |
| 490 return processLibraryTags(handler, element).then((_) { | 474 return processLibraryTags(handler, element).then((_) { |
| 491 compiler.withCurrentElement(element, () { | 475 compiler.withCurrentElement(element, () { |
| 492 handler.registerLibraryExports(element); | 476 handler.registerLibraryExports(element); |
| 493 onLibraryLoadedCallbacks.add( | |
| 494 () => compiler.onLibraryLoaded(element, resolvedUri)); | |
| 495 }); | 477 }); |
| 496 return element; | 478 return element; |
| 497 }); | 479 }); |
| 498 }); | 480 }); |
| 499 }); | 481 }); |
| 500 } | 482 } |
| 501 | |
| 502 // TODO(johnniwinther): Remove this method when 'js_helper' is handled by | |
| 503 // [LibraryLoaderTask]. | |
| 504 void importLibrary(LibraryElement importingLibrary, | |
| 505 LibraryElement importedLibrary, | |
| 506 Import tag) { | |
| 507 new ImportLink(tag, importedLibrary).importLibrary(compiler, | |
| 508 importingLibrary); | |
| 509 } | |
| 510 } | 483 } |
| 511 | 484 |
| 512 | 485 |
| 513 /** | 486 /** |
| 514 * The fields of this class models a state machine for checking script | 487 * The fields of this class models a state machine for checking script |
| 515 * tags come in the correct order. | 488 * tags come in the correct order. |
| 516 */ | 489 */ |
| 517 class TagState { | 490 class TagState { |
| 518 static const int NO_TAG_SEEN = 0; | 491 static const int NO_TAG_SEEN = 0; |
| 519 static const int LIBRARY = 1; | 492 static const int LIBRARY = 1; |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 */ | 809 */ |
| 837 class LibraryDependencyHandler { | 810 class LibraryDependencyHandler { |
| 838 final Compiler compiler; | 811 final Compiler compiler; |
| 839 | 812 |
| 840 /** | 813 /** |
| 841 * Newly loaded libraries and their corresponding node in the library | 814 * Newly loaded libraries and their corresponding node in the library |
| 842 * dependency graph. Libraries that have already been fully loaded are not | 815 * dependency graph. Libraries that have already been fully loaded are not |
| 843 * part of the dependency graph of this handler since their export scopes have | 816 * part of the dependency graph of this handler since their export scopes have |
| 844 * already been computed. | 817 * already been computed. |
| 845 */ | 818 */ |
| 846 Map<LibraryElement,LibraryDependencyNode> nodeMap = | 819 Map<LibraryElement, LibraryDependencyNode> nodeMap = |
| 847 new Map<LibraryElement,LibraryDependencyNode>(); | 820 new Map<LibraryElement, LibraryDependencyNode>(); |
| 848 | 821 |
| 849 LibraryDependencyHandler(Compiler this.compiler); | 822 LibraryDependencyHandler(Compiler this.compiler); |
| 850 | 823 |
| 824 /// The libraries loaded with this handler. |
| 825 Iterable<LibraryElement> get loadedLibraries => nodeMap.keys; |
| 826 |
| 851 /** | 827 /** |
| 852 * Performs a fixed-point computation on the export scopes of all registered | 828 * Performs a fixed-point computation on the export scopes of all registered |
| 853 * libraries and creates the import/export of the libraries based on the | 829 * libraries and creates the import/export of the libraries based on the |
| 854 * fixed-point. | 830 * fixed-point. |
| 855 */ | 831 */ |
| 856 void computeExports() { | 832 void computeExports() { |
| 857 bool changed = true; | 833 bool changed = true; |
| 858 while (changed) { | 834 while (changed) { |
| 859 changed = false; | 835 changed = false; |
| 860 Map<LibraryDependencyNode, Map<Element, Link<Export>>> tasks = | 836 Map<LibraryDependencyNode, Map<Element, Link<Export>>> tasks = |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 } | 911 } |
| 936 | 912 |
| 937 /** | 913 /** |
| 938 * Registers all top-level entities of [library] as starting point for the | 914 * Registers all top-level entities of [library] as starting point for the |
| 939 * fixed-point computation of the import/export scopes. | 915 * fixed-point computation of the import/export scopes. |
| 940 */ | 916 */ |
| 941 void registerLibraryExports(LibraryElement library) { | 917 void registerLibraryExports(LibraryElement library) { |
| 942 nodeMap[library].registerInitialExports(); | 918 nodeMap[library].registerInitialExports(); |
| 943 } | 919 } |
| 944 } | 920 } |
| OLD | NEW |