[[Invoke]] vs [[Get]]

Tom Van Cutsem tomvc.be at gmail.com
Mon Jun 10 00:52:36 PDT 2013


2013/6/9 Brian Di Palma <offler at gmail.com>

> On Sun, Jun 9, 2013 at 4:18 PM, Tom Van Cutsem <tomvc.be at gmail.com> wrote:
> >
> > No, we can't just blindly call GetValue in step 1 as that would lead to
> the
> > "get" trap being invoked on a proxy (which is the wrong trap).
> >
>
> Why can't we have the two traps trigger?
>

Think of invoke() as:

invoke = get + call (i.e. lookup a method and call it immediately)

IOW, the "invoke" behavior already encompasses all of the "get" behavior.
There is no need to duplicate the "get" behavior separately.

One of the primary reasons why invoke() was added was precisely to avoid
calling the get-trap, because the get-trap must often allocate and return a
(bound) function, only to have that function be immediately called.


> I would imagine that proxies are meant to be consistent with
> getters/setters?
> So in this example obj.f() triggers the getter, yet if I understand
> what you're advocating it wouldn't trigger a [[Get]] trap?
>
> var obj = { get f() {
>   console.info( "getter called." );
>   return console.info.bind(console);
> } }
>
> obj.f( "getter also called" )
>
> > "getter called."
> > "getter also called"
>

If you want "invoke" to also trigger the "get" trap, just have your handler
subclass DelegatingHandler as explained in [1].
Assuming obj refers to your object definition above:

var proxy = new Proxy(obj,
  new class extends DelegatingHandler {
    get(target, name, rcvr) {
      console.info("get trap called");
      return super.get(target, name, rcvr); // forward to obj
    },
    invoke: (target, name, args, rcvr) {
      console.info("invoke trap called");
      return super.invoke(target, name, args, rcvr); // forward to obj
    }
  });

proxy.f("getter also called");
// "invoke trap called"
// "get trap called"
// "getter called."
// "getter also called"

The DelegatingHandler class's inherited "invoke" trap will call back on
(i.e. reuse) the "get" trap to provide an answer. IOW, it is implemented as:

invoke: function(target, name, args, rcvr) {
  var callable = this.get(target, name, rcvr);
  return Function.prototype.apply.call(callable, rcvr, args); // i.e.
callable.apply(rcvr, args)
}

I hope this clarifies things.

Cheers,
Tom

[1] http://wiki.ecmascript.org/doku.php?id=harmony:virtual_object_api
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130610/fe9ede00/attachment.html>


More information about the es-discuss mailing list