Chromium Code Reviews| Index: lib/isolate/frog/messages.dart |
| diff --git a/lib/isolate/frog/messages.dart b/lib/isolate/frog/messages.dart |
| index 595db85d017dd8cac1f7067f1111c58be94241d5..a994b5a891f361acfb1c28253fdeaeb503162689 100644 |
| --- a/lib/isolate/frog/messages.dart |
| +++ b/lib/isolate/frog/messages.dart |
| @@ -7,147 +7,45 @@ |
| /** Serialize [message] (or simulate serialization). */ |
| _serializeMessage(message) { |
| if (_globalState.needSerialization) { |
| - return new _Serializer().traverse(message); |
| + return new _JsSerializer().traverse(message); |
| } else { |
| - return new _Copier().traverse(message); |
| + return new _JsCopier().traverse(message); |
| } |
| } |
| /** Deserialize [message] (or simulate deserialization). */ |
| _deserializeMessage(message) { |
| if (_globalState.needSerialization) { |
| - return new _Deserializer().deserialize(message); |
| + return new _JsDeserializer().deserialize(message); |
| } else { |
| // Nothing more to do. |
| return message; |
| } |
| } |
| -/** Abstract visitor for dart objects that can be sent as isolate messages. */ |
| -class _MessageTraverser { |
| +class _JsSerializer extends _Serializer { |
| - List _taggedObjects; |
| + _JsSerializer() : super() { _visited = new _JsVisitedMap(); } |
| - _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); |
| + visitSendPort(SendPort x) { |
| if (x is _NativeJsSendPort) return visitNativeJsSendPort(x); |
| if (x is _WorkerSendPort) return visitWorkerSendPort(x); |
| if (x is _BufferingSendPort) return visitBufferingSendPort(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 visitNativeJsSendPort(_NativeJsSendPort x); |
| - abstract visitWorkerSendPort(_WorkerSendPort x); |
| - abstract visitBufferingSendPort(_BufferingSendPort x); |
| - |
| - _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__'];"; |
| - |
| - _visitNativeOrWorkerPort(SendPort p) { |
| - if (p is _NativeJsSendPort) return visitNativeJsSendPort(p); |
| - if (p is _WorkerSendPort) return visitWorkerSendPort(p); |
| throw "Illegal underlying port $p"; |
| } |
| - static bool isPrimitive(x) { |
| - return (x === null) || (x is String) || (x is num) || (x is bool); |
| - } |
| -} |
| - |
| - |
| -/** 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 visitNativeJsSendPort(_NativeJsSendPort port) { |
| - return new _NativeJsSendPort(port._receivePort, port._isolateId); |
| + visitNativeJsSendPort(_NativeJsSendPort port) { |
| + return ['sendport', _globalState.currentManagerId, |
| + port._isolateId, port._receivePort._id]; |
| } |
| - SendPort visitWorkerSendPort(_WorkerSendPort port) { |
| - return new _WorkerSendPort( |
| - port._workerId, port._isolateId, port._receivePortId); |
| + visitWorkerSendPort(_WorkerSendPort port) { |
| + return ['sendport', port._workerId, port._isolateId, port._receivePortId]; |
| } |
| - SendPort visitBufferingSendPort(_BufferingSendPort port) { |
| + visitBufferingSendPort(_BufferingSendPort port) { |
| if (port._port != null) { |
| - return _visitNativeOrWorkerPort(port._port); |
| + return visitSendPort(port._port); |
| } else { |
| // TODO(floitsch): Use real exception (which one?). |
| throw |
| @@ -155,51 +53,33 @@ class _Copier extends _MessageTraverser { |
| " ports are resolved at this point."; |
| } |
| } |
| -} |
| - |
| -/** Visitor that serializes a message as a JSON array. */ |
| -class _Serializer extends _MessageTraverser { |
| - int _nextFreeRefId = 0; |
| - |
| - _Serializer() : super(); |
|
vsm
2012/07/04 05:21:54
nit: extra newline
|
| - 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]; |
| - } |
| +class _JsCopier extends _Copier { |
| - visitMap(Map map) { |
| - int copyId = _getInfo(map); |
| - if (copyId !== null) return ['ref', copyId]; |
| + _JsCopier() : super() { _visited = new _JsVisitedMap(); } |
| - 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(SendPort x) { |
| + if (x is _NativeJsSendPort) return visitNativeJsSendPort(x); |
| + if (x is _WorkerSendPort) return visitWorkerSendPort(x); |
| + if (x is _BufferingSendPort) return visitBufferingSendPort(x); |
| + throw "Illegal underlying port $p"; |
| } |
| - visitNativeJsSendPort(_NativeJsSendPort port) { |
| - return ['sendport', _globalState.currentManagerId, |
| - port._isolateId, port._receivePort._id]; |
| + SendPort visitNativeJsSendPort(_NativeJsSendPort port) { |
| + return new _NativeJsSendPort(port._receivePort, port._isolateId); |
| } |
| - visitWorkerSendPort(_WorkerSendPort port) { |
| - return ['sendport', port._workerId, port._isolateId, port._receivePortId]; |
| + SendPort visitWorkerSendPort(_WorkerSendPort port) { |
| + return new _WorkerSendPort( |
| + port._workerId, port._isolateId, port._receivePortId); |
| } |
| - visitBufferingSendPort(_BufferingSendPort port) { |
| + SendPort visitBufferingSendPort(_BufferingSendPort port) { |
| if (port._port != null) { |
| - return _visitNativeOrWorkerPort(port._port); |
| + return visitSendPort(port._port); |
| } else { |
| // TODO(floitsch): Use real exception (which one?). |
| throw |
| @@ -208,82 +88,11 @@ class _Serializer extends _MessageTraverser { |
| } |
| } |
|
vsm
2012/07/04 05:21:54
nit: extra newline
|
| - _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; |
| - } |
| } |
| -/** Deserializes arrays created with [_Serializer]. */ |
| -class _Deserializer { |
| - Map<int, Dynamic> _deserialized; |
| - |
| - _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; |
| - } |
| +class _JsDeserializer extends _Deserializer { |
| - 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) { |
| + SendPort deserializeSendPort(List x) { |
| int managerId = x[1]; |
| int isolateId = x[2]; |
| int receivePortId = x[3]; |
| @@ -298,19 +107,59 @@ class _Deserializer { |
| return new _WorkerSendPort(managerId, isolateId, receivePortId); |
| } |
| } |
| + |
| +} |
| + |
| +class _JsVisitedMap implements _MessageTraverserVisitedMap { |
| + List tagged; |
| + |
| + /** Retrieves any information stored in the native object [object]. */ |
| + operator[](var object) { |
| + return _getAttachedInfo(object); |
| + } |
| + |
| + /** Injects some information into the native [object]. */ |
| + void operator[]=(var object, var info) { |
| + tagged.add(object); |
| + _setAttachedInfo(object, info); |
| + } |
| + |
| + /** Get ready to rumble. */ |
| + void reset() { |
| + assert(tagged == null); |
| + tagged = new List(); |
| + } |
| + |
| + /** Remove all information injected in the native objects. */ |
| + cleanup() { |
| + int length = tagged.length; |
| + for (int i = 0, length = tagged.length; i < length; i++) { |
|
vsm
2012/07/04 05:21:54
Redundant length = tagged.length.
kasperl
2012/07/04 05:50:14
Done.
|
| + _clearAttachedInfo(tagged[i]); |
| + } |
| + tagged = null; |
| + } |
| + |
| + _clearAttachedInfo(var o) native |
| + "o['__MessageTraverser__attached_info__'] = (void 0);"; |
|
vsm
2012/07/04 05:21:54
I think this leaves the property on the object. T
kasperl
2012/07/04 05:50:14
This is intentional. We don't want to force the ob
|
| + |
| + _setAttachedInfo(var o, var info) native |
| + "o['__MessageTraverser__attached_info__'] = info;"; |
| + |
| + _getAttachedInfo(var o) native |
| + "return o['__MessageTraverser__attached_info__'];"; |
| } |
| // only visible for testing purposes |
| // TODO(sigmund): remove once we can disable privacy for testing (bug #1882) |
| class TestingOnly { |
| static copy(x) { |
| - return new _Copier().traverse(x); |
| + return new _JsCopier().traverse(x); |
| } |
| // only visible for testing purposes |
| static serialize(x) { |
| - _Serializer serializer = new _Serializer(); |
| - _Deserializer deserializer = new _Deserializer(); |
| + _Serializer serializer = new _JsSerializer(); |
| + _Deserializer deserializer = new _JsDeserializer(); |
| return deserializer.deserialize(serializer.traverse(x)); |
| } |
| } |