mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 08:51:21 +00:00
Serialize Elements through PortSync
Review URL: https://chromiumcodereview.appspot.com//10883037 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@11365 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
1bca4e07d5
commit
8802f83208
|
@ -88,6 +88,12 @@ function ReceivePortSync() {
|
|||
} else if (message instanceof Function) {
|
||||
return [ 'funcref', functionRefTable.makeRef(message),
|
||||
doSerialize(functionRefTable.sendPort) ];
|
||||
} else if (message instanceof HTMLElement) {
|
||||
var id = elementId(message);
|
||||
// Verify that the element is connected to the document.
|
||||
// Otherwise, we will not be able to find it on the other side.
|
||||
getElement(id);
|
||||
return [ 'element', id ];
|
||||
} else if (message instanceof DartProxy) {
|
||||
return [ 'objref', message._id, doSerialize(message._port) ];
|
||||
} else if (message.__proto__ != {}.__proto__) {
|
||||
|
@ -126,6 +132,7 @@ function ReceivePortSync() {
|
|||
case 'list': return deserializeList(message);
|
||||
case 'funcref': return deserializeFunction(message);
|
||||
case 'objref': return deserializeProxy(message);
|
||||
case 'element': return deserializeElement(message);
|
||||
default: throw 'unimplemented';
|
||||
}
|
||||
}
|
||||
|
@ -187,6 +194,11 @@ function ReceivePortSync() {
|
|||
throw 'Illegal proxy object: ' + message;
|
||||
}
|
||||
|
||||
function deserializeElement(message) {
|
||||
var id = message[1];
|
||||
return getElement(id);
|
||||
}
|
||||
|
||||
window.registerPort = function(name, port) {
|
||||
var stringified = JSON.stringify(serialize(port));
|
||||
window.localStorage['dart-port:' + name] = stringified;
|
||||
|
@ -376,4 +388,24 @@ function ReceivePortSync() {
|
|||
return sendPort.callSync([ref, Array.prototype.slice.call(arguments)]);
|
||||
}
|
||||
}
|
||||
|
||||
var localNextElementId = 0;
|
||||
var _DART_ID = 'data-dart_id';
|
||||
|
||||
function elementId(e) {
|
||||
if (e.hasAttribute(_DART_ID)) return e.getAttribute(_DART_ID);
|
||||
var id = (localNextElementId++).toString();
|
||||
e.setAttribute(_DART_ID, id);
|
||||
return id;
|
||||
}
|
||||
|
||||
function getElement(id) {
|
||||
var list = document.querySelectorAll('[' + _DART_ID + '="' + id + '"]');
|
||||
|
||||
if (list.length > 1) throw 'Non unique ID: ' + id;
|
||||
if (list.length == 0) {
|
||||
throw 'Element must be attached to the document: ' + id;
|
||||
}
|
||||
return list[0];
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -37682,6 +37682,26 @@ class JsProxy {
|
|||
}
|
||||
}
|
||||
|
||||
int _localNextElementId = 0;
|
||||
|
||||
const _DART_ID = 'data-dart_id';
|
||||
|
||||
var _elementId(Element e) {
|
||||
if (e.attributes.containsKey(_DART_ID)) return e.attributes[_DART_ID];
|
||||
var id = '$_isolateId-${_localNextElementId++}';
|
||||
e.attributes[_DART_ID] = id;
|
||||
return id;
|
||||
}
|
||||
|
||||
Element _getElement(var id) {
|
||||
var list = queryAll('[$_DART_ID="$id"]');
|
||||
if (list.length > 1) throw 'Non unique ID: $id';
|
||||
if (list.length == 0) {
|
||||
throw 'Only elements attached to document can be serialized: $id';
|
||||
}
|
||||
return list[0];
|
||||
}
|
||||
|
||||
class _JsSerializer extends _Serializer {
|
||||
|
||||
visitSendPortSync(SendPortSync x) {
|
||||
|
@ -37708,6 +37728,7 @@ class _JsSerializer extends _Serializer {
|
|||
visitObject(Object x) {
|
||||
if (x is Function) return visitFunction(x);
|
||||
if (x is JsProxy) return visitJsProxy(x);
|
||||
if (x is Element) return visitElement(x);
|
||||
|
||||
// TODO: Handle DOM elements and proxy other objects.
|
||||
var proxyId = _dartProxyRegistry._add(x);
|
||||
|
@ -37724,6 +37745,14 @@ class _JsSerializer extends _Serializer {
|
|||
visitJsProxy(JsProxy proxy) {
|
||||
return [ 'objref', proxy._id, visitSendPortSync(proxy._port) ];
|
||||
}
|
||||
|
||||
visitElement(Element element) {
|
||||
var id = _elementId(element);
|
||||
// Verify that the element is connected to the document.
|
||||
// Otherwise, we will not be able to find it on the other side.
|
||||
_getElement(id);
|
||||
return [ 'element', id ];
|
||||
}
|
||||
}
|
||||
|
||||
// Leaking implementation. Later will be backend specific and hopefully
|
||||
|
@ -37828,6 +37857,7 @@ class _JsDeserializer extends _Deserializer {
|
|||
switch (tag) {
|
||||
case 'funcref': return deserializeFunction(x);
|
||||
case 'objref': return deserializeProxy(x);
|
||||
case 'element': return deserializeElement(x);
|
||||
default: throw 'Illegal object type: $x';
|
||||
}
|
||||
}
|
||||
|
@ -37855,6 +37885,11 @@ class _JsDeserializer extends _Deserializer {
|
|||
if (port is _RemoteSendPortSync) throw 'Remote Dart proxies unsupported';
|
||||
throw 'Illegal proxy: $port';
|
||||
}
|
||||
|
||||
deserializeElement(x) {
|
||||
var id = x[1];
|
||||
return _getElement(id);
|
||||
}
|
||||
}
|
||||
|
||||
// The receiver is JS.
|
||||
|
@ -37992,6 +38027,8 @@ class ReceivePortSync {
|
|||
}
|
||||
}
|
||||
|
||||
get _isolateId => ReceivePortSync._isolateId;
|
||||
|
||||
void _dispatchEvent(String receiver, var message) {
|
||||
var event = document.$dom_createEvent('TextEvent');
|
||||
event.initTextEvent(receiver, false, false, window, JSON.stringify(message));
|
||||
|
|
|
@ -40787,6 +40787,26 @@ class JsProxy {
|
|||
}
|
||||
}
|
||||
|
||||
int _localNextElementId = 0;
|
||||
|
||||
const _DART_ID = 'data-dart_id';
|
||||
|
||||
var _elementId(Element e) {
|
||||
if (e.attributes.containsKey(_DART_ID)) return e.attributes[_DART_ID];
|
||||
var id = '$_isolateId-${_localNextElementId++}';
|
||||
e.attributes[_DART_ID] = id;
|
||||
return id;
|
||||
}
|
||||
|
||||
Element _getElement(var id) {
|
||||
var list = queryAll('[$_DART_ID="$id"]');
|
||||
if (list.length > 1) throw 'Non unique ID: $id';
|
||||
if (list.length == 0) {
|
||||
throw 'Only elements attached to document can be serialized: $id';
|
||||
}
|
||||
return list[0];
|
||||
}
|
||||
|
||||
class _JsSerializer extends _Serializer {
|
||||
|
||||
visitSendPortSync(SendPortSync x) {
|
||||
|
@ -40813,6 +40833,7 @@ class _JsSerializer extends _Serializer {
|
|||
visitObject(Object x) {
|
||||
if (x is Function) return visitFunction(x);
|
||||
if (x is JsProxy) return visitJsProxy(x);
|
||||
if (x is Element) return visitElement(x);
|
||||
|
||||
// TODO: Handle DOM elements and proxy other objects.
|
||||
var proxyId = _dartProxyRegistry._add(x);
|
||||
|
@ -40829,6 +40850,14 @@ class _JsSerializer extends _Serializer {
|
|||
visitJsProxy(JsProxy proxy) {
|
||||
return [ 'objref', proxy._id, visitSendPortSync(proxy._port) ];
|
||||
}
|
||||
|
||||
visitElement(Element element) {
|
||||
var id = _elementId(element);
|
||||
// Verify that the element is connected to the document.
|
||||
// Otherwise, we will not be able to find it on the other side.
|
||||
_getElement(id);
|
||||
return [ 'element', id ];
|
||||
}
|
||||
}
|
||||
|
||||
// Leaking implementation. Later will be backend specific and hopefully
|
||||
|
@ -40933,6 +40962,7 @@ class _JsDeserializer extends _Deserializer {
|
|||
switch (tag) {
|
||||
case 'funcref': return deserializeFunction(x);
|
||||
case 'objref': return deserializeProxy(x);
|
||||
case 'element': return deserializeElement(x);
|
||||
default: throw 'Illegal object type: $x';
|
||||
}
|
||||
}
|
||||
|
@ -40960,6 +40990,11 @@ class _JsDeserializer extends _Deserializer {
|
|||
if (port is _RemoteSendPortSync) throw 'Remote Dart proxies unsupported';
|
||||
throw 'Illegal proxy: $port';
|
||||
}
|
||||
|
||||
deserializeElement(x) {
|
||||
var id = x[1];
|
||||
return _getElement(id);
|
||||
}
|
||||
}
|
||||
|
||||
// The receiver is JS.
|
||||
|
@ -41097,6 +41132,8 @@ class ReceivePortSync {
|
|||
}
|
||||
}
|
||||
|
||||
get _isolateId => ReceivePortSync._isolateId;
|
||||
|
||||
void _dispatchEvent(String receiver, var message) {
|
||||
var event = document.$dom_createEvent('TextEvent');
|
||||
event.initTextEvent(receiver, false, false, window, JSON.stringify(message));
|
||||
|
|
|
@ -23,6 +23,26 @@ class JsProxy {
|
|||
}
|
||||
}
|
||||
|
||||
int _localNextElementId = 0;
|
||||
|
||||
const _DART_ID = 'data-dart_id';
|
||||
|
||||
var _elementId(Element e) {
|
||||
if (e.attributes.containsKey(_DART_ID)) return e.attributes[_DART_ID];
|
||||
var id = '$_isolateId-${_localNextElementId++}';
|
||||
e.attributes[_DART_ID] = id;
|
||||
return id;
|
||||
}
|
||||
|
||||
Element _getElement(var id) {
|
||||
var list = queryAll('[$_DART_ID="$id"]');
|
||||
if (list.length > 1) throw 'Non unique ID: $id';
|
||||
if (list.length == 0) {
|
||||
throw 'Only elements attached to document can be serialized: $id';
|
||||
}
|
||||
return list[0];
|
||||
}
|
||||
|
||||
class _JsSerializer extends _Serializer {
|
||||
|
||||
visitSendPortSync(SendPortSync x) {
|
||||
|
@ -49,6 +69,7 @@ class _JsSerializer extends _Serializer {
|
|||
visitObject(Object x) {
|
||||
if (x is Function) return visitFunction(x);
|
||||
if (x is JsProxy) return visitJsProxy(x);
|
||||
if (x is Element) return visitElement(x);
|
||||
|
||||
// TODO: Handle DOM elements and proxy other objects.
|
||||
var proxyId = _dartProxyRegistry._add(x);
|
||||
|
@ -65,6 +86,14 @@ class _JsSerializer extends _Serializer {
|
|||
visitJsProxy(JsProxy proxy) {
|
||||
return [ 'objref', proxy._id, visitSendPortSync(proxy._port) ];
|
||||
}
|
||||
|
||||
visitElement(Element element) {
|
||||
var id = _elementId(element);
|
||||
// Verify that the element is connected to the document.
|
||||
// Otherwise, we will not be able to find it on the other side.
|
||||
_getElement(id);
|
||||
return [ 'element', id ];
|
||||
}
|
||||
}
|
||||
|
||||
// Leaking implementation. Later will be backend specific and hopefully
|
||||
|
@ -169,6 +198,7 @@ class _JsDeserializer extends _Deserializer {
|
|||
switch (tag) {
|
||||
case 'funcref': return deserializeFunction(x);
|
||||
case 'objref': return deserializeProxy(x);
|
||||
case 'element': return deserializeElement(x);
|
||||
default: throw 'Illegal object type: $x';
|
||||
}
|
||||
}
|
||||
|
@ -196,6 +226,11 @@ class _JsDeserializer extends _Deserializer {
|
|||
if (port is _RemoteSendPortSync) throw 'Remote Dart proxies unsupported';
|
||||
throw 'Illegal proxy: $port';
|
||||
}
|
||||
|
||||
deserializeElement(x) {
|
||||
var id = x[1];
|
||||
return _getElement(id);
|
||||
}
|
||||
}
|
||||
|
||||
// The receiver is JS.
|
||||
|
@ -333,6 +368,8 @@ class ReceivePortSync {
|
|||
}
|
||||
}
|
||||
|
||||
get _isolateId => ReceivePortSync._isolateId;
|
||||
|
||||
void _dispatchEvent(String receiver, var message) {
|
||||
var event = document.$dom_createEvent('TextEvent');
|
||||
event.initTextEvent(receiver, false, false, window, JSON.stringify(message));
|
||||
|
|
61
tests/html/js_interop_element_test.dart
Normal file
61
tests/html/js_interop_element_test.dart
Normal file
|
@ -0,0 +1,61 @@
|
|||
// 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
|
||||
|
||||
#library('JsInteropElementTest');
|
||||
#import('../../pkg/unittest/unittest.dart');
|
||||
#import('../../pkg/unittest/html_config.dart');
|
||||
#import('dart:html');
|
||||
#import('dart:isolate');
|
||||
|
||||
injectSource(code) {
|
||||
final script = new ScriptElement();
|
||||
script.type = 'text/javascript';
|
||||
script.innerHTML = code;
|
||||
document.body.nodes.add(script);
|
||||
}
|
||||
|
||||
var jsElementTest = """
|
||||
var canvas = document.createElement('canvas');
|
||||
document.body.appendChild(canvas);
|
||||
|
||||
var port = window.lookupPort('test1');
|
||||
port.callSync(canvas);
|
||||
""";
|
||||
|
||||
var dartElementTest = """
|
||||
var port = new ReceivePortSync();
|
||||
port.receive(function (data) {
|
||||
return (data instanceof HTMLDivElement);
|
||||
});
|
||||
window.registerPort('test2', port.toSendPort());
|
||||
""";
|
||||
|
||||
main() {
|
||||
useHtmlConfiguration();
|
||||
|
||||
test('js-element', () {
|
||||
int invoked = 0;
|
||||
|
||||
var port = new ReceivePortSync();
|
||||
port.receive((data) {
|
||||
expect(data is CanvasElement);
|
||||
++invoked;
|
||||
});
|
||||
window.registerPort('test1', port.toSendPort());
|
||||
|
||||
injectSource(jsElementTest);
|
||||
expect(invoked, equals(1));
|
||||
});
|
||||
|
||||
test('dart-element', () {
|
||||
injectSource(dartElementTest);
|
||||
|
||||
var port = window.lookupPort('test2');
|
||||
var div = new DivElement();
|
||||
var canvas = new CanvasElement(100,100);
|
||||
document.body.nodes.addAll([div, canvas]);
|
||||
expect(port.callSync(div));
|
||||
expect(!port.callSync(canvas));
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue