| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 class MessageTraverser { | |
| 6 static bool isPrimitive(x) { | |
| 7 return (x === null) || (x is String) || (x is num) || (x is bool); | |
| 8 } | |
| 9 | |
| 10 MessageTraverser(); | |
| 11 | |
| 12 traverse(var x) { | |
| 13 if (isPrimitive(x)) return visitPrimitive(x); | |
| 14 _taggedObjects = new List(); | |
| 15 var result; | |
| 16 try { | |
| 17 result = _dispatch(x); | |
| 18 } finally { | |
| 19 _cleanup(); | |
| 20 } | |
| 21 return result; | |
| 22 } | |
| 23 | |
| 24 void _cleanup() { | |
| 25 int len = _taggedObjects.length; | |
| 26 for (int i = 0; i < len; i++) { | |
| 27 _clearAttachedInfo(_taggedObjects[i]); | |
| 28 } | |
| 29 _taggedObjects = null; | |
| 30 } | |
| 31 | |
| 32 void _attachInfo(var o, var info) { | |
| 33 _taggedObjects.add(o); | |
| 34 _setAttachedInfo(o, info); | |
| 35 } | |
| 36 | |
| 37 _getInfo(var o) { | |
| 38 return _getAttachedInfo(o); | |
| 39 } | |
| 40 | |
| 41 _dispatch(var x) { | |
| 42 if (isPrimitive(x)) return visitPrimitive(x); | |
| 43 if (x is List) return visitList(x); | |
| 44 if (x is Map) return visitMap(x); | |
| 45 if (x is SendPortImpl) return visitSendPort(x); | |
| 46 if (x is ReceivePortImpl) return visitReceivePort(x); | |
| 47 if (x is ReceivePortSingleShotImpl) return visitReceivePortSingleShot(x); | |
| 48 // TODO(floitsch): make this a real exception. (which one)? | |
| 49 throw new Exception("Message serialization: Illegal value $x passed"); | |
| 50 } | |
| 51 | |
| 52 abstract visitPrimitive(x); | |
| 53 abstract visitList(List x); | |
| 54 abstract visitMap(Map x); | |
| 55 abstract visitSendPort(SendPortImpl x); | |
| 56 abstract visitReceivePort(ReceivePortImpl x); | |
| 57 abstract visitReceivePortSingleShot(ReceivePortSingleShotImpl x); | |
| 58 | |
| 59 List _taggedObjects; | |
| 60 | |
| 61 _clearAttachedInfo(var obj) native; | |
| 62 _setAttachedInfo(var o, var info) native; | |
| 63 _getAttachedInfo(var o) native; | |
| 64 } | |
| 65 | |
| 66 class Copier extends MessageTraverser { | |
| 67 Copier() : super(); | |
| 68 | |
| 69 visitPrimitive(x) => x; | |
| 70 | |
| 71 List visitList(List list) { | |
| 72 List copy = _getInfo(list); | |
| 73 if (copy !== null) return copy; | |
| 74 | |
| 75 int len = list.length; | |
| 76 // TODO(floitsch): we loose the generic type of the List. | |
| 77 copy = new List(len); | |
| 78 _attachInfo(list, copy); | |
| 79 for (int i = 0; i < len; i++) { | |
| 80 copy[i] = _dispatch(list[i]); | |
| 81 } | |
| 82 return copy; | |
| 83 } | |
| 84 | |
| 85 Map visitMap(Map map) { | |
| 86 Map copy = _getInfo(map); | |
| 87 if (copy !== null) return copy; | |
| 88 | |
| 89 // TODO(floitsch): we loose the generic type of the map. | |
| 90 copy = new Map(); | |
| 91 _attachInfo(map, copy); | |
| 92 map.forEach((key, val) { | |
| 93 copy[_dispatch(key)] = _dispatch(val); | |
| 94 }); | |
| 95 return copy; | |
| 96 } | |
| 97 | |
| 98 SendPort visitSendPort(SendPortImpl port) { | |
| 99 return new SendPortImpl(port._workerId, | |
| 100 port._isolateId, | |
| 101 port._receivePortId); | |
| 102 } | |
| 103 | |
| 104 SendPort visitReceivePort(ReceivePortImpl port) { | |
| 105 return port._toNewSendPort(); | |
| 106 } | |
| 107 | |
| 108 SendPort visitReceivePortSingleShot(ReceivePortSingleShotImpl port) { | |
| 109 return port._toNewSendPort(); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 class Serializer extends MessageTraverser { | |
| 114 Serializer() : super(); | |
| 115 | |
| 116 visitPrimitive(x) => x; | |
| 117 | |
| 118 visitList(List list) { | |
| 119 int copyId = _getInfo(list); | |
| 120 if (copyId !== null) return _makeRef(copyId); | |
| 121 | |
| 122 int id = _nextFreeRefId++; | |
| 123 _attachInfo(list, id); | |
| 124 var jsArray = _serializeDartListIntoNewJsArray(list); | |
| 125 // TODO(floitsch): we are losing the generic type. | |
| 126 return _dartListToJsArrayNoCopy(['list', id, jsArray]); | |
| 127 } | |
| 128 | |
| 129 visitMap(Map map) { | |
| 130 int copyId = _getInfo(map); | |
| 131 if (copyId !== null) return _makeRef(copyId); | |
| 132 | |
| 133 int id = _nextFreeRefId++; | |
| 134 _attachInfo(map, id); | |
| 135 var keys = _serializeDartListIntoNewJsArray(map.getKeys()); | |
| 136 var values = _serializeDartListIntoNewJsArray(map.getValues()); | |
| 137 // TODO(floitsch): we are losing the generic type. | |
| 138 return _dartListToJsArrayNoCopy(['map', id, keys, values]); | |
| 139 } | |
| 140 | |
| 141 visitSendPort(SendPortImpl port) { | |
| 142 return _dartListToJsArrayNoCopy(['sendport', | |
| 143 port._workerId, | |
| 144 port._isolateId, | |
| 145 port._receivePortId]); | |
| 146 } | |
| 147 | |
| 148 visitReceivePort(ReceivePortImpl port) { | |
| 149 return visitSendPort(port.toSendPort());; | |
| 150 } | |
| 151 | |
| 152 visitReceivePortSingleShot(ReceivePortSingleShotImpl port) { | |
| 153 return visitSendPort(port.toSendPort()); | |
| 154 } | |
| 155 | |
| 156 _serializeDartListIntoNewJsArray(List list) { | |
| 157 int len = list.length; | |
| 158 var jsArray = _newJsArray(len); | |
| 159 for (int i = 0; i < len; i++) { | |
| 160 _jsArrayIndexSet(jsArray, i, _dispatch(list[i])); | |
| 161 } | |
| 162 return jsArray; | |
| 163 } | |
| 164 | |
| 165 _makeRef(int id) { | |
| 166 return _dartListToJsArrayNoCopy(['ref', id]); | |
| 167 } | |
| 168 | |
| 169 int _nextFreeRefId = 0; | |
| 170 | |
| 171 static _newJsArray(int len) native; | |
| 172 static _jsArrayIndexSet(jsArray, int index, val) native; | |
| 173 static _dartListToJsArrayNoCopy(List list) native; | |
| 174 } | |
| 175 | |
| 176 class Deserializer { | |
| 177 Deserializer(); | |
| 178 | |
| 179 static bool isPrimitive(x) { | |
| 180 return (x === null) || (x is String) || (x is num) || (x is bool); | |
| 181 } | |
| 182 | |
| 183 deserialize(x) { | |
| 184 if (isPrimitive(x)) return x; | |
| 185 // TODO(floitsch): this should be new HashMap<int, var|Dynamic>() | |
| 186 _deserialized = new HashMap(); | |
| 187 return _deserializeHelper(x); | |
| 188 } | |
| 189 | |
| 190 _deserializeHelper(x) { | |
| 191 if (isPrimitive(x)) return x; | |
| 192 assert(_isJsArray(x)); | |
| 193 switch (_jsArrayIndex(x, 0)) { | |
| 194 case 'ref': return _deserializeRef(x); | |
| 195 case 'list': return _deserializeList(x); | |
| 196 case 'map': return _deserializeMap(x); | |
| 197 case 'sendport': return _deserializeSendPort(x); | |
| 198 // TODO(floitsch): Use real exception (which one?). | |
| 199 default: throw "Unexpected serialized object"; | |
| 200 } | |
| 201 } | |
| 202 | |
| 203 _deserializeRef(x) { | |
| 204 int id = _jsArrayIndex(x, 1); | |
| 205 var result = _deserialized[id]; | |
| 206 assert(result !== null); | |
| 207 return result; | |
| 208 } | |
| 209 | |
| 210 List _deserializeList(x) { | |
| 211 int id = _jsArrayIndex(x, 1); | |
| 212 var jsArray = _jsArrayIndex(x, 2); | |
| 213 assert(_isJsArray(jsArray)); | |
| 214 List dartList = _jsArrayToDartListNoCopy(jsArray); | |
| 215 _deserialized[id] = dartList; | |
| 216 int len = dartList.length; | |
| 217 for (int i = 0; i < len; i++) { | |
| 218 dartList[i] = _deserializeHelper(dartList[i]); | |
| 219 } | |
| 220 return dartList; | |
| 221 } | |
| 222 | |
| 223 Map _deserializeMap(x) { | |
| 224 Map result = new Map(); | |
| 225 int id = _jsArrayIndex(x, 1); | |
| 226 _deserialized[id] = result; | |
| 227 var keys = _jsArrayIndex(x, 2); | |
| 228 var values = _jsArrayIndex(x, 3); | |
| 229 assert(_isJsArray(keys)); | |
| 230 assert(_isJsArray(values)); | |
| 231 int len = _jsArrayLength(keys); | |
| 232 assert(len == _jsArrayLength(values)); | |
| 233 for (int i = 0; i < len; i++) { | |
| 234 var key = _deserializeHelper(_jsArrayIndex(keys, i)); | |
| 235 var value = _deserializeHelper(_jsArrayIndex(values, i)); | |
| 236 result[key] = value; | |
| 237 } | |
| 238 return result; | |
| 239 } | |
| 240 | |
| 241 SendPort _deserializeSendPort(x) { | |
| 242 int workerId = _jsArrayIndex(x, 1); | |
| 243 int isolateId = _jsArrayIndex(x, 2); | |
| 244 int receivePortId = _jsArrayIndex(x, 3); | |
| 245 return new SendPortImpl(workerId, isolateId, receivePortId); | |
| 246 } | |
| 247 | |
| 248 List _jsArrayToDartListNoCopy(a) { | |
| 249 // We rely on the fact that Dart-lists are directly mapped to Js-arrays. | |
| 250 // TODO(floitsch): can we do better here? | |
| 251 assert(a is List); | |
| 252 return a; | |
| 253 } | |
| 254 | |
| 255 // TODO(floitsch): this should by Map<int, var> or Map<int, Dynamic>. | |
| 256 Map _deserialized; | |
| 257 | |
| 258 static bool _isJsArray(x) native; | |
| 259 static _jsArrayIndex(x, int index) native; | |
| 260 static int _jsArrayLength(x) native; | |
| 261 } | |
| OLD | NEW |