Closed Bug 658266 Opened 13 years ago Closed 11 years ago

[Harmony]Proxy: 'this' in getter/setter doesn't indicate the proxy object

Categories

(Core :: JavaScript Engine, defect)

x86
Windows XP
defect
Not set
normal

Tracking

()

RESOLVED INVALID

People

(Reporter: teramako, Unassigned)

References

Details

(Whiteboard: js-triage-needed)

User-Agent:       Mozilla/5.0 (Windows NT 5.1; rv:6.0a1) Gecko/20110518 Firefox/6.0a1
Build Identifier: Mozilla/5.0 (Windows NT 5.1; rv:6.0a1) Gecko/20110518 Firefox/6.0a1

I noticed that 'this' in a normal method (getGreeting) indicates the created proxy object, but 'this' in getter/setter indicates the original object. 
Is this expected result ?

var o = {
  name: "foo",
  getGreeting: function(){
    console.log("getGreeting: ", this === o, this === p); // result: false true
    return "Hello, " + this.name;
  },
  get greeting () {
    console.log("getGreeting: ", this === o, this === p); // result: true false
    return "Hello, " + this.name;
  },
};
var handler = {
  target: o,
  get: function (_, name) {
    console.log("[Handler]Getting:", name);
    return this.target[name];
  }
};
var p = Proxy.create(handler);
console.info("p,getGreeting()")
p.getGreeting();
console.info("p.greeting");
p.greeting;


Reproducible: Always


Actual Results:
Whiteboard: js-triage-needed
No longer blocks: harmony:proxy
This is not a bug, but expected behavior.

The reason is that in the "get" trap, in the case of the accessor, |return this.target[name]| will trigger the accessor on |this.target| with |this| bound to the target, as it should.

In the case of the method, |this.target[name]| returns a function, which is then called with |this| bound to the proxy.

To write proxies that leave |this| in accessors bound to the proxy, you should make use of the third argument passed into the "get" trap:

get: function(target, name, receiver) {
  console.log("[Handler]Getting:", name);
  return Reflect.get(target, name, receiver);
}

The |receiver| argument refers to the proxy itself.

The |Reflect.get(target,name,receiver)| method basically does the same as |this.target[name]|, except that if target.name is an accessor, it will call the accessor with |this| bound to |receiver|.

To my knowledge, the Reflect object does not yet exist in current implementations (it will be provided as a module in ECMAScript 6). But it can be implemented in JavaScript today. For an example implementation, see: <https://github.com/tvcutsem/harmony-reflect/blob/master/reflect.js#L1489>

If you are only interested in the code implementing Reflect.get, look at <https://github.com/tvcutsem/harmony-reflect/blob/master/reflect.js#L1604> (you only need lines 1604-1620).
Status: UNCONFIRMED → RESOLVED
Closed: 11 years ago
Resolution: --- → INVALID
(In reply to Tom Van Cutsem from comment #1)

I get it. Thank you very much :)
You need to log in before you can comment on or make changes to this bug.