-
Notifications
You must be signed in to change notification settings - Fork 46
Normative: Parent completion ordering DFS invariant extension #159
Conversation
Yulia: I think you've got more of the proposal paged in than me right now, so I'd appreciate it if you could take a look. Let me know if you prefer I try. |
c340f9c
to
a153448
Compare
I've rebased this to the PR bug fix in #159, and also separated out the cycle gathering on failure, as cycle errors are allowed to be sparse in the current module algorithm, it doesn't seem such an issue to ensure consistency by just relying on cycle root. Instead we can follow this up in a separate PR if necessary. Thanks for feedback so far. The diff should now be a little simpler as well. |
@jorendorff I've included your suggestions - brings the diff down nicely as well. |
d13b0fc
to
46b80ab
Compare
46b80ab
to
da8b55b
Compare
I've rebased this PR to the latest merge of the cycle root fix, should be much simpler to review. Further feedback welcome, I do think this is an important normative change to make. If it needs to go explicitly through the meeting that would be understandable. Further feedback would be very welcome to understand implementer interest. |
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 have unfortunately run out of time this week to fully do this review. If it can wait a week, I will do it then -- or someone can also take over. I made a few small comments.
I want to still make sure that we don't inadvertently end up changing this behaviour: https://github.com/web-platform-tests/wpt/pull/26771/files
Guy says it shouldn't be an issue but I would like to take more time to verify the implications.
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.
Still thinking about the order of evaluation. A couple of comments so far
e46dd47
to
b277c05
Compare
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.
Bar the issue I found with three tests, that appears to be a js shell issue (will verify that today), this looks fine and is probably a worthwhile change. It doesn't appear to have web platform implications so we are good there. I am setting this to approved.
Sketch implementation here: https://phabricator.services.mozilla.com/D105437
@syg it would be great to get your review on this PR if you're able to take a look. |
Just to reiterate, this PR is only to ensure that all sync subgraphs that depend on async modules execute in the original ordering, and it doesn't affect any of the other execution properties of this proposal that have already been agreed. |
Co-authored-by: Ms2ger <Ms2ger@gmail.com>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
I started implementing this and ran into a concern. I'd like the postorder position to be scoped to each top-level call to Edit: Perhaps I was premature on this concern: since the modules are always guaranteed to execute in global ascending order of when they first had their [[AsyncEvaluating]] set to true, in the global serial number approach, once a module finishes evaluating such that its ordinal is >= the global serial number, the global can be reset to 0. I think that works, but probably should draw up a proof to be safe. |
Another issue: what actually resolves the top level Promise? |
@syg nicely spotted - yes with the flattening of the previous recursive algorithm we need to now explicitly call the capabilities on the sync module parents of async modules. Further to your suggestion, the fix can possibly actually resolve capabilities on all sync parents of async modules, as they could all have eg a later dynamic import expression that attached to those modules specifically. For this reason I've added the capability resolution within the main exec loop to all sync modules. I also went ahead and moved the main "top level parent" capability resolution to the top, this is to ensure that the current module promise will resolve before the sync parent promises. Since all capability resolutions, I believe, wiill go into the task queue, the resolution functions can't be called synchronously. So having the capability resolution at the top should not break the sync invariant between the parent executions by calling a resolve function earlier than the parent executions. Please verify that I'm correct in that assumption though, and just let me know if further clarification would help. Will also await on @codehag when she gets back for review before merging so we have time here too. |
Great point! |
If someone wants to an executable implementation in V8 to check things with, here's the CL: https://chromium-review.googlesource.com/c/v8/v8/+/2757901 |
If somebody knows how to build a node.js version from that, you could run https://github.com/evanw/tla-fuzzer with that change and check the result. That's how I found the original case. |
…subgraphs This CL implements tc39/proposal-top-level-await#159, which reached consensus at the March 2021 TC39. The high-level intent is for parent modules that depend on async modules to remember the DFS post-order such that when their async dependency finishes, they execute in that original post-order. This aligns the ordering between completely sync module graphs and async module graphs. Bug: v8:11557 Change-Id: I5bd8f38f040115c255ca1ce8253b9686fdb4af03 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2757901 Commit-Queue: Shu-yu Guo <syg@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Adam Klein <adamk@chromium.org> Cr-Commit-Position: refs/heads/master@{#73551}
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.
Looks good to me.
I tested the patch in Node.js and can confirm it fixes #158 and has the correct timings for dynamic import registrations with the latest commit as well. |
This behavior was introduced after the Top-Level Await proposal reached stage 3: tc39/proposal-top-level-await#159
This behavior was introduced after the Top-Level Await proposal reached stage 3: tc39/proposal-top-level-await#159
This behavior was introduced after the Top-Level Await proposal reached stage 3: tc39/proposal-top-level-await#159
We've merged a test for the new semantics to Test262: tc39/test262#2989 |
This extension provides an approach to the case brought up in #158 where parent completion orderings entirely differing from the normal post-order execution might be seen as surprising behaviour.
This approach uses a new global execution ordering on async execution.
The async fulfillment is then split out into two separate phases: a first phase to gather the list of parent modules that are synchronously ready for execution at async fulfillment time of a dependent, and a second phase to execute this list in global execution-sorted order based on this ordering.
Async rejections are handled as previously.
This change only affects execution timings of deferred async executions, imposing this new post-ordering sort on them. If we consider module graphs where every module depends individually on a single module using top-level await, using the same well-defined post-order execution ordering on all sync parent subgraph execution completions that run together seems like a sensible adjustment to me to ensure predictable behaviour.
Fixes #158.
Further review / feedback very welcome. // cc @Ms2ger @littledan @MylesBorins @robpalme @sokra