Index: samples/pond/dart_lib.html |
diff --git a/samples/pond/dart_lib.html b/samples/pond/dart_lib.html |
index 51cb4d7b03028fce5e4a15a60ff4e96ba873aeca..af0cb0e3a0abd4db40b51fdcbffd706316b8a7ad 100755 |
--- a/samples/pond/dart_lib.html |
+++ b/samples/pond/dart_lib.html |
@@ -13921,7 +13921,6 @@ class Collections { |
#source("../../corelib/src/future.dart"); |
#source("../../corelib/src/hashable.dart"); |
#source("../../corelib/src/int.dart"); |
-#source("../../corelib/src/isolate.dart"); |
#source("../../corelib/src/iterable.dart"); |
#source("../../corelib/src/iterator.dart"); |
#source("../../corelib/src/list.dart"); |
@@ -14072,9 +14071,6 @@ void _assert(var test, String text, String url, int line, int column) { |
#source("collections.dart"); |
#source("date_implementation.dart"); |
-#source("isolate.dart"); |
-#source("isolate_serialization.dart"); |
- |
#source("function_implementation.dart"); |
/** |
@@ -14802,939 +14798,6 @@ class _FunctionImplementation implements Function native "Function" { |
} |
</script> |
-<script type="application//inert" id="lib_isolate_dart"> |
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-/** |
- * A native object that is shared across isolates. This object is visible to all |
- * isolates running on the same worker (either UI or background web worker). |
- * |
- * This is code that is intended to 'escape' the isolate boundaries in order to |
- * implement the semantics of friendly isolates in JavaScript. Without this we |
- * would have been forced to implement more code (including the top-level event |
- * loop) in JavaScript itself. |
- */ |
-GlobalState get _globalState() native "return \$globalState;"; |
-set _globalState(GlobalState val) native "\$globalState = val;"; |
- |
-/** |
- * Wrapper that takes the dart entry point and runs it within an isolate. The |
- * frog compiler will inject a call of the form [: startRootIsolate(main); :] |
- * when it determines that this wrapping is needed. For single-isolate |
- * applications (e.g. hello world), this call is not emitted. |
- */ |
-void startRootIsolate(entry) { |
- _globalState = new GlobalState(); |
- |
- // Don't start the main loop again, if we are in a worker. |
- if (_globalState.isWorker) return; |
- final rootContext = new IsolateContext(); |
- _globalState.rootContext = rootContext; |
- _fillStatics(rootContext); |
- |
- // BUG(5151491): Setting currentContext should not be necessary, but |
- // because closures passed to the DOM as event handlers do not bind their |
- // isolate automatically we try to give them a reasonable context to live in |
- // by having a "default" isolate (the first one created). |
- _globalState.currentContext = rootContext; |
- |
- rootContext.eval(entry); |
- _globalState.topEventLoop.run(); |
-} |
- |
-void _fillStatics(context) native @""" |
- $globals = context.isolateStatics; |
- $static_init(); |
-"""; |
- |
-/** Global state associated with the current worker. See [_globalState]. */ |
-// TODO(sigmund): split in multiple classes: global, thread, main-worker states? |
-class GlobalState { |
- |
- /** Next available isolate id. */ |
- int nextIsolateId = 0; |
- |
- /** Worker id associated with this worker. */ |
- int currentWorkerId = 0; |
- |
- /** |
- * Next available worker id. Only used by the main worker to assign a unique |
- * id to each worker created by it. |
- */ |
- int nextWorkerId = 1; |
- |
- /** Context for the currently running [Isolate]. */ |
- IsolateContext currentContext = null; |
- |
- /** Context for the root [Isolate] that first run in this worker. */ |
- IsolateContext rootContext = null; |
- |
- /** The top-level event loop. */ |
- EventLoop topEventLoop; |
- |
- /** Whether this program is running in a background worker. */ |
- bool isWorker; |
- |
- /** Whether this program is running in a UI worker. */ |
- bool inWindow; |
- |
- /** Whether we support spawning workers. */ |
- bool supportsWorkers; |
- |
- /** |
- * Whether to use web workers when implementing isolates. Set to false for |
- * debugging/testing. |
- */ |
- bool get useWorkers() => supportsWorkers; |
- |
- /** |
- * Whether to use the web-worker JSON-based message serialization protocol. By |
- * default this is only used with web workers. For debugging, you can force |
- * using this protocol by changing this field value to [true]. |
- */ |
- bool get needSerialization() => useWorkers; |
- |
- /** |
- * Registry of isolates. Isolates must be registered if, and only if, receive |
- * ports are alive. Normally no open receive-ports means that the isolate is |
- * dead, but DOM callbacks could resurrect it. |
- */ |
- Map<int, IsolateContext> isolates; |
- |
- /** Reference to the main worker. */ |
- MainWorker mainWorker; |
- |
- /** Registry of active workers. Only used in the main worker. */ |
- Map<int, var> workers; |
- |
- GlobalState() { |
- topEventLoop = new EventLoop(); |
- isolates = {}; |
- workers = {}; |
- mainWorker = new MainWorker(); |
- _nativeInit(); |
- } |
- |
- void _nativeInit() native @""" |
- this.isWorker = typeof ($globalThis['importScripts']) != 'undefined'; |
- this.inWindow = typeof(window) !== 'undefined'; |
- this.supportsWorkers = this.isWorker || |
- ((typeof $globalThis['Worker']) != 'undefined'); |
- |
- // if workers are supported, treat this as a main worker: |
- if (this.supportsWorkers) { |
- $globalThis.onmessage = function(e) { |
- IsolateNatives._processWorkerMessage(this.mainWorker, e); |
- }; |
- } |
- """; |
- |
- /** |
- * Close the worker running this code, called when there is nothing else to |
- * run. |
- */ |
- void closeWorker() { |
- if (isWorker) { |
- if (!isolates.isEmpty()) return; |
- mainWorker.postMessage( |
- _serializeMessage({'command': 'close'})); |
- } else if (isolates.containsKey(rootContext.id) && workers.isEmpty() && |
- !supportsWorkers && !inWindow) { |
- // This should only trigger when running on the command-line. |
- // We don't want this check to execute in the browser where the isolate |
- // might still be alive due to DOM callbacks. |
- throw new Exception("Program exited with open ReceivePorts."); |
- } |
- } |
-} |
- |
-_serializeMessage(message) { |
- if (_globalState.needSerialization) { |
- return new Serializer().traverse(message); |
- } else { |
- return new Copier().traverse(message); |
- } |
-} |
- |
-_deserializeMessage(message) { |
- if (_globalState.needSerialization) { |
- return new Deserializer().deserialize(message); |
- } else { |
- // Nothing more to do. |
- return message; |
- } |
-} |
- |
-/** Default worker. */ |
-class MainWorker { |
- int id = 0; |
- void postMessage(msg) native "return \$globalThis.postMessage(msg);"; |
- void set onmessage(f) native "\$globalThis.onmessage = f;"; |
- void terminate() {} |
-} |
- |
-/** |
- * A web worker. This type is also defined in 'dart:dom', but we define it here |
- * to avoid introducing a dependency from corelib to dom. 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. |
- */ |
-class _Worker native "*Worker" { |
- get id() native "return this.id;"; |
- void set id(i) native "this.id = i;"; |
- void set onmessage(f) native "this.onmessage = f;"; |
- void postMessage(msg) native "return this.postMessage(msg);"; |
-} |
- |
-/** Context information tracked for each isolate. */ |
-class IsolateContext { |
- /** Current isolate id. */ |
- int id; |
- |
- /** Registry of receive ports currently active on this isolate. */ |
- Map<int, ReceivePort> ports; |
- |
- /** Holds isolate globals (statics and top-level properties). */ |
- var isolateStatics; // native object containing all globals of an isolate. |
- |
- IsolateContext() { |
- id = _globalState.nextIsolateId++; |
- ports = {}; |
- initGlobals(); |
- } |
- |
- // these are filled lazily the first time the isolate starts running. |
- void initGlobals() native 'this.isolateStatics = {};'; |
- |
- /** |
- * Run [code] in the context of the isolate represented by [this]. Note this |
- * is called from JavaScript (see $wrap_call in corejs.dart). |
- */ |
- void eval(Function code) { |
- var old = _globalState.currentContext; |
- _globalState.currentContext = this; |
- this._setGlobals(); |
- var result = null; |
- try { |
- result = code(); |
- } finally { |
- _globalState.currentContext = old; |
- if (old != null) old._setGlobals(); |
- } |
- return result; |
- } |
- |
- void _setGlobals() native @'$globals = this.isolateStatics;'; |
- |
- /** Lookup a port registered for this isolate. */ |
- ReceivePort lookup(int id) => ports[id]; |
- |
- /** Register a port on this isolate. */ |
- void register(int portId, ReceivePort port) { |
- if (ports.containsKey(portId)) { |
- throw new Exception("Registry: ports must be registered only once."); |
- } |
- ports[portId] = port; |
- _globalState.isolates[id] = this; // indicate this isolate is active |
- } |
- |
- /** Unregister a port on this isolate. */ |
- void unregister(int portId) { |
- ports.remove(portId); |
- if (ports.isEmpty()) { |
- _globalState.isolates.remove(id); // indicate this isolate is not active |
- } |
- } |
-} |
- |
-/** Represent the event loop on a javascript thread (DOM or worker). */ |
-class EventLoop { |
- Queue<IsolateEvent> events; |
- |
- EventLoop() : events = new Queue<IsolateEvent>(); |
- |
- void enqueue(isolate, fn, msg) { |
- events.addLast(new IsolateEvent(isolate, fn, msg)); |
- } |
- |
- IsolateEvent dequeue() { |
- if (events.isEmpty()) return null; |
- return events.removeFirst(); |
- } |
- |
- /** Process a single event, if any. */ |
- bool runIteration() { |
- final event = dequeue(); |
- if (event == null) { |
- _globalState.closeWorker(); |
- return false; |
- } |
- event.process(); |
- return true; |
- } |
- |
- /** Function equivalent to [:window.setTimeout:] when available, or null. */ |
- static Function _wrapSetTimeout() native """ |
- return typeof window != 'undefined' ? |
- function(a, b) { window.setTimeout(a, b); } : undefined; |
- """; |
- |
- /** |
- * Runs multiple iterations of the run-loop. If possible, each iteration is |
- * run asynchronously. |
- */ |
- void _runHelper() { |
- final setTimeout = _wrapSetTimeout(); |
- if (setTimeout != null) { |
- // Run each iteration from the browser's top event loop. |
- void next() { |
- if (!runIteration()) return; |
- setTimeout(next, 0); |
- } |
- next(); |
- } else { |
- // Run synchronously until no more iterations are available. |
- while (runIteration()) {} |
- } |
- } |
- |
- /** |
- * Call [_runHelper] but ensure that worker exceptions are propragated. Note |
- * this is called from JavaScript (see $wrap_call in corejs.dart). |
- */ |
- void run() { |
- if (!_globalState.isWorker) { |
- _runHelper(); |
- } else { |
- try { |
- _runHelper(); |
- } catch(var e, var trace) { |
- _globalState.mainWorker.postMessage(_serializeMessage( |
- {'command': 'error', 'msg': '$e\n$trace' })); |
- } |
- } |
- } |
-} |
- |
-/** An event in the top-level event queue. */ |
-class IsolateEvent { |
- IsolateContext isolate; |
- Function fn; |
- String message; |
- |
- IsolateEvent(this.isolate, this.fn, this.message); |
- |
- void process() { |
- isolate.eval(fn); |
- } |
-} |
- |
-/** Implementation of a send port on top of JavaScript. */ |
-class SendPortImpl implements SendPort { |
- |
- const SendPortImpl(this._workerId, this._isolateId, this._receivePortId); |
- |
- void send(var message, [SendPort replyTo = null]) { |
- if (replyTo !== null && !(replyTo is SendPortImpl)) { |
- throw "SendPort::send: Illegal replyTo type."; |
- } |
- IsolateNatives._sendMessage(_workerId, _isolateId, _receivePortId, |
- _serializeMessage(message), _serializeMessage(replyTo)); |
- } |
- |
- // TODO(sigmund): get rid of _sendNow (still used in corelib code) |
- void _sendNow(var message, replyTo) { send(message, replyTo); } |
- |
- ReceivePortSingleShotImpl call(var message) { |
- final result = new ReceivePortSingleShotImpl(); |
- this.send(message, result.toSendPort()); |
- return result; |
- } |
- |
- ReceivePortSingleShotImpl _callNow(var message) { |
- final result = new ReceivePortSingleShotImpl(); |
- send(message, result.toSendPort()); |
- return result; |
- } |
- |
- bool operator==(var other) { |
- return (other is SendPortImpl) && |
- (_workerId == other._workerId) && |
- (_isolateId == other._isolateId) && |
- (_receivePortId == other._receivePortId); |
- } |
- |
- int hashCode() { |
- return (_workerId << 16) ^ (_isolateId << 8) ^ _receivePortId; |
- } |
- |
- final int _receivePortId; |
- final int _isolateId; |
- final int _workerId; |
-} |
- |
-/** Default factory for receive ports. */ |
-class ReceivePortFactory { |
- |
- factory ReceivePort() { |
- return new ReceivePortImpl(); |
- } |
- |
- factory ReceivePort.singleShot() { |
- return new ReceivePortSingleShotImpl(); |
- } |
-} |
- |
-/** Implementation of a multi-use [ReceivePort] on top of JavaScript. */ |
-class ReceivePortImpl implements ReceivePort { |
- ReceivePortImpl() |
- : _id = _nextFreeId++ { |
- _globalState.currentContext.register(_id, this); |
- } |
- |
- void receive(void onMessage(var message, SendPort replyTo)) { |
- _callback = onMessage; |
- } |
- |
- void close() { |
- _callback = null; |
- _globalState.currentContext.unregister(_id); |
- } |
- |
- /** |
- * Returns a fresh [SendPort]. The implementation is not allowed to cache |
- * existing ports. |
- */ |
- SendPort toSendPort() { |
- return new SendPortImpl( |
- _globalState.currentWorkerId, _globalState.currentContext.id, _id); |
- } |
- |
- int _id; |
- Function _callback; |
- |
- static int _nextFreeId = 1; |
-} |
- |
-/** Implementation of a single-shot [ReceivePort]. */ |
-class ReceivePortSingleShotImpl implements ReceivePort { |
- |
- ReceivePortSingleShotImpl() : _port = new ReceivePortImpl() { } |
- |
- void receive(void callback(var message, SendPort replyTo)) { |
- _port.receive((var message, SendPort replyTo) { |
- _port.close(); |
- callback(message, replyTo); |
- }); |
- } |
- |
- void close() { |
- _port.close(); |
- } |
- |
- SendPort toSendPort() => _port.toSendPort(); |
- |
- final ReceivePortImpl _port; |
-} |
- |
-final String _SPAWNED_SIGNAL = "spawned"; |
- |
-class IsolateNatives { |
- |
- /** JavaScript-specific implementation to spawn an isolate. */ |
- static Future<SendPort> spawn(Isolate isolate, bool isLight) { |
- Completer<SendPort> completer = new Completer<SendPort>(); |
- ReceivePort port = new ReceivePort.singleShot(); |
- port.receive((msg, SendPort replyPort) { |
- assert(msg == _SPAWNED_SIGNAL); |
- completer.complete(replyPort); |
- }); |
- |
- // TODO(floitsch): throw exception if isolate's class doesn't have a |
- // default constructor. |
- if (_globalState.useWorkers && !isLight) { |
- _startWorker(isolate, port.toSendPort()); |
- } else { |
- _startNonWorker(isolate, port.toSendPort()); |
- } |
- |
- return completer.future; |
- } |
- |
- static SendPort _startWorker(Isolate runnable, SendPort replyPort) { |
- var factoryName = _getJSConstructorName(runnable); |
- if (_globalState.isWorker) { |
- _globalState.mainWorker.postMessage(_serializeMessage({ |
- 'command': 'spawn-worker', |
- 'factoryName': factoryName, |
- 'replyPort': replyPort})); |
- } else { |
- _spawnWorker(factoryName, _serializeMessage(replyPort)); |
- } |
- } |
- |
- |
- /** |
- * The src url for the script tag that loaded this code. Used to create |
- * JavaScript workers. |
- */ |
- static String get _thisScript() => |
- _thisScriptCache != null ? _thisScriptCache : _computeThisScript(); |
- |
- static String _thisScriptCache; |
- |
- // TODO(sigmund): fix - this code should be run synchronously when loading the |
- // script. Running lazily on DOMContentLoaded will yield incorrect results. |
- static String _computeThisScript() native @""" |
- if (!$globalState.supportsWorkers || $globalState.isWorker) return null; |
- |
- // TODO(5334778): Find a cross-platform non-brittle way of getting the |
- // currently running script. |
- var scripts = document.getElementsByTagName('script'); |
- // The scripts variable only contains the scripts that have already been |
- // executed. The last one is the currently running script. |
- var script = scripts[scripts.length - 1]; |
- var src = script && script.src; |
- if (!src) { |
- // TODO() |
- src = "FIXME:5407062" + "_" + Math.random().toString(); |
- if (script) script.src = src; |
- } |
- IsolateNatives._thisScriptCache = src; |
- return src; |
- """; |
- |
- /** Starts a new worker with the given URL. */ |
- static _Worker _newWorker(url) native "return new Worker(url);"; |
- |
- /** |
- * Spawns an isolate in a worker. [factoryName] is the Javascript constructor |
- * name for the isolate entry point class. |
- */ |
- static void _spawnWorker(factoryName, serializedReplyPort) { |
- final worker = _newWorker(_thisScript); |
- worker.onmessage = (e) { _processWorkerMessage(worker, e); }; |
- var workerId = _globalState.nextWorkerId++; |
- // We also store the id on the worker itself so that we can unregister it. |
- worker.id = workerId; |
- _globalState.workers[workerId] = worker; |
- worker.postMessage(_serializeMessage({ |
- 'command': 'start', |
- 'id': workerId, |
- 'replyTo': serializedReplyPort, |
- 'factoryName': factoryName })); |
- } |
- |
- /** |
- * 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 |
- * library can also run on top of nodejs. |
- */ |
- static _getEventData(e) native "return e.data"; |
- |
- /** |
- * 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) { |
- var msg = _deserializeMessage(_getEventData(e)); |
- switch (msg['command']) { |
- case 'start': |
- _globalState.currentWorkerId = msg['id']; |
- var runnerObject = |
- _allocate(_getJSConstructorFromName(msg['factoryName'])); |
- var serializedReplyTo = msg['replyTo']; |
- _globalState.topEventLoop.enqueue(new IsolateContext(), function() { |
- var replyTo = _deserializeMessage(serializedReplyTo); |
- IsolateNatives._startIsolate(runnerObject, replyTo); |
- }, 'worker-start'); |
- _globalState.topEventLoop.run(); |
- break; |
- case 'spawn-worker': |
- _spawnWorker(msg['factoryName'], msg['replyPort']); |
- break; |
- case 'message': |
- _sendMessage(msg['workerId'], msg['isolateId'], msg['portId'], |
- msg['msg'], msg['replyTo']); |
- _globalState.topEventLoop.run(); |
- break; |
- case 'close': |
- _log("Closing Worker"); |
- _globalState.workers.remove(sender.id); |
- sender.terminate(); |
- _globalState.topEventLoop.run(); |
- break; |
- case 'log': |
- _log(msg['msg']); |
- break; |
- case 'print': |
- if (_globalState.isWorker) { |
- _globalState.mainWorker.postMessage( |
- _serializeMessage({'command': 'print', 'msg': msg})); |
- } else { |
- print(msg['msg']); |
- } |
- break; |
- case 'error': |
- throw msg['msg']; |
- } |
- } |
- |
- /** Log a message, forwarding to the main worker if appropriate. */ |
- static _log(msg) { |
- if (_globalState.isWorker) { |
- _globalState.mainWorker.postMessage( |
- _serializeMessage({'command': 'log', 'msg': msg })); |
- } else { |
- try { |
- _consoleLog(msg); |
- } catch(e, trace) { |
- throw new Exception(trace); |
- } |
- } |
- } |
- |
- static void _consoleLog(msg) native "\$globalThis.console.log(msg);"; |
- |
- |
- /** |
- * Extract the constructor of runnable, so it can be allocated in another |
- * isolate. |
- */ |
- static var _getJSConstructor(Isolate runnable) native """ |
- return runnable.constructor; |
- """; |
- |
- /** Extract the constructor name of a runnable */ |
- // TODO(sigmund): find a browser-generic way to support this. |
- static var _getJSConstructorName(Isolate runnable) native """ |
- return runnable.constructor.name; |
- """; |
- |
- /** Find a constructor given it's name. */ |
- static var _getJSConstructorFromName(String factoryName) native """ |
- return \$globalThis[factoryName]; |
- """; |
- |
- /** Create a new JavasSript object instance given it's constructor. */ |
- static var _allocate(var ctor) native "return new ctor();"; |
- |
- /** Starts a non-worker isolate. */ |
- static SendPort _startNonWorker(Isolate runnable, SendPort replyTo) { |
- // Spawn a new isolate and create the receive port in it. |
- final spawned = new IsolateContext(); |
- |
- // Instead of just running the provided runnable, we create a |
- // new cloned instance of it with a fresh state in the spawned |
- // isolate. This way, we do not get cross-isolate references |
- // through the runnable. |
- final ctor = _getJSConstructor(runnable); |
- _globalState.topEventLoop.enqueue(spawned, function() { |
- _startIsolate(_allocate(ctor), replyTo); |
- }, 'nonworker start'); |
- } |
- |
- /** Given a ready-to-start runnable, start running it. */ |
- static void _startIsolate(Isolate isolate, SendPort replyTo) { |
- _fillStatics(_globalState.currentContext); |
- ReceivePort port = new ReceivePort(); |
- replyTo.send(_SPAWNED_SIGNAL, port.toSendPort()); |
- isolate._run(port); |
- } |
- |
- static void _sendMessage(int workerId, int isolateId, int receivePortId, |
- message, replyTo) { |
- // Both the message and the replyTo are already serialized. |
- if (workerId == _globalState.currentWorkerId) { |
- var isolate = _globalState.isolates[isolateId]; |
- if (isolate == null) return; // Isolate has been closed. |
- var receivePort = isolate.lookup(receivePortId); |
- if (receivePort == null) return; // ReceivePort has been closed. |
- _globalState.topEventLoop.enqueue(isolate, () { |
- if (receivePort._callback != null) { |
- receivePort._callback( |
- _deserializeMessage(message), _deserializeMessage(replyTo)); |
- } |
- }, 'receive ' + message); |
- } else { |
- var worker; |
- // communication between workers go through the main worker |
- if (_globalState.isWorker) { |
- worker = _globalState.mainWorker; |
- } else { |
- // TODO(sigmund): make sure this works |
- worker = _globalState.workers[workerId]; |
- } |
- worker.postMessage(_serializeMessage({ |
- 'command': 'message', |
- 'workerId': workerId, |
- 'isolateId': isolateId, |
- 'portId': receivePortId, |
- 'msg': message, |
- 'replyTo': replyTo })); |
- } |
- } |
-} |
- |
-</script> |
-<script type="application//inert" id="lib_isolate_serialization_dart"> |
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-/** |
- * Abstract visitor for dart objects that can be passed as messages between any |
- * isolates. |
- */ |
-class MessageTraverser { |
- static bool isPrimitive(x) { |
- return (x === null) || (x is String) || (x is num) || (x is bool); |
- } |
- |
- MessageTraverser(); |
- |
- /** Visitor's entry point. */ |
- traverse(var x) { |
- if (isPrimitive(x)) return visitPrimitive(x); |
- _taggedObjects = new List(); |
- var result; |
- try { |
- result = _dispatch(x); |
- } finally { |
- _cleanup(); |
- } |
- return result; |
- } |
- |
- /** Remove all information injected in the native objects by this visitor. */ |
- void _cleanup() { |
- int len = _taggedObjects.length; |
- for (int i = 0; i < len; i++) { |
- _clearAttachedInfo(_taggedObjects[i]); |
- } |
- _taggedObjects = null; |
- } |
- |
- /** Injects into the native object some information used by the visitor. */ |
- void _attachInfo(var o, var info) { |
- _taggedObjects.add(o); |
- _setAttachedInfo(o, info); |
- } |
- |
- /** Retrieves any information stored in the native object [o]. */ |
- _getInfo(var o) { |
- return _getAttachedInfo(o); |
- } |
- |
- _dispatch(var x) { |
- if (isPrimitive(x)) return visitPrimitive(x); |
- if (x is List) return visitList(x); |
- if (x is Map) return visitMap(x); |
- if (x is SendPortImpl) return visitSendPort(x); |
- if (x is ReceivePortImpl) return visitReceivePort(x); |
- if (x is ReceivePortSingleShotImpl) return visitReceivePortSingleShot(x); |
- // TODO(floitsch): make this a real exception. (which one)? |
- throw "Message serialization: Illegal value $x passed"; |
- } |
- |
- abstract visitPrimitive(x); |
- abstract visitList(List x); |
- abstract visitMap(Map x); |
- abstract visitSendPort(SendPortImpl x); |
- abstract visitReceivePort(ReceivePortImpl x); |
- abstract visitReceivePortSingleShot(ReceivePortSingleShotImpl x); |
- |
- List _taggedObjects; |
- |
- _clearAttachedInfo(var o) native |
- "o['__MessageTraverser__attached_info__'] = (void 0);"; |
- |
- _setAttachedInfo(var o, var info) native |
- "o['__MessageTraverser__attached_info__'] = info;"; |
- |
- _getAttachedInfo(var o) native |
- "return o['__MessageTraverser__attached_info__'];"; |
-} |
- |
-/** A visitor that recursively copies a message. */ |
-class Copier extends MessageTraverser { |
- Copier() : super(); |
- |
- visitPrimitive(x) => x; |
- |
- List visitList(List list) { |
- List copy = _getInfo(list); |
- if (copy !== null) return copy; |
- |
- int len = list.length; |
- |
- // TODO(floitsch): we loose the generic type of the List. |
- copy = new List(len); |
- _attachInfo(list, copy); |
- for (int i = 0; i < len; i++) { |
- copy[i] = _dispatch(list[i]); |
- } |
- return copy; |
- } |
- |
- Map visitMap(Map map) { |
- Map copy = _getInfo(map); |
- if (copy !== null) return copy; |
- |
- // TODO(floitsch): we loose the generic type of the map. |
- copy = new Map(); |
- _attachInfo(map, copy); |
- map.forEach((key, val) { |
- copy[_dispatch(key)] = _dispatch(val); |
- }); |
- return copy; |
- } |
- |
- SendPort visitSendPort(SendPortImpl port) { |
- return new SendPortImpl(port._workerId, |
- port._isolateId, |
- port._receivePortId); |
- } |
- |
- SendPort visitReceivePort(ReceivePortImpl port) { |
- return port.toSendPort(); |
- } |
- |
- SendPort visitReceivePortSingleShot(ReceivePortSingleShotImpl port) { |
- return port.toSendPort(); |
- } |
-} |
- |
-/** Visitor that serializes a message as a JSON array. */ |
-class Serializer extends MessageTraverser { |
- Serializer() : super(); |
- |
- visitPrimitive(x) => x; |
- |
- visitList(List list) { |
- int copyId = _getInfo(list); |
- if (copyId !== null) return ['ref', copyId]; |
- |
- int id = _nextFreeRefId++; |
- _attachInfo(list, id); |
- var jsArray = _serializeList(list); |
- // TODO(floitsch): we are losing the generic type. |
- return ['list', id, jsArray]; |
- } |
- |
- visitMap(Map map) { |
- int copyId = _getInfo(map); |
- if (copyId !== null) return ['ref', copyId]; |
- |
- int id = _nextFreeRefId++; |
- _attachInfo(map, id); |
- var keys = _serializeList(map.getKeys()); |
- var values = _serializeList(map.getValues()); |
- // TODO(floitsch): we are losing the generic type. |
- return ['map', id, keys, values]; |
- } |
- |
- visitSendPort(SendPortImpl port) { |
- return ['sendport', port._workerId, port._isolateId, port._receivePortId]; |
- } |
- |
- visitReceivePort(ReceivePortImpl port) { |
- return visitSendPort(port.toSendPort());; |
- } |
- |
- visitReceivePortSingleShot(ReceivePortSingleShotImpl port) { |
- return visitSendPort(port.toSendPort()); |
- } |
- |
- _serializeList(List list) { |
- int len = list.length; |
- var result = new List(len); |
- for (int i = 0; i < len; i++) { |
- result[i] = _dispatch(list[i]); |
- } |
- return result; |
- } |
- |
- int _nextFreeRefId = 0; |
-} |
- |
-/** Deserializes arrays created with [Serializer]. */ |
-class Deserializer { |
- Deserializer(); |
- |
- static bool isPrimitive(x) { |
- return (x === null) || (x is String) || (x is num) || (x is bool); |
- } |
- |
- deserialize(x) { |
- if (isPrimitive(x)) return x; |
- // TODO(floitsch): this should be new HashMap<int, var|Dynamic>() |
- _deserialized = new HashMap(); |
- return _deserializeHelper(x); |
- } |
- |
- _deserializeHelper(x) { |
- if (isPrimitive(x)) return x; |
- assert(x is List); |
- switch (x[0]) { |
- case 'ref': return _deserializeRef(x); |
- case 'list': return _deserializeList(x); |
- case 'map': return _deserializeMap(x); |
- case 'sendport': return _deserializeSendPort(x); |
- // TODO(floitsch): Use real exception (which one?). |
- default: throw "Unexpected serialized object"; |
- } |
- } |
- |
- _deserializeRef(List x) { |
- int id = x[1]; |
- var result = _deserialized[id]; |
- assert(result !== null); |
- return result; |
- } |
- |
- List _deserializeList(List x) { |
- int id = x[1]; |
- // We rely on the fact that Dart-lists are directly mapped to Js-arrays. |
- List dartList = x[2]; |
- _deserialized[id] = dartList; |
- int len = dartList.length; |
- for (int i = 0; i < len; i++) { |
- dartList[i] = _deserializeHelper(dartList[i]); |
- } |
- return dartList; |
- } |
- |
- Map _deserializeMap(List x) { |
- Map result = new Map(); |
- int id = x[1]; |
- _deserialized[id] = result; |
- List keys = x[2]; |
- List values = x[3]; |
- int len = keys.length; |
- assert(len == values.length); |
- for (int i = 0; i < len; i++) { |
- var key = _deserializeHelper(keys[i]); |
- var value = _deserializeHelper(values[i]); |
- result[key] = value; |
- } |
- return result; |
- } |
- |
- SendPort _deserializeSendPort(List x) { |
- int workerId = x[1]; |
- int isolateId = x[2]; |
- int receivePortId = x[3]; |
- return new SendPortImpl(workerId, isolateId, receivePortId); |
- } |
- |
- // TODO(floitsch): this should by Map<int, var> or Map<int, Dynamic>. |
- Map<int, Dynamic> _deserialized; |
-} |
- |
-</script> |
<script type="application//inert" id="lib_json_frog_dart"> |
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
@@ -56402,189 +55465,6 @@ interface int extends num { |
} |
</script> |
-<script type="application//inert" id="src_isolate_dart"> |
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-// Dart core library. |
- |
-/** |
- * [SendPort]s are created from [ReceivePort]s. Any message sent through |
- * a [SendPort] is delivered to its respective [ReceivePort]. There might be |
- * many [SendPort]s for the same [ReceivePort]. |
- * |
- * [SendPort]s can be transmitted to other isolates. |
- */ |
-interface SendPort extends Hashable { |
- |
- /** |
- * Sends an asynchronous [message] to this send port. The message is |
- * copied to the receiving isolate. If the message contains any |
- * receive ports, they are translated to the corresponding send port |
- * before being transmitted. If specified, the [replyTo] port will be |
- * provided to the receiver to facilitate exchanging sequences of |
- * messages. |
- */ |
- void send(var message, [SendPort replyTo]); |
- |
- /** |
- * Creates a new single-shot receive port, sends a message to this |
- * send port with replyTo set to the opened port, and returns the |
- * receive port. |
- */ |
- ReceivePort call(var message); |
- |
- /** |
- * Tests whether [other] is a [SendPort] pointing to the same |
- * [ReceivePort] as this one. |
- */ |
- bool operator==(var other); |
- |
- /** |
- * Returns an immutable hash code for this send port that is |
- * consistent with the == operator. |
- */ |
- int hashCode(); |
- |
-} |
- |
- |
-/** |
- * [ReceivePort]s, together with [SendPort]s, are the only means of |
- * communication between isolates. [ReceivePort]s have a [:toSendPort:] method |
- * which returns a [SendPort]. Any message that is sent through this [SendPort] |
- * is delivered to the [ReceivePort] it has been created from. There, they are |
- * dispatched to the callback that has been registered on the receive port. |
- * |
- * A [ReceivePort] may have many [SendPort]s. |
- */ |
-interface ReceivePort default ReceivePortFactory { |
- |
- /** |
- * Opens a long-lived port for receiving messages. The returned port |
- * must be explicitly closed through [ReceivePort.close]. |
- */ |
- ReceivePort(); |
- |
- /** |
- * Opens a single-shot reply port. Once a message has been received |
- * on this port, it is automatically closed -- obviously without |
- * throwing the message away before it can be processed. This |
- * constructor is used indirectly through [SendPort.call]. |
- */ |
- ReceivePort.singleShot(); |
- |
- /** |
- * Sets up a callback function for receiving pending or future |
- * messages on this receive port. |
- */ |
- void receive(void callback(var message, SendPort replyTo)); |
- |
- /** |
- * Closes this receive port immediately. Pending messages will not |
- * be processed and it is impossible to re-open the port. Single-shot |
- * reply ports, such as those created through [SendPort.call], are |
- * automatically closed when the reply has been received. Multiple |
- * invocations of [close] are allowed but ignored. |
- */ |
- void close(); |
- |
- /** |
- * Creates a new send port that sends to this receive port. It is legal to |
- * create several [SendPort]s from the same [ReceivePort]. |
- */ |
- SendPort toSendPort(); |
- |
-} |
- |
-/** |
- * The [Isolate] class serves two purposes: (1) as template for spawning a new |
- * isolate, and (2) as entry-point for the newly spawned isolate. |
- * |
- * New isolates are spawned by sub-classing [Isolate] and then invoking |
- * [:spawn:] on the instance. This will spawn a new isolate, which creates a |
- * new instance of the class, initializes the instance's [port] field |
- * and invokes the instance method [main]. |
- * |
- * The new instance is created by invoking the default constructor of the |
- * class that served as template for spawning the new isolate. This means, that |
- * sub-classes must have a default constructor (i.e. no-argument constructor). |
- * |
- * Isolates may be "heavy" or "light". Heavy isolates live in their own thread, |
- * whereas "light" isolates live in the same thread as the isolate which spawned |
- * them. |
- */ |
-class Isolate { |
- |
- /** |
- * Redirects to [Isolate.light]. |
- */ |
- Isolate() : this.light(); |
- |
- /** |
- * Creates a new isolate-template for a light isolate. |
- */ |
- Isolate.light() : _isLight = true; |
- |
- /** |
- * Creates a new isolate-template for a heavy isolate. |
- */ |
- Isolate.heavy() : _isLight = false; |
- |
- /** |
- * Spawns a new isolate, using this instance as template. |
- * |
- * The new isolate lives in a new thread (for heavy templates) |
- * or in the same thread as the current isolate (for light templates), if |
- * possible. |
- * |
- * During the initialization of the new isolate a [ReceivePort] is created |
- * inside the new isolate and stored in the read-only field [port]. |
- * A corresponding [SendPort] is sent to the isolate that invoked [spawn]. |
- * Since spawning an isolate is an asynchronous operation this method returns |
- * a [Future] of this [SendPort]. |
- * |
- * A common pattern to instantiate new isolates is to enqueue the instructions |
- * using [Future.then]. |
- * [:myIsolate.spawn().then((SendPort port) { port.send('hi there'); });:] |
- */ |
- Future<SendPort> spawn() { |
- return IsolateNatives.spawn(this, _isLight); |
- } |
- |
- // The private run method is invoked with the receive port. Before |
- // main is invoked we store the port in a field so it can be |
- // accessed from subclasses of Isolate. |
- void _run(ReceivePort port) { |
- _port = port; |
- main(); |
- } |
- |
- /** |
- * When [Isolate]s are used as entry-points, the [port] field contains a |
- * [ReceivePort]. The isolate that initiated the spawn holds a corresponding |
- * [SendPort]. |
- * |
- * Note that isolates should generally close their [ReceivePort]s when they |
- * are done, including this port. |
- */ |
- ReceivePort get port() { |
- return _port; |
- } |
- |
- /** |
- * When isolates are created, an instance of the template's class is |
- * instantiated in the new isolate. After the [port] has been set up, this |
- * [main] method is invoked on the instance. |
- */ |
- abstract void main(); |
- |
- final bool _isLight; |
- ReceivePort _port; |
-} |
- |
-</script> |
<script type="application//inert" id="src_iterable_dart"> |
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |