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

Unified Diff: lib/dart_interop.js

Issue 12457030: [js-interop] Fix function binding and avoid noSuchMethod when using map notation (Closed) Base URL: https://github.com/dart-lang/js-interop.git@master
Patch Set: Fix for constructors plus cleanup Created 7 years, 8 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 | lib/js.dart » ('j') | lib/js.dart » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
« no previous file with comments | « no previous file | lib/js.dart » ('j') | lib/js.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698