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

Does EnumerateObjectProperties have specified order enumeration? #1819

Closed
dSalieri opened this issue Dec 21, 2019 · 19 comments
Closed

Does EnumerateObjectProperties have specified order enumeration? #1819

dSalieri opened this issue Dec 21, 2019 · 19 comments
Labels

Comments

@dSalieri
Copy link

My question sounds as: in chapter 13.7.5.15 EnumerateObjectProperties we have the following steps of the algorithm:

  1. Assert: Type(O) is Object.
  2. Return an Iterator object (25.1.1.2) whose next method iterates over all the String-valued keys of enumerable properties of O. The iterator object is never directly accessible to ECMAScript code. The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below.

If we read further, we will see the following entry:

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

Question: why is it written above that order of enumerating the properties is not specified, if the operation [[OwnPropertyKeys]] is concrete specified, which describes in what sequence the property keys should go.

I saw a lot of questions on SO about this issue. But the answers were different since some said that there is order, while others did not, please clarify the situation

@ljharb
Copy link
Member

ljharb commented Dec 21, 2019

#1791 is relevant.

@jmdyck
Copy link
Collaborator

jmdyck commented Dec 21, 2019

  • 6.1.7.3 doesn't require that [[OwnPropertyKeys]] return property keys in a particular order. Most kinds of object do specify a particular order, but Proxy objects don't, and non-standard exotics aren't required to.
  • Although the spec says that EnumerateObjectProperties must use [[OwnPropertyKeys]] to obtain the own property keys of an object, I don't think that it's required to enumerate them in the same (relative) order.

@dSalieri
Copy link
Author

@jmdyck if we touches invariants, the invariant does not say anything about how property keys should be enumerated. You said that: “Most kinds of object do specify a particular order” - what exactly is a particular order for them in this case, because as I wrote earlier in the question, the specification is ambiguous (not clear) and people interpret it as they want. I would like to hear not an opinion or an assumption, but the real situation.

Yes, the specification uses [[OwnPropertyKeys]], which specifies the specific order in which properties are obtained. But what's the point of mixing these properties or changing their order after receiving property keys? By the way, I saw somewhere that some operations that do not use prototype chains, but have only their own properties, have just the specified transfer order in accordance with [[OwnPropertyKeys]] - as an example, GetOwnPropertyKeys algorithm. From this we can conclude that the internal [[OwnPropertyKeys]] method is used to obtain the personal properties of the object, not its prototypes, and since we have an operation called EnumerateObjectProperties, we must list all the properties of the object, including the properties of its prototypes. And since there can be an unlimited number of prototypes, [[OwnPropertyKeys]] is also applied to the prototype as an object. That for the object which was the initiator of EnumerateObjectProperties is not told how to dock its personal properties with the properties that it inherits.

This is my vision of the situation. But again, I would like to hear the official version.

@jmdyck
Copy link
Collaborator

jmdyck commented Dec 22, 2019

You said that: "Most kinds of object do specify a particular order" - what exactly is a particular order for them in this case,

Note that I wrote that in a paragraph about the behavior of [[OwnPropertyKeys]]. I think you've read it as talking about EnumerateObjectProperties.

Yes, the specification uses [[OwnPropertyKeys]], which specifies the specific order in which properties are obtained.

My first point is that the spec doesn't always specify that order.

But what's the point of mixing these properties or changing their order after receiving property keys?

You're reading the spec too much like an implementation. When the spec says:

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

it means that EnumerateObjectProperties should behave as if it did that. Or in other words, the set of own property keys that EnumerateObjectProperties starts with for an object must be the same as would be returned by an invocation of the object's [[OwnPropertyKeys]] internal method.

An implementation might have a function A that returns own property keys in alphabetical order, say. And a slower function B that returns the same keys, but in the order required of [[OwnPropertyKeys]]. The corresponding implementation of EnumerateObjectProperties could invoke B, but it's allowed to invoke A, and that's faster, so it does. From the outside, it might look like it's invoking [[OwnPropertyKeys]] and then rearranging the results (for which you're asking, what's the point?), but that's not what it's doing.

@dSalieri
Copy link
Author

@jmdyck

