Invoke trap

Brandon Benvie bbenvie at mozilla.com
Fri Jun 7 13:15:05 PDT 2013


On 6/7/2013 12:53 PM, David Bruant wrote:
> Le 02/06/2013 09:46, Rick Waldron a écrit :
>> 4.4 Proxies
>>
>> Proxy Invoke Trap and wrong |this|-binding on built-in methods
>>
>> AWB: with current default behavior of “get”, “Caretaker” will break 
>> on built-ins such as Date, because the |this| binding is by default 
>> set to the proxy, so the Date built-in method will not find the 
>> correct private state.
>> ARB: Same issue with binary methods
>> ...
>> STH: We should add invoke trap but not change the object model
>> MM: Pleasant to have. Separate from private state.
>> AWB: used to think this was an issue with proxies, but convinced that 
>> it’s an API issue: we need to provide default handlers that do the 
>> right thing, and which users can subclass. In particular, want a 
>> handler that, on forwarding, rebinds |this| to the target.
>> STH: If you want to proxy a Date method the underlying `this` needs 
>> to be a non wrapped Date object.
> Doesn't this break encapsulation?
>
> var d = new Date();
> var pd = new Proxy(d, {
> invoke: function(target, name, thisArg, args){
> return target[name].apply(thisArg, args)
> }
> })
>
> var pt = pd.getTime(); // calls the invoke trap
>
> // in a mixed-trusted context with access to pd:
> var ppd = new Proxy(pd, {
> invoke: function(target, name, thisArg, args){
> // does the actual unwrapped date object leak through thisArg?
> }
> });
>
> var ppt = ppd.getTime();
>
> In any case, what is the following supposed to do:
>
> Date.prototype.getTime.call( new Proxy(new Date(), handler) )
>
> I imagine we would want this to work too. Is this going through the 
> invoke trap as well? The question stands for all new "class-specific" 
> (Map, Set, etc.) methods that would be dot-called with a proxy as 
> first argument.
>
> If the problem being solved is making Date (and Map, Set, etc) 
> built-in methods works on wrapped objects, I feel the invoke trap is 
> only a partial solution.
>
>
> I intuit (but have no proof) that for Date.prototype.getTime.call to 
> work on proxies, there is a need for class-specific traps.
> * Object properties have specific traps to intermediate access 
> (has/get/set/defineProperty/keys, etc.),
> * [[Prototype]] has specific traps to intermediate access 
> (get/setPrototypeOf)
> * [[Extensible]] has a specific trap to intermediate access 
> (preventExtensions)
> * [[Call]] has a specific trap to intermediate access (apply)
> * [[Construct]] has a specific trap to intermediate access (construct)
> * Some other things that are somewhat internal (@@iterator, @@class, 
> etc.) are exposed as symbols and are mediated via object 
> properties-related trap
>
> The pattern I see is that a good share of object internal properties 
> (ES5.1 - 8.6.2 - Table 8 and Table 9) have traps dedicated to mediate 
> access.
>
> The case of functions is interesting. There are traps that are only 
> relevant when the target is a function. In that regard, adding traps 
> that are specific to accessing the Date internal [[Time]] value or 
> specific traps to mediate access to [[MapData]] isn't any different 
> than the current specific traps that mediate [[Call]] or [[Construct]]
>
> David
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss

I believe the purpose of adding multiple types of handlers [1] was to 
address this and similar issues.

    In the case of the |get|, |set| and |invoke| traps, there is a
    choice to be made when forwarding the property get/set or the
    invoked method: should the value of |this| in a target’s accessor or
    method be set to the proxy object or to the target object? Either
    choice can be sensible, depending on your application. 

    The |DelegatingHandler| implements |get|, |set| and |invoke| in such
    a way that |this| inside forwarded accessors or method invocations
    remains bound to the |receiver| argument. Proxies using the
    |DelegatingHandler| can thus be used as prototypes for other
    objects: they leave the |this|-binding intact upon forwarding.

...

    |ForwardingHandler| is itself a subclass of |DelegatingHandler| (so
    it comes with an appropriate default implementation for all Proxy
    traps). It overrides the |get|, |set| and |invoke| traps so that
    forwarded accessors or method calls get run with |this| set to the
    target object.


[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/20130607/654027db/attachment.html>


More information about the es-discuss mailing list