| 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 |