OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 _serialize(var message) { | 5 _serialize(var message) { |
6 return new _JsSerializer().traverse(message); | 6 return new _JsSerializer().traverse(message); |
7 } | 7 } |
8 | 8 |
9 class JsProxy { | 9 class JsProxy { |
10 SendPortSync _port; | 10 SendPortSync _port; |
11 final _id; | 11 final _id; |
12 | 12 |
13 JsProxy._internal(this._port, this._id); | 13 JsProxy._internal(this._port, this._id); |
14 | 14 |
15 noSuchMethod(method, args) { | 15 noSuchMethod(method, args) { |
16 var result = _port.callSync([_id, method, args]); | 16 var result = _port.callSync([_id, method, args]); |
17 switch (result[0]) { | 17 switch (result[0]) { |
18 case 'return': return result[1]; | 18 case 'return': return result[1]; |
19 case 'exception': throw result[1]; | 19 case 'exception': throw result[1]; |
20 case 'none': throw new NoSuchMethodException(this, method, args); | 20 case 'none': throw new NoSuchMethodException(this, method, args); |
21 default: throw 'Invalid return value'; | 21 default: throw 'Invalid return value'; |
22 } | 22 } |
23 } | 23 } |
24 } | 24 } |
25 | 25 |
| 26 int _localNextElementId = 0; |
| 27 |
| 28 const _DART_ID = 'data-dart_id'; |
| 29 |
| 30 var _elementId(Element e) { |
| 31 if (e.attributes.containsKey(_DART_ID)) return e.attributes[_DART_ID]; |
| 32 var id = '$_isolateId-${_localNextElementId++}'; |
| 33 e.attributes[_DART_ID] = id; |
| 34 return id; |
| 35 } |
| 36 |
| 37 Element _getElement(var id) { |
| 38 var list = queryAll('[$_DART_ID="$id"]'); |
| 39 if (list.length > 1) throw 'Non unique ID: $id'; |
| 40 if (list.length == 0) { |
| 41 throw 'Only elements attached to document can be serialized: $id'; |
| 42 } |
| 43 return list[0]; |
| 44 } |
| 45 |
26 class _JsSerializer extends _Serializer { | 46 class _JsSerializer extends _Serializer { |
27 | 47 |
28 visitSendPortSync(SendPortSync x) { | 48 visitSendPortSync(SendPortSync x) { |
29 if (x is _JsSendPortSync) return visitJsSendPortSync(x); | 49 if (x is _JsSendPortSync) return visitJsSendPortSync(x); |
30 if (x is _LocalSendPortSync) return visitLocalSendPortSync(x); | 50 if (x is _LocalSendPortSync) return visitLocalSendPortSync(x); |
31 if (x is _RemoteSendPortSync) return visitRemoteSendPortSync(x); | 51 if (x is _RemoteSendPortSync) return visitRemoteSendPortSync(x); |
32 throw "Unknown port type $x"; | 52 throw "Unknown port type $x"; |
33 } | 53 } |
34 | 54 |
35 visitJsSendPortSync(_JsSendPortSync x) { | 55 visitJsSendPortSync(_JsSendPortSync x) { |
36 return [ 'sendport', 'nativejs', x._id ]; | 56 return [ 'sendport', 'nativejs', x._id ]; |
37 } | 57 } |
38 | 58 |
39 visitLocalSendPortSync(_LocalSendPortSync x) { | 59 visitLocalSendPortSync(_LocalSendPortSync x) { |
40 return [ 'sendport', 'dart', | 60 return [ 'sendport', 'dart', |
41 ReceivePortSync._isolateId, x._receivePort._portId ]; | 61 ReceivePortSync._isolateId, x._receivePort._portId ]; |
42 } | 62 } |
43 | 63 |
44 visitRemoteSendPortSync(_RemoteSendPortSync x) { | 64 visitRemoteSendPortSync(_RemoteSendPortSync x) { |
45 return [ 'sendport', 'dart', | 65 return [ 'sendport', 'dart', |
46 x._receivePort._isolateId, x._receivePort._portId ]; | 66 x._receivePort._isolateId, x._receivePort._portId ]; |
47 } | 67 } |
48 | 68 |
49 visitObject(Object x) { | 69 visitObject(Object x) { |
50 if (x is Function) return visitFunction(x); | 70 if (x is Function) return visitFunction(x); |
51 if (x is JsProxy) return visitJsProxy(x); | 71 if (x is JsProxy) return visitJsProxy(x); |
| 72 if (x is Element) return visitElement(x); |
52 | 73 |
53 // TODO: Handle DOM elements and proxy other objects. | 74 // TODO: Handle DOM elements and proxy other objects. |
54 var proxyId = _dartProxyRegistry._add(x); | 75 var proxyId = _dartProxyRegistry._add(x); |
55 return [ 'objref', proxyId, | 76 return [ 'objref', proxyId, |
56 visitSendPortSync(_dartProxyRegistry._sendPort) ]; | 77 visitSendPortSync(_dartProxyRegistry._sendPort) ]; |
57 } | 78 } |
58 | 79 |
59 visitFunction(Function func) { | 80 visitFunction(Function func) { |
60 return [ 'funcref', | 81 return [ 'funcref', |
61 _functionRegistry._add(func), | 82 _functionRegistry._add(func), |
62 visitSendPortSync(_functionRegistry._sendPort), null ]; | 83 visitSendPortSync(_functionRegistry._sendPort), null ]; |
63 } | 84 } |
64 | 85 |
65 visitJsProxy(JsProxy proxy) { | 86 visitJsProxy(JsProxy proxy) { |
66 return [ 'objref', proxy._id, visitSendPortSync(proxy._port) ]; | 87 return [ 'objref', proxy._id, visitSendPortSync(proxy._port) ]; |
67 } | 88 } |
| 89 |
| 90 visitElement(Element element) { |
| 91 var id = _elementId(element); |
| 92 // Verify that the element is connected to the document. |
| 93 // Otherwise, we will not be able to find it on the other side. |
| 94 _getElement(id); |
| 95 return [ 'element', id ]; |
| 96 } |
68 } | 97 } |
69 | 98 |
70 // Leaking implementation. Later will be backend specific and hopefully | 99 // Leaking implementation. Later will be backend specific and hopefully |
71 // not leaking (at least in most of the cases.) | 100 // not leaking (at least in most of the cases.) |
72 // TODO: provide better, backend specific implementation. | 101 // TODO: provide better, backend specific implementation. |
73 class _Registry<T> { | 102 class _Registry<T> { |
74 final String _name; | 103 final String _name; |
75 int _nextId; | 104 int _nextId; |
76 final Map<String, T> _registry; | 105 final Map<String, T> _registry; |
77 final ReceivePortSync _port; | 106 final ReceivePortSync _port; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 default: | 191 default: |
163 throw 'Illegal SendPortSync type: $tag'; | 192 throw 'Illegal SendPortSync type: $tag'; |
164 } | 193 } |
165 } | 194 } |
166 | 195 |
167 deserializeObject(List x) { | 196 deserializeObject(List x) { |
168 String tag = x[0]; | 197 String tag = x[0]; |
169 switch (tag) { | 198 switch (tag) { |
170 case 'funcref': return deserializeFunction(x); | 199 case 'funcref': return deserializeFunction(x); |
171 case 'objref': return deserializeProxy(x); | 200 case 'objref': return deserializeProxy(x); |
| 201 case 'element': return deserializeElement(x); |
172 default: throw 'Illegal object type: $x'; | 202 default: throw 'Illegal object type: $x'; |
173 } | 203 } |
174 } | 204 } |
175 | 205 |
176 deserializeFunction(List x) { | 206 deserializeFunction(List x) { |
177 var id = x[1]; | 207 var id = x[1]; |
178 SendPortSync port = deserializeSendPort(x[2]); | 208 SendPortSync port = deserializeSendPort(x[2]); |
179 // TODO: Support varargs when there is support in the language. | 209 // TODO: Support varargs when there is support in the language. |
180 return ([arg0 = _UNSPECIFIED, arg1 = _UNSPECIFIED, | 210 return ([arg0 = _UNSPECIFIED, arg1 = _UNSPECIFIED, |
181 arg2 = _UNSPECIFIED, arg3 = _UNSPECIFIED]) { | 211 arg2 = _UNSPECIFIED, arg3 = _UNSPECIFIED]) { |
182 var args = [arg0, arg1, arg2, arg3]; | 212 var args = [arg0, arg1, arg2, arg3]; |
183 var last = args.indexOf(_UNSPECIFIED); | 213 var last = args.indexOf(_UNSPECIFIED); |
184 if (last >= 0) args = args.getRange(0, last); | 214 if (last >= 0) args = args.getRange(0, last); |
185 var message = [id, args]; | 215 var message = [id, args]; |
186 return port.callSync(message); | 216 return port.callSync(message); |
187 }; | 217 }; |
188 } | 218 } |
189 | 219 |
190 deserializeProxy(x) { | 220 deserializeProxy(x) { |
191 var id = x[1]; | 221 var id = x[1]; |
192 var port = deserializeSendPort(x[2]); | 222 var port = deserializeSendPort(x[2]); |
193 if (port is _JsSendPortSync) return new JsProxy._internal(port, id); | 223 if (port is _JsSendPortSync) return new JsProxy._internal(port, id); |
194 if (port is _LocalSendPortSync) return _dartProxyRegistry._get(id); | 224 if (port is _LocalSendPortSync) return _dartProxyRegistry._get(id); |
195 // TODO(vsm): Support this case. | 225 // TODO(vsm): Support this case. |
196 if (port is _RemoteSendPortSync) throw 'Remote Dart proxies unsupported'; | 226 if (port is _RemoteSendPortSync) throw 'Remote Dart proxies unsupported'; |
197 throw 'Illegal proxy: $port'; | 227 throw 'Illegal proxy: $port'; |
198 } | 228 } |
| 229 |
| 230 deserializeElement(x) { |
| 231 var id = x[1]; |
| 232 return _getElement(id); |
| 233 } |
199 } | 234 } |
200 | 235 |
201 // The receiver is JS. | 236 // The receiver is JS. |
202 class _JsSendPortSync implements SendPortSync { | 237 class _JsSendPortSync implements SendPortSync { |
203 | 238 |
204 num _id; | 239 num _id; |
205 _JsSendPortSync(this._id); | 240 _JsSendPortSync(this._id); |
206 | 241 |
207 callSync(var message) { | 242 callSync(var message) { |
208 var serialized = _serialize(message); | 243 var serialized = _serialize(message); |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 | 361 |
327 static SendPortSync _lookup(int isolateId, int portId) { | 362 static SendPortSync _lookup(int isolateId, int portId) { |
328 if (isolateId == _isolateId) { | 363 if (isolateId == _isolateId) { |
329 return _portMap[portId].toSendPort(); | 364 return _portMap[portId].toSendPort(); |
330 } else { | 365 } else { |
331 return new _RemoteSendPortSync(isolateId, portId); | 366 return new _RemoteSendPortSync(isolateId, portId); |
332 } | 367 } |
333 } | 368 } |
334 } | 369 } |
335 | 370 |
| 371 get _isolateId => ReceivePortSync._isolateId; |
| 372 |
336 void _dispatchEvent(String receiver, var message) { | 373 void _dispatchEvent(String receiver, var message) { |
337 var event = document.$dom_createEvent('TextEvent'); | 374 var event = document.$dom_createEvent('TextEvent'); |
338 event.initTextEvent(receiver, false, false, window, JSON.stringify(message)); | 375 event.initTextEvent(receiver, false, false, window, JSON.stringify(message)); |
339 window.$dom_dispatchEvent(event); | 376 window.$dom_dispatchEvent(event); |
340 } | 377 } |
OLD | NEW |