Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1254)

Unified Diff: pkg/browser/lib/interop.js

Issue 49793003: Remove sync ports from interop.js (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/browser/lib/interop.js
diff --git a/pkg/browser/lib/interop.js b/pkg/browser/lib/interop.js
index 1caeb5a209937eb0967c211bd0bc1e4a8a59926b..f4087dc745e80800184b2e14bab399503a79a16c 100644
--- a/pkg/browser/lib/interop.js
+++ b/pkg/browser/lib/interop.js
@@ -2,536 +2,8 @@
// 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.
-// ---------------------------------------------------------------------------
-// Support for JS interoperability
-// ---------------------------------------------------------------------------
-function SendPortSync() {
-}
-
-function ReceivePortSync() {
- this.id = ReceivePortSync.id++;
- ReceivePortSync.map[this.id] = this;
-}
-
// Type for remote proxies to Dart objects with dart2js.
+// WARNING: do not call this constructor
Jacob 2013/10/28 21:36:59 missing period.
function DartObject(o) {
this.o = o;
}
-
-(function() {
- // Serialize the following types as follows:
- // - primitives / null: unchanged
- // - 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) {
- // Implementation detail: for now use linear search.
- // Another option is expando, but it may prohibit
- // VM optimizations (like putting object into slow mode
- // on property deletion.)
- var id = visited.indexOf(obj);
- if (id != -1) return [ 'ref', id ];
- var id = visited.length;
- visited.push(obj);
- return serializer(id);
- }
-
- function doSerialize(message) {
- if (message == null) {
- return null; // Convert undefined to null.
- } else if (typeof(message) == 'string' ||
- typeof(message) == 'number' ||
- typeof(message) == 'boolean') {
- return message;
- } else if (message instanceof Array) {
- return checkedSerialization(message, function(id) {
- var values = new Array(message.length);
- for (var i = 0; i < message.length; i++) {
- values[i] = doSerialize(message[i]);
- }
- return [ 'list', id, values ];
- });
- } else if (message instanceof LocalSendPortSync) {
- return [ 'sendport', 'nativejs', message.receivePort.id ];
- } else if (message instanceof DartSendPortSync) {
- return [ 'sendport', 'dart', message.isolateId, message.portId ];
- } else {
- return checkedSerialization(message, function(id) {
- var keys = Object.getOwnPropertyNames(message);
- var values = new Array(keys.length);
- for (var i = 0; i < keys.length; i++) {
- values[i] = doSerialize(message[keys[i]]);
- }
- return [ 'map', id, keys, values ];
- });
- }
- }
- return doSerialize(message);
- }
-
- function deserialize(message) {
- return deserializeHelper(message);
- }
-
- function deserializeHelper(message) {
- if (message == null ||
- typeof(message) == 'string' ||
- typeof(message) == 'number' ||
- typeof(message) == 'boolean') {
- return message;
- }
- switch (message[0]) {
- case 'map': return deserializeMap(message);
- case 'sendport': return deserializeSendPort(message);
- case 'list': return deserializeList(message);
- default: throw 'unimplemented';
- }
- }
-
- function deserializeMap(message) {
- var result = { };
- var id = message[1];
- var keys = message[2];
- var values = message[3];
- for (var i = 0, length = keys.length; i < length; i++) {
- var key = deserializeHelper(keys[i]);
- var value = deserializeHelper(values[i]);
- result[key] = value;
- }
- return result;
- }
-
- function deserializeSendPort(message) {
- var tag = message[1];
- switch (tag) {
- case 'nativejs':
- var id = message[2];
- return new LocalSendPortSync(ReceivePortSync.map[id]);
- case 'dart':
- var isolateId = message[2];
- var portId = message[3];
- return new DartSendPortSync(isolateId, portId);
- default:
- throw 'Illegal SendPortSync type: $tag';
- }
- }
-
- function deserializeList(message) {
- var values = message[2];
- var length = values.length;
- var result = new Array(length);
- for (var i = 0; i < length; i++) {
- result[i] = deserializeHelper(values[i]);
- }
- return result;
- }
-
- window.registerPort = function(name, port) {
- var stringified = JSON.stringify(serialize(port));
- var attrName = 'dart-port:' + name;
- document.documentElement.setAttribute(attrName, stringified);
- };
-
- window.lookupPort = function(name) {
- var attrName = 'dart-port:' + name;
- var stringified = document.documentElement.getAttribute(attrName);
- return deserialize(JSON.parse(stringified));
- };
-
- ReceivePortSync.id = 0;
- ReceivePortSync.map = {};
-
- ReceivePortSync.dispatchCall = function(id, message) {
- // TODO(vsm): Handle and propagate exceptions.
- var deserialized = deserialize(message);
- var result = ReceivePortSync.map[id].callback(deserialized);
- return serialize(result);
- };
-
- ReceivePortSync.prototype.receive = function(callback) {
- this.callback = callback;
- };
-
- ReceivePortSync.prototype.toSendPort = function() {
- return new LocalSendPortSync(this);
- };
-
- ReceivePortSync.prototype.close = function() {
- delete ReceivePortSync.map[this.id];
- };
-
- if (navigator.webkitStartDart) {
- window.addEventListener('js-sync-message', function(event) {
- var data = JSON.parse(getPortSyncEventData(event));
- var deserialized = deserialize(data.message);
- var result = ReceivePortSync.map[data.id].callback(deserialized);
- // TODO(vsm): Handle and propagate exceptions.
- dispatchEvent('js-result', serialize(result));
- }, false);
- }
-
- function LocalSendPortSync(receivePort) {
- this.receivePort = receivePort;
- }
-
- LocalSendPortSync.prototype = new SendPortSync();
-
- LocalSendPortSync.prototype.callSync = function(message) {
- // TODO(vsm): Do a direct deepcopy.
- message = deserialize(serialize(message));
- return this.receivePort.callback(message);
- }
-
- function DartSendPortSync(isolateId, portId) {
- this.isolateId = isolateId;
- this.portId = portId;
- }
-
- DartSendPortSync.prototype = new SendPortSync();
-
- function dispatchEvent(receiver, message) {
- var string = JSON.stringify(message);
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent(receiver, false, false, string);
- window.dispatchEvent(event);
- }
-
- function getPortSyncEventData(event) {
- return event.detail;
- }
-
- DartSendPortSync.prototype.callSync = function(message) {
- var serialized = serialize(message);
- var target = 'dart-port-' + this.isolateId + '-' + this.portId;
- // TODO(vsm): Make this re-entrant.
- // TODO(vsm): Set this up set once, on the first call.
- var source = target + '-result';
- var result = null;
- var listener = function (e) {
- result = JSON.parse(getPortSyncEventData(e));
- };
- window.addEventListener(source, listener, false);
- dispatchEvent(target, [source, serialized]);
- window.removeEventListener(source, listener, false);
- return deserialize(result);
- }
-})();
-
-(function() {
- // Proxy support for js.dart.
-
- // We don't use 'window' because we might be in a web worker, but we don't
- // use 'self' because not all browsers support it
- var globalContext = function() { return this; }();
-
- // Table for local objects and functions that are proxied.
- function ProxiedObjectTable() {
- // Name for debugging.
- this.name = 'js-ref';
-
- // Table from IDs to JS objects.
- this.map = {};
-
- // Generator for new IDs.
- this._nextId = 0;
-
- // Ports for managing communication to proxies.
- this.port = new ReceivePortSync();
- this.sendPort = this.port.toSendPort();
- }
-
- // Number of valid IDs. This is the number of objects (global and local)
- // kept alive by this table.
- ProxiedObjectTable.prototype.count = function () {
- return Object.keys(this.map).length;
- }
-
- var _dartRefPropertyName = "_$dart_ref";
-
- // attempts to add an unenumerable property to o. If that is not allowed
- // it silently fails.
- function _defineProperty(o, name, value) {
- if (Object.isExtensible(o)) {
- try {
- Object.defineProperty(o, name, { 'value': value });
- } catch (e) {
- // object is native and lies about being extensible
- // see https://bugzilla.mozilla.org/show_bug.cgi?id=775185
- }
- }
- }
-
- // Adds an object to the table and return an ID for serialization.
- ProxiedObjectTable.prototype.add = function (obj, id) {
- if (id != null) {
- this.map[id] = obj;
- return id;
- } else {
- var ref = obj[_dartRefPropertyName];
- if (ref == null) {
- ref = this.name + '-' + this._nextId++;
- this.map[ref] = obj;
- _defineProperty(obj, _dartRefPropertyName, ref);
- }
- return ref;
- }
- }
-
- // Gets the object or function corresponding to this ID.
- ProxiedObjectTable.prototype.contains = function (id) {
- return this.map.hasOwnProperty(id);
- }
-
- // Gets the object or function corresponding to this ID.
- ProxiedObjectTable.prototype.get = function (id) {
- if (!this.map.hasOwnProperty(id)) {
- throw 'Proxy ' + id + ' has been invalidated.'
- }
- return this.map[id];
- }
-
- ProxiedObjectTable.prototype._initialize = function () {
- // Configure this table's port to forward methods, getters, and setters
- // from the remote proxy to the local object.
- var table = this;
-
- this.port.receive(function (message) {
- // TODO(vsm): Support a mechanism to register a handler here.
- try {
- var receiver = table.get(message[0]);
- var member = message[1];
- var kind = message[2];
- var args = message[3].map(deserialize);
- if (kind == 'get') {
- // Getter.
- var field = member;
- if (field in receiver && args.length == 0) {
- return [ 'return', serialize(receiver[field]) ];
- }
- } else if (kind == 'set') {
- // Setter.
- var field = member;
- if (args.length == 1) {
- return [ 'return', serialize(receiver[field] = args[0]) ];
- }
- } else if (kind == 'hasProperty') {
- var field = member;
- return [ 'return', field in receiver ];
- } else if (kind == 'apply') {
- // Direct function invocation.
- return [ 'return',
- serialize(receiver.apply(args[0], args.slice(1))) ];
- } else if (member == '[]' && args.length == 1) {
- // Index getter.
- return [ 'return', serialize(receiver[args[0]]) ];
- } else if (member == '[]=' && args.length == 2) {
- // Index setter.
- return [ 'return', serialize(receiver[args[0]] = args[1]) ];
- } else {
- // Member function invocation.
- var f = receiver[member];
- if (f) {
- var result = f.apply(receiver, args);
- return [ 'return', serialize(result) ];
- }
- }
- return [ 'none' ];
- } catch (e) {
- return [ 'throws', e.toString() ];
- }
- });
- }
-
- // Singleton for local proxied objects.
- var proxiedObjectTable = new ProxiedObjectTable();
- proxiedObjectTable._initialize()
-
- // Type for remote proxies to Dart objects.
- function DartObject(id, sendPort) {
- this.id = id;
- this.port = sendPort;
- }
-
- // Serializes JS types to SendPortSync format:
- // - primitives -> primitives
- // - sendport -> sendport
- // - Function -> [ 'funcref', function-id, sendport ]
- // - Object -> [ 'objref', object-id, sendport ]
- function serialize(message) {
- if (message == null) {
- return null; // Convert undefined to null.
- } else if (typeof(message) == 'string' ||
- typeof(message) == 'number' ||
- typeof(message) == 'boolean') {
- // Primitives are passed directly through.
- return message;
- } else if (message instanceof SendPortSync) {
- // Non-proxied objects are serialized.
- return message;
- } else if (typeof(message) == 'function') {
- if ('_dart_id' in message) {
- // Remote function proxy.
- var remoteId = message._dart_id;
- var remoteSendPort = message._dart_port;
- return [ 'funcref', remoteId, remoteSendPort ];
- } else {
- // Local function proxy.
- return [ 'funcref',
- proxiedObjectTable.add(message),
- proxiedObjectTable.sendPort ];
- }
- } else if (message instanceof DartObject) {
- // Remote object proxy.
- return [ 'objref', message.id, message.port ];
- } else {
- // Local object proxy.
- return [ 'objref',
- proxiedObjectTable.add(message),
- proxiedObjectTable.sendPort ];
- }
- }
-
- function deserialize(message) {
- if (message == null) {
- return null; // Convert undefined to null.
- } else if (typeof(message) == 'string' ||
- typeof(message) == 'number' ||
- typeof(message) == 'boolean') {
- // Primitives are passed directly through.
- return message;
- } else if (message instanceof SendPortSync) {
- // Serialized type.
- return message;
- }
- var tag = message[0];
- switch (tag) {
- case 'funcref': return deserializeFunction(message);
- case 'objref': return deserializeObject(message);
- }
- throw 'Unsupported serialized data: ' + message;
- }
-
- // Create a local function that forwards to the remote function.
- function deserializeFunction(message) {
- var id = message[1];
- var port = message[2];
- // TODO(vsm): Add a more robust check for a local SendPortSync.
- if ("receivePort" in port) {
- // Local function.
- return proxiedObjectTable.get(id);
- } else {
- // Remote function. Forward to its port.
- if (proxiedObjectTable.contains(id)) {
- return proxiedObjectTable.get(id);
- }
- var f = function () {
- var args = Array.prototype.slice.apply(arguments);
- args.splice(0, 0, this);
- args = args.map(serialize);
- var result = port.callSync([id, '#call', args]);
- if (result[0] == 'throws') throw deserialize(result[1]);
- return deserialize(result[1]);
- };
- // Cache the remote id and port.
- f._dart_id = id;
- f._dart_port = port;
- proxiedObjectTable.add(f, id);
- return f;
- }
- }
-
- // Creates a DartObject to forwards to the remote object.
- function deserializeObject(message) {
- var id = message[1];
- var port = message[2];
- // TODO(vsm): Add a more robust check for a local SendPortSync.
- if ("receivePort" in port) {
- // Local object.
- return proxiedObjectTable.get(id);
- } else {
- // Remote object.
- if (proxiedObjectTable.contains(id)) {
- return proxiedObjectTable.get(id);
- }
- var proxy = new DartObject(id, port);
- proxiedObjectTable.add(proxy, id);
- return proxy;
- }
- }
-
- // Remote handler to construct a new JavaScript object given its
- // serialized constructor and arguments.
- function construct(args) {
- args = args.map(deserialize);
- var constructor = args[0];
-
- // The following code solves the problem of invoking a JavaScript
- // constructor with an unknown number arguments.
- // First bind the constructor to the argument list using bind.apply().
- // The first argument to bind() is the binding of 'this', make it 'null'
- // After that, use the JavaScript 'new' operator which overrides any binding
- // of 'this' with the new instance.
- args[0] = null;
- var factoryFunction = constructor.bind.apply(constructor, args);
- return serialize(new factoryFunction());
- }
-
- // Remote handler to return the top-level JavaScript context.
- function context(data) {
- return serialize(globalContext);
- }
-
- // Return true if a JavaScript proxy is instance of a given type (instanceof).
- function proxyInstanceof(args) {
- var obj = deserialize(args[0]);
- var type = deserialize(args[1]);
- return obj instanceof type;
- }
-
- // Return true if a JavaScript proxy is instance of a given type (instanceof).
- function proxyDeleteProperty(args) {
- var obj = deserialize(args[0]);
- var member = deserialize(args[1]);
- delete obj[member];
- }
-
- function proxyConvert(args) {
- return serialize(deserializeDataTree(args));
- }
-
- function deserializeDataTree(data) {
- var type = data[0];
- var value = data[1];
- if (type === 'map') {
- var obj = {};
- for (var i = 0; i < value.length; i++) {
- obj[value[i][0]] = deserializeDataTree(value[i][1]);
- }
- return obj;
- } else if (type === 'list') {
- var list = [];
- for (var i = 0; i < value.length; i++) {
- list.push(deserializeDataTree(value[i]));
- }
- return list;
- } else /* 'simple' */ {
- return deserialize(value);
- }
- }
-
- function makeGlobalPort(name, f) {
- var port = new ReceivePortSync();
- port.receive(f);
- window.registerPort(name, port.toSendPort());
- }
-
- makeGlobalPort('dart-js-context', context);
- makeGlobalPort('dart-js-create', construct);
- makeGlobalPort('dart-js-instanceof', proxyInstanceof);
- makeGlobalPort('dart-js-delete-property', proxyDeleteProperty);
- makeGlobalPort('dart-js-convert', proxyConvert);
-})();
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698