Proxies: get+fn vs. invoke

Tom Van Cutsem tomvc.be at gmail.com
Thu Oct 14 11:57:41 PDT 2010


>
> ... All do work. I.e. any missing property, for you, is a method. Do
> whatever you want with it. Call e.g. your noSuchMethod function inside it.
> - Hm, but how can I test whether a some method (or a property) exists on my
> object?
>
> Obviously, the approach:
>
> if (!o.n) {
>   o.n = function () {};
> }
>
> or even so:
>
> if (typeof o.n != "function") {
>   o.n = function () {};
> }
>
> won't work. Why should I get always a "function" for every reading of a
> (non-existing) property?
>

Ok, I finally see what issue you are addressing. I will try to summarize
(for you to see if I get it right)
- o is a proxy that proxies for another object o2, but in addition, it wants
to treat missing methods on o2 specially (e.g. return a no-op function to
prevent errors or return a method of some other object)
- its get method would look something like:
get: function(r, name) {
  var prop = target[name];
  if (prop) return prop;
  // else deal with the missing method, probably by returning a function
}
- your feature-test using !o.n would fail because o.n returns a function, so
the then-branch of the if-statement will not trigger.

- what you would like to do is to return 'undefined' from the 'get' trap if
the missing property is only accessed, and return a function only when the
property is invoked.

First: good point. AFAICT, this can't be done using the current proxy API,
and adding a flag to `get` or another trap would make this possible.

It is, however, debatable whether it is appropriate to override `o.n` with
the external function just because it does not exist on o2. After all, the
proxy can handle missing methods. Presumably, the code in the else-branch is
going to make use of `o.n` (either as a funarg, or it may call it as a
method `o.n(...)`. This will not crash, the proxy will deal with it. It's
not clear that overriding the `n` method with the function of the
then-branch is the right thing to do. Normally such feature-testing is done
to make sure that later calls to `o.n(...)` won't crash. When using proxies
that deal with missing methods, calling `o.n(...)` won't crash the code, so
why should the method be replaced?


> - Another minor thing -- `delete` does not really delete.
>
> delete foo.bar;
> foo.bar; // function
>

Well, it depends on how you implement the proxy. It could keep track of
deleted property names (I agree this would be cumbersome).
But would a separate `noSuchMethod` trap really help here? Consider:

delete foo.bar;
foo.bar(); // I expect this to crash now, but it will still call
`noSuchMethod`



> - OK, and what about the prototype chain? Where should I put this proxy
> object in order to prevent of catching of all my missing properties (because
> I want to catch them from other objects in the prototype chain, to which
> these properties belong)?
>
> Object.prototype.foo = 10;
>
> "foo" in o // true, OK
> o.foo; // but it's a _function_, not 10
>

If o is a proxy that first queries another target object (like the
noopHandler does), it will find 'foo' and it will return 10.



> What about to have `noSuchMethod` _additionally_ to the `get`? It will
> catch only missing properties, but: not _just_ missing properties, but
> missing properties which use a call expressions at call-sites. Thus, we can
> combine two approaches allowing a user to choose how to handle the case of
> missing _method_.
>
>
> handler.get = function (r, name) {
>   if (name == "baz") {
>     return function () { ... }; // and cache "baz" name if you wish
>   }
>   // other cases
>   return object[name];
> };
>
> handler.noSuchMethod = function (name, args) {
>   return this.delegate[name].apply(this, args);
> };
>

Could you specify when noSuchMethod is called? I think the algorithm inside
the proxy's [[Get]] method would look something like:

If the "get" trap on the handler returns undefined AND the handler defines a
"noSuchMethod" trap AND the [[Get]] was triggered by a call expression, then
instead of returning undefined, return the result of calling the
"noSuchMethod" trap.

Correct?

Cheers,
Tom
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20101014/35fc3641/attachment-0001.html>


More information about the es-discuss mailing list