-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Comments
#1791 is relevant. |
|
@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. |
Note that I wrote that in a paragraph about the behavior of
My first point is that the spec doesn't always specify that order.
You're reading the spec too much like an implementation. When the spec says:
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. |
Alright.
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:
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. 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]]? |
Okay, I'll try to spell it out in more detail, but I'm not sure it's going to be clearer.
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]]). |
@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?
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).
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.
Wait what is about:
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.
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? |
That largely depends on what you mean by "follow the steps". If you mean that the implementation needs to have a procedure corresponding to
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.
Again, it depends on what you mean by "follow the steps".
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).
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 |
"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.
Why we don't need to do that?
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.
Although this is a little implicit, but it’s understandable, the main thing is to correspond the specification requirement - the rest does not matter.
Ok, now let's recall our internal object method [[OwnPropertyKeys]].
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? |
Because:
(Or rather, the implementation only needs to exhibit some behaviour that could be observed of the model.)
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."
That might make some things easier, but it would probably be an inefficient implementation.
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.
Yes, it defines what should happen in the model.
To indirectly specify constraints on some of the behavior that the implementation must exhibit.
Can you think of an example where the spec gives the steps of an operation when it would be easier to "impose restrictions"?
This was covered in issue #1628. I'm not going to rehash it here. |
@jmdyck Hmm, what exactly is meant by:
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]])?
I can’t remember this in the specification. By constraint, I certainly meant invariants. And they are applied to the internal methods of objects.
Exactly, if I'm not mistaken, invariants are created to cover objects not defined by the specification. Is not it? |
Maybe. I'm not sure what you have in mind when you say "the essence of the algorithm".
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. |
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?
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. |
Possibly. It's hard for me to tell.
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.
And do have the answer to that question now?
Something like that, yes. But it sounds like you're still thinking in terms of "implementing each spec algorithm".
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.
[[OwnPropertyKeys]] is fairly easy, because the list of keys it returns is completely observable (just not via EnumerateObjectProperties). |
@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 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
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.
This can be seen by various methods:
But this conflicts with the statement:
How would I suggest that in the
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?
That is, still As for
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.
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. |
Yes, but that particular order is required only for ordinary objects.
Yes, because it's completely observable.
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.
The two statements don't conflict. 6.1.7.3 doesn't impose a constraint on the order of keys returned by any
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.
Yes, something like that.
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
It's not clear to me what you're confused about. |
@jmdyck Well, it became clearer.
Well, let's say so in I didn’t really understand the part about: |
Right.
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 |
@jmdyck Well, now everything is clear. Thank you for your efforts. |
My question sounds as: in chapter 13.7.5.15 EnumerateObjectProperties we have the following steps of the algorithm:
If we read further, we will see the following entry:
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
The text was updated successfully, but these errors were encountered: