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

Tom Van Cutsem at
Thu Sep 26 02:16:40 PDT 2013

2013/9/25 Boris Zbarsky <bzbarsky at>

> 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")
> should throw if the "loc" is not same-origin with me.  But:
> Object.**getOwnPropertyDescriptor(**Location.prototype,
> "href"), "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 || don't expect
|thing| to influence the result of the call (cf. the discussion in the
[[invoke]] thread <>).

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

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: <>

More information about the es-discuss mailing list