On Dec 2, 2012, at 11:40 AM, Tom Van Cutsem wrote:

> 2012/12/2 Mark S. Miller <[email protected]>
> I think we can rescue around wrapping. I'll call this approach "opaque
> around wrapping". The idea is that the proxy passes into the handler
> trap a proxy-generated no-argument function (a thunk) called "action".
> 
> Interesting. I had thought of a similar approach, but hadn't pursued it 
> because I thought allocating a thunk per trap invocation would be deemed too 
> expensive. I'll go ahead and sketch the design, which I think corresponds 
> closely with your approach B)

This is my first reaction too.  I want Proxies to be lightweight enough so they 
really can be used be used for things like self hosting built-ins and web API 
objects.  The need to create an pass in a action thunk on each trap calls 
initially feels too expensive.

But that is only a first reaction.  Perhaps the expense really isn't that 
great. Or perhaps a lot of the cases where I have assumed the Proxies would be 
needed could be handled by lightweight mechanisms such such as the 
@elementGet/@elementSet hooks described in 
http://wiki.ecmascript.org/doku.php?id=strawman:object_model_reformation  (see 
Implementing Built-inArray without Proxy and Rationalizing DOM HTMLCollections 
examples)

Allen











> 
> First, from the point-of-view of the trap implementor, things would work as 
> follows (I show the "defineProperty" trap only as an example)
> 
> All traps take an extra thunk as last argument, which I will name "forward", 
> since calling that thunk has the effect of forwarding the operation to the 
> target, returning the original result.
> 
> defineProperty: function(target, name, desc, forward) {
>   // before
>   var result = forward();
>   // after
>   return result;
> }
> 
> Now, from the point-of-view of the proxy implementation, how is the above 
> trap called?
> 
> // in the proxy, intercepting Object.defineProperty(proxy, name, desc)
> // where proxy = Proxy(target, handler)
> var result = Uninitialized;
> var thunk = function() {
>   if (result === Disabled) throw new Error("can only call forward() during 
> trap invocation");
>   if (result !== Uninitialized) throw new Error("forward() can be called only 
> once");
>   result = Reflect.defineProperty(target, name, desc); // forward to target
>   return result;
> };
> var trapResult = handler["defineProperty"].call(handler, target, name, desc, 
> thunk);
> if (result !== Uninitialized && result === trapResult) return result; // no 
> invariant checks when original result is returned
> if (result === Uninitialized || result !== trapResult) { /* do invariant 
> checks */ ; return result; }
> result = Disabled; // ensures one cannot call forward() outside of dynamic 
> extent of the invocation
> 
> I'll answer your questions for the above design:
>  
> Open questions that take us to different design possibilities:
> 1) what happens if the trap does not call action?
> Invariant checks are performed on the returned result.
>  
> 2) what happens if the trap calls action more than once?
> An exception is thrown.
>  
> 3) do actions ever return anything, in case the trap wants to pay
> attention to it?
> Yes, it returns the value of the operation, applied to the target.
>  
> 4) are there any return values from the trap that the proxy would pay
> attention to?
> Yes. If the trap returns the original result, it doesn't do any extra checks. 
> Otherwise it does.
>  
> 5) if the original operation performed by action throws, should the
> action still just return to the trap normally?
> A thrown exception would escape and abort the entire operation, unless the 
> trap wraps the call to forward() in a try-catch block.
>  
> 6) what happens if the trap throws rather that returning?
> Thrown exceptions are always propagated to clients.
>  
> I prefer #A to #B as it gains the full benefits of simplifying the
> overall spec and implementation. However, #B still seems better than
> current direct proxies, as the normal case gets target-maintenance and
> invariant checking for free.
> 
> I agree that #B doesn't really simplify anything in the spec (the invariant 
> checks are still there sometimes).
> I'm not sure if it is inherently better than the current design though: we 
> gain performance in terms of avoiding invariant checks, but we lose 
> performance by having to allocate a per-call thunk, + the API becomes more 
> complex (an additional parameter to every trap)
> 
> I do think that passing an action or "forward()" thunk to a trap as extra 
> argument beats David's proposed "throw ForwardToTarget" trick in terms of 
> elegance and usability (maybe not in terms of performance).
> 
> Cheers,
> Tom
> _______________________________________________
> es-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to