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

Unified Diff: dart/sdk/lib/_internal/lib/isolate_helper.dart

Issue 292743019: Complete with error if Worker fails. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Merged with r36656 Created 6 years, 7 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 | « no previous file | dart/tests/isolate/isolate.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dart/sdk/lib/_internal/lib/isolate_helper.dart
diff --git a/dart/sdk/lib/_internal/lib/isolate_helper.dart b/dart/sdk/lib/_internal/lib/isolate_helper.dart
index cfb0a96d6b29e04db6760038aad96a41cd24c736..06176b2ac9c95fc10a6f6e67f13c2776d8de19e8 100644
--- a/dart/sdk/lib/_internal/lib/isolate_helper.dart
+++ b/dart/sdk/lib/_internal/lib/isolate_helper.dart
@@ -683,6 +683,7 @@ class _MainManagerStub {
}
const String _SPAWNED_SIGNAL = "spawned";
+const String _SPAWN_FAILED_SIGNAL = "spawn failed";
var globalThis = Primitives.computeGlobalThis();
var globalWindow = JS('', "#.window", globalThis);
@@ -802,10 +803,14 @@ class IsolateNatives {
_globalState.topEventLoop.run();
break;
case 'spawn-worker':
- _spawnWorker(msg['functionName'], msg['uri'],
- msg['args'], msg['msg'],
- msg['isSpawnUri'], msg['startPaused'],
- msg['replyPort']);
+ var replyPort = msg['replyPort'];
+ spawn(msg['functionName'], msg['uri'],
+ msg['args'], msg['msg'],
+ false, msg['isSpawnUri'], msg['startPaused']).then((msg) {
+ replyPort.send(msg);
+ }, onError: (String errorMessage) {
+ replyPort.send([_SPAWN_FAILED_SIGNAL, errorMessage]);
+ });
break;
case 'message':
SendPort port = msg['port'];
@@ -905,22 +910,28 @@ class IsolateNatives {
if (uri != null && uri.endsWith(".dart")) uri += ".js";
ReceivePort port = new ReceivePort();
- Future<List> result = port.first.then((msg) {
- assert(msg[0] == _SPAWNED_SIGNAL);
- return msg;
+ Completer<List> completer = new Completer();
+ port.first.then((msg) {
+ if (msg[0] == _SPAWNED_SIGNAL) {
+ completer.complete(msg);
+ } else {
+ assert(msg[0] == _SPAWN_FAILED_SIGNAL);
+ completer.completeError(msg[1]);
+ }
});
SendPort signalReply = port.sendPort;
if (_globalState.useWorkers && !isLight) {
- _startWorker(functionName, uri, args, message, isSpawnUri, startPaused,
- signalReply);
+ _startWorker(
+ functionName, uri, args, message, isSpawnUri, startPaused,
+ signalReply, (String message) => completer.completeError(message));
} else {
_startNonWorker(
functionName, uri, args, message, isSpawnUri, startPaused,
signalReply);
}
- return result;
+ return completer.future;
}
static void _startWorker(
@@ -928,7 +939,8 @@ class IsolateNatives {
List<String> args, message,
bool isSpawnUri,
bool startPaused,
- SendPort replyPort) {
+ SendPort replyPort,
+ void onError(String message)) {
if (_globalState.isWorker) {
_globalState.mainManager.postMessage(_serializeMessage({
'command': 'spawn-worker',
@@ -941,7 +953,7 @@ class IsolateNatives {
'replyPort': replyPort}));
} else {
_spawnWorker(functionName, uri, args, message,
- isSpawnUri, startPaused, replyPort);
+ isSpawnUri, startPaused, replyPort, onError);
}
}
@@ -1007,14 +1019,38 @@ class IsolateNatives {
List<String> args, message,
bool isSpawnUri,
bool startPaused,
- SendPort replyPort) {
+ SendPort replyPort,
+ void onError(String message)) {
if (uri == null) uri = thisScript;
final worker = JS('var', 'new Worker(#)', uri);
-
- var processWorkerMessageTrampoline =
- JS('', "(function (f, a) { return function (e) { f(a, e); }})(#, #)",
- DART_CLOSURE_TO_JS(_processWorkerMessage),
- worker);
+ // Trampolines are used when wanting to call a Dart closure from
+ // JavaScript. The helper function DART_CLOSURE_TO_JS only accepts
+ // top-level or static methods, and the trampoline allows us to capture
+ // arguments and values which can be passed to a static method.
+ final onerrorTrampoline = JS(
+ '',
+ '''
+(function (f, u, c) {
+ return function(e) {
+ return f(e, u, c)
+ }
+})(#, #, #)''',
+ DART_CLOSURE_TO_JS(workerOnError), uri, onError);
+ JS('void', '#.onerror = #', worker, onerrorTrampoline);
+
+ var processWorkerMessageTrampoline = JS(
+ '',
+ """
+(function (f, a) {
+ return function (e) {
+ // We can stop listening for errors when the first message is received as
+ // we only listen for messages to determine if the uri was bad.
+ e.onerror = null;
+ return f(a, e);
+ }
+})(#, #)""",
+ DART_CLOSURE_TO_JS(_processWorkerMessage),
+ worker);
JS('void', '#.onmessage = #', worker, processWorkerMessageTrampoline);
var workerId = _globalState.nextManagerId++;
// We also store the id on the worker itself so that we can unregister it.
@@ -1034,6 +1070,25 @@ class IsolateNatives {
'startPaused': startPaused,
'functionName': functionName }));
}
+
+ static bool workerOnError(
+ /* Event */ event,
+ String uri,
+ void onError(String message)) {
+ // Attempt to shut up the browser, as the error has been handled. Chrome
+ // ignores this :-(
+ JS('void', '#.preventDefault()', event);
+ String message = JS('String|Null', '#.message', event);
+ if (message == null) {
+ // Some browsers, including Chrome, fail to provide a proper error
+ // event.
+ message = 'Error spawning worker for $uri';
+ } else {
+ message = 'Error spawning worker for $uri ($message)';
+ }
+ onError(message);
+ return true;
+ }
}
/********************************************************
« no previous file with comments | « no previous file | dart/tests/isolate/isolate.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698