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 |