With ordinary objects, methods and property getter functions are both invoked on the object itself. If this object is proxied with Proxy.Handler, however, the property getter function will be invoked on the original object and the method will be invoked on the proxy object. The code below demonstrates.

I find this surprising, though I'm not sure whether it constitutes a bug in Proxy.Handler. I do think it is at least a reason why the receiver argument to get() is necessary and should not be removed as proposed by http://wiki.ecmascript.org/doku.php?id=strawman:proxy_drop_receiver

The code that demonstrates this is below. It runs in the current Firefox Aurora. I have actually been affected by this issue when the proxy object is stored in a WeakMap but the object it is forwarding to is not in the WeakMap.

    David Flanagan


if (this.console) print = console.log.bind(console);

// An object with an accessor property and a method.
var o = {
    get property() { return map.get(this); },
    method: function() { return map.get(this); }
};

var map = new WeakMap();
map.set(o, "o");

// Both the getter function and method are invoked on o
print(o.property);         // prints "o"
print(o.method());         // prints "o"

// This works for inherited properties and methods, too
var p = Object.create(o);
map.set(p, "p");
print(p.property);        // prints "p"
print(p.method());        // ditto


// When we create a proxy with a forwarding handler, though, the this value
// is different in the two cases.
var handler = {
    target: o,
    get: function(receiver, name) {
        return this.target[name];  // Same as Proxy.Handler.prototype.get
    }
}

var q = Proxy.create(handler);
map.set(q, "q");
print(q.property);   // Prints "o"
print(q.method());   // Prints "q"

// In order to invoke the getter function on the same object as the method
// we have to go to more trouble and use code that is probably much slower.
// And, we need that first receiver argument.
var handler2 = {
    target: o,
    get: function(receiver, name) {
        var d = Object.getOwnPropertyDescriptor(this.target, name);
        if (d.value) return d.value;
        else return d.get.call(receiver);
    }
};

var r = Proxy.create(handler2);
map.set(r, "r");
print(r.property);   // Prints "r"
print(r.method());   // Prints "r"


_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to