Re: New ES6 draft now available
Hi, I haven't been following very closely some of the most recent discussions, so I appologize if my comments have been addressed already Le 23/11/2012 18:48, Allen Wirfs-Brock a écrit : Changes include: . Reorganized Chapter 8 into separate language type and specification type sub sections . Added Symbol property keys to the definition of the Object Type. terminology migration from talking about property names to property keys. I support this change. It's somewhat minor, but clearly indicates that a shift has occured. . MOP changes: Added [[GetInheritance]]/[[SetInheritance]] as internal methods for accessing [[Prototype]] internal prototype chain. Why not [[GetPrototype]] and [[SetPrototype]]? We have a absurd number of excellent resources (including but not limited to Dmitry Soshnikov and Axel Rauschmayer's websites/blogs) which use extensively the ES5 internal [[Prototype]]. It's also been very hard to get people to understand the difference between .prototype and [[Prototype]]. I'm afraid a new change would create a lot of confusion. Added [[[IsExtensible]]/[[PreventExtensions]]. ES5 had a note mentioning that there was no standard mechanism to set [[Extensible]] from false to true; this new way makes the note unnecessary by design of having internal methods instead of an internal property. OCaps FTW I guess :-) Replaced [[Get]]/[[Put]] with [[GetP]]/[[SetP]]. At some point we may be able to rename these as [[Get]]/[[Set]]. +1 for [[Get]]/[[Set]]. That's the accessor terminology, that's what JS devs are used to. It makes the spec easier to read for them. Eliminated [[GetProperty]], [[CanPut]], [[HasProperty]], [[DefaultValue]]. So good to see this cleanup :-) Added Keys, [[OwnPropertyKeys]], [[Freeze]], [[Seal]], [[IsFrozen]], [[IsSealed]]. For both the enumerations and the layer on top of [[PreventExtension]], I'm uneasy. * [[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 For proxies, [[Extensible]]ity-related operations have invariants so inconsistencies between [[PreventExtensions]], [[Freeze]], [[Seal]], [[IsExtensible]], [[IsFrozen]] and [[IsSealed]] are impossible. However, one can legitimately wonder what will happen if a new built-in operation using [[PreventExtensions]] is introduced in a later version of ECMAScript. Let's say experience with unique/private symbols reveals that the current Object.freeze behavior (whatever it is in regard to symbols) is inappropriate and that adding a new Object.freezeWithDifferentSymbolHandling is introduced. The current pattern suggests that adding new [[FreezeWithDifferentSymbolHandling]]/[[IsFrozenWithDifferentSymbolHandling]] internals will be the way to go. I'm not sure it's a good pattern. The issue seems worse in footgunness scale for enumeration operations because different operations could yield completely unrelated results. And once again, if it is wanted to add a new enumeration operation on syntax surface, it seems that a new internal operation will be necessary. 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. . instanceof operator no longer uses an internal method. Instead, extensible via a @@hasInstance symbol-keyed regular method. I don't remember a discussion on this topic, but I think it's an interesting change. Is it for browser APIs? There might be an associated security worry here if any object can have its
Re: New ES6 draft now available
• MOP changes: Added [[GetInheritance]]/[[SetInheritance]] as internal methods for accessing [[Prototype]] internal prototype chain. Why not [[GetPrototype]] and [[SetPrototype]]? We have a absurd number of excellent resources (including but not limited to Dmitry Soshnikov and Axel Rauschmayer's websites/blogs) which use extensively the ES5 internal [[Prototype]]. It's also been very hard to get people to understand the difference between .prototype and [[Prototype]]. I'm afraid a new change would create a lot of confusion. Currently, we have the following inheritance-related terms: 1. [[Prototype]] 2. [[GetInheritance]], [[SetInheritance]] 3. __proto__ 4. Object.getPrototypeOf() 5. C.prototype 1-4 are closely related, 5 refers to a different concept. I still welcome any measure to make this terminology easier to understand and talk about, but I realize that that might not be possible. Axel -- Dr. Axel Rauschmayer a...@rauschma.de home: rauschma.de twitter: twitter.com/rauschma blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: New ES6 draft now available
David Bruant wrote: Hi, I haven't been following very closely some of the most recent discussions, so I appologize if my comments have been addressed already Le 23/11/2012 18:48, Allen Wirfs-Brock a écrit : Changes include: • MOP changes: Added [[GetInheritance]]/[[SetInheritance]] as internal methods for accessing [[Prototype]] internal prototype chain. Why not [[GetPrototype]] and [[SetPrototype]]? We have a absurd number of excellent resources (including but not limited to Dmitry Soshnikov and Axel Rauschmayer's websites/blogs) which use extensively the ES5 internal [[Prototype]]. It's also been very hard to get people to understand the difference between .prototype and [[Prototype]]. I'm afraid a new change would create a lot of confusion. Neither of them is prototype, so the naming is unhappy. It is good that renaming is happening. And [[Prototype]] is imo worse of the two (the second being .prototype), so I welcome the fact that the operations were named as such. I hope the next step is to rename [[Prototype]] itself to [[Inheritance]]. Fair share of uses of [[Prototype]] were deleted in this change, and from those that left the most are in Chapter 15 where they are used mechanically to spec builtins. David Herby ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: New ES6 draft now available
Le 24/11/2012 15:23, Herby Vojčík a écrit : David Bruant wrote: Hi, I haven't been following very closely some of the most recent discussions, so I appologize if my comments have been addressed already Le 23/11/2012 18:48, Allen Wirfs-Brock a écrit : Changes include: • MOP changes: Added [[GetInheritance]]/[[SetInheritance]] as internal methods for accessing [[Prototype]] internal prototype chain. Why not [[GetPrototype]] and [[SetPrototype]]? We have a absurd number of excellent resources (including but not limited to Dmitry Soshnikov and Axel Rauschmayer's websites/blogs) which use extensively the ES5 internal [[Prototype]]. It's also been very hard to get people to understand the difference between .prototype and [[Prototype]]. I'm afraid a new change would create a lot of confusion. Neither of them is prototype I don't understand this sentence. What does them refer to? David so the naming is unhappy. It is good that renaming is happening. And [[Prototype]] is imo worse of the two (the second being .prototype), so I welcome the fact that the operations were named as such. I hope the next step is to rename [[Prototype]] itself to [[Inheritance]]. Fair share of uses of [[Prototype]] were deleted in this change, and from those that left the most are in Chapter 15 where they are used mechanically to spec builtins. David Herby ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: New ES6 draft now available
Le 24/11/2012 14:58, Axel Rauschmayer a écrit : • MOP changes: Added [[GetInheritance]]/[[SetInheritance]] as internal methods for accessing [[Prototype]] internal prototype chain. Why not [[GetPrototype]] and [[SetPrototype]]? We have a absurd number of excellent resources (including but not limited to Dmitry Soshnikov and Axel Rauschmayer's websites/blogs) which use extensively the ES5 internal [[Prototype]]. It's also been very hard to get people to understand the difference between .prototype and [[Prototype]]. I'm afraid a new change would create a lot of confusion. Currently, we have the following inheritance-related terms: 1. [[Prototype]] 2. [[GetInheritance]], [[SetInheritance]] 3. __proto__ 4. Object.getPrototypeOf() The fact that Object.getPrototypeOf retrieves the [[Prototype]] (ES5) or delegates to [[GetPrototype]] (ES6?) makes sense. I find delegating to [[GetInheritance]] more debatable. 5. C.prototype 1-4 are closely related, 5 refers to a different concept. I still welcome any measure to make this terminology easier to understand and talk about, but I realize that that might not be possible. As far as ES6 is concerned, it's likely that the 5 form will disappear because classes will cover most of the basic needs. .prototype will become useful only for people who know what they're doing. But ES6 in production is far down the road... David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
The ES6 MOP (Was: New ES6 draft now available)
(Changing Subject to better identify what is probably an important topic.) On Nov 24, 2012, at 5:31 AM, David Bruant wrote: Hi, I haven't been following very closely some of the most recent discussions, so I appologize if my comments have been addressed already (The possible excessive proxy invariants... thread https://mail.mozilla.org/pipermail/es-discuss/2012-November/026510.html and a few others are quite relevant to some of the points you raise below) Before I plunge in, I want to provide a little back ground for lurkers. In the Rev 12 ES6 draft, section 8.1.6 and its subsections define what I consider to be the ES Meta-Object Protocol (MOP). I don't actually use that terminology in the specification, but it is a convenient and concise term for something important so I'm going to use it below and probably in other discussions. The MOP generically defines the capabilities of all objects. The MOP is the abstraction layer that generic language features see and use interact with generic objects. If a (generic) capability is not exposed via the MOP is isn't available for use in specifying language features that apply to all kinds of objects. There may be many different forms of objects that provide alternative implementations of the MOP interface. These alternative forms include ordinary objects and various specified exotic objects including Proxy objects, Symbol objects, Array objects, etc. Other alternative forms includes what was formerly called host objects and encompasses the object forms specified by W3C's WebIDL. The MOP is the semantic extension point for plugging new forms of objects into ECMAScript. There could be many alternative MOP designs, and the current design is highly derived form the legacy ES=5.1 internal method model. There are various principles that might be applied to MOP design. Two principles I believe in are: 1) The MOP should be as narrow as possible (minimize number of MOP methods), and 2) Don't replicate common functionality across multiple MOP methods. The current ES6 draft MOP makes compromises on these principles. I think we can get closer it closer to them. Le 23/11/2012 18:48, Allen Wirfs-Brock a écrit : Changes include: • Reorganized Chapter 8 into separate language type and specification type sub sections • Added Symbol property keys to the definition of the Object Type. terminology migration from talking about “property names” to “property keys”. I support this change. It's somewhat minor, but clearly indicates that a shift has occured. • MOP changes: Added [[GetInheritance]]/[[SetInheritance]] as internal methods for accessing [[Prototype]] internal prototype chain. Why not [[GetPrototype]] and [[SetPrototype]]? We have a absurd number of excellent resources (including but not limited to Dmitry Soshnikov and Axel Rauschmayer's websites/blogs) which use extensively the ES5 internal [[Prototype]]. It's also been very hard to get people to understand the difference between .prototype and [[Prototype]]. I'm afraid a new change would create a lot of confusion. [[Prototype]] is now specified as internal state of ordinary objects and only some kinds of exotic objects. (For example, symbols and Proxy objects don't have that internal state). At the MOP level [[GetP]], [[SetP]] and [[Enumerate]] are the only methods whose ordinary implementations cares about inheritance. There really isn't anything in the MOP that mandates prototypal inheritance or even single inheritance. The MOP is currently rich enough that it is even possible to define object forms that support various styles of multiple inheritance. However, we do have legacy language and library operations for setting (__proto__) and retrieving [[Prototype]]. To define those language features they need to show up generically in the MOP. That's what [[GetInhertiance]]/[[SetInheritance]] provides. I choose those names because I wanted to place some distance between the generic MOP level operation and the specific [[Prototype]] internal data property that is present in ordinary objects. BTW, internal data property is a formally defined term that means private per object state. Such state is not part of the MOP. I think in the long run, the new names should reduce confusion, but I could be wrong. Regardless, I figured that there would be some controversy about these new names and they could easily be [[GetPrototype]]/[[SetPrototype]] but I wanted to run it up the flag pole and get reactions. Added [[[IsExtensible]]/[[PreventExtensions]]. ES5 had a note mentioning that there was no standard mechanism to set [[Extensible]] from false to true; this new way makes the note unnecessary by design of having internal methods instead of an internal property. OCaps FTW I guess :-) The MOP only works in terms of methods. All internal state is defined as parts of specific kinds of objects that implement the MOP
Re: New ES6 draft now available
On Nov 24, 2012, at 6:23 AM, Herby Vojčík wrote: David Bruant wrote: Hi, I haven't been following very closely some of the most recent discussions, so I appologize if my comments have been addressed already Le 23/11/2012 18:48, Allen Wirfs-Brock a écrit : Changes include: • MOP changes: Added [[GetInheritance]]/[[SetInheritance]] as internal methods for accessing [[Prototype]] internal prototype chain. Why not [[GetPrototype]] and [[SetPrototype]]? We have a absurd number of excellent resources (including but not limited to Dmitry Soshnikov and Axel Rauschmayer's websites/blogs) which use extensively the ES5 internal [[Prototype]]. It's also been very hard to get people to understand the difference between .prototype and [[Prototype]]. I'm afraid a new change would create a lot of confusion. Neither of them is prototype, so the naming is unhappy. It is good that renaming is happening. And [[Prototype]] is imo worse of the two (the second being .prototype), so I welcome the fact that the operations were named as such. I hope the next step is to rename [[Prototype]] itself to [[Inheritance]]. Fair share of uses of [[Prototype]] were deleted in this change, and from those that left the most are in Chapter 15 where they are used mechanically to spec builtins. This is largely now the case. Other than the Chapter 15 boiler plate all generic access should now be expressed as [[GetInheriance]]. The only place there should now be direct reference to [[Prototype]] are in the implementation of the MOP interface of ordinary objects or exotic objects that also have a [[Prototype]]. Ultimately these should all be in the currently numbered sections 8.3-8.5. I need to think about what we should do in chapter 15. Because class definitions use the work extends perhaps we can define some boiler place language that uses that verb. Allen David Herby ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: New ES6 draft now available
On Nov 24, 2012, at 8:43 AM, David Bruant wrote: Le 24/11/2012 14:58, Axel Rauschmayer a écrit : • MOP changes: Added [[GetInheritance]]/[[SetInheritance]] as internal methods for accessing [[Prototype]] internal prototype chain. Why not [[GetPrototype]] and [[SetPrototype]]? We have a absurd number of excellent resources (including but not limited to Dmitry Soshnikov and Axel Rauschmayer's websites/blogs) which use extensively the ES5 internal [[Prototype]]. It's also been very hard to get people to understand the difference between .prototype and [[Prototype]]. I'm afraid a new change would create a lot of confusion. Currently, we have the following inheritance-related terms: 1. [[Prototype]] 2. [[GetInheritance]], [[SetInheritance]] 3. __proto__ 4. Object.getPrototypeOf() The fact that Object.getPrototypeOf retrieves the [[Prototype]] (ES5) or delegates to [[GetPrototype]] (ES6?) makes sense. I find delegating to [[GetInheritance]] more debatable. This is a point that TomV and I have debated. Tom also thinks that the MOP/Proxy trap/Reflect.* naming should follow the precedents set by ES=5. My position is that these legacy functions are at a higher layer than the MOP and hence do not necessarily need to follow the same conventions. Also the current names are not all that consistent and don't reflect our current deeper understanding of JS objects (including DOM legacy). I'd prefer to keep the MOPish layer (including Proxy traps and Reflect.*) internally consistent and where necessary or beneficial deviate from legacy naming used at higher abstraction layers. 5. C.prototype 1-4 are closely related, 5 refers to a different concept. I still welcome any measure to make this terminology easier to understand and talk about, but I realize that that might not be possible. As far as ES6 is concerned, it's likely that the 5 form will disappear because classes will cover most of the basic needs. .prototype will become useful only for people who know what they're doing. But ES6 in production is far down the road... Yes, but everything we are talking about here is specifically about ES6 and beyond... Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: The ES6 MOP (Was: New ES6 draft now available)
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
Re: A new function name property proposal
On 24/11/2012, at 07:14, Brendan Eich wrote: Jorge Chamorro wrote: Bind the name inside the function *too*. That's not a compatible change, and unmotivated by any actual foot damage. The footgun (1) is to have the name bound *only* in the outer scope. We need evidence this is a real hazard. Otherwise you're assuming a conclusion and using a circular argument of sorts: that lack of the inner unwritable name binding is a problem requiring just that solution. Yes it's a corner case. Ok, so what's the non-corner foot-damaging case? Programmers do intentionally replace a function's name in its scope, e.g. to auto-memoize. Oh, how does that work? I've written memoizers but never needed to overwrite a name. http://osteele.com/posts/2006/04/one-line-javascript-memoization Works on global functions as well prototype methods. It can be done with FDs, but all the examples are using NFEs. The writable binding created by a function declaration? That's required by backward compatibility (e.g. the memoization pattern). The -outer- writable binding isn't the problem, the problem is the lack of binding in the inner scope. Is there a reason for not having it? Again, introducing such a binding is an incompatible change. I don't know what it might break, but I doubt anyone wants the risk. Also there's overhead in making such an inner binding -- another reason implementors won't go there. Finally, you have not justified this change by any evidence it addresses a real, observed hazard. Sorry, but I can't help thinking that fib should be bound in FDs as in NFEs: function fib (n) { return (n 2) ? 1 : fib(n-2)+ fib(n-1); } because if not it becomes a free var meaning that any recursive FD can be broken from the outside at any time, which does not seem to be the Right Way to do the things. Sounds like a WTF... one that's rarely going to bit, but a WTF nevertheless. Don't you think so? Cheers, -- Jorge. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: The ES6 MOP (Was: New ES6 draft now available)
On Nov 24, 2012, at 9:54 AM, David Bruant wrote: 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. I think it is a much smaller footgun than having 3 independent traps that don't have to be provided as a unit. If you have a single well specified trap, I expect an trap implementor to know or read the trap specification and see that there is a parameter that must be dealt with in a valid implementation. In practice, they are likely to handle all the variations in a single loop rather than having three separate loops and possibly deviant loop implementations in three separate traps. Also, implementations are going to want to optimize and always produce the complete inherited set is going to be observable (via proxy traps as the proto chain is climbed). Also note that the behavior of these traps for ordinary objects will be fully defined so that means that just getting own property names necessarily means that all proto and probably inherited properties must be observably visited and this even applies to code doing Proxy invariant checking that might need to access the own property names list. I think a single operation with a filter hint is a good trap off between trying to minimize footgunness and allowing implementations (including via Proxy traps) to apply reasonable optimizations. • 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. and it current happens 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
Leap second clarification
Hello, About 4 months ago, a leap second is inserted. And it reveals that there are many implementation diversity for leap seconds. For example, JavaScriptCore accepts the leap second in Date#toString format[1], but rejects it in ISO 8601 format. On the other hand, SpiderMonkey rejects it in Date#toString format, but accepts in ISO 8601. V8 rejects the leap second in ISO format and when it comes in Date#toString format, heuristic second check(0-59) decides it isn't second and fail to parse it. Chakra rejects both, and Carakan shows the same behavior to SpiderMonkey ( quated from this blog post http://uupaa.hatenablog.com/entry/2012/07/02/113201 ) I think it is better to describe it as NOTE or standardize this behavior. [1] Thu Dec 31 23:59:60 GMT 1998 [2] 2012-07-01T08:59:60Z -- Regards, Yusuke Suzuki ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A new function name property proposal
Jorge Chamorro wrote: On 24/11/2012, at 07:14, Brendan Eich wrote: Programmers do intentionally replace a function's name in its scope, e.g. to auto-memoize. Oh, how does that work? I've written memoizers but never needed to overwrite a name. http://osteele.com/posts/2006/04/one-line-javascript-memoization Works on global functions as well prototype methods. It can be done with FDs, but all the examples are using NFEs. Yes. So? The point is we can't make an incompatible change without more motivation and some sense that we're not going to break the web. Neither is in evidence. Don't you think so? No. You're rehashing a hypothetical worry at this point. Evidence first, to get any farther. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: New ES6 draft now available
David Bruant wrote: Hi, I haven't been following very closely some of the most recent discussions, so I appologize if my comments have been addressed already Le 23/11/2012 18:48, Allen Wirfs-Brock a écrit : Changes include: • Reorganized Chapter 8 into separate language type and specification type sub sections • Added Symbol property keys to the definition of the Object Type. terminology migration from talking about “property names” to “property keys”. I support this change. It's somewhat minor, but clearly indicates that a shift has occured. +1 • MOP changes: Added [[GetInheritance]]/[[SetInheritance]] as internal methods for accessing [[Prototype]] internal prototype chain. Why not [[GetPrototype]] and [[SetPrototype]]? We have a absurd number of excellent resources (including but not limited to Dmitry Soshnikov and Axel Rauschmayer's websites/blogs) which use extensively the ES5 internal [[Prototype]]. It's also been very hard to get people to understand the difference between .prototype and [[Prototype]]. I'm afraid a new change would create a lot of confusion. Yes, please -- let's not change names gratuitously. [[Prototype]] stays, so these should be related names. Added [[[IsExtensible]]/[[PreventExtensions]]. ES5 had a note mentioning that there was no standard mechanism to set [[Extensible]] from false to true; this new way makes the note unnecessary by design of having internal methods instead of an internal property. OCaps FTW I guess :-) Or just a restrictive MOP FTW ;-). Replaced [[Get]]/[[Put]] with [[GetP]]/[[SetP]]. At some point we may be able to rename these as [[Get]]/[[Set]]. +1 for [[Get]]/[[Set]]. That's the accessor terminology, that's what JS devs are used to. It makes the spec easier to read for them. Yes, I assumed the -P suffixing was a temporary renaming aid. Allen, can you confirm? Eliminated [[GetProperty]], [[CanPut]], [[HasProperty]], [[DefaultValue]]. So good to see this cleanup :-) +10! 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. As an internal method architecture for the spec, this seems fine -- the object returned cannot be observed and could be an internal type, a la Reference. For a proxy trap, this seems too low-level and the overhead (without optimization to look into the continuation for a destructuring pattern and avoid the object allocation) is again a potential problem. Tom should weigh in. • instanceof operator no longer uses an internal method. Instead, extensible via a @@hasInstance symbol-keyed regular method. I don't remember a discussion on this topic, but I think it's an interesting change. Is it for browser APIs? Yes, the DOM specifically, and WebIDL in general. There might be an associated security worry here if any object can have its @@hasInstance changed, but one good thing is that the debate of trapping instanceof ends if it's a symbol-keyed method. Proxies have trap integrity, that is, you can't mess with their handlers to mutate traps unless you are granted the handler capability. Right? • Defined all of the functions in the @Reflect module corresponding to MOP internal operations. IIRC __proto__ has been agreed to be an data property The jury is still out (could be accessor with poisoned reflection), but this is not material to your point. 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. Yes, we covered this on-list extensively. There should be no *.setPrototypeOf function anywhere. /be ___ es-discuss mailing list es-discuss@mozilla.org
Re: possible excessive proxy invariants for Object.keys/etc??
I am looking forward to proxies in JavaScript, and had a thought on the issues below. You could extend the the direct proxy approach for this. When the Proxy receives getOwnPropertyNames, it 1) notifies the handler that property names are being requested 2) the handler adds/removes any properties (configurable or otherwise subject to the normal constraints) on the target 3) upon return, the proxy invokes getOwnPropertyNames directly on the target (e..g, invoking the *normal *system primitive) This approach appears to have consistent behavior for configurability and extensibility. For example, the trap operation above could add configurable properties to an extensible target, and remove them later. It could add non-configurable properties, but they are permanent once added, etc. Thus there's no loss of generality. In addition to optionally setting up properties on the target, the handler trap above would need to indicate to the proxy (via exception or boolean result) that the getOwnPropertyNames operation should proceed ahead or fail. This extension of the direct proxy approach applies to all query operations, eliminates the copying and validation overhead discussed below, simplifies the implementation, retains full backwards compatibility, and enables most if not all the expressiveness we might expect for proxies. Dean From: Allen Wirfs-Brock al...@wirfs-brock.com Date: Tue, Nov 20, 2012 at 2:18 PM Subject: Fwd: possible excessive proxy invariants for Object.keys/etc?? To: es-discuss discussion es-discuss@mozilla.org Tom Van Custem have been having some email discussion while I work on integrating Proxys into the ES6 spec. He and I agree that some broader input would be useful so I'm going to forward some of the message here to es-discuss and carry the discussion forward here. Here is the first message with other to follow: Begin forwarded message: From: Allen Wirfs-Brock al...@wirfs-brock.com Date: November 18, 2012 1:26:14 PM PST To: Tom Van Cutsem tomvc...@gmail.com, Mark S. Miller erig...@google.com Cc: Jason Orendorff jorendo...@mozilla.com Subject: possible excessive proxy invariants for Object.keys/etc?? I'm wondering if the wiki spec. for these functions aren't doing invariant checking that goes beyond what is required for the integrity purposes you have stated. In general, proxies traps check to ensure that the invariants of a sealed/frozen target object aren't violated. Generally, only minimal processing needs to be done if the target is extensible and has no non-configurable properties. In fact the Virtual Object proposal says As long as the proxy does not expose non-configurable properties or becomes non-extensible, the target object is fully ignored (except to acquire internal properties such as [[Class]]). . The proxy spec.for Object.getOwnPropertyNames/kets/etc. seem to be doing quite a bit more than this. They 1) always copy the array returned from the trap? Why is this necessary? Sure the author of a trap should probably always return a fresh object but not doing so doesn't violate the integrity of the frozen/sealed invariants? In most cases they will provide a fresh object and copying adds unnecessary work that is proportional to the number of names to every such call. 2) ensuring that the list of property keys contains no duplicates. Why is this essential? Again, I don't see what it has to do with the integrity of the frozen/sealed invariants. It is extra and probably unnecessary work that is at least proportional to the number of names). 3) Every name in the list returned by the trap code is looked up on the target to determine whether or not it exists, even if the target is extensible. Each of those lookup is observable (the target might itself be a proxy) so, according to the algorithm they all must be performed. 4) Every own property of the target, is observably looked up (possibly a second time) even if the object is extensible and has no non-configurable properties. It isn't clear to me if any of this work is really necessary to ensure integrity. After all, what can you do with any of these names other than use them as the property key argument to some other trap/internal method such as [[SetP]], [[DefineOwnProperty]], etc. Called on a proxy, those fundamental operations are going to enforce the integrity invariants of the actual properties involved so the get name checks doesn't really seem to be adding anything essential. Perhaps we can just get rid of all the above checking. It seems like a good idea to me. Alternatively, it suggests that a [[GetNonConfigurablePropertyNames]] internal method/trap would be a useful call to have as the integrity invariants only care about non-configurable properties. That would significantly limit the work in the case where there are none and limit the observable trap calls to only the non-configurable properties. Allen
Re: possible excessive proxy invariants for Object.keys/etc??
+1. I think this is a really effective extension of the direct proxy approach, and I don't know why we didn't see it earlier. It's weird that this preserves all the flexibility of fully virtual configurable properties even though it insists that even these be made into real properties on the target. The trick is that placing a configurable property on the target doesn't commit the handler to anything, since the handler can remove or change this property freely as of the next trap. Apologies again for not yet having the time to do more than skim the thread at this point. But IIRC someone already suggested a similar change to some of the imperative traps -- perhaps freeze, seal, and preventExtensions. The handler would not perform these operations on the target, only to have the proxy check it. Rather, if the trap indicates that the operation should succeed, the proxy then simply performs the operation -- or else throws. I wonder if this philosophy could be extended to some of the other imperative operations as well? What expressiveness does this even-more-direct proxy approach lose? AFAICT, not much. At the same time, it should result in a *much* simpler implementation and much greater confidence that invariants of the non-proxy sublanguage are preserved by the introduction of proxies. In fact, I think it's much stronger on invariant preservation that the current direct proxies, while being much simpler. On Sat, Nov 24, 2012 at 6:49 PM, Dean Tribble dtrib...@gmail.com wrote: I am looking forward to proxies in JavaScript, and had a thought on the issues below. You could extend the the direct proxy approach for this. When the Proxy receives getOwnPropertyNames, it 1) notifies the handler that property names are being requested 2) the handler adds/removes any properties (configurable or otherwise subject to the normal constraints) on the target 3) upon return, the proxy invokes getOwnPropertyNames directly on the target (e..g, invoking the normal system primitive) This approach appears to have consistent behavior for configurability and extensibility. For example, the trap operation above could add configurable properties to an extensible target, and remove them later. It could add non-configurable properties, but they are permanent once added, etc. Thus there's no loss of generality. In addition to optionally setting up properties on the target, the handler trap above would need to indicate to the proxy (via exception or boolean result) that the getOwnPropertyNames operation should proceed ahead or fail. This extension of the direct proxy approach applies to all query operations, eliminates the copying and validation overhead discussed below, simplifies the implementation, retains full backwards compatibility, and enables most if not all the expressiveness we might expect for proxies. Dean From: Allen Wirfs-Brock al...@wirfs-brock.com Date: Tue, Nov 20, 2012 at 2:18 PM Subject: Fwd: possible excessive proxy invariants for Object.keys/etc?? To: es-discuss discussion es-discuss@mozilla.org Tom Van Custem have been having some email discussion while I work on integrating Proxys into the ES6 spec. He and I agree that some broader input would be useful so I'm going to forward some of the message here to es-discuss and carry the discussion forward here. Here is the first message with other to follow: Begin forwarded message: From: Allen Wirfs-Brock al...@wirfs-brock.com Date: November 18, 2012 1:26:14 PM PST To: Tom Van Cutsem tomvc...@gmail.com, Mark S. Miller erig...@google.com Cc: Jason Orendorff jorendo...@mozilla.com Subject: possible excessive proxy invariants for Object.keys/etc?? I'm wondering if the wiki spec. for these functions aren't doing invariant checking that goes beyond what is required for the integrity purposes you have stated. In general, proxies traps check to ensure that the invariants of a sealed/frozen target object aren't violated. Generally, only minimal processing needs to be done if the target is extensible and has no non-configurable properties. In fact the Virtual Object proposal says As long as the proxy does not expose non-configurable properties or becomes non-extensible, the target object is fully ignored (except to acquire internal properties such as [[Class]]). . The proxy spec.for Object.getOwnPropertyNames/kets/etc. seem to be doing quite a bit more than this. They 1) always copy the array returned from the trap? Why is this necessary? Sure the author of a trap should probably always return a fresh object but not doing so doesn't violate the integrity of the frozen/sealed invariants? In most cases they will provide a fresh object and copying adds unnecessary work that is proportional to the number of names to every such call. 2) ensuring that the list of property keys contains no duplicates. Why is this essential? Again, I don't see what it has to do with the integrity of the