Chromium Code Reviews| 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 library dart2js.library_loader; |
| 6 | |
| 7 import 'dart:async'; | |
| 8 import 'dart2jslib.dart' | |
| 9 show Compiler, | |
| 10 CompilerTask, | |
| 11 MessageKind, | |
| 12 Script, | |
| 13 invariant; | |
| 14 import 'elements/elements.dart' | |
| 15 show CompilationUnitElement, | |
| 16 Element, | |
| 17 LibraryElement, | |
| 18 PrefixElement; | |
| 19 import 'elements/modelx.dart' | |
| 20 show CompilationUnitElementX, | |
| 21 DeferredLoaderGetterElementX, | |
| 22 ErroneousElementX, | |
| 23 LibraryElementX, | |
| 24 PrefixElementX; | |
| 25 import 'helpers/helpers.dart'; | |
| 26 import 'native_handler.dart' as native; | |
| 27 import 'tree/tree.dart'; | |
| 28 import 'util/util.dart' show Link, LinkBuilder; | |
| 6 | 29 |
| 7 /** | 30 /** |
| 8 * [CompilerTask] for loading libraries and setting up the import/export scopes. | 31 * [CompilerTask] for loading libraries and setting up the import/export scopes. |
| 9 * | 32 * |
| 10 * The library loader uses four different kinds of URIs in different parts of | 33 * The library loader uses four different kinds of URIs in different parts of |
| 11 * the loading process. | 34 * the loading process. |
| 12 * | 35 * |
| 13 * ## User URI ## | 36 * ## User URI ## |
| 14 * | 37 * |
| 15 * A 'user URI' is a URI provided by the user in code and as the main entry URI | 38 * A 'user URI' is a URI provided by the user in code and as the main entry URI |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 * [LibraryElement]. | 128 * [LibraryElement]. |
| 106 * | 129 * |
| 107 * If the library is not already loaded, the method creates the | 130 * If the library is not already loaded, the method creates the |
| 108 * [LibraryElement] for the library and computes the import/export scope, | 131 * [LibraryElement] for the library and computes the import/export scope, |
| 109 * loading and computing the import/export scopes of all required libraries in | 132 * loading and computing the import/export scopes of all required libraries in |
| 110 * the process. The method handles cyclic dependency between libraries. | 133 * the process. The method handles cyclic dependency between libraries. |
| 111 * | 134 * |
| 112 * This is the main entry point for [LibraryLoader]. | 135 * This is the main entry point for [LibraryLoader]. |
| 113 */ | 136 */ |
| 114 Future<LibraryElement> loadLibrary(Uri resolvedUri); | 137 Future<LibraryElement> loadLibrary(Uri resolvedUri); |
| 138 } | |
| 115 | 139 |
| 116 // TODO(johnniwinther): Remove this when patches don't need special parsing. | 140 /// Callback for creating synthesized/patch libraries during library loading. |
| 117 Future registerLibraryFromTag(LibraryDependencyHandler handler, | 141 abstract class LibraryLoaderCallback { |
|
floitsch
2014/06/23 19:12:33
Don't call this "callback". It took me some time t
Johnni Winther
2014/06/24 08:11:20
Done.
| |
| 118 LibraryElement library, | 142 /// Call this when a new synthesized/patch library has been created. |
|
floitsch
2014/06/23 19:12:33
This is ambiguous.
Who needs to call this method?
Johnni Winther
2014/06/24 08:11:20
Done.
| |
| 119 LibraryDependency tag); | 143 /// |
| 144 /// This call ensures that [library] will part of library dependency graph | |
| 145 /// used for computing import/export scopes. | |
| 146 void onLibraryCreated(LibraryElement library); | |
| 147 | |
| 148 /// Call this when a new synthesized/patch library has been scanned. | |
| 149 /// | |
| 150 /// On this call library tags in [library] will be processed, allowing for | |
| 151 /// imports/exports/parts in the synthesized/patch library. | |
| 152 Future onLibraryScanned(LibraryElement library); | |
| 120 } | 153 } |
| 121 | 154 |
| 122 /** | 155 /** |
| 123 * [CombinatorFilter] is a succinct representation of a list of combinators from | 156 * [CombinatorFilter] is a succinct representation of a list of combinators from |
| 124 * a library dependency tag. | 157 * a library dependency tag. |
| 125 */ | 158 */ |
| 126 class CombinatorFilter { | 159 class CombinatorFilter { |
| 127 const CombinatorFilter(); | 160 const CombinatorFilter(); |
| 128 | 161 |
| 129 /** | 162 /** |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 214 final Map<String, LibraryElement> libraryNames = | 247 final Map<String, LibraryElement> libraryNames = |
| 215 new Map<String, LibraryElement>(); | 248 new Map<String, LibraryElement>(); |
| 216 | 249 |
| 217 LibraryDependencyHandler currentHandler; | 250 LibraryDependencyHandler currentHandler; |
| 218 | 251 |
| 219 Future<LibraryElement> loadLibrary(Uri resolvedUri) { | 252 Future<LibraryElement> loadLibrary(Uri resolvedUri) { |
| 220 return measure(() { | 253 return measure(() { |
| 221 assert(currentHandler == null); | 254 assert(currentHandler == null); |
| 222 // TODO(johnniwinther): Ensure that currentHandler correctly encloses the | 255 // TODO(johnniwinther): Ensure that currentHandler correctly encloses the |
| 223 // loading of a library cluster. | 256 // loading of a library cluster. |
| 224 currentHandler = new LibraryDependencyHandler(compiler); | 257 currentHandler = new LibraryDependencyHandler(this); |
| 225 return createLibrary(currentHandler, null, resolvedUri) | 258 return createLibrary(currentHandler, null, resolvedUri) |
| 226 .then((LibraryElement library) { | 259 .then((LibraryElement library) { |
| 227 return compiler.withCurrentElement(library, () { | 260 return compiler.withCurrentElement(library, () { |
| 228 return measure(() { | 261 return measure(() { |
| 229 currentHandler.computeExports(); | 262 currentHandler.computeExports(); |
| 230 Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{}; | 263 Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{}; |
| 231 currentHandler.loadedLibraries.forEach( | 264 currentHandler.loadedLibraries.forEach( |
| 232 (LibraryElement loadedLibrary) { | 265 (LibraryElement loadedLibrary) { |
| 233 loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary; | 266 loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary; |
| 234 }); | 267 }); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 263 MessageKind.GENERIC, {'text': 'Error: Out of order.'}); | 296 MessageKind.GENERIC, {'text': 'Error: Out of order.'}); |
| 264 return tagState; | 297 return tagState; |
| 265 } | 298 } |
| 266 return TagState.NEXT[value]; | 299 return TagState.NEXT[value]; |
| 267 } | 300 } |
| 268 | 301 |
| 269 bool importsDartCore = false; | 302 bool importsDartCore = false; |
| 270 var libraryDependencies = new LinkBuilder<LibraryDependency>(); | 303 var libraryDependencies = new LinkBuilder<LibraryDependency>(); |
| 271 Uri base = library.entryCompilationUnit.script.readableUri; | 304 Uri base = library.entryCompilationUnit.script.readableUri; |
| 272 | 305 |
| 273 // TODO(rnystrom): Remove .toList() here if #11523 is fixed. | 306 // TODO(rnystrom): Remove .toList() here if #11523 is fixed. |
|
floitsch
2014/06/23 19:12:33
11523 has been closed with 'asDesigned'.
It should
Johnni Winther
2014/06/24 08:11:20
Removed the comment. Still need the `toList()` cal
| |
| 274 return Future.forEach(library.tags.reverse().toList(), (LibraryTag tag) { | 307 return Future.forEach(library.tags.reverse().toList(), (LibraryTag tag) { |
| 275 return compiler.withCurrentElement(library, () { | 308 return compiler.withCurrentElement(library, () { |
| 276 if (tag.isImport) { | 309 if (tag.isImport) { |
| 277 Import import = tag; | 310 Import import = tag; |
| 278 tagState = checkTag(TagState.IMPORT_OR_EXPORT, import); | 311 tagState = checkTag(TagState.IMPORT_OR_EXPORT, import); |
| 279 if (import.uri.dartString.slowToString() == 'dart:core') { | 312 if (import.uri.dartString.slowToString() == 'dart:core') { |
| 280 importsDartCore = true; | 313 importsDartCore = true; |
| 281 } | 314 } |
| 282 libraryDependencies.addLast(import); | 315 libraryDependencies.addLast(import); |
| 283 } else if (tag.isExport) { | 316 } else if (tag.isExport) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 294 Part part = tag; | 327 Part part = tag; |
| 295 StringNode uri = part.uri; | 328 StringNode uri = part.uri; |
| 296 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); | 329 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); |
| 297 tagState = checkTag(TagState.SOURCE, part); | 330 tagState = checkTag(TagState.SOURCE, part); |
| 298 return scanPart(part, resolvedUri, library); | 331 return scanPart(part, resolvedUri, library); |
| 299 } else { | 332 } else { |
| 300 compiler.internalError(tag, "Unhandled library tag."); | 333 compiler.internalError(tag, "Unhandled library tag."); |
| 301 } | 334 } |
| 302 }); | 335 }); |
| 303 }).then((_) { | 336 }).then((_) { |
| 304 // TODO(johnniwinther): Move callback to after patching. | 337 return compiler.onLibraryScanned(library, handler); |
| 305 compiler.onLibraryScanned(library); | 338 }).then((_) { |
| 306 return compiler.withCurrentElement(library, () { | 339 return compiler.withCurrentElement(library, () { |
| 307 checkDuplicatedLibraryName(library); | 340 checkDuplicatedLibraryName(library); |
| 308 // Apply patch, if any. | 341 |
| 309 if (library.isPlatformLibrary) { | |
| 310 return patchDartLibrary(handler, library, library.canonicalUri.path); | |
| 311 } | |
| 312 }); | |
| 313 }).then((_) { | |
| 314 return compiler.withCurrentElement(library, () { | |
| 315 // Import dart:core if not already imported. | 342 // Import dart:core if not already imported. |
| 316 if (!importsDartCore && !isDartCore(library.canonicalUri)) { | 343 if (!importsDartCore && !isDartCore(library.canonicalUri)) { |
| 317 return loadCoreLibrary(handler).then((LibraryElement coreLibrary) { | 344 return loadCoreLibrary(handler).then((LibraryElement coreLibrary) { |
| 318 handler.registerDependency(library, null, coreLibrary); | 345 handler.registerDependency(library, null, coreLibrary); |
| 319 }); | 346 }); |
| 320 } | 347 } |
| 321 }); | 348 }); |
| 322 }).then((_) { | 349 }).then((_) { |
| 323 // TODO(rnystrom): Remove .toList() here if #11523 is fixed. | 350 // TODO(rnystrom): Remove .toList() here if #11523 is fixed. |
| 324 return Future.forEach(libraryDependencies.toLink().toList(), (tag) { | 351 return Future.forEach(libraryDependencies.toLink().toList(), (tag) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 379 return new Future.value(compiler.coreLibrary); | 406 return new Future.value(compiler.coreLibrary); |
| 380 } | 407 } |
| 381 | 408 |
| 382 Uri coreUri = new Uri(scheme: 'dart', path: 'core'); | 409 Uri coreUri = new Uri(scheme: 'dart', path: 'core'); |
| 383 return createLibrary(handler, null, coreUri).then((LibraryElement library) { | 410 return createLibrary(handler, null, coreUri).then((LibraryElement library) { |
| 384 compiler.coreLibrary = library; | 411 compiler.coreLibrary = library; |
| 385 return library; | 412 return library; |
| 386 }); | 413 }); |
| 387 } | 414 } |
| 388 | 415 |
| 389 Future patchDartLibrary(LibraryDependencyHandler handler, | |
| 390 LibraryElement library, | |
| 391 String dartLibraryPath) { | |
| 392 if (library.isPatched) return new Future.value(); | |
| 393 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath); | |
| 394 if (patchUri == null) return new Future.value(); | |
| 395 | |
| 396 return compiler.patchParser.patchLibrary(handler, patchUri, library); | |
| 397 } | |
| 398 | |
| 399 /** | 416 /** |
| 400 * Handle a part tag in the scope of [library]. The [resolvedUri] given is | 417 * Handle a part tag in the scope of [library]. The [resolvedUri] given is |
| 401 * used as is, any URI resolution should be done beforehand. | 418 * used as is, any URI resolution should be done beforehand. |
| 402 */ | 419 */ |
| 403 Future scanPart(Part part, Uri resolvedUri, LibraryElement library) { | 420 Future scanPart(Part part, Uri resolvedUri, LibraryElement library) { |
| 404 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri); | 421 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri); |
| 405 Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part); | 422 Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part); |
| 406 if (readableUri == null) return new Future.value(); | 423 if (readableUri == null) return new Future.value(); |
| 407 return compiler.withCurrentElement(library, () { | 424 return compiler.withCurrentElement(library, () { |
| 408 return compiler.readScript(part, readableUri). | 425 return compiler.readScript(part, readableUri). |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 458 LibraryElement library = compiler.libraries[resolvedUri.toString()]; | 475 LibraryElement library = compiler.libraries[resolvedUri.toString()]; |
| 459 if (library != null) { | 476 if (library != null) { |
| 460 return new Future.value(library); | 477 return new Future.value(library); |
| 461 } | 478 } |
| 462 return compiler.withCurrentElement(importingLibrary, () { | 479 return compiler.withCurrentElement(importingLibrary, () { |
| 463 return compiler.readScript(node, readableUri) | 480 return compiler.readScript(node, readableUri) |
| 464 .then((Script script) { | 481 .then((Script script) { |
| 465 if (script == null) return null; | 482 if (script == null) return null; |
| 466 LibraryElement element = new LibraryElementX(script, resolvedUri); | 483 LibraryElement element = new LibraryElementX(script, resolvedUri); |
| 467 compiler.withCurrentElement(element, () { | 484 compiler.withCurrentElement(element, () { |
| 468 compiler.onLibraryCreated(element); | 485 handler.onLibraryCreated(element); |
| 469 handler.registerNewLibrary(element); | |
| 470 native.maybeEnableNative(compiler, element); | 486 native.maybeEnableNative(compiler, element); |
| 471 compiler.libraries[resolvedUri.toString()] = element; | 487 compiler.libraries[resolvedUri.toString()] = element; |
| 472 compiler.scanner.scanLibrary(element); | 488 compiler.scanner.scanLibrary(element); |
| 473 }); | 489 }); |
| 474 return processLibraryTags(handler, element).then((_) { | 490 return processLibraryTags(handler, element).then((_) { |
| 475 compiler.withCurrentElement(element, () { | 491 compiler.withCurrentElement(element, () { |
| 476 handler.registerLibraryExports(element); | 492 handler.registerLibraryExports(element); |
| 477 }); | 493 }); |
| 478 return element; | 494 return element; |
| 479 }); | 495 }); |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 800 } | 816 } |
| 801 | 817 |
| 802 /** | 818 /** |
| 803 * Helper class used for computing the possibly cyclic import/export scopes of | 819 * Helper class used for computing the possibly cyclic import/export scopes of |
| 804 * a set of libraries. | 820 * a set of libraries. |
| 805 * | 821 * |
| 806 * This class is used by [ScannerTask.scanLibrary] to collect all newly loaded | 822 * This class is used by [ScannerTask.scanLibrary] to collect all newly loaded |
| 807 * libraries and to compute their import/export scopes through a fixed-point | 823 * libraries and to compute their import/export scopes through a fixed-point |
| 808 * algorithm. | 824 * algorithm. |
| 809 */ | 825 */ |
| 810 class LibraryDependencyHandler { | 826 class LibraryDependencyHandler implements LibraryLoaderCallback { |
| 811 final Compiler compiler; | 827 final LibraryLoaderTask task; |
| 812 | 828 |
| 813 /** | 829 /** |
| 814 * Newly loaded libraries and their corresponding node in the library | 830 * Newly loaded libraries and their corresponding node in the library |
| 815 * dependency graph. Libraries that have already been fully loaded are not | 831 * dependency graph. Libraries that have already been fully loaded are not |
| 816 * part of the dependency graph of this handler since their export scopes have | 832 * part of the dependency graph of this handler since their export scopes have |
| 817 * already been computed. | 833 * already been computed. |
| 818 */ | 834 */ |
| 819 Map<LibraryElement, LibraryDependencyNode> nodeMap = | 835 Map<LibraryElement, LibraryDependencyNode> nodeMap = |
| 820 new Map<LibraryElement, LibraryDependencyNode>(); | 836 new Map<LibraryElement, LibraryDependencyNode>(); |
| 821 | 837 |
| 822 LibraryDependencyHandler(Compiler this.compiler); | 838 LibraryDependencyHandler(LibraryLoaderTask this.task); |
| 839 | |
| 840 Compiler get compiler => task.compiler; | |
| 823 | 841 |
| 824 /// The libraries loaded with this handler. | 842 /// The libraries loaded with this handler. |
| 825 Iterable<LibraryElement> get loadedLibraries => nodeMap.keys; | 843 Iterable<LibraryElement> get loadedLibraries => nodeMap.keys; |
| 826 | 844 |
| 827 /** | 845 /** |
| 828 * Performs a fixed-point computation on the export scopes of all registered | 846 * Performs a fixed-point computation on the export scopes of all registered |
| 829 * libraries and creates the import/export of the libraries based on the | 847 * libraries and creates the import/export of the libraries based on the |
| 830 * fixed-point. | 848 * fixed-point. |
| 831 */ | 849 */ |
| 832 void computeExports() { | 850 void computeExports() { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 910 nodeMap[library] = new LibraryDependencyNode(library); | 928 nodeMap[library] = new LibraryDependencyNode(library); |
| 911 } | 929 } |
| 912 | 930 |
| 913 /** | 931 /** |
| 914 * Registers all top-level entities of [library] as starting point for the | 932 * Registers all top-level entities of [library] as starting point for the |
| 915 * fixed-point computation of the import/export scopes. | 933 * fixed-point computation of the import/export scopes. |
| 916 */ | 934 */ |
| 917 void registerLibraryExports(LibraryElement library) { | 935 void registerLibraryExports(LibraryElement library) { |
| 918 nodeMap[library].registerInitialExports(); | 936 nodeMap[library].registerInitialExports(); |
| 919 } | 937 } |
| 938 | |
| 939 void onLibraryCreated(LibraryElement library) { | |
| 940 compiler.onLibraryCreated(library); | |
| 941 registerNewLibrary(library); | |
| 942 } | |
| 943 | |
| 944 Future onLibraryScanned(LibraryElement library) { | |
| 945 return task.processLibraryTags(this, library); | |
| 946 } | |
| 920 } | 947 } |
| OLD | NEW |