Skip to content
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

Closed
anba opened this issue Apr 29, 2015 · 40 comments
Closed

"es6 & beyond": ch 7, errors in example code #423

anba opened this issue Apr 29, 2015 · 40 comments
Assignees

Comments

@anba
Copy link

anba commented Apr 29, 2015

Symbol.hasInstance requires Object.defineProperty (b/c non-configurable property on Function.prototype):

Foo[Symbol.hasInstance] = function(inst) {
    return inst.greeting == "hello";
};

Needs to be:

Object.defineProperty(Foo, Symbol.hasInstance, {
  value: function (inst) {
    return inst.greeting == "hello";
  },
  configurable: true
});

The additive operator calls ToPrimitive without a hint, that means the hint argument for Symbol.toPrimitive is "default":

arr[Symbol.toPrimitive] = function(hint) {
    if (hint == "number") {
        // sum all numbers
        return this.reduce( function(acc,curr){
            return acc + curr;
        }, 0 );
    }
};

Needs to be:

arr[Symbol.toPrimitive] = function(hint) {
    if (hint == "number" || hint == "default") {
        // sum all numbers
        return this.reduce( function(acc,curr){
            return acc + curr;
        }, 0 );
    }
};

true and false need to be switched for the Symbol.unscopables example.

o[Symbol.unscopables] = {
    a: true,
    b: false,
    c: true
};

=>

o[Symbol.unscopables] = {
    a: false,
    b: true,
    c: false
};
Some of the functions will look familiar as functions of the same names on Object:
    ...
    Reflect.ownKeys(..) --> Object.getOwnPropertyNames(..)

Not quite correct, Reflect.ownKeys(..) returns the union of Object.getOwnPropertyNames(..) and Object.getOwnPropertySymbols(..).

Also, Reflect.has(..) corresponds to the Object.prototype.hasOwnProperty(..) method. Essentially, Reflect.has(o,"foo") performs o.hasOwnProperty("foo").

Wrong, Reflect.has(object, key) performs key in object.

You can enumerate an object's values, essentially identical to consuming its @@iterator with ... or for..of, with Reflect.enumerate(..). For example, Reflect.enumerate([1,2,3]) would consume the iterator of the array, and return the received values as another [1,2,3] array.

Wrong, Reflect.enumerate(..) returns the enumerable properties (including prototype properties) like for..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?

@getify
Copy link
Owner

getify commented Apr 29, 2015

Thanks for the fantastic reviews and notes! Will update ASAP. :)

@getify getify changed the title ES6 & Beyond, ch.7: Errors in example code "es6 & beyond": ch 7, errors in example code Apr 29, 2015
@getify getify self-assigned this Apr 29, 2015
@getify
Copy link
Owner

getify commented Apr 29, 2015

b/c non-configurable property on Function.prototype

Actually, isn't defineProperty(..) needed strictly because @@hasInstance is a non-writable property on Function.prototype? configurable:false means the built-in one on Function.prototype can't be changed, but writable:false means that to set one on Foo, defineProperty(..) must be used. Correct?

Object.defineProperty( .. configurable: true } )

That's not strictly necessary, right? I can just do Object.defineProperty(Foo,Symbol.hasInstance,{value: .. }), right?

@anba
Copy link
Author

anba commented Apr 29, 2015

Actually, isn't defineProperty(..) needed strictly because @@hasInstance is a non-writable property on Function.prototype? configurable:false means the built-in one on Function.prototype can't be changed, but writable:false means that to set one on Foo, defineProperty(..) must be used. Correct?

Yes. Sorry about the confusion.

Object.defineProperty( .. configurable: true } )

That's not strictly necessary, right? I can just do Object.defineProperty(Foo,Symbol.hasInstance,{value: .. }), right?

Yep.

@getify
Copy link
Owner

getify commented Apr 29, 2015

the hint argument for Symbol.toPrimitive is "default":

Interesting. I had seen that the ToPrimtive abstract operation only gets "string" or "number", and that in the absence of a hint, "number" is assumed. I hadn't seen that the @@toPrimtive gets "default" in that latter case. Wonder why the args to @@toPrimitive aren't just the same as to ToPrimitive?

Since the built-in algorithm treats "default" the same as "number", seems like you'll probably always just end up doing hint == "default" || hint == "number", right? :)

@getify getify closed this as completed in 1966ded Apr 29, 2015
@getify
Copy link
Owner

getify commented Apr 29, 2015

Addressed these concerns in that update. Please let me know if I missed anything. Thanks again! :)

@anba
Copy link
Author

anba commented Apr 30, 2015

1966ded looks good to me.

The Reflect.enumerate(..) example from c2b9841 isn't correct. The property order in for-in, Reflect.enumerate and Object.keys is still implementation dependent, cf. 9.1.11 [[Enumerate]] :

The mechanics and order of enumerating the properties is not specified [...]

And 7.3.21 EnumerableOwnNames, step 6 (Object.keys calls EnumerableOwnNames):

Order the elements of names so they are in the same relative order as would be produced by the Iterator that would be returned if the [[Enumerate]] internal method was invoked on O.

IOW property order is only specified for Object.getOwnPropertyNames, Object.getOwnPropertySymbols and Reflect.ownKeys.

@getify
Copy link
Owner

getify commented Apr 30, 2015

Hmm... here's the logic I followed, what did I miss?

  1. 26.1.5.2: Reflect.enumerate(..) uses [[Enumerate]]
  2. 9.1.11: [[Enumerate]] essentially uses Reflect.ownKeys(..), as shown by the informative code listed.
  3. 26.1.11.3: Reflect.ownKeys(..) uses [[OwnPropertyKeys]], which has a well-defined order.

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 Reflect.ownKeys(..) if not to suggest that its order-behavior is what would be reliably observed?

@getify
Copy link
Owner

getify commented Apr 30, 2015

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 Object.keys(..) and for..in also have the predictable ordering. +@kangax

@anba
Copy link
Author

anba commented Apr 30, 2015

Moreover, the rest of that same sentence says "...but must conform to the rules specified below."

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.

@getify
Copy link
Owner

getify commented Apr 30, 2015

The spec indicates that the Proxy trap ownKeys is invoked for the [[OwnPropertyKeys]] operation (the one with defined ordering). In this @rauschma blog post, he indicates that Object.keys(..) will hit the ownKeys Proxy trap. Object.keys(..) invokes EnumerableOwnNames, which indeed calls [[OwnPropertyKeys]].

So, if I'm understanding this correctly, Object.keys(..) and for..in do invoke [[OwnPropertyKeys]] (indirectly, via EnumerableOwnNames), which does result in a predictable defined ordering. But then it's EnumerableOwnNames that subsequently jumbles up the ordering in implementation-dependent ways so as to not be predictable.

And for Reflect.enumerate(..), the spec says:

[[Enumerate]] must obtain the own property keys of the target object as if by calling its [[OwnPropertyKeys]] internal method.

But apparently, that's not supposed to indicate the ordering of [[OwnPropertyKeys]] applies, only what keys it obtains.

Do I have that correct?

@getify
Copy link
Owner

getify commented Apr 30, 2015

the code is only informative, not normative.

I do understand the difference. However, in this case, the "informative" part is rather misleading. :( +@allenwb

@anba
Copy link
Author

anba commented Apr 30, 2015

Do I have that correct?

Not quite. Reflect.enumerate() and for..in only call [[Enumerate]]. [[Enumerate]] itself does not call [[OwnPropertyKeys]], the spec says (emphasis mine):

[[Enumerate]] must obtain the own property keys of the target
object _as if_ by calling its [[OwnPropertyKeys]] internal method.

[[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.

Object.keys() (resp. EnumerableOwnNames) is a different beast. This operation has that strange additional re-order step for backward compatibility reasons (backward compatibility for Object.keys(), but also for 24.3.1.1 InternalizeJSONProperty, cf. the for-in loop in json2.js). By saying Object.keys(..) orders keys the same way as for-in, it's possible to use both interchangeably in that JSON operation.
I'm not quite sure if there's an additional reason beside JSON, maybe someone else can provide more info.

@getify
Copy link
Owner

getify commented Apr 30, 2015

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

And for Reflect.enumerate(..), the spec says:

[[Enumerate]] must obtain the own property keys of the target object as if by calling its [[OwnPropertyKeys]] internal method.

But apparently, that's not supposed to indicate the ordering of [[OwnPropertyKeys]] applies, only what keys it obtains.

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 EnumerableOwnNames (called explicitly by Object.keys(..)), in 7.3.21, says:

NOTE The order of elements is returned list is the same as the enumeration order that used by a for-in statement.

So, Object.keys(..) and for..in are going to end up with the same ordering, even though technically they aren't using the same abstract operation.


So, let me see if I now have this straight:

All three features (Reflect.enumerate(..), Object.keys(..), and for..in) have distinct algorithms (abstract operations) that wind up with the same key ordering, and that ordering is not the same as the ordering that comes from Reflect.ownKeys(..) (via [[OwnPropertyKeys]]).

Is that now accurate?

@anba
Copy link
Author

anba commented Apr 30, 2015

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

This was in response to:

So, if I'm understanding this correctly, Object.keys(..), Reflect.enumerate(..), and for..in all do invoke [[OwnPropertyKeys]] (indirectly, via EnumerableOwnNames), which does result in a predictable defined ordering.


Is that now accurate?

Yes.

@getify
Copy link
Owner

getify commented Apr 30, 2015

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 [[Enumerate]] section in particular needs to be a lot clearer on the fact that neither its non-normative use of Reflect.ownKeys(..) in example code, nor its "as if" statement referring to [[OwnPropertyKeys]] indicate the ordering that Reflect.ownKeys(..) and [[OwnPropertyKeys]] have, only the set of keys eligible for enumeration.

I hope I'm not the only non-TC39'r that figures out that important nuance.

+@allenwb @nzakas @rauschma @kangax

@anba
Copy link
Author

anba commented Apr 30, 2015

OK, thanks. Appreciate your tolerance in helping me sort all this out!

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:

  1. The prototype is changed during enumeration.
  2. The enumerable attribute is changed during enumeration.
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"
IE11: "a b A"
SpiderMonkey, Nashorn: "a b A B"
JavaScriptCore, V8: "a A B"

@allenwb
Copy link

allenwb commented Apr 30, 2015

@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.

@getify
Copy link
Owner

getify commented Apr 30, 2015

@allenwb

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:

  1. "The mechanics and order of enumerating the properties is not specified _but must conform to the rules specified below._"
  2. (then below) "[[Enumerate]] must obtain the own property keys of the target object _as if_ by calling its [[OwnPropertyKeys]] internal method."

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?

@allenwb
Copy link

allenwb commented Apr 30, 2015

@getify
Is there something non-compliant in the informative code that is shown? If so, that is a bug I can probably fix.

"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.

(then below) "[[Enumerate]] must obtain the own property keys of the target object as if by calling its [[OwnPropertyKeys]] internal method."

I interpret the second statement, which implies defined ordering, to be clarifying the earlier "but must conform.."

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?

@getify
Copy link
Owner

getify commented Apr 30, 2015

Is there something non-compliant in the informative code that is shown?

The code shows using Reflect.ownKeys(..), which will in fact produce the ordering from [[OwnPropertyKeys]]. This is not the proper ordering that Reflect.enumerate(..) is supposed to use.

It seems like it would have been more appropriate to use Object.keys(..), which does produce the same ordering as Reflect.enumerate(..) is supposed to have. That is, to say, Object.keys(..) and Reflect.enumerate(..) are both supposed to be the same ordering, but the ordering is implementation dependent (see earlier messages in this thread).

@getify
Copy link
Owner

getify commented Apr 30, 2015

as if x" means: the observable results will be the same

But they will in fact not be the same. Hence, my concern.

If [[Enumerate]] actually used [[OwnPropertyKeys]], the ordering would be the same as [[OwnPropertyKeys]], and I'd be able to observe that order. But that's not the correct order that [[Enumerate]] is supposed to have, which is presumably why you don't just have it actually call [[OwnPropertyKeys]]. So you do something that produces a different order, and I'll be able to observe a different order than if you had used [[OwnPropertyKeys]].

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.

Why do you think it implies ordering? It says "obtain... as if by".

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.

@getify
Copy link
Owner

getify commented Apr 30, 2015

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?

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 [[OwnPropertyKeys]] (which has clear ordering behavior), that sure seems to me to imply that this "as if" reference to [[OwnPropertyKeys]] is in fact clarifying that earlier "...the rules specified below".

@allenwb
Copy link

allenwb commented Apr 30, 2015

@getify

The code shows using Reflect.ownKeys(..), which will in fact produce the ordering from [[OwnPropertyKeys]], which is not the proper ordering that Reflect.enumerate(..) is supposed to used.

There is no "proper ordering" specified for Reflect.enumerate(obj). And all that it does is invoke obj.[[Enumerate]](). Neither 6.1.7.2 or 6.1.7.3 places any generic ordering requirements upon [[Enumerate]] and 9.1.11, which defines [[Enumerate]] for ordinary objects, explicitly says that enumeration order is "unspecified". I just don't see what is suggesting to you that there is some required or proper order.

@getify
Copy link
Owner

getify commented Apr 30, 2015

I just don't see what is suggesting to you that there is some required or proper order.

The example code asserts that the order will be/must be the same order as [[OwnPropertyKeys]], because that is incontrovertibly what Reflect.ownKeys(..) will do. Even though that code is non-normative, it is nevertheless inconsistent with the previous statement that ordering is implementation dependent.

If the example code used Object.keys(..) instead, the example code would actually match (no more, no less) the level of expectation of ordering -- that is, no expectation at all -- as is stated explicitly in the previous "The mechanics and order of enumerating the properties is not specified..." statement.

@allenwb
Copy link

allenwb commented Apr 30, 2015

@getify

The common understanding for "obtain" that I would assume is an algorithm for going and getting stuff. The nature of how that algorithm works will absolutely determine the order of stuff I get back.

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).

@getify
Copy link
Owner

getify commented Apr 30, 2015

Can you think of a better word that would not mislead you?

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:

  1. is more clear about the deviation than "as if" is (specifically the confused implications of "observable" earlier in the thread).
  2. uses "set", which has a common interpretation as being unordered.

That completely divorces the statement from having any implication about ordering.

@allenwb
Copy link

allenwb commented Apr 30, 2015

The example code asserts that the order will be/must be the same order as [[OwnPropertyKeys]], because that is incontrovertibly what Reflect.ownKeys(..) will do. Even though that code is non-normative, it is not consistent with the previous statement that ordering is implementation dependent.

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.

If the example code used Object.keys(..) instead, the example code would actually match (no more, no less) the level of expectation of ordering -- that is, no expectation at all -- as is stated explicitly in the previous "The mechanics and order of enumerating the properties is not specified..." statement.

It would violate architectural laying violation for an implementation of 9.1.11 to use Object.keys. And Object.keys is itself defined in terms of [[OwnPropertyKeys]], so why would the expectations be any different.

@allenwb
Copy link

allenwb commented Apr 30, 2015

"[[Enumerate]] must produce the same set of owned property keys as the target object's [[OwnPropertyKeys]] internal method produces."

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 next of the Iterator returned by [[Enumerate]]. That is not the same set as the List of values returned by [[OwnPropertyKeys]]. [[OwnPropertyKeys]] includes symbol-keyed properties and non-enumerable properties.

@getify
Copy link
Owner

getify commented Apr 30, 2015

hence it imposes an implementation dependent ordering.

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 [[Enumerate]]. The ordering it produced would always be the specification-required ordering from [[OwnPropertyKeys]]. No implementation that used that code would be able to make up its own ordering.

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".

@getify
Copy link
Owner

getify commented Apr 30, 2015

Object.keys is itself defined in terms of [[OwnPropertyKeys]], so why would the expectations be any different.

Not exactly. Object.keys(..) starts by getting [[OwnPropertyKeys]], but then 7.3.21.6 jumbles the order in an implementation-dependent way, which is precisely what I'm suggesting is the intent of the specification text for [[Enumerate]].

In fact, if you read Object.keys(..), it relies on the order of [[Enumerate]], and the order of [[Enumerate]] is by extension supposed to match Object.keys(..). For non-normative example code, that sounds like a perfect match that they circularly and symmetrically reference each other.

I'm not suggesting the specification text for [[Enumerate]] should actually invoke Object.keys(..). I am suggesting the non-normative example code in [[Enumerate]] should use Object.keys(..), since that will actually result in the correct implementation-dependent ordering.

@getify
Copy link
Owner

getify commented Apr 30, 2015

The set of keys "produced" by [[Enumerate]] presumably means

I didn't say that.

I said essentially "...as [[OwnPropertyKeys]] produces..." [[OwnPropertyKeys]] doesn't produce an iterator, but even if it did, repeatedly calling next() on it and retrieving those values would in fact produce the set of values from it that we're after, assuming of course you filter to only get "owned property keys" and not just "everything it returns".

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.

[[OwnPropertyKeys]] includes symbol-keyed properties and non-enumerable properties.

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.

@getify
Copy link
Owner

getify commented Apr 30, 2015

So how about this rewording?

"[[Enumerate]] must produce the same set of owned property keys as would be returned by calling GetOwnPropertyKeys(target, String)".

@allenwb
Copy link

allenwb commented Apr 30, 2015

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:

...The enumerable property names of prototype objects must be obtained as if by invoking the prototype object’s [[Enumerate]] internal method. [[Enumerate]] must obtain the own property keys of the target object as if by calling its [[OwnPropertyKeys]] internal method. Property attributes of the target object must be obtained as if by calling its [[GetOwnProperty]] internal method.

Where "..." represents everything stating with the paragraph following the numbered step. What if it was changed to:

... When implementing the preceding rules:

  • The enumerable property names of prototype objects must be obtained as if by invoking the prototype object’s [[Enumerate]] internal method [and processed in an implementation defined order].
  • The own property keys of the target object must be obtained as if by calling its [[OwnPropertyKeys]] internal method [and processed in an implementation defined order]..
  • The property attributes of the target object must be obtained as if by calling its [[GetOwnProperty]] internal method.

I think the text in brackets is unnecessary, but would be ok to have.

@getify
Copy link
Owner

getify commented Apr 30, 2015

  1. The bullet list helps... a little bit anyway.
  2. I was attempting to reword around "obtained" and "as if" confusions without needing to explicitly saying something about ordering as you have done in brackets. If you think the statement in brackets is better than finding other rewording, I'm fine in that it accomplishes my ultimate goal of decreasing confusion. I would change "and processed" to "but processed", as one final nit.
  3. Since you brought it up, it's unclear to me what in this text indicates that the "own property keys" must be "string property keys" (as not symbol props), and moreover what in the text indicates they must be enumerable?

@allenwb
Copy link

allenwb commented Apr 30, 2015

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.

@getify
Copy link
Owner

getify commented May 1, 2015

would "must be retrieved by calling" be any clearer?

That sounds like the opposite of the wording we want, if I understand correctly. It doesn't actually call [[OwnPropertyKeys]], does it?

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 [[OwnPropertyKeys]].

getify added a commit that referenced this issue May 1, 2015
@getify
Copy link
Owner

getify commented May 1, 2015

@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!

@allenwb
Copy link

allenwb commented May 1, 2015

On May 1, 2015, at 6:36 AM, Kyle Simpson wrote:

@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!


Reply to this email directly or view it on GitHub.

"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.

@getify
Copy link
Owner

getify commented May 1, 2015

great notes @allenwb, thanks as always for your patience with me as I get up to speed. ;-)

@getify
Copy link
Owner

getify commented May 1, 2015

@allenwb made tweaks based on your comments, in 572c341

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants