-
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!!
source
Outdated
data-x="dom-Navigation-currentEntry">navigation.currentEntry</code> property, and update the | ||
browser UI, such as the location bar.</p> | ||
|
||
<p>The <code data-x="dom-NavigationInterceptOptions-commit">commit</code> option can be set to |
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.
Nit: merge this with the previous paragraph.
source
Outdated
<code>DOMException</code> if called on a <code>NavigateEvent</code> that has already been | ||
committed due to the default "<code | ||
data-x="dom-NavigationCommitBehavior-immediate">immediate</code>" commit behavior, if called | ||
more than once for the same navigation, or if called synchronously, during event dispatch, or |
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.
more than once for the same navigation, or if called synchronously, during event dispatch, or | |
more than once for the same navigation, if called synchronously during event dispatch, or if called |
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 <[email protected]> Commit-Queue: Nate Chapin <[email protected]> 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 <[email protected]> Commit-Queue: Nate Chapin <[email protected]> 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 <[email protected]> Commit-Queue: Nate Chapin <[email protected]> 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 <[email protected]> Commit-Queue: Nate Chapin <[email protected]> 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 <[email protected]> Commit-Queue: Nate Chapin <[email protected]> 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 <[email protected]> Commit-Queue: Nate Chapin <[email protected]> Cr-Commit-Position: refs/heads/main@{#1425920} -- wpt-commits: 1786c24ad28fd6d2ed33b5f1d9946f2fa75bd648 wpt-pr: 51003
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.
This still seems like it's missing a lot of the hard parts discussed in #10919 (review) and following comments:
- No throwing for precommitHandlers on non-cancelable navigations
- For traverses, doesn't properly cancel and then restart the traverse upon commit.
Oops, I had these in a previous revision and forgot to port them when I shuffled things around. I think it's good now. |
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.
Awesome, the hard stuff looks good now! Just found some smaller things, both editorial and some stuff detected by comparing with the implementation.
This adapter adds an integration with the Navigation API, allowing SPA Router navigations to be displayed more fully in the browser UI. With this, site visitors will be able to see that a page is loading via the loading spinner in the tab. They will also have access to cancel the navigation with the browser UI via the "stop" button or by pressing the escape key (only relevant for slower connections). Note that this implementation relies on features currently only available in Chrome Canary with the "Experimental Web Platform features" flag enabled. * https://github.com/WICG/navigation-api?tab=readme-ov-file#precommit-handlers * whatwg/html#10919
This adapter adds an integration with the Navigation API, allowing SPA Router navigations to be displayed more fully in the browser UI. With this, site visitors will be able to see that a page is loading via the loading spinner in the tab. They will also have access to cancel the navigation with the browser UI via the "stop" button or by pressing the escape key (only relevant for slower connections). Note that this implementation relies on features currently only available in Chrome Canary with the "Experimental Web Platform features" flag enabled. * https://github.com/WICG/navigation-api?tab=readme-ov-file#precommit-handlers * whatwg/html#10919
This adapter adds an integration with the Navigation API, allowing SPA Router navigations to be displayed more fully in the browser UI. With this, site visitors will be able to see that a page is loading via the loading spinner in the tab. They will also have access to cancel the navigation with the browser UI via the "stop" button or by pressing the escape key (only relevant for slower connections). Note that this implementation relies on features currently only available in Chrome Canary with the "Experimental Web Platform features" flag enabled. * https://github.com/WICG/navigation-api?tab=readme-ov-file#precommit-handlers * whatwg/html#10919
This adapter adds an integration with the Navigation API, allowing SPA Router navigations to be displayed more fully in the browser UI. With this, site visitors will be able to see that a page is loading via the loading spinner in the tab. They will also have access to cancel the navigation with the browser UI via the "stop" button or by pressing the escape key (only relevant for slower connections). Note that this implementation relies on features currently only available in Chrome Canary with the "Experimental Web Platform features" flag enabled. * https://github.com/WICG/navigation-api?tab=readme-ov-file#precommit-handlers * whatwg/html#10919
This adapter adds an integration with the Navigation API, allowing SPA Router navigations to be displayed more fully in the browser UI. With this, site visitors will be able to see that a page is loading via the loading spinner in the tab. They will also have access to cancel the navigation with the browser UI via the "stop" button or by pressing the escape key (only relevant for slower connections). Note that this implementation relies on features currently only available in Chrome Canary with the "Experimental Web Platform features" flag enabled. * https://github.com/WICG/navigation-api?tab=readme-ov-file#precommit-handlers * whatwg/html#10919
This adapter adds an integration with the Navigation API, allowing SPA Router navigations to be displayed more fully in the browser UI. With this, site visitors will be able to see that a page is loading via the loading spinner in the tab. They will also have access to cancel the navigation with the browser UI via the "stop" button or by pressing the escape key (only relevant for slower connections). Note that this implementation relies on features currently only available in Chrome Canary with the "Experimental Web Platform features" flag enabled. * https://github.com/WICG/navigation-api?tab=readme-ov-file#precommit-handlers * whatwg/html#10919
This adapter adds an integration with the Navigation API, allowing SPA Router navigations to be displayed more fully in the browser UI. With this, site visitors will be able to see that a page is loading via the loading spinner in the tab. They will also have access to cancel the navigation with the browser UI via the "stop" button or by pressing the escape key (only relevant for slower connections). Note that this implementation relies on features currently only available in Chrome Canary with the "Experimental Web Platform features" flag enabled. * https://github.com/WICG/navigation-api?tab=readme-ov-file#precommit-handlers * whatwg/html#10919
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.
This LGTM!
I guess we have a few more feature requests we might want to incorporate:
NavigationTransition
should have acommitted
promise WICG/navigation-api#285NavigationPrecommitController.redirect
should accept at leaststate
and potentially alsoinfo
WICG/navigation-api#286
My guess is that in the interests of getting standards-positions etc., we should bundle them into a single HTML Standard PR.
One way to do this would be to take this PR in its current state as good, and then work on other PRs targeting the noamr:nav-commit
branch which I could review separately, and then merge in to this branch. That could help stop this PR from getting too large and unwieldy.
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 )