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

Navigating to same url - replace or add? #6682

Open
jakearchibald opened this issue May 13, 2021 · 6 comments
Open

Navigating to same url - replace or add? #6682

jakearchibald opened this issue May 13, 2021 · 6 comments
Labels
interop Implementations are not interoperable with each other topic: history topic: navigation

Comments

@jakearchibald
Copy link
Contributor

jakearchibald commented May 13, 2021

It seems like:

  • Navigating from /a to /a is treated like a reload (replaces history entry).
  • Navigating from /a to /a#foo is a hash change navigation.
  • Navigating from /a#foo to /a is a full navigation to /a (adds a history entry).

However, replace should only happen if the initiator is same origin to the current document.

There's a non-interoperable case when it comes to redirects:

  1. Navigate to https://redirect-session-history.glitch.me/a - entry1
  2. Navigate to /b which redirects to /a

In this case Chrome & Safari will add a new history entry, whereas Firefox will replace the existing entry (or treat it like a reload, I'm not sure which).

I don't think it matters too much which behaviour we go with, but the Chrome/Safari behaviour seems simpler.

Firefox will switch to 'replace' even if part of the redirect is cross-origin, but I don't think that really matters in this case, because I'm pretty sure it's already observable.

@annevk @domenic @smaug---- this is the case we 'discovered' in the meeting.

Tests

Test:

  1. Navigate to https://redirect-session-history.glitch.me/a - entry1
  2. Navigate to /a

Chrome, Firefox, Safari: replace doc in entry1

Test:

  1. Navigate to https://redirect-session-history.glitch.me/a - entry1
  2. Navigate to /a#foo - entry2
  3. Navigate to /a

Chrome, Firefox: 3 history entries, first two share a document

Safari: 3 buggy history entries. Going back results in no doc change. Going back again results in no doc change, but also no hash change.

Test:

  1. Navigate to https://redirect-session-history.glitch.me/a - entry1
  2. Navigate to /b which redirects to /a

Chrome, Safari: 2 history entries, separate documents
Firefox: replace doc in entry1

Firefox will still replace if the redirect goes via another origin.

Test:

  1. Navigate to https://redirect-session-history.glitch.me/a - entry1
  2. Navigate to /a#foo - entry2
  3. Navigate to /b which redirects to /a

Chrome, Firefox: 3 history entries, first two share a document

Safari: 3 buggy history entries. Going back results in no doc change. Going back again results in no doc change, but also no hash change.

Test:

  1. Nav to https://redirect-session-history.glitch.me/a - entry1
  2. Nav to /a#foo - entry2
  3. Nav to /b which redirects to /a#hello

Chrome, Firefox: Entry 3 has a different doc to entries 1 and 2 (which continue to share a doc).

Safari: 3 buggy history entries. Going back results in no doc change. Going back again results in no doc change, but also no hash change.

@domenic
Copy link
Member

domenic commented May 13, 2021

Navigating from /a to /a is treated like a reload (replaces history entry).

Like a reload, or like a same-URL replace? As visible to service workers :).

Navigating from /a#foo to /a is a full navigation to /a (adds a history entry).

This was fairly surprising to me!

I don't think it matters too much which behaviour we go with, but the Chrome/Safari behaviour seems simpler.

Strongly agreed; it'd be good to settle on whether we're doing a replace or push synchronously, and not change our mind later.

@domenic domenic added topic: navigation interop Implementations are not interoperable with each other labels May 13, 2021
@domenic
Copy link
Member

domenic commented Jun 15, 2021

So @rakina found an added wrinkle here, which is the connection to #6213. In Chrome currently, whether you do replace/default depends on comparing the original request URL to the document's current URL (*). Whereas, whether you carry over the history.state value depends on comparing the final response URL to the document's current URL (*).

This means that if you do location.href = location.href, and the server has updated to redirect to a new location, Chrome currently does a "replace" navigation, but loses history.state. Maybe that's OK?

More broadly, we have three options:

  1. Compare with the final response URL to determine both replace and state carry-over
  2. Compare with the initial request URL to determine both replace and state carry-over
  3. Compare with the initial request URL to determine replace, and compare with the final response URL to determine state carry-over

The current spec discussion seems to be leaning toward (3), but maybe there's value in the consistency of (1) or (2).

(*) "document's current URL": this is further complicated by #6649. I'm not sure which of the two possible "current URLs" Chrome uses in document.open() situations, but it shouldn't matter too much for the purpose of this question.

@jakearchibald
Copy link
Contributor Author

1. Compare with the final response URL to determine both replace and state carry-over

This gets complicated if we need to change behaviour if any of the redirects are cross-origin. I'm not sure if the cross-origin thing is a real issue, but it feels bad.

2. Compare with the initial request URL to determine both replace and state carry-over

You'd still need to check the response URL to avoid transferring history state cross-origin… so would you change replace/append here too for consistency?

3. Compare with the initial request URL to determine replace, and compare with the final response URL to determine state carry-over

As in, what Chrome currently does? I think this is what I prefer. The asymmetry is weird, but history.state is broken-weird anyway.

@jakearchibald
Copy link
Contributor Author

A detail that I haven't seen covered elsewhere, but thankfully it's consistent between browsers: POST navigations to the same URL append a new entry, rather than replace the current entry.

GET form submissions appear to behave like link clicks (phew). Navigations from a page that loaded via a form submission don't appear to behave in any special way (also phew).

Tests

Test:

  1. https://iframe-session-history.glitch.me/
  2. Click "Navigate via POST to /" - add or replace?
  3. Click "Navigate via POST to /" - add or replace?

Chrome, Firefox, Safari: add add

Test:

  1. https://iframe-session-history.glitch.me/?
  2. Click "Navigate via form GET to /" - add or replace?

Chrome, Firefox, Safari: Replace

Test:

  1. https://iframe-session-history.glitch.me/
  2. Click "Navigate via POST"
  3. Click "Navigate to current URL" - add or replace?

Chrome, Firefox, Safari: Replace

@jakearchibald
Copy link
Contributor Author

(in fact, form submission is kinda forgotten about in 'navigate'. Eg, the spec says that a form submission to a URL that only differs by fragment shouldn't submit at all, and should just perform an in-page navigation)

@jakearchibald
Copy link
Contributor Author

Test:

  1. https://iframe-session-history.glitch.me/
  2. iframe-1: Navigate to about:blank
  3. Navigate to '#foo' - add or replace?

Chrome, Firefox: add
Safari: replace

I'm going to stick with what Chrome & Firefox do here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interop Implementations are not interoperable with each other topic: history topic: navigation
Development

No branches or pull requests

2 participants