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.