-
Notifications
You must be signed in to change notification settings - Fork 101
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
Precisely specify iteration details. Fixes #396 #451
base: main
Are you sure you want to change the base?
Conversation
…djust wording of the invocation as suggested.
Do note that this is not the same semantics as ES Maps use, because deletion is specified differently. Specifically, for an ES Map, deleting leaves a |
Thanks @bakkot, great catch. Can you think of any way to specify those semantics without tombstones, which feel a bit awkward? Like... snapshotting the keys, but then doing a separate exists check before actually executing the steps? |
Offhand nothing else occurs to me, though you might be able to find something in the literature. If you're trying to get exactly ES Map semantics, using the same specification mechanism as ES is probably going to be easiest. Snapshotting is going to be tricky. There's a bunch of weird edge cases: like, suppose you had |
Yeah, indeed, I think capturing the precise semantics without using tombstones would be a huge burden. My inclination is to specify that lists and maps can have holes, but they're automatically skipped over by all spec-author-facing operations; only the list/map iteration internal algo sees them. |
Yeah, that seems fair. So there are several competing issues here:
I think the best path forward here is to push toward aligning Infra maps/sets with JS ones, and try to be sure to have people write web platform tests for modifications-during-iteration for any Infra map/set usage (not just maplike/setlike, but other cases too). But the wrapper operations path is also viable. It would basically defer the question of how to precisely specify Infra map/set iteration until later. |
(For the record I typed up most of the above, went to a meeting, missed @tabatkins's response, then pressed submit.)
Do you mean set/map, or list/map? Changing lists to have holes might have other knock-on effects, e.g. by making list iteration mismatch |
I meant list, but I'm not wedded to that; i'd be okay with lists and sets having different iteration behavior if needed. Regarding Array iteration, note that Arrays already differ from themselves between forEach() and iteration, so who knows what we should be consistent with. |
Fair point. It's probably fine to add holes to lists; I'm happy for you to give it a shot. |
I wonder to what extent we should give advice here to implementations as not all lists will need this complexity. I wonder if we can do similar things to "ASCII string" whereby we essentially assert the thing will have a subset of the total semantics. |
Okay, I won't get back to finishing this PR until at least next week due to vacation, but just gathering some thoughts here:
I think I don't like (3). I'm leaning to (2), but could be convinced on (1) if we think it's better to put the burden of thinking about which type to use on impls rather than spec authors. We'd have guidance either way in Infra, just targeted at different audiences. |
@tabatkins ping on picking this back up! I think I prefer (1) if possible, but I'm OK with (2) if you prefer. |
Hi from Blink-land. I've been trying to review @yuki3's patches making Blink's pair iterators and map/setlike code more spec-conformant and ended up stumbling upon #396 and this PR. It would be great to have more clarity on this; I was wondering if there's been any progress with the patch and the approaches discussed above. |
It's remained on my list of things to wrap up "real soon now". :/ |
Okay, picking this back up now. I've gone with Option 1 from my comment - lists and maps can have holes, which are invisible to all algorithms unless explicitly specified. This is done in a somewhat handwavey style that is hopefully okay, but if we want to be more precise I can add an explicit "with holes" argument to every algo, defaulting to false, and pass that around appropriately. Big thing left is to just decide which of the list iteration behaviors to steal from JS: Array.forEach records the length of the list at the start and stops at that length, even if items were added mid-iteration; Array iteration recalculates the length on each iteration to check if it should stop, so items added mid-iteration will be visited as well. JS Maps do the latter behavior in both instances, so I'm currently leaning towards (and the spec text reflects) doing that for lists as well. (And I know that my wrapping isn't correct right now; I hate length-based wrapping so I'm leaving it to be done immediately prior to merging.) |
Added a "sequence iteration" concept, and invoked it explicitly for list and map iteration.
Sequence iteration is defined in the same terms that ES does (see tc39/ecma262#2766 where ES is making itself more consistent in this regard): you maintain an internal index, incrementing it each step, and checking it against the length at each iteration. If the sequence changes size or order while executing its steps, that's fine, the next iteration will just see whatever the i+1th value of the sequence now is.
Happy to invoke this in a different way; what I have just seemed like a short and straightforward way to do so.
Preview | Diff