| Index: runtime/bin/vmservice/loader.dart
|
| diff --git a/runtime/bin/vmservice/loader.dart b/runtime/bin/vmservice/loader.dart
|
| index 7bec4a1cda1c23147d5e19bd897ff7deeea1a677..42bc6f92c948ef4bfcb5b8ad151b30c284c7afce 100644
|
| --- a/runtime/bin/vmservice/loader.dart
|
| +++ b/runtime/bin/vmservice/loader.dart
|
| @@ -4,6 +4,303 @@
|
|
|
| part of vmservice_io;
|
|
|
| +_sanitizeWindowsPath(path) {
|
| + // For Windows we need to massage the paths a bit according to
|
| + // http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
|
| + //
|
| + // Convert
|
| + // C:\one\two\three
|
| + // to
|
| + // /C:/one/two/three
|
| +
|
| + if (_isWindows == false) {
|
| + // Do nothing when not running Windows.
|
| + return path;
|
| + }
|
| +
|
| + var fixedPath = "${path.replaceAll('\\', '/')}";
|
| +
|
| + if ((path.length > 2) && (path[1] == ':')) {
|
| + // Path begins with a drive letter.
|
| + return '/$fixedPath';
|
| + }
|
| +
|
| + return fixedPath;
|
| +}
|
| +
|
| +_trimWindowsPath(path) {
|
| + // Convert /X:/ to X:/.
|
| + if (_isWindows == false) {
|
| + // Do nothing when not running Windows.
|
| + return path;
|
| + }
|
| + if (!path.startsWith('/') || (path.length < 3)) {
|
| + return path;
|
| + }
|
| + // Match '/?:'.
|
| + if ((path[0] == '/') && (path[2] == ':')) {
|
| + // Remove leading '/'.
|
| + return path.substring(1);
|
| + }
|
| + return path;
|
| +}
|
| +
|
| +// Ensure we have a trailing slash character.
|
| +_enforceTrailingSlash(uri) {
|
| + if (!uri.endsWith('/')) {
|
| + return '$uri/';
|
| + }
|
| + return uri;
|
| +}
|
| +
|
| +// State associated with the isolate that is used for loading.
|
| +class IsolateLoaderState extends IsolateEmbedderData {
|
| + IsolateLoaderState(this.isolateId);
|
| +
|
| + final int isolateId;
|
| +
|
| + SendPort sp;
|
| +
|
| + void init(String packageRootFlag,
|
| + String packagesConfigFlag,
|
| + String workingDirectory,
|
| + String rootScript) {
|
| + // _workingDirectory must be set first.
|
| + _workingDirectory = new Uri.directory(workingDirectory);
|
| + if (rootScript != null) {
|
| + _rootScript = Uri.parse(rootScript);
|
| + }
|
| + // If the --package-root flag was passed.
|
| + if (packageRootFlag != null) {
|
| + _setPackageRoot(packageRootFlag);
|
| + }
|
| + // If the --packages flag was passed.
|
| + if (packagesConfigFlag != null) {
|
| + _setPackagesConfig(packagesConfigFlag);
|
| + }
|
| + }
|
| +
|
| + void cleanup() {
|
| + if (_packagesPort != null) {
|
| + _packagesPort.close();
|
| + _packagesPort = null;
|
| + }
|
| + }
|
| +
|
| + // The working directory when the embedder started.
|
| + Uri _workingDirectory;
|
| +
|
| + // The root script's uri.
|
| + Uri _rootScript;
|
| +
|
| + bool _traceLoading = false;
|
| +
|
| + // Packages are either resolved looking up in a map or resolved from within a
|
| + // package root.
|
| + 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 default it
|
| + // is the 'packages' directory right next to the script.
|
| + Uri _packageRoot = null;
|
| +
|
| + // The map describing how certain package names are mapped to Uris.
|
| + Uri _packageConfig = null;
|
| + Map<String, Uri> _packageMap = null;
|
| +
|
| + _setPackageRoot(String packageRoot) {
|
| + packageRoot = _enforceTrailingSlash(packageRoot);
|
| + if (packageRoot.startsWith('file:') ||
|
| + packageRoot.startsWith('http:') ||
|
| + packageRoot.startsWith('https:')) {
|
| + _packageRoot = _workingDirectory.resolve(packageRoot);
|
| + } else {
|
| + packageRoot = _sanitizeWindowsPath(packageRoot);
|
| + packageRoot = _trimWindowsPath(packageRoot);
|
| + _packageRoot = _workingDirectory.resolveUri(new Uri.file(packageRoot));
|
| + }
|
| + }
|
| +
|
| + _setPackagesConfig(String packagesParam) {
|
| + var packagesName = _sanitizeWindowsPath(packagesParam);
|
| + var packagesUri = Uri.parse(packagesName);
|
| + if (packagesUri.scheme == '') {
|
| + // Script does not have a scheme, assume that it is a path,
|
| + // resolve it against the working directory.
|
| + packagesUri = _workingDirectory.resolveUri(packagesUri);
|
| + }
|
| + _requestPackagesMap(packagesUri);
|
| + _pendingPackageLoads.add(() {
|
| + // Dummy action.
|
| + });
|
| + }
|
| +
|
| + // Handling of access to the package root or package map from user code.
|
| + _triggerPackageResolution(action) {
|
| + if (_packagesReady) {
|
| + // Packages are ready. Execute the action now.
|
| + action();
|
| + } else {
|
| + if (_pendingPackageLoads.isEmpty) {
|
| + // Package resolution has not been setup yet, and this is the first
|
| + // request for package resolution & loading.
|
| + _requestPackagesMap();
|
| + }
|
| + // Register the action for when the package resolution is ready.
|
| + _pendingPackageLoads.add(action);
|
| + }
|
| + }
|
| +
|
| + // A list of callbacks which should be invoked after the package map has been
|
| + // loaded.
|
| + List<Function> _pendingPackageLoads = [];
|
| +
|
| + // 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';
|
| + var wrong = 'package://$path';
|
| +
|
| + throw "URIs using the 'package:' scheme should look like "
|
| + "'$right', not '$wrong'.";
|
| + }
|
| +
|
| + if (_traceLoading) {
|
| + _log('Resolving package with uri path: ${uri.path}');
|
| + }
|
| + var resolvedUri;
|
| + 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];
|
| + var mapping = _packageMap[packageName];
|
| + if (_traceLoading) {
|
| + _log("Mapped '$packageName' package to '$mapping'");
|
| + }
|
| + if (mapping == null) {
|
| + throw "No mapping for '$packageName' package when resolving '$uri'.";
|
| + }
|
| + var path;
|
| + if (uri.path.length > packageName.length) {
|
| + path = uri.path.substring(packageName.length + 1);
|
| + } else {
|
| + // Handle naked package resolution to the default package name:
|
| + // package:foo is equivalent to package:foo/foo.dart
|
| + assert(uri.path.length == packageName.length);
|
| + path = "$packageName.dart";
|
| + }
|
| + if (_traceLoading) {
|
| + _log("Path to be resolved in package: $path");
|
| + }
|
| + resolvedUri = mapping.resolve(path);
|
| + }
|
| + if (_traceLoading) {
|
| + _log("Resolved '$uri' to '$resolvedUri'.");
|
| + }
|
| + return resolvedUri;
|
| + }
|
| +
|
| + RawReceivePort _packagesPort;
|
| +
|
| + void _requestPackagesMap([Uri packageConfig]) {
|
| + assert(_packagesPort == null);
|
| + assert(_rootScript != null);
|
| + // Create a port to receive the packages map on.
|
| + _packagesPort = new RawReceivePort(_handlePackagesReply);
|
| + var sp = _packagesPort.sendPort;
|
| +
|
| + if (packageConfig != null) {
|
| + // Explicitly specified .packages path.
|
| + _handlePackagesRequest(sp,
|
| + _traceLoading,
|
| + -2,
|
| + packageConfig);
|
| + } else {
|
| + // Search for .packages or packages/ starting at the root script.
|
| + _handlePackagesRequest(sp,
|
| + _traceLoading,
|
| + -1,
|
| + _rootScript);
|
| + }
|
| +
|
| + if (_traceLoading) {
|
| + _log("Requested packages map for '$_rootScript'.");
|
| + }
|
| + }
|
| +
|
| + void _handlePackagesReply(msg) {
|
| + assert(_packagesPort != null);
|
| + // Make sure to close the _packagePort before any other action.
|
| + _packagesPort.close();
|
| + _packagesPort = null;
|
| +
|
| + if (_traceLoading) {
|
| + _log("Got packages reply: $msg");
|
| + }
|
| + if (msg is String) {
|
| + if (_traceLoading) {
|
| + _log("Got failure response on package port: '$msg'");
|
| + }
|
| + // 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");
|
| + }
|
| + }
|
| + } else {
|
| + _packageError = "Bad type of packages reply: ${msg.runtimeType}";
|
| + if (_traceLoading) {
|
| + _log(_packageError);
|
| + }
|
| + }
|
| +
|
| + // Resolve all pending package loads now that we know how to resolve them.
|
| + while (_pendingPackageLoads.length > 0) {
|
| + // Order does not matter as we queue all of the requests up right now.
|
| + var req = _pendingPackageLoads.removeLast();
|
| + // Call the registered closure, to handle the delayed action.
|
| + req();
|
| + }
|
| + // Reset the pending package loads to empty. So that we eventually can
|
| + // finish loading.
|
| + _pendingPackageLoads = [];
|
| + }
|
| +
|
| +}
|
| +
|
| _log(msg) {
|
| print("% $msg");
|
| }
|
| @@ -11,19 +308,38 @@ _log(msg) {
|
| var _httpClient;
|
|
|
| // Send a response to the requesting isolate.
|
| -void _sendResourceResponse(SendPort sp, int id, dynamic data) {
|
| +void _sendResourceResponse(SendPort sp,
|
| + int tag,
|
| + Uri uri,
|
| + String libraryUrl,
|
| + dynamic data) {
|
| assert((data is List<int>) || (data is String));
|
| - var msg = new List(2);
|
| - msg[0] = id;
|
| - msg[1] = data;
|
| + var msg = new List(4);
|
| + if (data is String) {
|
| + // We encountered an error, flip the sign of the tag to indicate that.
|
| + tag = -tag;
|
| + if (libraryUrl == null) {
|
| + data = 'Could not load "$uri": $data';
|
| + } else {
|
| + data = 'Could not import "$uri" from "$libraryUrl": $data';
|
| + }
|
| + }
|
| + msg[0] = tag;
|
| + msg[1] = uri.toString();
|
| + msg[2] = libraryUrl;
|
| + msg[3] = data;
|
| sp.send(msg);
|
| }
|
|
|
| -void _loadHttp(SendPort sp, int id, Uri uri) {
|
| +void _loadHttp(SendPort sp,
|
| + int tag,
|
| + Uri uri,
|
| + Uri resolvedUri,
|
| + String libraryUrl) {
|
| if (_httpClient == null) {
|
| _httpClient = new HttpClient()..maxConnectionsPerHost = 6;
|
| }
|
| - _httpClient.getUrl(uri)
|
| + _httpClient.getUrl(resolvedUri)
|
| .then((HttpClientRequest request) => request.close())
|
| .then((HttpClientResponse response) {
|
| var builder = new BytesBuilder(copy: false);
|
| @@ -31,37 +347,46 @@ void _loadHttp(SendPort sp, int id, Uri uri) {
|
| builder.add,
|
| onDone: () {
|
| if (response.statusCode != 200) {
|
| - var msg = "Failure getting $uri:\n"
|
| + var msg = "Failure getting $resolvedUri:\n"
|
| " ${response.statusCode} ${response.reasonPhrase}";
|
| - _sendResourceResponse(sp, id, msg);
|
| + _sendResourceResponse(sp, tag, uri, libraryUrl, msg);
|
| } else {
|
| - _sendResourceResponse(sp, id, builder.takeBytes());
|
| + _sendResourceResponse(sp, tag, uri, libraryUrl,
|
| + builder.takeBytes());
|
| }
|
| },
|
| onError: (e) {
|
| - _sendResourceResponse(sp, id, e.toString());
|
| + _sendResourceResponse(sp, tag, uri, libraryUrl, e.toString());
|
| });
|
| })
|
| .catchError((e) {
|
| - _sendResourceResponse(sp, id, e.toString());
|
| + _sendResourceResponse(sp, tag, uri, libraryUrl, e.toString());
|
| });
|
| // It's just here to push an event on the event loop so that we invoke the
|
| // scheduled microtasks.
|
| Timer.run(() {});
|
| }
|
|
|
| -void _loadFile(SendPort sp, int id, Uri uri) {
|
| - var path = uri.toFilePath();
|
| +void _loadFile(SendPort sp,
|
| + int tag,
|
| + Uri uri,
|
| + Uri resolvedUri,
|
| + String libraryUrl) {
|
| + var path = resolvedUri.toFilePath();
|
| var sourceFile = new File(path);
|
| sourceFile.readAsBytes().then((data) {
|
| - _sendResourceResponse(sp, id, data);
|
| + _sendResourceResponse(sp, tag, uri, libraryUrl, data);
|
| },
|
| onError: (e) {
|
| - _sendResourceResponse(sp, id, e.toString());
|
| + _sendResourceResponse(sp, tag, uri, libraryUrl, e.toString());
|
| });
|
| }
|
|
|
| -void _loadDataUri(SendPort sp, int id, Uri uri) {
|
| +void _loadDataUri(SendPort sp,
|
| + int tag,
|
| + Uri uri,
|
| + Uri resolvedUri,
|
| + String libraryUrl) {
|
| try {
|
| var mime = uri.data.mimeType;
|
| if ((mime != "application/dart") &&
|
| @@ -74,25 +399,102 @@ void _loadDataUri(SendPort sp, int id, Uri uri) {
|
| // The C++ portion of the embedder assumes UTF-8.
|
| throw "Only utf-8 or US-ASCII encodings are supported: $charset given.";
|
| }
|
| - _sendResourceResponse(sp, id, uri.data.contentAsBytes());
|
| + _sendResourceResponse(sp, tag, uri, libraryUrl, uri.data.contentAsBytes());
|
| } catch (e) {
|
| - _sendResourceResponse(sp, id, "Invalid data uri ($uri):\n $e");
|
| + _sendResourceResponse(sp, tag, uri, libraryUrl,
|
| + "Invalid data uri ($uri):\n $e");
|
| }
|
| }
|
|
|
| -_handleResourceRequest(SendPort sp, bool traceLoading, int id, Uri resource) {
|
| - if (resource.scheme == 'file') {
|
| - _loadFile(sp, id, resource);
|
| - } else if ((resource.scheme == 'http') || (resource.scheme == 'https')) {
|
| - _loadHttp(sp, id, resource);
|
| - } else if ((resource.scheme == 'data')) {
|
| - _loadDataUri(sp, id, resource);
|
| +// Loading a package URI needs to first map the package name to a loadable
|
| +// URI.
|
| +_loadPackage(IsolateLoaderState loaderState,
|
| + SendPort sp,
|
| + bool traceLoading,
|
| + int tag,
|
| + Uri uri,
|
| + Uri resolvedUri,
|
| + String libraryUrl) {
|
| + if (loaderState._packagesReady) {
|
| + var resolvedUri;
|
| + try {
|
| + resolvedUri = loaderState._resolvePackageUri(uri);
|
| + } catch (e, s) {
|
| + if (traceLoading) {
|
| + _log("Exception ($e) when resolving package URI: $uri");
|
| + }
|
| + // Report error.
|
| + _sendResourceResponse(sp,
|
| + tag,
|
| + uri,
|
| + libraryUrl,
|
| + e.toString());
|
| + return;
|
| + }
|
| + // Recursively call with the new resolved uri.
|
| + _handleResourceRequest(loaderState,
|
| + sp,
|
| + traceLoading,
|
| + tag,
|
| + uri,
|
| + resolvedUri,
|
| + libraryUrl);
|
| } else {
|
| - _sendResourceResponse(sp, id,
|
| - 'Unknown scheme (${resource.scheme}) for $resource');
|
| + if (loaderState._pendingPackageLoads.isEmpty) {
|
| + // Package resolution has not been setup yet, and this is the first
|
| + // request for package resolution & loading.
|
| + loaderState._requestPackagesMap();
|
| + }
|
| + // Register the action of loading this package once the package resolution
|
| + // is ready.
|
| + loaderState._pendingPackageLoads.add(() {
|
| + _handleResourceRequest(loaderState,
|
| + sp,
|
| + traceLoading,
|
| + tag,
|
| + uri,
|
| + uri,
|
| + libraryUrl);
|
| + });
|
| + if (traceLoading) {
|
| + _log("Pending package load of '$uri': "
|
| + "${loaderState._pendingPackageLoads.length} pending");
|
| + }
|
| }
|
| }
|
|
|
| +// TODO(johnmccutchan): This and most other top level functions in this file
|
| +// should be turned into methods on the IsolateLoaderState class.
|
| +_handleResourceRequest(IsolateLoaderState loaderState,
|
| + SendPort sp,
|
| + bool traceLoading,
|
| + int tag,
|
| + Uri uri,
|
| + Uri resolvedUri,
|
| + String libraryUrl) {
|
| + if (resolvedUri.scheme == 'file') {
|
| + _loadFile(sp, tag, uri, resolvedUri, libraryUrl);
|
| + } else if ((resolvedUri.scheme == 'http') ||
|
| + (resolvedUri.scheme == 'https')) {
|
| + _loadHttp(sp, tag, uri, resolvedUri, libraryUrl);
|
| + } else if ((resolvedUri.scheme == 'data')) {
|
| + _loadDataUri(sp, tag, uri, resolvedUri, libraryUrl);
|
| + } else if ((resolvedUri.scheme == 'package')) {
|
| + _loadPackage(loaderState,
|
| + sp,
|
| + traceLoading,
|
| + tag,
|
| + uri,
|
| + resolvedUri,
|
| + libraryUrl);
|
| + } else {
|
| + _sendResourceResponse(sp, tag,
|
| + uri,
|
| + libraryUrl,
|
| + 'Unknown scheme (${resolvedUri.scheme}) for '
|
| + '$resolvedUri');
|
| + }
|
| +}
|
|
|
| // Handling of packages requests. Finding and parsing of .packages file or
|
| // packages/ directories.
|
| @@ -329,7 +731,6 @@ _findPackagesFile(SendPort sp, bool traceLoading, Uri base) async {
|
| }
|
| }
|
|
|
| -
|
| Future<bool> _loadHttpPackagesFile(SendPort sp,
|
| bool traceLoading,
|
| Uri resource) async {
|
| @@ -386,13 +787,16 @@ _loadPackagesData(sp, traceLoading, resource){
|
| }
|
| }
|
|
|
| -
|
| +// This code used to exist in a second isolate and so it uses a SendPort to
|
| +// report it's return value. This could be refactored so that it returns it's
|
| +// value and the caller could wait on the future rather than a message on
|
| +// SendPort.
|
| _handlePackagesRequest(SendPort sp,
|
| bool traceLoading,
|
| - int id,
|
| + int tag,
|
| Uri resource) async {
|
| try {
|
| - if (id == -1) {
|
| + if (tag == -1) {
|
| if (resource.scheme == 'file') {
|
| _findPackagesFile(sp, traceLoading, resource);
|
| } else if ((resource.scheme == 'http') || (resource.scheme == 'https')) {
|
| @@ -409,7 +813,7 @@ _handlePackagesRequest(SendPort sp,
|
| sp.send("Unsupported scheme used to locate .packages file: "
|
| "'$resource'.");
|
| }
|
| - } else if (id == -2) {
|
| + } else if (tag == -2) {
|
| if (traceLoading) {
|
| _log("Handling load of packages map: '$resource'.");
|
| }
|
| @@ -432,7 +836,7 @@ _handlePackagesRequest(SendPort sp,
|
| "'$resource'.");
|
| }
|
| } else {
|
| - sp.send("Unknown packages request id: $id for '$resource'.");
|
| + sp.send("Unknown packages request tag: $tag for '$resource'.");
|
| }
|
| } catch (e, s) {
|
| if (traceLoading) {
|
| @@ -442,21 +846,143 @@ _handlePackagesRequest(SendPort sp,
|
| }
|
| }
|
|
|
| +// Shutdown all active loaders by sending an error message.
|
| +void shutdownLoaders() {
|
| + String message = 'Service shutdown';
|
| + if (_httpClient != null) {
|
| + _httpClient.close(force: true);
|
| + _httpClient = null;
|
| + }
|
| + isolateEmbedderData.values.toList().forEach((IsolateLoaderState ils) {
|
| + ils.cleanup();
|
| + assert(ils.sp != null);
|
| + _sendResourceResponse(ils.sp, 1, null, null, message);
|
| + });
|
| +}
|
| +
|
| +// See Dart_LibraryTag in dart_api.h
|
| +const _Dart_kCanonicalizeUrl = 0; // Canonicalize the URL.
|
| +const _Dart_kScriptTag = 1; // Load the root script.
|
| +const _Dart_kSourceTag = 2; // Load a part source.
|
| +const _Dart_kImportTag = 3; // Import a library.
|
| +
|
| +// Extra requests. Keep these in sync between loader.dart and builtin.dart.
|
| +const _Dart_kInitLoader = 4; // Initialize the loader.
|
| +const _Dart_kResourceLoad = 5; // Resource class support.
|
| +const _Dart_kGetPackageRootUri = 6; // Uri of the packages/ directory.
|
| +const _Dart_kGetPackageConfigUri = 7; // Uri of the .packages file.
|
| +const _Dart_kResolvePackageUri = 8; // Resolve a package: uri.
|
|
|
| // External entry point for loader requests.
|
| _processLoadRequest(request) {
|
| - SendPort sp = request[0];
|
| - assert(sp != null);
|
| - bool traceLoading = request[1];
|
| - assert(traceLoading != null);
|
| - int id = request[2];
|
| - assert(id != null);
|
| - String resource = request[3];
|
| - assert(resource != null);
|
| - var uri = Uri.parse(resource);
|
| - if (id >= 0) {
|
| - _handleResourceRequest(sp, traceLoading, id, uri);
|
| - } else {
|
| - _handlePackagesRequest(sp, traceLoading, id, uri);
|
| + assert(request is List);
|
| + assert(request.length > 4);
|
| +
|
| + // Should we trace loading?
|
| + bool traceLoading = request[0];
|
| +
|
| + // This is the sending isolate's Dart_GetMainPortId().
|
| + int isolateId = request[1];
|
| +
|
| + // The tag describing the operation.
|
| + int tag = request[2];
|
| +
|
| + // The send port to send the response on.
|
| + SendPort sp = request[3];
|
| +
|
| + // Grab the loader state for the requesting isolate.
|
| + IsolateLoaderState loaderState = isolateEmbedderData[isolateId];
|
| +
|
| + // We are either about to initialize the loader, or, we already have.
|
| + assert((tag == _Dart_kInitLoader) || (loaderState != null));
|
| +
|
| + // Handle the request specified in the tag.
|
| + switch (tag) {
|
| + case _Dart_kScriptTag: {
|
| + Uri uri = Uri.parse(request[4]);
|
| + // Remember the root script.
|
| + loaderState._rootScript = uri;
|
| + _handleResourceRequest(loaderState,
|
| + sp,
|
| + traceLoading,
|
| + tag,
|
| + uri,
|
| + uri,
|
| + null);
|
| + }
|
| + break;
|
| + case _Dart_kSourceTag:
|
| + case _Dart_kImportTag: {
|
| + // The url of the file being loaded.
|
| + var uri = Uri.parse(request[4]);
|
| + // The library that is importing/parting the file.
|
| + String libraryUrl = request[5];
|
| + _handleResourceRequest(loaderState,
|
| + sp,
|
| + traceLoading,
|
| + tag,
|
| + uri,
|
| + uri,
|
| + libraryUrl);
|
| + }
|
| + break;
|
| + case _Dart_kInitLoader: {
|
| + String packageRoot = request[4];
|
| + String packagesFile = request[5];
|
| + String workingDirectory = request[6];
|
| + String rootScript = request[7];
|
| + if (loaderState == null) {
|
| + loaderState = new IsolateLoaderState(isolateId);
|
| + isolateEmbedderData[isolateId] = loaderState;
|
| + loaderState.init(packageRoot,
|
| + packagesFile,
|
| + workingDirectory,
|
| + rootScript);
|
| + }
|
| + loaderState.sp = sp;
|
| + assert(isolateEmbedderData[isolateId] == loaderState);
|
| + }
|
| + break;
|
| + case _Dart_kResourceLoad: {
|
| + Uri uri = Uri.parse(request[4]);
|
| + _handleResourceRequest(loaderState,
|
| + sp,
|
| + traceLoading,
|
| + tag,
|
| + uri,
|
| + uri,
|
| + null);
|
| + }
|
| + break;
|
| + case _Dart_kGetPackageRootUri:
|
| + loaderState._triggerPackageResolution(() {
|
| + // Respond with the package root (if any) after package resolution.
|
| + sp.send(loaderState._packageRoot);
|
| + });
|
| + break;
|
| + case _Dart_kGetPackageConfigUri:
|
| + loaderState._triggerPackageResolution(() {
|
| + // Respond with the packages config (if any) after package resolution.
|
| + sp.send(loaderState._packageConfig);
|
| + });
|
| + break;
|
| + case _Dart_kResolvePackageUri:
|
| + Uri uri = Uri.parse(request[4]);
|
| + loaderState._triggerPackageResolution(() {
|
| + // Respond with the resolved package uri after package resolution.
|
| + Uri resolvedUri;
|
| + try {
|
| + resolvedUri = loaderState._resolvePackageUri(uri);
|
| + } catch (e, s) {
|
| + if (traceLoading) {
|
| + _log("Exception ($e) when resolving package URI: $uri");
|
| + }
|
| + resolvedUri = null;
|
| + }
|
| + sp.send(resolvedUri);
|
| + });
|
| + break;
|
| + default:
|
| + _log('Unknown loader request tag=$tag from $isolateId');
|
| }
|
| }
|
|
|