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 |