Le 24/11/2012 18:10, Allen Wirfs-Brock a écrit :
* [[Enumerate]], [[Keys]] and [[OwnPropertyKeys]] are very close
operations
* So are [[PreventExtensions]]/[[Freeze]]/[[Seal]] on one side and
[[IsExtensible]]/[[IsFrozen]]/[[IsSealed]]
I'm afraid that making them distinct operations increases
footgun-ness. [[HasProperty]] has been removed in favored of
[[HasOwnProperty]] (which might be removed in favor of only keeping
[[GetOwnProperty]], though the conclusion of the discussion was the
keep both IIRC) because the former could be "robustly" composed between
Yes, I agree. In particular I think [[Enumerate]], [[Keys]], and
[[OwnPropertyKeys]] should be reduced to a single parameterized trap.
Multiple traps make it harder to create an internally consistent MOP
provider (eg, Proxy handler).
(...)
Here is an idea to uniformize the enumeration story while removing
enumeration inconsistency footgun. I'll describe it in proxy trap
terms. A unique trap (or internal operation)
keyEnumerate: () -> iterator for {propertyKey, enumerable}
There is this unique operation which returns an iterator not for
property keys, but for an object containing a property key and a
boolean signifying the enumerable boolean.
Using this, each userland operation would use this iterator, drain it
out (unless the iteration is being aborted like by throwing in a
for-in loop) and filter out based on the exact userland operation so
that:
* All would filter out if propertyKey is ever a private symbol
* Object.getOwnPropertyNames would keep all other property keys
regardless of the enumerable value
* Object.keys would filter out properties which are described as
non-enumerable
* for-in would filter out non-enumerable and retrieve the different
keyEnumerate from the prototype chain objects.
With this unique internal operation, an object is able to communicate
its intent regarding what's enumerated and each enumeration userland
operation only keeps what it's interested in.
Yes, something like this. My inclination would be to add a hint
parameter indicating one of the currently known variations. I think it
is justified as enabling the "handler" to optimize its internal work
of collecting the set of keys.
I'm afraid an hint parameter has the same downside than having several
traps: offering the possibility to make different code paths for
different userland enumeration operations. This very possibility is the
footgun in my opinion.
I felt satisfied with the [[keyEnumerate]] internal operation, because
as a trap, people will have to return an iterator that iterates over
everything and the engine (not the trap) makes the call of what is to be
actually enumerated by the different variations.
Not letting the trap know how the result will be used is the best way to
prevent people from writing erroneous traps in my opinion.
• Defined all of the functions in the @Reflect module corresponding
to MOP internal operations.
IIRC __proto__ has been agreed to be an data property and there was
no Reflect.setPrototypeOf operation in the harmony Reflect module
proposal on purpose so that 'delete Object.prototype.__proto__' at
any point would be enough to be sure that all [[Prototype]]-setting
capabilities are removed.
So I think the Reflect.setPrototypeOf should be removed.
Do you want to be able to set __proto__ on DOM objects and other
exotic objects?
I personally don't, but for sure others do. I'm happy with the static
inheritance mechanism we will soon have and cover the vast majority of
current __proto__ use cases.
Adding Reflect.setPrototypeOf has exactly the same issues than an
extractable __proto__ setter. See May meeting notes [1]:
"DH: I can predict the security bugs: the implementor just thinks about
the normal case, but the attacker takes the accessor out, installs it on
an object that inherits from a proxy to an object from another global
etc. etc. and something internal breaks
MM: that's the most compelling argument I've heard. the additional
testing surface area is much bigger"
__proto__ really is in ES6 as a de facto standard. I'm not sure it is a
good enough reason to make setting the [[Prototype]] a first citizen of
the language.
If so, it needs to be part of the MOP. "In for a penny, in for a
pound". If we are going to make __proto__ part of the language than we
have to accommodate just like any other feature. If you want to be
able to disable it make deletion of Reflect.setPrototypeOf be the
switch. Or define a new function for doing it. But I don't think we
should be bending the MOP to accommodate idioms like deleting
__proto__.. Remember, the first point above. [[SetInheritance]] is a
generic operation, only some objects implement via a [[Prototype]]
internal data property.
In practice, it's all of them except in platforms with no __proto__, no?
Even proxies have no way to override [[SetInheritance]].
Actually, if Reflect.setPrototypeOf is added, a setPrototypeOf handler
trap needs to be added as well. Some previous discussions about
__proto__ and proxies occurred at the July meeting [2].
David
[1] https://mail.mozilla.org/pipermail/es-discuss/2012-May/022834.html
[2]
http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies#discussed_during_tc39_july_2012_meeting_microsoft_redmond
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss