-
Notifications
You must be signed in to change notification settings - Fork 33.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"es6 & beyond": ch 7, errors in example code #423
Comments
Thanks for the fantastic reviews and notes! Will update ASAP. :) |
Actually, isn't
That's not strictly necessary, right? I can just do |
Yes. Sorry about the confusion.
Yep. |
Interesting. I had seen that the Since the built-in algorithm treats |
Addressed these concerns in that update. Please let me know if I missed anything. Thanks again! :) |
1966ded looks good to me. The
And 7.3.21 EnumerableOwnNames, step 6 (Object.keys calls EnumerableOwnNames):
IOW property order is only specified for |
Hmm... here's the logic I followed, what did I miss?
So, the fact that the informative code in 9.1.11 seems to contradict the statement "The mechanics and order of enumerating the properties is not specified". Moreover, the rest of that same sentence says "...but must conform to the rules specified below." Why does the informative code show use of |
Also, it seems perhaps the ES6 compat tables are potentially misled on this topic? https://kangax.github.io/compat-table/es6/#own_property_order Specifically, that they suggest that |
The rules don't include the generator function given in 9.1.11. The example only shows one possibility to implement [[Enumerate]], but the code is only informative, not normative. |
The spec indicates that the Proxy trap So, if I'm understanding this correctly, And for
But apparently, that's not supposed to indicate the ordering of Do I have that correct? |
I do understand the difference. However, in this case, the "informative" part is rather misleading. :( +@allenwb |
Not quite.
[[OwnPropertyKeys]] is only mentioned in [[Enumerate]] to make clear which properties have to be handled. That way an implementation cannot return additional property keys or leave out some of them.
|
I think I said the same thing, right? Quoting myself from above:
I would strongly suggest that that is super confusing to bury the lack of ordering in the nuance of "as if". I get it now, but I read this a dozen times and didn't get it. And clearly several other ES6 wonks have also missed it. Furthering the confusion, the informative note for
So, So, let me see if I now have this straight: All three features ( Is that now accurate? |
This was in response to:
Yes. |
OK, thanks. Appreciate your tolerance in helping me sort all this out! I am going to set aside my concern at how confusing it is that some orderings are predictably defined and others are not. That battle is obviously over and moot. However, I am going to file a spec bug to suggest that the I hope I'm not the only non-TC39'r that figures out that important nuance. |
Sure thing. The [[Enumerate]] specification was left a bit wishy-washy so implementation can keep their legacy behaviour. But time will tell if this legacy behaviour can be retained if additional language features are added (Proxies are especially interesting in this regard). For example two simple functions where [[Enumerate]] doesn't provide a definite answer about the runtime behaviour:
function changeProto() {
var o = {__proto__: {b: 0}, a: 0};
for (var k in o) {
if (k === "a") {
o.__proto__ = {c: 0};
}
console.log(k);
}
}
function changeEnumerable() {
var o = {A: 0, B: 0};
for (var k in o) {
if (k === "A") {
Object.defineProperty(o, "B", {enumerable: false});
}
console.log(k);
}
}
changeProto();
changeEnumerable(); Output using the example implementation from the spec: "a c A" |
@getify the meaning of "normative" and "non-normative"/"informative" are essential in understanding standards documents. See http://www.servicemanagement101.com/index.php/discussions/what-is-the-difference-between-a-normative-and-non-normative-document-accompanying-a-standard for a good explanation Note that "informative" material in a standard is non-normative material that is intended to assist in the understanding or use of the associated normative material. |
Yes, again, I am well aware of that. But if "assisting in the understanding" actually takes you wildly off course, it's not very "informative", is it? There are two pieces of information that mislead: One of them is in a non-normative code snippet. Sure, you can dismiss what it actually does if you mentally think "oh, it suggests this code is compliant, but it's not actually compliant." The note about the code says "...that conforms to these rules", but clearly that code does not in fact conform to the rules. But the more misleading one is the use of the phrase "as if" in otherwise normative text (or at least, what appears to be). That "as if" phrase apparently means "sorta like, but only partially". It's the "partially" part that is not in any way clear. It's not reasonably inferable from "as if" alone that this means "the same set of keys but not in the same order". It's a stretch, IMO, to suggest that a disconnected sentence several paragraphs earlier is somehow supposed to be connected mentally. Plainly:
I interpret the second statement, which implies defined ordering, to be clarifying the earlier "but must conform.." To be clear, I understand "as if" means "doesn't really call", but I don't understand how "as if" means "only partially like it". Setting aside normative vs non-normative, is that clear why there's unnecessary confusion there? |
@getify "as if" has a specific meaning in standards and is fine to use in normative text. "as if x" means: the observable results will be the same as you would get if you did x but it is ok to get those results some other way.
Why do you think it implies ordering? It says "obtain... as if by". It does not say "present ordered ... as if by". In fact, the numbered algorithm step explicitly says that the ordering is not specified. So, why are you trying to interpret what it subsequently says in a contrary manner? |
The code shows using It seems like it would have been more appropriate to use |
But they will in fact not be the same. Hence, my concern. If This is precisely the crux of the problem. "as if" implies that I'd be able to observe the same behavior (including the ordering), when in fact I'll only be able to observe the same keys in the list, but not be able to observe the same ordering.
The common understanding for "obtain" that I would assume is a specific set of steps for going and getting stuff. The nature of how that algorithm works will absolutely determine the order of stuff I get back. |
Again, I am trying to interpret the words in what I'd consider the most natural way from reading english words. The phrase "...but must conform to the rules specified below." comes at the end of the same sentence as the assertion of there being no ordering. The english word "but" typically contradicts or clarifies the immediately previous statement, in conventional grammar. So "but must conform..." implies that stuff that comes later will clarify this statement of no ordering. So, later, when it says "as if" and mentions |
There is no "proper ordering" specified for |
The example code asserts that the order will be/must be the same order as If the example code used |
So you are clearly reading something into "obtain" that I did not intend. I actually selected that word (and used the passive voice) specifically because I did not want to imply anything about processing order. Can you think of a better word that would not mislead you? 9.1.11 does not provide an algorithm, just a set of requirements (and a couple non-requirements). |
Old: "[[Enumerate]] must obtain the own property keys of the target object as if by calling its [[OwnPropertyKeys]] internal method." I would suggest this rewording: "[[Enumerate]] must produce the same set of owned property keys as the target object's [[OwnPropertyKeys]] internal method produces." The primary differences here are:
That completely divorces the statement from having any implication about ordering. |
The example code is "an implementation" and hence it imposes an implementation dependent ordering. But there is no assertion that there is anything normative about that particular algorithm or the ordering it produces.
It would violate architectural laying violation for an implementation of 9.1.11 to use |
The above is actually not correct. The set of keys "produced" by [[Enumerate]] presumably means the set of values that are returned by repeatedly calling |
But the ordering that code will produce is not implementation dependent from the perspective of any conforming ES6 engine. Imagine an engine decided to take that code verbatim and implement it for To put it plainly, the code puts a stronger requirement (guaranteeing an ordering) than the surrounding specification text is intended to. That's what I mean by "inconsistent". |
Not exactly. In fact, if you read I'm not suggesting the specification text for |
I didn't say that. I said essentially "...as [[OwnPropertyKeys]] produces..." If "produce" implies too much of iterator.next() semantics, perhaps s/produce/retrieve/. I am attempting to say the same thing as "obtain" says in existing wording, but changing the surrounding words to remove any implications of ordering.
I already said "owned property keys" (just as your original text did), which I assume filters out symbol properties. That is, if my text suffers from a confusion about whether symbol properties should be returned, so does yours. The same is true of enumerable or not. |
So how about this rewording? "[[Enumerate]] must produce the same set of owned property keys as would be returned by calling GetOwnPropertyKeys(target, String)". |
The current wording is trying to state some specific requirements that you restatement seems to be muddling (although I appreciate that you find the current text muddled). The spec. currently says:
Where "..." represents everything stating with the paragraph following the numbered step. What if it was changed to:
I think the text in brackets is unnecessary, but would be ok to have. |
|
would "must be retrieved by calling" be any clearer? I'm reluctant to eliminate "as if", which has a well establish meaning in language specifications and one that is quite applicable here. "string property keys" is covered in the first sentence of the numbered step. Also in the 2nd sentence of the of the paragraph that follow the numbered item. |
That sounds like the opposite of the wording we want, if I understand correctly. It doesn't actually call If you meant "must be retrieved as if by calling", then I'd say "retrieved as if by" is clearer to me than "obtained as if by", especially with the bracketed comment about it not relating to the ordering of |
@allenwb @anba if you don't mind, can you both please review the rework of the "Property Enumeration Order" section to make sure I correctly explained the outcome of this thread? Thanks! |
On May 1, 2015, at 6:36 AM, Kyle Simpson wrote:
"Prior to ES6, the order of enumeration of an object's keys/properties was implementation dependent and undefined by the specification. Generally, most engines have enumerated them in creation order, though developers have been strongly encouraged not to ever rely on this ordering. As of ES6, the order of enumeration is now defined in the specification (ES6 specification, section 9.1.12) as the " I think in the second paragraph you should say "order of enumeration for own properties is now...". Also, in ES6, when we say "enumeration order" we really specifically mean the order returned by [[Enumerate]] which is the order used by for-in. Because of that, it is somewhat misleading to use the phrase "order of enumeration" to talk about Reflect.ownKeys or as the title of this general discussion. More generally we are talking about different ways of iterating over property keys and the ordering each method provides. For example: for (key of Reflect.ownKeys(obj)) ... The Reflect.ownKeys ordering is something new in ES6. In ES5, the key ordering produced by Object.getOwnPropoertyNames was unspecified. (ie, implementation defined) "In other words, all four mechanisms will produce the same implementation dependent ordering..." It's less then obvious which four mechanisms you mean (I think: [[Enumerate]], Reflect.enumerate, for-in, Object.keys). It particular, I think somebody could get easily confused and think this is also talking about [[OwnPropertyKeys]] and friends. "Boiling this down: as of ES6, Reflect.ownKeys(..), Object.getOwnPropertyNames(..), and Object.getOwnPropertySymbols(..) all have predictable and reliable ordering..." once implementations all conform to the ES6 spec. Otherwise, than the above concern, I think you got it. |
great notes @allenwb, thanks as always for your patience with me as I get up to speed. ;-) |
Symbol.hasInstance requires Object.defineProperty (b/c non-configurable property on Function.prototype):
Needs to be:
The additive operator calls ToPrimitive without a hint, that means the
hint
argument for Symbol.toPrimitive is "default":Needs to be:
true
andfalse
need to be switched for theSymbol.unscopables
example.=>
Not quite correct,
Reflect.ownKeys(..)
returns the union ofObject.getOwnPropertyNames(..)
andObject.getOwnPropertySymbols(..)
.Wrong,
Reflect.has(object, key)
performskey in object
.Wrong,
Reflect.enumerate(..)
returns the enumerable properties (including prototype properties) likefor..in
, e.g.[...Reflect.enumerate([1,2,3])]
returns[ "0", "1", "2" ]
.And in "Tail Call Optimization (TCO)" it should be noted that tail calls are only valid in strict mode code. Maybe also add
"use strict";
to the examples?The text was updated successfully, but these errors were encountered: