Chromium Code Reviews| Index: runtime/bin/builtin.dart |
| diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart |
| index 42a5e1e9c4122cbe110a0cd9a559f3852b247efc..44779f9ba0f870985a111ac7648f0c8f680f7707 100644 |
| --- a/runtime/bin/builtin.dart |
| +++ b/runtime/bin/builtin.dart |
| @@ -4,10 +4,18 @@ |
| library builtin; |
| // NOTE: Do not import 'dart:io' in builtin. |
| +import 'dart:async'; |
| import 'dart:collection'; |
| +import 'dart:_internal'; |
| import 'dart:isolate'; |
| import 'dart:typed_data'; |
| + |
| +// Before handling an embedder entrypoint we finalize the setup of the |
| +// dart:_builtin library. |
| +bool _setupCompleted = false; |
| + |
| + |
| // The root library (aka the script) is imported into this library. The |
| // standalone embedder uses this to lookup the main entrypoint in the |
| // root library's namespace. |
| @@ -49,10 +57,11 @@ _getUriBaseClosure() => _uriBase; |
| // The embedder forwards most loading requests to this library. |
| // See Dart_LibraryTag in dart_api.h |
| -const Dart_kScriptTag = null; |
| -const Dart_kImportTag = 0; |
| -const Dart_kSourceTag = 1; |
| -const Dart_kCanonicalizeUrl = 2; |
| +const _Dart_kScriptTag = null; |
| +const _Dart_kImportTag = 0; |
| +const _Dart_kSourceTag = 1; |
| +const _Dart_kCanonicalizeUrl = 2; |
| +const _Dart_kResourceLoad = 3; |
| // Embedder sets this to true if the --trace-loading flag was passed on the |
| // command line. |
| @@ -119,16 +128,16 @@ class _LoadRequest { |
| final int _id; |
| final int _tag; |
| final String _uri; |
| - final String _libraryUri; |
| final Uri _resourceUri; |
| + final _context; |
| _LoadRequest(this._id, |
| this._tag, |
| this._uri, |
| - this._libraryUri, |
| - this._resourceUri); |
| + this._resourceUri, |
| + this._context); |
| - toString() => "LoadRequest($_id, $_tag, $_uri, $_libraryUri, $_resourceUri)"; |
| + toString() => "LoadRequest($_id, $_tag, $_uri, $_resourceUri, $_context)"; |
| } |
| @@ -195,6 +204,9 @@ _enforceTrailingSlash(uri) { |
| // Embedder Entrypoint: |
| // The embedder calls this method with the current working directory. |
| void _setWorkingDirectory(cwd) { |
| + if (!_setupCompleted) { |
| + _setupHooks(); |
| + } |
| if (_traceLoading) { |
| _log('Setting working directory: $cwd'); |
| } |
| @@ -208,6 +220,9 @@ void _setWorkingDirectory(cwd) { |
| // Embedder Entrypoint: |
| // The embedder calls this method with a custom package root. |
| _setPackageRoot(String packageRoot) { |
| + if (!_setupCompleted) { |
| + _setupHooks(); |
| + } |
| if (_traceLoading) { |
| _log('Setting package root: $packageRoot'); |
| } |
| @@ -323,7 +338,17 @@ void _handleLoaderReply(msg) { |
| var req = _reqMap[id]; |
| try { |
| if (dataOrError is Uint8List) { |
| - _loadScript(req, dataOrError); |
| + // Successfully loaded the data. |
| + if (req._tag == _Dart_kResourceLoad) { |
| + Completer c = req._context; |
| + c.complete(dataOrError); |
| + } else { |
| + // TODO: Currently a compilation error while loading the script is |
| + // fatal for the isolate. _loadScriptCallback() does not return and |
| + // the number of requests remains out of sync. |
| + _loadScriptCallback(req._tag, req._uri, req._context, dataOrError); |
| + } |
| + _finishLoadRequest(req); |
| } else { |
| assert(dataOrError is String); |
| var error = new _LoadError(req._uri, dataOrError.toString()); |
| @@ -339,10 +364,7 @@ void _handleLoaderReply(msg) { |
| } |
| -void _startLoadRequest(int tag, |
| - String uri, |
| - String libraryUri, |
| - Uri resourceUri) { |
| +void _startLoadRequest(int tag, String uri, Uri resourceUri, context) { |
| if (_receivePort == null) { |
| if (_traceLoading) { |
| _log("Initializing load port."); |
| @@ -356,7 +378,7 @@ void _startLoadRequest(int tag, |
| var curId = _reqId++; |
| assert(_reqMap[curId] == null); |
| - _reqMap[curId] = new _LoadRequest(curId, tag, uri, libraryUri, resourceUri); |
| + _reqMap[curId] = new _LoadRequest(curId, tag, uri, resourceUri, context); |
| assert(_receivePort != null); |
| assert(_sendPort != null); |
| @@ -369,8 +391,9 @@ void _startLoadRequest(int tag, |
| _loadPort.send(msg); |
| if (_traceLoading) { |
| - _log("Loading of $resourceUri for $uri started with id: $curId, " |
| - "${_reqMap.length} requests outstanding"); |
| + _log("Loading of $resourceUri for $uri started with id: $curId. " |
| + "${_reqMap.length} requests remaining, " |
| + "${_pendingPackageLoads.length} packages pending."); |
| } |
| } |
| @@ -408,13 +431,17 @@ void _handlePackagesReply(msg) { |
| } |
| // Resolve all pending package loads now that we know how to resolve them. |
| - for (var i = 0; i < _pendingPackageLoads.length; i++) { |
| - var req = _pendingPackageLoads[i]; |
| + while (_pendingPackageLoads.length > 0) { |
| + var req = _pendingPackageLoads.removeLast(); |
| if (req != null) { |
| if (_traceLoading) { |
| _log("Handling deferred load request: $req"); |
| } |
| - _loadPackage(req._tag, req._uri, req._libraryUri, req._resourceUri); |
| + _loadPackage(req._tag, req._uri, req._resourceUri, req._context); |
| + } else { |
| + if (_traceLoading) { |
| + _log("Skipping dummy deferred request."); |
| + } |
| } |
| } |
| // Reset the pending package loads to empty. So that we eventually can |
| @@ -446,6 +473,9 @@ void _requestPackagesMap() { |
| // Embedder Entrypoint: |
| // Request the load of a particular packages map. |
| void _loadPackagesMap(String packagesParam) { |
| + if (!_setupCompleted) { |
| + _setupHooks(); |
| + } |
| // First convert the packages parameter from the command line to a URI which |
| // can be handled by the loader code. |
| // TODO(iposva): Consider refactoring the common code below which is almost |
| @@ -490,21 +520,12 @@ void _loadPackagesMap(String packagesParam) { |
| } |
| -void _loadScript(_LoadRequest req, Uint8List data) { |
| - // TODO: Currently a compilation error while loading the script is |
| - // fatal for the isolate. _loadScriptCallback() does not return and |
| - // the number of requests remains out of sync. |
| - _loadScriptCallback(req._tag, req._uri, req._libraryUri, data); |
| - _finishLoadRequest(req); |
| -} |
| - |
| - |
| void _asyncLoadError(_LoadRequest req, _LoadError error) { |
| if (_traceLoading) { |
| _log("_asyncLoadError(${req._uri}), error: $error"); |
| } |
| - var libraryUri = req._libraryUri; |
| - if (req._tag == Dart_kImportTag) { |
| + var libraryUri = req._context; |
| + if (req._tag == _Dart_kImportTag) { |
| // When importing a library, the libraryUri is the imported |
| // uri. |
| libraryUri = req._uri; |
| @@ -514,36 +535,39 @@ void _asyncLoadError(_LoadRequest req, _LoadError error) { |
| } |
| -_loadDataFromLoadPort(int tag, |
| - String uri, |
| - String libraryUri, |
| - Uri resourceUri) { |
| +_loadDataFromLoadPort(int tag, String uri, Uri resourceUri, context) { |
| try { |
| - _startLoadRequest(tag, uri, libraryUri, resourceUri); |
| - } catch (e) { |
| + _startLoadRequest(tag, uri, resourceUri, context); |
| + } catch (e, s) { |
| + // For resource loads we need to complete with an error. |
| + if (tag == _Dart_kResourceLoad) { |
| + assert(context is Completer); |
| + context.completeError(e, s); |
| + } |
| + |
| if (_traceLoading) { |
| _log("Exception when communicating with service isolate: $e"); |
| } |
| // Wrap inside a _LoadError unless we are already propagating a previously |
| // seen _LoadError. |
| var error = (e is _LoadError) ? e : new _LoadError(e.toString()); |
| - _asyncLoadError(tag, uri, libraryUri, error); |
| + _asyncLoadError(tag, uri, context, error); |
| } |
| } |
| // Loading a package URI needs to first map the package name to a loadable |
| // URI. |
| -_loadPackage(int tag, String uri, String libraryUri, Uri resourceUri) { |
| +_loadPackage(int tag, String uri, Uri resourceUri, context) { |
| if (_packagesReady()) { |
| - _loadData(tag, uri, libraryUri, _resolvePackageUri(resourceUri)); |
| + _loadData(tag, uri, _resolvePackageUri(resourceUri), context); |
| } else { |
| if (_pendingPackageLoads.isEmpty) { |
| // Package resolution has not been setup yet, and this is the first |
| // request for package resolution & loading. |
| _requestPackagesMap(); |
| } |
| - var req = new _LoadRequest(-1, tag, uri, libraryUri, resourceUri); |
| + var req = new _LoadRequest(-1, tag, uri, resourceUri, context); |
| _pendingPackageLoads.add(req); |
| if (_traceLoading) { |
| _log("Pending package load of '$uri': " |
| @@ -554,14 +578,14 @@ _loadPackage(int tag, String uri, String libraryUri, Uri resourceUri) { |
| // Load the data associated with the resourceUri. |
| -_loadData(int tag, String uri, String libraryUri, Uri resourceUri) { |
| +_loadData(int tag, String uri, Uri resourceUri, context) { |
| if (resourceUri.scheme == 'package') { |
| // package based uris need to be resolved to the correct loadable location. |
| // The logic of which is handled seperately, and then _loadData is called |
| // recursively. |
| - _loadPackage(tag, uri, libraryUri, resourceUri); |
| + _loadPackage(tag, uri, resourceUri, context); |
| } else { |
| - _loadDataFromLoadPort(tag, uri, libraryUri, resourceUri); |
| + _loadDataFromLoadPort(tag, uri, resourceUri, context); |
| } |
| } |
| @@ -569,14 +593,17 @@ _loadData(int tag, String uri, String libraryUri, Uri resourceUri) { |
| // Embedder Entrypoint: |
| // Asynchronously loads script data through a http[s] or file uri. |
| _loadDataAsync(int tag, String uri, String libraryUri) { |
| + if (!_setupCompleted) { |
| + _setupHooks(); |
| + } |
| var resourceUri; |
| - if (tag == Dart_kScriptTag) { |
| + if (tag == _Dart_kScriptTag) { |
| resourceUri = _resolveScriptUri(uri); |
| uri = resourceUri.toString(); |
| } else { |
| resourceUri = Uri.parse(uri); |
| } |
| - _loadData(tag, uri, libraryUri, resourceUri); |
| + _loadData(tag, uri, resourceUri, libraryUri); |
| } |
| @@ -584,6 +611,9 @@ _loadDataAsync(int tag, String uri, String libraryUri) { |
| // Function called by standalone embedder to resolve uris when the VM requests |
| // Dart_kCanonicalizeUrl from the tag handler. |
| String _resolveUri(String base, String userString) { |
| + if (!_setupCompleted) { |
| + _setupHooks(); |
| + } |
| if (_traceLoading) { |
| _log('Resolving: $userString from $base'); |
| } |
| @@ -602,9 +632,23 @@ String _resolveUri(String base, String userString) { |
| } |
| +// Handling of Resource class by dispatching to the load port. |
| +Future<List<int>> _resourceReadAsBytes(Uri uri) { |
| + var completer = new Completer<List<int>>(); |
| + // Request the load of the resource associating the completer as the context |
| + // for the load. |
| + _loadData(_Dart_kResourceLoad, uri.toString(), uri, completer); |
| + // Return the future that will be triggered once the resource has been loaded. |
| + return completer.future; |
| +} |
| + |
| + |
| // Embedder Entrypoint (gen_snapshot): |
| // Resolve relative paths relative to working directory. |
| String _resolveInWorkingDirectory(String fileName) { |
| + if (!_setupCompleted) { |
| + _setupHooks(); |
| + } |
| if (_workingDirectory == null) { |
| throw 'No current working directory set.'; |
| } |
| @@ -679,6 +723,9 @@ String _filePathFromUri(String userUri) { |
| // The filename part is the extension name, with the platform-dependent |
| // prefixes and extensions added. |
| _extensionPathFromUri(String userUri) { |
| + if (!_setupCompleted) { |
| + _setupHooks(); |
| + } |
| if (!userUri.startsWith(_DART_EXT)) { |
| throw 'Unexpected internal error: Extension URI $userUri missing dart-ext:'; |
| } |
| @@ -706,3 +753,10 @@ _extensionPathFromUri(String userUri) { |
| return [path, filename, name]; |
| } |
| + |
| + |
| +// |
|
siva
2015/08/04 21:48:23
Dangling comment start ?
|
| +_setupHooks() { |
| + _setupCompleted = true; |
| + VMLibraryHooks.resourceReadAsBytes = _resourceReadAsBytes; |
| +} |