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

Traversing the joint session history and forward/back idempotence #73

Closed
domenic opened this issue Mar 15, 2021 · 4 comments · Fixed by #120
Closed

Traversing the joint session history and forward/back idempotence #73

domenic opened this issue Mar 15, 2021 · 4 comments · Fixed by #120
Labels
foundational Foundational open questions whose resolution may change the model dramatically

Comments

@domenic
Copy link
Collaborator

domenic commented Mar 15, 2021

https://github.com/WICG/app-history#correspondence-with-the-joint-session-history states

The rule here for choosing C, instead of B, is that it moves the joint session history the fewest number of steps necessary to make I1 active.

This has the unfortunate consequence that calling appHistory.back(); appHistory.forward(); does not always take the user back to the view they started on.

For example, given the scenario there:

  • We start on D/O3/I2.
  • The outer frame calls appHistory.back(). This takes us back to B/O2/I1.
  • The outer frame calls appHistory.forward(). Per the fewest-steps rule, this takes us forward to C/O3/I1.

That is, the inner frame is on https://example.com/inner-start, instead of https://example.com/inner-end.

This is not great. Can we avoid it, by choosing a different rule, such as always go to the most-forward joint session history entry? Maybe. Or maybe whichever rule we pick, it will have consequences like this in one scenario or another (e.g. maybe it'd make the reverse, appHistory.forward(); appHistory.back(), non-idempotent). To be investigated.

@domenic domenic added the foundational Foundational open questions whose resolution may change the model dramatically label Mar 15, 2021
@domenic
Copy link
Collaborator Author

domenic commented Mar 16, 2021

Here is an example where going to the most-forward breaks idempotence:

A. https://example.com/o1
   ┗ https://example.com/i1
B. https://example.com/o1
   ┗ https://example.com/i2
C. https://example.com/o2 (via pushState)
   ┗ https://example.com/i2
D. https://example.com/o2
   ┗ https://example.com/i3
  • We start at C/O2/I2
  • appHistory.back() in the outer frame goes to the most-forward joint session history entry which changes the outer frame. That's B/O1/I2.
  • appHistory.forward() in the outer frame goes to the most-forward joint session history entry which changes the outer frame. That's D/O2/I3.

@domenic
Copy link
Collaborator Author

domenic commented Mar 16, 2021

And I think this is generally just not solvable. Consider a joint session history where the top frame stays on the same app history entry for, say, 11 joint session history entries, B through L. If the current joint session history entry is D, then appHistory.back() has to take us to JSH entry A: that's the only JSHE in the backward direction that changes the top frame.

But then what possible rule could take us forward to joint session history entry D when we call appHistory.forward()? There's no way to pick it out of all the other possibilities (B through L) without some sort of memory. And maintaining such a memory is not worth it, because to make it general and handle cases like back/back/forward/forward or similar becomes ridiculous.

So I think the conclusion has to be that back/forward traversal is a bit fraught with app history in terms of the impact it'll have on your iframes.

@tbondwilkinson
Copy link
Contributor

I think this is acceptable, as long as most people know that the proper API, if you want reasonable navigational behavior, is to use the key-based API to navigate to a specific entry.

@jakearchibald
Copy link

Another case to consider:

Screenshot 2021-04-20 at 11 31 31

And iframe-2 is sandboxed.

  1. Start on step 3.
  2. iframe-2 calls appHistory.back(), moving to step 2.
  3. iframe-2 calls appHistory.forward().

In the "fewest steps" model we move back to step 3. Things get more confusing in the "most steps" model, which suggests going to step 4. Options:

  • Traversal fails. Going to step 4 means navigating iframe-1, and iframe-2 is not allowed to navigate iframe-1.
  • Traversal proceeds to step 4, but iframe-1 gets out of sync of the history timeline.
  • Traversal proceeds to step 3, since that's the "most steps" that navigate things that iframe-2 is allowed to navigate.

The "fewest steps" model seems a lot simpler in this case.

You still get the situation where iframe-2 cannot call appHistory.back() if we're on step 4 of the timeline. I don't see a way around that other than whatwg/html#6501.

domenic added a commit that referenced this issue May 27, 2021
domenic added a commit that referenced this issue Jun 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
foundational Foundational open questions whose resolution may change the model dramatically
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants