Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Unified Diff: pkg/compiler/lib/src/library_loader.dart

Issue 2760923004: Eliminate multi-callback structure for LibraryLoader. (Closed)
Patch Set: . Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/library_loader.dart
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/library_loader.dart
index 8865f1e6e28183e1a0f9e7178fa11c0e90e11908..c4c76e43ca8d5fdc47071b92a7be1579ca420983 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -29,15 +29,21 @@ import 'elements/modelx.dart'
SyntheticImportElement;
import 'enqueue.dart' show DeferredAction;
import 'environment.dart';
+import 'io/source_file.dart' show SourceFile;
+import 'patch_parser.dart' show PatchParserTask;
import 'resolved_uri_translator.dart';
import 'script.dart';
import 'serialization/serialization.dart' show LibraryDeserializer;
import 'tree/tree.dart';
import 'util/util.dart' show Link, LinkBuilder;
+import 'package:front_end/src/fasta/scanner.dart' show Token;
+
typedef Future<Iterable<LibraryElement>> ReuseLibrariesFunction(
Iterable<LibraryElement> libraries);
+typedef Uri PatchResolverFunction(String dartLibraryPath);
+
/**
* [CompilerTask] for loading libraries and setting up the import/export scopes.
*
@@ -138,7 +144,8 @@ abstract class LibraryLoaderTask implements LibraryProvider, CompilerTask {
ScriptLoader scriptLoader,
ElementScanner scriptScanner,
LibraryDeserializer deserializer,
- LibraryLoaderListener listener,
+ PatchResolverFunction patchResolverFunc,
+ PatchParserTask patchParser,
Environment environment,
DiagnosticReporter reporter,
Measurer measurer) = _LibraryLoaderTask;
@@ -146,8 +153,10 @@ abstract class LibraryLoaderTask implements LibraryProvider, CompilerTask {
/// Returns all libraries that have been loaded.
Iterable<LibraryElement> get libraries;
- /// Loads the library specified by the [resolvedUri] and returns its
- /// [LibraryElement].
+ /// Loads the library specified by the [resolvedUri] and returns the
+ /// [LoadedLibraries] that were loaded to load the specified uri. The
+ /// [LibraryElement] itself can be found by calling
+ /// `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.
///
/// If the library is not already loaded, the method creates the
/// [LibraryElement] for the library and computes the import/export scope,
@@ -157,7 +166,7 @@ abstract class LibraryLoaderTask implements LibraryProvider, CompilerTask {
/// If [skipFileWithPartOfTag] is `true`, `null` is returned if the
/// compilation unit for [resolvedUri] contains a `part of` tag. This is only
/// used for analysis through [Compiler.analyzeUri].
- Future<LibraryElement> loadLibrary(Uri resolvedUri,
+ Future<LoadedLibraries> loadLibrary(Uri resolvedUri,
{bool skipFileWithPartOfTag: false});
/// Reset the library loader task to prepare for compilation. If provided,
@@ -180,6 +189,31 @@ abstract class LibraryLoaderTask implements LibraryProvider, CompilerTask {
/// Returns the deferred actions registered since the last call to
/// [pullDeferredActions].
Iterable<DeferredAction> pullDeferredActions();
+
+ /// The locations of js patch-files relative to the sdk-descriptors.
+ static const _patchLocations = const <String, String>{
+ "async": "_internal/js_runtime/lib/async_patch.dart",
+ "collection": "_internal/js_runtime/lib/collection_patch.dart",
+ "convert": "_internal/js_runtime/lib/convert_patch.dart",
+ "core": "_internal/js_runtime/lib/core_patch.dart",
+ "developer": "_internal/js_runtime/lib/developer_patch.dart",
+ "io": "_internal/js_runtime/lib/io_patch.dart",
+ "isolate": "_internal/js_runtime/lib/isolate_patch.dart",
+ "math": "_internal/js_runtime/lib/math_patch.dart",
+ "mirrors": "_internal/js_runtime/lib/mirrors_patch.dart",
+ "typed_data": "_internal/js_runtime/lib/typed_data_patch.dart",
+ "_internal": "_internal/js_runtime/lib/internal_patch.dart"
+ };
+
+ /// Returns the location of the patch-file associated with [libraryName]
+ /// resolved from [plaformConfigUri].
+ ///
+ /// Returns null if there is none.
+ static Uri resolvePatchUri(String libraryName, Uri platformConfigUri) {
+ String patchLocation = _patchLocations[libraryName];
+ if (patchLocation == null) return null;
+ return platformConfigUri.resolve(patchLocation);
+ }
}
/// Interface for an entity that provide libraries. For instance from normal
@@ -303,14 +337,19 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
/// from a serialized form.
final LibraryDeserializer deserializer;
- /// Hooks to inform others about progress done by this loader.
- // TODO(sigmund): move away from this.
- final LibraryLoaderListener listener;
-
/// Definitions provided via the `-D` command line flags. Used to resolve
/// conditional imports.
final Environment environment;
+ // TODO(efortuna): Don't pass PatchParserTask here.
+ final PatchParserTask _patchParserTask;
+
+ /// Function that accepts the string name of a library and returns the
+ /// path to the corresponding patch file. This is a function that is passed in
+ /// because our test mock_compiler subclasses compiler.
+ // 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!
+ final PatchResolverFunction _patchResolverFunc;
+
List<DeferredAction> _deferredActions = <DeferredAction>[];
final DiagnosticReporter reporter;
@@ -320,7 +359,8 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
this.scriptLoader,
this.scanner,
this.deserializer,
- this.listener,
+ this._patchResolverFunc,
+ this._patchParserTask,
this.environment,
this.reporter,
Measurer measurer)
@@ -335,8 +375,6 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
final Map<String, LibraryElement> libraryNames =
new Map<String, LibraryElement>();
- LibraryDependencyHandler currentHandler;
-
Iterable<LibraryElement> get libraries => libraryCanonicalUriMap.values;
LibraryElement lookupLibrary(Uri canonicalUri) {
@@ -345,8 +383,6 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
void reset({bool reuseLibrary(LibraryElement library)}) {
measure(() {
- assert(currentHandler == null);
-
Iterable<LibraryElement> reusedLibraries = null;
if (reuseLibrary != null) {
reusedLibraries = measureSubtask(_reuseLibrarySubtaskName, () {
@@ -373,8 +409,6 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)) {
return measure(() {
- assert(currentHandler == null);
-
Future<LibraryElement> wrapper(LibraryElement library) {
try {
return reuseLibrary(library)
@@ -401,7 +435,6 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
Future<Null> resetLibraries(
Future<Iterable<LibraryElement>> reuseLibraries(
Iterable<LibraryElement> libraries)) {
- assert(currentHandler == null);
return measureSubtask(_reuseLibrarySubtaskName, () {
return new Future<Iterable<LibraryElement>>(() {
// Wrap in Future to shield against errors in user code.
@@ -431,31 +464,20 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
}
}
- Future<LibraryElement> loadLibrary(Uri resolvedUri,
- {bool skipFileWithPartOfTag: false}) {
- return measure(() {
- assert(currentHandler == null);
- // TODO(johnniwinther): Ensure that currentHandler correctly encloses the
- // loading of a library cluster.
- currentHandler = new LibraryDependencyHandler(this);
- return createLibrary(
- currentHandler, null, resolvedUri, NO_LOCATION_SPANNABLE,
- skipFileWithPartOfTag: skipFileWithPartOfTag)
- .then((LibraryElement library) {
- if (library == null) {
- currentHandler = null;
- return null;
- }
- return reporter.withCurrentElement(library, () {
- return measure(() {
- currentHandler.computeExports();
- LoadedLibraries loadedLibraries = new _LoadedLibraries(library,
- currentHandler.newLibraries, currentHandler.nodeMap, this);
- currentHandler = null;
- return listener
- .onLibrariesLoaded(loadedLibraries)
- .then((_) => library);
- });
+ Future<LoadedLibraries> loadLibrary(Uri resolvedUri,
+ {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.
+ return measure(() async {
+ 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.
+ LibraryElement library = await createLibrary(
+ loader, null, resolvedUri, NO_LOCATION_SPANNABLE,
+ skipFileWithPartOfTag: skipFileWithPartOfTag);
+ 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.
+ return null;
+ }
+ return reporter.withCurrentElement(library, () {
+ return measure(() {
+ loader.computeExports();
+ return new _LoadedLibraries(library, loader.newLibraries, this);
});
});
});
@@ -548,8 +570,6 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
}
});
}).then((_) {
- return listener.onLibraryScanned(library, handler);
Siggi Cherem (dart-lang) 2017/03/24 17:40:27 woo hoo!
- }).then((_) {
return reporter.withCurrentElement(library, () {
checkDuplicatedLibraryName(library);
@@ -659,20 +679,18 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
LibraryDependencyHandler handler, LibraryElement library) {
libraryCanonicalUriMap[library.canonicalUri] = library;
handler.registerNewLibrary(library);
- return listener.onLibraryScanned(library, handler).then((_) {
- return Future.forEach(library.imports, (ImportElement import) {
- Uri resolvedUri = library.canonicalUri.resolveUri(import.uri);
+ return Future.forEach(library.imports, (ImportElement import) {
+ Uri resolvedUri = library.canonicalUri.resolveUri(import.uri);
+ return createLibrary(handler, library, resolvedUri, library);
+ }).then((_) {
+ return Future.forEach(library.exports, (ExportElement export) {
+ Uri resolvedUri = library.canonicalUri.resolveUri(export.uri);
return createLibrary(handler, library, resolvedUri, library);
}).then((_) {
- return Future.forEach(library.exports, (ExportElement export) {
- Uri resolvedUri = library.canonicalUri.resolveUri(export.uri);
- return createLibrary(handler, library, resolvedUri, library);
- }).then((_) {
- // TODO(johnniwinther): Shouldn't there be an [ImportElement] for the
- // implicit import of dart:core?
- return createLibrary(handler, library, Uris.dart_core, library);
- }).then((_) => library);
- });
+ // TODO(johnniwinther): Shouldn't there be an [ImportElement] for the
+ // implicit import of dart:core?
+ return createLibrary(handler, library, Uris.dart_core, library);
+ }).then((_) => library);
});
}
@@ -693,57 +711,67 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
*/
Future<LibraryElement> createLibrary(LibraryDependencyHandler handler,
LibraryElement importingLibrary, Uri resolvedUri, Spannable spannable,
- {bool skipFileWithPartOfTag: false}) {
+ {bool skipFileWithPartOfTag: false}) async {
Uri readableUri =
uriTranslator.translate(importingLibrary, resolvedUri, spannable);
LibraryElement library = libraryCanonicalUriMap[resolvedUri];
if (library != null) {
return new Future.value(library);
}
- return deserializer.readLibrary(resolvedUri).then((LibraryElement library) {
- if (library != null) {
- return loadDeserializedLibrary(handler, library);
- }
- return reporter.withCurrentElement(importingLibrary, () {
- return _readScript(spannable, readableUri, resolvedUri)
- .then((Script script) {
- if (script == null) return null;
- LibraryElement element =
- createLibrarySync(handler, script, resolvedUri);
- CompilationUnitElementX compilationUnit =
- element.entryCompilationUnit;
- if (compilationUnit.partTag != null) {
- if (skipFileWithPartOfTag) {
- // TODO(johnniwinther): Avoid calling [listener.onLibraryCreated]
- // for this library.
- libraryCanonicalUriMap.remove(resolvedUri);
- return null;
- }
- if (importingLibrary == null) {
- DiagnosticMessage error = reporter.withCurrentElement(
- compilationUnit,
- () => reporter.createMessage(
- compilationUnit.partTag, MessageKind.MAIN_HAS_PART_OF));
- reporter.reportError(error);
- } else {
- DiagnosticMessage error = reporter.withCurrentElement(
- compilationUnit,
- () => reporter.createMessage(
- compilationUnit.partTag, MessageKind.IMPORT_PART_OF));
- DiagnosticMessage info = reporter.withCurrentElement(
- importingLibrary,
- () => reporter.createMessage(
- spannable, MessageKind.IMPORT_PART_OF_HERE));
- reporter.reportError(error, [info]);
- }
+ library = await deserializer.readLibrary(resolvedUri);
+ if (library != null) {
+ return loadDeserializedLibrary(handler, library);
+ }
+ return reporter.withCurrentElement(importingLibrary, () {
+ return _readScript(spannable, readableUri, resolvedUri)
+ .then((Script script) async {
+ if (script == null) return null;
+ LibraryElement element =
+ createLibrarySync(handler, script, resolvedUri);
+ CompilationUnitElementX compilationUnit = element.entryCompilationUnit;
+ if (compilationUnit.partTag != null) {
+ if (skipFileWithPartOfTag) {
+ // TODO(johnniwinther): Avoid calling
+ // [compiler.processLoadedLibraries] with this library.
+ libraryCanonicalUriMap.remove(resolvedUri);
+ return null;
}
- return processLibraryTags(handler, element).then((_) {
- reporter.withCurrentElement(element, () {
- handler.registerLibraryExports(element);
- });
- return element;
- });
+ if (importingLibrary == null) {
+ DiagnosticMessage error = reporter.withCurrentElement(
+ compilationUnit,
+ () => reporter.createMessage(
+ compilationUnit.partTag, MessageKind.MAIN_HAS_PART_OF));
+ reporter.reportError(error);
+ } else {
+ DiagnosticMessage error = reporter.withCurrentElement(
+ compilationUnit,
+ () => reporter.createMessage(
+ compilationUnit.partTag, MessageKind.IMPORT_PART_OF));
+ DiagnosticMessage info = reporter.withCurrentElement(
+ importingLibrary,
+ () => reporter.createMessage(
+ spannable, MessageKind.IMPORT_PART_OF_HERE));
+ reporter.reportError(error, [info]);
+ }
+ }
+ await processLibraryTags(handler, element);
+ reporter.withCurrentElement(element, () {
+ handler.registerLibraryExports(element);
});
+
+ 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
+ // Don't patch library currently disallowed.
+ !element.isSynthesized &&
+ !element.isPatched &&
+ // Don't patch deserialized libraries.
+ !deserializer.isDeserialized(element)) {
+ // Apply patch, if any.
+ Uri patchUri = _patchResolverFunc(element.canonicalUri.path);
+ if (patchUri != null) {
+ await _patchParserTask.patchLibrary(handler, patchUri, element);
+ }
+ }
+ return element;
});
});
}
@@ -1330,7 +1358,6 @@ class LibraryDependencyHandler implements LibraryLoader {
* Registers [library] for the processing of its import/export scope.
*/
void registerNewLibrary(LibraryElement library) {
- task.listener.onLibraryCreated(library);
_newLibraries.add(library);
if (!library.exportsHandled) {
nodeMap[library] = new LibraryDependencyNode(library);
@@ -1350,11 +1377,12 @@ class LibraryDependencyHandler implements LibraryLoader {
}
}
-/// Information on the bulk of newly loaded libraries through a call to
+/// Information on the set libraries loaded as a result of a call to
/// [LibraryLoader.loadLibrary].
abstract class LoadedLibraries {
- /// The uri passed to [LibraryLoader.loadLibrary].
- Uri get rootUri;
+ /// The accesss the library object created corresponding to the library
+ /// passed to [LibraryLoader.loadLibrary].
+ LibraryElement get rootLibrary;
/// Returns `true` if a library with canonical [uri] was loaded in this bulk.
bool containsLibrary(Uri uri);
@@ -1369,7 +1397,7 @@ abstract class LoadedLibraries {
///
/// The argument [importChainReversed] to [callback] contains the chain of
/// imports uris that lead to importing [uri] starting in [uri] and ending in
- /// [rootUri].
+ /// the uri that was passed in with [loadLibrary].
///
/// [callback] is called once for each chain of imports leading to [uri] until
/// [callback] returns `false`.
@@ -1381,22 +1409,19 @@ class _LoadedLibraries implements LoadedLibraries {
final _LibraryLoaderTask task;
final LibraryElement rootLibrary;
final Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{};
- final Map<LibraryElement, LibraryDependencyNode> nodeMap;
+ final List<LibraryElement> _newLibraries;
- _LoadedLibraries(this.rootLibrary, Iterable<LibraryElement> libraries,
- this.nodeMap, this.task) {
- libraries.forEach((LibraryElement loadedLibrary) {
+ _LoadedLibraries(this.rootLibrary, this._newLibraries, this.task) {
+ _newLibraries.forEach((LibraryElement loadedLibrary) {
loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary;
});
}
- Uri get rootUri => rootLibrary.canonicalUri;
-
bool containsLibrary(Uri uri) => loadedLibraries.containsKey(uri);
LibraryElement getLibrary(Uri uri) => loadedLibraries[uri];
- void forEachLibrary(f(LibraryElement library)) => nodeMap.keys.forEach(f);
+ void forEachLibrary(f(LibraryElement library)) => _newLibraries.forEach(f);
void forEachImportChain(Uri targetUri,
{bool callback(Link<Uri> importChainReversed)}) {
@@ -1475,7 +1500,7 @@ class _LoadedLibraries implements LoadedLibraries {
computeSuffixes(rootLibrary, const Link<Uri>());
}
- String toString() => 'root=$rootLibrary,libraries=${loadedLibraries.keys}';
+ String toString() => 'root=$rootLibrary,libraries=${_newLibraries}';
}
// TODO(sigmund): remove ScriptLoader & ElementScanner. Such abstraction seems
@@ -1528,21 +1553,7 @@ abstract class ScriptLoader {
abstract class ElementScanner {
void scanLibrary(LibraryElement library);
void scanUnit(CompilationUnitElement unit);
-}
-
-/// TODO(sigmund): remove this abstraction. Ideally the loader can produce the
-/// LoadedLibraries results once, and the compiler and choose what to do with
-/// it instead.
-abstract class LibraryLoaderListener {
- /// Called after a request to load a library. The [results] will include all
- /// transitive libraries loaded as a result of the initial request.
- Future onLibrariesLoaded(LoadedLibraries results);
-
- /// Called whenever a library element is created.
- void onLibraryCreated(LibraryElement library);
-
- /// Called whenever a library is scanned from a script file.
- Future onLibraryScanned(LibraryElement library, LibraryLoader loader);
+ 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.
}
const _reuseLibrarySubtaskName = "Reuse library";

Powered by Google App Engine
This is Rietveld 408576698