@samitouri / QOS-React-1 / commits / 4ca97e4891

Clean up enableSiblingPrerendering flag (#32319)

Jack Pope committed May 8, 2025 at 20:49 UTC 4ca97e4891b6a664b4c3a183f16b81139655ff57
46 files changed +866 -1178
packages/react-cache/src/__tests__/ReactCacheOld-test.internal.js
+35 -25
@@ -126,8 +126,8 @@ describe('ReactCache', () => {
126 await waitForAll([
127 'Suspend! [Hi]',
128 'Loading...',
129 -
130 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Hi]'] : []),
129 + // pre-warming
130 + 'Suspend! [Hi]',
131 ]);
132
133 jest.advanceTimersByTime(100);
@@ -150,8 +150,8 @@ describe('ReactCache', () => {
150 await waitForAll([
151 'Suspend! [Hi]',
152 'Loading...',
153 -
154 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Hi]'] : []),
153 + // pre-warming
154 + 'Suspend! [Hi]',
155 ]);
156
157 textResourceShouldFail = true;
@@ -195,8 +195,8 @@ describe('ReactCache', () => {
195 await waitForAll([
196 'App',
197 'Loading...',
198 -
199 - ...(gate('enableSiblingPrerendering') ? ['App'] : []),
198 + // pre-warming
199 + 'App',
200 ]);
201 assertConsoleErrorDev([
202 'Invalid key type. Expected a string, number, symbol, or ' +
@@ -204,27 +204,24 @@ describe('ReactCache', () => {
204 'To use non-primitive values as keys, you must pass a hash ' +
205 'function as the second argument to createResource().\n' +
206 ' in App (at **)',
207 - ...(gate('enableSiblingPrerendering')
208 - ? [
209 - 'Invalid key type. Expected a string, number, symbol, or ' +
210 - "boolean, but instead received: [ 'Hi', 100 ]\n\n" +
211 - 'To use non-primitive values as keys, you must pass a hash ' +
212 - 'function as the second argument to createResource().\n' +
213 - ' in App (at **)',
214 - ]
215 - : []),
207 +
208 + // pre-warming
209 + 'Invalid key type. Expected a string, number, symbol, or ' +
210 + "boolean, but instead received: [ 'Hi', 100 ]\n\n" +
211 + 'To use non-primitive values as keys, you must pass a hash ' +
212 + 'function as the second argument to createResource().\n' +
213 + ' in App (at **)',
214 ]);
215 } else {
216 await waitForAll([
217 'App',
218 'Loading...',
221 -
222 - ...(gate('enableSiblingPrerendering') ? ['App'] : []),
219 + // pre-warming
220 + 'App',
221 ]);
222 }
223 });
224
227 - // @gate enableSiblingPrerendering
225 it('evicts least recently used values', async () => {
226 ReactCache.unstable_setGlobalCacheLimit(3);
227
@@ -240,15 +237,28 @@ describe('ReactCache', () => {
237 await waitForPaint(['Suspend! [1]', 'Loading...']);
238 jest.advanceTimersByTime(100);
239 assertLog(['Promise resolved [1]']);
243 - await waitForAll([1, 'Suspend! [2]']);
240 + await waitForAll([
241 + 1,
242 + 'Suspend! [2]',
243 + ...(gate('alwaysThrottleRetries')
244 + ? []
245 + : [1, 'Suspend! [2]', 'Suspend! [3]']),
246 + ]);
247
248 jest.advanceTimersByTime(100);
246 - assertLog(['Promise resolved [2]']);
247 - await waitForAll([1, 2, 'Suspend! [3]']);
249 + assertLog([
250 + 'Promise resolved [2]',
251 + ...(gate('alwaysThrottleRetries') ? [] : ['Promise resolved [3]']),
252 + ]);
253 + await waitForAll([
254 + 1,
255 + 2,
256 + ...(gate('alwaysThrottleRetries') ? ['Suspend! [3]'] : [3]),
257 + ]);
258
259 jest.advanceTimersByTime(100);
250 - assertLog(['Promise resolved [3]']);
251 - await waitForAll([1, 2, 3]);
260 + assertLog(gate('alwaysThrottleRetries') ? ['Promise resolved [3]'] : []);
261 + await waitForAll(gate('alwaysThrottleRetries') ? [1, 2, 3] : []);
262
263 await act(() => jest.advanceTimersByTime(100));
264 expect(root).toMatchRenderedOutput('123');
@@ -378,8 +388,8 @@ describe('ReactCache', () => {
388 await waitForAll([
389 'Suspend! [Hi]',
390 'Loading...',
381 -
382 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Hi]'] : []),
391 + // pre-warming
392 + 'Suspend! [Hi]',
393 ]);
394
395 resolveThenable('Hi');
packages/react-devtools-shared/src/__tests__/TimelineProfiler-test.js
+9 -63
@@ -15,22 +15,11 @@ import {
15 normalizeCodeLocInfo,
16 } from './utils';
17
18 -import {ReactVersion} from '../../../../ReactVersions';
19 -import semver from 'semver';
20 -
18 let React = require('react');
19 let Scheduler;
20 let store;
21 let utils;
22
26 -// TODO: This is how other DevTools tests access the version but we should find
27 -// a better solution for this
28 -const ReactVersionTestingAgainst = process.env.REACT_VERSION || ReactVersion;
29 -// Disabling this while the flag is off in experimental. Leaving the logic so we can
30 -// restore the behavior when we turn the flag back on.
31 -const enableSiblingPrerendering =
32 - false && semver.gte(ReactVersionTestingAgainst, '19.0.0');
33 -
23 // This flag is on experimental which disables timeline profiler.
24 const enableComponentPerformanceTrack =
25 React.version.startsWith('19') && React.version.includes('experimental');
@@ -1678,8 +1667,8 @@ describe('Timeline profiler', () => {
1667
1668 await waitForAll([
1669 'suspended',
1681 -
1682 - ...(enableSiblingPrerendering ? ['suspended'] : []),
1670 + // pre-warming
1671 + 'suspended',
1672 ]);
1673
1674 Scheduler.unstable_advanceTime(10);
@@ -1691,8 +1680,7 @@ describe('Timeline profiler', () => {
1680 const timelineData = stopProfilingAndGetTimelineData();
1681
1682 // Verify the Suspense event and duration was recorded.
1694 - if (enableSiblingPrerendering) {
1695 - expect(timelineData.suspenseEvents).toMatchInlineSnapshot(`
1683 + expect(timelineData.suspenseEvents).toMatchInlineSnapshot(`
1684 [
1685 {
1686 "componentName": "Example",
@@ -1720,29 +1708,11 @@ describe('Timeline profiler', () => {
1708 },
1709 ]
1710 `);
1723 - } else {
1724 - const suspenseEvent = timelineData.suspenseEvents[0];
1725 - expect(suspenseEvent).toMatchInlineSnapshot(`
1726 - {
1727 - "componentName": "Example",
1728 - "depth": 0,
1729 - "duration": 10,
1730 - "id": "0",
1731 - "phase": "mount",
1732 - "promiseName": "",
1733 - "resolution": "resolved",
1734 - "timestamp": 10,
1735 - "type": "suspense",
1736 - "warning": null,
1737 - }
1738 - `);
1739 - }
1711
1712 // There should be two batches of renders: Suspeneded and resolved.
1713 expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);
1743 - expect(timelineData.componentMeasures).toHaveLength(
1744 - enableSiblingPrerendering ? 3 : 2,
1745 - );
1714 + // An additional measure with pre-warming
1715 + expect(timelineData.componentMeasures).toHaveLength(3);
1716 });
1717
1718 it('should mark concurrent render with suspense that rejects', async () => {
@@ -1769,11 +1739,7 @@ describe('Timeline profiler', () => {
1739 </React.Suspense>,
1740 );
1741
1772 - await waitForAll([
1773 - 'suspended',
1774 -
1775 - ...(enableSiblingPrerendering ? ['suspended'] : []),
1776 - ]);
1742 + await waitForAll(['suspended', 'suspended']);
1743
1744 Scheduler.unstable_advanceTime(10);
1745 rejectFn();
@@ -1784,8 +1750,7 @@ describe('Timeline profiler', () => {
1750 const timelineData = stopProfilingAndGetTimelineData();
1751
1752 // Verify the Suspense event and duration was recorded.
1787 - if (enableSiblingPrerendering) {
1788 - expect(timelineData.suspenseEvents).toMatchInlineSnapshot(`
1753 + expect(timelineData.suspenseEvents).toMatchInlineSnapshot(`
1754 [
1755 {
1756 "componentName": "Example",
@@ -1813,30 +1778,11 @@ describe('Timeline profiler', () => {
1778 },
1779 ]
1780 `);
1816 - } else {
1817 - expect(timelineData.suspenseEvents).toHaveLength(1);
1818 - const suspenseEvent = timelineData.suspenseEvents[0];
1819 - expect(suspenseEvent).toMatchInlineSnapshot(`
1820 - {
1821 - "componentName": "Example",
1822 - "depth": 0,
1823 - "duration": 10,
1824 - "id": "0",
1825 - "phase": "mount",
1826 - "promiseName": "",
1827 - "resolution": "rejected",
1828 - "timestamp": 10,
1829 - "type": "suspense",
1830 - "warning": null,
1831 - }
1832 - `);
1833 - }
1781
1782 // There should be two batches of renders: Suspeneded and resolved.
1783 expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);
1837 - expect(timelineData.componentMeasures).toHaveLength(
1838 - enableSiblingPrerendering ? 3 : 2,
1839 - );
1784 + // An additional measure with pre-warming
1785 + expect(timelineData.componentMeasures).toHaveLength(3);
1786 });
1787
1788 it('should mark cascading class component state updates', async () => {
packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.js
+2 -1
@@ -751,7 +751,8 @@ describe('ReactDOMFiberAsync', () => {
751 // Because it suspended, it remains on the current path
752 expect(div.textContent).toBe('/path/a');
753 });
754 - assertLog(gate('enableSiblingPrerendering') ? ['Suspend! [/path/b]'] : []);
754 + // pre-warming
755 + assertLog(['Suspend! [/path/b]']);
756
757 await act(async () => {
758 resolvePromise();
packages/react-dom/src/__tests__/ReactDOMForm-test.js
+8 -8
@@ -1437,8 +1437,8 @@ describe('ReactDOMForm', () => {
1437 assertLog([
1438 'Suspend! [Count: 0]',
1439 'Loading...',
1440 -
1441 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Count: 0]'] : []),
1440 + // pre-warming
1441 + 'Suspend! [Count: 0]',
1442 ]);
1443 await act(() => resolveText('Count: 0'));
1444 assertLog(['Count: 0']);
@@ -1448,8 +1448,8 @@ describe('ReactDOMForm', () => {
1448 assertLog([
1449 'Suspend! [Count: 1]',
1450 'Loading...',
1451 -
1452 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Count: 1]'] : []),
1451 + // pre-warming
1452 + 'Suspend! [Count: 1]',
1453 ]);
1454 expect(container.textContent).toBe('Loading...');
1455
@@ -1482,8 +1482,8 @@ describe('ReactDOMForm', () => {
1482 await act(() => root.render(<App />));
1483 assertLog([
1484 'Suspend! [Count: 0]',
1485 -
1486 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Count: 0]'] : []),
1485 + // pre-warming
1486 + 'Suspend! [Count: 0]',
1487 ]);
1488 await act(() => resolveText('Count: 0'));
1489 assertLog(['Count: 0']);
@@ -1501,8 +1501,8 @@ describe('ReactDOMForm', () => {
1501 ]);
1502 assertLog([
1503 'Suspend! [Count: 1]',
1504 -
1505 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Count: 1]'] : []),
1504 + // pre-warming
1505 + 'Suspend! [Count: 1]',
1506 ]);
1507 expect(container.textContent).toBe('Count: 0');
1508 });
packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js
+4 -2
@@ -164,8 +164,10 @@ describe('ReactDOMSuspensePlaceholder', () => {
164 'A',
165 'Suspend! [B]',
166 'Loading...',
167 -
168 - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [B]', 'C'] : []),
167 + // pre-warming
168 + 'A',
169 + 'Suspend! [B]',
170 + 'C',
171 ]);
172 await act(() => {
173 resolveText('B');
packages/react-dom/src/__tests__/ReactWrongReturnPointer-test.js
+4 -4
@@ -196,8 +196,8 @@ test('regression (#20932): return pointer is correct before entering deleted tre
196 'Suspend! [0]',
197 'Loading Async...',
198 'Loading Tail...',
199 -
200 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [0]'] : []),
199 + // pre-warming
200 + 'Suspend! [0]',
201 ]);
202 await act(() => {
203 resolveText(0);
@@ -211,7 +211,7 @@ test('regression (#20932): return pointer is correct before entering deleted tre
211 'Loading Async...',
212 'Suspend! [1]',
213 'Loading Async...',
214 -
215 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [1]'] : []),
214 + // pre-warming
215 + 'Suspend! [1]',
216 ]);
217 });
packages/react-reconciler/src/ReactFiberCompleteWork.js
+1 -4
@@ -41,7 +41,6 @@ import {
41 enableRenderableContext,
42 passChildrenWhenCloningPersistedNodes,
43 disableLegacyMode,
44 - enableSiblingPrerendering,
44 enableViewTransition,
45 enableSuspenseyImages,
46 } from 'shared/ReactFeatureFlags';
@@ -667,9 +666,7 @@ function scheduleRetryEffect(
666
667 // Track the lanes that have been scheduled for an immediate retry so that
668 // we can mark them as suspended upon committing the root.
670 - if (enableSiblingPrerendering) {
671 - markSpawnedRetryLane(retryLane);
672 - }
669 + markSpawnedRetryLane(retryLane);
670 }
671 }
672
packages/react-reconciler/src/ReactFiberLane.js
+11 -17
@@ -27,7 +27,6 @@ import {
27 transitionLaneExpirationMs,
28 retryLaneExpirationMs,
29 disableLegacyMode,
30 - enableSiblingPrerendering,
30 } from 'shared/ReactFeatureFlags';
31 import {isDevToolsPresent} from './ReactFiberDevToolsHook';
32 import {clz32} from './clz32';
@@ -267,13 +266,11 @@ export function getNextLanes(
266 if (nonIdlePingedLanes !== NoLanes) {
267 nextLanes = getHighestPriorityLanes(nonIdlePingedLanes);
268 } else {
270 - if (enableSiblingPrerendering) {
271 - // Nothing has been pinged. Check for lanes that need to be prewarmed.
272 - if (!rootHasPendingCommit) {
273 - const lanesToPrewarm = nonIdlePendingLanes & ~warmLanes;
274 - if (lanesToPrewarm !== NoLanes) {
275 - nextLanes = getHighestPriorityLanes(lanesToPrewarm);
276 - }
269 + // Nothing has been pinged. Check for lanes that need to be prewarmed.
270 + if (!rootHasPendingCommit) {
271 + const lanesToPrewarm = nonIdlePendingLanes & ~warmLanes;
272 + if (lanesToPrewarm !== NoLanes) {
273 + nextLanes = getHighestPriorityLanes(lanesToPrewarm);
274 }
275 }
276 }
@@ -293,13 +290,11 @@ export function getNextLanes(
290 if (pingedLanes !== NoLanes) {
291 nextLanes = getHighestPriorityLanes(pingedLanes);
292 } else {
296 - if (enableSiblingPrerendering) {
297 - // Nothing has been pinged. Check for lanes that need to be prewarmed.
298 - if (!rootHasPendingCommit) {
299 - const lanesToPrewarm = pendingLanes & ~warmLanes;
300 - if (lanesToPrewarm !== NoLanes) {
301 - nextLanes = getHighestPriorityLanes(lanesToPrewarm);
302 - }
293 + // Nothing has been pinged. Check for lanes that need to be prewarmed.
294 + if (!rootHasPendingCommit) {
295 + const lanesToPrewarm = pendingLanes & ~warmLanes;
296 + if (lanesToPrewarm !== NoLanes) {
297 + nextLanes = getHighestPriorityLanes(lanesToPrewarm);
298 }
299 }
300 }
@@ -802,7 +797,7 @@ export function markRootSuspended(
797 root.suspendedLanes |= suspendedLanes;
798 root.pingedLanes &= ~suspendedLanes;
799
805 - if (enableSiblingPrerendering && didAttemptEntireTree) {
800 + if (didAttemptEntireTree) {
801 // Mark these lanes as warm so we know there's nothing else to work on.
802 root.warmLanes |= suspendedLanes;
803 } else {
@@ -913,7 +908,6 @@ export function markRootFinished(
908 // suspended) instead of the regular mode (i.e. unwind and skip the siblings
909 // as soon as something suspends to unblock the rest of the update).
910 if (
916 - enableSiblingPrerendering &&
911 suspendedRetryLanes !== NoLanes &&
912 // Note that we only do this if there were no updates since we started
913 // rendering. This mirrors the logic in markRootUpdated — whenever we
packages/react-reconciler/src/ReactFiberRootScheduler.js
+1 -2
@@ -18,7 +18,6 @@ import {
18 enableProfilerTimer,
19 enableProfilerNestedUpdatePhase,
20 enableComponentPerformanceTrack,
21 - enableSiblingPrerendering,
21 enableYieldingBeforePassive,
22 enableGestureTransition,
23 } from 'shared/ReactFeatureFlags';
@@ -381,7 +380,7 @@ function scheduleTaskForRootDuringMicrotask(
380 // If we're prerendering, then we should use the concurrent work loop
381 // even if the lanes are synchronous, so that prerendering never blocks
382 // the main thread.
384 - !(enableSiblingPrerendering && checkIfRootIsPrerendering(root, nextLanes))
383 + !checkIfRootIsPrerendering(root, nextLanes)
384 ) {
385 // Synchronous work is always flushed at the end of the microtask, so we
386 // don't need to schedule an additional task.
packages/react-reconciler/src/ReactFiberWorkLoop.js
+51 -73
@@ -47,7 +47,6 @@ import {
47 enableInfiniteRenderLoopDetection,
48 disableLegacyMode,
49 disableDefaultPropsExceptForClasses,
50 - enableSiblingPrerendering,
50 enableComponentPerformanceTrack,
51 enableYieldingBeforePassive,
52 enableThrottledScheduling,
@@ -1061,7 +1060,7 @@ export function performWorkOnRoot(
1060 // the main thread.
1061 // TODO: We should consider doing this whenever a sync lane is suspended,
1062 // even for regular pings.
1064 - (enableSiblingPrerendering && checkIfRootIsPrerendering(root, lanes));
1063 + checkIfRootIsPrerendering(root, lanes);
1064
1065 let exitStatus = shouldTimeSlice
1066 ? renderRootConcurrent(root, lanes)
@@ -1072,11 +1071,7 @@ export function performWorkOnRoot(
1071 do {
1072 if (exitStatus === RootInProgress) {
1073 // Render phase is still in progress.
1075 - if (
1076 - enableSiblingPrerendering &&
1077 - workInProgressRootIsPrerendering &&
1078 - !shouldTimeSlice
1079 - ) {
1074 + if (workInProgressRootIsPrerendering && !shouldTimeSlice) {
1075 // We're in prerendering mode, but time slicing is not enabled. This
1076 // happens when something suspends during a synchronous update. Exit the
1077 // 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 {
2052 // API for suspending. This implementation detail can change later, once we
2053 // deprecate the old API in favor of `use`.
2054 thrownValue = getSuspendedThenable();
2060 - workInProgressSuspendedReason =
2061 - // TODO: Suspending the work loop during the render phase is
2062 - // currently not compatible with sibling prerendering. We will add
2063 - // this optimization back in a later step.
2064 - !enableSiblingPrerendering &&
2065 - shouldRemainOnPreviousScreen() &&
2066 - // Check if there are other pending updates that might possibly unblock this
2067 - // component from suspending. This mirrors the check in
2068 - // renderDidSuspendDelayIfPossible. We should attempt to unify them somehow.
2069 - // TODO: Consider unwinding immediately, using the
2070 - // SuspendedOnHydration mechanism.
2071 - !includesNonIdleWork(workInProgressRootSkippedLanes) &&
2072 - !includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes)
2073 - ? // Suspend work loop until data resolves
2074 - thrownValue === SuspenseActionException
2075 - ? SuspendedOnAction
2076 - : SuspendedOnData
2077 - : // Don't suspend work loop, except to check if the data has
2078 - // immediately resolved (i.e. in a microtask). Otherwise, trigger the
2079 - // nearest Suspense fallback.
2080 - SuspendedOnImmediate;
2055 + // TODO: Suspending the work loop during the render phase is
2056 + // currently not compatible with sibling prerendering. We will add
2057 + // this optimization back in a later step.
2058 + // Don't suspend work loop, except to check if the data has
2059 + // immediately resolved (i.e. in a microtask). Otherwise, trigger the
2060 + // nearest Suspense fallback.
2061 + workInProgressSuspendedReason = SuspendedOnImmediate;
2062 } else if (thrownValue === SuspenseyCommitException) {
2063 thrownValue = getSuspendedThenable();
2064 workInProgressSuspendedReason = SuspendedOnInstance;
@@ -2421,7 +2402,6 @@ function renderRootSync(
2402 workInProgressThrownValue = null;
2403 throwAndUnwindWorkLoop(root, unitOfWork, thrownValue, reason);
2404 if (
2424 - enableSiblingPrerendering &&
2405 shouldYieldForPrerendering &&
2406 workInProgressRootIsPrerendering
2407 ) {
@@ -3008,56 +2988,54 @@ function throwAndUnwindWorkLoop(
2988 if (unitOfWork.flags & Incomplete) {
2989 // Unwind the stack until we reach the nearest boundary.
2990 let skipSiblings;
3011 - if (!enableSiblingPrerendering) {
2991 +
2992 + if (
2993 + // The current algorithm for both hydration and error handling assumes
2994 + // that the tree is rendered sequentially. So we always skip the siblings.
2995 + getIsHydrating() ||
2996 + suspendedReason === SuspendedOnError
2997 + ) {
2998 skipSiblings = true;
3013 - } else {
2999 + // We intentionally don't set workInProgressRootDidSkipSuspendedSiblings,
3000 + // because we don't want to trigger another prerender attempt.
3001 + } else if (
3002 + // Check whether this is a prerender
3003 + !workInProgressRootIsPrerendering &&
3004 + // Offscreen rendering is also a form of speculative rendering
3005 + !includesSomeLane(workInProgressRootRenderLanes, OffscreenLane)
3006 + ) {
3007 + // This is not a prerender. Skip the siblings during this render. A
3008 + // separate prerender will be scheduled for later.
3009 + skipSiblings = true;
3010 + workInProgressRootDidSkipSuspendedSiblings = true;
3011 +
3012 + // Because we're skipping the siblings, schedule an immediate retry of
3013 + // this boundary.
3014 + //
3015 + // The reason we do this is because a prerender is only scheduled when
3016 + // the root is blocked from committing, i.e. RootSuspendedWithDelay.
3017 + // When the root is not blocked, as in the case when we render a
3018 + // fallback, the original lane is considered to be finished, and
3019 + // therefore no longer in need of being prerendered. However, there's
3020 + // still a pending retry that will happen once the data streams in.
3021 + // We should start rendering that even before the data streams in so we
3022 + // can prerender the siblings.
3023 if (
3015 - // The current algorithm for both hydration and error handling assumes
3016 - // that the tree is rendered sequentially. So we always skip the siblings.
3017 - getIsHydrating() ||
3018 - suspendedReason === SuspendedOnError
3019 - ) {
3020 - skipSiblings = true;
3021 - // We intentionally don't set workInProgressRootDidSkipSuspendedSiblings,
3022 - // because we don't want to trigger another prerender attempt.
3023 - } else if (
3024 - // Check whether this is a prerender
3025 - !workInProgressRootIsPrerendering &&
3026 - // Offscreen rendering is also a form of speculative rendering
3027 - !includesSomeLane(workInProgressRootRenderLanes, OffscreenLane)
3024 + suspendedReason === SuspendedOnData ||
3025 + suspendedReason === SuspendedOnAction ||
3026 + suspendedReason === SuspendedOnImmediate ||
3027 + suspendedReason === SuspendedOnDeprecatedThrowPromise
3028 ) {
3029 - // This is not a prerender. Skip the siblings during this render. A
3030 - // separate prerender will be scheduled for later.
3031 - skipSiblings = true;
3032 - workInProgressRootDidSkipSuspendedSiblings = true;
3033 -
3034 - // Because we're skipping the siblings, schedule an immediate retry of
3035 - // this boundary.
3036 - //
3037 - // The reason we do this is because a prerender is only scheduled when
3038 - // the root is blocked from committing, i.e. RootSuspendedWithDelay.
3039 - // When the root is not blocked, as in the case when we render a
3040 - // fallback, the original lane is considered to be finished, and
3041 - // therefore no longer in need of being prerendered. However, there's
3042 - // still a pending retry that will happen once the data streams in.
3043 - // We should start rendering that even before the data streams in so we
3044 - // can prerender the siblings.
3045 - if (
3046 - suspendedReason === SuspendedOnData ||
3047 - suspendedReason === SuspendedOnAction ||
3048 - suspendedReason === SuspendedOnImmediate ||
3049 - suspendedReason === SuspendedOnDeprecatedThrowPromise
3050 - ) {
3051 - const boundary = getSuspenseHandler();
3052 - if (boundary !== null && boundary.tag === SuspenseComponent) {
3053 - boundary.flags |= ScheduleRetry;
3054 - }
3029 + const boundary = getSuspenseHandler();
3030 + if (boundary !== null && boundary.tag === SuspenseComponent) {
3031 + boundary.flags |= ScheduleRetry;
3032 }
3056 - } else {
3057 - // This is a prerender. Don't skip the siblings.
3058 - skipSiblings = false;
3033 }
3034 + } else {
3035 + // This is a prerender. Don't skip the siblings.
3036 + skipSiblings = false;
3037 }
3038 +
3039 unwindUnitOfWork(unitOfWork, skipSiblings);
3040 } else {
3041 // Although the fiber suspended, we're intentionally going to commit it in
packages/react-reconciler/src/__tests__/ActivityLegacySuspense-test.js
+2 -3
@@ -205,9 +205,8 @@ describe('Activity Suspense', () => {
205 });
206 assertLog([
207 'Suspend! [hello]',
208 - ...(gate(flags => flags.enableSiblingPrerendering)
209 - ? ['Suspend! [hello]']
210 - : []),
208 + // pre-warming
209 + 'Suspend! [hello]',
210 ]);
211 expect(root).toMatchRenderedOutput('Loading');
212
packages/react-reconciler/src/__tests__/ActivityStrictMode-test.js
+4 -5
@@ -240,11 +240,10 @@ describe('Activity StrictMode', () => {
240 'Parent mount',
241 'Parent unmount',
242 'Parent mount',
243 -
244 - ...(gate('enableSiblingPrerendering')
245 - ? ['Child rendered', 'Child suspended']
246 - : []),
247 -
243 + // pre-warming
244 + 'Child rendered',
245 + 'Child suspended',
246 + // end pre-warming
247 '------------------------------',
248 'Child rendered',
249 'Child rendered',
packages/react-reconciler/src/__tests__/ActivitySuspense-test.js
+9 -6
@@ -202,9 +202,8 @@ describe('Activity Suspense', () => {
202 });
203 assertLog([
204 'Suspend! [hello]',
205 - ...(gate(flags => flags.enableSiblingPrerendering)
206 - ? ['Suspend! [hello]']
207 - : []),
205 + // pre-warming
206 + 'Suspend! [hello]',
207 ]);
208 expect(root).toMatchRenderedOutput('Loading');
209
@@ -265,7 +264,8 @@ describe('Activity Suspense', () => {
264 assertLog([
265 'Open',
266 'Suspend! [Async]',
268 - ...(gate(flags => flags.enableSiblingPrerendering) ? ['Loading...'] : []),
267 + // pre-warming
268 + 'Loading...',
269 ]);
270 // It should suspend with delay to prevent the already-visible Suspense
271 // boundary from switching to a fallback
@@ -276,7 +276,9 @@ describe('Activity Suspense', () => {
276 await resolveText('Async');
277 });
278 assertLog([
279 - ...(gate(flags => flags.enableSiblingPrerendering) ? ['Open'] : []),
279 + // pre-warming
280 + 'Open',
281 + // end pre-warming
282 'Async',
283 ]);
284 expect(root).toMatchRenderedOutput(
@@ -333,7 +335,8 @@ describe('Activity Suspense', () => {
335 assertLog([
336 'Open',
337 'Suspend! [Async]',
336 - ...(gate(flags => flags.enableSiblingPrerendering) ? ['Loading...'] : []),
338 + // pre-warming
339 + 'Loading...',
340 ]);
341 // It should suspend with delay to prevent the already-visible Suspense
342 // boundary from switching to a fallback
packages/react-reconciler/src/__tests__/ReactActWarnings-test.js
+15 -17
@@ -367,8 +367,8 @@ describe('act warnings', () => {
367 assertLog([
368 'Suspend! [Async]',
369 'Loading...',
370 -
371 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Async]'] : []),
370 + // pre-warming
371 + 'Suspend! [Async]',
372 ]);
373 expect(root).toMatchRenderedOutput('Loading...');
374
@@ -388,21 +388,19 @@ describe('act warnings', () => {
388 "This ensures that you're testing the behavior the user would see in the browser. " +
389 'Learn more at https://react.dev/link/wrap-tests-with-act',
390
391 - ...(gate('enableSiblingPrerendering')
392 - ? [
393 - 'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\n' +
394 - '\n' +
395 - 'When testing, code that resolves suspended data should be wrapped into act(...):\n' +
396 - '\n' +
397 - 'act(() => {\n' +
398 - ' /* finish loading suspended data */\n' +
399 - '});\n' +
400 - '/* assert on the output */\n' +
401 - '\n' +
402 - "This ensures that you're testing the behavior the user would see in the browser. " +
403 - 'Learn more at https://react.dev/link/wrap-tests-with-act',
404 - ]
405 - : []),
391 + // pre-warming
392 +
393 + 'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\n' +
394 + '\n' +
395 + 'When testing, code that resolves suspended data should be wrapped into act(...):\n' +
396 + '\n' +
397 + 'act(() => {\n' +
398 + ' /* finish loading suspended data */\n' +
399 + '});\n' +
400 + '/* assert on the output */\n' +
401 + '\n' +
402 + "This ensures that you're testing the behavior the user would see in the browser. " +
403 + 'Learn more at https://react.dev/link/wrap-tests-with-act',
404 ],
405
406 {withoutStack: true},
packages/react-reconciler/src/__tests__/ReactAsyncActions-test.js
+5 -6
@@ -301,10 +301,9 @@ describe('ReactAsyncActions', () => {
301 'Async action ended',
302 'Pending: false',
303 'Suspend! [A1]',
304 -
305 - ...(gate('enableSiblingPrerendering')
306 - ? ['Suspend! [B1]', 'Suspend! [C1]']
307 - : []),
304 + // pre-warming
305 + 'Suspend! [B1]',
306 + 'Suspend! [C1]',
307 ]);
308 expect(root).toMatchRenderedOutput(
309 <>
@@ -321,8 +320,8 @@ describe('ReactAsyncActions', () => {
320 'Pending: false',
321 'A1',
322 'Suspend! [B1]',
324 -
325 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C1]'] : []),
323 + // pre-warming
324 + 'Suspend! [C1]',
325 ]);
326 expect(root).toMatchRenderedOutput(
327 <>
packages/react-reconciler/src/__tests__/ReactBatching-test.internal.js
+4 -2
@@ -113,8 +113,10 @@ describe('ReactBlockingMode', () => {
113 'A',
114 'Suspend! [B]',
115 'Loading...',
116 -
117 - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [B]', 'C'] : []),
116 + // pre-warming
117 + 'A',
118 + 'Suspend! [B]',
119 + 'C',
120 ]);
121 // In Legacy Mode, A and B would mount in a hidden primary tree. In
122 // Concurrent Mode, nothing in the primary tree should mount. But the
packages/react-reconciler/src/__tests__/ReactCPUSuspense-test.js
+2 -2
@@ -233,8 +233,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
233 // Inner contents suspended, so we continue showing a fallback.
234 assertLog([
235 'Suspend! [Inner]',
236 -
237 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Inner]'] : []),
236 + // pre-warming
237 + 'Suspend! [Inner]',
238 ]);
239 expect(root).toMatchRenderedOutput(
240 <>
packages/react-reconciler/src/__tests__/ReactConcurrentErrorRecovery-test.js
+3 -11
@@ -399,10 +399,8 @@ describe('ReactConcurrentErrorRecovery', () => {
399 });
400 assertLog([
401 'Suspend! [Async]',
402 -
403 - ...(gate('enableSiblingPrerendering')
404 - ? ['Caught an error: Oops!']
405 - : []),
402 + // pre-warming
403 + 'Caught an error: Oops!',
404 ]);
405 // The render suspended without committing the error.
406 expect(root).toMatchRenderedOutput(null);
@@ -420,13 +418,7 @@ describe('ReactConcurrentErrorRecovery', () => {
418 );
419 });
420 });
423 - assertLog([
424 - 'Suspend! [Async]',
425 -
426 - ...(gate('enableSiblingPrerendering')
427 - ? ['Caught an error: Oops!']
428 - : []),
429 - ]);
421 + assertLog(['Suspend! [Async]', 'Caught an error: Oops!']);
422 expect(root).toMatchRenderedOutput(null);
423
424 await act(async () => {
packages/react-reconciler/src/__tests__/ReactContextPropagation-test.js
+6 -6
@@ -398,8 +398,8 @@ describe('ReactLazyContextPropagation', () => {
398 'Suspend! [B]',
399 'Loading...',
400 'B',
401 -
402 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []),
401 + // pre-warming
402 + 'Suspend! [B]',
403 ]);
404 expect(root).toMatchRenderedOutput('Loading...B');
405
@@ -484,8 +484,8 @@ describe('ReactLazyContextPropagation', () => {
484 'Suspend! [B]',
485 'Loading...',
486 'B',
487 -
488 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []),
487 + // pre-warming
488 + 'Suspend! [B]',
489 ]);
490 expect(root).toMatchRenderedOutput('Loading...B');
491
@@ -822,8 +822,8 @@ describe('ReactLazyContextPropagation', () => {
822 assertLog([
823 'Suspend! [B]',
824 'Loading...',
825 -
826 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []),
825 + // pre-warming
826 + 'Suspend! [B]',
827 ]);
828 expect(root).toMatchRenderedOutput('Loading...');
829
packages/react-reconciler/src/__tests__/ReactDeferredValue-test.js
+13 -16
@@ -420,10 +420,9 @@ describe('ReactDeferredValue', () => {
420 // The initial value suspended, so we attempt the final value, which
421 // also suspends.
422 'Suspend! [Final]',
423 -
424 - ...(gate('enableSiblingPrerendering')
425 - ? ['Suspend! [Loading...]', 'Suspend! [Final]']
426 - : []),
423 + // pre-warming
424 + 'Suspend! [Loading...]',
425 + 'Suspend! [Final]',
426 ]);
427 expect(root).toMatchRenderedOutput(null);
428
@@ -463,10 +462,9 @@ describe('ReactDeferredValue', () => {
462 // The initial value suspended, so we attempt the final value, which
463 // also suspends.
464 'Suspend! [Final]',
466 -
467 - ...(gate('enableSiblingPrerendering')
468 - ? ['Suspend! [Loading...]', 'Suspend! [Final]']
469 - : []),
465 + // pre-warming
466 + 'Suspend! [Loading...]',
467 + 'Suspend! [Final]',
468 ]);
469 expect(root).toMatchRenderedOutput(null);
470
@@ -507,8 +505,8 @@ describe('ReactDeferredValue', () => {
505 // The initial value suspended, so we attempt the final value, which
506 // also suspends.
507 'Suspend! [Final]',
510 -
511 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Final]'] : []),
508 + // pre-warming
509 + 'Suspend! [Final]',
510 ]);
511 expect(root).toMatchRenderedOutput('Fallback');
512
@@ -541,10 +539,9 @@ describe('ReactDeferredValue', () => {
539 // The initial value suspended, so we attempt the final value, which
540 // also suspends.
541 'Suspend! [Final]',
544 -
545 - ...(gate('enableSiblingPrerendering')
546 - ? ['Suspend! [Loading...]', 'Suspend! [Final]']
547 - : []),
542 + // pre-warming
543 + 'Suspend! [Loading...]',
544 + 'Suspend! [Final]',
545 ]);
546 expect(root).toMatchRenderedOutput(null);
547
@@ -644,8 +641,8 @@ describe('ReactDeferredValue', () => {
641 // go straight to attempting the final value.
642 'Suspend! [Content]',
643 'Loading...',
647 -
648 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Content]'] : []),
644 + // pre-warming
645 + 'Suspend! [Content]',
646 ]);
647 // The content suspended, so we show a Suspense fallback
648 expect(root).toMatchRenderedOutput('Loading...');
packages/react-reconciler/src/__tests__/ReactExpiration-test.js
+4 -3
@@ -654,9 +654,10 @@ describe('ReactExpiration', () => {
654 });
655 await waitForAll([
656 'Suspend! [A1]',
657 -
658 - ...(gate('enableSiblingPrerendering') ? ['B', 'C'] : []),
659 -
657 + // pre-warming
658 + 'B',
659 + 'C',
660 + // end pre-warming
661 'Loading...',
662 ]);
663
packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js
+2 -2
@@ -3658,8 +3658,8 @@ describe('ReactHooksWithNoopRenderer', () => {
3658 'A',
3659 'Suspend! [A]',
3660 'Loading',
3661 -
3662 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
3661 + // pre-warming
3662 + 'Suspend! [A]',
3663 ]);
3664 expect(ReactNoop).toMatchRenderedOutput(
3665 <>
packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js
+19 -22
@@ -198,7 +198,10 @@ describe('ReactLazy', () => {
198
199 await resolveFakeImport(Foo);
200
201 - await waitForAll(['Foo']);
201 + await waitForAll([
202 + 'Foo',
203 + ...(gate('alwaysThrottleRetries') ? [] : ['Foo']),
204 + ]);
205 expect(root).not.toMatchRenderedOutput('FooBar');
206
207 await act(() => resolveFakeImport(Bar));
@@ -326,8 +329,8 @@ describe('ReactLazy', () => {
329 await waitForAll([
330 'Suspend! [LazyChildA]',
331 'Loading...',
329 -
330 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [LazyChildB]'] : []),
332 + // pre-warming
333 + 'Suspend! [LazyChildB]',
334 ]);
335 expect(root).not.toMatchRenderedOutput('AB');
336
@@ -339,21 +342,12 @@ describe('ReactLazy', () => {
342 // we can unwrap the result synchronously if it already loaded. Like `use`.
343 await waitFor([
344 'A',
342 -
343 - // When enableSiblingPrerendering is on, LazyChildB was already
344 - // initialized. So it also already resolved when we called
345 - // resolveFakeImport above. So it doesn't suspend again.
346 - ...(gate('enableSiblingPrerendering')
347 - ? ['B']
348 - : ['Suspend! [LazyChildB]']),
345 + // pre-warming: LazyChildB was already initialized. So it also already resolved
346 + // when we called resolveFakeImport above. So it doesn't suspend again.
347 + 'B',
348 ]);
349 });
351 - assertLog([
352 - ...(gate('enableSiblingPrerendering') ? [] : ['A', 'B']),
353 -
354 - 'Did mount: A',
355 - 'Did mount: B',
356 - ]);
350 + assertLog(['Did mount: A', 'Did mount: B']);
351 expect(root).toMatchRenderedOutput('AB');
352
353 // Swap the position of A and B
@@ -1612,7 +1606,11 @@ describe('ReactLazy', () => {
1606 expect(ref.current).toBe(null);
1607
1608 await act(() => resolveFakeImport(Foo));
1615 - assertLog(['Foo', ...(gate('enableSiblingPrerendering') ? ['Foo'] : [])]);
1609 + assertLog([
1610 + 'Foo',
1611 + // pre-warming
1612 + 'Foo',
1613 + ]);
1614
1615 await act(() => resolveFakeImport(ForwardRefBar));
1616 assertLog(['Foo', 'forwardRef', 'Bar']);
@@ -1910,17 +1908,16 @@ describe('ReactLazy', () => {
1908 await waitForAll([
1909 'Init A',
1910 'Loading...',
1913 -
1914 - ...(gate('enableSiblingPrerendering') ? ['Init B'] : []),
1911 + // pre-warming
1912 + 'Init B',
1913 ]);
1914 expect(root).not.toMatchRenderedOutput('AB');
1915
1916 await act(() => resolveFakeImport(ChildA));
1917 assertLog([
1918 'A',
1921 -
1922 - // When enableSiblingPrerendering is on, B was already initialized.
1923 - ...(gate('enableSiblingPrerendering') ? ['A'] : ['Init B']),
1919 + // pre-warming
1920 + 'A',
1921 ]);
1922
1923 await act(() => resolveFakeImport(ChildB));
packages/react-reconciler/src/__tests__/ReactSiblingPrerendering-test.js
+28 -52
@@ -171,7 +171,7 @@ describe('ReactSiblingPrerendering', () => {
171 // After B suspends, we're still able to prerender C without starting
172 // over because there's no fallback, so the root is blocked from
173 // committing anyway.
174 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C]'] : []),
174 + 'Suspend! [C]',
175 ]);
176 });
177
@@ -207,12 +207,10 @@ describe('ReactSiblingPrerendering', () => {
207 // The second render is a prerender of the hidden content.
208 await waitForPaint([
209 'Suspend! [B]',
210 -
210 // If B and C were visible, C would not have been attempted
211 // during this pass, because it would prevented the fallback
212 // from showing.
214 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C]'] : []),
215 -
213 + 'Suspend! [C]',
214 'Loading...',
215 ]);
216 expect(root).toMatchRenderedOutput('A');
@@ -240,13 +238,11 @@ describe('ReactSiblingPrerendering', () => {
238
239 // Immediately after the fallback commits, retry the boundary again. This
240 // time we include B, since we're not blocking the fallback from showing.
243 - if (gate('enableSiblingPrerendering')) {
244 - if (gate(flags => flags.enableYieldingBeforePassive)) {
245 - // Passive effects.
246 - await waitForPaint([]);
247 - }
248 - await waitForPaint(['Suspend! [A]', 'Suspend! [B]']);
241 + if (gate(flags => flags.enableYieldingBeforePassive)) {
242 + // Passive effects.
243 + await waitForPaint([]);
244 }
245 + await waitForPaint(['Suspend! [A]', 'Suspend! [B]']);
246 });
247 expect(root).toMatchRenderedOutput('Loading...');
248 });
@@ -282,11 +278,7 @@ describe('ReactSiblingPrerendering', () => {
278
279 // Now that the fallback is visible, we can prerender the siblings. Start
280 // prerendering, then yield to simulate an interleaved event.
285 - if (gate('enableSiblingPrerendering')) {
286 - await waitFor(['A']);
287 - } else {
288 - await waitForAll([]);
289 - }
281 + await waitFor(['A']);
282
283 // To avoid the Suspense throttling mechanism, let's pretend there's been
284 // more than a Just Noticeable Difference since we rendered the
@@ -298,10 +290,6 @@ describe('ReactSiblingPrerendering', () => {
290 // shouldn't unwind and lose our work-in-progress.
291 await resolveText('B');
292 await waitForPaint([
301 - // When sibling prerendering is not enabled, we weren't already rendering
302 - // when the data for B came in, so A doesn't get rendered until now.
303 - ...(gate('enableSiblingPrerendering') ? [] : ['A']),
304 -
293 'B',
294 'Suspend! [C]',
295
@@ -321,23 +309,19 @@ describe('ReactSiblingPrerendering', () => {
309
310 // Now that the inner fallback is showing, we can prerender the rest of
311 // the tree.
324 - assertLog(
325 - gate('enableSiblingPrerendering')
326 - ? [
327 - // NOTE: C renders twice instead of once because when B resolved, it
328 - // was treated like a retry update, not just a ping. So first it
329 - // regular renders, then it prerenders. TODO: We should be able to
330 - // optimize this by detecting inside the retry listener that the
331 - // outer boundary is no longer suspended, and therefore doesn't need
332 - // to be updated.
333 - 'Suspend! [C]',
334 -
335 - // Now we're in prerender mode, so D is incuded in this attempt.
336 - 'Suspend! [C]',
337 - 'Suspend! [D]',
338 - ]
339 - : [],
340 - );
312 + assertLog([
313 + // NOTE: C renders twice instead of once because when B resolved, it
314 + // was treated like a retry update, not just a ping. So first it
315 + // regular renders, then it prerenders. TODO: We should be able to
316 + // optimize this by detecting inside the retry listener that the
317 + // outer boundary is no longer suspended, and therefore doesn't need
318 + // to be updated.
319 + 'Suspend! [C]',
320 +
321 + // Now we're in prerender mode, so D is incuded in this attempt.
322 + 'Suspend! [C]',
323 + 'Suspend! [D]',
324 + ]);
325 expect(root).toMatchRenderedOutput(
326 <div>
327 <div>AB</div>
@@ -402,9 +386,7 @@ describe('ReactSiblingPrerendering', () => {
386 );
387 });
388 // Once the inner fallback is committed, we can start prerendering C.
405 - assertLog(
406 - gate('enableSiblingPrerendering') ? ['Suspend! [B]', 'Suspend! [C]'] : [],
407 - );
389 + assertLog(['Suspend! [B]', 'Suspend! [C]']);
390 });
391
392 it(
@@ -488,9 +470,7 @@ describe('ReactSiblingPrerendering', () => {
470 await waitForPaint([]);
471 }
472 // Now we can proceed to prerendering C.
491 - if (gate('enableSiblingPrerendering')) {
492 - await waitForPaint(['Suspend! [B]', 'Suspend! [C]']);
493 - }
473 + await waitForPaint(['Suspend! [B]', 'Suspend! [C]']);
474 });
475 assertLog([]);
476 },
@@ -519,12 +499,10 @@ describe('ReactSiblingPrerendering', () => {
499 // Synchronously render everything until we suspend in the shell
500 assertLog(['A', 'B', 'Suspend! [Async]']);
501
522 - if (gate('enableSiblingPrerendering')) {
523 - // The rest of the siblings begin to prerender concurrently. Notice
524 - // that we don't unwind here; we pick up where we left off above.
525 - await waitFor(['C']);
526 - await waitFor(['D']);
527 - }
502 + // The rest of the siblings begin to prerender concurrently. Notice
503 + // that we don't unwind here; we pick up where we left off above.
504 + await waitFor(['C']);
505 + await waitFor(['D']);
506
507 assertLog([]);
508 expect(root).toMatchRenderedOutput(null);
@@ -555,10 +533,8 @@ describe('ReactSiblingPrerendering', () => {
533 // Synchronously render everything until we suspend in the shell
534 assertLog(['A', 'B', 'Suspend! [Async]']);
535
558 - if (gate('enableSiblingPrerendering')) {
559 - // The rest of the siblings begin to prerender concurrently
560 - await waitFor(['C']);
561 - }
536 + // The rest of the siblings begin to prerender concurrently
537 + await waitFor(['C']);
538
539 // While we're prerendering, Async resolves. We should unwind and
540 // start over, rather than continue prerendering D.
packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js
+48 -46
@@ -135,9 +135,9 @@ describe('ReactSuspense', () => {
135 'Bar',
136 // A suspends
137 'Suspend! [A]',
138 -
139 - ...(gate('enableSiblingPrerendering') ? ['B'] : []),
140 -
138 + // pre-warming
139 + 'B',
140 + // end pre-warming
141 'Loading...',
142 ]);
143 expect(container.textContent).toEqual('');
@@ -169,10 +169,9 @@ describe('ReactSuspense', () => {
169 'Loading A...',
170 'Suspend! [B]',
171 'Loading B...',
172 -
173 - ...(gate('enableSiblingPrerendering')
174 - ? ['Suspend! [A]', 'Suspend! [B]']
175 - : []),
172 + // pre-warming
173 + 'Suspend! [A]',
174 + 'Suspend! [B]',
175 ]);
176 expect(container.innerHTML).toEqual('Loading A...Loading B...');
177
@@ -181,8 +180,7 @@ describe('ReactSuspense', () => {
180 await act(() => resolveText('A'));
181 assertLog([
182 'A',
184 -
185 - ...(gate('enableSiblingPrerendering')
183 + ...(gate('alwaysThrottleRetries')
184 ? ['Suspend! [B]', 'Suspend! [B]']
185 : []),
186 ]);
@@ -288,10 +286,10 @@ describe('ReactSuspense', () => {
286 'Foo',
287 'Suspend! [A]',
288 'Loading...',
291 -
292 - ...(gate('enableSiblingPrerendering')
293 - ? ['Suspend! [A]', 'Suspend! [B]', 'Loading more...']
294 - : []),
289 + // pre-warming
290 + 'Suspend! [A]',
291 + 'Suspend! [B]',
292 + 'Loading more...',
293 ]);
294 expect(container.textContent).toEqual('Loading...');
295
@@ -341,10 +339,10 @@ describe('ReactSuspense', () => {
339 'Foo',
340 'Suspend! [A]',
341 'Loading...',
344 -
345 - ...(gate('enableSiblingPrerendering')
346 - ? ['Suspend! [A]', 'Suspend! [B]', 'Loading more...']
347 - : []),
342 + // pre-warming
343 + 'Suspend! [A]',
344 + 'Suspend! [B]',
345 + 'Loading more...',
346 ]);
347 expect(container.textContent).toEqual('Loading...');
348
@@ -390,10 +388,10 @@ describe('ReactSuspense', () => {
388 'Foo',
389 'Suspend! [A]',
390 'Loading...',
393 -
394 - ...(gate('enableSiblingPrerendering')
395 - ? ['Suspend! [A]', 'Suspend! [B]', 'Loading more...']
396 - : []),
391 + // pre-warming
392 + 'Suspend! [A]',
393 + 'Suspend! [B]',
394 + 'Loading more...',
395 ]);
396 expect(container.textContent).toEqual('Loading...');
397
@@ -482,8 +480,8 @@ describe('ReactSuspense', () => {
480 assertLog([
481 'Suspend! [default]',
482 'Loading...',
485 -
486 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [default]'] : []),
483 + // pre-warming
484 + 'Suspend! [default]',
485 ]);
486
487 await act(() => resolveText('default'));
@@ -494,8 +492,8 @@ describe('ReactSuspense', () => {
492 assertLog([
493 'Suspend! [new value]',
494 'Loading...',
497 -
498 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [new value]'] : []),
495 + // pre-warming
496 + 'Suspend! [new value]',
497 ]);
498
499 await act(() => resolveText('new value'));
@@ -539,8 +537,8 @@ describe('ReactSuspense', () => {
537 assertLog([
538 'Suspend! [default]',
539 'Loading...',
542 -
543 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [default]'] : []),
540 + // pre-warming
541 + 'Suspend! [default]',
542 ]);
543
544 await act(() => resolveText('default'));
@@ -551,8 +549,8 @@ describe('ReactSuspense', () => {
549 assertLog([
550 'Suspend! [new value]',
551 'Loading...',
554 -
555 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [new value]'] : []),
552 + // pre-warming
553 + 'Suspend! [new value]',
554 ]);
555
556 await act(() => resolveText('new value'));
@@ -593,8 +591,8 @@ describe('ReactSuspense', () => {
591 assertLog([
592 'Suspend! [default]',
593 'Loading...',
596 -
597 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [default]'] : []),
594 + // pre-warming
595 + 'Suspend! [default]',
596 ]);
597
598 await act(() => resolveText('default'));
@@ -605,8 +603,8 @@ describe('ReactSuspense', () => {
603 assertLog([
604 'Suspend! [new value]',
605 'Loading...',
608 -
609 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [new value]'] : []),
606 + // pre-warming
607 + 'Suspend! [new value]',
608 ]);
609
610 await act(() => resolveText('new value'));
@@ -647,8 +645,8 @@ describe('ReactSuspense', () => {
645 assertLog([
646 'Suspend! [default]',
647 'Loading...',
650 -
651 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [default]'] : []),
648 + // pre-warming
649 + 'Suspend! [default]',
650 ]);
651
652 await act(() => resolveText('default'));
@@ -659,8 +657,8 @@ describe('ReactSuspense', () => {
657 assertLog([
658 'Suspend! [new value]',
659 'Loading...',
662 -
663 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [new value]'] : []),
660 + // pre-warming
661 + 'Suspend! [new value]',
662 ]);
663
664 await act(() => resolveText('new value'));
@@ -708,10 +706,9 @@ describe('ReactSuspense', () => {
706 'Suspend! [Child 2]',
707 'Loading...',
708 'destroy layout',
711 -
712 - ...(gate('enableSiblingPrerendering')
713 - ? ['Child 1', 'Suspend! [Child 2]']
714 - : []),
709 + // pre-warming
710 + 'Child 1',
711 + 'Suspend! [Child 2]',
712 ]);
713
714 await act(() => resolveText('Child 2'));
@@ -737,13 +734,18 @@ describe('ReactSuspense', () => {
734 assertLog([
735 'Suspend! [Child 1]',
736 'Loading...',
740 -
741 - ...(gate('enableSiblingPrerendering')
742 - ? ['Suspend! [Child 1]', 'Suspend! [Child 2]']
743 - : []),
737 + // pre-warming
738 + 'Suspend! [Child 1]',
739 + 'Suspend! [Child 2]',
740 ]);
741 await resolveText('Child 1');
746 - await waitForAll(['Child 1', 'Suspend! [Child 2]']);
742 + await waitForAll([
743 + 'Child 1',
744 + 'Suspend! [Child 2]',
745 + ...(gate('alwaysThrottleRetries')
746 + ? []
747 + : ['Child 1', 'Suspend! [Child 2]']),
748 + ]);
749
750 jest.advanceTimersByTime(6000);
751
packages/react-reconciler/src/__tests__/ReactSuspenseCallback-test.js
+26 -13
@@ -60,9 +60,17 @@ describe('ReactSuspense', () => {
60
61 ReactNoop.render(elementBadType);
62 await waitForAll([]);
63 - assertConsoleErrorDev(['Unexpected type for suspenseCallback.'], {
64 - withoutStack: true,
65 - });
63 + assertConsoleErrorDev(
64 + [
65 + 'Unexpected type for suspenseCallback.',
66 + ...(gate('alwaysThrottleRetries')
67 + ? []
68 + : ['Unexpected type for suspenseCallback.']),
69 + ],
70 + {
71 + withoutStack: true,
72 + },
73 + );
74
75 const elementMissingCallback = (
76 <React.Suspense fallback={'Waiting'}>
@@ -93,7 +101,10 @@ describe('ReactSuspense', () => {
101 ReactNoop.render(element);
102 await waitForAll([]);
103 expect(ReactNoop).toMatchRenderedOutput('Waiting');
96 - expect(ops).toEqual([new Set([promise])]);
104 + expect(ops).toEqual([
105 + new Set([promise]),
106 + ...(gate('alwaysThrottleRetries') ? [] : new Set([promise])),
107 + ]);
108 ops = [];
109
110 await act(() => resolve());
@@ -132,7 +143,10 @@ describe('ReactSuspense', () => {
143 ReactNoop.render(element);
144 await waitForAll([]);
145 expect(ReactNoop).toMatchRenderedOutput('Waiting Tier 1');
135 - expect(ops).toEqual([new Set([promise1])]);
146 + expect(ops).toEqual([
147 + new Set([promise1]),
148 + ...(gate('alwaysThrottleRetries') ? [] : new Set([promise1, promise2])),
149 + ]);
150 ops = [];
151
152 await act(() => resolve1());
@@ -141,8 +155,8 @@ describe('ReactSuspense', () => {
155 expect(ReactNoop).toMatchRenderedOutput('Waiting Tier 1');
156 expect(ops).toEqual([
157 new Set([promise2]),
144 -
145 - ...(gate('enableSiblingPrerendering') ? new Set([promise2]) : []),
158 + // pre-warming
159 + new Set([promise2]),
160 ]);
161 ops = [];
162
@@ -182,7 +196,10 @@ describe('ReactSuspense', () => {
196 await waitForAll([]);
197 expect(ReactNoop).toMatchRenderedOutput('Waiting Tier 2');
198 expect(ops1).toEqual([]);
185 - expect(ops2).toEqual([new Set([promise])]);
199 + expect(ops2).toEqual([
200 + new Set([promise]),
201 + ...(gate('alwaysThrottleRetries') ? [] : [new Set([promise])]),
202 + ]);
203 });
204
205 // @gate enableSuspenseCallback
@@ -231,11 +248,7 @@ describe('ReactSuspense', () => {
248 await act(() => resolve1());
249 expect(ReactNoop).toMatchRenderedOutput('Waiting Tier 2Done');
250 expect(ops1).toEqual([]);
234 - expect(ops2).toEqual([
235 - new Set([promise2]),
236 -
237 - ...(gate('enableSiblingPrerendering') ? new Set([promise2]) : []),
238 - ]);
251 + expect(ops2).toEqual([new Set([promise2]), new Set([promise2])]);
252 ops1 = [];
253 ops2 = [];
254
packages/react-reconciler/src/__tests__/ReactSuspenseEffectsSemantics-test.js
+132 -204
@@ -283,14 +283,10 @@ describe('ReactSuspenseEffectsSemantics', () => {
283 'Text:Fallback create passive',
284 'Text:Outside create passive',
285 'App create passive',
286 -
287 - ...(gate('enableSiblingPrerendering')
288 - ? [
289 - 'Text:Inside:Before render',
290 - 'Suspend:Async',
291 - 'ClassText:Inside:After render',
292 - ]
293 - : []),
286 + // pre-warming
287 + 'Text:Inside:Before render',
288 + 'Suspend:Async',
289 + 'ClassText:Inside:After render',
290 ]);
291 expect(ReactNoop).toMatchRenderedOutput(
292 <>
@@ -687,14 +683,10 @@ describe('ReactSuspenseEffectsSemantics', () => {
683 ]);
684 await waitForAll([
685 'Text:Fallback create passive',
690 -
691 - ...(gate('enableSiblingPrerendering')
692 - ? [
693 - 'Text:Inside:Before render',
694 - 'Suspend:Async',
695 - 'Text:Inside:After render',
696 - ]
697 - : []),
686 + // pre-warming
687 + 'Text:Inside:Before render',
688 + 'Suspend:Async',
689 + 'Text:Inside:After render',
690 ]);
691 expect(ReactNoop).toMatchRenderedOutput(
692 <>
@@ -850,13 +842,12 @@ describe('ReactSuspenseEffectsSemantics', () => {
842 </>,
843 );
844 });
853 - if (gate('enableSiblingPrerendering')) {
854 - assertLog([
855 - 'ClassText:Inside:Before render',
856 - 'Suspend:Async',
857 - 'ClassText:Inside:After render',
858 - ]);
859 - }
845 + // pre-warming
846 + assertLog([
847 + 'ClassText:Inside:Before render',
848 + 'Suspend:Async',
849 + 'ClassText:Inside:After render',
850 + ]);
851
852 // Resolving the suspended resource should re-create inner layout effects.
853 await act(async () => {
@@ -961,10 +952,10 @@ describe('ReactSuspenseEffectsSemantics', () => {
952 ]);
953 await waitForAll([
954 'Text:Fallback create passive',
964 -
965 - ...(gate('enableSiblingPrerendering')
966 - ? ['Suspend:Async', 'Text:Outer render', 'Text:Inner render']
967 - : []),
955 + // pre-warming
956 + 'Suspend:Async',
957 + 'Text:Outer render',
958 + 'Text:Inner render',
959 ]);
960 expect(ReactNoop).toMatchRenderedOutput(
961 <>
@@ -1088,10 +1079,9 @@ describe('ReactSuspenseEffectsSemantics', () => {
1079 ]);
1080 await waitForAll([
1081 'Text:Fallback create passive',
1091 -
1092 - ...(gate('enableSiblingPrerendering')
1093 - ? ['Suspend:Async', 'Text:Outer render']
1094 - : []),
1082 + // pre-warming
1083 + 'Suspend:Async',
1084 + 'Text:Outer render',
1085 ]);
1086 expect(ReactNoop).toMatchRenderedOutput(
1087 <>
@@ -1195,10 +1185,9 @@ describe('ReactSuspenseEffectsSemantics', () => {
1185 'Text:InnerFallback create insertion',
1186 'Text:InnerFallback create layout',
1187 'Text:InnerFallback create passive',
1198 -
1199 - ...(gate('enableSiblingPrerendering')
1200 - ? ['Text:Inner render', 'Suspend:InnerAsync_1']
1201 - : []),
1188 + // pre-warming
1189 + 'Text:Inner render',
1190 + 'Suspend:InnerAsync_1',
1191 ]);
1192 expect(ReactNoop).toMatchRenderedOutput(
1193 <>
@@ -1228,16 +1217,12 @@ describe('ReactSuspenseEffectsSemantics', () => {
1217 'Text:OuterFallback create insertion',
1218 'Text:OuterFallback create layout',
1219 'Text:OuterFallback create passive',
1231 -
1232 - ...(gate('enableSiblingPrerendering')
1233 - ? [
1234 - 'Text:Outer render',
1235 - 'Suspend:OuterAsync_1',
1236 - 'Text:Inner render',
1237 - 'Suspend:InnerAsync_1',
1238 - 'Text:InnerFallback render',
1239 - ]
1240 - : []),
1220 + // pre-warming
1221 + 'Text:Outer render',
1222 + 'Suspend:OuterAsync_1',
1223 + 'Text:Inner render',
1224 + 'Suspend:InnerAsync_1',
1225 + 'Text:InnerFallback render',
1226 ]);
1227 expect(ReactNoop).toMatchRenderedOutput(
1228 <>
@@ -1255,15 +1240,11 @@ describe('ReactSuspenseEffectsSemantics', () => {
1240 assertLog([
1241 'Text:Outer render',
1242 'Suspend:OuterAsync_1',
1258 -
1259 - ...(gate('enableSiblingPrerendering')
1260 - ? [
1261 - 'Text:Outer render',
1262 - 'Suspend:OuterAsync_1',
1263 - 'Text:Inner render',
1264 - 'AsyncText:InnerAsync_1 render',
1265 - ]
1266 - : []),
1243 + // pre-warming
1244 + 'Text:Outer render',
1245 + 'Suspend:OuterAsync_1',
1246 + 'Text:Inner render',
1247 + 'AsyncText:InnerAsync_1 render',
1248 ]);
1249 expect(ReactNoop).toMatchRenderedOutput(
1250 <>
@@ -1288,16 +1269,12 @@ describe('ReactSuspenseEffectsSemantics', () => {
1269 'Text:Outer render',
1270 'Suspend:OuterAsync_1',
1271 'Text:OuterFallback render',
1291 -
1292 - ...(gate('enableSiblingPrerendering')
1293 - ? [
1294 - 'Text:Outer render',
1295 - 'Suspend:OuterAsync_1',
1296 - 'Text:Inner render',
1297 - 'Suspend:InnerAsync_2',
1298 - 'Text:InnerFallback render',
1299 - ]
1300 - : []),
1272 + // pre-warming
1273 + 'Text:Outer render',
1274 + 'Suspend:OuterAsync_1',
1275 + 'Text:Inner render',
1276 + 'Suspend:InnerAsync_2',
1277 + 'Text:InnerFallback render',
1278 ]);
1279 expect(ReactNoop).toMatchRenderedOutput(
1280 <>
@@ -1325,10 +1302,9 @@ describe('ReactSuspenseEffectsSemantics', () => {
1302 'Text:InnerFallback create layout',
1303 'Text:OuterFallback destroy passive',
1304 'AsyncText:OuterAsync_1 create passive',
1328 -
1329 - ...(gate('enableSiblingPrerendering')
1330 - ? ['Text:Inner render', 'Suspend:InnerAsync_2']
1331 - : []),
1305 + // pre-warming
1306 + 'Text:Inner render',
1307 + 'Suspend:InnerAsync_2',
1308 ]);
1309 expect(ReactNoop).toMatchRenderedOutput(
1310 <>
@@ -1382,15 +1358,11 @@ describe('ReactSuspenseEffectsSemantics', () => {
1358 'Text:OuterFallback create insertion',
1359 'Text:OuterFallback create layout',
1360 'Text:OuterFallback create passive',
1385 -
1386 - ...(gate('enableSiblingPrerendering')
1387 - ? [
1388 - 'Text:Outer render',
1389 - 'Suspend:OuterAsync_2',
1390 - 'Text:Inner render',
1391 - 'AsyncText:InnerAsync_2 render',
1392 - ]
1393 - : []),
1361 + // pre-warming
1362 + 'Text:Outer render',
1363 + 'Suspend:OuterAsync_2',
1364 + 'Text:Inner render',
1365 + 'AsyncText:InnerAsync_2 render',
1366 ]);
1367 expect(ReactNoop).toMatchRenderedOutput(
1368 <>
@@ -1480,10 +1452,9 @@ describe('ReactSuspenseEffectsSemantics', () => {
1452 'Text:InnerFallback create insertion',
1453 'Text:InnerFallback create layout',
1454 'Text:InnerFallback create passive',
1483 -
1484 - ...(gate('enableSiblingPrerendering')
1485 - ? ['Text:Inner render', 'Suspend:InnerAsync_1']
1486 - : []),
1455 + // pre-warming
1456 + 'Text:Inner render',
1457 + 'Suspend:InnerAsync_1',
1458 ]);
1459 expect(ReactNoop).toMatchRenderedOutput(
1460 <>
@@ -1512,16 +1483,12 @@ describe('ReactSuspenseEffectsSemantics', () => {
1483 'Text:OuterFallback create insertion',
1484 'Text:OuterFallback create layout',
1485 'Text:OuterFallback create passive',
1515 -
1516 - ...(gate('enableSiblingPrerendering')
1517 - ? [
1518 - 'Text:Outer render',
1519 - 'Suspend:OuterAsync_1',
1520 - 'Text:Inner render',
1521 - 'Suspend:InnerAsync_1',
1522 - 'Text:InnerFallback render',
1523 - ]
1524 - : []),
1486 + // pre-warming
1487 + 'Text:Outer render',
1488 + 'Suspend:OuterAsync_1',
1489 + 'Text:Inner render',
1490 + 'Suspend:InnerAsync_1',
1491 + 'Text:InnerFallback render',
1492 ]);
1493 expect(ReactNoop).toMatchRenderedOutput(
1494 <>
@@ -1630,10 +1597,9 @@ describe('ReactSuspenseEffectsSemantics', () => {
1597 await waitForAll([
1598 'Text:Fallback:Inside create passive',
1599 'Text:Fallback:Outside create passive',
1633 -
1634 - ...(gate('enableSiblingPrerendering')
1635 - ? ['Text:Inside render', 'Suspend:OutsideAsync']
1636 - : []),
1600 + // pre-warming
1601 + 'Text:Inside render',
1602 + 'Suspend:OutsideAsync',
1603 ]);
1604 expect(ReactNoop).toMatchRenderedOutput(
1605 <>
@@ -1667,15 +1633,11 @@ describe('ReactSuspenseEffectsSemantics', () => {
1633 ]);
1634 await waitForAll([
1635 'Text:Fallback:Fallback create passive',
1670 -
1671 - ...(gate('enableSiblingPrerendering')
1672 - ? [
1673 - 'Text:Inside render',
1674 - 'Suspend:OutsideAsync',
1675 - 'Text:Fallback:Inside render',
1676 - 'Suspend:FallbackAsync',
1677 - ]
1678 - : []),
1636 + // pre-warming
1637 + 'Text:Inside render',
1638 + 'Suspend:OutsideAsync',
1639 + 'Text:Fallback:Inside render',
1640 + 'Suspend:FallbackAsync',
1641 ]);
1642 expect(ReactNoop).toMatchRenderedOutput(
1643 <>
@@ -1787,15 +1749,11 @@ describe('ReactSuspenseEffectsSemantics', () => {
1749 'Text:Fallback:Outside create layout',
1750 'Text:Fallback:Fallback create passive',
1751 'Text:Fallback:Outside create passive',
1790 -
1791 - ...(gate('enableSiblingPrerendering')
1792 - ? [
1793 - 'Text:Inside render',
1794 - 'Suspend:OutsideAsync',
1795 - 'Text:Fallback:Inside render',
1796 - 'Suspend:FallbackAsync',
1797 - ]
1798 - : []),
1752 + // pre-warming
1753 + 'Text:Inside render',
1754 + 'Suspend:OutsideAsync',
1755 + 'Text:Fallback:Inside render',
1756 + 'Suspend:FallbackAsync',
1757 ]);
1758 expect(ReactNoop).toMatchRenderedOutput(
1759 <>
@@ -1915,8 +1873,8 @@ describe('ReactSuspenseEffectsSemantics', () => {
1873 ]);
1874 await waitForAll([
1875 'Text:Fallback create passive',
1918 -
1919 - ...(gate('enableSiblingPrerendering') ? ['Suspend:Suspend'] : []),
1876 + // pre-warming
1877 + 'Suspend:Suspend',
1878 ]);
1879 expect(ReactNoop).toMatchRenderedOutput(
1880 <>
@@ -2038,10 +1996,10 @@ describe('ReactSuspenseEffectsSemantics', () => {
1996 'Text:Fallback create insertion',
1997 'Text:Fallback create layout',
1998 'Text:Fallback create passive',
2041 -
2042 - ...(gate('enableSiblingPrerendering')
2043 - ? ['Suspend:Async', 'ThrowsInDidMount render', 'Text:Inside render']
2044 - : []),
1999 + // pre-warming
2000 + 'Suspend:Async',
2001 + 'ThrowsInDidMount render',
2002 + 'Text:Inside render',
2003 ]);
2004 expect(ReactNoop).toMatchRenderedOutput(
2005 <>
@@ -2301,14 +2259,10 @@ describe('ReactSuspenseEffectsSemantics', () => {
2259 'Text:Fallback create insertion',
2260 'Text:Fallback create layout',
2261 'Text:Fallback create passive',
2304 -
2305 - ...(gate('enableSiblingPrerendering')
2306 - ? [
2307 - 'Suspend:Async',
2308 - 'ThrowsInLayoutEffect render',
2309 - 'Text:Inside render',
2310 - ]
2311 - : []),
2262 + // pre-warming
2263 + 'Suspend:Async',
2264 + 'ThrowsInLayoutEffect render',
2265 + 'Text:Inside render',
2266 ]);
2267 expect(ReactNoop).toMatchRenderedOutput(
2268 <>
@@ -2555,14 +2509,13 @@ describe('ReactSuspenseEffectsSemantics', () => {
2509 );
2510 });
2511
2558 - if (gate('enableSiblingPrerendering')) {
2559 - assertLog([
2560 - 'Text:Function render',
2561 - 'Suspend:Async_1',
2562 - 'Suspend:Async_2',
2563 - 'ClassText:Class render',
2564 - ]);
2565 - }
2512 + // pre-warming
2513 + assertLog([
2514 + 'Text:Function render',
2515 + 'Suspend:Async_1',
2516 + 'Suspend:Async_2',
2517 + 'ClassText:Class render',
2518 + ]);
2519
2520 // Resolving the suspended resource should re-create inner layout effects.
2521 await act(async () => {
@@ -2572,15 +2525,11 @@ describe('ReactSuspenseEffectsSemantics', () => {
2525 'Text:Function render',
2526 'AsyncText:Async_1 render',
2527 'Suspend:Async_2',
2575 -
2576 - ...(gate('enableSiblingPrerendering')
2577 - ? [
2578 - 'Text:Function render',
2579 - 'AsyncText:Async_1 render',
2580 - 'Suspend:Async_2',
2581 - 'ClassText:Class render',
2582 - ]
2583 - : []),
2528 + // pre-warming
2529 + 'Text:Function render',
2530 + 'AsyncText:Async_1 render',
2531 + 'Suspend:Async_2',
2532 + 'ClassText:Class render',
2533 ]);
2534 expect(ReactNoop).toMatchRenderedOutput(
2535 <>
@@ -2715,14 +2664,14 @@ describe('ReactSuspenseEffectsSemantics', () => {
2664 </>,
2665 );
2666 });
2718 - if (gate('enableSiblingPrerendering')) {
2719 - assertLog([
2720 - 'Text:Function render',
2721 - 'Suspender "A" render',
2722 - 'Suspend:A',
2723 - 'ClassText:Class render',
2724 - ]);
2725 - }
2667 +
2668 + // pre-warming
2669 + assertLog([
2670 + 'Text:Function render',
2671 + 'Suspender "A" render',
2672 + 'Suspend:A',
2673 + 'ClassText:Class render',
2674 + ]);
2675
2676 // Resolving the suspended resource should re-create inner layout effects.
2677 textToRead = 'B';
@@ -2733,15 +2682,11 @@ describe('ReactSuspenseEffectsSemantics', () => {
2682 'Text:Function render',
2683 'Suspender "B" render',
2684 'Suspend:B',
2736 -
2737 - ...(gate('enableSiblingPrerendering')
2738 - ? [
2739 - 'Text:Function render',
2740 - 'Suspender "B" render',
2741 - 'Suspend:B',
2742 - 'ClassText:Class render',
2743 - ]
2744 - : []),
2685 + // pre-warming
2686 + 'Text:Function render',
2687 + 'Suspender "B" render',
2688 + 'Suspend:B',
2689 + 'ClassText:Class render',
2690 ]);
2691 expect(ReactNoop).toMatchRenderedOutput(
2692 <>
@@ -2977,15 +2922,11 @@ describe('ReactSuspenseEffectsSemantics', () => {
2922 'Text:Fallback create insertion',
2923 'Text:Fallback create layout',
2924 'Text:Fallback create passive',
2980 -
2981 - ...(gate('enableSiblingPrerendering')
2982 - ? [
2983 - 'Suspend:Async',
2984 - 'RefCheckerOuter render',
2985 - 'RefCheckerInner:refObject render',
2986 - 'RefCheckerInner:refCallback render',
2987 - ]
2988 - : []),
2925 + // pre-warming
2926 + 'Suspend:Async',
2927 + 'RefCheckerOuter render',
2928 + 'RefCheckerInner:refObject render',
2929 + 'RefCheckerInner:refCallback render',
2930 ]);
2931 expect(ReactNoop).toMatchRenderedOutput(
2932 <>
@@ -3089,17 +3030,13 @@ describe('ReactSuspenseEffectsSemantics', () => {
3030 'Text:Fallback create insertion',
3031 'Text:Fallback create layout',
3032 'Text:Fallback create passive',
3092 -
3093 - ...(gate('enableSiblingPrerendering')
3094 - ? [
3095 - 'Suspend:Async',
3096 - 'RefCheckerOuter render',
3097 - 'ClassComponent:refObject render',
3098 - 'RefCheckerInner:refObject render',
3099 - 'ClassComponent:refCallback render',
3100 - 'RefCheckerInner:refCallback render',
3101 - ]
3102 - : []),
3033 + // pre-warming
3034 + 'Suspend:Async',
3035 + 'RefCheckerOuter render',
3036 + 'ClassComponent:refObject render',
3037 + 'RefCheckerInner:refObject render',
3038 + 'ClassComponent:refCallback render',
3039 + 'RefCheckerInner:refCallback render',
3040 ]);
3041 expect(ReactNoop).toMatchRenderedOutput(<span prop="Fallback" />);
3042
@@ -3199,17 +3136,13 @@ describe('ReactSuspenseEffectsSemantics', () => {
3136 'Text:Fallback create insertion',
3137 'Text:Fallback create layout',
3138 'Text:Fallback create passive',
3202 -
3203 - ...(gate('enableSiblingPrerendering')
3204 - ? [
3205 - 'Suspend:Async',
3206 - 'RefCheckerOuter render',
3207 - 'FunctionComponent render',
3208 - 'RefCheckerInner:refObject render',
3209 - 'FunctionComponent render',
3210 - 'RefCheckerInner:refCallback render',
3211 - ]
3212 - : []),
3139 + // pre-warming
3140 + 'Suspend:Async',
3141 + 'RefCheckerOuter render',
3142 + 'FunctionComponent render',
3143 + 'RefCheckerInner:refObject render',
3144 + 'FunctionComponent render',
3145 + 'RefCheckerInner:refCallback render',
3146 ]);
3147 expect(ReactNoop).toMatchRenderedOutput(<span prop="Fallback" />);
3148
@@ -3311,10 +3244,9 @@ describe('ReactSuspenseEffectsSemantics', () => {
3244 'Text:Fallback create insertion',
3245 'Text:Fallback create layout',
3246 'Text:Fallback create passive',
3314 -
3315 - ...(gate('enableSiblingPrerendering')
3316 - ? ['Suspend:Async', 'RefChecker render']
3317 - : []),
3247 + // pre-warming
3248 + 'Suspend:Async',
3249 + 'RefChecker render',
3250 ]);
3251 expect(ReactNoop).toMatchRenderedOutput(<span prop="Fallback" />);
3252
@@ -3433,14 +3365,10 @@ describe('ReactSuspenseEffectsSemantics', () => {
3365 'Text:Fallback create insertion',
3366 'Text:Fallback create layout',
3367 'Text:Fallback create passive',
3436 -
3437 - ...(gate('enableSiblingPrerendering')
3438 - ? [
3439 - 'Suspend:Async',
3440 - 'ThrowsInRefCallback render',
3441 - 'Text:Inside render',
3442 - ]
3443 - : []),
3368 + // pre-warming
3369 + 'Suspend:Async',
3370 + 'ThrowsInRefCallback render',
3371 + 'Text:Inside render',
3372 ]);
3373 expect(ReactNoop).toMatchRenderedOutput(
3374 <>
packages/react-reconciler/src/__tests__/ReactSuspenseFallback-test.js
+12 -12
@@ -142,8 +142,8 @@ describe('ReactSuspenseFallback', () => {
142 await waitForAll([
143 'Suspend! [A]',
144 'Loading...',
145 -
146 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
145 + // pre-warming
146 + 'Suspend! [A]',
147 ]);
148 expect(ReactNoop).toMatchRenderedOutput(<span prop="Loading..." />);
149 });
@@ -159,8 +159,8 @@ describe('ReactSuspenseFallback', () => {
159 await waitForAll([
160 'Suspend! [A]',
161 // null
162 -
163 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
162 + // pre-warming
163 + 'Suspend! [A]',
164 ]);
165 expect(ReactNoop).toMatchRenderedOutput(null);
166 });
@@ -176,8 +176,8 @@ describe('ReactSuspenseFallback', () => {
176 await waitForAll([
177 'Suspend! [A]',
178 // null
179 -
180 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
179 + // pre-warming
180 + 'Suspend! [A]',
181 ]);
182 expect(ReactNoop).toMatchRenderedOutput(null);
183 });
@@ -195,8 +195,8 @@ describe('ReactSuspenseFallback', () => {
195 await waitForAll([
196 'Suspend! [A]',
197 'Loading...',
198 -
199 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
198 + // pre-warming
199 + 'Suspend! [A]',
200 ]);
201 expect(ReactNoop).toMatchRenderedOutput(<span prop="Loading..." />);
202 });
@@ -214,8 +214,8 @@ describe('ReactSuspenseFallback', () => {
214 await waitForAll([
215 'Suspend! [A]',
216 // null
217 -
218 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
217 + // pre-warming
218 + 'Suspend! [A]',
219 ]);
220 expect(ReactNoop).toMatchRenderedOutput(null);
221 });
@@ -233,8 +233,8 @@ describe('ReactSuspenseFallback', () => {
233 await waitForAll([
234 'Suspend! [A]',
235 // null
236 -
237 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
236 + // pre-warming
237 + 'Suspend! [A]',
238 ]);
239 expect(ReactNoop).toMatchRenderedOutput(null);
240 });
packages/react-reconciler/src/__tests__/ReactSuspenseList-test.js
+74 -73
@@ -245,9 +245,9 @@ describe('ReactSuspenseList', () => {
245 'Loading B',
246 'Suspend! [C]',
247 'Loading C',
248 - ...(gate('enableSiblingPrerendering')
249 - ? ['Suspend! [B]', 'Suspend! [C]']
250 - : []),
248 + // pre-warming
249 + 'Suspend! [B]',
250 + 'Suspend! [C]',
251 ]);
252
253 expect(ReactNoop).toMatchRenderedOutput(
@@ -260,7 +260,7 @@ describe('ReactSuspenseList', () => {
260
261 await act(() => C.resolve());
262 assertLog(
263 - gate('enableSiblingPrerendering')
263 + gate('alwaysThrottleRetries')
264 ? ['Suspend! [B]', 'C', 'Suspend! [B]']
265 : ['C'],
266 );
@@ -746,7 +746,8 @@ describe('ReactSuspenseList', () => {
746 await waitForAll([
747 'Suspend! [A]',
748 'Loading',
749 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
749 + // pre-warming
750 + 'Suspend! [A]',
751 ]);
752
753 expect(ReactNoop).toMatchRenderedOutput(<span>Loading</span>);
@@ -919,8 +920,8 @@ describe('ReactSuspenseList', () => {
920 'Loading A',
921 'Loading B',
922 'Loading C',
922 -
923 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
923 + // pre-warming
924 + 'Suspend! [A]',
925 ]);
926
927 expect(ReactNoop).toMatchRenderedOutput(
@@ -932,12 +933,7 @@ describe('ReactSuspenseList', () => {
933 );
934
935 await act(() => A.resolve());
935 - assertLog([
936 - 'A',
937 - 'Suspend! [B]',
938 -
939 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []),
940 - ]);
936 + assertLog(['A', 'Suspend! [B]', 'Suspend! [B]']);
937
938 expect(ReactNoop).toMatchRenderedOutput(
939 <>
@@ -990,8 +986,8 @@ describe('ReactSuspenseList', () => {
986 'Loading C',
987 'Loading B',
988 'Loading A',
993 -
994 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C]'] : []),
989 + // pre-warming
990 + 'Suspend! [C]',
991 ]);
992
993 expect(ReactNoop).toMatchRenderedOutput(
@@ -1006,8 +1002,8 @@ describe('ReactSuspenseList', () => {
1002 assertLog([
1003 'C',
1004 'Suspend! [B]',
1009 -
1010 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []),
1005 + // pre-warming
1006 + 'Suspend! [B]',
1007 ]);
1008
1009 expect(ReactNoop).toMatchRenderedOutput(
@@ -1133,8 +1129,8 @@ describe('ReactSuspenseList', () => {
1129 'A',
1130 'C',
1131 'Suspend! [E]',
1136 -
1137 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [E]'] : []),
1132 + // pre-warming
1133 + 'Suspend! [E]',
1134 ]);
1135
1136 // We can now resolve the full head.
@@ -1153,8 +1149,8 @@ describe('ReactSuspenseList', () => {
1149 assertLog([
1150 'E',
1151 'Suspend! [F]',
1156 -
1157 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [F]'] : []),
1152 + // pre-warming
1153 + 'Suspend! [F]',
1154 ]);
1155
1156 // In the tail we can resolve one-by-one.
@@ -1296,10 +1292,9 @@ describe('ReactSuspenseList', () => {
1292 'E',
1293 'Suspend! [F]',
1294 'Loading F',
1299 -
1300 - ...(gate('enableSiblingPrerendering')
1301 - ? ['Suspend! [D]', 'Suspend! [F]']
1302 - : []),
1295 + // pre-warming
1296 + 'Suspend! [D]',
1297 + 'Suspend! [F]',
1298 ]);
1299
1300 // This will suspend, since the boundaries are avoided. Give them
@@ -1347,8 +1342,8 @@ describe('ReactSuspenseList', () => {
1342 'D',
1343 'F',
1344 'Suspend! [B]',
1350 -
1351 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []),
1345 + // pre-warming
1346 + 'Suspend! [B]',
1347 ]);
1348
1349 // We can now resolve the full head.
@@ -1369,8 +1364,8 @@ describe('ReactSuspenseList', () => {
1364 assertLog([
1365 'B',
1366 'Suspend! [A]',
1372 -
1373 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
1367 + // pre-warming
1368 + 'Suspend! [A]',
1369 ]);
1370
1371 // In the tail we can resolve one-by-one.
@@ -1493,8 +1488,8 @@ describe('ReactSuspenseList', () => {
1488 await waitForAll([
1489 'Suspend! [A]',
1490 'Loading A',
1496 -
1497 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
1491 + // pre-warming
1492 + 'Suspend! [A]',
1493 ]);
1494
1495 expect(ReactNoop).toMatchRenderedOutput(<span>Loading A</span>);
@@ -2007,8 +2002,8 @@ describe('ReactSuspenseList', () => {
2002 'Suspend! [D]',
2003 'Loading D',
2004 'Loading E',
2010 -
2011 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []),
2005 + // pre-warming
2006 + 'Suspend! [B]',
2007 ]);
2008
2009 // This is suspended due to the update to D causing a loading state.
@@ -2030,7 +2025,11 @@ describe('ReactSuspenseList', () => {
2025
2026 await B.resolve();
2027
2033 - await waitForAll(['B', 'Suspend! [C]']);
2028 + await waitForAll([
2029 + 'B',
2030 + 'Suspend! [C]',
2031 + ...(!gate('alwaysThrottleRetries') ? ['Suspend! [C]'] : []),
2032 + ]);
2033
2034 // Incremental loading is suspended.
2035 jest.advanceTimersByTime(500);
@@ -2425,8 +2424,8 @@ describe('ReactSuspenseList', () => {
2424 'A',
2425 'Suspend! [B]',
2426 'Loading B',
2428 -
2429 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []),
2427 + // pre-warming
2428 + 'Suspend! [B]',
2429 ]);
2430
2431 expect(ReactNoop).toMatchRenderedOutput(
@@ -2511,8 +2510,8 @@ describe('ReactSuspenseList', () => {
2510 await waitForAll([
2511 'Suspend! [A]',
2512 'Loading A',
2514 -
2515 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
2513 + // pre-warming
2514 + 'Suspend! [A]',
2515 ]);
2516 expect(ReactNoop).toMatchRenderedOutput(<span>Loading A</span>);
2517 });
@@ -2795,8 +2794,8 @@ describe('ReactSuspenseList', () => {
2794 'B',
2795 'Suspend! [C]',
2796 'Fallback',
2798 -
2799 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C]'] : []),
2797 + // pre-warming
2798 + 'Suspend! [C]',
2799 ]);
2800 expect(ReactNoop).toMatchRenderedOutput(
2801 <>
@@ -2805,7 +2804,9 @@ describe('ReactSuspenseList', () => {
2804 <span>Loading...</span>
2805 </>,
2806 );
2808 - expect(onRender).toHaveBeenCalledTimes(1);
2807 + expect(onRender).toHaveBeenCalledTimes(
2808 + gate('alwaysThrottleRetries') ? 1 : 2,
2809 + );
2810
2811 // The treeBaseDuration should be the time to render each child. The last
2812 // one counts the fallback time.
@@ -2828,12 +2829,18 @@ describe('ReactSuspenseList', () => {
2829 <span>C</span>
2830 </>,
2831 );
2831 - expect(onRender).toHaveBeenCalledTimes(2);
2832 + expect(onRender).toHaveBeenCalledTimes(
2833 + gate('alwaysThrottleRetries') ? 2 : 3,
2834 + );
2835
2836 // actualDuration
2834 - expect(onRender.mock.calls[1][2]).toBe(1 + 4 + 5);
2837 + expect(onRender.mock.calls[1][2]).toBe(
2838 + gate('alwaysThrottleRetries') ? 1 + 4 + 5 : 5,
2839 + );
2840 // treeBaseDuration
2836 - expect(onRender.mock.calls[1][3]).toBe(1 + 4 + 5);
2841 + expect(onRender.mock.calls[1][3]).toBe(
2842 + gate('alwaysThrottleRetries') ? 1 + 4 + 5 : 8,
2843 + );
2844
2845 ReactNoop.render(<App addRow={true} suspendTail={true} />);
2846
@@ -2850,8 +2857,8 @@ describe('ReactSuspenseList', () => {
2857 'Fallback',
2858 // Lastly we render the tail.
2859 'Fallback',
2853 -
2854 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C]'] : []),
2860 + // pre-warming
2861 + 'Suspend! [C]',
2862 ]);
2863
2864 // Flush suspended time.
@@ -2867,7 +2874,7 @@ describe('ReactSuspenseList', () => {
2874 </>,
2875 );
2876 expect(onRender).toHaveBeenCalledTimes(
2870 - gate('enableSiblingPrerendering') ? 4 : 3,
2877 + gate('alwaysThrottleRetries') ? 4 : 5,
2878 );
2879
2880 // The treeBaseDuration should be the time to render the first two
@@ -2877,16 +2884,20 @@ describe('ReactSuspenseList', () => {
2884 // with force fallback mode.
2885
2886 // actualDuration
2880 - expect(onRender.mock.calls[2][2]).toBe((1 + 4 + 5 + 3) * 2 + 3);
2887 + expect(onRender.mock.calls[2][2]).toBe(
2888 + gate('alwaysThrottleRetries') ? (1 + 4 + 5 + 3) * 2 + 3 : 10,
2889 + );
2890 // treeBaseDuration
2882 - expect(onRender.mock.calls[2][3]).toBe(1 + 4 + 3 + 3);
2891 + expect(onRender.mock.calls[2][3]).toBe(
2892 + gate('alwaysThrottleRetries') ? 1 + 4 + 3 + 3 : 10,
2893 + );
2894
2895 await act(() => C.resolve());
2896 assertLog([
2897 'C',
2898 'Suspend! [D]',
2888 -
2889 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [D]'] : []),
2899 + // pre-warming
2900 + 'Suspend! [D]',
2901 ]);
2902 expect(ReactNoop).toMatchRenderedOutput(
2903 <>
@@ -2897,21 +2908,16 @@ describe('ReactSuspenseList', () => {
2908 </>,
2909 );
2910
2900 - if (gate('enableSiblingPrerendering')) {
2901 - expect(onRender).toHaveBeenCalledTimes(6);
2902 -
2903 - // actualDuration
2904 - expect(onRender.mock.calls[5][2]).toBe(12);
2905 - // treeBaseDuration
2906 - expect(onRender.mock.calls[5][3]).toBe(1 + 4 + 5 + 3);
2907 - } else {
2908 - expect(onRender).toHaveBeenCalledTimes(4);
2911 + expect(onRender).toHaveBeenCalledTimes(
2912 + gate('alwaysThrottleRetries') ? 6 : 7,
2913 + );
2914
2910 - // actualDuration
2911 - expect(onRender.mock.calls[3][2]).toBe(5 + 12);
2912 - // treeBaseDuration
2913 - expect(onRender.mock.calls[3][3]).toBe(1 + 4 + 5 + 3);
2914 - }
2915 + // actualDuration
2916 + expect(onRender.mock.calls[5][2]).toBe(
2917 + gate('alwaysThrottleRetries') ? 12 : 17,
2918 + );
2919 + // treeBaseDuration
2920 + expect(onRender.mock.calls[5][3]).toBe(1 + 4 + 5 + 3);
2921 });
2922
2923 // @gate enableSuspenseList
@@ -2977,8 +2983,8 @@ describe('ReactSuspenseList', () => {
2983 'Loading A',
2984 'Loading B',
2985 'Loading C',
2980 -
2981 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
2986 + // pre-warming
2987 + 'Suspend! [A]',
2988 ]);
2989
2990 expect(ReactNoop).toMatchRenderedOutput(
@@ -2990,12 +2996,7 @@ describe('ReactSuspenseList', () => {
2996 );
2997
2998 await act(() => A.resolve());
2993 - assertLog([
2994 - 'A',
2995 - 'Suspend! [B]',
2996 -
2997 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []),
2998 - ]);
2999 + assertLog(['A', 'Suspend! [B]', 'Suspend! [B]']);
3000 expect(ReactNoop).toMatchRenderedOutput(
3001 <>
3002 <span>A</span>
packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js
+59 -59
@@ -139,8 +139,10 @@ describe('ReactSuspensePlaceholder', () => {
139 'A',
140 'Suspend! [B]',
141 'Loading...',
142 -
143 - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [B]', 'C'] : []),
142 + // pre-warming
143 + 'A',
144 + 'Suspend! [B]',
145 + 'C',
146 ]);
147 expect(ReactNoop).toMatchRenderedOutput('Loading...');
148
@@ -160,8 +162,9 @@ describe('ReactSuspensePlaceholder', () => {
162 await waitForAll([
163 'Suspend! [B2]',
164 'Loading...',
163 -
164 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B2]', 'C'] : []),
165 + // pre-warming
166 + 'Suspend! [B2]',
167 + 'C',
168 ]);
169
170 // Time out the update
@@ -209,8 +212,10 @@ describe('ReactSuspensePlaceholder', () => {
212 'A',
213 'Suspend! [B]',
214 'Loading...',
212 -
213 - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [B]', 'C'] : []),
215 + // pre-warming
216 + 'A',
217 + 'Suspend! [B]',
218 + 'C',
219 ]);
220
221 expect(ReactNoop).not.toMatchRenderedOutput('ABC');
@@ -225,8 +230,10 @@ describe('ReactSuspensePlaceholder', () => {
230 'A',
231 'Suspend! [B2]',
232 'Loading...',
228 -
229 - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [B2]', 'C'] : []),
233 + // pre-warming
234 + 'A',
235 + 'Suspend! [B2]',
236 + 'C',
237 ]);
238 // Time out the update
239 jest.advanceTimersByTime(750);
@@ -264,8 +271,10 @@ describe('ReactSuspensePlaceholder', () => {
271 'a',
272 'Suspend! [b]',
273 'Loading...',
267 -
268 - ...(gate('enableSiblingPrerendering') ? ['a', 'Suspend! [b]', 'c'] : []),
274 + // pre-warming
275 + 'a',
276 + 'Suspend! [b]',
277 + 'c',
278 ]);
279
280 expect(ReactNoop).toMatchRenderedOutput(<uppercase>LOADING...</uppercase>);
@@ -280,8 +289,9 @@ describe('ReactSuspensePlaceholder', () => {
289 'a',
290 'Suspend! [b2]',
291 'Loading...',
283 -
284 - ...(gate('enableSiblingPrerendering') ? ['a', 'Suspend! [b2]', 'c'] : []),
292 + 'a',
293 + 'Suspend! [b2]',
294 + 'c',
295 ]);
296 // Time out the update
297 jest.advanceTimersByTime(750);
@@ -375,15 +385,17 @@ describe('ReactSuspensePlaceholder', () => {
385 'Suspending',
386 'Suspend! [Loaded]',
387 'Fallback',
378 -
379 - ...(gate('enableSiblingPrerendering')
380 - ? ['Suspending', 'Suspend! [Loaded]', 'Text']
381 - : []),
388 + // pre-warming
389 + 'Suspending',
390 + 'Suspend! [Loaded]',
391 + 'Text',
392 ]);
393 // Since this is initial render we immediately commit the fallback. Another test below
394 // deals with the update case where this suspends.
395 expect(ReactNoop).toMatchRenderedOutput('Loading...');
386 - expect(onRender).toHaveBeenCalledTimes(1);
396 + expect(onRender).toHaveBeenCalledTimes(
397 + gate('alwaysThrottleRetries') ? 1 : 2,
398 + );
399
400 // Initial mount only shows the "Loading..." Fallback.
401 // The treeBaseDuration then should be 10ms spent rendering Fallback,
@@ -401,21 +413,12 @@ describe('ReactSuspensePlaceholder', () => {
413 ]);
414 expect(ReactNoop).toMatchRenderedOutput('LoadedText');
415
404 - if (gate('enableSiblingPrerendering')) {
405 - expect(onRender).toHaveBeenCalledTimes(3);
406 -
407 - // When the suspending data is resolved and our final UI is rendered,
408 - // both times should include the 8ms re-rendering Suspending and AsyncText.
409 - expect(onRender.mock.calls[2][2]).toBe(8);
410 - expect(onRender.mock.calls[2][3]).toBe(8);
411 - } else {
412 - expect(onRender).toHaveBeenCalledTimes(2);
413 -
414 - // When the suspending data is resolved and our final UI is rendered,
415 - // both times should include the 8ms re-rendering Suspending and AsyncText.
416 - expect(onRender.mock.calls[1][2]).toBe(8);
417 - expect(onRender.mock.calls[1][3]).toBe(8);
418 - }
416 + expect(onRender).toHaveBeenCalledTimes(3);
417 +
418 + // When the suspending data is resolved and our final UI is rendered,
419 + // both times should include the 8ms re-rendering Suspending and AsyncText.
420 + expect(onRender.mock.calls[2][2]).toBe(8);
421 + expect(onRender.mock.calls[2][3]).toBe(8);
422 });
423 });
424
@@ -536,14 +539,16 @@ describe('ReactSuspensePlaceholder', () => {
539 'Suspending',
540 'Suspend! [Loaded]',
541 'Fallback',
539 -
540 - ...(gate('enableSiblingPrerendering')
541 - ? ['Suspending', 'Suspend! [Loaded]', 'Text']
542 - : []),
542 + // pre-warming
543 + 'Suspending',
544 + 'Suspend! [Loaded]',
545 + 'Text',
546 ]);
547 // Show the fallback UI.
548 expect(ReactNoop).toMatchRenderedOutput('Loading...');
546 - expect(onRender).toHaveBeenCalledTimes(2);
549 + expect(onRender).toHaveBeenCalledTimes(
550 + gate('alwaysThrottleRetries') ? 2 : 3,
551 + );
552
553 jest.advanceTimersByTime(900);
554
@@ -579,15 +584,16 @@ describe('ReactSuspensePlaceholder', () => {
584 'Suspend! [Loaded]',
585 'Fallback',
586 'Suspend! [Sibling]',
582 -
583 - ...(gate('enableSiblingPrerendering')
584 - ? ['Suspending', 'Suspend! [Loaded]', 'New', 'Suspend! [Sibling]']
585 - : []),
587 + // pre-warming
588 + 'Suspending',
589 + 'Suspend! [Loaded]',
590 + 'New',
591 + 'Suspend! [Sibling]',
592 ]);
593 expect(ReactNoop).toMatchRenderedOutput('Loading...');
594
595 expect(onRender).toHaveBeenCalledTimes(
590 - gate('enableSiblingPrerendering') ? 4 : 3,
596 + gate('alwaysThrottleRetries') ? 4 : 5,
597 );
598
599 // Resolve the pending promise.
@@ -600,23 +606,17 @@ describe('ReactSuspensePlaceholder', () => {
606 await waitForAll(['Suspending', 'Loaded', 'New', 'Sibling']);
607 });
608
603 - if (gate('enableSiblingPrerendering')) {
604 - expect(onRender).toHaveBeenCalledTimes(5);
605 -
606 - // When the suspending data is resolved and our final UI is rendered,
607 - // both times should include the 6ms rendering Text,
608 - // the 2ms rendering Suspending, and the 1ms rendering AsyncText.
609 - expect(onRender.mock.calls[4][2]).toBe(9);
610 - expect(onRender.mock.calls[4][3]).toBe(9);
611 - } else {
612 - expect(onRender).toHaveBeenCalledTimes(4);
613 -
614 - // When the suspending data is resolved and our final UI is rendered,
615 - // both times should include the 6ms rendering Text,
616 - // the 2ms rendering Suspending, and the 1ms rendering AsyncText.
617 - expect(onRender.mock.calls[3][2]).toBe(9);
618 - expect(onRender.mock.calls[3][3]).toBe(9);
619 - }
609 + expect(onRender).toHaveBeenCalledTimes(
610 + gate('alwaysThrottleRetries') ? 5 : 6,
611 + );
612 +
613 + // When the suspending data is resolved and our final UI is rendered,
614 + // both times should include the 6ms rendering Text,
615 + // the 2ms rendering Suspending, and the 1ms rendering AsyncText.
616 + expect(onRender.mock.calls[4][2]).toBe(9);
617 + expect(onRender.mock.calls[4][3]).toBe(
618 + gate('alwaysThrottleRetries') ? 9 : 10,
619 + );
620 });
621 });
622 });
packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js
+107 -254
@@ -296,7 +296,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
296 // A suspends
297 'Suspend! [A]',
298
299 - ...(gate('enableSiblingPrerendering') ? ['B'] : []),
299 + // pre-warming
300 + 'B',
301 + // end pre-warming
302
303 // We immediately unwind and switch to a fallback without
304 // rendering siblings.
@@ -334,10 +336,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
336 'Loading A...',
337 'Suspend! [B]',
338 'Loading B...',
337 -
338 - ...(gate('enableSiblingPrerendering')
339 - ? ['Suspend! [A]', 'Suspend! [B]']
340 - : []),
339 + // pre-warming
340 + 'Suspend! [A]',
341 + 'Suspend! [B]',
342 ]);
343 expect(ReactNoop).toMatchRenderedOutput(
344 <>
@@ -351,8 +352,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
352 await act(() => resolveText('A'));
353 assertLog([
354 'A',
354 -
355 - ...(gate('enableSiblingPrerendering')
355 + ...(gate('alwaysThrottleRetries')
356 ? ['Suspend! [B]', 'Suspend! [B]']
357 : []),
358 ]);
@@ -395,9 +395,10 @@ describe('ReactSuspenseWithNoopRenderer', () => {
395 await waitForAll([
396 'A',
397 'Suspend! [B]',
398 -
399 - ...(gate('enableSiblingPrerendering') ? ['C', 'D'] : []),
400 -
398 + // pre-warming
399 + 'C',
400 + 'D',
401 + // end pre-warming
402 'Loading...',
403 ]);
404 // Did not commit yet.
@@ -509,8 +510,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
510 await waitForAll([
511 'Suspend! [Result]',
512 'Loading...',
512 -
513 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Result]'] : []),
513 + // pre-warming
514 + 'Suspend! [Result]',
515 ]);
516 expect(ReactNoop).toMatchRenderedOutput(<span prop="Loading..." />);
517
@@ -562,8 +563,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
563 'A',
564 'Suspend! [1]',
565 'Loading...',
565 -
566 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [1]'] : []),
566 + // pre-warming
567 + 'Suspend! [1]',
568 ]);
569
570 await act(() => resolveText('1'));
@@ -631,9 +632,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
632 });
633 await waitForAll([
634 'Suspend! [A]',
634 -
635 - ...(gate('enableSiblingPrerendering') ? ['B'] : []),
636 -
635 + // pre-warming
636 + 'B',
637 + // end pre-warming
638 'Loading...',
639 ]);
640 expect(ReactNoop).toMatchRenderedOutput(null);
@@ -765,14 +766,10 @@ describe('ReactSuspenseWithNoopRenderer', () => {
766 // The async content suspends
767 'Suspend! [Outer content]',
768 'Loading outer...',
768 -
769 - ...(gate('enableSiblingPrerendering')
770 - ? [
771 - 'Suspend! [Outer content]',
772 - 'Suspend! [Inner content]',
773 - 'Loading inner...',
774 - ]
775 - : []),
769 + // pre-warming
770 + 'Suspend! [Outer content]',
771 + 'Suspend! [Inner content]',
772 + 'Loading inner...',
773 ]);
774 // The outer loading state finishes immediately.
775 expect(ReactNoop).toMatchRenderedOutput(
@@ -952,10 +949,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
949 await waitForAll([
950 'Suspend! [A]',
951 'Loading...',
955 -
956 - ...(gate('enableSiblingPrerendering')
957 - ? ['Suspend! [A]', 'Suspend! [B]']
958 - : []),
952 + // pre-warming
953 + 'Suspend! [A]',
954 + 'Suspend! [B]',
955 ]);
956 expect(ReactNoop).toMatchRenderedOutput(<span prop="Loading..." />);
957
@@ -1068,10 +1064,10 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1064 ReactNoop.render(<App />);
1065 await waitForAll([
1066 'Suspend! [A]',
1071 -
1072 - ...(gate('enableSiblingPrerendering')
1073 - ? ['Suspend! [A]', 'Suspend! [B]', 'Suspend! [C]']
1074 - : []),
1067 + // pre-warming
1068 + 'Suspend! [A]',
1069 + 'Suspend! [B]',
1070 + 'Suspend! [C]',
1071 ]);
1072 expect(ReactNoop).toMatchRenderedOutput('Loading...');
1073
@@ -1735,10 +1731,10 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1731 // A suspends
1732 'Suspend! [A]',
1733 'Loading...',
1738 -
1739 - ...(gate('enableSiblingPrerendering')
1740 - ? ['Suspend! [A]', 'Suspend! [B]', 'Loading more...']
1741 - : []),
1734 + // pre-warming
1735 + 'Suspend! [A]',
1736 + 'Suspend! [B]',
1737 + 'Loading more...',
1738 ]);
1739 expect(ReactNoop).toMatchRenderedOutput(<span prop="Loading..." />);
1740
@@ -1753,8 +1749,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1749 // B suspends
1750 'Suspend! [B]',
1751 'Loading more...',
1756 -
1757 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []),
1752 + // pre-warming
1753 + 'Suspend! [B]',
1754 ]);
1755
1756 // Because we've already been waiting for so long we've exceeded
@@ -1799,10 +1795,10 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1795 // A suspends
1796 'Suspend! [A]',
1797 'Loading...',
1802 -
1803 - ...(gate('enableSiblingPrerendering')
1804 - ? ['Suspend! [A]', 'Suspend! [B]', 'Loading more...']
1805 - : []),
1798 + // pre-warming
1799 + 'Suspend! [A]',
1800 + 'Suspend! [B]',
1801 + 'Loading more...',
1802 ]);
1803 expect(ReactNoop).toMatchRenderedOutput(<span prop="Loading..." />);
1804
@@ -1881,10 +1877,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1877 'Loading A...',
1878 'Suspend! [B]',
1879 'Loading B...',
1884 -
1885 - ...(gate('enableSiblingPrerendering')
1886 - ? ['Suspend! [A]', 'Suspend! [B]']
1887 - : []),
1880 + // pre-warming
1881 + 'Suspend! [A]',
1882 + 'Suspend! [B]',
1883 ]);
1884 expect(ReactNoop).toMatchRenderedOutput(
1885 <>
@@ -2035,8 +2030,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2030
2031 assertLog([
2032 'Suspend! [A]',
2038 -
2039 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
2033 + // pre-warming
2034 + 'Suspend! [A]',
2035 ]);
2036 expect(ReactNoop).toMatchRenderedOutput('Loading...');
2037
@@ -2046,10 +2041,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2041
2042 assertLog([
2043 'Suspend! [A]',
2049 -
2050 - ...(gate('enableSiblingPrerendering')
2051 - ? ['Suspend! [A]', 'Suspend! [B]']
2052 - : []),
2044 + // pre-warming
2045 + 'Suspend! [A]',
2046 + 'Suspend! [B]',
2047 ]);
2048 });
2049
@@ -2108,8 +2102,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2102
2103 assertLog([
2104 'Suspend! [A]',
2111 -
2112 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
2105 + // pre-warming
2106 + 'Suspend! [A]',
2107 ]);
2108 await resolveText('A');
2109
@@ -2138,8 +2132,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2132
2133 assertLog([
2134 'Suspend! [A]',
2141 -
2142 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
2135 + // pre-warming
2136 + 'Suspend! [A]',
2137 ]);
2138 await resolveText('A');
2139
@@ -2168,8 +2162,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2162 'Foo',
2163 'Suspend! [A]',
2164 'Initial load...',
2171 -
2172 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]', 'B'] : []),
2165 + // pre-warming
2166 + 'Suspend! [A]',
2167 + 'B',
2168 ]);
2169 expect(ReactNoop).toMatchRenderedOutput(<span prop="Initial load..." />);
2170
@@ -2191,8 +2186,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2186 'Suspend! [C]',
2187 'Updating...',
2188 'B',
2194 -
2195 - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [C]'] : []),
2189 + // pre-warming
2190 + 'A',
2191 + 'Suspend! [C]',
2192 ]);
2193 // Flush to skip suspended time.
2194 Scheduler.unstable_advanceTime(600);
@@ -2240,8 +2236,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2236 'Suspend! [A]',
2237 'B',
2238 // null
2243 -
2244 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
2239 + // pre-warming
2240 + 'Suspend! [A]',
2241 ]);
2242 expect(ReactNoop).toMatchRenderedOutput(<span prop="B" />);
2243
@@ -2263,8 +2259,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2259 'Suspend! [C]',
2260 // null
2261 'B',
2266 -
2267 - ...(gate('enableSiblingPrerendering') ? ['A', 'Suspend! [C]'] : []),
2262 + // pre-warming
2263 + 'A',
2264 + 'Suspend! [C]',
2265 ]);
2266 // Flush to skip suspended time.
2267 Scheduler.unstable_advanceTime(600);
@@ -2312,8 +2309,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2309 'A',
2310 'Suspend! [B]',
2311 'Loading B...',
2315 -
2316 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []),
2312 + // pre-warming
2313 + 'Suspend! [B]',
2314 ]);
2315 // Flush to skip suspended time.
2316 Scheduler.unstable_advanceTime(600);
@@ -2394,8 +2391,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2391 'A',
2392 'Suspend! [B]',
2393 // Null
2397 -
2398 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []),
2394 + // pre-warming
2395 + 'Suspend! [B]',
2396 ]);
2397 // Still suspended.
2398 expect(ReactNoop).toMatchRenderedOutput(<span prop="A" />);
@@ -2424,8 +2421,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2421 await waitForAll([
2422 'Suspend! [A]',
2423 'Loading...',
2427 -
2428 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
2424 + // pre-warming
2425 + 'Suspend! [A]',
2426 ]);
2427 // Only a short time is needed to unsuspend the initial loading state.
2428 Scheduler.unstable_advanceTime(400);
@@ -2478,8 +2475,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2475 await waitForAll([
2476 'Suspend! [A]',
2477 'Loading...',
2481 -
2482 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
2478 + // pre-warming
2479 + 'Suspend! [A]',
2480 ]);
2481 // Only a short time is needed to unsuspend the initial loading state.
2482 Scheduler.unstable_advanceTime(400);
@@ -2538,8 +2535,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2535 await waitForAll([
2536 'Suspend! [A]',
2537 'Loading...',
2541 -
2542 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
2538 + // pre-warming
2539 + 'Suspend! [A]',
2540 ]);
2541 // Only a short time is needed to unsuspend the initial loading state.
2542 Scheduler.unstable_advanceTime(400);
@@ -2587,8 +2584,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2584 await waitForAll([
2585 'Suspend! [A]',
2586 'Loading...',
2590 -
2591 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
2587 + // pre-warming
2588 + 'Suspend! [A]',
2589 ]);
2590 // Only a short time is needed to unsuspend the initial loading state.
2591 Scheduler.unstable_advanceTime(400);
@@ -2652,8 +2649,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2649 await waitForAll([
2650 'Suspend! [A]',
2651 'Loading...',
2655 -
2656 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
2652 + // pre-warming
2653 + 'Suspend! [A]',
2654 ]);
2655 // Only a short time is needed to unsuspend the initial loading state.
2656 Scheduler.unstable_advanceTime(400);
@@ -2727,8 +2724,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2724 await waitForAll([
2725 'Suspend! [A]',
2726 'Loading...',
2730 -
2731 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [A]'] : []),
2727 + // pre-warming
2728 + 'Suspend! [A]',
2729 ]);
2730 // Only a short time is needed to unsuspend the initial loading state.
2731 Scheduler.unstable_advanceTime(400);
@@ -2794,8 +2791,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2791 'Hi!',
2792 'Suspend! [A]',
2793 'Loading...',
2797 -
2798 - ...(gate('enableSiblingPrerendering') ? ['Hi!', 'Suspend! [A]'] : []),
2794 + // pre-warming
2795 + 'Hi!',
2796 + 'Suspend! [A]',
2797 ]);
2798 await act(() => resolveText('A'));
2799 assertLog(['Hi!', 'A']);
@@ -3117,73 +3115,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3115 },
3116 );
3117
3120 - // TODO: This test is substantially different when sibling prerendering is
3121 - // enabled because we never work on Idle updates if there are pending retries.
3122 - // This was already an issue before the enableSiblingPrerendering change but
3123 - // it's exacerbated by the fact that we schedule a retry immediately. I'm not
3124 - // going to bother to update this test for now, though, because Idle updates
3125 - // aren't actually used and should probably just be deleted unless/until we
3126 - // finish the feature. Feel free to delete if needed.
3127 - // @gate !enableSiblingPrerendering
3128 - // @gate enableLegacyCache
3129 - it(
3130 - 'multiple updates originating inside a Suspense boundary at different ' +
3131 - 'priority levels are not dropped, including Idle updates',
3132 - async () => {
3133 - const {useState} = React;
3134 - const root = ReactNoop.createRoot();
3135 -
3136 - function Parent() {
3137 - return (
3138 - <>
3139 - <Suspense fallback={<Text text="Loading..." />}>
3140 - <Child />
3141 - </Suspense>
3142 - </>
3143 - );
3144 - }
3145 -
3146 - let setText;
3147 - function Child() {
3148 - const [text, _setText] = useState('A');
3149 - setText = _setText;
3150 - return <AsyncText text={text} />;
3151 - }
3152 -
3153 - await seedNextTextCache('A');
3154 - await act(() => {
3155 - root.render(<Parent />);
3156 - });
3157 - assertLog(['A']);
3158 - expect(root).toMatchRenderedOutput(<span prop="A" />);
3159 -
3160 - await act(async () => {
3161 - // Schedule two updates that originate inside the Suspense boundary.
3162 - // The first one causes the boundary to suspend. The second one is at
3163 - // lower priority and unsuspends it by hiding the async component.
3164 - setText('B');
3165 -
3166 - await resolveText('C');
3167 - ReactNoop.idleUpdates(() => {
3168 - setText('C');
3169 - });
3170 -
3171 - // First we attempt the high pri update. It suspends.
3172 - await waitForPaint(['Suspend! [B]', 'Loading...']);
3173 - expect(root).toMatchRenderedOutput(
3174 - <>
3175 - <span hidden={true} prop="A" />
3176 - <span prop="Loading..." />
3177 - </>,
3178 - );
3179 -
3180 - // Now flush the remaining work. The Idle update successfully finishes.
3181 - await waitForAll(['C']);
3182 - expect(root).toMatchRenderedOutput(<span prop="C" />);
3183 - });
3184 - },
3185 - );
3186 -
3118 // @gate enableLegacyCache
3119 it(
3120 'fallback component can update itself even after a high pri update to ' +
@@ -3226,8 +3157,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3157 await waitForAll([
3158 'Suspend! [B]',
3159 'Loading...',
3229 -
3230 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [B]'] : []),
3160 + // pre-warming
3161 + 'Suspend! [B]',
3162 ]);
3163 });
3164
@@ -3264,8 +3195,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3195
3196 // Then complete the update to the fallback.
3197 'Still loading...',
3267 -
3268 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C]'] : []),
3198 + 'Suspend! [C]',
3199 ]);
3200 expect(root).toMatchRenderedOutput(
3201 <>
@@ -3326,12 +3256,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3256 await act(() => {
3257 setText('C');
3258 });
3329 - assertLog([
3330 - 'Suspend! [C]',
3331 - 'Loading...',
3332 -
3333 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C]'] : []),
3334 - ]);
3259 + assertLog(['Suspend! [C]', 'Loading...', 'Suspend! [C]']);
3260
3261 // Commit. This will insert a fragment fiber to wrap around the component
3262 // that triggered the update.
@@ -3411,8 +3336,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3336 assertLog([
3337 'Suspend! [C]',
3338 'Loading...',
3414 -
3415 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [C]'] : []),
3339 + // pre-warming
3340 + 'Suspend! [C]',
3341 ]);
3342
3343 // Commit. This will insert a fragment fiber to wrap around the component
@@ -3444,9 +3369,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3369 // be able to finish rendering.
3370 assertLog([
3371 'Suspend! [D]',
3447 -
3448 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [D]'] : []),
3449 -
3372 + // pre-warming
3373 + 'Suspend! [D]',
3374 + // end pre-warming
3375 'E',
3376 ]);
3377 expect(root).toMatchRenderedOutput(<span prop="E" />);
@@ -3534,10 +3459,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3459 'Outer step: 0',
3460 'Suspend! [Inner text: B]',
3461 'Loading...',
3537 -
3538 - ...(gate('enableSiblingPrerendering')
3539 - ? ['Suspend! [Inner text: B]', 'Inner step: 0']
3540 - : []),
3462 + // pre-warming
3463 + 'Suspend! [Inner text: B]',
3464 + 'Inner step: 0',
3465 ]);
3466 // Commit the placeholder
3467 await advanceTimers(250);
@@ -3566,10 +3490,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3490 'Outer step: 1',
3491 'Suspend! [Inner text: B]',
3492 'Loading...',
3569 -
3570 - ...(gate('enableSiblingPrerendering')
3571 - ? ['Suspend! [Inner text: B]', 'Inner step: 1']
3572 - : []),
3493 + // pre-warming
3494 + 'Suspend! [Inner text: B]',
3495 + 'Inner step: 1',
3496 ]);
3497 expect(root).toMatchRenderedOutput(
3498 <>
@@ -3664,8 +3587,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3587 'Outer: B0',
3588 'Suspend! [Inner: B0]',
3589 'Loading...',
3667 -
3668 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Inner: B0]'] : []),
3590 + // pre-warming
3591 + 'Suspend! [Inner: B0]',
3592 ]);
3593 // Commit the placeholder
3594 await advanceTimers(250);
@@ -3907,77 +3830,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3830 });
3831 });
3832
3910 - // TODO: This test is substantially different when sibling prerendering is
3911 - // enabled because we never work on Idle updates if there are pending retries.
3912 - // This was already an issue before the enableSiblingPrerendering change but
3913 - // it's exacerbated by the fact that we schedule a retry immediately. I'm not
3914 - // going to bother to update this test for now, though, because Idle updates
3915 - // aren't actually used and should probably just be deleted unless/until we
3916 - // finish the feature. Feel free to delete if needed.
3917 - // @gate !enableSiblingPrerendering
3918 - // @gate enableLegacyCache
3919 - it('regression related to Idle updates (outdated experiment): #18657', async () => {
3920 - const {useState} = React;
3921 -
3922 - let setText;
3923 - function App() {
3924 - const [text, _setText] = useState('A');
3925 - setText = _setText;
3926 - return <AsyncText text={text} />;
3927 - }
3928 -
3929 - const root = ReactNoop.createRoot();
3930 - await act(async () => {
3931 - await seedNextTextCache('A');
3932 - root.render(
3933 - <Suspense fallback={<Text text="Loading..." />}>
3934 - <App />
3935 - </Suspense>,
3936 - );
3937 - });
3938 - assertLog(['A']);
3939 - expect(root).toMatchRenderedOutput(<span prop="A" />);
3940 -
3941 - await act(async () => {
3942 - setText('B');
3943 - ReactNoop.idleUpdates(() => {
3944 - setText('C');
3945 - });
3946 -
3947 - // Suspend the first update. This triggers an immediate fallback because
3948 - // it wasn't wrapped in startTransition.
3949 - await waitForPaint(['Suspend! [B]', 'Loading...']);
3950 - expect(root).toMatchRenderedOutput(
3951 - <>
3952 - <span hidden={true} prop="A" />
3953 - <span prop="Loading..." />
3954 - </>,
3955 - );
3956 -
3957 - // Once the fallback renders, proceed to the Idle update. This will
3958 - // also suspend.
3959 - await waitForAll(['Suspend! [C]']);
3960 - });
3961 -
3962 - // Finish loading B.
3963 - await act(async () => {
3964 - setText('B');
3965 - await resolveText('B');
3966 - });
3967 - // We did not try to render the Idle update again because there have been no
3968 - // additional updates since the last time it was attempted.
3969 - assertLog(['B']);
3970 - expect(root).toMatchRenderedOutput(<span prop="B" />);
3971 -
3972 - // Finish loading C.
3973 - await act(async () => {
3974 - setText('C');
3975 - await resolveText('C');
3976 - });
3977 - assertLog(['C']);
3978 - expect(root).toMatchRenderedOutput(<span prop="C" />);
3979 - });
3980 -
3833 // @gate enableLegacyCache
3834 it('retries have lower priority than normal updates', async () => {
3835 const {useState} = React;
@@ -4004,8 +3856,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3856 'A',
3857 'Suspend! [Async]',
3858 'Loading...',
4007 -
4008 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Async]'] : []),
3859 + // pre-warming
3860 + 'Suspend! [Async]',
3861 ]);
3862 expect(root).toMatchRenderedOutput(
3863 <>
@@ -4076,8 +3928,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3928 assertLog([
3929 'Suspend! [Async]',
3930 'Loading...',
4079 -
4080 - ...(gate('enableSiblingPrerendering') ? ['Suspend! [Async]'] : []),
3931 + // pre-warming
3932 + 'Suspend! [Async]',
3933 ]);
3934 expect(root).toMatchRenderedOutput(
3935 <>
@@ -4248,10 +4100,11 @@ describe('ReactSuspenseWithNoopRenderer', () => {
4100 '1',
4101 'Suspend! [Async]',
4102 'Loading...',
4251 -
4252 - ...(gate('enableSiblingPrerendering')
4253 - ? ['Suspend! [Async]', 'A', 'B', 'C']
4254 - : []),
4103 + // pre-warming
4104 + 'Suspend! [Async]',
4105 + 'A',
4106 + 'B',
4107 + 'C',
4108 ]);
4109 expect(root).toMatchRenderedOutput(
4110 <>
packages/react-reconciler/src/__tests__/ReactTransition-test.js
+3 -3
@@ -860,9 +860,9 @@ describe('ReactTransition', () => {
860 assertLog([
861 // Suspend.
862 'Suspend! [Async]',
863 -
864 - ...(gate('enableSiblingPrerendering') ? ['Normal pri: 0'] : []),
865 -
863 + // pre-warming
864 + 'Normal pri: 0',
865 + // end pre-warming
866 'Loading...',
867 ]);
868 expect(root).toMatchRenderedOutput('(empty), Normal pri: 0');
packages/react-reconciler/src/__tests__/ReactTransitionTracing-test.js
+127 -107
@@ -442,7 +442,9 @@ describe('ReactInteractionTracing', () => {
442 await waitForAll([
443 'Suspend [Page Two]',
444 'Loading...',
445 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Page Two]'] : []),
445 + // pre-warming
446 + 'Suspend [Page Two]',
447 + // end pre-warming
448 'onTransitionStart(page transition, 1000)',
449 'onTransitionProgress(page transition, 1000, 2000, [suspense page])',
450 ]);
@@ -533,7 +535,9 @@ describe('ReactInteractionTracing', () => {
535 await waitForAll([
536 'Suspend [Page Two]',
537 'Loading...',
536 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Page Two]'] : []),
538 + // pre-warming
539 + 'Suspend [Page Two]',
540 + // end pre-warming
541 'onTransitionStart(page transition, 1000)',
542 'onTransitionProgress(page transition, 1000, 1000, [suspense page])',
543 ]);
@@ -552,7 +556,9 @@ describe('ReactInteractionTracing', () => {
556 'Suspend [Show Text]',
557 'Show Text Loading...',
558 'Page Two',
555 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Show Text]'] : []),
559 + // pre-warming
560 + 'Suspend [Show Text]',
561 + // end pre-warming
562 'onTransitionStart(text transition, 2000)',
563 'onTransitionProgress(text transition, 2000, 2000, [show text])',
564 ]);
@@ -642,7 +648,9 @@ describe('ReactInteractionTracing', () => {
648 await waitForAll([
649 'Suspend [Page Two]',
650 'Loading...',
645 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Page Two]'] : []),
651 + // pre-warming
652 + 'Suspend [Page Two]',
653 + // end pre-warming
654 'onTransitionStart(page transition, 1000)',
655 'onTransitionProgress(page transition, 1000, 2000, [suspense page])',
656 ]);
@@ -656,9 +664,10 @@ describe('ReactInteractionTracing', () => {
664 'Show Text Loading...',
665 'Suspend [Page Two]',
666 'Loading...',
659 - ...(gate('enableSiblingPrerendering')
660 - ? ['Suspend [Show Text]', 'Suspend [Page Two]']
661 - : []),
667 + // pre-warming
668 + 'Suspend [Show Text]',
669 + 'Suspend [Page Two]',
670 + // end pre-warming
671 'onTransitionStart(show text, 2000)',
672 'onTransitionProgress(show text, 2000, 2000, [show text])',
673 ]);
@@ -761,15 +770,13 @@ describe('ReactInteractionTracing', () => {
770 await waitForAll([
771 'Suspend [Page Two]',
772 'Loading...',
764 - ...(gate('enableSiblingPrerendering')
765 - ? [
766 - 'Suspend [Page Two]',
767 - 'Suspend [Show Text One]',
768 - 'Show Text One Loading...',
769 - 'Suspend [Show Text Two]',
770 - 'Show Text Two Loading...',
771 - ]
772 - : []),
773 + // pre-warming
774 + 'Suspend [Page Two]',
775 + 'Suspend [Show Text One]',
776 + 'Show Text One Loading...',
777 + 'Suspend [Show Text Two]',
778 + 'Show Text Two Loading...',
779 + // end pre-warming
780 'onTransitionStart(page transition, 1000)',
781 'onTransitionProgress(page transition, 1000, 2000, [suspense page])',
782 ]);
@@ -784,9 +791,10 @@ describe('ReactInteractionTracing', () => {
791 'Show Text One Loading...',
792 'Suspend [Show Text Two]',
793 'Show Text Two Loading...',
787 - ...(gate('enableSiblingPrerendering')
788 - ? ['Suspend [Show Text One]', 'Suspend [Show Text Two]']
789 - : []),
794 + // pre-warming
795 + 'Suspend [Show Text One]',
796 + 'Suspend [Show Text Two]',
797 + // end pre-warming
798 'onTransitionProgress(page transition, 1000, 3000, [show text one, show text two])',
799 ]);
800
@@ -899,15 +907,13 @@ describe('ReactInteractionTracing', () => {
907 await waitForAll([
908 'Suspend [Page Two]',
909 'Loading...',
902 - ...(gate('enableSiblingPrerendering')
903 - ? [
904 - 'Suspend [Page Two]',
905 - 'Suspend [Show Text One]',
906 - 'Show Text One Loading...',
907 - 'Suspend [Show Text]',
908 - 'Show Text Loading...',
909 - ]
910 - : []),
910 + // pre-warming
911 + 'Suspend [Page Two]',
912 + 'Suspend [Show Text One]',
913 + 'Show Text One Loading...',
914 + 'Suspend [Show Text]',
915 + 'Show Text Loading...',
916 + // end pre-warming
917 'onTransitionStart(navigate, 1000)',
918 'onTransitionStart(show text one, 1000)',
919 'onTransitionProgress(navigate, 1000, 2000, [suspense page])',
@@ -923,9 +929,10 @@ describe('ReactInteractionTracing', () => {
929 'Show Text One Loading...',
930 'Suspend [Show Text]',
931 'Show Text Loading...',
926 - ...(gate('enableSiblingPrerendering')
927 - ? ['Suspend [Show Text One]', 'Suspend [Show Text]']
928 - : []),
932 + // pre-warming
933 + 'Suspend [Show Text One]',
934 + 'Suspend [Show Text]',
935 + // end pre-warming
936 'onTransitionProgress(navigate, 1000, 3000, [show text one, <null>])',
937 'onTransitionProgress(show text one, 1000, 3000, [show text one, <null>])',
938 ]);
@@ -942,13 +949,11 @@ describe('ReactInteractionTracing', () => {
949 'Show Text Loading...',
950 'Suspend [Show Text Two]',
951 'Show Text Two Loading...',
945 - ...(gate('enableSiblingPrerendering')
946 - ? [
947 - 'Suspend [Show Text One]',
948 - 'Suspend [Show Text]',
949 - 'Suspend [Show Text Two]',
950 - ]
951 - : []),
952 + // pre-warming
953 + 'Suspend [Show Text One]',
954 + 'Suspend [Show Text]',
955 + 'Suspend [Show Text Two]',
956 + // end pre-warming
957 'onTransitionStart(show text two, 3000)',
958 'onTransitionProgress(show text two, 3000, 4000, [show text two])',
959 ]);
@@ -1153,9 +1158,11 @@ describe('ReactInteractionTracing', () => {
1158 await waitForAll([
1159 'Suspend [Page Two]',
1160 'Loading...',
1156 - ...(gate('enableSiblingPrerendering')
1157 - ? ['Suspend [Page Two]', 'Suspend [Marker Text]', 'Loading...']
1158 - : []),
1161 + // pre-warming
1162 + 'Suspend [Page Two]',
1163 + 'Suspend [Marker Text]',
1164 + 'Loading...',
1165 + // end pre-warming
1166 'onTransitionStart(page transition, 1000)',
1167 ]);
1168
@@ -1167,7 +1174,9 @@ describe('ReactInteractionTracing', () => {
1174 'Page Two',
1175 'Suspend [Marker Text]',
1176 'Loading...',
1170 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Marker Text]'] : []),
1177 + // pre-warming
1178 + 'Suspend [Marker Text]',
1179 + // end pre-warming
1180 'onMarkerProgress(page transition, async marker, 1000, 3000, [marker suspense])',
1181 'onMarkerComplete(page transition, sync marker, 1000, 3000)',
1182 ]);
@@ -1271,15 +1280,13 @@ describe('ReactInteractionTracing', () => {
1280 await waitForAll([
1281 'Suspend [Outer Text]',
1282 'Outer...',
1274 - ...(gate('enableSiblingPrerendering')
1275 - ? [
1276 - 'Suspend [Outer Text]',
1277 - 'Suspend [Inner Text One]',
1278 - 'Inner One...',
1279 - 'Suspend [Inner Text Two]',
1280 - 'Inner Two...',
1281 - ]
1282 - : []),
1283 + // pre-warming
1284 + 'Suspend [Outer Text]',
1285 + 'Suspend [Inner Text One]',
1286 + 'Inner One...',
1287 + 'Suspend [Inner Text Two]',
1288 + 'Inner Two...',
1289 + // end pre-warming
1290 'onTransitionStart(page transition, 1000)',
1291 'onMarkerProgress(page transition, outer marker, 1000, 2000, [outer])',
1292 ]);
@@ -1297,9 +1304,9 @@ describe('ReactInteractionTracing', () => {
1304 'Suspend [Inner Text One]',
1305 'Inner One...',
1306 'Inner Text Two',
1300 - ...(gate('enableSiblingPrerendering')
1301 - ? ['Suspend [Inner Text One]']
1302 - : []),
1307 + // pre-warming
1308 + 'Suspend [Inner Text One]',
1309 + // end pre-warming
1310 'onMarkerProgress(page transition, outer marker, 1000, 4000, [inner one])',
1311 'onMarkerComplete(page transition, marker two, 1000, 4000)',
1312 ]);
@@ -1535,9 +1542,10 @@ describe('ReactInteractionTracing', () => {
1542 'Loading...',
1543 'Suspend [Sibling Text]',
1544 'Sibling Loading...',
1538 - ...(gate('enableSiblingPrerendering')
1539 - ? ['Suspend [Page Two]', 'Suspend [Sibling Text]']
1540 - : []),
1545 + // pre-warming
1546 + 'Suspend [Page Two]',
1547 + 'Suspend [Sibling Text]',
1548 + // end pre-warming
1549 'onTransitionStart(transition one, 1000)',
1550 'onMarkerProgress(transition one, parent, 1000, 2000, [suspense page, suspense sibling])',
1551 'onMarkerProgress(transition one, marker one, 1000, 2000, [suspense page])',
@@ -1553,9 +1561,10 @@ describe('ReactInteractionTracing', () => {
1561 'Loading...',
1562 'Suspend [Sibling Text]',
1563 'Sibling Loading...',
1556 - ...(gate('enableSiblingPrerendering')
1557 - ? ['Suspend [Page Two]', 'Suspend [Sibling Text]']
1558 - : []),
1564 + // pre-warming
1565 + 'Suspend [Page Two]',
1566 + 'Suspend [Sibling Text]',
1567 + // end pre-warming
1568 'onMarkerProgress(transition one, parent, 1000, 3000, [suspense sibling])',
1569 'onMarkerIncomplete(transition one, marker one, 1000, [{endTime: 3000, name: marker one, type: marker}, {endTime: 3000, name: suspense page, type: suspense}])',
1570 'onMarkerIncomplete(transition one, parent, 1000, [{endTime: 3000, name: marker one, type: marker}, {endTime: 3000, name: suspense page, type: suspense}])',
@@ -1569,9 +1578,9 @@ describe('ReactInteractionTracing', () => {
1578 'Loading...',
1579 'Suspend [Sibling Text]',
1580 'Sibling Loading...',
1572 - ...(gate('enableSiblingPrerendering')
1573 - ? ['Suspend [Page Two]', 'Suspend [Sibling Text]']
1574 - : []),
1581 + // pre-warming
1582 + 'Suspend [Page Two]',
1583 + 'Suspend [Sibling Text]',
1584 ]);
1585 });
1586
@@ -1693,9 +1702,10 @@ describe('ReactInteractionTracing', () => {
1702 'Loading One...',
1703 'Suspend [Page Two]',
1704 'Loading Two...',
1696 - ...(gate('enableSiblingPrerendering')
1697 - ? ['Suspend [Page One]', 'Suspend [Page Two]']
1698 - : []),
1705 + // pre-warming
1706 + 'Suspend [Page One]',
1707 + 'Suspend [Page Two]',
1708 + // end pre-warming
1709 'onTransitionStart(transition, 1000)',
1710 'onMarkerProgress(transition, parent, 1000, 2000, [suspense one, suspense two])',
1711 'onMarkerProgress(transition, one, 1000, 2000, [suspense one])',
@@ -1709,7 +1719,9 @@ describe('ReactInteractionTracing', () => {
1719 await waitForAll([
1720 'Suspend [Page Two]',
1721 'Loading Two...',
1712 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Page Two]'] : []),
1722 + // pre-warming
1723 + 'Suspend [Page Two]',
1724 + // end pre-warming
1725 'onMarkerProgress(transition, parent, 1000, 3000, [suspense two])',
1726 'onMarkerIncomplete(transition, one, 1000, [{endTime: 3000, name: one, type: marker}, {endTime: 3000, name: suspense one, type: suspense}])',
1727 'onMarkerIncomplete(transition, parent, 1000, [{endTime: 3000, name: one, type: marker}, {endTime: 3000, name: suspense one, type: suspense}])',
@@ -1836,14 +1848,12 @@ describe('ReactInteractionTracing', () => {
1848 'Loading One...',
1849 'Suspend [Page Two]',
1850 'Loading Two...',
1839 - ...(gate('enableSiblingPrerendering')
1840 - ? [
1841 - 'Suspend [Page One]',
1842 - 'Suspend [Child]',
1843 - 'Loading Child...',
1844 - 'Suspend [Page Two]',
1845 - ]
1846 - : []),
1851 + // pre-warming
1852 + 'Suspend [Page One]',
1853 + 'Suspend [Child]',
1854 + 'Loading Child...',
1855 + 'Suspend [Page Two]',
1856 + // end pre-warming
1857 'onTransitionStart(transition, 1000)',
1858 'onMarkerProgress(transition, parent, 1000, 2000, [suspense one, suspense two])',
1859 'onMarkerProgress(transition, one, 1000, 2000, [suspense one])',
@@ -1858,7 +1868,9 @@ describe('ReactInteractionTracing', () => {
1868 'Page One',
1869 'Suspend [Child]',
1870 'Loading Child...',
1861 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Child]'] : []),
1871 + // pre-warming
1872 + 'Suspend [Child]',
1873 + // end pre-warming
1874 'onMarkerProgress(transition, parent, 1000, 3000, [suspense two, suspense child])',
1875 'onMarkerProgress(transition, one, 1000, 3000, [suspense child])',
1876 'onMarkerComplete(transition, page one, 1000, 3000)',
@@ -1871,7 +1883,10 @@ describe('ReactInteractionTracing', () => {
1883 await waitForAll([
1884 'Suspend [Page Two]',
1885 'Loading Two...',
1874 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Page Two]'] : []),
1886 + // pre-warming
1887 + 'Suspend [Page Two]',
1888 + // end pre-warming
1889 +
1890 // "suspense one" has unsuspended so shouldn't be included
1891 // tracing marker "page one" has completed so shouldn't be included
1892 // all children of "suspense child" haven't yet been rendered so shouldn't be included
@@ -1969,7 +1984,9 @@ describe('ReactInteractionTracing', () => {
1984
1985 await waitForAll([
1986 'Suspend [Child]',
1972 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Child]'] : []),
1987 + // pre-warming
1988 + 'Suspend [Child]',
1989 + // end pre-warming
1990 'onTransitionStart(transition, 0)',
1991 'onMarkerProgress(transition, parent, 0, 1000, [child])',
1992 'onTransitionProgress(transition, 0, 1000, [child])',
@@ -1983,9 +2000,9 @@ describe('ReactInteractionTracing', () => {
2000 await waitForAll([
2001 'Suspend [Appended child]',
2002 'Suspend [Child]',
1986 - ...(gate('enableSiblingPrerendering')
1987 - ? ['Suspend [Appended child]', 'Suspend [Child]']
1988 - : []),
2003 + // pre-warming
2004 + 'Suspend [Appended child]',
2005 + 'Suspend [Child]',
2006 ]);
2007
2008 // This deleted child isn't part of the transition so we
@@ -1995,7 +2012,8 @@ describe('ReactInteractionTracing', () => {
2012 await advanceTimers(1000);
2013 await waitForAll([
2014 'Suspend [Child]',
1998 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Child]'] : []),
2015 + // pre-warming
2016 + 'Suspend [Child]',
2017 ]);
2018
2019 await resolveText('Child');
@@ -2097,7 +2115,9 @@ describe('ReactInteractionTracing', () => {
2115
2116 assertLog([
2117 'Suspend [Child]',
2100 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Child]'] : []),
2118 + // pre-warming
2119 + 'Suspend [Child]',
2120 + // end pre-warming
2121 'onTransitionStart(transition one, 0)',
2122 'onMarkerProgress(transition one, parent, 0, 1000, [child])',
2123 'onTransitionProgress(transition one, 0, 1000, [child])',
@@ -2118,9 +2138,10 @@ describe('ReactInteractionTracing', () => {
2138 assertLog([
2139 'Suspend [Appended child]',
2140 'Suspend [Child]',
2121 - ...(gate('enableSiblingPrerendering')
2122 - ? ['Suspend [Appended child]', 'Suspend [Child]']
2123 - : []),
2141 + // pre-warming
2142 + 'Suspend [Appended child]',
2143 + 'Suspend [Child]',
2144 + // end pre-warming
2145 'onTransitionStart(transition two, 1000)',
2146 'onMarkerProgress(transition two, appended child, 1000, 2000, [appended child])',
2147 'onTransitionProgress(transition two, 1000, 2000, [appended child])',
@@ -2134,7 +2155,9 @@ describe('ReactInteractionTracing', () => {
2155
2156 assertLog([
2157 'Suspend [Child]',
2137 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Child]'] : []),
2158 + // pre-warming
2159 + 'Suspend [Child]',
2160 + // end pre-warming
2161 'onMarkerProgress(transition two, appended child, 1000, 3000, [])',
2162 'onMarkerIncomplete(transition two, appended child, 1000, [{endTime: 3000, name: appended child, type: suspense}])',
2163 ]);
@@ -2291,20 +2314,11 @@ describe('ReactInteractionTracing', () => {
2314 assertLog([
2315 'Suspend [Text]',
2316 'Loading...',
2294 -
2295 - ...(gate('enableSiblingPrerendering')
2296 - ? [
2297 - 'Suspend [Text]',
2298 - 'onTransitionStart(transition, 0)',
2299 -
2300 - 'Suspend [Hidden Text]',
2301 - 'Hidden Loading...',
2302 - ]
2303 - : [
2304 - 'Suspend [Hidden Text]',
2305 - 'Hidden Loading...',
2306 - 'onTransitionStart(transition, 0)',
2307 - ]),
2317 + // pre-warming
2318 + 'Suspend [Text]',
2319 + 'onTransitionStart(transition, 0)',
2320 + 'Suspend [Hidden Text]',
2321 + 'Hidden Loading...',
2322 ]);
2323
2324 await act(() => {
@@ -2368,7 +2382,9 @@ describe('ReactInteractionTracing', () => {
2382 assertLog([
2383 'Suspend [Page Two]',
2384 'Loading...',
2371 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Page Two]'] : []),
2385 + // pre-warming
2386 + 'Suspend [Page Two]',
2387 + // end pre-warming
2388 'onTransitionStart(page transition, 0)',
2389 'onTransitionProgress(page transition, 0, 1000, [suspense page])',
2390 ]);
@@ -2440,10 +2456,13 @@ describe('ReactInteractionTracing', () => {
2456 'Text',
2457 'Suspend [Text Two]',
2458 'Loading Two...',
2443 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Text Two]'] : []),
2459 + // pre-warming
2460 + 'Suspend [Text Two]',
2461 + // end pre-warming
2462 'onTransitionStart(transition, 0)',
2463 'onTransitionProgress(transition, 0, 1000, [two])',
2446 - ...(gate('enableSiblingPrerendering') ? ['Suspend [Text Two]'] : []),
2464 + // pre-warming
2465 + 'Suspend [Text Two]',
2466 ]);
2467
2468 await act(() => {
@@ -2515,9 +2534,10 @@ describe('ReactInteractionTracing', () => {
2534 'Loading one...',
2535 'Suspend [Text two]',
2536 'Loading two...',
2518 - ...(gate('enableSiblingPrerendering')
2519 - ? ['Suspend [Text one]', 'Suspend [Text two]']
2520 - : []),
2537 + // pre-warming
2538 + 'Suspend [Text one]',
2539 + 'Suspend [Text two]',
2540 + // end pre-warming
2541 'onTransitionStart(transition one, 0) /root one/',
2542 'onTransitionProgress(transition one, 0, 1000, [one]) /root one/',
2543 'onTransitionStart(transition two, 0) /root two/',
packages/react-reconciler/src/__tests__/ReactUse-test.js
+18 -27
@@ -196,8 +196,8 @@ describe('ReactUse', () => {
196 assertLog([
197 'Suspend!',
198 'Loading...',
199 -
200 - ...(gate('enableSiblingPrerendering') ? ['Suspend!'] : []),
199 + // pre-warming
200 + 'Suspend!',
201 ]);
202 expect(root).toMatchRenderedOutput('Loading...');
203 });
@@ -1123,10 +1123,9 @@ describe('ReactUse', () => {
1123 });
1124 assertLog([
1125 '(Loading A...)',
1126 -
1127 - ...(gate('enableSiblingPrerendering')
1128 - ? ['(Loading C...)', '(Loading B...)']
1129 - : []),
1126 + // pre-warming
1127 + '(Loading C...)',
1128 + '(Loading B...)',
1129 ]);
1130 expect(root).toMatchRenderedOutput('(Loading A...)');
1131
@@ -2051,16 +2050,12 @@ describe('ReactUse', () => {
2050 assertLog(['Async text requested [World]']);
2051
2052 await act(() => resolveTextRequests('World'));
2054 - assertConsoleErrorDev(
2055 - gate('enableSiblingPrerendering')
2056 - ? [
2057 - 'A component was suspended by an uncached promise. ' +
2058 - 'Creating promises inside a Client Component or hook is not yet supported, ' +
2059 - 'except via a Suspense-compatible library or framework.\n' +
2060 - ' in App (at **)',
2061 - ]
2062 - : [],
2063 - );
2053 + assertConsoleErrorDev([
2054 + 'A component was suspended by an uncached promise. ' +
2055 + 'Creating promises inside a Client Component or hook is not yet supported, ' +
2056 + 'except via a Suspense-compatible library or framework.\n' +
2057 + ' in App (at **)',
2058 + ]);
2059
2060 assertLog(['Hi', 'World']);
2061 expect(root).toMatchRenderedOutput('Hi World');
@@ -2107,17 +2102,13 @@ describe('ReactUse', () => {
2102 assertLog(['Async text requested [World]']);
2103
2104 await act(() => resolveTextRequests('World'));
2110 - assertConsoleErrorDev(
2111 - gate('enableSiblingPrerendering')
2112 - ? [
2113 - 'A component was suspended by an uncached promise. ' +
2114 - 'Creating promises inside a Client Component or hook is not yet supported, ' +
2115 - 'except via a Suspense-compatible library or framework.\n' +
2116 - ' in div (at **)\n' +
2117 - ' in App (at **)',
2118 - ]
2119 - : [],
2120 - );
2105 + assertConsoleErrorDev([
2106 + 'A component was suspended by an uncached promise. ' +
2107 + 'Creating promises inside a Client Component or hook is not yet supported, ' +
2108 + 'except via a Suspense-compatible library or framework.\n' +
2109 + ' in div (at **)\n' +
2110 + ' in App (at **)',
2111 + ]);
2112
2113 assertLog(['Hi', 'World']);
2114 expect(root).toMatchRenderedOutput(<div>Hi World</div>);
packages/react-reconciler/src/__tests__/StrictEffectsMode-test.js
+6 -8
@@ -907,10 +907,9 @@ describe('StrictEffectsMode', () => {
907 'Child suspended',
908 'Fallback',
909 'Fallback',
910 -
911 - ...(gate('enableSiblingPrerendering')
912 - ? ['Child rendered', 'Child suspended']
913 - : []),
910 + // pre-warming
911 + 'Child rendered',
912 + 'Child suspended',
913 ]);
914
915 log = [];
@@ -932,10 +931,9 @@ describe('StrictEffectsMode', () => {
931 'Fallback',
932 'Parent dep destroy',
933 'Parent dep create',
935 -
936 - ...(gate('enableSiblingPrerendering')
937 - ? ['Child rendered', 'Child suspended']
938 - : []),
934 + // pre-warming
935 + 'Child rendered',
936 + 'Child suspended',
937 ]);
938
939 log = [];
packages/react-reconciler/src/__tests__/useSyncExternalStore-test.js
+11 -8
@@ -333,8 +333,8 @@ describe('useSyncExternalStore', () => {
333 // This should a synchronous re-render of A using the updated value. In
334 // this test, this causes A to suspend.
335 'Suspend A',
336 -
337 - ...(gate('enableSiblingPrerendering') ? ['B: Updated'] : []),
336 + // pre-warming
337 + 'B: Updated',
338 ]);
339 // Nothing has committed, because A suspended and no fallback
340 // was provided.
@@ -419,7 +419,9 @@ describe('useSyncExternalStore', () => {
419 await act(async () => {
420 root.render(<App />);
421 });
422 - assertLog([...(gate('enableSiblingPrerendering') ? ['(not set)'] : [])]);
422 +
423 + // pre-warming
424 + assertLog(['(not set)']);
425
426 expect(root).toMatchRenderedOutput('Loading...');
427
@@ -429,11 +431,12 @@ describe('useSyncExternalStore', () => {
431 resolveText('A');
432 });
433 assertLog([
432 - ...(gate('enableSiblingPrerendering')
433 - ? ['A', 'B', 'A', 'B', 'B']
434 - : gate(flags => flags.alwaysThrottleRetries)
435 - ? ['A', '(not set)', 'A', '(not set)', 'B']
436 - : ['A', '(not set)', 'A', '(not set)', '(not set)', 'B']),
434 + 'A',
435 + 'B',
436 + 'A',
437 + 'B',
438 + 'B',
439 + ...(gate('alwaysThrottleRetries') ? [] : ['B']),
440 ]);
441
442 expect(root).toMatchRenderedOutput('AB');
packages/shared/ReactFeatureFlags.js
-2
@@ -141,8 +141,6 @@ export const enablePersistedModeClonedFlag = false;
141
142 export const enableShallowPropDiffing = false;
143
144 -export const enableSiblingPrerendering = true;
145 -
144 /**
145 * Enables an expiration time for retry lanes to avoid starvation.
146 */
packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js
-1
@@ -23,7 +23,6 @@ export const enableHiddenSubtreeInsertionEffectCleanup = __VARIANT__;
23 export const enablePersistedModeClonedFlag = __VARIANT__;
24 export const enableShallowPropDiffing = __VARIANT__;
25 export const passChildrenWhenCloningPersistedNodes = __VARIANT__;
26 -export const enableSiblingPrerendering = __VARIANT__;
26 export const enableFastAddPropertiesInDiffing = __VARIANT__;
27 export const enableLazyPublicInstanceInFabric = __VARIANT__;
28 export const renameElementSymbol = __VARIANT__;
packages/shared/forks/ReactFeatureFlags.native-fb.js
-1
@@ -25,7 +25,6 @@ export const {
25 enablePersistedModeClonedFlag,
26 enableShallowPropDiffing,
27 passChildrenWhenCloningPersistedNodes,
28 - enableSiblingPrerendering,
28 enableFastAddPropertiesInDiffing,
29 enableLazyPublicInstanceInFabric,
30 renameElementSymbol,
packages/shared/forks/ReactFeatureFlags.native-oss.js
-2
@@ -61,8 +61,6 @@ export const renameElementSymbol = true;
61 export const retryLaneExpirationMs = 5000;
62 export const syncLaneExpirationMs = 250;
63 export const transitionLaneExpirationMs = 5000;
64 -export const enableSiblingPrerendering = true;
65 -
64 export const enableHydrationLaneScheduling = true;
65
66 export const enableYieldingBeforePassive = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
-1
@@ -62,7 +62,6 @@ export const enableInfiniteRenderLoopDetection = false;
62
63 export const renameElementSymbol = true;
64 export const enableShallowPropDiffing = false;
65 -export const enableSiblingPrerendering = true;
65
66 export const enableYieldingBeforePassive = true;
67
packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js
-1
@@ -60,7 +60,6 @@ export const renameElementSymbol = false;
60 export const retryLaneExpirationMs = 5000;
61 export const syncLaneExpirationMs = 250;
62 export const transitionLaneExpirationMs = 5000;
63 -export const enableSiblingPrerendering = true;
63 export const enableHydrationLaneScheduling = true;
64 export const enableYieldingBeforePassive = false;
65 export const enableThrottledScheduling = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
-1
@@ -71,7 +71,6 @@ export const renameElementSymbol = false;
71
72 export const enableObjectFiber = false;
73 export const enableShallowPropDiffing = false;
74 -export const enableSiblingPrerendering = true;
74
75 export const enableHydrationLaneScheduling = true;
76
packages/shared/forks/ReactFeatureFlags.www-dynamic.js
-1
@@ -33,7 +33,6 @@ export const transitionLaneExpirationMs = 5000;
33 export const enableSchedulingProfiler = __VARIANT__;
34
35 export const enableInfiniteRenderLoopDetection = __VARIANT__;
36 -export const enableSiblingPrerendering = __VARIANT__;
36
37 export const enableFastAddPropertiesInDiffing = __VARIANT__;
38 export const enableLazyPublicInstanceInFabric = false;
packages/shared/forks/ReactFeatureFlags.www.js
-1
@@ -26,7 +26,6 @@ export const {
26 enableObjectFiber,
27 enableRenderableContext,
28 enableRetryLaneExpiration,
29 - enableSiblingPrerendering,
29 enableTransitionTracing,
30 enableTrustedTypesIntegration,
31 favorSafetyOverHydrationPerf,
scripts/jest/TestFlags.js
+1 -1
@@ -87,7 +87,7 @@ function getTestFlags() {
87 // TODO: Suspending the work loop during the render phase is currently
88 // not compatible with sibling prerendering. We will add this optimization
89 // back in a later step.
90 - enableSuspendingDuringWorkLoop: !featureFlags.enableSiblingPrerendering,
90 + enableSuspendingDuringWorkLoop: false,
91
92 // This flag is used to determine whether we should run Fizz tests using
93 // the external runtime or the inline script runtime.