Index: dart/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart |
diff --git a/dart/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart b/dart/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart |
index ebbb9fd02a566663cd58f7f630b8ba1387d653ff..59ea2eb8640b7f4b638a19162ba5c1c860d86c6f 100644 |
--- a/dart/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart |
+++ b/dart/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart |
@@ -107,7 +107,9 @@ void startRootIsolate(entry) { |
* [_ManagerStub] - A handle held within one manager that allows interaction |
* with another manager. A target manager may be addressed by zero or more |
* [_ManagerStub]s. |
- * |
+ * TODO(ahe): The _ManagerStub concept is broken. It was an attempt |
+ * to create a common interface between the native Worker class and |
+ * _MainManagerStub. |
*/ |
/** |
@@ -183,10 +185,10 @@ class _Manager { |
Map<int, _IsolateContext> isolates; |
/** Reference to the main [_Manager]. Null in the main [_Manager] itself. */ |
- _ManagerStub mainManager; |
+ _MainManagerStub mainManager; |
- /** Registry of active [_ManagerStub]s. Only used in the main [_Manager]. */ |
- Map<int, _ManagerStub> managers; |
+ /// Registry of active Web Workers. Only used in the main [_Manager]. |
+ Map<int, dynamic /* Worker */> managers; |
/** The entry point given by [startRootIsolate]. */ |
final Function entry; |
@@ -195,7 +197,7 @@ class _Manager { |
_nativeDetectEnvironment(); |
topEventLoop = new _EventLoop(); |
isolates = new Map<int, _IsolateContext>(); |
- managers = new Map<int, _ManagerStub>(); |
+ managers = new Map<int, dynamic>(); |
if (isWorker) { // "if we are not the main manager ourself" is the intent. |
mainManager = new _MainManagerStub(); |
_nativeInitWorkerMessageHandler(); |
@@ -390,41 +392,17 @@ class _IsolateEvent { |
} |
} |
-/** An interface for a stub used to interact with a manager. */ |
-abstract class _ManagerStub { |
- get id; |
- void set id(int i); |
- void set onmessage(Function f); |
- void postMessage(msg); |
- void terminate(); |
-} |
- |
/** A stub for interacting with the main manager. */ |
-class _MainManagerStub implements _ManagerStub { |
- get id => 0; |
- void set id(int i) { throw new UnimplementedError(); } |
- void set onmessage(f) { |
- throw new Exception("onmessage should not be set on MainManagerStub"); |
- } |
+class _MainManagerStub { |
void postMessage(msg) { |
- JS("void", r"#.postMessage(#)", globalThis, msg); |
+ // "self" is a way to refer to the global context object that |
+ // works in HTML pages and in Web Workers. It does not work in d8 |
+ // and Firefox jsshell, because that would have been too easy. |
+ // |
+ // See: http://www.w3.org/TR/workers/#the-global-scope |
+ // and: http://www.w3.org/TR/Window/#dfn-self-attribute |
+ JS("void", r"self.postMessage(#)", msg); |
} |
- void terminate() {} // Nothing useful to do here. |
-} |
- |
-/** |
- * A stub for interacting with a manager built on a web worker. This |
- * definition uses a 'hidden' type (* prefix on the native name) to |
- * enforce that the type is defined dynamically only when web workers |
- * are actually available. |
- */ |
-// @Native("*Worker"); |
-class _WorkerStub implements _ManagerStub { |
- get id => JS("", "#.id", this); |
- void set id(i) { JS("void", "#.id = #", this, i); } |
- void set onmessage(f) { JS("void", "#.onmessage = #", this, f); } |
- void postMessage(msg) { JS("void", "#.postMessage(#)", this, msg); } |
- void terminate() { JS("void", "#.terminate()", this); } |
} |
const String _SPAWNED_SIGNAL = "spawned"; |
@@ -439,6 +417,9 @@ class IsolateNatives { |
static String thisScript = computeThisScript(); |
+ /// Associates an ID with a native worker object. |
+ static final Expando<int> workerIds = new Expando<int>(); |
+ |
/** |
* The src url for the script tag that loaded this code. Used to create |
* JavaScript workers. |
@@ -488,9 +469,6 @@ class IsolateNatives { |
static computeGlobalThis() => JS('', 'function() { return this; }()'); |
- /** Starts a new worker with the given URL. */ |
- static _WorkerStub _newWorker(url) => JS("_WorkerStub", r"new Worker(#)", url); |
- |
/** |
* Assume that [e] is a browser message event and extract its message data. |
* We don't import the dom explicitly so, when workers are disabled, this |
@@ -502,7 +480,7 @@ class IsolateNatives { |
* Process messages on a worker, either to control the worker instance or to |
* pass messages along to the isolate running in the worker. |
*/ |
- static void _processWorkerMessage(sender, e) { |
+ static void _processWorkerMessage(/* Worker */ sender, e) { |
var msg = _deserializeMessage(_getEventData(e)); |
switch (msg['command']) { |
case 'start': |
@@ -537,9 +515,8 @@ class IsolateNatives { |
_globalState.topEventLoop.run(); |
break; |
case 'close': |
- _log("Closing Worker"); |
- _globalState.managers.remove(sender.id); |
- sender.terminate(); |
+ _globalState.managers.remove(workerIds[sender]); |
+ JS('void', '#.terminate()', sender); |
_globalState.topEventLoop.run(); |
break; |
case 'log': |
@@ -675,24 +652,26 @@ class IsolateNatives { |
*/ |
static void _spawnWorker(functionName, uri, replyPort) { |
if (uri == null) uri = thisScript; |
- final worker = _newWorker(uri); |
- worker.onmessage = JS('', |
- 'function(e) { #(#, e); }', |
- DART_CLOSURE_TO_JS(_processWorkerMessage), |
- worker); |
+ final worker = JS('var', 'new Worker(#)', uri); |
+ |
+ var processWorkerMessageTrampoline = |
+ JS('', 'function(e) { #(#, 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. |
- worker.id = workerId; |
+ workerIds[worker] = workerId; |
_globalState.managers[workerId] = worker; |
- worker.postMessage(_serializeMessage({ |
- 'command': 'start', |
- 'id': workerId, |
- // Note: we serialize replyPort twice because the child worker needs to |
- // first deserialize the worker id, before it can correctly deserialize |
- // the port (port deserialization is sensitive to what is the current |
- // workerId). |
- 'replyTo': _serializeMessage(replyPort), |
- 'functionName': functionName })); |
+ JS('void', '#.postMessage(#)', worker, _serializeMessage({ |
+ 'command': 'start', |
+ 'id': workerId, |
+ // Note: we serialize replyPort twice because the child worker needs to |
+ // first deserialize the worker id, before it can correctly deserialize |
+ // the port (port deserialization is sensitive to what is the current |
+ // workerId). |
+ 'replyTo': _serializeMessage(replyPort), |
+ 'functionName': functionName })); |
} |
} |
@@ -807,9 +786,9 @@ class _WorkerSendPort extends _BaseSendPort implements SendPort { |
_globalState.mainManager.postMessage(workerMessage); |
} else { |
// Deliver the message only if the worker is still alive. |
- _ManagerStub manager = _globalState.managers[_workerId]; |
+ /* Worker */ var manager = _globalState.managers[_workerId]; |
if (manager != null) { |
- manager.postMessage(workerMessage); |
+ JS('void', '#.postMessage(#)', manager, workerMessage); |
} |
} |
}); |