diff --git a/packages/react-cache/src/__tests__/ReactCacheOld-test.internal.js b/packages/react-cache/src/__tests__/ReactCacheOld-test.internal.js index 0c75abf06b710..c9247f6a882d6 100644 --- a/packages/react-cache/src/__tests__/ReactCacheOld-test.internal.js +++ b/packages/react-cache/src/__tests__/ReactCacheOld-test.internal.js @@ -126,8 +126,8 @@ describe('ReactCache', () => { await waitForAll([ 'Suspend! [Hi]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Hi]'] : []), + // pre-warming + 'Suspend! [Hi]', ]); jest.advanceTimersByTime(100); @@ -150,8 +150,8 @@ describe('ReactCache', () => { await waitForAll([ 'Suspend! [Hi]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Hi]'] : []), + // pre-warming + 'Suspend! [Hi]', ]); textResourceShouldFail = true; @@ -195,8 +195,8 @@ describe('ReactCache', () => { await waitForAll([ 'App', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['App'] : []), + // pre-warming + 'App', ]); assertConsoleErrorDev([ 'Invalid key type. Expected a string, number, symbol, or ' + @@ -204,27 +204,24 @@ describe('ReactCache', () => { 'To use non-primitive values as keys, you must pass a hash ' + 'function as the second argument to createResource().\n' + ' in App (at **)', - ...(gate('enableSiblingPrerendering') - ? [ - 'Invalid key type. Expected a string, number, symbol, or ' + - "boolean, but instead received: [ 'Hi', 100 ]\n\n" + - 'To use non-primitive values as keys, you must pass a hash ' + - 'function as the second argument to createResource().\n' + - ' in App (at **)', - ] - : []), + + // pre-warming + 'Invalid key type. Expected a string, number, symbol, or ' + + "boolean, but instead received: [ 'Hi', 100 ]\n\n" + + 'To use non-primitive values as keys, you must pass a hash ' + + 'function as the second argument to createResource().\n' + + ' in App (at **)', ]); } else { await waitForAll([ 'App', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['App'] : []), + // pre-warming + 'App', ]); } }); - // @gate enableSiblingPrerendering it('evicts least recently used values', async () => { ReactCache.unstable_setGlobalCacheLimit(3); @@ -240,15 +237,28 @@ describe('ReactCache', () => { await waitForPaint(['Suspend! [1]', 'Loading...']); jest.advanceTimersByTime(100); assertLog(['Promise resolved [1]']); - await waitForAll([1, 'Suspend! [2]']); + await waitForAll([ + 1, + 'Suspend! [2]', + ...(gate('alwaysThrottleRetries') + ? [] + : [1, 'Suspend! [2]', 'Suspend! [3]']), + ]); jest.advanceTimersByTime(100); - assertLog(['Promise resolved [2]']); - await waitForAll([1, 2, 'Suspend! [3]']); + assertLog([ + 'Promise resolved [2]', + ...(gate('alwaysThrottleRetries') ? [] : ['Promise resolved [3]']), + ]); + await waitForAll([ + 1, + 2, + ...(gate('alwaysThrottleRetries') ? ['Suspend! [3]'] : [3]), + ]); jest.advanceTimersByTime(100); - assertLog(['Promise resolved [3]']); - await waitForAll([1, 2, 3]); + assertLog(gate('alwaysThrottleRetries') ? ['Promise resolved [3]'] : []); + await waitForAll(gate('alwaysThrottleRetries') ? [1, 2, 3] : []); await act(() => jest.advanceTimersByTime(100)); expect(root).toMatchRenderedOutput('123'); @@ -378,8 +388,8 @@ describe('ReactCache', () => { await waitForAll([ 'Suspend! [Hi]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Hi]'] : []), + // pre-warming + 'Suspend! [Hi]', ]); resolveThenable('Hi'); diff --git a/packages/react-devtools-shared/src/__tests__/TimelineProfiler-test.js b/packages/react-devtools-shared/src/__tests__/TimelineProfiler-test.js index e632227ab3a79..d46cac42b703f 100644 --- a/packages/react-devtools-shared/src/__tests__/TimelineProfiler-test.js +++ b/packages/react-devtools-shared/src/__tests__/TimelineProfiler-test.js @@ -15,22 +15,11 @@ import { normalizeCodeLocInfo, } from './utils'; -import {ReactVersion} from '../../../../ReactVersions'; -import semver from 'semver'; - let React = require('react'); let Scheduler; let store; let utils; -// TODO: This is how other DevTools tests access the version but we should find -// a better solution for this -const ReactVersionTestingAgainst = process.env.REACT_VERSION || ReactVersion; -// Disabling this while the flag is off in experimental. Leaving the logic so we can -// restore the behavior when we turn the flag back on. -const enableSiblingPrerendering = - false && semver.gte(ReactVersionTestingAgainst, '19.0.0'); - // This flag is on experimental which disables timeline profiler. const enableComponentPerformanceTrack = React.version.startsWith('19') && React.version.includes('experimental'); @@ -1678,8 +1667,8 @@ describe('Timeline profiler', () => { await waitForAll([ 'suspended', - - ...(enableSiblingPrerendering ? ['suspended'] : []), + // pre-warming + 'suspended', ]); Scheduler.unstable_advanceTime(10); @@ -1691,8 +1680,7 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); // Verify the Suspense event and duration was recorded. - if (enableSiblingPrerendering) { - expect(timelineData.suspenseEvents).toMatchInlineSnapshot(` + expect(timelineData.suspenseEvents).toMatchInlineSnapshot(` [ { "componentName": "Example", @@ -1720,29 +1708,11 @@ describe('Timeline profiler', () => { }, ] `); - } else { - const suspenseEvent = timelineData.suspenseEvents[0]; - expect(suspenseEvent).toMatchInlineSnapshot(` - { - "componentName": "Example", - "depth": 0, - "duration": 10, - "id": "0", - "phase": "mount", - "promiseName": "", - "resolution": "resolved", - "timestamp": 10, - "type": "suspense", - "warning": null, - } - `); - } // There should be two batches of renders: Suspeneded and resolved. expect(timelineData.batchUIDToMeasuresMap.size).toBe(2); - expect(timelineData.componentMeasures).toHaveLength( - enableSiblingPrerendering ? 3 : 2, - ); + // An additional measure with pre-warming + expect(timelineData.componentMeasures).toHaveLength(3); }); it('should mark concurrent render with suspense that rejects', async () => { @@ -1769,11 +1739,7 @@ describe('Timeline profiler', () => { , ); - await waitForAll([ - 'suspended', - - ...(enableSiblingPrerendering ? ['suspended'] : []), - ]); + await waitForAll(['suspended', 'suspended']); Scheduler.unstable_advanceTime(10); rejectFn(); @@ -1784,8 +1750,7 @@ describe('Timeline profiler', () => { const timelineData = stopProfilingAndGetTimelineData(); // Verify the Suspense event and duration was recorded. - if (enableSiblingPrerendering) { - expect(timelineData.suspenseEvents).toMatchInlineSnapshot(` + expect(timelineData.suspenseEvents).toMatchInlineSnapshot(` [ { "componentName": "Example", @@ -1813,30 +1778,11 @@ describe('Timeline profiler', () => { }, ] `); - } else { - expect(timelineData.suspenseEvents).toHaveLength(1); - const suspenseEvent = timelineData.suspenseEvents[0]; - expect(suspenseEvent).toMatchInlineSnapshot(` - { - "componentName": "Example", - "depth": 0, - "duration": 10, - "id": "0", - "phase": "mount", - "promiseName": "", - "resolution": "rejected", - "timestamp": 10, - "type": "suspense", - "warning": null, - } - `); - } // There should be two batches of renders: Suspeneded and resolved. expect(timelineData.batchUIDToMeasuresMap.size).toBe(2); - expect(timelineData.componentMeasures).toHaveLength( - enableSiblingPrerendering ? 3 : 2, - ); + // An additional measure with pre-warming + expect(timelineData.componentMeasures).toHaveLength(3); }); it('should mark cascading class component state updates', async () => { diff --git a/packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.js b/packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.js index 24a9c4308a2f9..c1dc8a33cceba 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.js @@ -751,7 +751,8 @@ describe('ReactDOMFiberAsync', () => { // Because it suspended, it remains on the current path expect(div.textContent).toBe('/path/a'); }); - assertLog(gate('enableSiblingPrerendering') ? ['Suspend! [/path/b]'] : []); + // pre-warming + assertLog(['Suspend! [/path/b]']); await act(async () => { resolvePromise(); diff --git a/packages/react-dom/src/__tests__/ReactDOMForm-test.js b/packages/react-dom/src/__tests__/ReactDOMForm-test.js index f981ed4c38dcf..03b9076b33827 100644 --- a/packages/react-dom/src/__tests__/ReactDOMForm-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMForm-test.js @@ -1437,8 +1437,8 @@ describe('ReactDOMForm', () => { assertLog([ 'Suspend! [Count: 0]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Count: 0]'] : []), + // pre-warming + 'Suspend! [Count: 0]', ]); await act(() => resolveText('Count: 0')); assertLog(['Count: 0']); @@ -1448,8 +1448,8 @@ describe('ReactDOMForm', () => { assertLog([ 'Suspend! [Count: 1]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Count: 1]'] : []), + // pre-warming + 'Suspend! [Count: 1]', ]); expect(container.textContent).toBe('Loading...'); @@ -1482,8 +1482,8 @@ describe('ReactDOMForm', () => { await act(() => root.render()); assertLog([ 'Suspend! [Count: 0]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Count: 0]'] : []), + // pre-warming + 'Suspend! [Count: 0]', ]); await act(() => resolveText('Count: 0')); assertLog(['Count: 0']); @@ -1501,8 +1501,8 @@ describe('ReactDOMForm', () => { ]); assertLog([ 'Suspend! [Count: 1]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Count: 1]'] : []), + // pre-warming + 'Suspend! [Count: 1]', ]); expect(container.textContent).toBe('Count: 0'); }); diff --git a/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js b/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js index fa22142702527..a38eb8f368e6d 100644 --- a/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js @@ -164,8 +164,10 @@ describe('ReactDOMSuspensePlaceholder', () => { 'A', 'Suspend! [B]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [B]', 'C'] : []), + // pre-warming + 'A', + 'Suspend! [B]', + 'C', ]); await act(() => { resolveText('B'); diff --git a/packages/react-dom/src/__tests__/ReactWrongReturnPointer-test.js b/packages/react-dom/src/__tests__/ReactWrongReturnPointer-test.js index 796d429625a70..e221f01b92d65 100644 --- a/packages/react-dom/src/__tests__/ReactWrongReturnPointer-test.js +++ b/packages/react-dom/src/__tests__/ReactWrongReturnPointer-test.js @@ -196,8 +196,8 @@ test('regression (#20932): return pointer is correct before entering deleted tre 'Suspend! [0]', 'Loading Async...', 'Loading Tail...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [0]'] : []), + // pre-warming + 'Suspend! [0]', ]); await act(() => { resolveText(0); @@ -211,7 +211,7 @@ test('regression (#20932): return pointer is correct before entering deleted tre 'Loading Async...', 'Suspend! [1]', 'Loading Async...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [1]'] : []), + // pre-warming + 'Suspend! [1]', ]); }); diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.js b/packages/react-reconciler/src/ReactFiberCompleteWork.js index c6b9334c65d30..d62e3c3fea11d 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.js @@ -41,7 +41,6 @@ import { enableRenderableContext, passChildrenWhenCloningPersistedNodes, disableLegacyMode, - enableSiblingPrerendering, enableViewTransition, enableSuspenseyImages, } from 'shared/ReactFeatureFlags'; @@ -667,9 +666,7 @@ function scheduleRetryEffect( // Track the lanes that have been scheduled for an immediate retry so that // we can mark them as suspended upon committing the root. - if (enableSiblingPrerendering) { - markSpawnedRetryLane(retryLane); - } + markSpawnedRetryLane(retryLane); } } diff --git a/packages/react-reconciler/src/ReactFiberLane.js b/packages/react-reconciler/src/ReactFiberLane.js index 6548aeac3af38..fdada6b065a29 100644 --- a/packages/react-reconciler/src/ReactFiberLane.js +++ b/packages/react-reconciler/src/ReactFiberLane.js @@ -27,7 +27,6 @@ import { transitionLaneExpirationMs, retryLaneExpirationMs, disableLegacyMode, - enableSiblingPrerendering, } from 'shared/ReactFeatureFlags'; import {isDevToolsPresent} from './ReactFiberDevToolsHook'; import {clz32} from './clz32'; @@ -267,13 +266,11 @@ export function getNextLanes( if (nonIdlePingedLanes !== NoLanes) { nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); } else { - if (enableSiblingPrerendering) { - // Nothing has been pinged. Check for lanes that need to be prewarmed. - if (!rootHasPendingCommit) { - const lanesToPrewarm = nonIdlePendingLanes & ~warmLanes; - if (lanesToPrewarm !== NoLanes) { - nextLanes = getHighestPriorityLanes(lanesToPrewarm); - } + // Nothing has been pinged. Check for lanes that need to be prewarmed. + if (!rootHasPendingCommit) { + const lanesToPrewarm = nonIdlePendingLanes & ~warmLanes; + if (lanesToPrewarm !== NoLanes) { + nextLanes = getHighestPriorityLanes(lanesToPrewarm); } } } @@ -293,13 +290,11 @@ export function getNextLanes( if (pingedLanes !== NoLanes) { nextLanes = getHighestPriorityLanes(pingedLanes); } else { - if (enableSiblingPrerendering) { - // Nothing has been pinged. Check for lanes that need to be prewarmed. - if (!rootHasPendingCommit) { - const lanesToPrewarm = pendingLanes & ~warmLanes; - if (lanesToPrewarm !== NoLanes) { - nextLanes = getHighestPriorityLanes(lanesToPrewarm); - } + // Nothing has been pinged. Check for lanes that need to be prewarmed. + if (!rootHasPendingCommit) { + const lanesToPrewarm = pendingLanes & ~warmLanes; + if (lanesToPrewarm !== NoLanes) { + nextLanes = getHighestPriorityLanes(lanesToPrewarm); } } } @@ -802,7 +797,7 @@ export function markRootSuspended( root.suspendedLanes |= suspendedLanes; root.pingedLanes &= ~suspendedLanes; - if (enableSiblingPrerendering && didAttemptEntireTree) { + if (didAttemptEntireTree) { // Mark these lanes as warm so we know there's nothing else to work on. root.warmLanes |= suspendedLanes; } else { @@ -913,7 +908,6 @@ export function markRootFinished( // suspended) instead of the regular mode (i.e. unwind and skip the siblings // as soon as something suspends to unblock the rest of the update). if ( - enableSiblingPrerendering && suspendedRetryLanes !== NoLanes && // Note that we only do this if there were no updates since we started // rendering. This mirrors the logic in markRootUpdated — whenever we diff --git a/packages/react-reconciler/src/ReactFiberRootScheduler.js b/packages/react-reconciler/src/ReactFiberRootScheduler.js index 3415d1795a9a2..f7c26580bb95a 100644 --- a/packages/react-reconciler/src/ReactFiberRootScheduler.js +++ b/packages/react-reconciler/src/ReactFiberRootScheduler.js @@ -18,7 +18,6 @@ import { enableProfilerTimer, enableProfilerNestedUpdatePhase, enableComponentPerformanceTrack, - enableSiblingPrerendering, enableYieldingBeforePassive, enableGestureTransition, } from 'shared/ReactFeatureFlags'; @@ -381,7 +380,7 @@ function scheduleTaskForRootDuringMicrotask( // If we're prerendering, then we should use the concurrent work loop // even if the lanes are synchronous, so that prerendering never blocks // the main thread. - !(enableSiblingPrerendering && checkIfRootIsPrerendering(root, nextLanes)) + !checkIfRootIsPrerendering(root, nextLanes) ) { // Synchronous work is always flushed at the end of the microtask, so we // don't need to schedule an additional task. diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index 80d8f27951a18..95285c936eb93 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -47,7 +47,6 @@ import { enableInfiniteRenderLoopDetection, disableLegacyMode, disableDefaultPropsExceptForClasses, - enableSiblingPrerendering, enableComponentPerformanceTrack, enableYieldingBeforePassive, enableThrottledScheduling, @@ -1061,7 +1060,7 @@ export function performWorkOnRoot( // the main thread. // TODO: We should consider doing this whenever a sync lane is suspended, // even for regular pings. - (enableSiblingPrerendering && checkIfRootIsPrerendering(root, lanes)); + checkIfRootIsPrerendering(root, lanes); let exitStatus = shouldTimeSlice ? renderRootConcurrent(root, lanes) @@ -1072,11 +1071,7 @@ export function performWorkOnRoot( do { if (exitStatus === RootInProgress) { // Render phase is still in progress. - if ( - enableSiblingPrerendering && - workInProgressRootIsPrerendering && - !shouldTimeSlice - ) { + if (workInProgressRootIsPrerendering && !shouldTimeSlice) { // We're in prerendering mode, but time slicing is not enabled. This // happens when something suspends during a synchronous update. Exit the // the work loop. When we resume, we'll use the concurrent work loop so @@ -2057,27 +2052,13 @@ function handleThrow(root: FiberRoot, thrownValue: any): void { // API for suspending. This implementation detail can change later, once we // deprecate the old API in favor of `use`. thrownValue = getSuspendedThenable(); - workInProgressSuspendedReason = - // TODO: Suspending the work loop during the render phase is - // currently not compatible with sibling prerendering. We will add - // this optimization back in a later step. - !enableSiblingPrerendering && - shouldRemainOnPreviousScreen() && - // Check if there are other pending updates that might possibly unblock this - // component from suspending. This mirrors the check in - // renderDidSuspendDelayIfPossible. We should attempt to unify them somehow. - // TODO: Consider unwinding immediately, using the - // SuspendedOnHydration mechanism. - !includesNonIdleWork(workInProgressRootSkippedLanes) && - !includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes) - ? // Suspend work loop until data resolves - thrownValue === SuspenseActionException - ? SuspendedOnAction - : SuspendedOnData - : // Don't suspend work loop, except to check if the data has - // immediately resolved (i.e. in a microtask). Otherwise, trigger the - // nearest Suspense fallback. - SuspendedOnImmediate; + // TODO: Suspending the work loop during the render phase is + // currently not compatible with sibling prerendering. We will add + // this optimization back in a later step. + // Don't suspend work loop, except to check if the data has + // immediately resolved (i.e. in a microtask). Otherwise, trigger the + // nearest Suspense fallback. + workInProgressSuspendedReason = SuspendedOnImmediate; } else if (thrownValue === SuspenseyCommitException) { thrownValue = getSuspendedThenable(); workInProgressSuspendedReason = SuspendedOnInstance; @@ -2421,7 +2402,6 @@ function renderRootSync( workInProgressThrownValue = null; throwAndUnwindWorkLoop(root, unitOfWork, thrownValue, reason); if ( - enableSiblingPrerendering && shouldYieldForPrerendering && workInProgressRootIsPrerendering ) { @@ -3008,56 +2988,54 @@ function throwAndUnwindWorkLoop( if (unitOfWork.flags & Incomplete) { // Unwind the stack until we reach the nearest boundary. let skipSiblings; - if (!enableSiblingPrerendering) { + + if ( + // The current algorithm for both hydration and error handling assumes + // that the tree is rendered sequentially. So we always skip the siblings. + getIsHydrating() || + suspendedReason === SuspendedOnError + ) { skipSiblings = true; - } else { + // We intentionally don't set workInProgressRootDidSkipSuspendedSiblings, + // because we don't want to trigger another prerender attempt. + } else if ( + // Check whether this is a prerender + !workInProgressRootIsPrerendering && + // Offscreen rendering is also a form of speculative rendering + !includesSomeLane(workInProgressRootRenderLanes, OffscreenLane) + ) { + // This is not a prerender. Skip the siblings during this render. A + // separate prerender will be scheduled for later. + skipSiblings = true; + workInProgressRootDidSkipSuspendedSiblings = true; + + // Because we're skipping the siblings, schedule an immediate retry of + // this boundary. + // + // The reason we do this is because a prerender is only scheduled when + // the root is blocked from committing, i.e. RootSuspendedWithDelay. + // When the root is not blocked, as in the case when we render a + // fallback, the original lane is considered to be finished, and + // therefore no longer in need of being prerendered. However, there's + // still a pending retry that will happen once the data streams in. + // We should start rendering that even before the data streams in so we + // can prerender the siblings. if ( - // The current algorithm for both hydration and error handling assumes - // that the tree is rendered sequentially. So we always skip the siblings. - getIsHydrating() || - suspendedReason === SuspendedOnError - ) { - skipSiblings = true; - // We intentionally don't set workInProgressRootDidSkipSuspendedSiblings, - // because we don't want to trigger another prerender attempt. - } else if ( - // Check whether this is a prerender - !workInProgressRootIsPrerendering && - // Offscreen rendering is also a form of speculative rendering - !includesSomeLane(workInProgressRootRenderLanes, OffscreenLane) + suspendedReason === SuspendedOnData || + suspendedReason === SuspendedOnAction || + suspendedReason === SuspendedOnImmediate || + suspendedReason === SuspendedOnDeprecatedThrowPromise ) { - // This is not a prerender. Skip the siblings during this render. A - // separate prerender will be scheduled for later. - skipSiblings = true; - workInProgressRootDidSkipSuspendedSiblings = true; - - // Because we're skipping the siblings, schedule an immediate retry of - // this boundary. - // - // The reason we do this is because a prerender is only scheduled when - // the root is blocked from committing, i.e. RootSuspendedWithDelay. - // When the root is not blocked, as in the case when we render a - // fallback, the original lane is considered to be finished, and - // therefore no longer in need of being prerendered. However, there's - // still a pending retry that will happen once the data streams in. - // We should start rendering that even before the data streams in so we - // can prerender the siblings. - if ( - suspendedReason === SuspendedOnData || - suspendedReason === SuspendedOnAction || - suspendedReason === SuspendedOnImmediate || - suspendedReason === SuspendedOnDeprecatedThrowPromise - ) { - const boundary = getSuspenseHandler(); - if (boundary !== null && boundary.tag === SuspenseComponent) { - boundary.flags |= ScheduleRetry; - } + const boundary = getSuspenseHandler(); + if (boundary !== null && boundary.tag === SuspenseComponent) { + boundary.flags |= ScheduleRetry; } - } else { - // This is a prerender. Don't skip the siblings. - skipSiblings = false; } + } else { + // This is a prerender. Don't skip the siblings. + skipSiblings = false; } + unwindUnitOfWork(unitOfWork, skipSiblings); } else { // Although the fiber suspended, we're intentionally going to commit it in diff --git a/packages/react-reconciler/src/__tests__/ActivityLegacySuspense-test.js b/packages/react-reconciler/src/__tests__/ActivityLegacySuspense-test.js index 424594cc35e80..3d059ab8e3efa 100644 --- a/packages/react-reconciler/src/__tests__/ActivityLegacySuspense-test.js +++ b/packages/react-reconciler/src/__tests__/ActivityLegacySuspense-test.js @@ -205,9 +205,8 @@ describe('Activity Suspense', () => { }); assertLog([ 'Suspend! [hello]', - ...(gate(flags => flags.enableSiblingPrerendering) - ? ['Suspend! [hello]'] - : []), + // pre-warming + 'Suspend! [hello]', ]); expect(root).toMatchRenderedOutput('Loading'); diff --git a/packages/react-reconciler/src/__tests__/ActivityStrictMode-test.js b/packages/react-reconciler/src/__tests__/ActivityStrictMode-test.js index 12b319080de5c..78947437f6473 100644 --- a/packages/react-reconciler/src/__tests__/ActivityStrictMode-test.js +++ b/packages/react-reconciler/src/__tests__/ActivityStrictMode-test.js @@ -240,11 +240,10 @@ describe('Activity StrictMode', () => { 'Parent mount', 'Parent unmount', 'Parent mount', - - ...(gate('enableSiblingPrerendering') - ? ['Child rendered', 'Child suspended'] - : []), - + // pre-warming + 'Child rendered', + 'Child suspended', + // end pre-warming '------------------------------', 'Child rendered', 'Child rendered', diff --git a/packages/react-reconciler/src/__tests__/ActivitySuspense-test.js b/packages/react-reconciler/src/__tests__/ActivitySuspense-test.js index 2fb35df4574ad..b18573efa5b02 100644 --- a/packages/react-reconciler/src/__tests__/ActivitySuspense-test.js +++ b/packages/react-reconciler/src/__tests__/ActivitySuspense-test.js @@ -202,9 +202,8 @@ describe('Activity Suspense', () => { }); assertLog([ 'Suspend! [hello]', - ...(gate(flags => flags.enableSiblingPrerendering) - ? ['Suspend! [hello]'] - : []), + // pre-warming + 'Suspend! [hello]', ]); expect(root).toMatchRenderedOutput('Loading'); @@ -265,7 +264,8 @@ describe('Activity Suspense', () => { assertLog([ 'Open', 'Suspend! [Async]', - ...(gate(flags => flags.enableSiblingPrerendering) ? ['Loading...'] : []), + // pre-warming + 'Loading...', ]); // It should suspend with delay to prevent the already-visible Suspense // boundary from switching to a fallback @@ -276,7 +276,9 @@ describe('Activity Suspense', () => { await resolveText('Async'); }); assertLog([ - ...(gate(flags => flags.enableSiblingPrerendering) ? ['Open'] : []), + // pre-warming + 'Open', + // end pre-warming 'Async', ]); expect(root).toMatchRenderedOutput( @@ -333,7 +335,8 @@ describe('Activity Suspense', () => { assertLog([ 'Open', 'Suspend! [Async]', - ...(gate(flags => flags.enableSiblingPrerendering) ? ['Loading...'] : []), + // pre-warming + 'Loading...', ]); // It should suspend with delay to prevent the already-visible Suspense // boundary from switching to a fallback diff --git a/packages/react-reconciler/src/__tests__/ReactActWarnings-test.js b/packages/react-reconciler/src/__tests__/ReactActWarnings-test.js index 82827406557dc..017238e3f9500 100644 --- a/packages/react-reconciler/src/__tests__/ReactActWarnings-test.js +++ b/packages/react-reconciler/src/__tests__/ReactActWarnings-test.js @@ -367,8 +367,8 @@ describe('act warnings', () => { assertLog([ 'Suspend! [Async]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Async]'] : []), + // pre-warming + 'Suspend! [Async]', ]); expect(root).toMatchRenderedOutput('Loading...'); @@ -388,21 +388,19 @@ describe('act warnings', () => { "This ensures that you're testing the behavior the user would see in the browser. " + 'Learn more at https://react.dev/link/wrap-tests-with-act', - ...(gate('enableSiblingPrerendering') - ? [ - 'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\n' + - '\n' + - 'When testing, code that resolves suspended data should be wrapped into act(...):\n' + - '\n' + - 'act(() => {\n' + - ' /* finish loading suspended data */\n' + - '});\n' + - '/* assert on the output */\n' + - '\n' + - "This ensures that you're testing the behavior the user would see in the browser. " + - 'Learn more at https://react.dev/link/wrap-tests-with-act', - ] - : []), + // pre-warming + + 'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\n' + + '\n' + + 'When testing, code that resolves suspended data should be wrapped into act(...):\n' + + '\n' + + 'act(() => {\n' + + ' /* finish loading suspended data */\n' + + '});\n' + + '/* assert on the output */\n' + + '\n' + + "This ensures that you're testing the behavior the user would see in the browser. " + + 'Learn more at https://react.dev/link/wrap-tests-with-act', ], {withoutStack: true}, diff --git a/packages/react-reconciler/src/__tests__/ReactAsyncActions-test.js b/packages/react-reconciler/src/__tests__/ReactAsyncActions-test.js index 43e071d4141cf..20480eb287675 100644 --- a/packages/react-reconciler/src/__tests__/ReactAsyncActions-test.js +++ b/packages/react-reconciler/src/__tests__/ReactAsyncActions-test.js @@ -301,10 +301,9 @@ describe('ReactAsyncActions', () => { 'Async action ended', 'Pending: false', 'Suspend! [A1]', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [B1]', 'Suspend! [C1]'] - : []), + // pre-warming + 'Suspend! [B1]', + 'Suspend! [C1]', ]); expect(root).toMatchRenderedOutput( <> @@ -321,8 +320,8 @@ describe('ReactAsyncActions', () => { 'Pending: false', 'A1', 'Suspend! [B1]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C1]'] : []), + // pre-warming + 'Suspend! [C1]', ]); expect(root).toMatchRenderedOutput( <> diff --git a/packages/react-reconciler/src/__tests__/ReactBatching-test.internal.js b/packages/react-reconciler/src/__tests__/ReactBatching-test.internal.js index b11e78bdec526..bc3cfd8deb573 100644 --- a/packages/react-reconciler/src/__tests__/ReactBatching-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactBatching-test.internal.js @@ -113,8 +113,10 @@ describe('ReactBlockingMode', () => { 'A', 'Suspend! [B]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [B]', 'C'] : []), + // pre-warming + 'A', + 'Suspend! [B]', + 'C', ]); // In Legacy Mode, A and B would mount in a hidden primary tree. In // Concurrent Mode, nothing in the primary tree should mount. But the diff --git a/packages/react-reconciler/src/__tests__/ReactCPUSuspense-test.js b/packages/react-reconciler/src/__tests__/ReactCPUSuspense-test.js index b36164fca285b..1b1489de33a4f 100644 --- a/packages/react-reconciler/src/__tests__/ReactCPUSuspense-test.js +++ b/packages/react-reconciler/src/__tests__/ReactCPUSuspense-test.js @@ -233,8 +233,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { // Inner contents suspended, so we continue showing a fallback. assertLog([ 'Suspend! [Inner]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Inner]'] : []), + // pre-warming + 'Suspend! [Inner]', ]); expect(root).toMatchRenderedOutput( <> diff --git a/packages/react-reconciler/src/__tests__/ReactConcurrentErrorRecovery-test.js b/packages/react-reconciler/src/__tests__/ReactConcurrentErrorRecovery-test.js index 4a00607ffb848..d4bd1958f64c0 100644 --- a/packages/react-reconciler/src/__tests__/ReactConcurrentErrorRecovery-test.js +++ b/packages/react-reconciler/src/__tests__/ReactConcurrentErrorRecovery-test.js @@ -399,10 +399,8 @@ describe('ReactConcurrentErrorRecovery', () => { }); assertLog([ 'Suspend! [Async]', - - ...(gate('enableSiblingPrerendering') - ? ['Caught an error: Oops!'] - : []), + // pre-warming + 'Caught an error: Oops!', ]); // The render suspended without committing the error. expect(root).toMatchRenderedOutput(null); @@ -420,13 +418,7 @@ describe('ReactConcurrentErrorRecovery', () => { ); }); }); - assertLog([ - 'Suspend! [Async]', - - ...(gate('enableSiblingPrerendering') - ? ['Caught an error: Oops!'] - : []), - ]); + assertLog(['Suspend! [Async]', 'Caught an error: Oops!']); expect(root).toMatchRenderedOutput(null); await act(async () => { diff --git a/packages/react-reconciler/src/__tests__/ReactContextPropagation-test.js b/packages/react-reconciler/src/__tests__/ReactContextPropagation-test.js index 019119edf7ce8..6ed19ba6d505b 100644 --- a/packages/react-reconciler/src/__tests__/ReactContextPropagation-test.js +++ b/packages/react-reconciler/src/__tests__/ReactContextPropagation-test.js @@ -398,8 +398,8 @@ describe('ReactLazyContextPropagation', () => { 'Suspend! [B]', 'Loading...', 'B', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []), + // pre-warming + 'Suspend! [B]', ]); expect(root).toMatchRenderedOutput('Loading...B'); @@ -484,8 +484,8 @@ describe('ReactLazyContextPropagation', () => { 'Suspend! [B]', 'Loading...', 'B', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []), + // pre-warming + 'Suspend! [B]', ]); expect(root).toMatchRenderedOutput('Loading...B'); @@ -822,8 +822,8 @@ describe('ReactLazyContextPropagation', () => { assertLog([ 'Suspend! [B]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []), + // pre-warming + 'Suspend! [B]', ]); expect(root).toMatchRenderedOutput('Loading...'); diff --git a/packages/react-reconciler/src/__tests__/ReactDeferredValue-test.js b/packages/react-reconciler/src/__tests__/ReactDeferredValue-test.js index f57fc0ac0239a..f8504720ac863 100644 --- a/packages/react-reconciler/src/__tests__/ReactDeferredValue-test.js +++ b/packages/react-reconciler/src/__tests__/ReactDeferredValue-test.js @@ -420,10 +420,9 @@ describe('ReactDeferredValue', () => { // The initial value suspended, so we attempt the final value, which // also suspends. 'Suspend! [Final]', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [Loading...]', 'Suspend! [Final]'] - : []), + // pre-warming + 'Suspend! [Loading...]', + 'Suspend! [Final]', ]); expect(root).toMatchRenderedOutput(null); @@ -463,10 +462,9 @@ describe('ReactDeferredValue', () => { // The initial value suspended, so we attempt the final value, which // also suspends. 'Suspend! [Final]', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [Loading...]', 'Suspend! [Final]'] - : []), + // pre-warming + 'Suspend! [Loading...]', + 'Suspend! [Final]', ]); expect(root).toMatchRenderedOutput(null); @@ -507,8 +505,8 @@ describe('ReactDeferredValue', () => { // The initial value suspended, so we attempt the final value, which // also suspends. 'Suspend! [Final]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Final]'] : []), + // pre-warming + 'Suspend! [Final]', ]); expect(root).toMatchRenderedOutput('Fallback'); @@ -541,10 +539,9 @@ describe('ReactDeferredValue', () => { // The initial value suspended, so we attempt the final value, which // also suspends. 'Suspend! [Final]', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [Loading...]', 'Suspend! [Final]'] - : []), + // pre-warming + 'Suspend! [Loading...]', + 'Suspend! [Final]', ]); expect(root).toMatchRenderedOutput(null); @@ -644,8 +641,8 @@ describe('ReactDeferredValue', () => { // go straight to attempting the final value. 'Suspend! [Content]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Content]'] : []), + // pre-warming + 'Suspend! [Content]', ]); // The content suspended, so we show a Suspense fallback expect(root).toMatchRenderedOutput('Loading...'); diff --git a/packages/react-reconciler/src/__tests__/ReactExpiration-test.js b/packages/react-reconciler/src/__tests__/ReactExpiration-test.js index 5b09d7d0b8821..1c678f8cfe4b0 100644 --- a/packages/react-reconciler/src/__tests__/ReactExpiration-test.js +++ b/packages/react-reconciler/src/__tests__/ReactExpiration-test.js @@ -654,9 +654,10 @@ describe('ReactExpiration', () => { }); await waitForAll([ 'Suspend! [A1]', - - ...(gate('enableSiblingPrerendering') ? ['B', 'C'] : []), - + // pre-warming + 'B', + 'C', + // end pre-warming 'Loading...', ]); diff --git a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js index f72b738cf69b4..905aac9a7857e 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js +++ b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js @@ -3658,8 +3658,8 @@ describe('ReactHooksWithNoopRenderer', () => { 'A', 'Suspend! [A]', 'Loading', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput( <> diff --git a/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js b/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js index e8c2153cab94a..a6306bfcfe7e4 100644 --- a/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js @@ -198,7 +198,10 @@ describe('ReactLazy', () => { await resolveFakeImport(Foo); - await waitForAll(['Foo']); + await waitForAll([ + 'Foo', + ...(gate('alwaysThrottleRetries') ? [] : ['Foo']), + ]); expect(root).not.toMatchRenderedOutput('FooBar'); await act(() => resolveFakeImport(Bar)); @@ -326,8 +329,8 @@ describe('ReactLazy', () => { await waitForAll([ 'Suspend! [LazyChildA]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [LazyChildB]'] : []), + // pre-warming + 'Suspend! [LazyChildB]', ]); expect(root).not.toMatchRenderedOutput('AB'); @@ -339,21 +342,12 @@ describe('ReactLazy', () => { // we can unwrap the result synchronously if it already loaded. Like `use`. await waitFor([ 'A', - - // When enableSiblingPrerendering is on, LazyChildB was already - // initialized. So it also already resolved when we called - // resolveFakeImport above. So it doesn't suspend again. - ...(gate('enableSiblingPrerendering') - ? ['B'] - : ['Suspend! [LazyChildB]']), + // pre-warming: LazyChildB was already initialized. So it also already resolved + // when we called resolveFakeImport above. So it doesn't suspend again. + 'B', ]); }); - assertLog([ - ...(gate('enableSiblingPrerendering') ? [] : ['A', 'B']), - - 'Did mount: A', - 'Did mount: B', - ]); + assertLog(['Did mount: A', 'Did mount: B']); expect(root).toMatchRenderedOutput('AB'); // Swap the position of A and B @@ -1612,7 +1606,11 @@ describe('ReactLazy', () => { expect(ref.current).toBe(null); await act(() => resolveFakeImport(Foo)); - assertLog(['Foo', ...(gate('enableSiblingPrerendering') ? ['Foo'] : [])]); + assertLog([ + 'Foo', + // pre-warming + 'Foo', + ]); await act(() => resolveFakeImport(ForwardRefBar)); assertLog(['Foo', 'forwardRef', 'Bar']); @@ -1910,17 +1908,16 @@ describe('ReactLazy', () => { await waitForAll([ 'Init A', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Init B'] : []), + // pre-warming + 'Init B', ]); expect(root).not.toMatchRenderedOutput('AB'); await act(() => resolveFakeImport(ChildA)); assertLog([ 'A', - - // When enableSiblingPrerendering is on, B was already initialized. - ...(gate('enableSiblingPrerendering') ? ['A'] : ['Init B']), + // pre-warming + 'A', ]); await act(() => resolveFakeImport(ChildB)); diff --git a/packages/react-reconciler/src/__tests__/ReactSiblingPrerendering-test.js b/packages/react-reconciler/src/__tests__/ReactSiblingPrerendering-test.js index ceb32160976e0..4252fef65f33c 100644 --- a/packages/react-reconciler/src/__tests__/ReactSiblingPrerendering-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSiblingPrerendering-test.js @@ -171,7 +171,7 @@ describe('ReactSiblingPrerendering', () => { // After B suspends, we're still able to prerender C without starting // over because there's no fallback, so the root is blocked from // committing anyway. - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C]'] : []), + 'Suspend! [C]', ]); }); @@ -207,12 +207,10 @@ describe('ReactSiblingPrerendering', () => { // The second render is a prerender of the hidden content. await waitForPaint([ 'Suspend! [B]', - // If B and C were visible, C would not have been attempted // during this pass, because it would prevented the fallback // from showing. - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C]'] : []), - + 'Suspend! [C]', 'Loading...', ]); expect(root).toMatchRenderedOutput('A'); @@ -240,13 +238,11 @@ describe('ReactSiblingPrerendering', () => { // Immediately after the fallback commits, retry the boundary again. This // time we include B, since we're not blocking the fallback from showing. - if (gate('enableSiblingPrerendering')) { - if (gate(flags => flags.enableYieldingBeforePassive)) { - // Passive effects. - await waitForPaint([]); - } - await waitForPaint(['Suspend! [A]', 'Suspend! [B]']); + if (gate(flags => flags.enableYieldingBeforePassive)) { + // Passive effects. + await waitForPaint([]); } + await waitForPaint(['Suspend! [A]', 'Suspend! [B]']); }); expect(root).toMatchRenderedOutput('Loading...'); }); @@ -282,11 +278,7 @@ describe('ReactSiblingPrerendering', () => { // Now that the fallback is visible, we can prerender the siblings. Start // prerendering, then yield to simulate an interleaved event. - if (gate('enableSiblingPrerendering')) { - await waitFor(['A']); - } else { - await waitForAll([]); - } + await waitFor(['A']); // To avoid the Suspense throttling mechanism, let's pretend there's been // more than a Just Noticeable Difference since we rendered the @@ -298,10 +290,6 @@ describe('ReactSiblingPrerendering', () => { // shouldn't unwind and lose our work-in-progress. await resolveText('B'); await waitForPaint([ - // When sibling prerendering is not enabled, we weren't already rendering - // when the data for B came in, so A doesn't get rendered until now. - ...(gate('enableSiblingPrerendering') ? [] : ['A']), - 'B', 'Suspend! [C]', @@ -321,23 +309,19 @@ describe('ReactSiblingPrerendering', () => { // Now that the inner fallback is showing, we can prerender the rest of // the tree. - assertLog( - gate('enableSiblingPrerendering') - ? [ - // NOTE: C renders twice instead of once because when B resolved, it - // was treated like a retry update, not just a ping. So first it - // regular renders, then it prerenders. TODO: We should be able to - // optimize this by detecting inside the retry listener that the - // outer boundary is no longer suspended, and therefore doesn't need - // to be updated. - 'Suspend! [C]', - - // Now we're in prerender mode, so D is incuded in this attempt. - 'Suspend! [C]', - 'Suspend! [D]', - ] - : [], - ); + assertLog([ + // NOTE: C renders twice instead of once because when B resolved, it + // was treated like a retry update, not just a ping. So first it + // regular renders, then it prerenders. TODO: We should be able to + // optimize this by detecting inside the retry listener that the + // outer boundary is no longer suspended, and therefore doesn't need + // to be updated. + 'Suspend! [C]', + + // Now we're in prerender mode, so D is incuded in this attempt. + 'Suspend! [C]', + 'Suspend! [D]', + ]); expect(root).toMatchRenderedOutput(
AB
@@ -402,9 +386,7 @@ describe('ReactSiblingPrerendering', () => { ); }); // Once the inner fallback is committed, we can start prerendering C. - assertLog( - gate('enableSiblingPrerendering') ? ['Suspend! [B]', 'Suspend! [C]'] : [], - ); + assertLog(['Suspend! [B]', 'Suspend! [C]']); }); it( @@ -488,9 +470,7 @@ describe('ReactSiblingPrerendering', () => { await waitForPaint([]); } // Now we can proceed to prerendering C. - if (gate('enableSiblingPrerendering')) { - await waitForPaint(['Suspend! [B]', 'Suspend! [C]']); - } + await waitForPaint(['Suspend! [B]', 'Suspend! [C]']); }); assertLog([]); }, @@ -519,12 +499,10 @@ describe('ReactSiblingPrerendering', () => { // Synchronously render everything until we suspend in the shell assertLog(['A', 'B', 'Suspend! [Async]']); - if (gate('enableSiblingPrerendering')) { - // The rest of the siblings begin to prerender concurrently. Notice - // that we don't unwind here; we pick up where we left off above. - await waitFor(['C']); - await waitFor(['D']); - } + // The rest of the siblings begin to prerender concurrently. Notice + // that we don't unwind here; we pick up where we left off above. + await waitFor(['C']); + await waitFor(['D']); assertLog([]); expect(root).toMatchRenderedOutput(null); @@ -555,10 +533,8 @@ describe('ReactSiblingPrerendering', () => { // Synchronously render everything until we suspend in the shell assertLog(['A', 'B', 'Suspend! [Async]']); - if (gate('enableSiblingPrerendering')) { - // The rest of the siblings begin to prerender concurrently - await waitFor(['C']); - } + // The rest of the siblings begin to prerender concurrently + await waitFor(['C']); // While we're prerendering, Async resolves. We should unwind and // start over, rather than continue prerendering D. diff --git a/packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js b/packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js index d7ad652f1da7e..8657365b063aa 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js @@ -135,9 +135,9 @@ describe('ReactSuspense', () => { 'Bar', // A suspends 'Suspend! [A]', - - ...(gate('enableSiblingPrerendering') ? ['B'] : []), - + // pre-warming + 'B', + // end pre-warming 'Loading...', ]); expect(container.textContent).toEqual(''); @@ -169,10 +169,9 @@ describe('ReactSuspense', () => { 'Loading A...', 'Suspend! [B]', 'Loading B...', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [A]', 'Suspend! [B]'] - : []), + // pre-warming + 'Suspend! [A]', + 'Suspend! [B]', ]); expect(container.innerHTML).toEqual('Loading A...Loading B...'); @@ -181,8 +180,7 @@ describe('ReactSuspense', () => { await act(() => resolveText('A')); assertLog([ 'A', - - ...(gate('enableSiblingPrerendering') + ...(gate('alwaysThrottleRetries') ? ['Suspend! [B]', 'Suspend! [B]'] : []), ]); @@ -288,10 +286,10 @@ describe('ReactSuspense', () => { 'Foo', 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [A]', 'Suspend! [B]', 'Loading more...'] - : []), + // pre-warming + 'Suspend! [A]', + 'Suspend! [B]', + 'Loading more...', ]); expect(container.textContent).toEqual('Loading...'); @@ -341,10 +339,10 @@ describe('ReactSuspense', () => { 'Foo', 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [A]', 'Suspend! [B]', 'Loading more...'] - : []), + // pre-warming + 'Suspend! [A]', + 'Suspend! [B]', + 'Loading more...', ]); expect(container.textContent).toEqual('Loading...'); @@ -390,10 +388,10 @@ describe('ReactSuspense', () => { 'Foo', 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [A]', 'Suspend! [B]', 'Loading more...'] - : []), + // pre-warming + 'Suspend! [A]', + 'Suspend! [B]', + 'Loading more...', ]); expect(container.textContent).toEqual('Loading...'); @@ -482,8 +480,8 @@ describe('ReactSuspense', () => { assertLog([ 'Suspend! [default]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [default]'] : []), + // pre-warming + 'Suspend! [default]', ]); await act(() => resolveText('default')); @@ -494,8 +492,8 @@ describe('ReactSuspense', () => { assertLog([ 'Suspend! [new value]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [new value]'] : []), + // pre-warming + 'Suspend! [new value]', ]); await act(() => resolveText('new value')); @@ -539,8 +537,8 @@ describe('ReactSuspense', () => { assertLog([ 'Suspend! [default]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [default]'] : []), + // pre-warming + 'Suspend! [default]', ]); await act(() => resolveText('default')); @@ -551,8 +549,8 @@ describe('ReactSuspense', () => { assertLog([ 'Suspend! [new value]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [new value]'] : []), + // pre-warming + 'Suspend! [new value]', ]); await act(() => resolveText('new value')); @@ -593,8 +591,8 @@ describe('ReactSuspense', () => { assertLog([ 'Suspend! [default]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [default]'] : []), + // pre-warming + 'Suspend! [default]', ]); await act(() => resolveText('default')); @@ -605,8 +603,8 @@ describe('ReactSuspense', () => { assertLog([ 'Suspend! [new value]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [new value]'] : []), + // pre-warming + 'Suspend! [new value]', ]); await act(() => resolveText('new value')); @@ -647,8 +645,8 @@ describe('ReactSuspense', () => { assertLog([ 'Suspend! [default]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [default]'] : []), + // pre-warming + 'Suspend! [default]', ]); await act(() => resolveText('default')); @@ -659,8 +657,8 @@ describe('ReactSuspense', () => { assertLog([ 'Suspend! [new value]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [new value]'] : []), + // pre-warming + 'Suspend! [new value]', ]); await act(() => resolveText('new value')); @@ -708,10 +706,9 @@ describe('ReactSuspense', () => { 'Suspend! [Child 2]', 'Loading...', 'destroy layout', - - ...(gate('enableSiblingPrerendering') - ? ['Child 1', 'Suspend! [Child 2]'] - : []), + // pre-warming + 'Child 1', + 'Suspend! [Child 2]', ]); await act(() => resolveText('Child 2')); @@ -737,13 +734,18 @@ describe('ReactSuspense', () => { assertLog([ 'Suspend! [Child 1]', 'Loading...', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [Child 1]', 'Suspend! [Child 2]'] - : []), + // pre-warming + 'Suspend! [Child 1]', + 'Suspend! [Child 2]', ]); await resolveText('Child 1'); - await waitForAll(['Child 1', 'Suspend! [Child 2]']); + await waitForAll([ + 'Child 1', + 'Suspend! [Child 2]', + ...(gate('alwaysThrottleRetries') + ? [] + : ['Child 1', 'Suspend! [Child 2]']), + ]); jest.advanceTimersByTime(6000); diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseCallback-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseCallback-test.js index 921c9666a935e..866e87bd6c4bd 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseCallback-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseCallback-test.js @@ -60,9 +60,17 @@ describe('ReactSuspense', () => { ReactNoop.render(elementBadType); await waitForAll([]); - assertConsoleErrorDev(['Unexpected type for suspenseCallback.'], { - withoutStack: true, - }); + assertConsoleErrorDev( + [ + 'Unexpected type for suspenseCallback.', + ...(gate('alwaysThrottleRetries') + ? [] + : ['Unexpected type for suspenseCallback.']), + ], + { + withoutStack: true, + }, + ); const elementMissingCallback = ( @@ -93,7 +101,10 @@ describe('ReactSuspense', () => { ReactNoop.render(element); await waitForAll([]); expect(ReactNoop).toMatchRenderedOutput('Waiting'); - expect(ops).toEqual([new Set([promise])]); + expect(ops).toEqual([ + new Set([promise]), + ...(gate('alwaysThrottleRetries') ? [] : new Set([promise])), + ]); ops = []; await act(() => resolve()); @@ -132,7 +143,10 @@ describe('ReactSuspense', () => { ReactNoop.render(element); await waitForAll([]); expect(ReactNoop).toMatchRenderedOutput('Waiting Tier 1'); - expect(ops).toEqual([new Set([promise1])]); + expect(ops).toEqual([ + new Set([promise1]), + ...(gate('alwaysThrottleRetries') ? [] : new Set([promise1, promise2])), + ]); ops = []; await act(() => resolve1()); @@ -141,8 +155,8 @@ describe('ReactSuspense', () => { expect(ReactNoop).toMatchRenderedOutput('Waiting Tier 1'); expect(ops).toEqual([ new Set([promise2]), - - ...(gate('enableSiblingPrerendering') ? new Set([promise2]) : []), + // pre-warming + new Set([promise2]), ]); ops = []; @@ -182,7 +196,10 @@ describe('ReactSuspense', () => { await waitForAll([]); expect(ReactNoop).toMatchRenderedOutput('Waiting Tier 2'); expect(ops1).toEqual([]); - expect(ops2).toEqual([new Set([promise])]); + expect(ops2).toEqual([ + new Set([promise]), + ...(gate('alwaysThrottleRetries') ? [] : [new Set([promise])]), + ]); }); // @gate enableSuspenseCallback @@ -231,11 +248,7 @@ describe('ReactSuspense', () => { await act(() => resolve1()); expect(ReactNoop).toMatchRenderedOutput('Waiting Tier 2Done'); expect(ops1).toEqual([]); - expect(ops2).toEqual([ - new Set([promise2]), - - ...(gate('enableSiblingPrerendering') ? new Set([promise2]) : []), - ]); + expect(ops2).toEqual([new Set([promise2]), new Set([promise2])]); ops1 = []; ops2 = []; diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseEffectsSemantics-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseEffectsSemantics-test.js index d45b29aee59ef..9fc94d7d0eee4 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseEffectsSemantics-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseEffectsSemantics-test.js @@ -283,14 +283,10 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:Fallback create passive', 'Text:Outside create passive', 'App create passive', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Text:Inside:Before render', - 'Suspend:Async', - 'ClassText:Inside:After render', - ] - : []), + // pre-warming + 'Text:Inside:Before render', + 'Suspend:Async', + 'ClassText:Inside:After render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -687,14 +683,10 @@ describe('ReactSuspenseEffectsSemantics', () => { ]); await waitForAll([ 'Text:Fallback create passive', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Text:Inside:Before render', - 'Suspend:Async', - 'Text:Inside:After render', - ] - : []), + // pre-warming + 'Text:Inside:Before render', + 'Suspend:Async', + 'Text:Inside:After render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -850,13 +842,12 @@ describe('ReactSuspenseEffectsSemantics', () => { , ); }); - if (gate('enableSiblingPrerendering')) { - assertLog([ - 'ClassText:Inside:Before render', - 'Suspend:Async', - 'ClassText:Inside:After render', - ]); - } + // pre-warming + assertLog([ + 'ClassText:Inside:Before render', + 'Suspend:Async', + 'ClassText:Inside:After render', + ]); // Resolving the suspended resource should re-create inner layout effects. await act(async () => { @@ -961,10 +952,10 @@ describe('ReactSuspenseEffectsSemantics', () => { ]); await waitForAll([ 'Text:Fallback create passive', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend:Async', 'Text:Outer render', 'Text:Inner render'] - : []), + // pre-warming + 'Suspend:Async', + 'Text:Outer render', + 'Text:Inner render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -1088,10 +1079,9 @@ describe('ReactSuspenseEffectsSemantics', () => { ]); await waitForAll([ 'Text:Fallback create passive', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend:Async', 'Text:Outer render'] - : []), + // pre-warming + 'Suspend:Async', + 'Text:Outer render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -1195,10 +1185,9 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:InnerFallback create insertion', 'Text:InnerFallback create layout', 'Text:InnerFallback create passive', - - ...(gate('enableSiblingPrerendering') - ? ['Text:Inner render', 'Suspend:InnerAsync_1'] - : []), + // pre-warming + 'Text:Inner render', + 'Suspend:InnerAsync_1', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -1228,16 +1217,12 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:OuterFallback create insertion', 'Text:OuterFallback create layout', 'Text:OuterFallback create passive', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Text:Outer render', - 'Suspend:OuterAsync_1', - 'Text:Inner render', - 'Suspend:InnerAsync_1', - 'Text:InnerFallback render', - ] - : []), + // pre-warming + 'Text:Outer render', + 'Suspend:OuterAsync_1', + 'Text:Inner render', + 'Suspend:InnerAsync_1', + 'Text:InnerFallback render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -1255,15 +1240,11 @@ describe('ReactSuspenseEffectsSemantics', () => { assertLog([ 'Text:Outer render', 'Suspend:OuterAsync_1', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Text:Outer render', - 'Suspend:OuterAsync_1', - 'Text:Inner render', - 'AsyncText:InnerAsync_1 render', - ] - : []), + // pre-warming + 'Text:Outer render', + 'Suspend:OuterAsync_1', + 'Text:Inner render', + 'AsyncText:InnerAsync_1 render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -1288,16 +1269,12 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:Outer render', 'Suspend:OuterAsync_1', 'Text:OuterFallback render', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Text:Outer render', - 'Suspend:OuterAsync_1', - 'Text:Inner render', - 'Suspend:InnerAsync_2', - 'Text:InnerFallback render', - ] - : []), + // pre-warming + 'Text:Outer render', + 'Suspend:OuterAsync_1', + 'Text:Inner render', + 'Suspend:InnerAsync_2', + 'Text:InnerFallback render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -1325,10 +1302,9 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:InnerFallback create layout', 'Text:OuterFallback destroy passive', 'AsyncText:OuterAsync_1 create passive', - - ...(gate('enableSiblingPrerendering') - ? ['Text:Inner render', 'Suspend:InnerAsync_2'] - : []), + // pre-warming + 'Text:Inner render', + 'Suspend:InnerAsync_2', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -1382,15 +1358,11 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:OuterFallback create insertion', 'Text:OuterFallback create layout', 'Text:OuterFallback create passive', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Text:Outer render', - 'Suspend:OuterAsync_2', - 'Text:Inner render', - 'AsyncText:InnerAsync_2 render', - ] - : []), + // pre-warming + 'Text:Outer render', + 'Suspend:OuterAsync_2', + 'Text:Inner render', + 'AsyncText:InnerAsync_2 render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -1480,10 +1452,9 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:InnerFallback create insertion', 'Text:InnerFallback create layout', 'Text:InnerFallback create passive', - - ...(gate('enableSiblingPrerendering') - ? ['Text:Inner render', 'Suspend:InnerAsync_1'] - : []), + // pre-warming + 'Text:Inner render', + 'Suspend:InnerAsync_1', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -1512,16 +1483,12 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:OuterFallback create insertion', 'Text:OuterFallback create layout', 'Text:OuterFallback create passive', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Text:Outer render', - 'Suspend:OuterAsync_1', - 'Text:Inner render', - 'Suspend:InnerAsync_1', - 'Text:InnerFallback render', - ] - : []), + // pre-warming + 'Text:Outer render', + 'Suspend:OuterAsync_1', + 'Text:Inner render', + 'Suspend:InnerAsync_1', + 'Text:InnerFallback render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -1630,10 +1597,9 @@ describe('ReactSuspenseEffectsSemantics', () => { await waitForAll([ 'Text:Fallback:Inside create passive', 'Text:Fallback:Outside create passive', - - ...(gate('enableSiblingPrerendering') - ? ['Text:Inside render', 'Suspend:OutsideAsync'] - : []), + // pre-warming + 'Text:Inside render', + 'Suspend:OutsideAsync', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -1667,15 +1633,11 @@ describe('ReactSuspenseEffectsSemantics', () => { ]); await waitForAll([ 'Text:Fallback:Fallback create passive', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Text:Inside render', - 'Suspend:OutsideAsync', - 'Text:Fallback:Inside render', - 'Suspend:FallbackAsync', - ] - : []), + // pre-warming + 'Text:Inside render', + 'Suspend:OutsideAsync', + 'Text:Fallback:Inside render', + 'Suspend:FallbackAsync', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -1787,15 +1749,11 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:Fallback:Outside create layout', 'Text:Fallback:Fallback create passive', 'Text:Fallback:Outside create passive', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Text:Inside render', - 'Suspend:OutsideAsync', - 'Text:Fallback:Inside render', - 'Suspend:FallbackAsync', - ] - : []), + // pre-warming + 'Text:Inside render', + 'Suspend:OutsideAsync', + 'Text:Fallback:Inside render', + 'Suspend:FallbackAsync', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -1915,8 +1873,8 @@ describe('ReactSuspenseEffectsSemantics', () => { ]); await waitForAll([ 'Text:Fallback create passive', - - ...(gate('enableSiblingPrerendering') ? ['Suspend:Suspend'] : []), + // pre-warming + 'Suspend:Suspend', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -2038,10 +1996,10 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:Fallback create insertion', 'Text:Fallback create layout', 'Text:Fallback create passive', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend:Async', 'ThrowsInDidMount render', 'Text:Inside render'] - : []), + // pre-warming + 'Suspend:Async', + 'ThrowsInDidMount render', + 'Text:Inside render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -2301,14 +2259,10 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:Fallback create insertion', 'Text:Fallback create layout', 'Text:Fallback create passive', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Suspend:Async', - 'ThrowsInLayoutEffect render', - 'Text:Inside render', - ] - : []), + // pre-warming + 'Suspend:Async', + 'ThrowsInLayoutEffect render', + 'Text:Inside render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -2555,14 +2509,13 @@ describe('ReactSuspenseEffectsSemantics', () => { ); }); - if (gate('enableSiblingPrerendering')) { - assertLog([ - 'Text:Function render', - 'Suspend:Async_1', - 'Suspend:Async_2', - 'ClassText:Class render', - ]); - } + // pre-warming + assertLog([ + 'Text:Function render', + 'Suspend:Async_1', + 'Suspend:Async_2', + 'ClassText:Class render', + ]); // Resolving the suspended resource should re-create inner layout effects. await act(async () => { @@ -2572,15 +2525,11 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:Function render', 'AsyncText:Async_1 render', 'Suspend:Async_2', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Text:Function render', - 'AsyncText:Async_1 render', - 'Suspend:Async_2', - 'ClassText:Class render', - ] - : []), + // pre-warming + 'Text:Function render', + 'AsyncText:Async_1 render', + 'Suspend:Async_2', + 'ClassText:Class render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -2715,14 +2664,14 @@ describe('ReactSuspenseEffectsSemantics', () => { , ); }); - if (gate('enableSiblingPrerendering')) { - assertLog([ - 'Text:Function render', - 'Suspender "A" render', - 'Suspend:A', - 'ClassText:Class render', - ]); - } + + // pre-warming + assertLog([ + 'Text:Function render', + 'Suspender "A" render', + 'Suspend:A', + 'ClassText:Class render', + ]); // Resolving the suspended resource should re-create inner layout effects. textToRead = 'B'; @@ -2733,15 +2682,11 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:Function render', 'Suspender "B" render', 'Suspend:B', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Text:Function render', - 'Suspender "B" render', - 'Suspend:B', - 'ClassText:Class render', - ] - : []), + // pre-warming + 'Text:Function render', + 'Suspender "B" render', + 'Suspend:B', + 'ClassText:Class render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -2977,15 +2922,11 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:Fallback create insertion', 'Text:Fallback create layout', 'Text:Fallback create passive', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Suspend:Async', - 'RefCheckerOuter render', - 'RefCheckerInner:refObject render', - 'RefCheckerInner:refCallback render', - ] - : []), + // pre-warming + 'Suspend:Async', + 'RefCheckerOuter render', + 'RefCheckerInner:refObject render', + 'RefCheckerInner:refCallback render', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -3089,17 +3030,13 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:Fallback create insertion', 'Text:Fallback create layout', 'Text:Fallback create passive', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Suspend:Async', - 'RefCheckerOuter render', - 'ClassComponent:refObject render', - 'RefCheckerInner:refObject render', - 'ClassComponent:refCallback render', - 'RefCheckerInner:refCallback render', - ] - : []), + // pre-warming + 'Suspend:Async', + 'RefCheckerOuter render', + 'ClassComponent:refObject render', + 'RefCheckerInner:refObject render', + 'ClassComponent:refCallback render', + 'RefCheckerInner:refCallback render', ]); expect(ReactNoop).toMatchRenderedOutput(); @@ -3199,17 +3136,13 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:Fallback create insertion', 'Text:Fallback create layout', 'Text:Fallback create passive', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Suspend:Async', - 'RefCheckerOuter render', - 'FunctionComponent render', - 'RefCheckerInner:refObject render', - 'FunctionComponent render', - 'RefCheckerInner:refCallback render', - ] - : []), + // pre-warming + 'Suspend:Async', + 'RefCheckerOuter render', + 'FunctionComponent render', + 'RefCheckerInner:refObject render', + 'FunctionComponent render', + 'RefCheckerInner:refCallback render', ]); expect(ReactNoop).toMatchRenderedOutput(); @@ -3311,10 +3244,9 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:Fallback create insertion', 'Text:Fallback create layout', 'Text:Fallback create passive', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend:Async', 'RefChecker render'] - : []), + // pre-warming + 'Suspend:Async', + 'RefChecker render', ]); expect(ReactNoop).toMatchRenderedOutput(); @@ -3433,14 +3365,10 @@ describe('ReactSuspenseEffectsSemantics', () => { 'Text:Fallback create insertion', 'Text:Fallback create layout', 'Text:Fallback create passive', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Suspend:Async', - 'ThrowsInRefCallback render', - 'Text:Inside render', - ] - : []), + // pre-warming + 'Suspend:Async', + 'ThrowsInRefCallback render', + 'Text:Inside render', ]); expect(ReactNoop).toMatchRenderedOutput( <> diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseFallback-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseFallback-test.js index 2a6664c0dc2de..836ed7aac826b 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseFallback-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseFallback-test.js @@ -142,8 +142,8 @@ describe('ReactSuspenseFallback', () => { await waitForAll([ 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput(); }); @@ -159,8 +159,8 @@ describe('ReactSuspenseFallback', () => { await waitForAll([ 'Suspend! [A]', // null - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput(null); }); @@ -176,8 +176,8 @@ describe('ReactSuspenseFallback', () => { await waitForAll([ 'Suspend! [A]', // null - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput(null); }); @@ -195,8 +195,8 @@ describe('ReactSuspenseFallback', () => { await waitForAll([ 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput(); }); @@ -214,8 +214,8 @@ describe('ReactSuspenseFallback', () => { await waitForAll([ 'Suspend! [A]', // null - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput(null); }); @@ -233,8 +233,8 @@ describe('ReactSuspenseFallback', () => { await waitForAll([ 'Suspend! [A]', // null - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput(null); }); diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseList-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseList-test.js index 7cfe72dfc4ec8..6faeae3acba0d 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseList-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseList-test.js @@ -245,9 +245,9 @@ describe('ReactSuspenseList', () => { 'Loading B', 'Suspend! [C]', 'Loading C', - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [B]', 'Suspend! [C]'] - : []), + // pre-warming + 'Suspend! [B]', + 'Suspend! [C]', ]); expect(ReactNoop).toMatchRenderedOutput( @@ -260,7 +260,7 @@ describe('ReactSuspenseList', () => { await act(() => C.resolve()); assertLog( - gate('enableSiblingPrerendering') + gate('alwaysThrottleRetries') ? ['Suspend! [B]', 'C', 'Suspend! [B]'] : ['C'], ); @@ -746,7 +746,8 @@ describe('ReactSuspenseList', () => { await waitForAll([ 'Suspend! [A]', 'Loading', - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput(Loading); @@ -919,8 +920,8 @@ describe('ReactSuspenseList', () => { 'Loading A', 'Loading B', 'Loading C', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput( @@ -932,12 +933,7 @@ describe('ReactSuspenseList', () => { ); await act(() => A.resolve()); - assertLog([ - 'A', - 'Suspend! [B]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []), - ]); + assertLog(['A', 'Suspend! [B]', 'Suspend! [B]']); expect(ReactNoop).toMatchRenderedOutput( <> @@ -990,8 +986,8 @@ describe('ReactSuspenseList', () => { 'Loading C', 'Loading B', 'Loading A', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C]'] : []), + // pre-warming + 'Suspend! [C]', ]); expect(ReactNoop).toMatchRenderedOutput( @@ -1006,8 +1002,8 @@ describe('ReactSuspenseList', () => { assertLog([ 'C', 'Suspend! [B]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []), + // pre-warming + 'Suspend! [B]', ]); expect(ReactNoop).toMatchRenderedOutput( @@ -1133,8 +1129,8 @@ describe('ReactSuspenseList', () => { 'A', 'C', 'Suspend! [E]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [E]'] : []), + // pre-warming + 'Suspend! [E]', ]); // We can now resolve the full head. @@ -1153,8 +1149,8 @@ describe('ReactSuspenseList', () => { assertLog([ 'E', 'Suspend! [F]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [F]'] : []), + // pre-warming + 'Suspend! [F]', ]); // In the tail we can resolve one-by-one. @@ -1296,10 +1292,9 @@ describe('ReactSuspenseList', () => { 'E', 'Suspend! [F]', 'Loading F', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [D]', 'Suspend! [F]'] - : []), + // pre-warming + 'Suspend! [D]', + 'Suspend! [F]', ]); // This will suspend, since the boundaries are avoided. Give them @@ -1347,8 +1342,8 @@ describe('ReactSuspenseList', () => { 'D', 'F', 'Suspend! [B]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []), + // pre-warming + 'Suspend! [B]', ]); // We can now resolve the full head. @@ -1369,8 +1364,8 @@ describe('ReactSuspenseList', () => { assertLog([ 'B', 'Suspend! [A]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); // In the tail we can resolve one-by-one. @@ -1493,8 +1488,8 @@ describe('ReactSuspenseList', () => { await waitForAll([ 'Suspend! [A]', 'Loading A', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput(Loading A); @@ -2007,8 +2002,8 @@ describe('ReactSuspenseList', () => { 'Suspend! [D]', 'Loading D', 'Loading E', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []), + // pre-warming + 'Suspend! [B]', ]); // This is suspended due to the update to D causing a loading state. @@ -2030,7 +2025,11 @@ describe('ReactSuspenseList', () => { await B.resolve(); - await waitForAll(['B', 'Suspend! [C]']); + await waitForAll([ + 'B', + 'Suspend! [C]', + ...(!gate('alwaysThrottleRetries') ? ['Suspend! [C]'] : []), + ]); // Incremental loading is suspended. jest.advanceTimersByTime(500); @@ -2425,8 +2424,8 @@ describe('ReactSuspenseList', () => { 'A', 'Suspend! [B]', 'Loading B', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []), + // pre-warming + 'Suspend! [B]', ]); expect(ReactNoop).toMatchRenderedOutput( @@ -2511,8 +2510,8 @@ describe('ReactSuspenseList', () => { await waitForAll([ 'Suspend! [A]', 'Loading A', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput(Loading A); }); @@ -2795,8 +2794,8 @@ describe('ReactSuspenseList', () => { 'B', 'Suspend! [C]', 'Fallback', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C]'] : []), + // pre-warming + 'Suspend! [C]', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -2805,7 +2804,9 @@ describe('ReactSuspenseList', () => { Loading... , ); - expect(onRender).toHaveBeenCalledTimes(1); + expect(onRender).toHaveBeenCalledTimes( + gate('alwaysThrottleRetries') ? 1 : 2, + ); // The treeBaseDuration should be the time to render each child. The last // one counts the fallback time. @@ -2828,12 +2829,18 @@ describe('ReactSuspenseList', () => { C , ); - expect(onRender).toHaveBeenCalledTimes(2); + expect(onRender).toHaveBeenCalledTimes( + gate('alwaysThrottleRetries') ? 2 : 3, + ); // actualDuration - expect(onRender.mock.calls[1][2]).toBe(1 + 4 + 5); + expect(onRender.mock.calls[1][2]).toBe( + gate('alwaysThrottleRetries') ? 1 + 4 + 5 : 5, + ); // treeBaseDuration - expect(onRender.mock.calls[1][3]).toBe(1 + 4 + 5); + expect(onRender.mock.calls[1][3]).toBe( + gate('alwaysThrottleRetries') ? 1 + 4 + 5 : 8, + ); ReactNoop.render(); @@ -2850,8 +2857,8 @@ describe('ReactSuspenseList', () => { 'Fallback', // Lastly we render the tail. 'Fallback', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C]'] : []), + // pre-warming + 'Suspend! [C]', ]); // Flush suspended time. @@ -2867,7 +2874,7 @@ describe('ReactSuspenseList', () => { , ); expect(onRender).toHaveBeenCalledTimes( - gate('enableSiblingPrerendering') ? 4 : 3, + gate('alwaysThrottleRetries') ? 4 : 5, ); // The treeBaseDuration should be the time to render the first two @@ -2877,16 +2884,20 @@ describe('ReactSuspenseList', () => { // with force fallback mode. // actualDuration - expect(onRender.mock.calls[2][2]).toBe((1 + 4 + 5 + 3) * 2 + 3); + expect(onRender.mock.calls[2][2]).toBe( + gate('alwaysThrottleRetries') ? (1 + 4 + 5 + 3) * 2 + 3 : 10, + ); // treeBaseDuration - expect(onRender.mock.calls[2][3]).toBe(1 + 4 + 3 + 3); + expect(onRender.mock.calls[2][3]).toBe( + gate('alwaysThrottleRetries') ? 1 + 4 + 3 + 3 : 10, + ); await act(() => C.resolve()); assertLog([ 'C', 'Suspend! [D]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [D]'] : []), + // pre-warming + 'Suspend! [D]', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -2897,21 +2908,16 @@ describe('ReactSuspenseList', () => { , ); - if (gate('enableSiblingPrerendering')) { - expect(onRender).toHaveBeenCalledTimes(6); - - // actualDuration - expect(onRender.mock.calls[5][2]).toBe(12); - // treeBaseDuration - expect(onRender.mock.calls[5][3]).toBe(1 + 4 + 5 + 3); - } else { - expect(onRender).toHaveBeenCalledTimes(4); + expect(onRender).toHaveBeenCalledTimes( + gate('alwaysThrottleRetries') ? 6 : 7, + ); - // actualDuration - expect(onRender.mock.calls[3][2]).toBe(5 + 12); - // treeBaseDuration - expect(onRender.mock.calls[3][3]).toBe(1 + 4 + 5 + 3); - } + // actualDuration + expect(onRender.mock.calls[5][2]).toBe( + gate('alwaysThrottleRetries') ? 12 : 17, + ); + // treeBaseDuration + expect(onRender.mock.calls[5][3]).toBe(1 + 4 + 5 + 3); }); // @gate enableSuspenseList @@ -2977,8 +2983,8 @@ describe('ReactSuspenseList', () => { 'Loading A', 'Loading B', 'Loading C', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput( @@ -2990,12 +2996,7 @@ describe('ReactSuspenseList', () => { ); await act(() => A.resolve()); - assertLog([ - 'A', - 'Suspend! [B]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []), - ]); + assertLog(['A', 'Suspend! [B]', 'Suspend! [B]']); expect(ReactNoop).toMatchRenderedOutput( <> A diff --git a/packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js b/packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js index c24169c43f1f2..196022d8a3834 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js @@ -139,8 +139,10 @@ describe('ReactSuspensePlaceholder', () => { 'A', 'Suspend! [B]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [B]', 'C'] : []), + // pre-warming + 'A', + 'Suspend! [B]', + 'C', ]); expect(ReactNoop).toMatchRenderedOutput('Loading...'); @@ -160,8 +162,9 @@ describe('ReactSuspensePlaceholder', () => { await waitForAll([ 'Suspend! [B2]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B2]', 'C'] : []), + // pre-warming + 'Suspend! [B2]', + 'C', ]); // Time out the update @@ -209,8 +212,10 @@ describe('ReactSuspensePlaceholder', () => { 'A', 'Suspend! [B]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [B]', 'C'] : []), + // pre-warming + 'A', + 'Suspend! [B]', + 'C', ]); expect(ReactNoop).not.toMatchRenderedOutput('ABC'); @@ -225,8 +230,10 @@ describe('ReactSuspensePlaceholder', () => { 'A', 'Suspend! [B2]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [B2]', 'C'] : []), + // pre-warming + 'A', + 'Suspend! [B2]', + 'C', ]); // Time out the update jest.advanceTimersByTime(750); @@ -264,8 +271,10 @@ describe('ReactSuspensePlaceholder', () => { 'a', 'Suspend! [b]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['a', 'Suspend! [b]', 'c'] : []), + // pre-warming + 'a', + 'Suspend! [b]', + 'c', ]); expect(ReactNoop).toMatchRenderedOutput(LOADING...); @@ -280,8 +289,9 @@ describe('ReactSuspensePlaceholder', () => { 'a', 'Suspend! [b2]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['a', 'Suspend! [b2]', 'c'] : []), + 'a', + 'Suspend! [b2]', + 'c', ]); // Time out the update jest.advanceTimersByTime(750); @@ -375,15 +385,17 @@ describe('ReactSuspensePlaceholder', () => { 'Suspending', 'Suspend! [Loaded]', 'Fallback', - - ...(gate('enableSiblingPrerendering') - ? ['Suspending', 'Suspend! [Loaded]', 'Text'] - : []), + // pre-warming + 'Suspending', + 'Suspend! [Loaded]', + 'Text', ]); // Since this is initial render we immediately commit the fallback. Another test below // deals with the update case where this suspends. expect(ReactNoop).toMatchRenderedOutput('Loading...'); - expect(onRender).toHaveBeenCalledTimes(1); + expect(onRender).toHaveBeenCalledTimes( + gate('alwaysThrottleRetries') ? 1 : 2, + ); // Initial mount only shows the "Loading..." Fallback. // The treeBaseDuration then should be 10ms spent rendering Fallback, @@ -401,21 +413,12 @@ describe('ReactSuspensePlaceholder', () => { ]); expect(ReactNoop).toMatchRenderedOutput('LoadedText'); - if (gate('enableSiblingPrerendering')) { - expect(onRender).toHaveBeenCalledTimes(3); - - // When the suspending data is resolved and our final UI is rendered, - // both times should include the 8ms re-rendering Suspending and AsyncText. - expect(onRender.mock.calls[2][2]).toBe(8); - expect(onRender.mock.calls[2][3]).toBe(8); - } else { - expect(onRender).toHaveBeenCalledTimes(2); - - // When the suspending data is resolved and our final UI is rendered, - // both times should include the 8ms re-rendering Suspending and AsyncText. - expect(onRender.mock.calls[1][2]).toBe(8); - expect(onRender.mock.calls[1][3]).toBe(8); - } + expect(onRender).toHaveBeenCalledTimes(3); + + // When the suspending data is resolved and our final UI is rendered, + // both times should include the 8ms re-rendering Suspending and AsyncText. + expect(onRender.mock.calls[2][2]).toBe(8); + expect(onRender.mock.calls[2][3]).toBe(8); }); }); @@ -536,14 +539,16 @@ describe('ReactSuspensePlaceholder', () => { 'Suspending', 'Suspend! [Loaded]', 'Fallback', - - ...(gate('enableSiblingPrerendering') - ? ['Suspending', 'Suspend! [Loaded]', 'Text'] - : []), + // pre-warming + 'Suspending', + 'Suspend! [Loaded]', + 'Text', ]); // Show the fallback UI. expect(ReactNoop).toMatchRenderedOutput('Loading...'); - expect(onRender).toHaveBeenCalledTimes(2); + expect(onRender).toHaveBeenCalledTimes( + gate('alwaysThrottleRetries') ? 2 : 3, + ); jest.advanceTimersByTime(900); @@ -579,15 +584,16 @@ describe('ReactSuspensePlaceholder', () => { 'Suspend! [Loaded]', 'Fallback', 'Suspend! [Sibling]', - - ...(gate('enableSiblingPrerendering') - ? ['Suspending', 'Suspend! [Loaded]', 'New', 'Suspend! [Sibling]'] - : []), + // pre-warming + 'Suspending', + 'Suspend! [Loaded]', + 'New', + 'Suspend! [Sibling]', ]); expect(ReactNoop).toMatchRenderedOutput('Loading...'); expect(onRender).toHaveBeenCalledTimes( - gate('enableSiblingPrerendering') ? 4 : 3, + gate('alwaysThrottleRetries') ? 4 : 5, ); // Resolve the pending promise. @@ -600,23 +606,17 @@ describe('ReactSuspensePlaceholder', () => { await waitForAll(['Suspending', 'Loaded', 'New', 'Sibling']); }); - if (gate('enableSiblingPrerendering')) { - expect(onRender).toHaveBeenCalledTimes(5); - - // When the suspending data is resolved and our final UI is rendered, - // both times should include the 6ms rendering Text, - // the 2ms rendering Suspending, and the 1ms rendering AsyncText. - expect(onRender.mock.calls[4][2]).toBe(9); - expect(onRender.mock.calls[4][3]).toBe(9); - } else { - expect(onRender).toHaveBeenCalledTimes(4); - - // When the suspending data is resolved and our final UI is rendered, - // both times should include the 6ms rendering Text, - // the 2ms rendering Suspending, and the 1ms rendering AsyncText. - expect(onRender.mock.calls[3][2]).toBe(9); - expect(onRender.mock.calls[3][3]).toBe(9); - } + expect(onRender).toHaveBeenCalledTimes( + gate('alwaysThrottleRetries') ? 5 : 6, + ); + + // When the suspending data is resolved and our final UI is rendered, + // both times should include the 6ms rendering Text, + // the 2ms rendering Suspending, and the 1ms rendering AsyncText. + expect(onRender.mock.calls[4][2]).toBe(9); + expect(onRender.mock.calls[4][3]).toBe( + gate('alwaysThrottleRetries') ? 9 : 10, + ); }); }); }); diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js index 79968949e3d99..3637093529f9a 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js @@ -296,7 +296,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { // A suspends 'Suspend! [A]', - ...(gate('enableSiblingPrerendering') ? ['B'] : []), + // pre-warming + 'B', + // end pre-warming // We immediately unwind and switch to a fallback without // rendering siblings. @@ -334,10 +336,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { 'Loading A...', 'Suspend! [B]', 'Loading B...', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [A]', 'Suspend! [B]'] - : []), + // pre-warming + 'Suspend! [A]', + 'Suspend! [B]', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -351,8 +352,7 @@ describe('ReactSuspenseWithNoopRenderer', () => { await act(() => resolveText('A')); assertLog([ 'A', - - ...(gate('enableSiblingPrerendering') + ...(gate('alwaysThrottleRetries') ? ['Suspend! [B]', 'Suspend! [B]'] : []), ]); @@ -395,9 +395,10 @@ describe('ReactSuspenseWithNoopRenderer', () => { await waitForAll([ 'A', 'Suspend! [B]', - - ...(gate('enableSiblingPrerendering') ? ['C', 'D'] : []), - + // pre-warming + 'C', + 'D', + // end pre-warming 'Loading...', ]); // Did not commit yet. @@ -509,8 +510,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { await waitForAll([ 'Suspend! [Result]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Result]'] : []), + // pre-warming + 'Suspend! [Result]', ]); expect(ReactNoop).toMatchRenderedOutput(); @@ -562,8 +563,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { 'A', 'Suspend! [1]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [1]'] : []), + // pre-warming + 'Suspend! [1]', ]); await act(() => resolveText('1')); @@ -631,9 +632,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { }); await waitForAll([ 'Suspend! [A]', - - ...(gate('enableSiblingPrerendering') ? ['B'] : []), - + // pre-warming + 'B', + // end pre-warming 'Loading...', ]); expect(ReactNoop).toMatchRenderedOutput(null); @@ -765,14 +766,10 @@ describe('ReactSuspenseWithNoopRenderer', () => { // The async content suspends 'Suspend! [Outer content]', 'Loading outer...', - - ...(gate('enableSiblingPrerendering') - ? [ - 'Suspend! [Outer content]', - 'Suspend! [Inner content]', - 'Loading inner...', - ] - : []), + // pre-warming + 'Suspend! [Outer content]', + 'Suspend! [Inner content]', + 'Loading inner...', ]); // The outer loading state finishes immediately. expect(ReactNoop).toMatchRenderedOutput( @@ -952,10 +949,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { await waitForAll([ 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [A]', 'Suspend! [B]'] - : []), + // pre-warming + 'Suspend! [A]', + 'Suspend! [B]', ]); expect(ReactNoop).toMatchRenderedOutput(); @@ -1068,10 +1064,10 @@ describe('ReactSuspenseWithNoopRenderer', () => { ReactNoop.render(); await waitForAll([ 'Suspend! [A]', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [A]', 'Suspend! [B]', 'Suspend! [C]'] - : []), + // pre-warming + 'Suspend! [A]', + 'Suspend! [B]', + 'Suspend! [C]', ]); expect(ReactNoop).toMatchRenderedOutput('Loading...'); @@ -1735,10 +1731,10 @@ describe('ReactSuspenseWithNoopRenderer', () => { // A suspends 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [A]', 'Suspend! [B]', 'Loading more...'] - : []), + // pre-warming + 'Suspend! [A]', + 'Suspend! [B]', + 'Loading more...', ]); expect(ReactNoop).toMatchRenderedOutput(); @@ -1753,8 +1749,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { // B suspends 'Suspend! [B]', 'Loading more...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []), + // pre-warming + 'Suspend! [B]', ]); // Because we've already been waiting for so long we've exceeded @@ -1799,10 +1795,10 @@ describe('ReactSuspenseWithNoopRenderer', () => { // A suspends 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [A]', 'Suspend! [B]', 'Loading more...'] - : []), + // pre-warming + 'Suspend! [A]', + 'Suspend! [B]', + 'Loading more...', ]); expect(ReactNoop).toMatchRenderedOutput(); @@ -1881,10 +1877,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { 'Loading A...', 'Suspend! [B]', 'Loading B...', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [A]', 'Suspend! [B]'] - : []), + // pre-warming + 'Suspend! [A]', + 'Suspend! [B]', ]); expect(ReactNoop).toMatchRenderedOutput( <> @@ -2035,8 +2030,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { assertLog([ 'Suspend! [A]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput('Loading...'); @@ -2046,10 +2041,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { assertLog([ 'Suspend! [A]', - - ...(gate('enableSiblingPrerendering') - ? ['Suspend! [A]', 'Suspend! [B]'] - : []), + // pre-warming + 'Suspend! [A]', + 'Suspend! [B]', ]); }); @@ -2108,8 +2102,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { assertLog([ 'Suspend! [A]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); await resolveText('A'); @@ -2138,8 +2132,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { assertLog([ 'Suspend! [A]', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); await resolveText('A'); @@ -2168,8 +2162,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { 'Foo', 'Suspend! [A]', 'Initial load...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]', 'B'] : []), + // pre-warming + 'Suspend! [A]', + 'B', ]); expect(ReactNoop).toMatchRenderedOutput(); @@ -2191,8 +2186,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { 'Suspend! [C]', 'Updating...', 'B', - - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [C]'] : []), + // pre-warming + 'A', + 'Suspend! [C]', ]); // Flush to skip suspended time. Scheduler.unstable_advanceTime(600); @@ -2240,8 +2236,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { 'Suspend! [A]', 'B', // null - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); expect(ReactNoop).toMatchRenderedOutput(); @@ -2263,8 +2259,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { 'Suspend! [C]', // null 'B', - - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [C]'] : []), + // pre-warming + 'A', + 'Suspend! [C]', ]); // Flush to skip suspended time. Scheduler.unstable_advanceTime(600); @@ -2312,8 +2309,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { 'A', 'Suspend! [B]', 'Loading B...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []), + // pre-warming + 'Suspend! [B]', ]); // Flush to skip suspended time. Scheduler.unstable_advanceTime(600); @@ -2394,8 +2391,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { 'A', 'Suspend! [B]', // Null - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []), + // pre-warming + 'Suspend! [B]', ]); // Still suspended. expect(ReactNoop).toMatchRenderedOutput(); @@ -2424,8 +2421,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { await waitForAll([ 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); // Only a short time is needed to unsuspend the initial loading state. Scheduler.unstable_advanceTime(400); @@ -2478,8 +2475,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { await waitForAll([ 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); // Only a short time is needed to unsuspend the initial loading state. Scheduler.unstable_advanceTime(400); @@ -2538,8 +2535,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { await waitForAll([ 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); // Only a short time is needed to unsuspend the initial loading state. Scheduler.unstable_advanceTime(400); @@ -2587,8 +2584,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { await waitForAll([ 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); // Only a short time is needed to unsuspend the initial loading state. Scheduler.unstable_advanceTime(400); @@ -2652,8 +2649,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { await waitForAll([ 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); // Only a short time is needed to unsuspend the initial loading state. Scheduler.unstable_advanceTime(400); @@ -2727,8 +2724,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { await waitForAll([ 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []), + // pre-warming + 'Suspend! [A]', ]); // Only a short time is needed to unsuspend the initial loading state. Scheduler.unstable_advanceTime(400); @@ -2794,8 +2791,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { 'Hi!', 'Suspend! [A]', 'Loading...', - - ...(gate('enableSiblingPrerendering') ? ['Hi!', 'Suspend! [A]'] : []), + // pre-warming + 'Hi!', + 'Suspend! [A]', ]); await act(() => resolveText('A')); assertLog(['Hi!', 'A']); @@ -3117,73 +3115,6 @@ describe('ReactSuspenseWithNoopRenderer', () => { }, ); - // TODO: This test is substantially different when sibling prerendering is - // enabled because we never work on Idle updates if there are pending retries. - // This was already an issue before the enableSiblingPrerendering change but - // it's exacerbated by the fact that we schedule a retry immediately. I'm not - // going to bother to update this test for now, though, because Idle updates - // aren't actually used and should probably just be deleted unless/until we - // finish the feature. Feel free to delete if needed. - // @gate !enableSiblingPrerendering - // @gate enableLegacyCache - it( - 'multiple updates originating inside a Suspense boundary at different ' + - 'priority levels are not dropped, including Idle updates', - async () => { - const {useState} = React; - const root = ReactNoop.createRoot(); - - function Parent() { - return ( - <> - }> - - - - ); - } - - let setText; - function Child() { - const [text, _setText] = useState('A'); - setText = _setText; - return ; - } - - await seedNextTextCache('A'); - await act(() => { - root.render(); - }); - assertLog(['A']); - expect(root).toMatchRenderedOutput(); - - await act(async () => { - // Schedule two updates that originate inside the Suspense boundary. - // The first one causes the boundary to suspend. The second one is at - // lower priority and unsuspends it by hiding the async component. - setText('B'); - - await resolveText('C'); - ReactNoop.idleUpdates(() => { - setText('C'); - }); - - // First we attempt the high pri update. It suspends. - await waitForPaint(['Suspend! [B]', 'Loading...']); - expect(root).toMatchRenderedOutput( - <> -