Note that I wrote that in a paragraph about the behavior of [[OwnPropertyKeys]]. I think you've read it as talking about EnumerateObjectProperties.
My first point is that the spec doesn't always specify that order.

Alright.

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

The [[OwnPropertyKeys]] method specifies how keys should be added to the resulting list. From which we will then read the properties in iteration order. Therefore:

An implementation might have a function A that returns own property keys in alphabetical order, say. And a slower function B that returns the same keys, but in the order required of [[OwnPropertyKeys]]. The corresponding implementation of EnumerateObjectProperties could invoke B, but it's allowed to invoke A, and that's faster, so it does. From the outside, it might look like it's invoking [[OwnPropertyKeys]] and then rearranging the results (for which you're asking, what's the point?), but that's not what it's doing.

I don’t understand what you brought about 2 abstract functions if the specification requires the execution of [[OwnPropertyKeys]], which, as I said, is clearly defined several times.
Although if the implementation uses its own algorithm instead of [[OwnPropertyKeys]] in EnumerateObjectProperties, then this is a specification mismatch. Is not it?

And it looks like you made a logical mistake: you say there are "A" and "B", "A" does not match [[OwnPropertyKeys]], and "B" matches [[OwnPropertyKeys]]. Then you write that it is allowed to invoke "A". Why?

So you confused me. What do functions "A" and "B" have to do with [[OwnPropertyKeys]]?

@jmdyck
Copy link
Collaborator

jmdyck commented Dec 22, 2019

Okay, I'll try to spell it out in more detail, but I'm not sure it's going to be clearer.

EnumerateObjectProperties is an abstract operation. [[OwnPropertyKeys]] is an internal method. Neither of these is accessible to ECMAScript code. So an implementation is not required to have procedures with these names, or similar names, or any particular unit of code that identifiably accomplishes what these two things are specified to do. The spec does not tell you how to design/construct your implementation. It defines a large model and how it behaves, and says "There. Whatever behavior can be observed of that model, i.e. the effects that are visible to ECMAScript code, that is what is required of your implementation."

So when the spec "requires the execution of [[OwnPropertyKeys]]", it doesn't mean that your implementation has to have a procedure implementing EnumerateObjectProperties and a procedure implementing [[OwnPropertyKeys]] and the former is required to call the latter. It just means that, in the abstract model the spec is constructing, EnumerateObjectProperties calls [[OwnPropertyKeys]] to get the set of own property keys that it starts with.

Now, despite the above, an implementation is certainly not disallowed from having procedures that directly correspond to abstract operations and internal. So for simplicity, consider an implementation that has a procedure (call it E) that directly corresponds to what EnumerateObjectProperties does. And it has a procedure (B) that supplies own property keys in exactly the way required by [[OwnPropertyKeys]]. So you might expect E to call B. And it could, but the spec does not require it. If the spec said that the iterator returned by EnumerateObjectProperties went through the keys in the same order as the list supplied by [[OwnPropertyKeys]], then in this hypothetical implementation, E probably would call B. But the spec doesn't say that. In this implementation, E is free to call any procedure that supplies the same set of keys as B. In this example, there's a faster procedure (A) that will do so, and so E calls A. (So no, I didn't make a logical mistake.)

So when the spec allows the iterator returned by EnumerateObjectProperties to iterate through keys in a different order than is returned by [[OwnPropertyKeys]], the point is not to allow the implementation to rearrange a list of keys that it gets from somewhere, the point is to allow the implementation to use a list of keys that is (already) in a different order from that required by [[OwnPropertyKeys]] (or, more likely, to use a pre-existing property-finding algorithm that doesn't find properties in the order required of [[OwnPropertyKeys]]).

@dSalieri
Copy link
Author

@jmdyck EnumerateObjectProperties is not fully defined, so the implementation of this function may vary other than what is specified by the specification itself. [[OwnPropertyKeys]] - defined by the specification and we need to follow the steps in this method, we should not do what is not specified in this method. Is that not so?

EnumerateObjectProperties is an abstract operation. [[OwnPropertyKeys]] is an internal method. Neither of these is accessible to ECMAScript code. So an implementation is not required to have procedures with these names, or similar names, or any particular unit of code that identifiably accomplishes what these two things are specified to do. The spec does not tell you how to design/construct your implementation. It defines a large model and how it behaves, and says "There. Whatever behavior can be observed of that model, i.e. the effects that are visible to ECMAScript code, that is what is required of your implementation."

The fact that the abstract operation and the internal method is not accessible from ECMAScript code does not mean that we should not follow the steps of the algorithms in them (as to the fact that the implementation is not required to follow the specific names of the algorithms, this is obvious).

So when the spec "requires the execution of [[OwnPropertyKeys]]", it doesn't mean that your implementation has to have a procedure implementing EnumerateObjectProperties and a procedure implementing [[OwnPropertyKeys]] and the former is required to call the latter. It just means that, in the abstract model the spec is constructing, EnumerateObjectProperties calls [[OwnPropertyKeys]] to get the set of own property keys that it starts with.

If the implementation does not follow the steps that are defined by the specification, it will be a mismatch, a violation. Does the specification mean that implementations are allowed to implement the ECMAScript model as she pleases, breaking the rules that the specification sets? If you say that it doesn’t matter what the abstract operation EnumerateObjectProperties and the [[OwnPropertyKeys]] method will be called in the implementation, then this is understandable.

Now, despite the above, an implementation is certainly not disallowed from having procedures that directly correspond to abstract operations and internal. So for simplicity, consider an implementation that has a procedure (call it E) that directly corresponds to what EnumerateObjectProperties does. And it has a procedure (B) that supplies own property keys in exactly the way required by [[OwnPropertyKeys]]. So you might expect E to call B. And it could, but the spec does not require it.

Wait what is about:

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

You say that the implementation is not required to use [[OwnPropertyKeys]], but the quote above from the specification thinks differently. Or what? If I misunderstood, explain.

So when the spec allows the iterator returned by EnumerateObjectProperties to iterate through keys in a different order than is returned by [[OwnPropertyKeys]], the point is not to allow the implementation to rearrange a list of keys that it gets from somewhere, the point is to allow the implementation to use a list of keys that is (already) in a different order from that required by [[OwnPropertyKeys]] (or, more likely, to use a pre-existing property-finding algorithm that doesn't find properties in the order required of [[OwnPropertyKeys]]).

As I understand it, you are talking about not re-sorting the property keys of the object, which were obtained as a result of some actions that are not described by the specification in the EnumerateObjectProperties operation. I am right?

@jmdyck
Copy link
Collaborator

jmdyck commented Dec 23, 2019

[[OwnPropertyKeys]] - defined by the specification and we need to follow the steps in this method,

That largely depends on what you mean by "follow the steps". If you mean that the implementation needs to have a procedure corresponding to [[OwnPropertyKeys]], with lines that correspond to step 1, and lines that correspond to step 2, and so on, then no, we don't need to do that. The implementation only needs to exhibit the behavior that would be observed of the model.

we should not do what is not specified in this method. Is that not so?

An implementation can certainly do things that are not specified in the method, provided they're not inconsistent with the constraints imposed by the method.

The fact that the abstract operation and the internal method is not accessible from ECMAScript code does not mean that we should not follow the steps of the algorithms in them

Again, it depends on what you mean by "follow the steps".

If the implementation does not follow the steps that are defined by the specification, it will be a mismatch, a violation.

No, the implementation is free to do something different if it gets the same results (or more precisely, if it gets results that conform to the constraints imposed by the spec).

Wait what is about:

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

You say that the implementation is not required to use [[OwnPropertyKeys]], but the quote above from the specification thinks differently. Or what? If I misunderstood, explain.

EnumerateObjectProperties and [[OwnPropertyKeys]] only exist in the spec's model (or at least, they're only guaranteed to exist in the spec's model). So when the spec says that EnumerateObjectProperties must call [[OwnPropertyKeys]], it's telling you something about how the model works. That restricts the behavior that the model can exhibit, which then restricts the behavior that a conforming implementation can exhibit.

For example, one observable restriction on behavior that results from the quoted sentence is that if X is an object without a prototype, then for (key in X) must give you the same set of keys as the String-valued keys returned by Reflect.ownKeys(X). (I think I got that right.)

@dSalieri
Copy link
Author

dSalieri commented Dec 25, 2019

@jmdyck

That largely depends on what you mean by "follow the steps".

"follow the steps" - by this I meant that the implementation follows the requirements that are written in each step of an operation or algorithm. If a single line is written in the specification, then the implementation does not have to enforce as a single line of code.

If you mean that the implementation needs to have a procedure corresponding to
[[OwnPropertyKeys]], with lines that correspond to step 1, and lines that correspond to step 2, and so on, then no, we don't need to do that.

Why we don't need to do that?

The implementation only needs to exhibit the behavior that would be observed of the model

Is this somewhere described in the specification? It always seemed to me that the implementation should clearly correspond to the points that are specifically specified in the specification. But where the specification does not give clear directions - there you can do whatever you want.

An implementation can certainly do things that are not specified in the method, provided they're not inconsistent with the constraints imposed by the method.

Although this is a little implicit, but it’s understandable, the main thing is to correspond the specification requirement - the rest does not matter.

If the implementation does not follow the steps that are defined by the specification, it will be a mismatch, a violation.

No, the implementation is free to do something different if it gets the same results (or more precisely, if it gets results that conform to the constraints imposed by the spec).

Ok, now let's recall our internal object method [[OwnPropertyKeys]].
There are 5 steps and each step clearly defines what should happen when this method is called. If the implementation does not follow [[OwnPropertyKeys]], then why is it defined by the specification? It makes sense to define an operation when it is easier to impose restrictions and not write the steps of the operation in the specification?

For example, one observable restriction on behavior that results from the quoted sentence is that if X is an object without a prototype, then for (key in X) must give you the same set of keys as the String-valued keys returned by Reflect.ownKeys(X)

As I wrote above, it makes sense to define the steps of an operation in a specification if you can just impose restrictions? And due to only restrictions, we will achieve what you wrote above.

I remember the invariants - constraints for the internal methods of an object. [[OwnPropertyKeys]] - is an internal method with the presence of invariants. But then the reasonable question is why do we need an algorithm and invariants (restrictions) defined together by a specification?

@jmdyck
Copy link
Collaborator

jmdyck commented Dec 25, 2019

If you mean that the implementation needs to have a procedure corresponding to
[[OwnPropertyKeys]], with lines that correspond to step 1, and lines that correspond to step 2, and so on, then no, we don't need to do that.

Why we don't need to do that?

Because:

The implementation only needs to exhibit the behavior that would be observed of the model

(Or rather, the implementation only needs to exhibit some behaviour that could be observed of the model.)

Is this somewhere described in the specification?

5.2 Algorithm Conventions says "These algorithms are used to precisely specify the required semantics of ECMAScript language constructs. The algorithms are not intended to imply the use of any specific implementation technique. In practice, there may be more efficient algorithms available to implement a given feature."

It always seemed to me that the implementation should clearly correspond to the points that are specifically specified in the specification.

That might make some things easier, but it would probably be an inefficient implementation.

Ok, now let's recall our internal object method [[OwnPropertyKeys]].
There are 5 steps

Presumably you're looking at the [[OwnPropertyKeys]] for ordinary objects. It has only one step, but it invokes OrdinaryOwnPropertyKeys, which has 5 top-level steps.

and each step clearly defines what should happen when this method is called.

Yes, it defines what should happen in the model.

If the implementation does not follow [[OwnPropertyKeys]], then why is it defined by the specification?

To indirectly specify constraints on some of the behavior that the implementation must exhibit.

It makes sense to define an operation when it is easier to impose restrictions and not write the steps of the operation in the specification?

Can you think of an example where the spec gives the steps of an operation when it would be easier to "impose restrictions"?

I remember the invariants - constraints for the internal methods of an object. [[OwnPropertyKeys]] - is an internal method with the presence of invariants. But then the reasonable question is why do we need an algorithm and invariants (restrictions) defined together by a specification?

This was covered in issue #1628. I'm not going to rehash it here.

@dSalieri
Copy link
Author

dSalieri commented Dec 26, 2019

@jmdyck Hmm, what exactly is meant by:

These algorithms are used to precisely specify the required semantics of ECMAScript language constructs

as I understand your answers in total, the steps of the algorithms shows the key meaning of any algorithm. Based on this, we must follow this meaning and we do not have to follow the steps, since the essence of the algorithm displayed in the steps of the specification is important. I am right?

Hmm, in that case, what should be the specification if it wants to specify exactly what steps that it shows in some algorithm have an important role in the order they are executed (hint at [[OwnPropertyKeys]])?

Can you think of an example where the spec gives the steps of an operation when it would be easier to "impose restrictions"?

I can’t remember this in the specification. By constraint, I certainly meant invariants. And they are applied to the internal methods of objects.

This was covered in issue #1628. I'm not going to rehash it here.

Exactly, if I'm not mistaken, invariants are created to cover objects not defined by the specification. Is not it?

@jmdyck
Copy link
Collaborator

jmdyck commented Dec 27, 2019

the steps of the algorithms shows the key meaning of any algorithm. Based on this, we must follow this meaning and we do not have to follow the steps, since the essence of the algorithm displayed in the steps of the specification is important. I am right?

Maybe. I'm not sure what you have in mind when you say "the essence of the algorithm".

Hmm, in that case, what should be the specification if it wants to specify exactly what steps that it shows in some algorithm have an important role in the order they are executed (hint at [[OwnPropertyKeys]])?

The spec doesn't have a special way to convey that the order of execution of an algorithm's steps is important -- that's the default. I.e., you have to assume that order is important unless you can prove otherwise.

@dSalieri
Copy link
Author

dSalieri commented Dec 27, 2019

@jmdyck

Maybe. I'm not sure what you have in mind when you say "the essence of the algorithm".

By this I meant that the implementing algorithm should behave in such a way that it follows the steps of the algorithm from the specification, but in such a way that it does not violate the goals that the algorithm from the specification pursues (Or what our visible effects should be in our algorithm). Now you understand what I mean? In this case, I understand correctly?

The spec doesn't have a special way to convey that the order of execution of an algorithm's steps is important -- that's the default. I.e., you have to assume that order is important unless you can prove otherwise.

I dare to suggest that Notes can explain the importance of the order in which certain steps are performed in specification algorithms. Since notes are often found in steps of an algorithm. But yes, you are right that there is no special way to specifically indicate the importance of the order of the steps in the algorithm.


As a result, my main question was that I asked if there was a specific order for obtaining property keys in EnumerateObjectProperties.
And what do we have in the end? In any algorithm provided by the specification, you can do whatever you want, but within the restrictions that the steps of these algorithms tell us.
From this the question arises: "how do we understand what is the restrictions and what is not"? How can I understand what there are restrictions in the [[OwnPropertyKeys]] and what are not? Because my question did not go away, maybe the order that creates the algorithm [[OwnPropertyKeys]] is important?

@jmdyck
Copy link
Collaborator

jmdyck commented Dec 27, 2019

In this case, I understand correctly?

Possibly. It's hard for me to tell.

I dare to suggest that Notes can explain the importance of the order in which certain steps are performed in specification algorithms.

They can. But since "order is important" is the default, I think such a Note would only be useful when the order of steps is somehow unintuitive, which is probably fairly rare.

As a result, my main question was that I asked if there was a specific order for obtaining property keys in EnumerateObjectProperties.

And do have the answer to that question now?

In any algorithm provided by the specification, you can do whatever you want, but within the restrictions that the steps of these algorithms tell us.

Something like that, yes. But it sounds like you're still thinking in terms of "implementing each spec algorithm".

From this the question arises: "how do we understand what is the restrictions and what is not"?

I'm not sure what you mean by "restrictions" there, but I think the answer is: you need to read and understand the spec and figure out how the algorithm steps (and any other requirements in the spec) constrain the observable behavior of the model.

How can I understand what there are restrictions in the [[OwnPropertyKeys]] and what are not? Because my question did not go away, maybe the order that creates the algorithm [[OwnPropertyKeys]] is important?

[[OwnPropertyKeys]] is fairly easy, because the list of keys it returns is completely observable (just not via EnumerateObjectProperties).

@dSalieri
Copy link
Author

@jmdyck I did not answer for a long time, as I was collecting my thoughts for the complete and correct construction of my message.

So. Let's start with the thesis that you wrote once in one of your posts above:

The implementation only needs to exhibit the behavior that would be observed of the model

The model is a specification (not an implementation of the specification). That is, the implementation should demonstrate the behavior that the specification provides, right? From this I can conclude the following: the internal method [[OwnPropertyKeys]] from the ECMAScript model in the specification implementation is required to return a list of property keys in the order described by the specification, namely:

  1. For each own property key P of O that is an array index, in ascending numeric index order, do
    a. Add P as the last element of keys.
  2. For each own property key P of O that is a String but is not an array index, in ascending chronological order of property creation, do
    a. Add P as the last element of keys.
  3. For each own property key P of O that is a Symbol, in ascending chronological order of property creation, do
    a. Add P as the last element of keys.

Do I understand correctly that the order of adding keys to the list is still important? First numeric, then string, then symbol. Since in the ECMAScript model we observe specifically this order for property keys that are proprietary to the object.

(Or rather, the implementation only needs to exhibit some behaviour that could be observed of the model.)

This can be seen by various methods: Object.keys, Object.values, Object.entries, Reflect.ownKeys
But remember your following statement:

6.1.7.3 doesn't require that [[OwnPropertyKeys]] return property keys in a particular order. Most kinds of object do specify a particular order, but Proxy objects don't, and non-standard exotics aren't required to.

But this conflicts with the statement:

The spec doesn't have a special way to convey that the order of execution of an algorithm's steps is important -- that's the default. I.e., you have to assume that order is important unless you can prove otherwise.

How would I suggest that in the [[OwnPropertyKeys]] internal method, the order in which the properties are added matters. And only because there are such lines in the algorithm:

...is an array index, in ascending numeric index order, do...
...is a String but is not an array index, in ascending chronological order of property creation, do...
...is a Symbol, in ascending chronological order of property creation, do...

Otherwise, the specification would write that the properties can be added to the list in any convenient way. And then, instructions on how keys should be added to the list - is this not a constrain? Or am I wrong?
And by the way:

If the implementation does not follow [[OwnPropertyKeys]], then why is it defined by the specification?

To indirectly specify constraints on some of the behavior that the implementation must exhibit.

That is, still [[OwnPropertyKeys]] imposes constraints, and what are these constraints in this case? A rather confusing situation regarding [[OwnPropertyKeys]] has developed

As for for ... in which is engaged in the enumeration of the keys of the properties of the object, it lists not only the own keys of the specified object but the keys of its prototypes to null prototype in the chain. And here, as we can see, the specification does not tell us how to process the properties of an object and the properties of its prototype chain (there is no specific sequence).
So yes:

As a result, my main question was that I asked if there was a specific order for obtaining property keys in EnumerateObjectProperties.

And do have the answer to that question now?

I have an answer to this question. There is no order to get properties with the EnumerateObjectProperties operation. Since the specification does not tell us how to specifically process the properties of prototypes of an object (it only tells what operation to use to get properties from each prototype object) and does not say how a chain should be formed from the properties of an object with its inherited properties.

Something like that, yes. But it sounds like you're still thinking in terms of "implementing each spec algorithm".

Perhaps because the specification is perceived to me as a set of algorithms. But I will take into account that the specification should be perceived as a model with observable effects.

@jmdyck
Copy link
Collaborator

jmdyck commented Dec 31, 2019

[...] the internal method [[OwnPropertyKeys]] from the ECMAScript model in the specification implementation is required to return a list of property keys in the order described by the specification, namely:

[steps from OrdinaryOwnPropertyKeys]

Yes, but that particular order is required only for ordinary objects.

Do I understand correctly that the order of adding keys to the list is still important?

Yes, because it's completely observable.

Since in the ECMAScript model we observe specifically this order for property keys that are proprietary to the object.
This can be seen by various methods: Object.keys, Object.values, Object.entries, Reflect.ownKeys

Note that Object.keys, Object.values, and Object.entries invoke EnumerableOwnPropertyNames, which exposes only String-valued property keys, so they don't allow you to observe the effect of step 4 of OrdinaryOwnPropertyKeys. But Reflect.ownKeys does, because it exposes all own property keys.


But remember your following statement:

6.1.7.3 doesn't require that [[OwnPropertyKeys]] return property keys in a particular order. Most kinds of object do specify a particular order, but Proxy objects don't, and non-standard exotics aren't required to.

But this conflicts with the statement:

The spec doesn't have a special way to convey that the order of execution of an algorithm's steps is important -- that's the default. I.e., you have to assume that order is important unless you can prove otherwise.

The two statements don't conflict. 6.1.7.3 doesn't impose a constraint on the order of keys returned by any [[OwnPropertyKeys]] method, but specific [[OwnPropertyKeys]] methods are free to specify a particular order.

How would I suggest that in the [[OwnPropertyKeys]] internal method, the order in which the properties are added matters.

Not sure what you mean. Suggest to whom? One way to show someone that that order matters is to point to the definition of Reflect.ownKeys.

Otherwise, the specification would write that the properties can be added to the list in any convenient way.

Yes, something like that.


And by the way:

If the implementation does not follow [[OwnPropertyKeys]], then why is it defined by the specification?

To indirectly specify constraints on some of the behavior that the implementation must exhibit.

That is, still [[OwnPropertyKeys]] imposes constraints, and what are these constraints in this case?

That depends on what "this case" is. If you're talking about any object, then the constraints are only those imposed by 6.1.7.3. But if you're talking about a specific kind of standard-defined object, then the constraints are those imposed by the relevant definition of [[OwnPropertyKeys]].

A rather confusing situation regarding [[OwnPropertyKeys]] has developed

It's not clear to me what you're confused about.

@dSalieri
Copy link
Author

dSalieri commented Jan 2, 2020

@jmdyck Well, it became clearer.
That is, the invariants from 6.1.7.3 for [[OwnPropertyKeys]] show general constrains for all types of objects. A specific description of the [[OwnPropertyKeys]] algorithm for some types of objects is a specialization, that is, these algorithms can set additional constrains in addition to 6.1.7.3, but which do not contradict invariants. In addition, you said in your first message that there is no order for exotic objects

6.1.7.3 doesn't require that [[OwnPropertyKeys]] return property keys in a particular order. Most kinds of object do specify a particular order, but Proxy objects don't, and non-standard exotics aren't required to.

Well, let's say so in String Exotic Objects, Integer-Indexed Exotic Objects, Module Namespace Exotic Objects, there is an order for obtaining properties. But as for Proxy, yes there is no order, The user sets the proxy object when it returns the object with indexed keys (that is, the user of the object can pre-construct the list of returned properties in the order he needs) And the algorithm will later return the list of values ​​in that order in which the user formed in the ownKeys method. Is not it?

I didn’t really understand the part about: ... and non-standard exotics aren't required to - what was meant by this? Above, I showed that most of the exotic that has an overridden algorithm [[OwnPropertyKeys]] has the specified order of listing properties. So what kind of exotics did you mean that have no specified property enumeration?
I dare to assume that the standard exotic is the exotic specified in the specification, and not the standard one that is not in the specification and it is invented by a third-party developer. You probably meant it. If so then there are no more questions :)

@jmdyck
Copy link
Collaborator

jmdyck commented Jan 4, 2020

But as for Proxy, yes there is no order, [...] the [OwnPropertyKeys] algorithm will later return the list of values in that order in which the user formed in the ownKeys method.

Right.

I didn't really understand the part about: ... and non-standard exotics aren't required to - what was meant by this? [...] So what kind of exotics did you mean that have no specified property enumeration? I dare to assume that the standard exotic is the exotic specified in the specification,

Right, I'm using "standard" as a synonym for "defined in the ES spec". So non-standard exotics are those not defined in the ES spec. The definition of such an exotic might guarantee a particular order for the result of [[OwnPropertyKeys]], but it isn't required to -- the spec only requires that it satisfy the invariants of 6.1.7.3.

@dSalieri
Copy link
Author

dSalieri commented Jan 5, 2020

@jmdyck Well, now everything is clear. Thank you for your efforts.

@ljharb ljharb closed this as completed Jan 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants