| 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
|
|
|