Membranes, unmediated access to objects through Object.getPrototypeOf

Tom Van Cutsem tomvc.be at gmail.com
Thu Oct 11 00:03:06 PDT 2012


2012/10/11 Brendan Eich <brendan at mozilla.org>

> Why would not the target be nulled and the handler be replaced with a
> handler full of throwing traps? Sorry if I missed a message on this.
>

Yes, that's the general idea. It's just that you need some built-in
function to do this for you.


>
>  We need platform support for revocation, because it cannot be implemented
>> by JS code.
>>
>
> I quite agree, but this does not mean a Proxy.revocable constructor,
> unless you want a revoke method to work only on proxies distinguished by
> being created via an alternative constructor.
>
> IIRC (and I hope I do!) we were considering RevokableProxy or
> Proxy.revocable only because non-revocable proxies cannot tolerate overhead
> in dispatching their traps to check for a default-false revoked internal
> property. But your idea of nulling target and replacing handler with a
> throwing handler seemed to avoid any overhead.
>
> So is the issue the revoke API and a desire to "narrow" it to apply only
> to proxies distinguished from birth as revocable? If so, why?


tl;dr:
- revocable proxies and non-revocable proxies are exactly the same
internally (this is good)
- only revocable proxies require an associated |revoke()| function. Thus
having two constructors makes sense as it avoids the (object allocation and
API ergonomics) overhead of the revoke() function for non-revocable proxies.


You're right: thanks to David's insight of just replacing a proxy's
[[Handler]] with a special handler that always throws, revocable proxies
are no different from non-revocable proxies except for the fact that
there's a user-visible function to actually perform this replacement.

So indeed, the currently specced Proxy.revocable is there only to expose
the additional |revoke()| function acting as that proxy's off-switch. I
think the current API strikes a pretty good balance:

- proxies that don't need an off-switch are not bothered by the additional
return value. For these cases, one can continue to write just |proxy = new
Proxy(target, handler)|.
- Proxy.revocable, contrary to just the Proxy constructor, has to allocate
the unique |revoke()| function for the new proxy. The Proxy constructor
avoids that overhead if you never need to revoke.
- Proxy.revocable returns a tuple {proxy, revoke}. While more cumbersome to
work with (especially in pre-ES6 code without destructuring), this API gets
the authority to revoke a proxy exactly right: at proxy birth, only the
creator of the proxy holds the right to revoke it. This is infinitely
better than a global Proxy.revoke(proxy) method that would allow arbitrary
objects to revoke any proxy.

Cheers,
Tom
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20121011/36b58efe/attachment-0001.html>


More information about the es-discuss mailing list