| Index: lib/dart_interop.js
|
| diff --git a/lib/dart_interop.js b/lib/dart_interop.js
|
| index bef5a0efbdb21ae306491f6eec428719065ce41d..6e41166a0ee966704ce2f5d2d1cd38339c079ad4 100644
|
| --- a/lib/dart_interop.js
|
| +++ b/lib/dart_interop.js
|
| @@ -12,6 +12,36 @@
|
|
|
| var globalContext = window;
|
|
|
| + // Support for binding the receiver (this) in proxied functions.
|
| + function bindIfFunction(f, _this) {
|
| + if (typeof(f) != "function") {
|
| + return f;
|
| + } else {
|
| + return new BoundFunction(_this, f);
|
| + }
|
| + }
|
| +
|
| + function unbind(obj) {
|
| + if (obj instanceof BoundFunction) {
|
| + return obj.object;
|
| + } else {
|
| + return obj;
|
| + }
|
| + }
|
| +
|
| + function getBoundThis(obj) {
|
| + if (obj instanceof BoundFunction) {
|
| + return obj._this;
|
| + } else {
|
| + return globalContext;
|
| + }
|
| + }
|
| +
|
| + function BoundFunction(_this, object) {
|
| + this._this = _this;
|
| + this.object = object;
|
| + }
|
| +
|
| // Table for local objects and functions that are proxied.
|
| function ProxiedObjectTable() {
|
| // Name for debugging.
|
| @@ -127,7 +157,8 @@
|
| this.port.receive(function (message) {
|
| // TODO(vsm): Support a mechanism to register a handler here.
|
| try {
|
| - var receiver = table.get(message[0]);
|
| + var object = table.get(message[0]);
|
| + var receiver = unbind(object);
|
| var member = message[1];
|
| var kind = message[2];
|
| var args = message[3].map(deserialize);
|
| @@ -135,7 +166,8 @@
|
| // Getter.
|
| var field = member;
|
| if (field in receiver && args.length == 0) {
|
| - return [ 'return', serialize(receiver[field]) ];
|
| + var result = bindIfFunction(receiver[field], receiver);
|
| + return [ 'return', serialize(result) ];
|
| }
|
| } else if (kind == 'set') {
|
| // Setter.
|
| @@ -145,15 +177,17 @@
|
| }
|
| } else if (kind == 'apply') {
|
| // Direct function invocation.
|
| - // TODO(vsm): Should we capture _this_ automatically?
|
| - return [ 'return', serialize(receiver.apply(null, args)) ];
|
| + var _this = getBoundThis(object);
|
| + return [ 'return', serialize(receiver.apply(_this, args)) ];
|
| } else if (member == '[]' && args.length == 1) {
|
| // Index getter.
|
| - return [ 'return', serialize(receiver[args[0]]) ];
|
| + var result = bindIfFunction(receiver[args[0]], receiver);
|
| + return [ 'return', serialize(result) ];
|
| } 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);
|
| @@ -276,6 +310,12 @@
|
| } else if (message instanceof Element &&
|
| (message.ownerDocument == null || message.ownerDocument == document)) {
|
| return [ 'domref', serializeElement(message) ];
|
| + } else if (message instanceof BoundFunction &&
|
| + typeof(message.object) == 'function') {
|
| + // Local function proxy.
|
| + return [ 'funcref',
|
| + proxiedObjectTable.add(message),
|
| + proxiedObjectTable.sendPort ];
|
| } else if (typeof(message) == 'function') {
|
| if ('_dart_id' in message) {
|
| // Remote function proxy.
|
| @@ -366,7 +406,7 @@
|
| // serialized constructor and arguments.
|
| function construct(args) {
|
| args = args.map(deserialize);
|
| - var constructor = args[0];
|
| + var constructor = unbind(args[0]);
|
| args = Array.prototype.slice.call(args, 1);
|
|
|
| // Until 10 args, the 'new' operator is used. With more arguments we use a
|
| @@ -435,12 +475,16 @@
|
|
|
| // Return true if a JavaScript proxy is instance of a given type (instanceof).
|
| function proxyInstanceof(args) {
|
| - return deserialize(args[0]) instanceof deserialize(args[1]);
|
| + var obj = unbind(deserialize(args[0]));
|
| + var type = unbind(deserialize(args[1]));
|
| + return obj instanceof type;
|
| }
|
|
|
| // Return true if a JavaScript proxy is instance of a given type (instanceof).
|
| function proxyDeleteProperty(args) {
|
| - delete deserialize(args[0])[deserialize(args[1])];
|
| + var obj = unbind(deserialize(args[0]));
|
| + var member = unbind(deserialize(args[1]));
|
| + delete obj[member];
|
| }
|
|
|
| function proxyConvert(args) {
|
|
|