// Copyright (c) 2012, 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. // Patch file for the dart:isolate library. /******************************************************** Inserted from lib/isolate/serialization.dart ********************************************************/ class _MessageTraverserVisitedMap { operator[](var object) => null; void operator[]=(var object, var info) { } void reset() { } void cleanup() { } } /** Abstract visitor for dart objects that can be sent as isolate messages. */ class _MessageTraverser { _MessageTraverserVisitedMap _visited; _MessageTraverser() : _visited = new _MessageTraverserVisitedMap(); /** Visitor's entry point. */ traverse(var x) { if (isPrimitive(x)) return visitPrimitive(x); _visited.reset(); var result; try { result = _dispatch(x); } finally { _visited.cleanup(); } return result; } _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 SendPort) return visitSendPort(x); if (x is SendPortSync) return visitSendPortSync(x); // Overridable fallback. return visitObject(x); } abstract visitPrimitive(x); abstract visitList(List x); abstract visitMap(Map x); abstract visitSendPort(SendPort x); abstract visitSendPortSync(SendPortSync x); visitObject(Object x) { // TODO(floitsch): make this a real exception. (which one)? throw "Message serialization: Illegal value $x passed"; } 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 { visitPrimitive(x) => x; List visitList(List list) { List copy = _visited[list]; if (copy !== null) return copy; int len = list.length; // TODO(floitsch): we loose the generic type of the List. copy = new List(len); _visited[list] = copy; for (int i = 0; i < len; i++) { copy[i] = _dispatch(list[i]); } return copy; } Map visitMap(Map map) { Map copy = _visited[map]; if (copy !== null) return copy; // TODO(floitsch): we loose the generic type of the map. copy = new Map(); _visited[map] = copy; map.forEach((key, val) { copy[_dispatch(key)] = _dispatch(val); }); return copy; } } /** Visitor that serializes a message as a JSON array. */ class _Serializer extends _MessageTraverser { int _nextFreeRefId = 0; visitPrimitive(x) => x; visitList(List list) { int copyId = _visited[list]; if (copyId !== null) return ['ref', copyId]; int id = _nextFreeRefId++; _visited[list] = id; var jsArray = _serializeList(list); // TODO(floitsch): we are losing the generic type. return ['list', id, jsArray]; } visitMap(Map map) { int copyId = _visited[map]; if (copyId !== null) return ['ref', copyId]; int id = _nextFreeRefId++; _visited[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]; } _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 _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() _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); default: return deserializeObject(x); } } _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; } abstract deserializeSendPort(List x); deserializeObject(List x) { // TODO(floitsch): Use real exception (which one?). throw "Unexpected serialized object"; } }