ES6 Proxy Function Call Trap

Isiah Meadows impinball at gmail.com
Fri Jun 12 06:37:17 UTC 2015


To be honest, you could simply subclass Proxy to add an invoke hook, if
it's that simple:

```js
function makeHandler(handler) {
  let {get, invoke} = handler;
  let lastGet = false;
  let opts = {};
  Object.keys(opts)
    .filter(key => key !== 'get' && key !== 'call')
    .map(key => [key, handler[key]])
    .forEach(([key, func]) =>
        opts[key] = function () {
      lastGet = false;
      func.apply(this, arguments);
    });
  opts.get = function (target, property) {
    new Proxy(target[property], {
      apply(f, thisArg, args) {
        return invoke.call(handler, target, property, args);
      },
    });
    return get.apply(this, arguments);
  };
  return opts;
}

class InvokeProxy extends Proxy {
  constructor(target, handler) {
    super(target, makeHandler(handler));
  }

  static revocable(target, handler) {
    return Proxy.revocable(target, makeHandler(handler));
}
```

---------- Forwarded message ----------

  From: Tom Van Cutsem <tomvc.be at gmail.com>
To: Kevin Smith <zenparsing at gmail.com>
Cc: es-discuss <es-discuss at mozilla.org>
Date: Thu, 11 Jun 2015 21:01:48 +0200
Subject: Re: ES6 Proxy Function Call Trap

Edwin,

I sympathize with your point-of-view, but we've debated all the pros and
cons of `invoke` long ago, and unless new arguments are brought to the
table, I don't think it will be added again soon.

To clarify why the "invoke = get + call" equivalence is so important,
consider for instance the common coding pattern of a "conditional" method
call, where one only wants to invoke a method if it exists:

```js

var foo = obj.foo;

if (foo) {

  foo.call(obj)

}

```

With the current Proxy API, the `get` trap returns a function (or a proxy
for a function), and the code works fine regardless of whether foo() is
called as a method, or as a function.

With the addition of `invoke`, if you don't also provide a `get` trap, then
the code will not behave as expected. Likely `obj.foo` will return
`undefined`, even though `obj.foo()` would have triggered the `invoke` trap
and done something useful.

So, *any* robust use of `invoke` still requires implementing a `get` trap
(to allow for all the use cases where methods are extracted as functions
from objects). As a result, it would lead to a net *increase* in
lines-of-code.

2015-06-11 15:48 GMT+02:00 Kevin Smith <zenparsing at gmail.com>:

  Could a userland library make writing these kinds of proxies more
ergonomic?

 I don't see why not. The Proxy API offers only the bare minimum tools to
create your own custom "exotic" objects. Arguably we need to grow some good
libraries around it to make building these types of objects more routine
(although I'd be the first to point out that you should avoid "exotic"
objects unless there's a really compelling reason to go that route)

Cheers,

Tom
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150612/37e1373e/attachment-0001.html>


More information about the es-discuss mailing list