Remove proxying support from dart:html

I'm moving this functionality to a user-level library.

Review URL: https://chromiumcodereview.appspot.com//10914129

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@11997 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
vsm@google.com 2012-09-06 22:27:45 +00:00
parent 2561dd7544
commit 37b7e470e4
9 changed files with 6 additions and 1142 deletions

View file

@ -46,12 +46,13 @@ function ReceivePortSync() {
}
(function() {
// Serialize:
// Serialize the following types as follows:
// - primitives / null: unchanged
// - lists: [ 'list', id, list of recursively serialized elements ]
// - maps: [ 'map', id, map of keys and recursively serialized values ]
// - functions: [ 'funcref', function-proxy-id, function-proxy-send-port ]
// - objects: [ 'objref', object-proxy-id, object-proxy-send-port ]
// - lists: [ 'list', internal id, list of recursively serialized elements ]
// - maps: [ 'map', internal id, map of keys and recursively serialized values ]
// - send ports: [ 'sendport', type, isolate id, port id ]
//
// Note, internal id's are for cycle detection.
function serialize(message) {
var visited = [];
function checkedSerialization(obj, serializer) {
@ -85,27 +86,6 @@ function ReceivePortSync() {
return [ 'sendport', 'nativejs', message.receivePort.id ];
} else if (message instanceof DartSendPortSync) {
return [ 'sendport', 'dart', message.isolateId, message.portId ];
} else if (message instanceof Function) {
// In case we are reserializing a previously serialized
// function, use a cached value.
if (message._dart_serialized) return message._dart_serialized;
message._dart_serialized = [ 'funcref',
functionRefTable.makeRef(message),
doSerialize(functionRefTable.sendPort) ];
return message._dart_serialized;
} 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__) {
// TODO(vsm): Is the above portable and what we want?
// Proxy non-map Objects.
return [ 'objref', jsRefTable.makeRef(message),
doSerialize(jsRefTable.sendPort) ];
} else {
return checkedSerialization(message, function(id) {
var keys = Object.getOwnPropertyNames(message);
@ -135,9 +115,6 @@ function ReceivePortSync() {
case 'map': return deserializeMap(message);
case 'sendport': return deserializeSendPort(message);
case 'list': return deserializeList(message);
case 'funcref': return deserializeFunction(message);
case 'objref': return deserializeProxy(message);
case 'element': return deserializeElement(message);
default: throw 'unimplemented';
}
}
@ -180,33 +157,6 @@ function ReceivePortSync() {
return result;
}
function deserializeFunction(message) {
var ref = message[1];
var sendPort = deserializeSendPort(message[2]);
// Number of arguments is not used as of now
// we cannot find it out for Dart function in pure Dart.
var result = _makeFunctionFromRef(ref, sendPort);
// Cache the serialized form in case we resend this.
result._dart_serialized = message;
return result;
}
function deserializeProxy(message) {
var id = message[1];
var port = deserializeSendPort(message[2]);
if (port instanceof LocalSendPortSync) {
return jsRefTable.map[id];
} else if (port instanceof DartSendPortSync) {
return new DartProxy(port, id);
}
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;
@ -290,136 +240,4 @@ function ReceivePortSync() {
window.removeEventListener(source, listener, false);
return deserialize(result);
}
// Proxy support
function RefTable(name) {
// TODO(vsm): Fix leaks, particularly in dart2js case.
this.name = name;
this.map = {};
this.id = 0;
this.initialized = false;
this.port = new ReceivePortSync();
this.sendPort = this.port.toSendPort();
}
RefTable.prototype.nextId = function () { return this.id++; }
RefTable.prototype.makeRef = function (obj) {
this.initializeOnce();
// TODO(vsm): Cache refs for each obj.
var ref = this.name + '-' + this.nextId();
this.map[ref] = obj;
return ref;
}
RefTable.prototype.initializeOnce = function () {
if (!this.initialized) {
this.initialize();
}
this.initialized = true;
}
// Overridable initialization on first use hook.
RefTable.prototype.initialize = function () {}
RefTable.prototype.get = function (ref) {
return this.map[ref];
}
function FunctionRefTable() {}
FunctionRefTable.prototype = new RefTable('func-ref');
FunctionRefTable.prototype.initialize = function () {
var map = this.map;
this.port.receive(function (message) {
var id = message[0];
var args = message[1];
var f = map[id];
// TODO(vsm): Should we capture this automatically?
return f.apply(null, args);
});
}
var functionRefTable = new FunctionRefTable();
function JSRefTable() {}
JSRefTable.prototype = new RefTable('js-ref');
JSRefTable.prototype.initialize = function () {
var map = this.map;
this.port.receive(function (message) {
// TODO(vsm): Support a mechanism to register a handler here.
var receiver = map[message[0]];
var method = message[1];
var args = message[2];
if (method.indexOf("get:") == 0) {
// Getter.
var field = method.substring(4);
if (field in receiver && args.length == 0) {
return [ 'return', receiver[field] ];
}
} else if (method.indexOf("set:") == 0) {
// Setter.
var field = method.substring(4);
if (field in receiver && args.length == 1) {
return [ 'return', receiver[field] = args[0] ];
}
} else {
var f = receiver[method];
if (f) {
try {
var result = f.apply(receiver, args);
return [ 'return', result ];
} catch (e) {
return [ 'exception', e ];
}
}
}
return [ 'none' ];
});
}
var jsRefTable = new JSRefTable();
function DartProxy(port, id) {
this._port = port;
this._id = id;
}
// Leaking implementation.
// TODO(vsm): provide proper, backend-specific implementation.
function _makeFunctionFromRef(ref, sendPort) {
// If the sendPort is local, just return the underlying function.
// Otherwise, create a new function that forwards to the remote
// port.
if (sendPort instanceof LocalSendPortSync) {
return functionRefTable.map[ref];
}
return function() {
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];
}
})();

View file

@ -37910,43 +37910,6 @@ _serialize(var message) {
return new _JsSerializer().traverse(message);
}
class JsProxy {
SendPortSync _port;
final _id;
JsProxy._internal(this._port, this._id);
noSuchMethod(method, args) {
var result = _port.callSync([_id, method, args]);
switch (result[0]) {
case 'return': return result[1];
case 'exception': throw result[1];
case 'none': throw new NoSuchMethodException(this, method, args);
default: throw 'Invalid return value';
}
}
}
int _localNextElementId = 0;
const _DART_ID = 'data-dart_id';
_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) {
@ -37969,147 +37932,12 @@ class _JsSerializer extends _Serializer {
return [ 'sendport', 'dart',
x._receivePort._isolateId, x._receivePort._portId ];
}
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);
return [ 'objref', proxyId,
visitSendPortSync(_dartProxyRegistry._sendPort) ];
}
visitFunction(Function func) {
// Look for a cached serialization first. The cached version
// should point to the original port.
var serialized = _deserializedFunctionTable.find(func);
if (serialized != null) return serialized;
// Create a new serialization forwarding to this port.
return [ 'funcref',
_functionRegistry._add(func),
visitSendPortSync(_functionRegistry._sendPort), null ];
}
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
// not leaking (at least in most of the cases.)
// TODO: provide better, backend specific implementation.
class _Registry<T> {
final String _name;
int _nextId;
final Map<String, T> _registry;
final ReceivePortSync _port;
_Registry(this._name) :
_nextId = 0,
_registry = <T>{},
_port = new ReceivePortSync();
String _add(T x) {
// TODO(vsm): Cache x and reuse id.
final id = '$_name-${_nextId++}';
_registry[id] = x;
return id;
}
T _get(String id) {
return _registry[id];
}
get _sendPort => _port.toSendPort();
}
class _FunctionRegistry extends _Registry<Function> {
_FunctionRegistry() : super('func-ref') {
_port.receive((msg) {
final id = msg[0];
final args = msg[1];
final f = _registry[id];
switch (args.length) {
case 0: return f();
case 1: return f(args[0]);
case 2: return f(args[0], args[1]);
case 3: return f(args[0], args[1], args[2]);
case 4: return f(args[0], args[1], args[2], args[3]);
default: throw 'Unsupported number of arguments.';
}
});
}
}
_FunctionRegistry __functionRegistry;
get _functionRegistry {
if (__functionRegistry === null) __functionRegistry = new _FunctionRegistry();
return __functionRegistry;
}
/// End of function serialization implementation.
/// Object proxy implementation.
class _DartProxyRegistry extends _Registry<Object> {
_DartProxyRegistry() : super('dart-ref') {
_port.receive((msg) {
// TODO(vsm): Support a mechanism to register a handler here.
throw 'Invocation unsupported on Dart proxies';
});
}
}
_DartProxyRegistry __dartProxyRegistry;
get _dartProxyRegistry {
if (__dartProxyRegistry === null) {
__dartProxyRegistry = new _DartProxyRegistry();
}
return __dartProxyRegistry;
}
/// End of object proxy implementation.
_deserialize(var message) {
return new _JsDeserializer().deserialize(message);
}
// TODO(vsm): Replace this with a hash map once functions are
// hashable.
class _DeserializedFunctionTable {
List data;
_DeserializedFunctionTable() {
data = [];
}
find(Function f) {
for (var item in data) {
if (f == item[0]) return item[1];
}
return null;
}
add(Function f, x) {
data.add([f, x]);
}
}
_DeserializedFunctionTable __deserializedFunctionTable = null;
get _deserializedFunctionTable {
if (__deserializedFunctionTable == null) {
__deserializedFunctionTable = new _DeserializedFunctionTable();
}
return __deserializedFunctionTable;
}
class _JsDeserializer extends _Deserializer {
@ -38129,53 +37957,6 @@ class _JsDeserializer extends _Deserializer {
throw 'Illegal SendPortSync type: $tag';
}
}
deserializeObject(List x) {
String tag = x[0];
switch (tag) {
case 'funcref': return deserializeFunction(x);
case 'objref': return deserializeProxy(x);
case 'element': return deserializeElement(x);
default: throw 'Illegal object type: $x';
}
}
deserializeFunction(List x) {
var id = x[1];
// If the sendPort is local, just return the underlying function.
// Otherwise, create a new function that forwards to the remote
// port.
SendPortSync port = deserializeSendPort(x[2]);
if (port is _LocalSendPortSync) {
return _functionRegistry._get(id);
}
// TODO: Support varargs when there is support in the language.
var f = ([arg0 = _UNSPECIFIED, arg1 = _UNSPECIFIED,
arg2 = _UNSPECIFIED, arg3 = _UNSPECIFIED]) {
var args = [arg0, arg1, arg2, arg3];
var last = args.indexOf(_UNSPECIFIED);
if (last >= 0) args = args.getRange(0, last);
var message = [id, args];
return port.callSync(message);
};
_deserializedFunctionTable.add(f, x);
return f;
}
deserializeProxy(x) {
var id = x[1];
var port = deserializeSendPort(x[2]);
if (port is _JsSendPortSync) return new JsProxy._internal(port, id);
if (port is _LocalSendPortSync) return _dartProxyRegistry._get(id);
// TODO(vsm): Support this case.
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.

View file

@ -40943,43 +40943,6 @@ _serialize(var message) {
return new _JsSerializer().traverse(message);
}
class JsProxy {
SendPortSync _port;
final _id;
JsProxy._internal(this._port, this._id);
noSuchMethod(method, args) {
var result = _port.callSync([_id, method, args]);
switch (result[0]) {
case 'return': return result[1];
case 'exception': throw result[1];
case 'none': throw new NoSuchMethodException(this, method, args);
default: throw 'Invalid return value';
}
}
}
int _localNextElementId = 0;
const _DART_ID = 'data-dart_id';
_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) {
@ -41002,147 +40965,12 @@ class _JsSerializer extends _Serializer {
return [ 'sendport', 'dart',
x._receivePort._isolateId, x._receivePort._portId ];
}
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);
return [ 'objref', proxyId,
visitSendPortSync(_dartProxyRegistry._sendPort) ];
}
visitFunction(Function func) {
// Look for a cached serialization first. The cached version
// should point to the original port.
var serialized = _deserializedFunctionTable.find(func);
if (serialized != null) return serialized;
// Create a new serialization forwarding to this port.
return [ 'funcref',
_functionRegistry._add(func),
visitSendPortSync(_functionRegistry._sendPort), null ];
}
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
// not leaking (at least in most of the cases.)
// TODO: provide better, backend specific implementation.
class _Registry<T> {
final String _name;
int _nextId;
final Map<String, T> _registry;
final ReceivePortSync _port;
_Registry(this._name) :
_nextId = 0,
_registry = <T>{},
_port = new ReceivePortSync();
String _add(T x) {
// TODO(vsm): Cache x and reuse id.
final id = '$_name-${_nextId++}';
_registry[id] = x;
return id;
}
T _get(String id) {
return _registry[id];
}
get _sendPort => _port.toSendPort();
}
class _FunctionRegistry extends _Registry<Function> {
_FunctionRegistry() : super('func-ref') {
_port.receive((msg) {
final id = msg[0];
final args = msg[1];
final f = _registry[id];
switch (args.length) {
case 0: return f();
case 1: return f(args[0]);
case 2: return f(args[0], args[1]);
case 3: return f(args[0], args[1], args[2]);
case 4: return f(args[0], args[1], args[2], args[3]);
default: throw 'Unsupported number of arguments.';
}
});
}
}
_FunctionRegistry __functionRegistry;
get _functionRegistry {
if (__functionRegistry === null) __functionRegistry = new _FunctionRegistry();
return __functionRegistry;
}
/// End of function serialization implementation.
/// Object proxy implementation.
class _DartProxyRegistry extends _Registry<Object> {
_DartProxyRegistry() : super('dart-ref') {
_port.receive((msg) {
// TODO(vsm): Support a mechanism to register a handler here.
throw 'Invocation unsupported on Dart proxies';
});
}
}
_DartProxyRegistry __dartProxyRegistry;
get _dartProxyRegistry {
if (__dartProxyRegistry === null) {
__dartProxyRegistry = new _DartProxyRegistry();
}
return __dartProxyRegistry;
}
/// End of object proxy implementation.
_deserialize(var message) {
return new _JsDeserializer().deserialize(message);
}
// TODO(vsm): Replace this with a hash map once functions are
// hashable.
class _DeserializedFunctionTable {
List data;
_DeserializedFunctionTable() {
data = [];
}
find(Function f) {
for (var item in data) {
if (f == item[0]) return item[1];
}
return null;
}
add(Function f, x) {
data.add([f, x]);
}
}
_DeserializedFunctionTable __deserializedFunctionTable = null;
get _deserializedFunctionTable {
if (__deserializedFunctionTable == null) {
__deserializedFunctionTable = new _DeserializedFunctionTable();
}
return __deserializedFunctionTable;
}
class _JsDeserializer extends _Deserializer {
@ -41162,53 +40990,6 @@ class _JsDeserializer extends _Deserializer {
throw 'Illegal SendPortSync type: $tag';
}
}
deserializeObject(List x) {
String tag = x[0];
switch (tag) {
case 'funcref': return deserializeFunction(x);
case 'objref': return deserializeProxy(x);
case 'element': return deserializeElement(x);
default: throw 'Illegal object type: $x';
}
}
deserializeFunction(List x) {
var id = x[1];
// If the sendPort is local, just return the underlying function.
// Otherwise, create a new function that forwards to the remote
// port.
SendPortSync port = deserializeSendPort(x[2]);
if (port is _LocalSendPortSync) {
return _functionRegistry._get(id);
}
// TODO: Support varargs when there is support in the language.
var f = ([arg0 = _UNSPECIFIED, arg1 = _UNSPECIFIED,
arg2 = _UNSPECIFIED, arg3 = _UNSPECIFIED]) {
var args = [arg0, arg1, arg2, arg3];
var last = args.indexOf(_UNSPECIFIED);
if (last >= 0) args = args.getRange(0, last);
var message = [id, args];
return port.callSync(message);
};
_deserializedFunctionTable.add(f, x);
return f;
}
deserializeProxy(x) {
var id = x[1];
var port = deserializeSendPort(x[2]);
if (port is _JsSendPortSync) return new JsProxy._internal(port, id);
if (port is _LocalSendPortSync) return _dartProxyRegistry._get(id);
// TODO(vsm): Support this case.
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.

View file

@ -6,43 +6,6 @@ _serialize(var message) {
return new _JsSerializer().traverse(message);
}
class JsProxy {
SendPortSync _port;
final _id;
JsProxy._internal(this._port, this._id);
noSuchMethod(method, args) {
var result = _port.callSync([_id, method, args]);
switch (result[0]) {
case 'return': return result[1];
case 'exception': throw result[1];
case 'none': throw new NoSuchMethodException(this, method, args);
default: throw 'Invalid return value';
}
}
}
int _localNextElementId = 0;
const _DART_ID = 'data-dart_id';
_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) {
@ -65,147 +28,12 @@ class _JsSerializer extends _Serializer {
return [ 'sendport', 'dart',
x._receivePort._isolateId, x._receivePort._portId ];
}
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);
return [ 'objref', proxyId,
visitSendPortSync(_dartProxyRegistry._sendPort) ];
}
visitFunction(Function func) {
// Look for a cached serialization first. The cached version
// should point to the original port.
var serialized = _deserializedFunctionTable.find(func);
if (serialized != null) return serialized;
// Create a new serialization forwarding to this port.
return [ 'funcref',
_functionRegistry._add(func),
visitSendPortSync(_functionRegistry._sendPort), null ];
}
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
// not leaking (at least in most of the cases.)
// TODO: provide better, backend specific implementation.
class _Registry<T> {
final String _name;
int _nextId;
final Map<String, T> _registry;
final ReceivePortSync _port;
_Registry(this._name) :
_nextId = 0,
_registry = <T>{},
_port = new ReceivePortSync();
String _add(T x) {
// TODO(vsm): Cache x and reuse id.
final id = '$_name-${_nextId++}';
_registry[id] = x;
return id;
}
T _get(String id) {
return _registry[id];
}
get _sendPort => _port.toSendPort();
}
class _FunctionRegistry extends _Registry<Function> {
_FunctionRegistry() : super('func-ref') {
_port.receive((msg) {
final id = msg[0];
final args = msg[1];
final f = _registry[id];
switch (args.length) {
case 0: return f();
case 1: return f(args[0]);
case 2: return f(args[0], args[1]);
case 3: return f(args[0], args[1], args[2]);
case 4: return f(args[0], args[1], args[2], args[3]);
default: throw 'Unsupported number of arguments.';
}
});
}
}
_FunctionRegistry __functionRegistry;
get _functionRegistry {
if (__functionRegistry === null) __functionRegistry = new _FunctionRegistry();
return __functionRegistry;
}
/// End of function serialization implementation.
/// Object proxy implementation.
class _DartProxyRegistry extends _Registry<Object> {
_DartProxyRegistry() : super('dart-ref') {
_port.receive((msg) {
// TODO(vsm): Support a mechanism to register a handler here.
throw 'Invocation unsupported on Dart proxies';
});
}
}
_DartProxyRegistry __dartProxyRegistry;
get _dartProxyRegistry {
if (__dartProxyRegistry === null) {
__dartProxyRegistry = new _DartProxyRegistry();
}
return __dartProxyRegistry;
}
/// End of object proxy implementation.
_deserialize(var message) {
return new _JsDeserializer().deserialize(message);
}
// TODO(vsm): Replace this with a hash map once functions are
// hashable.
class _DeserializedFunctionTable {
List data;
_DeserializedFunctionTable() {
data = [];
}
find(Function f) {
for (var item in data) {
if (f == item[0]) return item[1];
}
return null;
}
add(Function f, x) {
data.add([f, x]);
}
}
_DeserializedFunctionTable __deserializedFunctionTable = null;
get _deserializedFunctionTable {
if (__deserializedFunctionTable == null) {
__deserializedFunctionTable = new _DeserializedFunctionTable();
}
return __deserializedFunctionTable;
}
class _JsDeserializer extends _Deserializer {
@ -225,53 +53,6 @@ class _JsDeserializer extends _Deserializer {
throw 'Illegal SendPortSync type: $tag';
}
}
deserializeObject(List x) {
String tag = x[0];
switch (tag) {
case 'funcref': return deserializeFunction(x);
case 'objref': return deserializeProxy(x);
case 'element': return deserializeElement(x);
default: throw 'Illegal object type: $x';
}
}
deserializeFunction(List x) {
var id = x[1];
// If the sendPort is local, just return the underlying function.
// Otherwise, create a new function that forwards to the remote
// port.
SendPortSync port = deserializeSendPort(x[2]);
if (port is _LocalSendPortSync) {
return _functionRegistry._get(id);
}
// TODO: Support varargs when there is support in the language.
var f = ([arg0 = _UNSPECIFIED, arg1 = _UNSPECIFIED,
arg2 = _UNSPECIFIED, arg3 = _UNSPECIFIED]) {
var args = [arg0, arg1, arg2, arg3];
var last = args.indexOf(_UNSPECIFIED);
if (last >= 0) args = args.getRange(0, last);
var message = [id, args];
return port.callSync(message);
};
_deserializedFunctionTable.add(f, x);
return f;
}
deserializeProxy(x) {
var id = x[1];
var port = deserializeSendPort(x[2]);
if (port is _JsSendPortSync) return new JsProxy._internal(port, id);
if (port is _LocalSendPortSync) return _dartProxyRegistry._get(id);
// TODO(vsm): Support this case.
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.

View file

@ -83,10 +83,6 @@ js_interop_1_test: Fail
js_interop_2_test: Fail
js_interop_3_test: Fail
js_interop_4_test: Fail
js_interop_func_passing_test: Fail
js_interop_obj_passing_test: Fail
js_interop_obj_invoke_test: Fail
js_interop_element_test: Fail
measurement_test: Fail
messageevent_test: Fail
mutationobserver_test: Fail
@ -129,10 +125,6 @@ indexeddb_4_test: Fail # Need window.mozIndexedDB instead of window.webkitIn
inner_frame_test: Skip
js_interop_3_test: Fail
js_interop_4_test: Fail
js_interop_func_passing_test: Fail
js_interop_obj_passing_test: Fail
js_interop_obj_invoke_test: Fail
js_interop_element_test: Fail
# Interfaces not implemented: SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGStylable
svg_3_test: Fail
svgelement_test: Fail

View file

@ -1,61 +0,0 @@
// 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));
});
}

