-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
What should we do about location.replace? #6891
Comments
Some ideas to resolve this: Option 1: The current history entry of the navigable associated with the This takes the thing all browsers do in test 4, what Firefox does in test 3, and what Chrome does in test 2 (except for the state copy), and applies it as a general rule. If the replacement is same-document, then the document is reused and iframe history state is retained. I like this because it actually performs a replacement, rather than creating additional history entries, and it doesn't 'steal' history entries from other iframes etc etc. However, since this is pretty different to how browsers behave for test 1 (and browser behave pretty similar to each other in that case), it might not be feasible. Option 2: A new history entry is created, and is given the current step. The new entry has null state. If the navigable associated with the Entries become unreachable if they're part of a nested navigable, but if you tried to traverse to their step, a parent would navigate to a different document before they can traverse. For example: Top level entries: step 1 If the current step is 3, and the top level calls Top level entries: step 1 The step 3 and 4 items in the iframe are no longer reachable, as the parent would navigate to Top level entries: step 1 This takes the thing all browsers do in test 1, what Safari does in test 2, and what Chrome and Safari do in test 3, and applies it as a general rule. This results in cases where a single back click can navigate multiple things at once. That already happens when going back multiple steps, so it doesn't seem like a bad thing. Option 3: Do option 1 for nested navigables, and option 2 for top-level This results in the least change for browsers, but does it make sense branching behaviour like this? Whatever we pick, I'd like to apply the same rule to |
I've never had to deal with history and iframes on the same page, but option 1 makes the most sense to me for what should happen if I replaced the current entry. I'd be interested in knowing how many sites this affects, and how many of those sites know that this affects them. I doubt that's something we can really determine, but I imagine it's not a large number. |
I was initially thinking that cross-origin might play a role here and that's why distinguishing between top-level and nested could be reasonable, but after considering it more I'm not sure it would as they could use other history APIs too. Option 1 seems great indeed. I wonder what @smaug---- thinks. |
I'd like to note that Chrome's behavior in "Test 2: Top level replace with same document" is actually quite new. The previous behavior is the same as for "Test 1: Top level replace with new document" (see comment), where Chrome "replaces" only the current step instead of all the shared entries. I think similarly Test 4's behavior is also new, since we didn't have "shared frame entries" before this change. So Chrome's behavior was kinda consistent: replace the entry in the current step only (I think this is the same as option 2?). Since this behavior is consistent with other browsers for test 1 & test 2, I'm afraid following option 1 will break some sites that do location.replace() -> history.navigation (then again I don't know if this is common) That's for There's also the same-URL and |
Yeah, I've got a similar worry, but also no data.
I feel ready to give up on |
@rakina made me aware of a couple of quirks in
location.replace
, so I went digging, and it's a bit of a mess.Test 1: Top level replace with new document
This timeline is created by navigating to a page with an iframe, and navigating the iframe twice. The current step is 3.
What happens if
location.replace('//new-doc')
is called at the top level?Chrome:
Chrome effectively creates a new history entry for the top level navigable with the same step as the current step (3). The previous step 3 entry (in the iframe) is removed.
Firefox:
Firefox behaves the same as Chrome, but it's a bit buggy with bfcache. If you click back, the iframe is still on
//c
, but it's just out of sync with browser history. If you click back again, the iframe will navigate to//a
, then if you click forward it'll go to//b
😄Safari:
Like Chrome, except it loses
history.state
in the top level when iframes are navigated. So:Test 2: Top level replace with same document
Same initial timeline as before:
But this time
location.replace('#foo')
is called, making it a same-document replacement.Chrome:
Chrome replaces the currently active history entry in the top level navigable. State is retained, and the document is copied over. This seems totally inconsistent with test 1.
Firefox:
Firefox creates a new history entry for the top level navigable, and gives it the same step as the current step (3). The iframe entry that also had a step of 3 is removed. However, the iframe isn't navigated, so it still shows
//c
. If you go back, it still shows//c
, if you go back again it shows//a
, then if you go forward it shows//b
.Firefox's behaviour is consistent with test 1, but the resulting behaviour shows that it doesn't make sense as a general rule. To make it work, you'd have to navigate the iframe back to
//b
when the top level callslocation.replace
, and that just seems like a different type of weird.Safari:
Like Firefox, Safari creates a new history entry for the top level navigable, and gives it the same step as the current step (3). However, it doesn't remove the iframe entry that also has step 3. This means if you press back, both the iframe and top level navigate at the same time.
This actually feels consistent with test 1, as long as you can get over the fact that nothing was actually replaced.
Test 3: Other iframe replace with new document
This timeline is created by navigating to a page with two iframes, and navigating the first iframe twice. The current step is 3.
What happens if
location.replace('//2-b')
is called in the second iframe?Chrome & Safari:
Chrome and Safari create a new history entry for the iframe's navigable, and gives it the same step as the current step (3). It doesn't remove/replace any entry. This means if you press back, both iframes navigate at the same time.
Firefox:
Firefox replaces the current history entry of the iframe.
Test 4: Other iframe replace with same document
Same initial timeline as before:
What happens if
location.replace('#foo')
is called in the second iframe?Chrome, Firefox, Safari:
They replace the current history entry of the iframe.
It seems like behaviours here are inconsistent (even within a single browser), or obviously wrong in some cases. I'll try to come up with a 'solution' in a reply.
The text was updated successfully, but these errors were encountered: