Skip to content

Commit 0212737

Browse files
committed
Wrap more Suspense-only paths in the feature flag
1 parent bed371a commit 0212737

File tree

1 file changed

+129
-109
lines changed

1 file changed

+129
-109
lines changed

packages/react-reconciler/src/ReactFiberPendingWork.js

Lines changed: 129 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import type {ExpirationTime} from './ReactFiberExpirationTime';
1212

1313
import {NoWork} from './ReactFiberExpirationTime';
1414

15+
import {enableSuspense} from 'shared/ReactFeatureFlags';
16+
1517
// Because we don't have a global queue of updates, we use this module to keep
1618
// track of the pending levels of work that have yet to be flushed. You can
1719
// think of a PendingWork object as representing a batch of work that will
@@ -31,11 +33,13 @@ export type PendingWork = {
3133
};
3234

3335
function insertPendingWorkAtPosition(root, work, insertAfter, insertBefore) {
34-
work.next = insertBefore;
35-
if (insertAfter === null) {
36-
root.firstPendingWork = work;
37-
} else {
38-
insertAfter.next = work;
36+
if (enableSuspense) {
37+
work.next = insertBefore;
38+
if (insertAfter === null) {
39+
root.firstPendingWork = work;
40+
} else {
41+
insertAfter.next = work;
42+
}
3943
}
4044
}
4145

@@ -44,39 +48,41 @@ export function addPendingWork(
4448
startTime: ExpirationTime,
4549
expirationTime: ExpirationTime,
4650
): void {
47-
let match = null;
48-
let insertAfter = null;
49-
let insertBefore = root.firstPendingWork;
50-
while (insertBefore !== null) {
51-
if (insertBefore.expirationTime >= expirationTime) {
52-
// Retry anything with an equal or lower expiration time, since it may
53-
// be unblocked by the new work.
54-
insertBefore.shouldTryResuming = true;
55-
}
56-
if (insertBefore.expirationTime === expirationTime) {
57-
// Found a matching bucket. But we'll keep iterating so we can set
58-
// `shouldTryResuming` as needed.
59-
match = insertBefore;
60-
// Update the start time. We always measure from the most recently
61-
// added update.
62-
match.startTime = startTime;
51+
if (enableSuspense) {
52+
let match = null;
53+
let insertAfter = null;
54+
let insertBefore = root.firstPendingWork;
55+
while (insertBefore !== null) {
56+
if (insertBefore.expirationTime >= expirationTime) {
57+
// Retry anything with an equal or lower expiration time, since it may
58+
// be unblocked by the new work.
59+
insertBefore.shouldTryResuming = true;
60+
}
61+
if (insertBefore.expirationTime === expirationTime) {
62+
// Found a matching bucket. But we'll keep iterating so we can set
63+
// `shouldTryResuming` as needed.
64+
match = insertBefore;
65+
// Update the start time. We always measure from the most recently
66+
// added update.
67+
match.startTime = startTime;
68+
}
69+
if (match === null && insertBefore.expirationTime > expirationTime) {
70+
// Found the insertion position
71+
break;
72+
}
73+
insertAfter = insertBefore;
74+
insertBefore = insertBefore.next;
6375
}
64-
if (match === null && insertBefore.expirationTime > expirationTime) {
65-
// Found the insertion position
66-
break;
76+
if (match === null) {
77+
const work: PendingWork = {
78+
startTime,
79+
expirationTime,
80+
isSuspended: false,
81+
shouldTryResuming: false,
82+
next: null,
83+
};
84+
insertPendingWorkAtPosition(root, work, insertAfter, insertBefore);
6785
}
68-
insertAfter = insertBefore;
69-
insertBefore = insertBefore.next;
70-
}
71-
if (match === null) {
72-
const work: PendingWork = {
73-
startTime,
74-
expirationTime,
75-
isSuspended: false,
76-
shouldTryResuming: false,
77-
next: null,
78-
};
79-
insertPendingWorkAtPosition(root, work, insertAfter, insertBefore);
8086
}
8187
}
8288

@@ -85,112 +91,126 @@ export function flushPendingWork(
8591
currentTime: ExpirationTime,
8692
remainingExpirationTime: ExpirationTime,
8793
) {
88-
// Pop all work that has higher priority than the remaining priority.
89-
let firstUnflushedWork = root.firstPendingWork;
90-
while (firstUnflushedWork !== null) {
91-
if (
92-
remainingExpirationTime !== NoWork &&
93-
firstUnflushedWork.expirationTime >= remainingExpirationTime
94-
) {
95-
break;
94+
if (enableSuspense) {
95+
// Pop all work that has higher priority than the remaining priority.
96+
let firstUnflushedWork = root.firstPendingWork;
97+
while (firstUnflushedWork !== null) {
98+
if (
99+
remainingExpirationTime !== NoWork &&
100+
firstUnflushedWork.expirationTime >= remainingExpirationTime
101+
) {
102+
break;
103+
}
104+
firstUnflushedWork = firstUnflushedWork.next;
96105
}
97-
firstUnflushedWork = firstUnflushedWork.next;
98-
}
99-
root.firstPendingWork = firstUnflushedWork;
106+
root.firstPendingWork = firstUnflushedWork;
100107

101-
if (firstUnflushedWork === null) {
102-
if (remainingExpirationTime !== NoWork) {
108+
if (firstUnflushedWork === null) {
109+
if (remainingExpirationTime !== NoWork) {
110+
// There was an update during the render phase that wasn't flushed.
111+
addPendingWork(root, currentTime, remainingExpirationTime);
112+
}
113+
} else if (
114+
remainingExpirationTime !== NoWork &&
115+
firstUnflushedWork.expirationTime > remainingExpirationTime
116+
) {
103117
// There was an update during the render phase that wasn't flushed.
104118
addPendingWork(root, currentTime, remainingExpirationTime);
105119
}
106-
} else if (
107-
remainingExpirationTime !== NoWork &&
108-
firstUnflushedWork.expirationTime > remainingExpirationTime
109-
) {
110-
// There was an update during the render phase that wasn't flushed.
111-
addPendingWork(root, currentTime, remainingExpirationTime);
112120
}
113121
}
114122

115123
export function suspendPendingWork(
116124
root: FiberRoot,
117125
expirationTime: ExpirationTime,
118126
): void {
119-
let work = root.firstPendingWork;
120-
while (work !== null) {
121-
if (work.expirationTime === expirationTime) {
122-
work.isSuspended = true;
123-
work.shouldTryResuming = false;
124-
return;
125-
}
126-
if (work.expirationTime > expirationTime) {
127-
return;
127+
if (enableSuspense) {
128+
let work = root.firstPendingWork;
129+
while (work !== null) {
130+
if (work.expirationTime === expirationTime) {
131+
work.isSuspended = true;
132+
work.shouldTryResuming = false;
133+
return;
134+
}
135+
if (work.expirationTime > expirationTime) {
136+
return;
137+
}
138+
work = work.next;
128139
}
129-
work = work.next;
130140
}
131141
}
132142

133143
export function resumePendingWork(
134144
root: FiberRoot,
135145
expirationTime: ExpirationTime,
136146
): void {
137-
// Called when a promise resolves. This "pings" React to retry the previously
138-
// suspended render.
139-
let work = root.firstPendingWork;
140-
while (work !== null) {
141-
if (work.expirationTime === expirationTime) {
142-
work.shouldTryResuming = true;
143-
}
144-
if (work.expirationTime > expirationTime) {
145-
return;
147+
if (enableSuspense) {
148+
// Called when a promise resolves. This "pings" React to retry the previously
149+
// suspended render.
150+
let work = root.firstPendingWork;
151+
while (work !== null) {
152+
if (work.expirationTime === expirationTime) {
153+
work.shouldTryResuming = true;
154+
}
155+
if (work.expirationTime > expirationTime) {
156+
return;
157+
}
158+
work = work.next;
146159
}
147-
work = work.next;
148160
}
149161
}
150162

151163
export function findNextExpirationTimeToWorkOn(
152164
root: FiberRoot,
153165
): ExpirationTime {
154-
// Return the earliest time that either isn't suspended or has been pinged.
155-
let lastSuspendedTime = NoWork;
156-
let lastRetryTime = NoWork;
157-
let work = root.firstPendingWork;
158-
while (work !== null) {
159-
if (!work.isSuspended) {
160-
return work.expirationTime;
161-
}
162-
if (
163-
lastSuspendedTime === NoWork ||
164-
lastSuspendedTime < work.expirationTime
165-
) {
166-
lastSuspendedTime = work.expirationTime;
167-
}
168-
if (work.shouldTryResuming) {
169-
if (lastRetryTime === NoWork || lastRetryTime < work.expirationTime) {
170-
lastRetryTime = work.expirationTime;
166+
if (enableSuspense) {
167+
// Return the earliest time that either isn't suspended or has been pinged.
168+
let lastSuspendedTime = NoWork;
169+
let lastRetryTime = NoWork;
170+
let work = root.firstPendingWork;
171+
while (work !== null) {
172+
if (!work.isSuspended) {
173+
return work.expirationTime;
171174
}
175+
if (
176+
lastSuspendedTime === NoWork ||
177+
lastSuspendedTime < work.expirationTime
178+
) {
179+
lastSuspendedTime = work.expirationTime;
180+
}
181+
if (work.shouldTryResuming) {
182+
if (lastRetryTime === NoWork || lastRetryTime < work.expirationTime) {
183+
lastRetryTime = work.expirationTime;
184+
}
185+
}
186+
work = work.next;
172187
}
173-
work = work.next;
174-
}
175-
// This has the effect of coalescing all async updates that occur while we're
176-
// in a suspended state. This prevents us from rendering an intermediate state
177-
// that is no longer valid. An example is a tab switching interface: if
178-
// switching to a new tab is suspended, we should only switch to the last
179-
// tab that was clicked. If the user switches to tab A and then tab B, we
180-
// should continue suspending until B is ready.
181-
if (lastRetryTime >= lastSuspendedTime) {
182-
return lastRetryTime;
188+
// This has the effect of coalescing all async updates that occur while we're
189+
// in a suspended state. This prevents us from rendering an intermediate state
190+
// that is no longer valid. An example is a tab switching interface: if
191+
// switching to a new tab is suspended, we should only switch to the last
192+
// tab that was clicked. If the user switches to tab A and then tab B, we
193+
// should continue suspending until B is ready.
194+
if (lastRetryTime >= lastSuspendedTime) {
195+
return lastRetryTime;
196+
}
197+
return NoWork;
198+
} else {
199+
return root.current.expirationTime;
183200
}
184-
return NoWork;
185201
}
186202

187203
export function findStartTime(root: FiberRoot, expirationTime: ExpirationTime) {
188-
let match = root.firstPendingWork;
189-
while (match !== null) {
190-
if (match.expirationTime === expirationTime) {
191-
return match.startTime;
204+
if (enableSuspense) {
205+
let match = root.firstPendingWork;
206+
while (match !== null) {
207+
if (match.expirationTime === expirationTime) {
208+
return match.startTime;
209+
}
210+
match = match.next;
192211
}
193-
match = match.next;
212+
return NoWork;
213+
} else {
214+
return NoWork;
194215
}
195-
return NoWork;
196216
}

0 commit comments

Comments
 (0)