From bdea5464ffff485855dc935823479af3d9827058 Mon Sep 17 00:00:00 2001 From: Sebastian Sebbie Silbermann Date: Wed, 15 Apr 2026 19:14:15 +0200 Subject: [PATCH 1/2] [Fiber][enableYieldingBeforePassive] Enable in experimental builds again --- packages/shared/ReactFeatureFlags.js | 2 +- packages/shared/forks/ReactFeatureFlags.www-dynamic.js | 1 + packages/shared/forks/ReactFeatureFlags.www.js | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index c1d12dfcfbd4..5276aa184576 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -67,7 +67,7 @@ export const enableLegacyFBSupport: boolean = false; // Yield to the browser event loop and not just the scheduler event loop before passive effects. // Fix gated tests that fail with this flag enabled before turning it back on. -export const enableYieldingBeforePassive: boolean = false; +export const enableYieldingBeforePassive: boolean = __EXPERIMENTAL__; // Experiment to intentionally yield less to block high framerate animations. export const enableThrottledScheduling: boolean = false; diff --git a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js index e19b3314c19b..c3fb3736dcee 100644 --- a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js +++ b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js @@ -37,6 +37,7 @@ export const enableFragmentRefsScrollIntoView: boolean = __VARIANT__; export const enableFragmentRefsTextNodes: boolean = __VARIANT__; export const enableInternalInstanceMap: boolean = __VARIANT__; export const enableParallelTransitions: boolean = __VARIANT__; +export const enableYieldingBeforePassive: boolean = __VARIANT__; export const enableEffectEventMutationPhase: boolean = __VARIANT__; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index 740a3f3f845b..23f26ebfe0f3 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -35,6 +35,7 @@ export const { enableFragmentRefsTextNodes, enableInternalInstanceMap, enableParallelTransitions, + enableYieldingBeforePassive, } = dynamicFeatureFlags; // On WWW, __EXPERIMENTAL__ is used for a new modern build. @@ -53,8 +54,6 @@ export const enableMoveBefore: boolean = false; export const disableInputAttributeSyncing: boolean = false; export const enableLegacyFBSupport: boolean = true; -export const enableYieldingBeforePassive: boolean = false; - export const enableThrottledScheduling: boolean = false; export const enableComponentPerformanceTrack: boolean = true; From 4afd2b0c488a4f0fdd3f0c7bbc6029f67e317cfd Mon Sep 17 00:00:00 2001 From: Sebastian Sebbie Silbermann Date: Wed, 15 Apr 2026 19:50:54 +0200 Subject: [PATCH 2/2] Update tests that weren't updated during "Don't try to hydrate a hidden Offscreen tree" --- ...DOMServerPartialHydration-test.internal.js | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js index 3e6af7bc9744..104e8fb57827 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js @@ -3713,11 +3713,19 @@ describe('ReactDOMServerPartialHydration', () => { return Hidden; } + function VisibleChild() { + Scheduler.log('VisibleChild'); + React.useEffect(() => { + Scheduler.log('VisibleChild Effect'); + }); + return Visible; + } + function App() { Scheduler.log('App'); return ( <> - Visible + @@ -3733,7 +3741,7 @@ describe('ReactDOMServerPartialHydration', () => { // During server rendering, the Child component should not be evaluated, // because it's inside a hidden tree. const finalHTML = ReactDOMServer.renderToString(); - assertLog(['App']); + assertLog(['App', 'VisibleChild']); const container = document.createElement('div'); container.innerHTML = finalHTML; @@ -3753,17 +3761,18 @@ describe('ReactDOMServerPartialHydration', () => { // The visible span successfully hydrates ReactDOMClient.hydrateRoot(container, ); - await waitForPaint(['App']); + await waitForPaint(['App', 'VisibleChild']); expect(visibleRef.current).toBe(visibleSpan); + // Subsequently, the hidden child is prerendered on the client + // along with hydrating the Suspense boundary outside the Activity. if (gate(flags => flags.enableYieldingBeforePassive)) { - // Passive effects. - await waitForPaint([]); + await waitForPaint(['VisibleChild Effect']); + await waitForPaint(['HiddenChild']); + } else { + await waitForPaint(['VisibleChild Effect', 'HiddenChild']); } - // Subsequently, the hidden child is prerendered on the client - // along with hydrating the Suspense boundary outside the Activity. - await waitForPaint(['HiddenChild']); expect(container).toMatchInlineSnapshot(`
@@ -3779,6 +3788,11 @@ describe('ReactDOMServerPartialHydration', () => {
`); + if (gate(flags => flags.enableYieldingBeforePassive)) { + // passive effects + await waitForPaint([]); + } + // Next the child inside the Activity is hydrated. await waitForPaint(['HiddenChild']);