-
Notifications
You must be signed in to change notification settings - Fork 26
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
navigate events on traversal #114
Comments
@jakearchibald @natechapin ping for thoughts on this plan |
Sorry for the slow reply!
Do you feel the same about a link-click which targets some other frame? I guess it would be inconsistent otherwise.
Agreed, although I think it comes before the Unfortunately the Link click:
History traversal:
I couldn't figure out a single place for |
Hmm. Currently the readme says that those are only censored if the navigation is cross-document and initiated from a cross origin-domain window. I remember thinking through that now in some detail in #75. Especially the same-document case is important to fire navigate on. So probably we should align on that for this case too.
Good point.
Yep, in general we often have this issue with shared infrastructure betweeen traversal and navigation. I'm happy to duplicate for now and abstract later. |
In trying to spec
appHistory.back()
, I realized that there's a whole world of complexity around traversals that we seem to have forgotten, which is that history traversals can navigate multiple windows. Should all of them getnavigate
events? Which of them should be cancelable? Which should havecanRespond
true?See also #78 and #32 which touch on some related questions, but no issue so far has tackled the multi-window issue I believe. There is currently a spec ("Modify the traverse the history by a delta algorithm" in https://wicg.github.io/app-history/#navigate-algorithm-patches) but it doesn't appear to acknowledge the possibility of multiple windows being traversed, so I need to rewrite it.
Recapping some guiding principles from previous discussions:
If you get traversed and can either cancel it or
respondWith()
to replace it with a same-document nav, then you should get anavigate
event. Conversely, if you can do neither of those things, then don't fire thenavigate
event, since it's not actionable.Same-document traversals always have
canRespond
true, and thus always firenavigate
events. A SPA needs to be able to react to back-navigations just as much as it does to link clicks or other such things.Cross-document traversals must have
canRespond
false because converting those into same-document ones is just confusing.Developers are interested in canceling user-initiated traversals (Cancelling UI initiated navigations (back/forward) #32) although currently we've specced this as disallowed.
I'll add my own additional principle, which hasn't been previously discussed: you shouldn't be able to cancel a traversal (using
event.preventDefault()
) unless "you" initiated it. I.e. if you're getting navigated because some other frame calledhistory.back()
, then the event should be uncancelable.I think this leads to a model like the following:
Let currentWindow be the Window of the History or AppHistory object, or of the top-level browsing context being displayed while the user is pressing the back button.
Go to the browser process to figure out what windows a given traversal will affect, and whether the traversal will be same- or cross-document.
For each such Window w:
Let canRespond be true if it's same-document, false otherwise.
Let cancelable be true if this navigation is programatically-initiated and w = currentWindow; false otherwise. (We may also set it to true in some user-initiated cases per Cancelling UI initiated navigations (back/forward) #32 in the future.)
If canRespond is true or cancelable is true:
Queue a task on w to fire the navigate event with cancelable and canRespond set appropriately.
If the event is canceled, then bail out of the whole traversal (like when the user allows a beforeunload prompt to cancel the traversal), and reject the return value of
appHistory.back()
or whatever with an "AbortError" DOMException.If they called
respondWith()
, then...Track the promise given to respondWith. Maybe all the promises should be
Promise.all()
ed together to feed back into the return value ofappHistory.back()
? Or maybe only the one where w = currentWindow? I lean toward the latter.I don't think we need to do anything else? The history traversal was already underway, and it was already going to be same-document. So we just let it go through?
Ideally we'd have this be done in a single centralized algorithm, probably as patches to Jake's "apply the history step". In this case we'd probably do these... after the beforeunload prompt portion of "apply the history step"?? (Step 13 currently.)
Then
history.back()
andappHistory.back()
and user-initiated back button pressing all go through this centralized algorithm.How does this sound, @jakearchibald @natechapin? I know in the short term in Chromium our implementation is firing the
navigate
event entirely within the renderer process, only forappHistory.back()
, but as the vision for the ultimate architecture, does this make sense?The text was updated successfully, but these errors were encountered: