[react-dom] Enforce small gap between completed navigation and default Transition indicator (#33354)

This commit is contained in:
Sebastian "Sebbie" Silbermann 2025-05-28 19:46:12 +02:00 committed by GitHub
parent b07717d857
commit 5717f1933f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 45 additions and 2 deletions

View File

@ -12,6 +12,7 @@ import Button from './Button.js';
import Form from './Form.js';
import {Dynamic} from './Dynamic.js';
import {Client} from './Client.js';
import {Navigate} from './Navigate.js';
import {Note} from './cjs/Note.js';
@ -89,6 +90,7 @@ export default async function App({prerender}) {
<Note />
<Foo>{dedupedChild}</Foo>
<Bar>{Promise.resolve([dedupedChild])}</Bar>
<Navigate />
</Container>
</body>
</html>

View File

@ -0,0 +1,40 @@
'use client';
import * as React from 'react';
import Container from './Container.js';
export function Navigate() {
/** Repro for https://issues.chromium.org/u/1/issues/419746417 */
function provokeChromeCrash() {
React.startTransition(async () => {
console.log('Default transition triggered');
await new Promise(resolve => {
setTimeout(
() => {
history.pushState(
{},
'',
`?chrome-crash-419746417=${performance.now()}`
);
},
// This needs to happen before React's default transition indicator
// is displayed but after it's scheduled.
100 + -50
);
setTimeout(() => {
console.log('Default transition completed');
resolve();
}, 1000);
});
});
}
return (
<Container>
<h2>Navigation fixture</h2>
<button onClick={provokeChromeCrash}>Provoke Chrome Crash (fixed)</button>
</Container>
);
}

View File

@ -38,7 +38,8 @@ export function defaultOnDefaultTransitionIndicator(): void | (() => void) {
if (!isCancelled) {
// Some other navigation completed but we should still be running.
// Start another fake one to keep the loading indicator going.
startFakeNavigation();
// There needs to be an async gap to work around https://issues.chromium.org/u/1/issues/419746417.
setTimeout(startFakeNavigation, 20);
}
}
@ -70,7 +71,7 @@ export function defaultOnDefaultTransitionIndicator(): void | (() => void) {
}
}
// Delay the start a bit in case this is a fast navigation.
// Delay the start a bit in case this is a fast Transition.
setTimeout(startFakeNavigation, 100);
return function () {