Proxies: get+fn vs. invoke

Brendan Eich brendan at
Wed Oct 27 10:15:50 PDT 2010

On Oct 27, 2010, at 9:07 AM, Tom Van Cutsem wrote:
> With the risk of going round the block again... ;-)

Last time for sure. :-|

> I agree with your premises, namely that:
> a) `if (! = {}` is a common pattern to patch up objects that don't know how to deal with `bar` requests
> b) a proxy that pretends to have all possible properties can't be patched up using this pattern
> But I don't buy your conclusion, which is that a + b implies that proxies are somehow broken. If the proxy says "I know how to handle `bar` properties", then the client doesn't need to patch up the proxy by adding a `bar` property. Your patch-up pattern will work perfectly fine with proxies that don't pretend to have a `foo` property.
> There are good reasons for why proxy writers may want to distinguish get from invoke (for example, because invoke doesn't require caching the function returned by `get`),

(that was a reason I gave back when I was arguing for an "invoke" trap, yes.)

> but IMHO this patch-up pattern is not one of them.

Agreed, it is not one of them.

Dmitry, you are hypothesizing a proxy whose handler lazily creates all trapped properties with some non-falsy initial value.

But no one is dictating such a proxy handler implementation, it is broken as Tom points out but due to its own straw-design mistake (not due to anything inherent in Proxies), and in reality it's hard to write such a proxy.

In reality, programmers won't write handlers that trap any property name and return a useful (non-empty or not-constant-for-many-names) function value. My lazy method cloner, e.g., clones only methods found in (whether "own" or not) the given clone-parent object. It can't proxy a method for a property not in that object.

There is no "object detection" pattern that works for a silly proxy that returns, e.g., (function(){}), for all property has and get traps. Such a proxy is doing what you coded it to do, however broken or absurd. It is not the fault of the harmony:proxies proposal, or in any way due to the lack of noSuchMethod traps, that this could happen.

So really, this is a straw-man fallacy. We knock it down, but Proxies still stand. One can, after all, write silly or broken toString implementations in JS today, and patch them into Object.prototype even. This is a feature, not a bug.

Object detection, BTW, is not metaprogramming at all, IMHO. So I don't agree that if (! = ... is a "pattern" for trapping missing properties. It is imperative code in the base-level language. You have to write it in a certain place (or places) in the control flow graph. If you want something that runs for a given foo when accessing "bar", via a proxy-like API, then we are talking about real behavioral intercession metaprogramming.

So I don't buy Dmitry's argument that noSuchMethod somehow complements or completes the existing object detection pattern, but for call expressions -- the method_missing Ruby feature. It is not complementary, or even on the same meta-level. And really, the primal issue is whether invoke-only methods are a desirable pattern.

The reason I gave up noSuchMethod was that you can't make a coherent object with extractable methods-as-funargs without the full suite in the current harmony:proxies proposal, if all you have is noSuchMethod. But given the full suite in the current proposal, if you lack noSuchMethod, you can still emulate host and native objects. There are no invoke-only methods in ECMA-262, and the ones in ECMA-357 are considered design flaws, corrected (albeit with a clunky workaround, function::) in SpiderMonkey's E4X implementation.

So my final answer remains: invoke-only methods are an anti-pattern.

Ok, still I have no doubt Dmitry will argue: a trap for invoke-only methods is desirable on some basis, by some developers. It may be among a large number of developers, but we've heard only from a few (and with too many trips around the same block).

In any event, without more going 'round the same block over and over, we'll have to see how the more minimal, current harmony:proxies design plays out with a wider audience of developers who can actually play with it in Firefox 4.

(I still don't see how invoke-only methods work with all the partial-applying/currying JS libraries out there today (Prototype, JQuery, etc.), but perhaps there is a bright line between the functional-programming style of those libraries, and the intended noSuchMethod invoke-only methods.)


More information about the es-discuss mailing list