July 26, 2012 TC39 Meeting Notes

Tom Van Cutsem tomvc.be at gmail.com
Sat Jul 28 12:16:34 PDT 2012


Thanks to Rick for his notes. The discussion on proxy-related issues went
fast and touched upon a variety of issues. I complemented Rick's notes on
the proxy discussion with some notes on the proxies wiki page, see: <

I'll clarify further in-line below.

2012/7/28 David Bruant <bruant.d at gmail.com>

> Le 28/07/2012 01:58, Rick Waldron a écrit :
> > # July 26 2012 Meeting Notes
> >
> > # getPrototypeOf trap
> >
> > TVC: (introduction)
> >
> > __proto__ writable destroys invariant that [[Prototype]] link is stable
> >
> > Frozen objects should continue to have stable prototype chain
> Frozen objects should continue to have stable [[prototype]]. You can't
> guarantee for the entire chain.

Indeed, the stable [[prototype]] invariant is local (per object), not per
entire chain.

> > getPrototypeOf trap result should be consistent wth target object's proto
> >
> > MM: if the proto can be changed, the proxy should…?
> >
> > TVC: spec interceptable [[Prototype]]
> > [[Prototype]] is currently an internal prop
> > Would need to become internal accessor prop or split into [[GetProto]]
> > / [[SetProto]]
> > [[GetProto]] / [[SetProto]] would trigger traps for proxies
> >
> > AWB/BE: This is good
> >
> > YK: Do we want an analogous setPrototypeOf trap?
> >
> > TVC: Yes
> This is inconsistant with below...

To clarify, I think we'd only need setPrototypeOf if __proto__ would end up
being specified as an accessor (to trap
Object.getOwnPD(Object.prototype,'__proto__').set.call(proxy) )

> > AWB: If you have capability to set prototype ?
> >
> > TVC: proxy.__proto__ should just trigger the proxy's get trap
> >
> > var p = Proxy(target, handler)
> >
> > p.__proto__ // => handler.get(target, "__proto__", p)
> > p.__proto__ = x // => handler.set(target, "__proto__", x, p)
> If there is a setPrototypeOf trap as said above, it should be
> handler.setPrototypeOf, no?

No, the purpose of these slides was to show that p.__proto__ continues to
remain a normal property get/set for proxy handlers, regardless of how we
would end up specifying __proto__.

As mentioned above, setPrototypeOf would only be called to trap a call to
the __proto__ setter.

> > …
> > Trapping instanceof
> >
> > Function [[HasInstance]]
> >
> > x instanceof Global answering true if x and Global live in separate
> > frames/windows
> >
> > var fp = Proxy(targetFunction, handler);
> >
> > x instanceof fp // handler.hasInstance(targetFunction, x)
> >
> >
> > MM: Explains concerns originally raised on es-discuss list by David
> > Bruant, but shows the cap-leak is tolerable
> I'm interested in the demonstration :-)

Mark acknowledged your concerns, but pointed out that currently almost no
capability-secure JS code is out there that relies on the fact that
instanceof doesn't grant access to the LHS. Even so, most of that code will
be Caja code, which can be maintained to avoid the leak. In going forward,
we can just explain instanceof as an operator that internally sends a
message to the RHS, passing the LHS as an argument. In effect, the implicit
capability "leak" would become an explicitly stated capability "grant".

> > …
> >
> > DH: if hasInstance private name on instanceof RHS...
> >
> > MM: What Object.prototype does private name inherit from?
> I assume s/Object.prototype/[[Prototype]], here?


> > AWB: Probably null
> >
> > BE: the E4X any (*) name had null proto in SpiderMonkey, was true
> > singleton in VM
> >
> > AWB: functions have home context, but no reason for objects to
> >
> > DH: this is a new idea of value that is not really any object
> >
> > OH: if it has no properties and no prototype
> >
> > BE: cannot be forged.
> >
> > Discussion about unforgeability.
> >
> > DH: Trapping instanceof use case
> Does this line mean that DH asked for the use case? questioned it?
> reminded it?
> How did it relate to this discussion?

I can't remember. DH did not ask for the use case. The use case we
discussed for trapping instanceof is the one previously raised on this list
(allowing x instanceof Global to return true even if x originates from
another frame).

> > Trapping Object.isExtensible
> >
> > Currently Object.isExtensible doesnt trap same for isSealed isFrozen
> >
> > var p = Proxy(target, handler)
> >
> > Object.isExtensible( p ) => Object.isExtensible
> Are there new traps here? The conclusion of this part is hard to
> understand.

Yes: new traps "isExtensible", "isSealed", "isFrozen", to trap the
corresponding Object.* methods. I wouldn't even describe them as "new",
they were more of an oversight. Membranes need these traps to accurately
reflect the internal extensibility/sealed/frozen state of their wrapped

> Direct Proxies: "internal" properties
> Issue raised by Jason Orendorff; auto unwrapping is dangerous if
> built-in methods return non-primitive values
> Case:
> var arr = [o1, o2, o3];
> var it = arr.iterator();
> var membraneP = wrap(it);
> it.next.call(membraneP)
> Solution (?)
> Instead of auto-unwrapping, delegate to a nativeCall trap (which
> auto-unwraps by default)
I don't understand this use case and the problem that comes with it. Is
it specific to generators?

It's not specific to generators. See the "nativeCall trap" section on the
wiki page.

> # Proxies and private names
> (...)
> DH: so name.public === name?
> MM: I like that
> MM: are unique names in?
> DH: I think so
If they are, the .public part of private names could be retired with the
following setting:
* Private names don't trigger proxy traps call and are not be
reflectable at all. This is practically equivalent to calling a trap
with a useless public counterpart from the caller perspective. From the
proxy perspective, since the public part is useless, being called or not
sounds like it would be more or less equivalent.
* Unique names would be trapped and passed as unchanged as argument to
the trap (actually since name.public === name, passing the unique name
or its public counterpart is equivalent). If the proxy wants the unique
name not to be accessed, it cannot remove it from getOwnPropertyNames
trap result. So proxies can emulate their own private names.

We still want proxies to intercept private names. It may be that the proxy
handler knows about the private name, in which case it has the "capability"
to usefully intercept access to it.

> BE: are they actually distinguishable?
> MM: have to be if name.public === name or name.public !== name distinction
> DH: (named) boolean flag to Name constructor
If we have private and unique names, we might as well have 2
constructors : PrivateName and UniqueName. I find that more readable
than "new Name(true)".
> DH: do we have some way of reflecting unique names?
> TVC: Object.getNames() ?
> DH: ugh...
> AWB: maybe a flag to Object.getOwnPropertyNames({ unique: true })
> BE (editing notes): flags to methods are an API design anti-pattern
What's the conclusion of this part?

As I recall it, the discussion was inconclusive. As stated, I would favor a
new operation (like Object.getNames) that makes explicit the fact that it
returns name objects, rather than overloading existing methods.

Regarding the extra traps needed for private names: I scanned the list of
traps and I think we need to duplicate each trap that takes a property name
(a String) as argument, so we'll end up with:

get -> getName
set -> setName
has -> hasName
hasOwn -> hasOwnName
defineProperty -> defineName
deleteProperty -> deleteName
getOwnPropertyDescriptor -> getOwnNameDescriptor?

(the last three names are a bit inconsistent since I don't want to be known
as the guy that inflicted getOwnPropertyDescriptorName upon the world ;-)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120728/28898c61/attachment.html>

More information about the es-discuss mailing list