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

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

Issue 26270003: Cleanup JS() expressions. New Constructor for JsObject that preserves the correct prototype. Type c… (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 | sdk/lib/js/dart2js/js_dart2js.dart » ('j') | 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 8577e4f28b8c30aa67270ff78727da5789d0bea0..71af132522e77c5ef3f49b7b27e40535760acc3d 100644
--- a/pkg/browser/lib/interop.js
+++ b/pkg/browser/lib/interop.js
@@ -14,7 +14,7 @@ function ReceivePortSync() {
}
// Type for remote proxies to Dart objects with dart2js.
-function DartProxy(o) {
+function DartObject(o) {
this.o = o;
}
@@ -250,17 +250,40 @@ function DartProxy(o) {
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) {
- for (var ref in this.map) {
- var o = this.map[ref];
- if (o === obj) {
- return ref;
+ 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;
}
- var ref = this.name + '-' + this._nextId++;
- this.map[ref] = obj;
- 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.
@@ -328,7 +351,7 @@ function DartProxy(o) {
proxiedObjectTable._initialize()
// Type for remote proxies to Dart objects.
- function DartProxy(id, sendPort) {
+ function DartObject(id, sendPort) {
this.id = id;
this.port = sendPort;
}
@@ -361,7 +384,7 @@ function DartProxy(o) {
proxiedObjectTable.add(message),
proxiedObjectTable.sendPort ];
}
- } else if (message instanceof DartProxy) {
+ } else if (message instanceof DartObject) {
// Remote object proxy.
return [ 'objref', message.id, message.port ];
} else {
@@ -402,6 +425,9 @@ function DartProxy(o) {
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);
@@ -413,11 +439,12 @@ function DartProxy(o) {
// Cache the remote id and port.
f._dart_id = id;
f._dart_port = port;
+ proxiedObjectTable.add(f, id);
return f;
}
}
- // Creates a DartProxy to forwards to the remote object.
+ // Creates a DartObject to forwards to the remote object.
function deserializeObject(message) {
var id = message[1];
var port = message[2];
@@ -427,7 +454,12 @@ function DartProxy(o) {
return proxiedObjectTable.get(id);
} else {
// Remote object.
- return new DartProxy(id, port);
+ if (proxiedObjectTable.contains(id)) {
+ return proxiedObjectTable.get(id);
+ }
+ proxy = new DartObject(id, port);
+ proxiedObjectTable.add(proxy, id);
+ return proxy;
}
}
@@ -436,52 +468,16 @@ function DartProxy(o) {
function construct(args) {
args = args.map(deserialize);
var constructor = args[0];
- args = Array.prototype.slice.call(args, 1);
-
- // Until 10 args, the 'new' operator is used. With more arguments we use a
- // generic way that may not work, particularly when the constructor does not
- // have an "apply" method.
- var ret = null;
- if (args.length === 0) {
- ret = new constructor();
- } else if (args.length === 1) {
- ret = new constructor(args[0]);
- } else if (args.length === 2) {
- ret = new constructor(args[0], args[1]);
- } else if (args.length === 3) {
- ret = new constructor(args[0], args[1], args[2]);
- } else if (args.length === 4) {
- ret = new constructor(args[0], args[1], args[2], args[3]);
- } else if (args.length === 5) {
- ret = new constructor(args[0], args[1], args[2], args[3], args[4]);
- } else if (args.length === 6) {
- ret = new constructor(args[0], args[1], args[2], args[3], args[4],
- args[5]);
- } else if (args.length === 7) {
- ret = new constructor(args[0], args[1], args[2], args[3], args[4],
- args[5], args[6]);
- } else if (args.length === 8) {
- ret = new constructor(args[0], args[1], args[2], args[3], args[4],
- args[5], args[6], args[7]);
- } else if (args.length === 9) {
- ret = new constructor(args[0], args[1], args[2], args[3], args[4],
- args[5], args[6], args[7], args[8]);
- } else if (args.length === 10) {
- ret = new constructor(args[0], args[1], args[2], args[3], args[4],
- args[5], args[6], args[7], args[8], args[9]);
- } else {
- // Dummy Type with correct constructor.
- var Type = function(){};
- Type.prototype = constructor.prototype;
- // Create a new instance
- var instance = new Type();
-
- // Call the original constructor.
- ret = constructor.apply(instance, args);
- ret = Object(ret) === ret ? ret : instance;
- }
- return serialize(ret);
+ // 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.
« no previous file with comments | « no previous file | sdk/lib/js/dart2js/js_dart2js.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698