Proxies and preventExtensions: how to avoid inconsistency in a membrane?

Tom Van Cutsem tomvc.be at gmail.com
Sun Sep 4 20:14:53 UTC 2016


Hi Alex,

The problems you are seeing are inherent to what you're trying to achieve.
You're trying to build an abstraction (virtual extension properties that
should continue to work even on non-extensible objects) that are directly
in conflict with ES's invariants (e.g. if the object is truly
non-extensible, it shouldn't be able to report additional properties,
virtual or not (because the client can't tell the difference between an
extension property and a normal property, and we're trying to protect
clients from unexpected proxy behavior).

For the specific case of extension properties, the better alternative is to
simply let the untrusted code use WeakMaps to attach properties to objects
it doesn't control. Sadly the syntax is not as sweet as `obj[prop]`, but
this approach does completely sidestep the invariant issues (it's perfectly
fine to associate frozen objects with additional state via a WeakMap).

Essentially, if you want to implement a membrane that works in the face of
ES invariants, you need to use the "shadow target" technique where the
membrane proxy is not directly targeting the "real" target object but
instead a "dummy" target object that it can use to be more flexible in what
it can answer. It seems that is more or less the solution you stumbled
upon. See <
https://github.com/tvcutsem/harmony-reflect/blob/master/examples/generic_membrane.js>
for a membrane implementation that works this way.

I'm writing to ask the following:
>
>    1. Are there other options for the given problem that I am not seeing?
>
> To my knowledge, the shadow target technique is the only way to build
proxies that need to be able to do more than their real target allows.

>
>    1. Could the existing ProxyHandler part of the spec be extended, so
>    that in the future I could override that invariant (and others, yet
>    undetermined) explicitly?
>
> What do you mean by "override that invariant"? By definition, an invariant
can't be overridden. Otherwise it's no longer an invariant.


>
>    1. Could there be a Proxy.hasBeenRevoked(proxy) method?
>
> I don't see why you would need this. Note that revokable proxies can't be
just revoked by any other object: on creation, the code that creates the
proxy (presumably the membrane) is the only code that has access to the
revoke function. Thus, it is always possible for the creator of the proxy
to wrap the proxy's revoke function with additional actions that would need
to occur before or after revocation, and share only the wrapped revoke
function with the outside world.

Regards,
Tom
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20160904/40a69515/attachment.html>


More information about the es-discuss mailing list