Skip to content
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

Navigation API: deferred commit #10919

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open

Navigation API: deferred commit #10919

wants to merge 6 commits into from

Conversation

noamr
Copy link
Contributor

@noamr noamr commented Jan 16, 2025

This adds navigateEvent.prototype.intercept({commit: "after-transition"}), as well as NavigateEvent.prototype.commit().

Instead of always "committing" the navigation immediately, we refer to this interception option. If it's the default ("immediate"), the existing behavior is invoked.
The new "after-transition" behavior keeps the navigation un-committed, until NavigateEvent.prototype.commit() is called.

This follows roughly the same semantics of scroll.

See https://github.com/WICG/navigation-api/blob/main/README.md#deferred-commit

  • At least two implementers are interested (and none opposed):
  • Tests are written and can be reviewed and commented upon at:
  • Implementation bugs are filed:
    • Chromium:
    • Gecko: …
    • WebKit: …
    • Deno (only for timers, structured clone, base64 utils, channel messaging, module resolution, web workers, and web storage): …
    • Node.js (only for timers, structured clone, base64 utils, channel messaging, and module resolution): …
  • Corresponding HTML AAM & ARIA in HTML issues & PRs: N/A, no HTML elements involved in this
  • MDN issue is filed: Will be done as part of Chromium beta launch
  • The top of this comment includes a clear commit message to use.

(See WHATWG Working Mode: Changes for more details.)


/nav-history-apis.html ( diff )

@noamr noamr requested a review from domenic January 16, 2025 12:31
Copy link
Member

@domenic domenic left a 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.

source Outdated Show resolved Hide resolved
source Outdated Show resolved Hide resolved
source Outdated Show resolved Hide resolved
source Outdated Show resolved Hide resolved
source Outdated Show resolved Hide resolved
source Show resolved Hide resolved
source Show resolved Hide resolved
noamr added 4 commits January 21, 2025 11:52
This adds `navigateEvent.prototype.intercept({commit: "after-transition"})`,
as well as `NavigateEvent.prototype.commit()`.

Instead of always "committing" the navigation immediately,
we refer to this interception option. If it's the default
("immediate"), the existing behavior is invoked.
The new "after-transition" behavior keeps the navigation
un-committed, until `NavigateEvent.prototype.commit()` is
called.

This follows roughly the same semantics of `scroll`.

See https://github.com/WICG/navigation-api/blob/main/README.md#deferred-commit
@noamr
Copy link
Contributor Author

noamr commented Jan 21, 2025

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

Copy link
Member

@domenic domenic left a 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!!

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
Copy link
Member

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.

<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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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

@domenic domenic added addition/proposal New features or enhancements topic: navigation labels Jan 24, 2025
Copy link
Member

@domenic domenic left a 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 :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements topic: navigation
Development

Successfully merging this pull request may close these issues.

2 participants