View file

@ -1,97 +0,0 @@
// 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('JsInteropFuncPassingTest');
#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 dartToJsTest = """
var port = new ReceivePortSync();
port.receive(function (f) {
return f('fromJS');
});
window.registerPort('test1', port.toSendPort());
""";
var jsToDartTest = """
var port1 = window.lookupPort('test2a');
var result = port1.callSync(function (x) {
return x*2;
});
var port2 = window.lookupPort('test2b');
port2.callSync(result);
""";
var dartToJsToDartTest = """
var port = new ReceivePortSync();
port.receive(function (f) {
return f;
});
window.registerPort('test3', port.toSendPort());
""";
main() {
useHtmlConfiguration();
test('dart-to-js-function', () {
injectSource(dartToJsTest);
SendPortSync port = window.lookupPort('test1');
var result = port.callSync((msg) {
Expect.equals('fromJS', msg);
return 'received';
});
Expect.equals('received', result);
});
test('js-to-dart-function', () {
var port1 = new ReceivePortSync();
int invoked1 = 0;
port1.receive((f) {
++invoked1;
var data = f(21);
expect(data, equals(42));
return 'fromDart';
});
window.registerPort('test2a', port1.toSendPort());
var port2 = new ReceivePortSync();
int invoked2 = 0;
port2.receive((x) {
++invoked2;
expect(x, equals('fromDart'));
});
window.registerPort('test2b', port2.toSendPort());
injectSource(jsToDartTest);
expect(1, equals(invoked1));
expect(1, equals(invoked2));
});
test('dart-to-js-to-dart-function', () {
injectSource(dartToJsToDartTest);
validate(x) {
expect(x, equals('fromCaller'));
return 'fromCallee';
}
SendPortSync port = window.lookupPort('test3');
var f = port.callSync(validate);
var result = f('fromCaller');
Expect.equals('fromCallee', result);
});
}

View file

@ -1,51 +0,0 @@
// 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('JsInteropObjInvokeTest');
#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 jsProxyTest = """
function TestType(x) {
this.x = x;
}
TestType.prototype.razzle = function () {
return this.x * 2;
}
var data = new TestType(21);
var port = window.lookupPort('test1');
port.callSync(data);
""";
main() {
useHtmlConfiguration();
test('js-proxy', () {
int invoked = 0;
var port = new ReceivePortSync();
port.receive((data) {
expect(data.x, equals(21));
expect(data.razzle(), equals(42));
data.x = 100;
expect(data.razzle(), equals(200));
++invoked;
});
window.registerPort('test1', port.toSendPort());
injectSource(jsProxyTest);
expect(invoked, equals(1));
});
}

View file

@ -1,80 +0,0 @@
// 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('JsInteropObjPassingTest');
#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 jsProxyTest = """
function TestType(x) {
this.x = x;
}
TestType.prototype.razzle = function () {
return this.x * 2;
}
var data = new TestType(21);
var port1 = new ReceivePortSync();
port1.receive(function (x) {
return x.razzle();
});
window.registerPort('test1a', port1.toSendPort());
var port2 = window.lookupPort('test1b');
port2.callSync(data);
""";
var dartProxyTest = """
var port2 = new ReceivePortSync();
port2.receive(function (x) {
var port1 = window.lookupPort('test2a');
port1.callSync(x);
});
window.registerPort('test2b', port2.toSendPort());
""";
main() {
useHtmlConfiguration();
test('js-proxy', () {
int invoked = 0;
var port2 = new ReceivePortSync();
port2.receive((x) {
var port1 = window.lookupPort('test1a');
var result = port1.callSync(x);
expect(result, equals(42));
++invoked;
});
window.registerPort('test1b', port2.toSendPort());
injectSource(jsProxyTest);
expect(invoked, equals(1));
});
test('dart-proxy', () {
injectSource(dartProxyTest);
var buffer = new StringBuffer();
buffer.add('hello');
var port1 = new ReceivePortSync();
port1.receive((x) => x.add(' from dart'));
window.registerPort('test2a', port1.toSendPort());
var port2 = window.lookupPort('test2b');
port2.callSync(buffer);
expect(buffer.toString(), equals('hello from dart'));
});
}