-
Notifications
You must be signed in to change notification settings - Fork 164
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
Define [[OwnPropertyKeys]] of legacy platform objects #402
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for making this. Overall this looks really solid! Couple of comments and questions below (this is a part of the spec I'm not super familiar with, so please bear with me if some of those are silly).
property creation, [=list|append=] |P| to |keys|. | ||
1. [=list|For each=] |P| of |O|’s own property keys that is a Symbol, in ascending chronological order of | ||
property creation, [=list|append=] |P| to |keys|. | ||
1. Assert: |keys| has no duplicate items. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not used an ordered list instead (as you initially suggested)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Assuming you meant ordered set...) ES uses a plain List, and it would actually be a specification error if there are duplicates, since the named property visibility algorithm should filter out any supported property names that are also own properties on the object (or in its prototype chain).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Assuming you meant ordered set...)
I did. :)
ES uses a plain List, and it would actually be a specification error if there are duplicates, since the named property visibility algorithm should filter out any supported property names that are also own properties on the object (or in its prototype chain).
That makes sense.
the object’s [=supported property indices=] are | ||
enumerated first, in numerical order. | ||
1. If the object [=support named properties|supports named properties=] and doesn't implement an [=interface=] with the | ||
[{{LegacyUnenumerableNamedProperties}}] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The effects of the [{{LegacyUnenumerableNamedProperties}}] extended attribute seem totally gone from the updated algorithm. Is that on purpose?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, LegacyUnenumerableNamedProperties
controls the enumerable
bit in the descriptor but not the existence of the key. See [[GetOwnProperty]]. The original pseudo-algorithm defines the "enumeration order", basically the order of for-in loops, which accounts for both enumerability and key existence.
|keys|. | ||
1. If |O| [=support named properties|supports named properties=], then [=list|for each=] |P| of |O|’s | ||
[=supported property names=] that is visible according to the [=named property visibility algorithm=], | ||
[=list|append=] |P| to |keys|. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these also in ascending chronological order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The order is defined by the specification for the specific interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, right. That's the order in which they're spec'ed. In one of the toJSON-related algorithms we write this as:
If a toJSON operation with a [Default] extended attribute is declared on |I|,
then for each exposed regular attribute |attr| that is an interface member of |I|,
in order:
Maybe just add in order,
before [=list|append=] |P| to |keys|
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"for each" from Infra already defines the order so you don't have to add that kind of thing. (At least, iirc that's the idea.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@annevk, you're right. I'd just like to be a little more explicit in both those cases that enumeration order follows the order in which the attributes are specified in the interface. But we can leave that out for now and fix them up both together later if necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I totally mixed up a bunch of things here. Apologies for muddling the conversation. Please ignore this comment altogether.
index.bs
Outdated
@@ -12014,19 +12014,26 @@ However, for [=legacy platform objects=], | |||
properties on the object must be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be great to add a small blurb here that this is done by the [[OwnPropertyKeys]] method, e.g:
This document does not define a complete property enumeration order
for [=platform objects=] implementing [=interfaces=]
(or for <a href="#es-exception-objects">platform objects representing exceptions</a>).
However, it does for [=legacy platform objects=] by defining the \[[OwnPropertyKeys]] method as follows:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I seem to have forgotten to update that blurb… will do.
First of all, this PR is awesome. Second, I am concerned about the extent to which it matches implementations, especially with regard to ordering. In particular, it's possible implementations don't have a good order except in enumeration cases, if they don't map onto the recent ES spec updates which derive enumeration from own property keys. So, we'll need some good tests of the various permutations here to be sure. |
@domenic how do you want to go about this? Land this, then add the tests, then given the test results, file issues with rendering engines? Or do you want to wait until we have test results before we land this? |
While I did write this PR to match what implementations are doing, I would agree that there are a lot of corner cases, like index prop names that are not array index prop names ([2^32, 2^53)), assigning array index prop names to objects that don't support indexed properties (and vice versa), and symbols. To that end I'd definitely agree that there should be tests.
Can you point out the update you are referring to?
Is there a specific section in WPT for Web IDL compliance or should I look into adding these tests to the section of the tested interface (e.g. |
Ah OK, that's great. I thought it might have been just a translation of the previous enumeration section, in which case there was more cause for concern. But if you have validated this roughly matches browsers, then I would be comfortable merging before in-depth tests. @tobie
https://github.com/w3c/web-platform-tests/tree/master/WebIDL, almost always under ecmascript-binding. As you can see from some tests there, we generally pick representative objects. https://github.com/w3c/web-platform-tests/blob/255d54144a82ce76d8e50a4aa8de284151119f8b/WebIDL/ecmascript-binding/legacy-platform-object.html is probably the file to work on, although I think nobody would mind having a separate file for the OwnPropertyKeys sub-cases as that file is so generically named it could grow without bound. |
I've completed a more comprehensive audit of what browsers currently do. And the results are, well, inconsistently inconsistent. The test is live at https://timothygu.me/webidl-keys-test/, and the files available in https://github.com/TimothyGu/webidl-keys-test. I specifically looked at three interfaces: NamedNodeMap (used for From results from Chrome and Edge both exhibit the original issue I opened #400 for, namely they do not include named properties on an interface annotated with While Chrome and Firefox (and this proposal) consistently put own property symbols at the end for legacy platform objects in the same way as ES operates, Edge puts symbols in the front of all own properties. Not directly related to this proposal, Chrome 60 and Edge follow the current [[Set]] semantics in that for interfaces not supporting indexed properties, it still sets any indexed properties as own properties. However, Chrome 61 and Firefox will throw when trying to do so. Also not directly related to this proposal, Edge has a bug where its As for From the results, I see an even stronger need for standardization around [[OwnPropertyKeys]]. Other than |
The comments in the Hence The bit about whether an index should be treated as a name for Storage seems to be #366 which has stalled for some reason. :( I agree compat around that stuff is poor. |
@bzbarsky Thanks! I've updated the comments in the file, and it does make things clearer. To summarize, for
Do you have any comments regarding this PR itself though? |
So we avoid doing duplicate work, heads-up that I've started refactoring legacy-platform-object.html and turning @TimothyGu's tests into wpt in a dedicated branch. |
The behavior for symbols is actually not defined right now; the spec's text for them makes no sense and isn't implementable. In particular, [[Set]] in the spec ends up calling OrdinarySet for symbols, which eventually lands in the webidl-defined [[DefineOwnProperty]], which is broken in the face of symbols; see #175. Once that issue is resolved, I'll update Firefox to whatever that resolution is.
If we're still talking about Storage, then in the case of Firefox the order is rather random. In particular, it's just iterating the keys of a non-ordered hashtable, so the precise order will depend on how the keys collided, where they landed in the hashtable, etc. As in, we just don't implement the "chronological order" bit from the spec at all. As far as the test goes, it might also be worth checking that while
Yes, I do. It's totally awesome. ;) I was worried about duplication in the list, but the fix we did for named props not shadowing existing own props even on [OverridBuiltins] interfaces makes everything work out great. Thank you for doing this! |
Ah, thanks for clarifying then. Glad I could help! ❤️ |
Fixes #400.
Preview | Diff