tvcutsem / harmony-reflect

ES5 shim for ES6 Reflect and Proxy objects
http://www.ecma-international.org/ecma-262/6.0/#sec-reflection
Other
478 stars 48 forks source link

Can't trap invoke for all methods of a given proxy #22

Closed angus-c closed 10 years ago

angus-c commented 11 years ago

I suspect this is because the get trap is overriding the apply trap because the method is accessed before it is invoked. But wanted to check it's not due to my own bad code. Thanks!...

require('harmony-reflect');
function getApplyProxy(fn) {
  console.log(fn); //logged as expected
  //get trap also required?...
  return Proxy(
    fn,
    { apply: function() {
       console.log(arguments)
    }}
  )
}

var fnMonitor = Proxy(
  {},
  { get: function(t,p) {
    return (typeof t[p] == 'function' ? getApplyProxy(t[p]) : t[p]);
  }}
);

var Obj = function() {};
Obj.prototype = fnMonitor;

var a = new Obj;
a.fn = function() {};
a.fn(); //undefined(!)
tvcutsem commented 11 years ago

You get undefined because a.fn in the last line of code will not trigger the fnMonitor proxy's get trap, but instead it will just retrieve the property assigned to it on the previous line and execute that function.

If you make an object (call it the "child") inherit from a proxy, like you did here with a, then the proxy's "get" and "set" traps only get invoked for properties that the child object does not define itself.

Think of method lookup as starting at the child. If the child defines the property, it is returned immediately. If the child does not define it, lookup continues in the child's prototype. When this prototype chain traversal hits a proxy, the proxy's "get" trap is called.

So, your fnMonitor trick would work fine for catching all non-existent property accesses on a (like __noSuchMethod__ in Spidermonkey) but it doesn't work for intercepting existing properties.

angus-c commented 11 years ago

got it - thanks for clarifying

On Mon, Oct 21, 2013 at 1:34 PM, Tom Van Cutsem notifications@github.comwrote:

You get undefined because a.fn in the last line of code will _not_trigger the fnMonitor proxy's get trap, but instead it will just retrieve the property assigned to it on the previous line and execute that function.

If you make an object (call it the "child") inherit from a proxy, like you did here with a, then the proxy's "get" and "set" traps only get invoked for properties that the child object does not define itself.

Think of method lookup as starting at the child. If the child defines the property, it is returned immediately. If the child does not define it, lookup continues in the child's prototype. When this prototype chain traversal hits a proxy, the proxy's "get" trap is called.

So, your fnMonitor trick would work fine for catching all non-existent property accesses on a (like noSuchMethod in Spidermonkey) but it doesn't work for intercepting existing properties.

— Reply to this email directly or view it on GitHubhttps://github.com/tvcutsem/harmony-reflect/issues/22#issuecomment-26753680 .