| Index: frog/lib/isolate_serialization.dart
|
| diff --git a/frog/lib/isolate_serialization.dart b/frog/lib/isolate_serialization.dart
|
| index 52e978f5dd8bda75e8c9cea55fd65c95ff34f5ae..d836e2f0a5d66ea88e848be7bf125948c8396382 100644
|
| --- a/frog/lib/isolate_serialization.dart
|
| +++ b/frog/lib/isolate_serialization.dart
|
| @@ -2,6 +2,10 @@
|
| // 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);
|
| @@ -9,6 +13,7 @@ class MessageTraverser {
|
|
|
| MessageTraverser();
|
|
|
| + /** Visitor's entry point. */
|
| traverse(var x) {
|
| if (isPrimitive(x)) return visitPrimitive(x);
|
| _taggedObjects = new List();
|
| @@ -21,6 +26,7 @@ class MessageTraverser {
|
| 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++) {
|
| @@ -29,11 +35,13 @@ class MessageTraverser {
|
| _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);
|
| }
|
| @@ -58,11 +66,17 @@ class MessageTraverser {
|
|
|
| List _taggedObjects;
|
|
|
| - _clearAttachedInfo(var obj) native;
|
| - _setAttachedInfo(var o, var info) native;
|
| - _getAttachedInfo(var o) native;
|
| + _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();
|
|
|
| @@ -73,6 +87,7 @@ class Copier extends MessageTraverser {
|
| 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);
|
| @@ -110,6 +125,7 @@ class Copier extends MessageTraverser {
|
| }
|
| }
|
|
|
| +/** Visitor that serializes a message as a JSON array. */
|
| class Serializer extends MessageTraverser {
|
| Serializer() : super();
|
|
|
| @@ -117,32 +133,29 @@ class Serializer extends MessageTraverser {
|
|
|
| visitList(List list) {
|
| int copyId = _getInfo(list);
|
| - if (copyId !== null) return _makeRef(copyId);
|
| + if (copyId !== null) return ['ref', copyId];
|
|
|
| int id = _nextFreeRefId++;
|
| _attachInfo(list, id);
|
| - var jsArray = _serializeDartListIntoNewJsArray(list);
|
| + var jsArray = _serializeList(list);
|
| // TODO(floitsch): we are losing the generic type.
|
| - return _dartListToJsArrayNoCopy(['list', id, jsArray]);
|
| + return ['list', id, jsArray];
|
| }
|
|
|
| visitMap(Map map) {
|
| int copyId = _getInfo(map);
|
| - if (copyId !== null) return _makeRef(copyId);
|
| + if (copyId !== null) return ['ref', copyId];
|
|
|
| int id = _nextFreeRefId++;
|
| _attachInfo(map, id);
|
| - var keys = _serializeDartListIntoNewJsArray(map.getKeys());
|
| - var values = _serializeDartListIntoNewJsArray(map.getValues());
|
| + var keys = _serializeList(map.getKeys());
|
| + var values = _serializeList(map.getValues());
|
| // TODO(floitsch): we are losing the generic type.
|
| - return _dartListToJsArrayNoCopy(['map', id, keys, values]);
|
| + return ['map', id, keys, values];
|
| }
|
|
|
| visitSendPort(SendPortImpl port) {
|
| - return _dartListToJsArrayNoCopy(['sendport',
|
| - port._workerId,
|
| - port._isolateId,
|
| - port._receivePortId]);
|
| + return ['sendport', port._workerId, port._isolateId, port._receivePortId];
|
| }
|
|
|
| visitReceivePort(ReceivePortImpl port) {
|
| @@ -153,26 +166,19 @@ class Serializer extends MessageTraverser {
|
| return visitSendPort(port.toSendPort());
|
| }
|
|
|
| - _serializeDartListIntoNewJsArray(List list) {
|
| + _serializeList(List list) {
|
| int len = list.length;
|
| - var jsArray = _newJsArray(len);
|
| + var result = new List(len);
|
| for (int i = 0; i < len; i++) {
|
| - _jsArrayIndexSet(jsArray, i, _dispatch(list[i]));
|
| + result[i] = _dispatch(list[i]);
|
| }
|
| - return jsArray;
|
| - }
|
| -
|
| - _makeRef(int id) {
|
| - return _dartListToJsArrayNoCopy(['ref', id]);
|
| + return result;
|
| }
|
|
|
| int _nextFreeRefId = 0;
|
| -
|
| - static _newJsArray(int len) native;
|
| - static _jsArrayIndexSet(jsArray, int index, val) native;
|
| - static _dartListToJsArrayNoCopy(List list) native;
|
| }
|
|
|
| +/** Deserializes arrays created with [Serializer]. */
|
| class Deserializer {
|
| Deserializer();
|
|
|
| @@ -189,8 +195,8 @@ class Deserializer {
|
|
|
| _deserializeHelper(x) {
|
| if (isPrimitive(x)) return x;
|
| - assert(_isJsArray(x));
|
| - switch (_jsArrayIndex(x, 0)) {
|
| + assert(x is List);
|
| + switch (x[0]) {
|
| case 'ref': return _deserializeRef(x);
|
| case 'list': return _deserializeList(x);
|
| case 'map': return _deserializeMap(x);
|
| @@ -200,18 +206,17 @@ class Deserializer {
|
| }
|
| }
|
|
|
| - _deserializeRef(x) {
|
| - int id = _jsArrayIndex(x, 1);
|
| + _deserializeRef(List x) {
|
| + int id = x[1];
|
| var result = _deserialized[id];
|
| assert(result !== null);
|
| return result;
|
| }
|
|
|
| - List _deserializeList(x) {
|
| - int id = _jsArrayIndex(x, 1);
|
| - var jsArray = _jsArrayIndex(x, 2);
|
| - assert(_isJsArray(jsArray));
|
| - List dartList = _jsArrayToDartListNoCopy(jsArray);
|
| + 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++) {
|
| @@ -220,42 +225,29 @@ class Deserializer {
|
| return dartList;
|
| }
|
|
|
| - Map _deserializeMap(x) {
|
| + Map _deserializeMap(List x) {
|
| Map result = new Map();
|
| - int id = _jsArrayIndex(x, 1);
|
| + int id = x[1];
|
| _deserialized[id] = result;
|
| - var keys = _jsArrayIndex(x, 2);
|
| - var values = _jsArrayIndex(x, 3);
|
| - assert(_isJsArray(keys));
|
| - assert(_isJsArray(values));
|
| - int len = _jsArrayLength(keys);
|
| - assert(len == _jsArrayLength(values));
|
| + 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(_jsArrayIndex(keys, i));
|
| - var value = _deserializeHelper(_jsArrayIndex(values, i));
|
| + var key = _deserializeHelper(keys[i]);
|
| + var value = _deserializeHelper(values[i]);
|
| result[key] = value;
|
| }
|
| return result;
|
| }
|
|
|
| - SendPort _deserializeSendPort(x) {
|
| - int workerId = _jsArrayIndex(x, 1);
|
| - int isolateId = _jsArrayIndex(x, 2);
|
| - int receivePortId = _jsArrayIndex(x, 3);
|
| + SendPort _deserializeSendPort(List x) {
|
| + int workerId = x[1];
|
| + int isolateId = x[2];
|
| + int receivePortId = x[3];
|
| return new SendPortImpl(workerId, isolateId, receivePortId);
|
| }
|
|
|
| - List _jsArrayToDartListNoCopy(a) {
|
| - // We rely on the fact that Dart-lists are directly mapped to Js-arrays.
|
| - // TODO(floitsch): can we do better here?
|
| - assert(a is List);
|
| - return a;
|
| - }
|
| -
|
| // TODO(floitsch): this should by Map<int, var> or Map<int, Dynamic>.
|
| - Map _deserialized;
|
| -
|
| - static bool _isJsArray(x) native;
|
| - static _jsArrayIndex(x, int index) native;
|
| - static int _jsArrayLength(x) native;
|
| + Map<int, Dynamic> _deserialized;
|
| }
|
|
|