custom proto arg for Proxy.createFunction?

David Herman dherman at mozilla.com
Wed Feb 23 17:32:44 PST 2011


>> The simple instanceof check seems simpler and reasonably intuitive.
> By "hardcoding" p instanceof Function === true

I'm not proposing this -- it's already true. Try it out in SpiderMonkey:

    js> (Proxy.createFunction({}, function(){}, function(){})) instanceof Function
    true

> you're breaking your
> user expectation of finding the Function.prototype methods ("call",
> "apply" or any further addition) in the object.

I think I haven't made myself clear. Certainly, users generally expect invariants like:

    if (x instanceof y) and (key in y.prototype) then (key in x)
    if (y === Object.getPrototypeOf(x)) and (key in y) then (key in x)

But proxies *already* break these invariants. It's *already* possible to write a proxy that doesn't have a property that its prototype has. You can do this *both* with Proxy.create(), which lets you provide a prototype but act as though you don't have properties of the prototype, *and* with Proxy.createFunction(), which insists that your proxy is an instanceof Function but again lets you act as though you don't have the properties of Function.prototype.

None of this has anything to do with my suggested extension, which is allowing a user-specified prototype to Proxy.createFunction.

>>> With your solution, by removing Function.prototype from the chain, proxy
>>> functions couldn't be .call()-ed or .apply()-ed
>> That's already true, even without my extension:
>> 
>>    js> var proxy = Proxy.createFunction({}, function(){}, function(){})
>>    js> proxy.call(this)   
>>    typein:11: TypeError: getPropertyDescriptor is not a function
> The bug is in your code:

No, there's no bug. The point of my code was to demonstrate that it's already possible to break the above invariant.

If you want to promote as best practices that people should *strive* to uphold the invariant, even though it isn't enforced by the language, that's fine. But allowing user-specified prototypes for Proxy.createFunction doesn't change this. It's still up to the proxy writer to ensure that they delegate to the prototype, regardless of whether the prototype is Function.prototype or a descendant of Function.prototype.

> When you do "proxy.call(this)", the "proxy.call" getter is trapped as
> the "get" trap. Since you do not define it (your handler objectis
> empty), the default get trap is called (see here :
> http://wiki.ecmascript.org/doku.php?id=harmony:proxies#trap_defaults).
> In this default get trap, the first thing that is done is a call to
> this.getPropertyDescriptor ("this" refers to the handler object which is
> empty in your example). And here, the error is thrown by the engine
> since handler.getPropertyDescriptor isn't a function because it's undefined.

Well, of course! That's my point. Proxies do not force you to respect prototype delegation.

> This code is ugly, because my get handler methods assumes that the proxy
> object is reachable from the lexical scope which could not be the case
> (I could have used the "rec" argument, but that's not very clean). There
> is an ongoing discussion to make the proxy object available as an
> argument in each trap. This way, the get trap could be rewritten as:
> get: function (rec, name, proxy){
>    return Object.getPrototypeOf(proxy)[name];
>    // Object.getPrototypeOf(proxy) is Function.prototype by definition here
> }
> This is actually one more argument in the direction of making this happen.

That seems like a non sequitur; in what you've written, I don't see any argument against allowing Proxy.createFunction() to accept a user-specified prototype.

Again: the whole design of the proxy system *already* requires you to implement the delegation manually if you want to respect the prototype chain. But you don't have to respect the prototype delegation chain. That's true for both Object.create() and Object.createFunction().

All I'm proposing is allowing you to specify a descendant of Function.prototype as your prototype link, rather than Function.prototype itself. Either way, it's up to the programmer to decide whether they want to respect prototype delegation in their traps.

Dave



More information about the es-discuss mailing list