-
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
[View Transition] Event on old Document to set transition state #9702
Comments
We also have things like Are these events correct in their time? If not, is there a specific time during the document lifecycle where this event has to be dispatched? |
Yeah, when you described the conditions in the OP, I think |
We likely don't do it for cross-origin navs, since it will delay the navigation but can make an exception if its a same-origin nav with a transition? |
For non-prerendering cases, it is guaranteed. New documents don't start executing script until https://html.spec.whatwg.org/#scripts-may-run-for-the-newly-created-document |
For same origin navs it does. |
Great! Documenting a point @noamr made in our offline discussion, whatever event authors use will be followed by a frame, so that the names they setup influence what's captured. And it would be odd to render a frame after One model I'm gravitating towards is:
|
How does this model work with prerendering? I know combining prerendering and MPA view transitions is a goal we all share :) |
For sure! I'm not seeing which aspect is ambiguous with respect to pre-rendering. Mind clarifying the question you had in mind? |
Well, I guess I'm not 100% clear on the model, but I was scared by the question about whether Does that mess up the model here in any way? Your description in #9702 (comment) seems to be entirely about the preceding page, so maybe it's fine? But I wanted to double-check. |
There is no inherent reason to perform this before the new document can run any script, but we didn't want to make this invoke an implicit type of prerendering (having two "live" pages without explicitly using speculationrules). It's OK if those events run after scripts have run in the prerender case |
+1, I now see my statement was confusing. Clarifying the model to make sure I got it right:
|
Going back to this, I think the event should not be specific to view transitions, but rather a counterpart to
I see 3 options here:
All of the above shouldn't fire for prerender, only for a regular navigation redirect/commit. I'm currently slightly leaning towards 2 but if we can find a way to make (3) not break things I'm open. |
I actually prefer (1) without making it VT-specific. It could be a counterpart to the The con with (2) is that it doesn't cover the other use-case for this event: "The user can continue interacting with the page before we have a server response." Imagine that the transition depends on scrolling which changes which elements are onscreen. Without an event which fires right before browser capture, authors need to run a scroll handler to keep the DOM in "capture ready" state until snapshot or navigation cancellation. I also don't think there is work the browser can "prepare early". Other than changing layerization decisions based on (3) is interesting but could run into assumptions that |
pagehide isn't fired on tab switching. pagehide is like the better version of unload event. |
Thanks for clarifying @smaug----. Do you have thoughts on the other point: "rendering a frame after pagehide"? Would that mismatch developer expectations of how pagehide behaves today? |
We discussed with @petervanderbeken, and if possible would prefer reusing pagehide. It is after all not that different from (2) in case there are no redirects. The extra rendering is a new thing anyhow. If the old page is rather static, it might currently not trigger any paints while the new page is loading. |
We need the update the rendering loop to run for snapshots. That's because if the author changes which elements have a And while we can suppress callbacks that run as a part of update-the-rendering, it doesn't help make the script interaction any simpler. Script can trigger anything with a setTimeout instead. But I see your point that we should probably disallow triggering a new navigation once we've begun capturing the old Document for a transition. Is there already a way to place the Document in this state? I'm guessing we similarly don't want script to do this in the
The challenge here is that we'll need to add an async step between firing the pagehide event and marking the page hidden. So we can produce one last frame to snapshot before the page is marked hidden. In the current spec marking the Document hidden is synchronous after That's why we intentionally added this async step earlier here, before the unload algorithm is triggered. Since there's already an async task to run step 11, it was easier to add a new async step for rendering and capturing the last frame at the beginning. And we can introduce a new event at this spot for the author to configure state that affects the captured frame. |
Why would there be async step between firing pagehide and marking page hidden. We can have a rendering step there if we want. (I'm not saying we should do that, but just that we can, if we want) |
Because update-the-rendering steps run on a new task (generally driven by platform vsync notifications). So we'd need to go back to the event loop after firing pagehide, wait for the next update-the-rendering loop and then continue with the unload steps starting with marking the Document hidden. Are you suggesting synchronously triggering update-the-rendering after dispatching |
I'm just saying that it would be possible, if we want that. |
Its way too complicated to support in Chromium. We have a pull model where the compositor pulls an update from Blink while this will require Blink pushing a frame to the compositor which is a fundamental change. So I would prefer keeping the capture step async. |
Summarizing internal discussion: Thus perhaps a |
At which point would pagewillhide fire? |
When we get the final response for the new document, it will fire, delay hiding/unloading and render one more frame if there is a view transition. If there is no vt it will fire right before pagehide. Note that this event should include the URL of the target page in case it's same-origin. In general this event probably only makes sense for same-origin navigations, as in cross-origin navigations you can't delay the commit and you don't have a Perhaps |
beforeunload timing is quite different. That happens when you're about to start loading the next page. This new event would fire when the new page is about to be shown to the user. So perhaps better to not use name beforepagehide. I'm still trying to figure out the timing of the new event from implementation point of view. In Gecko we'd need to do one extra parent process -> content process -> parent process round trip for this, I think. And I guess check whether window.stop() is called or new navigations started or history.go() used... hmm, couldn't sites misuse the event? |
How about
Sounds right.
Yes, that's why I'm thinking to fire it for same-origin navigations only, or even fire it only when you have a pending cross-document view transition. |
I want to make progress on this. My main contemplation is where this should be a document event like The way it's going to work:
So thinking @smaug---- @domenic thoughts? |
I think I've followed all the recent discussion, and it sounds reasonable to me. But I'm still a bit stuck back on the questions of where the event is located and how often it fires. The latest proposal from @khushalsagar in #9702 (comment) has it fire on every navigation, right? Or only on cross-document navigations? Or are we still planning only same-origin cross-document navigations, like we were back in #9702 (comment) ? |
I think we can fire it for every cross-document navigation. If there is no view transition opt-in in css it would be fired right before pagehide, and if it's a cross-origin navigation you wouldn't get the post-cross-origin-redirect url. |
I've completed a first revision of the PR, I think it explains it: #10002
|
(I think this was discussed somewhere, but I can't find where) How does this all work in background tabs. The to be unloaded page might be first visibilityHidden when pageconceal would fire and then becomes visible right before pagehide. Or the to be unload might be hidden for a longer time, but new page is visible etc. |
I'm actually leaning towards aligning this event with
|
So I'm seeing the following options here, I'd like us to resolve on promptly.
|
Hmm, all three of those seem pretty nice to me. I think I'd be happy with any of them as good scopes for the event to fire, but the naming gets a bit tricky with (2) and (3) because of how it overlaps with the existing concept of "committed" in the navigation API. Right now, "committed" is exposed through the return values of Given this, assuming the idea for (2) or (3) would still be only for cross-document navigations, then I think we need to include that fact in the name. And, since the API today treats "committed" as "after the URL has already changed", I don't think "committed" should be used to mean "right before the URL is about to be changed". We should either say something like "before commit", or introduce a new term like "finalized" or something. So, some possible names for (2) and (3) might be:
Other notes for (3):
Overall, (1) is probably the simplest. But you all know better what kind of code people will be writing in this handler, which could steer toward (2) or (3). |
Ok, then SGTM. Just one minor correction in the comment above: "An event that fires for each cross-document navigation...".
This will be the case if the navigation is cross-origin. Do we need to hide this if the final URL is same-origin but there are cross-origin redirects? |
We don't need to hide it in that case. We currently don't hide anything based on cross-origin redirects, except for timing. |
Agreed, and fixed the comment. So proposing to move forward with way the current PR is going (fire for every cross-document navigation, either right before pagehide or at a special task if there is a view-transition). |
Some more naming alternative, as seems like other people raised that |
Other options which we discarded:
|
Sorry for going back and forth, but @khushalsagar raised a good point that we can't expose |
I'm still ok with option (1) in terms of the API shape. The fact that In terms of which navigations the event fires for, the use-case we have (with VT) is limited to cross-document same-origin navigations. Including any more navigations will be from the perspective of future proofing because we won't be able to change this, should use-cases come up, without compat risk. With the above in mind, firing it for all cross-document navigations but hiding both the destination entry and navigation type seems like a good path for now. I expect it will be feasible to expose a bit (like |
Added Agenda+ to make sure we have concensus about where we landed with this & picking a final name before merging. |
Sorry I missed this comment, |
Hmm, I think it’s the exact opposite here … swapping is an action between two things (here: two pages) and can apply to either of those two. By using “swap” as the name you can’t really tell if it targets the swapped from (outgoing) or swapped to (incoming) one. With IUC the order for all |
This refers to the old page "being swapped", which you can't say about the new page. The same way a page is "being hidden", "being clicked" or "being revealed" - those are all passive terms, which in the context of the verb swap relates only to the "old" member of the swapped things. The problem with conceal is that it implies gradual hiding, while it might be fired when you don't have a chance to do anything in the last frame.
This is not the order of events. |
But you are swapping one thing for the other – the action requires two participants. From the name itself it’s not clear which of the two participants you mean. By having the antonym of
Difference is that these actions only require 1 participant. You can’t be confused about which participant you mean.
Same thing can be said about reveal? e.g. “revealing curtain”.
Got it (to say I already had the correct order in my notes somewhere 🤦♂️) |
Yes, but I think the confusion here is trying to create symmetry. While |
Thanks for clarifying things here, @noamr. My expectation that these events were symmetric in nature put me on the wrong track here. |
See also w3c/csswg-drafts#9819. The pageswap event is specified here to work as follows: * It's sent whenever a document navigates away, to a different document, but not when unloaded for other reasons, such as closing the browser types or unloading an ancestor. * It includes a NavigationActivation object for same-origin navigations. * If the navigation might trigger a cross-document view-transition (this is determined when snapshotting the source document, by reading the CSS), pageswap is fired and then unloading is deferred until the old state is captured for the view transition. Otherwise, if the view transition is skipped, unloading happens immediately. Closes #9702.
Cross document VT needs an event on the old Document so authors can set up
view-transition-name
s based on where the user is navigating to. Thenavigate
event seems like the perfect choice but it has the following issues:Authors could work around this by tracking these updates themselves, like a scroll listener but better if we can give them an event right before the frame which is captured.
@noamr @vmpstr @domenic
The text was updated successfully, but these errors were encountered: