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 | 8 |
9 import 'common/names.dart' show Uris; | 9 import 'common/names.dart' show Uris; |
10 import 'common/tasks.dart' show CompilerTask, Measurer; | 10 import 'common/tasks.dart' show CompilerTask, Measurer; |
(...skipping 11 matching lines...) Expand all Loading... | |
22 DeferredLoaderGetterElementX, | 22 DeferredLoaderGetterElementX, |
23 ErroneousElementX, | 23 ErroneousElementX, |
24 ExportElementX, | 24 ExportElementX, |
25 ImportElementX, | 25 ImportElementX, |
26 LibraryElementX, | 26 LibraryElementX, |
27 LibraryDependencyElementX, | 27 LibraryDependencyElementX, |
28 PrefixElementX, | 28 PrefixElementX, |
29 SyntheticImportElement; | 29 SyntheticImportElement; |
30 import 'enqueue.dart' show DeferredAction; | 30 import 'enqueue.dart' show DeferredAction; |
31 import 'environment.dart'; | 31 import 'environment.dart'; |
32 import 'io/source_file.dart' show SourceFile; | |
33 import 'patch_parser.dart' show PatchParserTask; | |
32 import 'resolved_uri_translator.dart'; | 34 import 'resolved_uri_translator.dart'; |
33 import 'script.dart'; | 35 import 'script.dart'; |
34 import 'serialization/serialization.dart' show LibraryDeserializer; | 36 import 'serialization/serialization.dart' show LibraryDeserializer; |
35 import 'tree/tree.dart'; | 37 import 'tree/tree.dart'; |
36 import 'util/util.dart' show Link, LinkBuilder; | 38 import 'util/util.dart' show Link, LinkBuilder; |
37 | 39 |
40 import 'package:front_end/src/fasta/scanner.dart' show Token; | |
41 | |
38 typedef Future<Iterable<LibraryElement>> ReuseLibrariesFunction( | 42 typedef Future<Iterable<LibraryElement>> ReuseLibrariesFunction( |
39 Iterable<LibraryElement> libraries); | 43 Iterable<LibraryElement> libraries); |
40 | 44 |
45 typedef Uri PatchResolverFunction(String dartLibraryPath); | |
46 | |
41 /** | 47 /** |
42 * [CompilerTask] for loading libraries and setting up the import/export scopes. | 48 * [CompilerTask] for loading libraries and setting up the import/export scopes. |
43 * | 49 * |
44 * The library loader uses four different kinds of URIs in different parts of | 50 * The library loader uses four different kinds of URIs in different parts of |
45 * the loading process. | 51 * the loading process. |
46 * | 52 * |
47 * ## User URI ## | 53 * ## User URI ## |
48 * | 54 * |
49 * A 'user URI' is a URI provided by the user in code and as the main entry URI | 55 * A 'user URI' is a URI provided by the user in code and as the main entry URI |
50 * at the command line. These generally come in 3 versions: | 56 * at the command line. These generally come in 3 versions: |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
131 * do _not_ resolve to the same library when the package root URI happens to | 137 * do _not_ resolve to the same library when the package root URI happens to |
132 * point to the 'packages' folder. | 138 * point to the 'packages' folder. |
133 * | 139 * |
134 */ | 140 */ |
135 abstract class LibraryLoaderTask implements LibraryProvider, CompilerTask { | 141 abstract class LibraryLoaderTask implements LibraryProvider, CompilerTask { |
136 factory LibraryLoaderTask( | 142 factory LibraryLoaderTask( |
137 ResolvedUriTranslator uriTranslator, | 143 ResolvedUriTranslator uriTranslator, |
138 ScriptLoader scriptLoader, | 144 ScriptLoader scriptLoader, |
139 ElementScanner scriptScanner, | 145 ElementScanner scriptScanner, |
140 LibraryDeserializer deserializer, | 146 LibraryDeserializer deserializer, |
141 LibraryLoaderListener listener, | 147 PatchResolverFunction patchResolverFunc, |
148 PatchParserTask patchParser, | |
142 Environment environment, | 149 Environment environment, |
143 DiagnosticReporter reporter, | 150 DiagnosticReporter reporter, |
144 Measurer measurer) = _LibraryLoaderTask; | 151 Measurer measurer) = _LibraryLoaderTask; |
145 | 152 |
146 /// Returns all libraries that have been loaded. | 153 /// Returns all libraries that have been loaded. |
147 Iterable<LibraryElement> get libraries; | 154 Iterable<LibraryElement> get libraries; |
148 | 155 |
149 /// Loads the library specified by the [resolvedUri] and returns its | 156 /// Loads the library specified by the [resolvedUri] and returns the |
150 /// [LibraryElement]. | 157 /// [LoadedLibraries] that were loaded to load the specified uri. The |
158 /// [LibraryElement] itself can be found by calling | |
159 /// `loadedLibraries.rootLibrary` | |
Siggi Cherem (dart-lang)
2017/03/24 17:40:28
nit: add a `.` at the end.
Emily Fortuna
2017/03/24 18:30:19
Done.
| |
151 /// | 160 /// |
152 /// If the library is not already loaded, the method creates the | 161 /// If the library is not already loaded, the method creates the |
153 /// [LibraryElement] for the library and computes the import/export scope, | 162 /// [LibraryElement] for the library and computes the import/export scope, |
154 /// loading and computing the import/export scopes of all required libraries | 163 /// loading and computing the import/export scopes of all required libraries |
155 /// in the process. The method handles cyclic dependency between libraries. | 164 /// in the process. The method handles cyclic dependency between libraries. |
156 /// | 165 /// |
157 /// If [skipFileWithPartOfTag] is `true`, `null` is returned if the | 166 /// If [skipFileWithPartOfTag] is `true`, `null` is returned if the |
158 /// compilation unit for [resolvedUri] contains a `part of` tag. This is only | 167 /// compilation unit for [resolvedUri] contains a `part of` tag. This is only |
159 /// used for analysis through [Compiler.analyzeUri]. | 168 /// used for analysis through [Compiler.analyzeUri]. |
160 Future<LibraryElement> loadLibrary(Uri resolvedUri, | 169 Future<LoadedLibraries> loadLibrary(Uri resolvedUri, |
161 {bool skipFileWithPartOfTag: false}); | 170 {bool skipFileWithPartOfTag: false}); |
162 | 171 |
163 /// Reset the library loader task to prepare for compilation. If provided, | 172 /// Reset the library loader task to prepare for compilation. If provided, |
164 /// libraries matching [reuseLibrary] are reused. | 173 /// libraries matching [reuseLibrary] are reused. |
165 /// | 174 /// |
166 /// This method is used for incremental compilation. | 175 /// This method is used for incremental compilation. |
167 void reset({bool reuseLibrary(LibraryElement library)}); | 176 void reset({bool reuseLibrary(LibraryElement library)}); |
168 | 177 |
169 /// Asynchronous version of [reset]. | 178 /// Asynchronous version of [reset]. |
170 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)); | 179 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)); |
171 | 180 |
172 /// Similar to [resetAsync] but [reuseLibrary] maps all libraries to a list | 181 /// Similar to [resetAsync] but [reuseLibrary] maps all libraries to a list |
173 /// of libraries that can be reused. | 182 /// of libraries that can be reused. |
174 Future<Null> resetLibraries(ReuseLibrariesFunction reuseLibraries); | 183 Future<Null> resetLibraries(ReuseLibrariesFunction reuseLibraries); |
175 | 184 |
176 // TODO(johnniwinther): Move these to a separate interface. | 185 // TODO(johnniwinther): Move these to a separate interface. |
177 /// Register a deferred action to be performed during resolution. | 186 /// Register a deferred action to be performed during resolution. |
178 void registerDeferredAction(DeferredAction action); | 187 void registerDeferredAction(DeferredAction action); |
179 | 188 |
180 /// Returns the deferred actions registered since the last call to | 189 /// Returns the deferred actions registered since the last call to |
181 /// [pullDeferredActions]. | 190 /// [pullDeferredActions]. |
182 Iterable<DeferredAction> pullDeferredActions(); | 191 Iterable<DeferredAction> pullDeferredActions(); |
192 | |
193 /// The locations of js patch-files relative to the sdk-descriptors. | |
194 static const _patchLocations = const <String, String>{ | |
195 "async": "_internal/js_runtime/lib/async_patch.dart", | |
196 "collection": "_internal/js_runtime/lib/collection_patch.dart", | |
197 "convert": "_internal/js_runtime/lib/convert_patch.dart", | |
198 "core": "_internal/js_runtime/lib/core_patch.dart", | |
199 "developer": "_internal/js_runtime/lib/developer_patch.dart", | |
200 "io": "_internal/js_runtime/lib/io_patch.dart", | |
201 "isolate": "_internal/js_runtime/lib/isolate_patch.dart", | |
202 "math": "_internal/js_runtime/lib/math_patch.dart", | |
203 "mirrors": "_internal/js_runtime/lib/mirrors_patch.dart", | |
204 "typed_data": "_internal/js_runtime/lib/typed_data_patch.dart", | |
205 "_internal": "_internal/js_runtime/lib/internal_patch.dart" | |
206 }; | |
207 | |
208 /// Returns the location of the patch-file associated with [libraryName] | |
209 /// resolved from [plaformConfigUri]. | |
210 /// | |
211 /// Returns null if there is none. | |
212 static Uri resolvePatchUri(String libraryName, Uri platformConfigUri) { | |
213 String patchLocation = _patchLocations[libraryName]; | |
214 if (patchLocation == null) return null; | |
215 return platformConfigUri.resolve(patchLocation); | |
216 } | |
183 } | 217 } |
184 | 218 |
185 /// Interface for an entity that provide libraries. For instance from normal | 219 /// Interface for an entity that provide libraries. For instance from normal |
186 /// library loading or from deserialization. | 220 /// library loading or from deserialization. |
187 // TODO(johnniwinther): Use this to integrate deserialized libraries better. | 221 // TODO(johnniwinther): Use this to integrate deserialized libraries better. |
188 abstract class LibraryProvider { | 222 abstract class LibraryProvider { |
189 /// Looks up the library with the [canonicalUri]. | 223 /// Looks up the library with the [canonicalUri]. |
190 LibraryElement lookupLibrary(Uri canonicalUri); | 224 LibraryElement lookupLibrary(Uri canonicalUri); |
191 } | 225 } |
192 | 226 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
296 final ScriptLoader scriptLoader; | 330 final ScriptLoader scriptLoader; |
297 | 331 |
298 /// Provides a diet element model from a script file containing information | 332 /// Provides a diet element model from a script file containing information |
299 /// about imports and exports. Used when loading libraries from source. | 333 /// about imports and exports. Used when loading libraries from source. |
300 final ElementScanner scanner; | 334 final ElementScanner scanner; |
301 | 335 |
302 /// Provides a diet element model for a library. Used when loading libraries | 336 /// Provides a diet element model for a library. Used when loading libraries |
303 /// from a serialized form. | 337 /// from a serialized form. |
304 final LibraryDeserializer deserializer; | 338 final LibraryDeserializer deserializer; |
305 | 339 |
306 /// Hooks to inform others about progress done by this loader. | |
307 // TODO(sigmund): move away from this. | |
308 final LibraryLoaderListener listener; | |
309 | |
310 /// Definitions provided via the `-D` command line flags. Used to resolve | 340 /// Definitions provided via the `-D` command line flags. Used to resolve |
311 /// conditional imports. | 341 /// conditional imports. |
312 final Environment environment; | 342 final Environment environment; |
313 | 343 |
344 // TODO(efortuna): Don't pass PatchParserTask here. | |
345 final PatchParserTask _patchParserTask; | |
346 | |
347 /// Function that accepts the string name of a library and returns the | |
348 /// path to the corresponding patch file. This is a function that is passed in | |
349 /// because our test mock_compiler subclasses compiler. | |
350 // TODO(efortuna): Refactor mock_compiler to not do this. | |
Siggi Cherem (dart-lang)
2017/03/24 17:40:27
thanks for documenting so nicely the issue :)
I h
Emily Fortuna
2017/03/24 18:30:19
makes sense. upcoming CL!
| |
351 final PatchResolverFunction _patchResolverFunc; | |
352 | |
314 List<DeferredAction> _deferredActions = <DeferredAction>[]; | 353 List<DeferredAction> _deferredActions = <DeferredAction>[]; |
315 | 354 |
316 final DiagnosticReporter reporter; | 355 final DiagnosticReporter reporter; |
317 | 356 |
318 _LibraryLoaderTask( | 357 _LibraryLoaderTask( |
319 this.uriTranslator, | 358 this.uriTranslator, |
320 this.scriptLoader, | 359 this.scriptLoader, |
321 this.scanner, | 360 this.scanner, |
322 this.deserializer, | 361 this.deserializer, |
323 this.listener, | 362 this._patchResolverFunc, |
363 this._patchParserTask, | |
324 this.environment, | 364 this.environment, |
325 this.reporter, | 365 this.reporter, |
326 Measurer measurer) | 366 Measurer measurer) |
327 : super(measurer); | 367 : super(measurer); |
328 | 368 |
329 String get name => 'LibraryLoader'; | 369 String get name => 'LibraryLoader'; |
330 | 370 |
331 final Map<Uri, LibraryElement> libraryCanonicalUriMap = | 371 final Map<Uri, LibraryElement> libraryCanonicalUriMap = |
332 new Map<Uri, LibraryElement>(); | 372 new Map<Uri, LibraryElement>(); |
333 final Map<Uri, LibraryElement> libraryResourceUriMap = | 373 final Map<Uri, LibraryElement> libraryResourceUriMap = |
334 new Map<Uri, LibraryElement>(); | 374 new Map<Uri, LibraryElement>(); |
335 final Map<String, LibraryElement> libraryNames = | 375 final Map<String, LibraryElement> libraryNames = |
336 new Map<String, LibraryElement>(); | 376 new Map<String, LibraryElement>(); |
337 | 377 |
338 LibraryDependencyHandler currentHandler; | |
339 | |
340 Iterable<LibraryElement> get libraries => libraryCanonicalUriMap.values; | 378 Iterable<LibraryElement> get libraries => libraryCanonicalUriMap.values; |
341 | 379 |
342 LibraryElement lookupLibrary(Uri canonicalUri) { | 380 LibraryElement lookupLibrary(Uri canonicalUri) { |
343 return libraryCanonicalUriMap[canonicalUri]; | 381 return libraryCanonicalUriMap[canonicalUri]; |
344 } | 382 } |
345 | 383 |
346 void reset({bool reuseLibrary(LibraryElement library)}) { | 384 void reset({bool reuseLibrary(LibraryElement library)}) { |
347 measure(() { | 385 measure(() { |
348 assert(currentHandler == null); | |
349 | |
350 Iterable<LibraryElement> reusedLibraries = null; | 386 Iterable<LibraryElement> reusedLibraries = null; |
351 if (reuseLibrary != null) { | 387 if (reuseLibrary != null) { |
352 reusedLibraries = measureSubtask(_reuseLibrarySubtaskName, () { | 388 reusedLibraries = measureSubtask(_reuseLibrarySubtaskName, () { |
353 // Call [toList] to force eager calls to [reuseLibrary]. | 389 // Call [toList] to force eager calls to [reuseLibrary]. |
354 return libraryCanonicalUriMap.values.where(reuseLibrary).toList(); | 390 return libraryCanonicalUriMap.values.where(reuseLibrary).toList(); |
355 }); | 391 }); |
356 } | 392 } |
357 | 393 |
358 resetImplementation(reusedLibraries); | 394 resetImplementation(reusedLibraries); |
359 }); | 395 }); |
360 } | 396 } |
361 | 397 |
362 void resetImplementation(Iterable<LibraryElement> reusedLibraries) { | 398 void resetImplementation(Iterable<LibraryElement> reusedLibraries) { |
363 measure(() { | 399 measure(() { |
364 libraryCanonicalUriMap.clear(); | 400 libraryCanonicalUriMap.clear(); |
365 libraryResourceUriMap.clear(); | 401 libraryResourceUriMap.clear(); |
366 libraryNames.clear(); | 402 libraryNames.clear(); |
367 | 403 |
368 if (reusedLibraries != null) { | 404 if (reusedLibraries != null) { |
369 reusedLibraries.forEach(mapLibrary); | 405 reusedLibraries.forEach(mapLibrary); |
370 } | 406 } |
371 }); | 407 }); |
372 } | 408 } |
373 | 409 |
374 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)) { | 410 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)) { |
375 return measure(() { | 411 return measure(() { |
376 assert(currentHandler == null); | |
377 | |
378 Future<LibraryElement> wrapper(LibraryElement library) { | 412 Future<LibraryElement> wrapper(LibraryElement library) { |
379 try { | 413 try { |
380 return reuseLibrary(library) | 414 return reuseLibrary(library) |
381 .then((bool reuse) => reuse ? library : null); | 415 .then((bool reuse) => reuse ? library : null); |
382 } catch (exception, trace) { | 416 } catch (exception, trace) { |
383 reporter.onCrashInUserCode( | 417 reporter.onCrashInUserCode( |
384 'Uncaught exception in reuseLibrary', exception, trace); | 418 'Uncaught exception in reuseLibrary', exception, trace); |
385 rethrow; | 419 rethrow; |
386 } | 420 } |
387 } | 421 } |
388 | 422 |
389 List<Future<LibraryElement>> reusedLibrariesFuture = measureSubtask( | 423 List<Future<LibraryElement>> reusedLibrariesFuture = measureSubtask( |
390 _reuseLibrarySubtaskName, | 424 _reuseLibrarySubtaskName, |
391 () => libraryCanonicalUriMap.values.map(wrapper).toList()); | 425 () => libraryCanonicalUriMap.values.map(wrapper).toList()); |
392 | 426 |
393 return Future | 427 return Future |
394 .wait(reusedLibrariesFuture) | 428 .wait(reusedLibrariesFuture) |
395 .then((Iterable<LibraryElement> reusedLibraries) { | 429 .then((Iterable<LibraryElement> reusedLibraries) { |
396 resetImplementation(reusedLibraries.where((e) => e != null)); | 430 resetImplementation(reusedLibraries.where((e) => e != null)); |
397 }); | 431 }); |
398 }); | 432 }); |
399 } | 433 } |
400 | 434 |
401 Future<Null> resetLibraries( | 435 Future<Null> resetLibraries( |
402 Future<Iterable<LibraryElement>> reuseLibraries( | 436 Future<Iterable<LibraryElement>> reuseLibraries( |
403 Iterable<LibraryElement> libraries)) { | 437 Iterable<LibraryElement> libraries)) { |
404 assert(currentHandler == null); | |
405 return measureSubtask(_reuseLibrarySubtaskName, () { | 438 return measureSubtask(_reuseLibrarySubtaskName, () { |
406 return new Future<Iterable<LibraryElement>>(() { | 439 return new Future<Iterable<LibraryElement>>(() { |
407 // Wrap in Future to shield against errors in user code. | 440 // Wrap in Future to shield against errors in user code. |
408 return reuseLibraries(libraryCanonicalUriMap.values); | 441 return reuseLibraries(libraryCanonicalUriMap.values); |
409 }).catchError((exception, StackTrace trace) { | 442 }).catchError((exception, StackTrace trace) { |
410 reporter.onCrashInUserCode( | 443 reporter.onCrashInUserCode( |
411 'Uncaught exception in reuseLibraries', exception, trace); | 444 'Uncaught exception in reuseLibraries', exception, trace); |
412 throw exception; // Async rethrow. | 445 throw exception; // Async rethrow. |
413 }).then((Iterable<LibraryElement> reusedLibraries) { | 446 }).then((Iterable<LibraryElement> reusedLibraries) { |
414 measure(() { | 447 measure(() { |
415 resetImplementation(reusedLibraries); | 448 resetImplementation(reusedLibraries); |
416 }); | 449 }); |
417 }); | 450 }); |
418 }); | 451 }); |
419 } | 452 } |
420 | 453 |
421 /// Insert [library] in the internal maps. Used for compiler reuse. | 454 /// Insert [library] in the internal maps. Used for compiler reuse. |
422 void mapLibrary(LibraryElement library) { | 455 void mapLibrary(LibraryElement library) { |
423 libraryCanonicalUriMap[library.canonicalUri] = library; | 456 libraryCanonicalUriMap[library.canonicalUri] = library; |
424 | 457 |
425 Uri resourceUri = library.entryCompilationUnit.script.resourceUri; | 458 Uri resourceUri = library.entryCompilationUnit.script.resourceUri; |
426 libraryResourceUriMap[resourceUri] = library; | 459 libraryResourceUriMap[resourceUri] = library; |
427 | 460 |
428 if (library.hasLibraryName) { | 461 if (library.hasLibraryName) { |
429 String name = library.libraryName; | 462 String name = library.libraryName; |
430 libraryNames[name] = library; | 463 libraryNames[name] = library; |
431 } | 464 } |
432 } | 465 } |
433 | 466 |
434 Future<LibraryElement> loadLibrary(Uri resolvedUri, | 467 Future<LoadedLibraries> loadLibrary(Uri resolvedUri, |
435 {bool skipFileWithPartOfTag: false}) { | 468 {bool skipFileWithPartOfTag: false}) async { |
Siggi Cherem (dart-lang)
2017/03/24 17:40:28
seems like you don't need async here
Emily Fortuna
2017/03/24 18:30:19
Done.
| |
436 return measure(() { | 469 return measure(() async { |
437 assert(currentHandler == null); | 470 LibraryDependencyHandler loader = new LibraryDependencyHandler(this); |
Siggi Cherem (dart-lang)
2017/03/24 17:40:27
nit: maybe rename loader as handler?
Emily Fortuna
2017/03/24 18:30:19
Done.
| |
438 // TODO(johnniwinther): Ensure that currentHandler correctly encloses the | 471 LibraryElement library = await createLibrary( |
439 // loading of a library cluster. | 472 loader, null, resolvedUri, NO_LOCATION_SPANNABLE, |
440 currentHandler = new LibraryDependencyHandler(this); | 473 skipFileWithPartOfTag: skipFileWithPartOfTag); |
441 return createLibrary( | 474 if (library == null) { |
Siggi Cherem (dart-lang)
2017/03/24 17:40:28
style nit: we don't use the {} on this fast-exit c
Emily Fortuna
2017/03/24 18:30:19
Done.
| |
442 currentHandler, null, resolvedUri, NO_LOCATION_SPANNABLE, | 475 return null; |
443 skipFileWithPartOfTag: skipFileWithPartOfTag) | 476 } |
444 .then((LibraryElement library) { | 477 return reporter.withCurrentElement(library, () { |
445 if (library == null) { | 478 return measure(() { |
446 currentHandler = null; | 479 loader.computeExports(); |
447 return null; | 480 return new _LoadedLibraries(library, loader.newLibraries, this); |
448 } | |
449 return reporter.withCurrentElement(library, () { | |
450 return measure(() { | |
451 currentHandler.computeExports(); | |
452 LoadedLibraries loadedLibraries = new _LoadedLibraries(library, | |
453 currentHandler.newLibraries, currentHandler.nodeMap, this); | |
454 currentHandler = null; | |
455 return listener | |
456 .onLibrariesLoaded(loadedLibraries) | |
457 .then((_) => library); | |
458 }); | |
459 }); | 481 }); |
460 }); | 482 }); |
461 }); | 483 }); |
462 } | 484 } |
463 | 485 |
464 /** | 486 /** |
465 * Processes the library tags in [library]. | 487 * Processes the library tags in [library]. |
466 * | 488 * |
467 * The imported/exported libraries are loaded and processed recursively but | 489 * The imported/exported libraries are loaded and processed recursively but |
468 * the import/export scopes are not set up. | 490 * the import/export scopes are not set up. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
541 Part part = tag; | 563 Part part = tag; |
542 StringNode uri = part.uri; | 564 StringNode uri = part.uri; |
543 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); | 565 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); |
544 tagState.checkTag(TagState.PART, part, reporter); | 566 tagState.checkTag(TagState.PART, part, reporter); |
545 return scanPart(part, resolvedUri, library); | 567 return scanPart(part, resolvedUri, library); |
546 } else { | 568 } else { |
547 reporter.internalError(tag, "Unhandled library tag."); | 569 reporter.internalError(tag, "Unhandled library tag."); |
548 } | 570 } |
549 }); | 571 }); |
550 }).then((_) { | 572 }).then((_) { |
551 return listener.onLibraryScanned(library, handler); | |
Siggi Cherem (dart-lang)
2017/03/24 17:40:27
woo hoo!
| |
552 }).then((_) { | |
553 return reporter.withCurrentElement(library, () { | 573 return reporter.withCurrentElement(library, () { |
554 checkDuplicatedLibraryName(library); | 574 checkDuplicatedLibraryName(library); |
555 | 575 |
556 // Import dart:core if not already imported. | 576 // Import dart:core if not already imported. |
557 if (!importsDartCore && library.canonicalUri != Uris.dart_core) { | 577 if (!importsDartCore && library.canonicalUri != Uris.dart_core) { |
558 return createLibrary(handler, null, Uris.dart_core, library) | 578 return createLibrary(handler, null, Uris.dart_core, library) |
559 .then((LibraryElement coreLibrary) { | 579 .then((LibraryElement coreLibrary) { |
560 handler.registerDependency( | 580 handler.registerDependency( |
561 library, | 581 library, |
562 new SyntheticImportElement( | 582 new SyntheticImportElement( |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
652 } | 672 } |
653 | 673 |
654 /// Loads the deserialized [library] with the [handler]. | 674 /// Loads the deserialized [library] with the [handler]. |
655 /// | 675 /// |
656 /// All libraries imported or exported transitively from [library] will be | 676 /// All libraries imported or exported transitively from [library] will be |
657 /// loaded as well. | 677 /// loaded as well. |
658 Future<LibraryElement> loadDeserializedLibrary( | 678 Future<LibraryElement> loadDeserializedLibrary( |
659 LibraryDependencyHandler handler, LibraryElement library) { | 679 LibraryDependencyHandler handler, LibraryElement library) { |
660 libraryCanonicalUriMap[library.canonicalUri] = library; | 680 libraryCanonicalUriMap[library.canonicalUri] = library; |
661 handler.registerNewLibrary(library); | 681 handler.registerNewLibrary(library); |
662 return listener.onLibraryScanned(library, handler).then((_) { | 682 return Future.forEach(library.imports, (ImportElement import) { |
663 return Future.forEach(library.imports, (ImportElement import) { | 683 Uri resolvedUri = library.canonicalUri.resolveUri(import.uri); |
664 Uri resolvedUri = library.canonicalUri.resolveUri(import.uri); | 684 return createLibrary(handler, library, resolvedUri, library); |
685 }).then((_) { | |
686 return Future.forEach(library.exports, (ExportElement export) { | |
687 Uri resolvedUri = library.canonicalUri.resolveUri(export.uri); | |
665 return createLibrary(handler, library, resolvedUri, library); | 688 return createLibrary(handler, library, resolvedUri, library); |
666 }).then((_) { | 689 }).then((_) { |
667 return Future.forEach(library.exports, (ExportElement export) { | 690 // TODO(johnniwinther): Shouldn't there be an [ImportElement] for the |
668 Uri resolvedUri = library.canonicalUri.resolveUri(export.uri); | 691 // implicit import of dart:core? |
669 return createLibrary(handler, library, resolvedUri, library); | 692 return createLibrary(handler, library, Uris.dart_core, library); |
670 }).then((_) { | 693 }).then((_) => library); |
671 // TODO(johnniwinther): Shouldn't there be an [ImportElement] for the | |
672 // implicit import of dart:core? | |
673 return createLibrary(handler, library, Uris.dart_core, library); | |
674 }).then((_) => library); | |
675 }); | |
676 }); | 694 }); |
677 } | 695 } |
678 | 696 |
679 Future<Script> _readScript( | 697 Future<Script> _readScript( |
680 Spannable spannable, Uri readableUri, Uri resolvedUri) { | 698 Spannable spannable, Uri readableUri, Uri resolvedUri) { |
681 if (readableUri == null) { | 699 if (readableUri == null) { |
682 return new Future.value(new Script.synthetic(resolvedUri)); | 700 return new Future.value(new Script.synthetic(resolvedUri)); |
683 } else { | 701 } else { |
684 return scriptLoader.readScript(readableUri, spannable); | 702 return scriptLoader.readScript(readableUri, spannable); |
685 } | 703 } |
686 } | 704 } |
687 | 705 |
688 /** | 706 /** |
689 * Create (or reuse) a library element for the library specified by the | 707 * Create (or reuse) a library element for the library specified by the |
690 * [resolvedUri]. | 708 * [resolvedUri]. |
691 * | 709 * |
692 * If a new library is created, the [handler] is notified. | 710 * If a new library is created, the [handler] is notified. |
693 */ | 711 */ |
694 Future<LibraryElement> createLibrary(LibraryDependencyHandler handler, | 712 Future<LibraryElement> createLibrary(LibraryDependencyHandler handler, |
695 LibraryElement importingLibrary, Uri resolvedUri, Spannable spannable, | 713 LibraryElement importingLibrary, Uri resolvedUri, Spannable spannable, |
696 {bool skipFileWithPartOfTag: false}) { | 714 {bool skipFileWithPartOfTag: false}) async { |
697 Uri readableUri = | 715 Uri readableUri = |
698 uriTranslator.translate(importingLibrary, resolvedUri, spannable); | 716 uriTranslator.translate(importingLibrary, resolvedUri, spannable); |
699 LibraryElement library = libraryCanonicalUriMap[resolvedUri]; | 717 LibraryElement library = libraryCanonicalUriMap[resolvedUri]; |
700 if (library != null) { | 718 if (library != null) { |
701 return new Future.value(library); | 719 return new Future.value(library); |
702 } | 720 } |
703 return deserializer.readLibrary(resolvedUri).then((LibraryElement library) { | 721 library = await deserializer.readLibrary(resolvedUri); |
704 if (library != null) { | 722 if (library != null) { |
705 return loadDeserializedLibrary(handler, library); | 723 return loadDeserializedLibrary(handler, library); |
706 } | 724 } |
707 return reporter.withCurrentElement(importingLibrary, () { | 725 return reporter.withCurrentElement(importingLibrary, () { |
708 return _readScript(spannable, readableUri, resolvedUri) | 726 return _readScript(spannable, readableUri, resolvedUri) |
709 .then((Script script) { | 727 .then((Script script) async { |
710 if (script == null) return null; | 728 if (script == null) return null; |
711 LibraryElement element = | 729 LibraryElement element = |
712 createLibrarySync(handler, script, resolvedUri); | 730 createLibrarySync(handler, script, resolvedUri); |
713 CompilationUnitElementX compilationUnit = | 731 CompilationUnitElementX compilationUnit = element.entryCompilationUnit; |
714 element.entryCompilationUnit; | 732 if (compilationUnit.partTag != null) { |
715 if (compilationUnit.partTag != null) { | 733 if (skipFileWithPartOfTag) { |
716 if (skipFileWithPartOfTag) { | 734 // TODO(johnniwinther): Avoid calling |
717 // TODO(johnniwinther): Avoid calling [listener.onLibraryCreated] | 735 // [compiler.processLoadedLibraries] with this library. |
718 // for this library. | 736 libraryCanonicalUriMap.remove(resolvedUri); |
719 libraryCanonicalUriMap.remove(resolvedUri); | 737 return null; |
720 return null; | |
721 } | |
722 if (importingLibrary == null) { | |
723 DiagnosticMessage error = reporter.withCurrentElement( | |
724 compilationUnit, | |
725 () => reporter.createMessage( | |
726 compilationUnit.partTag, MessageKind.MAIN_HAS_PART_OF)); | |
727 reporter.reportError(error); | |
728 } else { | |
729 DiagnosticMessage error = reporter.withCurrentElement( | |
730 compilationUnit, | |
731 () => reporter.createMessage( | |
732 compilationUnit.partTag, MessageKind.IMPORT_PART_OF)); | |
733 DiagnosticMessage info = reporter.withCurrentElement( | |
734 importingLibrary, | |
735 () => reporter.createMessage( | |
736 spannable, MessageKind.IMPORT_PART_OF_HERE)); | |
737 reporter.reportError(error, [info]); | |
738 } | |
739 } | 738 } |
740 return processLibraryTags(handler, element).then((_) { | 739 if (importingLibrary == null) { |
741 reporter.withCurrentElement(element, () { | 740 DiagnosticMessage error = reporter.withCurrentElement( |
742 handler.registerLibraryExports(element); | 741 compilationUnit, |
743 }); | 742 () => reporter.createMessage( |
744 return element; | 743 compilationUnit.partTag, MessageKind.MAIN_HAS_PART_OF)); |
745 }); | 744 reporter.reportError(error); |
745 } else { | |
746 DiagnosticMessage error = reporter.withCurrentElement( | |
747 compilationUnit, | |
748 () => reporter.createMessage( | |
749 compilationUnit.partTag, MessageKind.IMPORT_PART_OF)); | |
750 DiagnosticMessage info = reporter.withCurrentElement( | |
751 importingLibrary, | |
752 () => reporter.createMessage( | |
753 spannable, MessageKind.IMPORT_PART_OF_HERE)); | |
754 reporter.reportError(error, [info]); | |
755 } | |
756 } | |
757 await processLibraryTags(handler, element); | |
758 reporter.withCurrentElement(element, () { | |
759 handler.registerLibraryExports(element); | |
746 }); | 760 }); |
761 | |
762 if (element.isPlatformLibrary && | |
Siggi Cherem (dart-lang)
2017/03/24 17:40:28
so nice to see patching done while loading, yay!
Emily Fortuna
2017/03/24 18:30:20
done! I aaaaaalmost did that in my cleanup process
| |
763 // Don't patch library currently disallowed. | |
764 !element.isSynthesized && | |
765 !element.isPatched && | |
766 // Don't patch deserialized libraries. | |
767 !deserializer.isDeserialized(element)) { | |
768 // Apply patch, if any. | |
769 Uri patchUri = _patchResolverFunc(element.canonicalUri.path); | |
770 if (patchUri != null) { | |
771 await _patchParserTask.patchLibrary(handler, patchUri, element); | |
772 } | |
773 } | |
774 return element; | |
747 }); | 775 }); |
748 }); | 776 }); |
749 } | 777 } |
750 | 778 |
751 LibraryElement createLibrarySync( | 779 LibraryElement createLibrarySync( |
752 LibraryDependencyHandler handler, Script script, Uri resolvedUri) { | 780 LibraryDependencyHandler handler, Script script, Uri resolvedUri) { |
753 LibraryElement element = new LibraryElementX(script, resolvedUri); | 781 LibraryElement element = new LibraryElementX(script, resolvedUri); |
754 return reporter.withCurrentElement(element, () { | 782 return reporter.withCurrentElement(element, () { |
755 if (handler != null) { | 783 if (handler != null) { |
756 handler.registerNewLibrary(element); | 784 handler.registerNewLibrary(element); |
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1323 assert(invariant(library, importingNode != null, | 1351 assert(invariant(library, importingNode != null, |
1324 message: "$library has not been registered")); | 1352 message: "$library has not been registered")); |
1325 importingNode.registerImportDependency(libraryDependency, loadedLibrary); | 1353 importingNode.registerImportDependency(libraryDependency, loadedLibrary); |
1326 } | 1354 } |
1327 } | 1355 } |
1328 | 1356 |
1329 /** | 1357 /** |
1330 * Registers [library] for the processing of its import/export scope. | 1358 * Registers [library] for the processing of its import/export scope. |
1331 */ | 1359 */ |
1332 void registerNewLibrary(LibraryElement library) { | 1360 void registerNewLibrary(LibraryElement library) { |
1333 task.listener.onLibraryCreated(library); | |
1334 _newLibraries.add(library); | 1361 _newLibraries.add(library); |
1335 if (!library.exportsHandled) { | 1362 if (!library.exportsHandled) { |
1336 nodeMap[library] = new LibraryDependencyNode(library); | 1363 nodeMap[library] = new LibraryDependencyNode(library); |
1337 } | 1364 } |
1338 } | 1365 } |
1339 | 1366 |
1340 /** | 1367 /** |
1341 * Registers all top-level entities of [library] as starting point for the | 1368 * Registers all top-level entities of [library] as starting point for the |
1342 * fixed-point computation of the import/export scopes. | 1369 * fixed-point computation of the import/export scopes. |
1343 */ | 1370 */ |
1344 void registerLibraryExports(LibraryElement library) { | 1371 void registerLibraryExports(LibraryElement library) { |
1345 nodeMap[library].registerInitialExports(); | 1372 nodeMap[library].registerInitialExports(); |
1346 } | 1373 } |
1347 | 1374 |
1348 Future processLibraryTags(LibraryElement library) { | 1375 Future processLibraryTags(LibraryElement library) { |
1349 return task.processLibraryTags(this, library); | 1376 return task.processLibraryTags(this, library); |
1350 } | 1377 } |
1351 } | 1378 } |
1352 | 1379 |
1353 /// Information on the bulk of newly loaded libraries through a call to | 1380 /// Information on the set libraries loaded as a result of a call to |
1354 /// [LibraryLoader.loadLibrary]. | 1381 /// [LibraryLoader.loadLibrary]. |
1355 abstract class LoadedLibraries { | 1382 abstract class LoadedLibraries { |
1356 /// The uri passed to [LibraryLoader.loadLibrary]. | 1383 /// The accesss the library object created corresponding to the library |
1357 Uri get rootUri; | 1384 /// passed to [LibraryLoader.loadLibrary]. |
1385 LibraryElement get rootLibrary; | |
1358 | 1386 |
1359 /// Returns `true` if a library with canonical [uri] was loaded in this bulk. | 1387 /// Returns `true` if a library with canonical [uri] was loaded in this bulk. |
1360 bool containsLibrary(Uri uri); | 1388 bool containsLibrary(Uri uri); |
1361 | 1389 |
1362 /// Returns the library with canonical [uri] that was loaded in this bulk. | 1390 /// Returns the library with canonical [uri] that was loaded in this bulk. |
1363 LibraryElement getLibrary(Uri uri); | 1391 LibraryElement getLibrary(Uri uri); |
1364 | 1392 |
1365 /// Applies all libraries in this bulk to [f]. | 1393 /// Applies all libraries in this bulk to [f]. |
1366 void forEachLibrary(f(LibraryElement library)); | 1394 void forEachLibrary(f(LibraryElement library)); |
1367 | 1395 |
1368 /// Applies all imports chains of [uri] in this bulk to [callback]. | 1396 /// Applies all imports chains of [uri] in this bulk to [callback]. |
1369 /// | 1397 /// |
1370 /// The argument [importChainReversed] to [callback] contains the chain of | 1398 /// The argument [importChainReversed] to [callback] contains the chain of |
1371 /// imports uris that lead to importing [uri] starting in [uri] and ending in | 1399 /// imports uris that lead to importing [uri] starting in [uri] and ending in |
1372 /// [rootUri]. | 1400 /// the uri that was passed in with [loadLibrary]. |
1373 /// | 1401 /// |
1374 /// [callback] is called once for each chain of imports leading to [uri] until | 1402 /// [callback] is called once for each chain of imports leading to [uri] until |
1375 /// [callback] returns `false`. | 1403 /// [callback] returns `false`. |
1376 void forEachImportChain(Uri uri, | 1404 void forEachImportChain(Uri uri, |
1377 {bool callback(Link<Uri> importChainReversed)}); | 1405 {bool callback(Link<Uri> importChainReversed)}); |
1378 } | 1406 } |
1379 | 1407 |
1380 class _LoadedLibraries implements LoadedLibraries { | 1408 class _LoadedLibraries implements LoadedLibraries { |
1381 final _LibraryLoaderTask task; | 1409 final _LibraryLoaderTask task; |
1382 final LibraryElement rootLibrary; | 1410 final LibraryElement rootLibrary; |
1383 final Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{}; | 1411 final Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{}; |
1384 final Map<LibraryElement, LibraryDependencyNode> nodeMap; | 1412 final List<LibraryElement> _newLibraries; |
1385 | 1413 |
1386 _LoadedLibraries(this.rootLibrary, Iterable<LibraryElement> libraries, | 1414 _LoadedLibraries(this.rootLibrary, this._newLibraries, this.task) { |
1387 this.nodeMap, this.task) { | 1415 _newLibraries.forEach((LibraryElement loadedLibrary) { |
1388 libraries.forEach((LibraryElement loadedLibrary) { | |
1389 loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary; | 1416 loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary; |
1390 }); | 1417 }); |
1391 } | 1418 } |
1392 | 1419 |
1393 Uri get rootUri => rootLibrary.canonicalUri; | |
1394 | |
1395 bool containsLibrary(Uri uri) => loadedLibraries.containsKey(uri); | 1420 bool containsLibrary(Uri uri) => loadedLibraries.containsKey(uri); |
1396 | 1421 |
1397 LibraryElement getLibrary(Uri uri) => loadedLibraries[uri]; | 1422 LibraryElement getLibrary(Uri uri) => loadedLibraries[uri]; |
1398 | 1423 |
1399 void forEachLibrary(f(LibraryElement library)) => nodeMap.keys.forEach(f); | 1424 void forEachLibrary(f(LibraryElement library)) => _newLibraries.forEach(f); |
1400 | 1425 |
1401 void forEachImportChain(Uri targetUri, | 1426 void forEachImportChain(Uri targetUri, |
1402 {bool callback(Link<Uri> importChainReversed)}) { | 1427 {bool callback(Link<Uri> importChainReversed)}) { |
1403 bool aborted = false; | 1428 bool aborted = false; |
1404 | 1429 |
1405 /// Map from libraries to the set of (unreversed) paths to [uri]. | 1430 /// Map from libraries to the set of (unreversed) paths to [uri]. |
1406 Map<LibraryElement, Iterable<Link<Uri>>> suffixChainMap = | 1431 Map<LibraryElement, Iterable<Link<Uri>>> suffixChainMap = |
1407 <LibraryElement, Iterable<Link<Uri>>>{}; | 1432 <LibraryElement, Iterable<Link<Uri>>>{}; |
1408 | 1433 |
1409 /// Computes the set of (unreversed) paths to [targetUri]. | 1434 /// Computes the set of (unreversed) paths to [targetUri]. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1468 } | 1493 } |
1469 suffixes.add(const Link<Uri>().prepend(canonicalUri)); | 1494 suffixes.add(const Link<Uri>().prepend(canonicalUri)); |
1470 } | 1495 } |
1471 suffixChainMap[library] = suffixes; | 1496 suffixChainMap[library] = suffixes; |
1472 return; | 1497 return; |
1473 } | 1498 } |
1474 | 1499 |
1475 computeSuffixes(rootLibrary, const Link<Uri>()); | 1500 computeSuffixes(rootLibrary, const Link<Uri>()); |
1476 } | 1501 } |
1477 | 1502 |
1478 String toString() => 'root=$rootLibrary,libraries=${loadedLibraries.keys}'; | 1503 String toString() => 'root=$rootLibrary,libraries=${_newLibraries}'; |
1479 } | 1504 } |
1480 | 1505 |
1481 // TODO(sigmund): remove ScriptLoader & ElementScanner. Such abstraction seems | 1506 // TODO(sigmund): remove ScriptLoader & ElementScanner. Such abstraction seems |
1482 // rather low-level. It might be more practical to split the library-loading | 1507 // rather low-level. It might be more practical to split the library-loading |
1483 // task itself. The task would continue to do the work of recursively loading | 1508 // task itself. The task would continue to do the work of recursively loading |
1484 // dependencies, but it can delegate to a set of subloaders how to do the actual | 1509 // dependencies, but it can delegate to a set of subloaders how to do the actual |
1485 // loading. We would then have a list of subloaders that use different | 1510 // loading. We would then have a list of subloaders that use different |
1486 // implementations: in-memory cache, deserialization, scanning from files. | 1511 // implementations: in-memory cache, deserialization, scanning from files. |
1487 // | 1512 // |
1488 // For example, the API might look like this: | 1513 // For example, the API might look like this: |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1521 /// Load script from a readable [uri], report any errors using the location of | 1546 /// Load script from a readable [uri], report any errors using the location of |
1522 /// the given [spannable]. | 1547 /// the given [spannable]. |
1523 Future<Script> readScript(Uri uri, [Spannable spannable]); | 1548 Future<Script> readScript(Uri uri, [Spannable spannable]); |
1524 } | 1549 } |
1525 | 1550 |
1526 /// API used by the library loader to synchronously scan a library or | 1551 /// API used by the library loader to synchronously scan a library or |
1527 /// compilation unit and ensure that their library tags are computed. | 1552 /// compilation unit and ensure that their library tags are computed. |
1528 abstract class ElementScanner { | 1553 abstract class ElementScanner { |
1529 void scanLibrary(LibraryElement library); | 1554 void scanLibrary(LibraryElement library); |
1530 void scanUnit(CompilationUnitElement unit); | 1555 void scanUnit(CompilationUnitElement unit); |
1531 } | 1556 Token scanFile(SourceFile file); |
Siggi Cherem (dart-lang)
2017/03/24 17:40:27
looks like you don't need scanFile after all? coul
Emily Fortuna
2017/03/24 18:30:20
yes thanks.
| |
1532 | |
1533 /// TODO(sigmund): remove this abstraction. Ideally the loader can produce the | |
1534 /// LoadedLibraries results once, and the compiler and choose what to do with | |
1535 /// it instead. | |
1536 abstract class LibraryLoaderListener { | |
1537 /// Called after a request to load a library. The [results] will include all | |
1538 /// transitive libraries loaded as a result of the initial request. | |
1539 Future onLibrariesLoaded(LoadedLibraries results); | |
1540 | |
1541 /// Called whenever a library element is created. | |
1542 void onLibraryCreated(LibraryElement library); | |
1543 | |
1544 /// Called whenever a library is scanned from a script file. | |
1545 Future onLibraryScanned(LibraryElement library, LibraryLoader loader); | |
1546 } | 1557 } |
1547 | 1558 |
1548 const _reuseLibrarySubtaskName = "Reuse library"; | 1559 const _reuseLibrarySubtaskName = "Reuse library"; |
OLD | NEW |