Force layout before startViewTransition (#32699)

This works around this Safari bug.
https://bugs.webkit.org/show_bug.cgi?id=290146

This unfortunate because it may cause additional layouts if there's more
updates to the tree coming by manual mutation before it gets painted
naturally. However, we might end up wanting to read layout early anyway.

This affects the fixture because we clone the `<link>` from the `<head>`
which is itself another bug. However, it should be possible to have
`<link>` tags inserted into the new tree so this is still relevant.
This commit is contained in:
Sebastian Markbåge 2025-03-21 10:05:31 -04:00 committed by GitHub
parent ac799e569d
commit e1e740717b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1669,6 +1669,12 @@ function customizeViewTransitionError(
return error;
}
/** @noinline */
function forceLayout(ownerDocument: Document) {
// This function exists to trick minifiers to not remove this unused member expression.
return (ownerDocument.documentElement: any).clientHeight;
}
export function startViewTransition(
rootContainer: Container,
transitionTypes: null | TransitionTypes,
@ -1698,8 +1704,7 @@ export function startViewTransition(
mutationCallback();
if (previousFontLoadingStatus === 'loaded') {
// Force layout calculation to trigger font loading.
// eslint-disable-next-line ft-flow/no-unused-expressions
(ownerDocument.documentElement: any).clientHeight;
forceLayout(ownerDocument);
if (
// $FlowFixMe[prop-missing]
ownerDocument.fonts.status === 'loading'
@ -1898,6 +1903,10 @@ export function startGestureTransition(
? (rootContainer: any)
: rootContainer.ownerDocument;
try {
// Force layout before we start the Transition. This works around a bug in Safari
// if one of the clones end up being a stylesheet that isn't loaded or uncached.
// https://bugs.webkit.org/show_bug.cgi?id=290146
forceLayout(ownerDocument);
// $FlowFixMe[prop-missing]
const transition = ownerDocument.startViewTransition({
update: mutationCallback,