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

Unified Diff: runtime/bin/builtin.dart

Issue 889443002: Service isolate rework take 2 (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 11 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
« no previous file with comments | « runtime/bin/builtin.cc ('k') | runtime/bin/builtin_common.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/builtin.dart
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index 155dc1fe4bf98b9fda561e7c62f2475090805ee9..a741da99b5ddee0b94675e7bb68934f92f3f5165 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -3,9 +3,92 @@
// BSD-style license that can be found in the LICENSE file.
library builtin;
-import 'dart:io';
import 'dart:async';
import 'dart:convert';
+import 'dart:isolate';
+
+
+//////////////////////
+/* Support for loading within the isolate via dart:io */
+import 'dart:io';
+
+// Enable by setting the #define LOAD_VIA_SERVICE_ISOLATE (see dartutils.cc)
+bool _load_via_service_isolate = false;
+
+var _httpClient;
+void _httpGet(int tag,
+ Uri uri,
+ String libraryUri,
+ loadCallback(List<int> data)) {
+ if (_httpClient == null) {
+ _httpClient = new HttpClient()..maxConnectionsPerHost = 6;
+ }
+ _httpClient.getUrl(uri)
+ .then((HttpClientRequest request) => request.close())
+ .then((HttpClientResponse response) {
+ var builder = new BytesBuilder(copy: false);
+ response.listen(
+ builder.add,
+ onDone: () {
+ if (response.statusCode != 200) {
+ var msg = 'Failure getting $uri: '
+ '${response.statusCode} ${response.reasonPhrase}';
+ _asyncLoadError(tag, uri.toString(), libraryUri, msg);
+ }
+ loadCallback(builder.takeBytes());
+ },
+ onError: (error) {
+ _asyncLoadError(tag, uri.toString(), libraryUri, error);
+ });
+ })
+ .catchError((error) {
+ _asyncLoadError(tag, uri.toString(), libraryUri, error);
+ });
+ // TODO(floitsch): remove this line. It's just here to push an event on the
+ // event loop so that we invoke the scheduled microtasks. Also remove the
+ // import of dart:async when this line is not needed anymore.
+ Timer.run(() {});
+}
+
+
+void _cleanup() {
+ if (_httpClient != null) {
+ _httpClient.close();
+ _httpClient = null;
+ }
+}
+
+_loadDataAsyncDartIO(int tag,
+ String uri,
+ String libraryUri,
+ Uri resourceUri) {
+ _startingOneLoadRequest(uri);
+ if ((resourceUri.scheme == 'http') || (resourceUri.scheme == 'https')) {
+ _httpGet(tag, resourceUri, libraryUri, (data) {
+ _loadScript(tag, uri, libraryUri, data);
+ });
+ } else {
+ var sourceFile = new File(resourceUri.toFilePath());
+ sourceFile.readAsBytes().then((data) {
+ _loadScript(tag, uri, libraryUri, data);
+ },
+ onError: (e) {
+ _asyncLoadError(tag, uri, libraryUri, e);
+ });
+ }
+}
+
+//////////////////////
+
+/* See Dart_LibraryTag in dart_api.h */
+const Dart_kScriptTag = null;
+const Dart_kImportTag = 0;
+const Dart_kSourceTag = 1;
+const Dart_kCanonicalizeUrl = 2;
+
+// Dart native extension scheme.
+const _DART_EXT = 'dart-ext:';
+
// import 'root_library'; happens here from C Code
// The root library (aka the script) is imported into this library. The
@@ -13,33 +96,34 @@ import 'dart:convert';
// root library's namespace.
Function _getMainClosure() => main;
+// A port for communicating with the service isolate for I/O.
+SendPort _loadPort;
+
+const _logBuiltin = false;
// Corelib 'print' implementation.
void _print(arg) {
_Logger._printString(arg.toString());
}
-
class _Logger {
static void _printString(String s) native "Logger_PrintString";
}
-
_getPrintClosure() => _print;
-const _logBuiltin = false;
+_getCurrentDirectoryPath() native "Directory_Current";
// Corelib 'Uri.base' implementation.
Uri _uriBase() {
- return new Uri.file(Directory.current.path + "/");
+ return new Uri.file(_getCurrentDirectoryPath() + "/");
}
-
_getUriBaseClosure() => _uriBase;
// Are we running on Windows?
-var _isWindows = false;
+var _isWindows;
var _workingWindowsDrivePrefix;
// The current working directory
var _workingDirectoryUri;
@@ -49,12 +133,6 @@ var _entryPointScript;
// The directory to look in to resolve "package:" scheme URIs.
var _packageRoot;
-
-void _setWindows() {
- _isWindows = true;
-}
-
-
_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
@@ -79,6 +157,22 @@ _sanitizeWindowsPath(path) {
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;
+}
_enforceTrailingSlash(uri) {
// Ensure we have a trailing slash character.
@@ -118,6 +212,8 @@ _setPackageRoot(String packageRoot) {
packageRoot.startsWith('https:')) {
_packageRoot = _workingDirectoryUri.resolve(packageRoot);
} else {
+ packageRoot = _sanitizeWindowsPath(packageRoot);
+ packageRoot = _trimWindowsPath(packageRoot);
_packageRoot = _workingDirectoryUri.resolveUri(new Uri.file(packageRoot));
}
if (_logBuiltin) {
@@ -126,6 +222,26 @@ _setPackageRoot(String packageRoot) {
}
+// Given a uri with a 'package' scheme, return a Uri that is prefixed with
+// the package root.
+Uri _resolvePackageUri(Uri uri) {
+ 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'.";
+ }
+
+ var packageRoot = _packageRoot == null ?
+ _entryPointScript.resolve('packages/') :
+ _packageRoot;
+ return packageRoot.resolve(uri.path);
+}
+
+
+
String _resolveScriptUri(String scriptName) {
if (_workingDirectoryUri == null) {
throw 'No current working directory set.';
@@ -147,8 +263,8 @@ String _resolveScriptUri(String scriptName) {
return _entryPointScript.toString();
}
-const _DART_EXT = 'dart-ext:';
+// Function called by standalone embedder to resolve uris.
String _resolveUri(String base, String userString) {
if (_logBuiltin) {
_print('# Resolving: $userString from $base');
@@ -162,26 +278,18 @@ String _resolveUri(String base, String userString) {
}
}
-
-// Returns either a file path or a URI starting with http[s]:, as a String.
-String _filePathFromUri(String userUri) {
+Uri _createUri(String userUri) {
var uri = Uri.parse(userUri);
- if (_logBuiltin) {
- _print('# Getting file path from: $uri');
- }
-
- var path;
switch (uri.scheme) {
case '':
case 'file':
- return uri.toFilePath();
- case 'package':
- return _filePathFromUri(_resolvePackageUri(uri).toString());
case 'http':
case 'https':
- return uri.toString();
+ return uri;
+ case 'package':
+ return _resolvePackageUri(uri);
default:
- // Only handling file, http, and package URIs
+ // Only handling file, http[s], and package URIs
// in standalone binary.
if (_logBuiltin) {
_print('# Unknown scheme (${uri.scheme}) in $uri.');
@@ -190,124 +298,127 @@ String _filePathFromUri(String userUri) {
}
}
-
-Uri _resolvePackageUri(Uri uri) {
- 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'.";
+int _numOutstandingLoadRequests = 0;
+void _finishedOneLoadRequest(String uri) {
+ assert(_numOutstandingLoadRequests > 0);
+ _numOutstandingLoadRequests--;
+ if (_logBuiltin) {
+ _print("Loading of $uri finished, "
+ "${_numOutstandingLoadRequests} requests remaining");
+ }
+ if (_numOutstandingLoadRequests == 0) {
+ _signalDoneLoading();
+ _cleanup();
}
-
- var packageRoot = _packageRoot == null ?
- _entryPointScript.resolve('packages/') :
- _packageRoot;
- return packageRoot.resolve(uri.path);
}
-
-int _numOutstandingLoadRequests = 0;
-var _httpClient;
-
-void _httpGet(Uri uri, String libraryUri, loadCallback(List<int> data)) {
- if (_httpClient == null) {
- _httpClient = new HttpClient()..maxConnectionsPerHost = 6;
+void _startingOneLoadRequest(String uri) {
+ assert(_numOutstandingLoadRequests >= 0);
+ _numOutstandingLoadRequests++;
+ if (_logBuiltin) {
+ _print("Loading of $uri started, "
+ "${_numOutstandingLoadRequests} requests outstanding");
}
- _httpClient.getUrl(uri)
- .then((HttpClientRequest request) => request.close())
- .then((HttpClientResponse response) {
- var builder = new BytesBuilder(copy: false);
- response.listen(
- builder.add,
- onDone: () {
- if (response.statusCode != 200) {
- var msg = 'Failure getting $uri: '
- '${response.statusCode} ${response.reasonPhrase}';
- _asyncLoadError(uri.toString(), libraryUri, msg);
- }
- loadCallback(builder.takeBytes());
- },
- onError: (error) {
- _asyncLoadError(uri.toString(), libraryUri, error);
- });
- })
- .catchError((error) {
- _asyncLoadError(uri.toString(), libraryUri, error);
- });
- // TODO(floitsch): remove this line. It's just here to push an event on the
- // event loop so that we invoke the scheduled microtasks. Also remove the
- // import of dart:async when this line is not needed anymore.
- Timer.run(() {});
}
+class LoadError extends Error {
+ final String message;
+ LoadError(this.message);
-void _signalDoneLoading() native "Builtin_DoneLoading";
-
-void _cleanup() {
- if (_httpClient != null) {
- _httpClient.close();
- _httpClient = null;
- }
+ String toString() => 'Load Error: $message';
}
+void _signalDoneLoading() native "Builtin_DoneLoading";
void _loadScriptCallback(int tag, String uri, String libraryUri, List<int> data)
native "Builtin_LoadScript";
+void _asyncLoadErrorCallback(uri, libraryUri, error)
+ native "Builtin_AsyncLoadError";
void _loadScript(int tag, String uri, String libraryUri, List<int> data) {
// TODO: Currently a compilation error while loading the script is
// fatal for the isolate. _loadScriptCallback() does not return and
// the _numOutstandingLoadRequests counter remains out of sync.
_loadScriptCallback(tag, uri, libraryUri, data);
- assert(_numOutstandingLoadRequests > 0);
- _numOutstandingLoadRequests--;
+ _finishedOneLoadRequest(uri);
+}
+
+void _asyncLoadError(tag, uri, libraryUri, error) {
if (_logBuiltin) {
- _print("native Builtin_LoadScript($uri) completed, "
- "${_numOutstandingLoadRequests} requests remaining");
+ _print("_asyncLoadError($uri), error: $error");
}
- if (_numOutstandingLoadRequests == 0) {
- _signalDoneLoading();
- _cleanup();
+ if (tag == Dart_kImportTag) {
+ // When importing a library, the libraryUri is the imported
+ // uri.
+ libraryUri = uri;
}
+ _asyncLoadErrorCallback(uri, libraryUri, new LoadError(error));
+ _finishedOneLoadRequest(uri);
}
-void _asyncLoadErrorCallback(uri, libraryUri, error)
- native "Builtin_AsyncLoadError";
+_loadDataAsyncLoadPort(int tag,
+ String uri,
+ String libraryUri,
+ Uri resourceUri) {
+ var receivePort = new ReceivePort();
+ receivePort.first.then((dataOrError) {
+ if (dataOrError is List<int>) {
+ _loadScript(tag, uri, libraryUri, dataOrError);
+ } else {
+ _asyncLoadError(tag, uri, libraryUri, dataOrError);
+ }
+ }).catchError((e) {
+ _asyncLoadError(tag, uri, libraryUri, e.toString());
+ });
+
+ try {
+ var msg = [receivePort.sendPort, resourceUri.toString()];
+ _loadPort.send(msg);
+ _startingOneLoadRequest(uri);
+ } catch (e) {
+ if (_logBuiltin) {
+ _print("Exception when communicating with service isolate: $e");
+ }
+ _asyncLoadError(tag, uri, libraryUri, e.toString());
+ receivePort.close();
+ }
+}
-void _asyncLoadError(uri, libraryUri, error) {
- assert(_numOutstandingLoadRequests > 0);
- if (_logBuiltin) {
- _print("_asyncLoadError($uri), error: $error");
+// Asynchronously loads script data through a http[s] or file uri.
+_loadDataAsync(int tag, String uri, String libraryUri) {
+ if (tag == Dart_kScriptTag) {
+ uri = _resolveScriptUri(uri);
}
- _numOutstandingLoadRequests--;
- _asyncLoadErrorCallback(uri, libraryUri, error);
- if (_numOutstandingLoadRequests == 0) {
- _signalDoneLoading();
- _cleanup();
+
+ Uri resourceUri = _createUri(uri);
+
+ if (_load_via_service_isolate) {
+ _loadDataAsyncLoadPort(tag, uri, libraryUri, resourceUri);
+ } else {
+ _loadDataAsyncDartIO(tag, uri, libraryUri, resourceUri);
}
-}
+}
-// Create a Uri of 'userUri'. If the input uri is a package uri, then the
-// package uri is resolved.
-Uri _createUri(String userUri) {
+// Returns either a file path or a URI starting with http[s]:, as a String.
+String _filePathFromUri(String userUri) {
var uri = Uri.parse(userUri);
if (_logBuiltin) {
- _print('# Creating uri for: $uri');
+ _print('# Getting file path from: $uri');
}
+ var path;
switch (uri.scheme) {
case '':
case 'file':
+ return uri.toFilePath();
+ case 'package':
+ return _filePathFromUri(_resolvePackageUri(uri).toString());
case 'http':
case 'https':
- return uri;
- case 'package':
- return _resolvePackageUri(uri);
+ return uri.toString();
default:
- // Only handling file, http[s], and package URIs
+ // Only handling file, http, and package URIs
// in standalone binary.
if (_logBuiltin) {
_print('# Unknown scheme (${uri.scheme}) in $uri.');
@@ -316,30 +427,15 @@ Uri _createUri(String userUri) {
}
}
+String _nativeLibraryExtension() native "Builtin_NativeLibraryExtension";
-// Asynchronously loads script data through a http[s] or file uri.
-_loadDataAsync(int tag, String uri, String libraryUri) {
- if (tag == null) {
- uri = _resolveScriptUri(uri);
- }
- Uri resourceUri = _createUri(uri);
- _numOutstandingLoadRequests++;
- if (_logBuiltin) {
- _print("_loadDataAsync($uri), "
- "${_numOutstandingLoadRequests} requests outstanding");
- }
- if ((resourceUri.scheme == 'http') || (resourceUri.scheme == 'https')) {
- _httpGet(resourceUri, libraryUri, (data) {
- _loadScript(tag, uri, libraryUri, data);
- });
+String _platformExtensionFileName(String name) {
+ var extension = _nativeLibraryExtension();
+
+ if (_isWindows) {
+ return '$name.$extension';
} else {
- var sourceFile = new File(resourceUri.toFilePath());
- sourceFile.readAsBytes().then((data) {
- _loadScript(tag, uri, libraryUri, data);
- },
- onError: (e) {
- _asyncLoadError(uri, libraryUri, e);
- });
+ return 'lib$name.$extension';
}
}
@@ -358,7 +454,7 @@ _extensionPathFromUri(String userUri) {
throw 'Unexpected internal error: Extension URI $userUri contains \\';
}
- String filename;
+
String name;
String path; // Will end in '/'.
int index = userUri.lastIndexOf('/');
@@ -373,19 +469,7 @@ _extensionPathFromUri(String userUri) {
}
path = _filePathFromUri(path);
-
- if (Platform.isLinux || Platform.isAndroid) {
- filename = 'lib$name.so';
- } else if (Platform.isMacOS) {
- filename = 'lib$name.dylib';
- } else if (Platform.isWindows) {
- filename = '$name.dll';
- } else {
- if (_logBuiltin) {
- _print('Native extensions not supported on ${Platform.operatingSystem}');
- }
- throw 'Native extensions not supported on ${Platform.operatingSystem}';
- }
+ var filename = _platformExtensionFileName(name);
return [path, filename, name];
}
« no previous file with comments | « runtime/bin/builtin.cc ('k') | runtime/bin/builtin_common.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698