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. |
Jennifer Messerly
2011/11/08 05:04:35
I'd add a TODO: we should get rid of a lot of this
jimhug
2011/11/08 15:39:01
+1 - But I'm also a little concerned about how we
|
+ */ |
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);"; |
jimhug
2011/11/08 15:39:01
I'm going to have to get you to explain (void 0) t
Siggi Cherem (dart-lang)
2011/11/08 17:56:42
void is an operator that produces the side effects
|
+ |
+ _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; |
} |