-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Navigation API: deferred commit #10919
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
base: main
Are you sure you want to change the base?
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 so much for working on this!!!
This is missing the behavior of auto-committing when all finished promises fulfill. See https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/navigation_api/navigate_event.cc;l=338;drc=3b5e9130048e66ce39338d34f99751d0a2346e9c for the counterpart Chromium code.
Fixed |
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.
LGTM with nits. So exciting!!
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 think, but am not sure, that delayed commit is broken for traverses. So marking as "request changes" until we figure that out.
The intention is to allow delaying traverses whenever the event is cancelable (which, for traverses, means same-document traverses of top-level traversables with some anti-abuse protection from history-action activation).
However, from what I can tell, the proposed spec is broken in this regard:
- They allow delaying traverses at all times. That is, there is nothing that gives an error when attempting to set
commit: "after-transition"
when the event is non-cancelable. - The "inner navigate event firing algorithm" will return false if you call
navigateEvent.intercept()
on a traverse, due to falling back to the final step 37. - This causes "check if unloading is canceled" to prevent the unloading, and thus the traversal to never happen.
- Later, when the developer calls
commit()
, nothing happens.
In Chromium, I'm not sure if it's working or not. The flow is similar to the spec, except calling commit()
ends up performing the URL and history update steps, because of this line.
We have tests for this. https://wpt.live/navigation-api/commit-behavior/after-transition-traverse.html in particular. It passes, in Chromium, but note that it's failing to test the actual position of navigation.currentEntry
in the entry index. It only tests the URL (via location.hash
). So it might be doing a push (or replace?) navigation instead of a traverse.
Or, it's possible that Chromium's RunURLAndHistoryUpdateSteps()
is doing a sort of traverse. Note that it does take a destination_item
.
This is related to #10621, which claims that Chromium is also using the RunURLAndHistoryUpdateSteps()
to do observable work for the reload case, despite the spec omitting them.
If Chromium is behaving correctly, then the right path to fixing both this issue and #10621 might be adding something to "commit" which handles the reload and traverse cases. It seems like it would be some subset of "apply the history step".
Sorry this got complicated :(
Spec-wise, does this mean more than failing when trying to set |
Yes. In particular, per my bulleted list above, in the success case currently no traversal ever happens. It should happen. |
Hmm but if |
The case I'm concerned about is a traversal with event.intercept({
commit: 'after-transition',
handler() { return delay(1000); }
}) In this case, step 32 will do nothing, because event's commit behavior is "after-transition". Step 36 will not execute, since event's interception state is "intercepted". Step 37 will return false, so we cancel the traversal (in https://html.spec.whatwg.org/#preventing-navigation:fire-a-traverse-navigate-event). Step 32.4.success should eventually re-do the traverse somehow, but it does not. A similarly broken case is a traversal with event.intercept({
commit: 'after-transition',
async handler() {
await delay(1000);
event.commit();
}
}) This will similarly do nothing in step 32 and step 37, and return false in step 37, sot he traverse is canceled. Then, calling |
I tried a few things in chrome, it seems like:
So I think the right thing to do here is to run the URL and history update steps 7-11, and also call popstate. So I think the plan of action would be to have a few steps equivalent to those fragment-navigation steps, extracting the history length/index from the appropriate places. WDYT @domenic ? |
That seems like the right start, but it's not sufficient, right? We also need to update the "browser process" view, and update any iframes. For push/replace, the URL and history update steps 12-13 do that, but the algorithm finalize a same-document navigation strongly assumes that it's only being used for push/replace, so it isn't quite usable for our purposes. I think this time we need to do at least some of "apply the history step", in order to:
However, it's a bit tricky since we've already done "apply the history step" once; we just bailed out in step 5 ("check if unloading is canceled") after firing the traverse I think we can just do this by adding an extra boolean argument to "apply the history step" which causes it to skip step 5? |
Isn't the existing |
Yes, it totally is; not sure how I missed that. |
When intercepting a navigation with the navigate event, the popstate event should only be fired if the navigation was a traversal (necessarily same-document, since cross-document traversals aren't interceptible), or if the navigation was a same-document fragment navigation (i.e., not originating from the history API or the navigation API). Follows whatwg/html#10989 and whatwg/html#10919 Fixed: 397377454, 398276373 Change-Id: I0f953cd10a8f2a80af0822e9ceafaaac965758fe
When intercepting a navigation with the navigate event, the popstate event should only be fired if the navigation was a traversal (necessarily same-document, since cross-document traversals aren't interceptible), or if the navigation was a same-document fragment navigation (i.e., not originating from the history API or the navigation API). Follows whatwg/html#10989 and whatwg/html#10919 Fixed: 397377454, 398276373 Change-Id: I0f953cd10a8f2a80af0822e9ceafaaac965758fe Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6299859 Reviewed-by: Domenic Denicola <domenic@chromium.org> Commit-Queue: Nate Chapin <japhet@chromium.org> Cr-Commit-Position: refs/heads/main@{#1425920}
When intercepting a navigation with the navigate event, the popstate event should only be fired if the navigation was a traversal (necessarily same-document, since cross-document traversals aren't interceptible), or if the navigation was a same-document fragment navigation (i.e., not originating from the history API or the navigation API). Follows whatwg/html#10989 and whatwg/html#10919 Fixed: 397377454, 398276373 Change-Id: I0f953cd10a8f2a80af0822e9ceafaaac965758fe Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6299859 Reviewed-by: Domenic Denicola <domenic@chromium.org> Commit-Queue: Nate Chapin <japhet@chromium.org> Cr-Commit-Position: refs/heads/main@{#1425920}
When intercepting a navigation with the navigate event, the popstate event should only be fired if the navigation was a traversal (necessarily same-document, since cross-document traversals aren't interceptible), or if the navigation was a same-document fragment navigation (i.e., not originating from the history API or the navigation API). Follows whatwg/html#10989 and whatwg/html#10919 Fixed: 397377454, 398276373 Change-Id: I0f953cd10a8f2a80af0822e9ceafaaac965758fe Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6299859 Reviewed-by: Domenic Denicola <domenic@chromium.org> Commit-Queue: Nate Chapin <japhet@chromium.org> Cr-Commit-Position: refs/heads/main@{#1425920}
…te firing behavior, a=testonly Automatic update from web-platform-tests Navigation API: match the spec on popstate firing behavior When intercepting a navigation with the navigate event, the popstate event should only be fired if the navigation was a traversal (necessarily same-document, since cross-document traversals aren't interceptible), or if the navigation was a same-document fragment navigation (i.e., not originating from the history API or the navigation API). Follows whatwg/html#10989 and whatwg/html#10919 Fixed: 397377454, 398276373 Change-Id: I0f953cd10a8f2a80af0822e9ceafaaac965758fe Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6299859 Reviewed-by: Domenic Denicola <domenic@chromium.org> Commit-Queue: Nate Chapin <japhet@chromium.org> Cr-Commit-Position: refs/heads/main@{#1425920} -- wpt-commits: 1786c24ad28fd6d2ed33b5f1d9946f2fa75bd648 wpt-pr: 51003
…te firing behavior, a=testonly Automatic update from web-platform-tests Navigation API: match the spec on popstate firing behavior When intercepting a navigation with the navigate event, the popstate event should only be fired if the navigation was a traversal (necessarily same-document, since cross-document traversals aren't interceptible), or if the navigation was a same-document fragment navigation (i.e., not originating from the history API or the navigation API). Follows whatwg/html#10989 and whatwg/html#10919 Fixed: 397377454, 398276373 Change-Id: I0f953cd10a8f2a80af0822e9ceafaaac965758fe Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6299859 Reviewed-by: Domenic Denicola <domenic@chromium.org> Commit-Queue: Nate Chapin <japhet@chromium.org> Cr-Commit-Position: refs/heads/main@{#1425920} -- wpt-commits: 1786c24ad28fd6d2ed33b5f1d9946f2fa75bd648 wpt-pr: 51003
…te firing behavior, a=testonly Automatic update from web-platform-tests Navigation API: match the spec on popstate firing behavior When intercepting a navigation with the navigate event, the popstate event should only be fired if the navigation was a traversal (necessarily same-document, since cross-document traversals aren't interceptible), or if the navigation was a same-document fragment navigation (i.e., not originating from the history API or the navigation API). Follows whatwg/html#10989 and whatwg/html#10919 Fixed: 397377454, 398276373 Change-Id: I0f953cd10a8f2a80af0822e9ceafaaac965758fe Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6299859 Reviewed-by: Domenic Denicola <domenic@chromium.org> Commit-Queue: Nate Chapin <japhet@chromium.org> Cr-Commit-Position: refs/heads/main@{#1425920} -- wpt-commits: 1786c24ad28fd6d2ed33b5f1d9946f2fa75bd648 wpt-pr: 51003
source
Outdated
<li> | ||
<p><span>Prepare to run script</span> given <var>navigation</var>'s <span>relevant settings | ||
object</span>.</p> | ||
<p>Let <var>cancel</var> be the following steps given <var>reason</var>:</p> |
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.
Cancel gets called when a handler rejects and only communicates cancellation through the navigateerror event. Should it also signal abort on event’s abort controller?
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.
Fixed
This is looking very, very close. I pushed some final nits, mostly around aesthetic preferences like putting precommit before commit and committed before finished. Final things:
|
Hmm it doesn't? It throws an
Fixed. It was a conflict with #11203. |
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.
Hmm it doesn't? It throws an
InvalidStateError
in step 4.
I was confused. I forgot that NavigationHistoryBehavior
was different than NavigationType
.
There's a lot of duplication in the steps for "Let cancel be the following steps given reason:" and "To abort the ongoing navigation given a Navigation navigation and an optional DOMException error:". Is there a way to consolidate those? In my implementation of the fake, after creating the abort reason in "To abort the ongoing navigation given a Navigation...", I call the cancel steps on the |
Spec updates are in whatwg/html#10919 For the most part, the updates revolve around the deferred commit handling (with precommitHandler). Updates to redirect allow more options. A committed promise now exists on the transition since commits can be delayed. Tests were made zoneless for easier debugging and timeouts were reduced.
Spec updates are in whatwg/html#10919 For the most part, the updates revolve around the deferred commit handling (with precommitHandler). Updates to redirect allow more options. A committed promise now exists on the transition since commits can be delayed. Tests were made zoneless for easier debugging and timeouts were reduced.
Spec updates are in whatwg/html#10919 For the most part, the updates revolve around the deferred commit handling (with precommitHandler). Updates to redirect allow more options. A committed promise now exists on the transition since commits can be delayed. Tests were made zoneless for easier debugging and timeouts were reduced.
Spec updates are in whatwg/html#10919 For the most part, the updates revolve around the deferred commit handling (with precommitHandler). Updates to redirect allow more options. A committed promise now exists on the transition since commits can be delayed. Tests were made zoneless for easier debugging and timeouts were reduced.
Spec updates are in whatwg/html#10919 For the most part, the updates revolve around the deferred commit handling (with precommitHandler). Updates to redirect allow more options. A committed promise now exists on the transition since commits can be delayed. Tests were made zoneless for easier debugging and timeouts were reduced. PR Close #62017
Spec updates are in whatwg/html#10919 For the most part, the updates revolve around the deferred commit handling (with precommitHandler). Updates to redirect allow more options. A committed promise now exists on the transition since commits can be delayed. Tests were made zoneless for easier debugging and timeouts were reduced. PR Close #62017
This adds
navigateEvent.prototype.intercept({precommitHandler})
.Instead of always "committing" the navigation immediately, the navigation only commits after all its
precommitHandler
promises are resolved.In addition, a
precommitHandler
receives aNavigationPrecommitController
as an argument, and can use it to changethe URL of the ongoing navigation before it is commited, using the
redirect(newURL)
function.See https://github.com/WICG/navigation-api/blob/main/README.md#precommit-handlers
(See WHATWG Working Mode: Changes for more details.)
/browsing-the-web.html ( diff )
/index.html ( diff )
/nav-history-apis.html ( diff )