Index: runtime/bin/builtin.dart |
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart |
index dc374f609a8769e7dd61b39ef6180a333d6f8c42..f162bcb2c8ec44cbfc60cbcbf1dc1c54d1a9655a 100644 |
--- a/runtime/bin/builtin.dart |
+++ b/runtime/bin/builtin.dart |
@@ -89,12 +89,19 @@ Uri _rootScript; |
// Packages are either resolved looking up in a map or resolved from within a |
// package root. |
-bool _packagesReady() => (_packageRoot != null) || (_packageMap != null); |
+bool get _packagesReady => |
+ (_packageRoot != null) || (_packageMap != null) || (_packageError != null); |
+// Error string set if there was an error resolving package configuration. |
+// For example not finding a .packages file or packages/ directory, malformed |
+// .packages file or any other related error. |
+String _packageError = null; |
// The directory to look in to resolve "package:" scheme URIs. By detault it is |
// the 'packages' directory right next to the script. |
Uri _packageRoot = null; // Used to be _rootScript.resolve('packages/'); |
// The map describing how certain package names are mapped to Uris. |
+Uri _packageConfig = null; |
Map<String, Uri> _packageMap = null; |
+ |
// A list of pending packags which have been requested while resolving the |
// location of the package root or the contents of the package map. |
List<_LoadRequest> _pendingPackageLoads = []; |
@@ -109,8 +116,9 @@ bool _pendingLoads() => !_reqMap.isEmpty || !_pendingPackageLoads.isEmpty; |
bool _isWindows = false; |
// Logging from builtin.dart is prefixed with a '*'. |
+String _logId = (Isolate.current.hashCode % 0x100000).toRadixString(16); |
_log(msg) { |
- _print("* $msg"); |
+ _print("* $_logId $msg"); |
} |
// A class wrapping the load error message in an Error object. |
@@ -235,8 +243,10 @@ _setPackageRoot(String packageRoot) { |
_packageRoot = _workingDirectory.resolveUri(new Uri.file(packageRoot)); |
} |
// Now that we have determined the packageRoot value being used, set it |
- // up for use in Platform.packageRoot. |
- VMLibraryHooks.packageRoot = _packageRoot.toString(); |
+ // up for use in Platform.packageRoot. This is only set when the embedder |
+ // sets up the package root. Automatically discovered package root will |
+ // not update the VMLibraryHooks value. |
+ VMLibraryHooks.packageRootString = _packageRoot.toString(); |
if (_traceLoading) { |
_log('Package root URI: $_packageRoot'); |
} |
@@ -246,6 +256,9 @@ _setPackageRoot(String packageRoot) { |
// Given a uri with a 'package' scheme, return a Uri that is prefixed with |
// the package root. |
Uri _resolvePackageUri(Uri uri) { |
+ assert(uri.scheme == "package"); |
+ assert(_packagesReady); |
+ |
if (!uri.host.isEmpty) { |
var path = '${uri.host}${uri.path}'; |
var right = 'package:$path'; |
@@ -259,7 +272,12 @@ Uri _resolvePackageUri(Uri uri) { |
_log('Resolving package with uri path: ${uri.path}'); |
} |
var resolvedUri; |
- if (_packageRoot != null) { |
+ if (_packageError != null) { |
+ if (_traceLoading) { |
+ _log("Resolving package with pending resolution error: $_packageError"); |
+ } |
+ throw _packageError; |
+ } else if (_packageRoot != null) { |
resolvedUri = _packageRoot.resolve(uri.path); |
} else { |
var packageName = uri.pathSegments[0]; |
@@ -408,22 +426,33 @@ void _handlePackagesReply(msg) { |
if (_traceLoading) { |
_log("Got failure response on package port: '$msg'"); |
} |
- throw msg; |
- } |
- if (msg.length == 1) { |
- if (_traceLoading) { |
- _log("Received package root: '${msg[0]}'"); |
+ // Remember the error message. |
+ _packageError = msg; |
+ } else if (msg is List) { |
+ if (msg.length == 1) { |
+ if (_traceLoading) { |
+ _log("Received package root: '${msg[0]}'"); |
+ } |
+ _packageRoot = Uri.parse(msg[0]); |
+ } else { |
+ // First entry contains the location of the loaded .packages file. |
+ assert((msg.length % 2) == 0); |
+ assert(msg.length >= 2); |
+ assert(msg[1] == null); |
+ _packageConfig = Uri.parse(msg[0]); |
+ _packageMap = new Map<String, Uri>(); |
+ for (var i = 2; i < msg.length; i+=2) { |
+ // TODO(iposva): Complain about duplicate entries. |
+ _packageMap[msg[i]] = Uri.parse(msg[i+1]); |
+ } |
+ if (_traceLoading) { |
+ _log("Setup package map: $_packageMap"); |
+ } |
} |
- _packageRoot = Uri.parse(msg[0]); |
} else { |
- assert((msg.length % 2) == 0); |
- _packageMap = new Map<String, Uri>(); |
- for (var i = 0; i < msg.length; i+=2) { |
- // TODO(iposva): Complain about duplicate entries. |
- _packageMap[msg[i]] = Uri.parse(msg[i+1]); |
- } |
+ _packageError = "Bad type of packages reply: ${msg.runtimeType}"; |
if (_traceLoading) { |
- _log("Setup package map: $_packageMap"); |
+ _log(_packageError); |
} |
} |
@@ -485,7 +514,8 @@ void _loadPackagesMap(String packagesParam) { |
// resolve it against the working directory. |
packagesUri = _workingDirectory.resolveUri(packagesUri); |
} |
- VMLibraryHooks.packageConfig = packagesUri.toString(); |
+ var packagesUriStr = packagesUri.toString(); |
+ VMLibraryHooks.packageConfigString = packagesUriStr; |
if (_traceLoading) { |
_log('Resolved packages map to: $packagesUri'); |
} |
@@ -500,7 +530,7 @@ void _loadPackagesMap(String packagesParam) { |
msg[0] = sp; |
msg[1] = _traceLoading; |
msg[2] = -2; |
- msg[3] = packagesUri.toString(); |
+ msg[3] = packagesUriStr; |
_loadPort.send(msg); |
// Signal that the resolution of the packages map has started. But in this |
@@ -519,34 +549,6 @@ void _loadPackagesMap(String packagesParam) { |
} |
-// Embedder Entrypoint: |
-// Add mapping from package name to URI. |
-void _addPackageMapEntry(String key, String value) { |
- if (!_setupCompleted) { |
- _setupHooks(); |
- } |
- if (_traceLoading) { |
- _log("Adding packages map entry: $key -> $value"); |
- } |
- if (_packageRoot != null) { |
- if (_traceLoading) { |
- _log("_packageRoot already set: $_packageRoot"); |
- } |
- throw "Cannot add package map entry to an exisiting package root."; |
- } |
- if (_packagesPort != null) { |
- if (_traceLoading) { |
- _log("Package map load request already pending."); |
- } |
- throw "Cannot add package map entry during package map resolution."; |
- } |
- if (_packageMap == null) { |
- _packageMap = new Map<String, Uri>(); |
- } |
- _packageMap[key] = _workingDirectory.resolve(value); |
-} |
- |
- |
void _asyncLoadError(_LoadRequest req, _LoadError error, StackTrace stack) { |
if (_traceLoading) { |
_log("_asyncLoadError(${req._uri}), error: $error\nstack: $stack"); |
@@ -587,8 +589,22 @@ _loadDataFromLoadPort(int tag, String uri, Uri resourceUri, context) { |
// Loading a package URI needs to first map the package name to a loadable |
// URI. |
_loadPackage(int tag, String uri, Uri resourceUri, context) { |
- if (_packagesReady()) { |
- _loadData(tag, uri, _resolvePackageUri(resourceUri), context); |
+ if (_packagesReady) { |
+ var resolvedUri; |
+ try { |
+ resolvedUri = _resolvePackageUri(resourceUri); |
+ } catch (e, s) { |
+ if (_traceLoading) { |
+ _log("Exception ($e) when resolving package URI: $resourceUri"); |
+ } |
+ // Wrap inside a _LoadError unless we are already propagating a previously |
+ // seen _LoadError. |
+ var error = (e is _LoadError) ? e : new _LoadError(uri, e.toString()); |
+ // Register a dummy load request and fail to load it. |
+ var req = new _LoadRequest(tag, uri, resourceUri, context); |
+ _asyncLoadError(req, error, s); |
+ } |
+ _loadData(tag, uri, resolvedUri, context); |
} else { |
if (_pendingPackageLoads.isEmpty) { |
// Package resolution has not been setup yet, and this is the first |
@@ -606,7 +622,7 @@ _loadPackage(int tag, String uri, Uri resourceUri, context) { |
}); |
if (_traceLoading) { |
_log("Pending package load of '$uri': " |
- "${_pendingPackageLoads.length} pending"); |
+ "${_pendingPackageLoads.length} pending"); |
} |
} |
} |
@@ -669,7 +685,7 @@ String _resolveUri(String base, String userString) { |
// Handling of access to the package root or package map from user code. |
_triggerPackageResolution(action) { |
- if (_packagesReady()) { |
+ if (_packagesReady) { |
// Packages are ready. Execute the action now. |
action(); |
} else { |
@@ -684,7 +700,7 @@ _triggerPackageResolution(action) { |
} |
-Future<Uri> _getPackageRoot() { |
+Future<Uri> _getPackageRootFuture() { |
if (_traceLoading) { |
_log("Request for package root from user code."); |
} |
@@ -696,19 +712,47 @@ Future<Uri> _getPackageRoot() { |
} |
-Future<Map<String, Uri>> _getPackageMap() { |
+Future<Uri> _getPackageConfigFuture() { |
if (_traceLoading) { |
- _log("Request for package map from user code."); |
+ _log("Request for package config from user code."); |
} |
- var completer = new Completer<Map<String, Uri>>(); |
+ var completer = new Completer<Uri>(); |
_triggerPackageResolution(() { |
- var result = (_packageMap != null) ? new Map.from(_packageMap) : {}; |
- completer.complete(result); |
+ completer.complete(_packageConfig); |
}); |
return completer.future; |
} |
+Future<Uri> _resolvePackageUriFuture(Uri packageUri) async { |
+ if (_traceLoading) { |
+ _log("Request for package Uri resolution from user code: $packageUri"); |
+ } |
+ if (packageUri.scheme != "package") { |
+ if (_traceLoading) { |
+ _log("Non-package Uri, returning unmodified: $packageUri"); |
+ } |
+ // Return the incoming parameter if not passed a package: URI. |
+ return packageUri; |
+ } |
+ |
+ if (!_packagesReady) { |
+ if (_traceLoading) { |
+ _log("Trigger loading by requesting the package config."); |
+ } |
+ // Make sure to trigger package resolution. |
+ var dummy = await _getPackageConfigFuture(); |
+ } |
+ assert(_packagesReady); |
+ |
+ var result = _resolvePackageUri(packageUri); |
+ if (_traceLoading) { |
+ _log("Resolved '$packageUri' to '$result'"); |
+ } |
+ return result; |
+} |
+ |
+ |
// Handling of Resource class by dispatching to the load port. |
Future<List<int>> _resourceReadAsBytes(Uri uri) { |
var completer = new Completer<List<int>>(); |
@@ -836,6 +880,8 @@ _extensionPathFromUri(String userUri) { |
_setupHooks() { |
_setupCompleted = true; |
VMLibraryHooks.resourceReadAsBytes = _resourceReadAsBytes; |
- VMLibraryHooks.getPackageRoot = _getPackageRoot; |
- VMLibraryHooks.getPackageMap = _getPackageMap; |
+ |
+ VMLibraryHooks.packageRootUriFuture = _getPackageRootFuture; |
+ VMLibraryHooks.packageConfigUriFuture = _getPackageConfigFuture; |
+ VMLibraryHooks.resolvePackageUriFuture = _resolvePackageUriFuture; |
} |