Proxying built-ins (Was: [[Invoke]] and implicit method calls)

Tom Van Cutsem tomvc.be at gmail.com
Thu Sep 26 02:16:40 PDT 2013


2013/9/25 Boris Zbarsky <bzbarsky at mit.edu>

> On 9/25/13 3:47 PM, Mark S. Miller wrote:
>
>> Hi Boris, I don't understand what you mean by "in general". I think the
>> SpiderMonkey use of cross-realm membranes is a great use case for
>> membranes, and I don't understand why they need any special logic at all
>> -- beyond the logic expressed by their handlers, which must include
>> revocation.
>>
>
> Mark,
>
> The issue is that if I have access to a different-realm Location object
> called "loc", say, then:
>
>   Object.**getOwnPropertyDescriptor(**Location.prototype,
> "href").get.call(loc)
>
> should throw if the "loc" is not same-origin with me.  But:
>
> Object.**getOwnPropertyDescriptor(**Location.prototype,
> "href").set.call(loc, "whatever")
>
> should perform the set.  (There are actually some more complications here
> for the specific case of Location, but let's ignore them for now.)
>
> What that means in practice is that the membrane isn't actually "revoked":
> it needs to be unwrapped to the real underlying object in some cases, but
> not others.
>
> The way we implement that, again, is with a way to unconditionally unwrap
> a cross-realm membrane, and a way to ask a cross-realm membrane whether
> it's ok to unwrap it.  Some of the methods/getters/setters involved use the
> former, and some use the latter.
>
> Note that in this case the actual property getter/setter is gotten without
> any interaction with membranes at all.  The only question is when a
> membrane around the thisArg to a function can be pierced to get to the
> thing the function actually knows how to operate on.


I believe the crucial part of why this works is because the built-ins can
recognize trusted, cross-realm proxies, from arbitrary other proxies.

In general, we can't let the built-in transfer control to an arbitrary
proxy handler, because users calling |builtin.call(thing)| don't expect
|thing| to influence the result of the call (cf. the discussion in the
[[invoke]] thread <
http://esdiscuss.org/topic/invoke-and-implicit-method-calls#content-115>).

Answering MarkM's question of whether we can self-host such behavior, I
believe we can:

```js
var trustedMembraneProxies = new WeakMap(); // maps trusted membrane
proxies to their target, allowing code with access to this WeakMap to
unwrap them

Object.defineProperty(Location.prototype, "href", {
   get: function() {
     var target = trustedMembraneProxies.get(this);
     if (target === undefined) {
        // this-binding was not a cross-realm wrapper, just operate on the
original this-binding
        target = this;
     }
     ... // execute builtin behavior with target as the this-binding
  }
}
```
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130926/1091053a/attachment.html>


More information about the es-discuss mailing list