Notification proxies (Was: possible excessive proxy invariants for Object.keys/etc??)

Tom Van Cutsem tomvc.be at gmail.com
Mon Dec 10 13:09:27 PST 2012


To pick up this thread again, I gave a talk about the trade-offs in
designing JS proxies at a meeting last week. The people following this
thread may be interested in seeing the slides: <
http://soft.vub.ac.be/~tvcutsem/invokedynamic/presentations/Tradeoffs_WGLD2012_Austin.pdf>
(the talk tremendously simplifies the story to cram it in 25 minutes. I
added some minimal notes to make the slides easier to follow.

The talk is more or less a story about how we started out with non-direct
proxies and ended up with direct-proxies. It doesn't provide any new
insights or discuss the recent notification proxies or "action-proxies".

Cheers,
Tom

2012/12/3 David Bruant <bruant.d at gmail.com>

> Le 03/12/2012 16:38, Mark S. Miller a écrit :
>
>  What eternal[1] invariant does this bypass?
>>
>> [1] https://mail.mozilla.org/**pipermail/es-discuss/2011-May/**
>> 014150.html<https://mail.mozilla.org/pipermail/es-discuss/2011-May/014150.html>
>>
> Apparently none... Yet, additionally to the last case I showed, there is
> also:
>
>     var p = new Proxy({a:1}, {
>         isExtensible: function(target, action){
>             var v = action();
>             Object.preventExtensions(**target);
>         }
>     })
>
>     // real life-like code?
>     if(Object.isExtensible(target)**){
>         Object.defineProperty(target, 'b', {value: 37}); // throws
>     }
>
> I agree it's not an eternal invariant, but it's quite surprising.
> [cc'ing Tom to make sure he reads this part]
> Arguably, the isExtensible, seal and freeze trap could have no "action"
> and just forward to the target. That's what the current invariant
> enforcement suggests anyway ("Invariant check: check whether the boolean
> trap result is equal to isFrozen(target), isSealed(target) or
> isExtensible(target)").
> This applies to current proxies actually. Maybe their return value could
> just be ignored. Trap authors have all the information they need with the
> trap arguments to decide whether they want to throw. For the rest, the
> operation can just be forwarded to the target (which it has to for
> invariant check already).
>
>
> Proxies-with-action have this weird taste of "one-move ahead"; like if
> they could run what they're expected and then play a bit more of the game
> before actually showing their before-last move. It makes sense they do not
> violate eternal invariants
>
> Although not rigorously necessary when it comes to the very minimalistic
> eternal invariants, the current proxies provides some guarantees by design
> which are nice both for whoever writes handlers and whoever manipulates
> proxies.
>
> Unrelated, but I think that custom property descriptor attributes are lost
> with action-proxies. I'm not sure yet what is a good way to recover them.
>
> David
>
>
>  On Mon, Dec 3, 2012 at 3:33 AM, David Bruant <bruant.d at gmail.com> wrote:
>>
>>> Le 03/12/2012 00:06, David Bruant a écrit :
>>>
>>>  The call to action performs
>>>>> the original operation on target and remembers the result. After the
>>>>> trap returns, the proxy returns the remembered result of action.
>>>>>
>>>>      target = {a:1};
>>>>      var p = new Proxy(target, {
>>>>          get: function(target, name, action){
>>>>              var v = action();
>>>>              target[name] = 2;
>>>>          }
>>>>      })
>>>>
>>>>      p.a; // ?
>>>>
>>>> If p.a is 1 because the call to "action" remembered the "1", then the
>>>> target and the proxy look awkwardly desynchronized. To know what's being
>>>> returned from the trap, one needs to remember when the action is being
>>>> called which makes writing traps harder I feel. With the current design,
>>>> looking at the return statements is enough.
>>>> If p.a is 2, I don't understand the point of "action". Or at least, I
>>>> don't see how it's better than just calling Reflect[trap].
>>>>
>>> I've found much MUCH worse:
>>>
>>>
>>>      target = {a:1};
>>>      var p = new Proxy(target, {
>>>          get: function(target, name, action){
>>>              var v = action();
>>>              Object.defineProperty(target, name, {value:2, configurable:
>>> false, writable:false})
>>>          }
>>>      })
>>>
>>>      p.a; // 1 ?
>>>
>>> In that case, the mechanism used to bypass invariant checking is a way to
>>> bypass invariants entirely.
>>>
>>>
>>> David
>>> ______________________________**_________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/**listinfo/es-discuss<https://mail.mozilla.org/listinfo/es-discuss>
>>>
>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20121210/4ca32d8e/attachment.html>


More information about the es-discuss mailing list