Flip expiration times (#13912)
See https://github.com/facebook/react/pull/13912 commit messages for how this was done.
Sophie Alpert committed
Oct 30, 2018 at 15:26 UTC
169f935f781c764a8c04f441c5e27b00a0329e8c
9 files changed
+79
-160
packages/react-dom/src/client/ReactDOM.js
+1
-1
@@ -400,7 +400,7 @@ ReactRoot.prototype.createBatch = function(): Batch {
400
let insertBefore = firstBatch;
401
while (
402
insertBefore !== null &&
403
- insertBefore._expirationTime <= expirationTime
403
+ insertBefore._expirationTime >= expirationTime
404
) {
405
insertAfter = insertBefore;
406
insertBefore = insertBefore._next;
packages/react-noop-renderer/src/createReactNoop.js
+3
-2
@@ -956,9 +956,10 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
956
rootID: string = DEFAULT_ROOT_ID,
957
) {
958
const root: any = roots.get(rootID);
959
+ const expiration = NoopRenderer.computeUniqueAsyncExpiration();
960
const batch = {
961
_defer: true,
961
- _expirationTime: 1,
962
+ _expirationTime: expiration,
963
_onComplete: () => {
964
root.firstBatch = null;
965
},
@@ -969,7 +970,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
970
expect(actual).toEqual(expectedFlush);
971
return (expectedCommit: Array<mixed>) => {
972
batch._defer = false;
972
- NoopRenderer.flushRoot(root, 1);
973
+ NoopRenderer.flushRoot(root, expiration);
974
expect(yieldedValues).toEqual(expectedCommit);
975
};
976
},
packages/react-reconciler/src/ReactFiberBeginWork.js
+5
-16
@@ -265,10 +265,7 @@ function updateMemoComponent(
265
return child;
266
}
267
let currentChild = ((current.child: any): Fiber); // This is always exactly one child
268
- if (
269
- updateExpirationTime === NoWork ||
270
- updateExpirationTime > renderExpirationTime
271
- ) {
268
+ if (updateExpirationTime < renderExpirationTime) {
269
// This will be the props with resolved defaultProps,
270
// unlike current.memoizedProps which will be the unresolved ones.
271
const prevProps = currentChild.memoizedProps;
@@ -302,11 +299,7 @@ function updateSimpleMemoComponent(
299
updateExpirationTime,
300
renderExpirationTime: ExpirationTime,
301
): null | Fiber {
305
- if (
306
- current !== null &&
307
- (updateExpirationTime === NoWork ||
308
- updateExpirationTime > renderExpirationTime)
309
- ) {
302
+ if (current !== null && updateExpirationTime < renderExpirationTime) {
303
const prevProps = current.memoizedProps;
304
if (
305
shallowEqual(prevProps, nextProps) &&
@@ -1471,10 +1464,7 @@ function bailoutOnAlreadyFinishedWork(
1464
1465
// Check if the children have any pending work.
1466
const childExpirationTime = workInProgress.childExpirationTime;
1474
- if (
1475
- childExpirationTime === NoWork ||
1476
- childExpirationTime > renderExpirationTime
1477
- ) {
1467
+ if (childExpirationTime < renderExpirationTime) {
1468
// The children don't have any work either. We can skip them.
1469
// TODO: Once we add back resuming, we should check if the children are
1470
// a work-in-progress set. If so, we need to transfer their effects.
@@ -1500,8 +1490,7 @@ function beginWork(
1490
if (
1491
oldProps === newProps &&
1492
!hasLegacyContextChanged() &&
1503
- (updateExpirationTime === NoWork ||
1504
- updateExpirationTime > renderExpirationTime)
1493
+ updateExpirationTime < renderExpirationTime
1494
) {
1495
// This fiber does not have any pending work. Bailout without entering
1496
// the begin phase. There's still some bookkeeping we that needs to be done
@@ -1550,7 +1539,7 @@ function beginWork(
1539
primaryChildFragment.childExpirationTime;
1540
if (
1541
primaryChildExpirationTime !== NoWork &&
1553
- primaryChildExpirationTime <= renderExpirationTime
1542
+ primaryChildExpirationTime >= renderExpirationTime
1543
) {
1544
// The primary children have pending work. Use the normal path
1545
// to attempt to render the primary children again.
packages/react-reconciler/src/ReactFiberExpirationTime.js
+7
-7
@@ -12,20 +12,20 @@ import MAX_SIGNED_31_BIT_INT from './maxSigned31BitInt';
12
export type ExpirationTime = number;
13
14
export const NoWork = 0;
15
-export const Sync = 1;
16
-export const Never = MAX_SIGNED_31_BIT_INT;
15
+export const Never = 1;
16
+export const Sync = MAX_SIGNED_31_BIT_INT;
17
18
const UNIT_SIZE = 10;
19
-const MAGIC_NUMBER_OFFSET = 2;
19
+const MAGIC_NUMBER_OFFSET = MAX_SIGNED_31_BIT_INT - 1;
20
21
// 1 unit of expiration time represents 10ms.
22
export function msToExpirationTime(ms: number): ExpirationTime {
23
// Always add an offset so that we don't clash with the magic number for NoWork.
24
- return ((ms / UNIT_SIZE) | 0) + MAGIC_NUMBER_OFFSET;
24
+ return MAGIC_NUMBER_OFFSET - ((ms / UNIT_SIZE) | 0);
25
}
26
27
export function expirationTimeToMs(expirationTime: ExpirationTime): number {
28
- return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE;
28
+ return (MAGIC_NUMBER_OFFSET - expirationTime) * UNIT_SIZE;
29
}
30
31
function ceiling(num: number, precision: number): number {
@@ -38,9 +38,9 @@ function computeExpirationBucket(
38
bucketSizeMs,
39
): ExpirationTime {
40
return (
41
- MAGIC_NUMBER_OFFSET +
41
+ MAGIC_NUMBER_OFFSET -
42
ceiling(
43
- currentTime - MAGIC_NUMBER_OFFSET + expirationInMs / UNIT_SIZE,
43
+ MAGIC_NUMBER_OFFSET - currentTime + expirationInMs / UNIT_SIZE,
44
bucketSizeMs / UNIT_SIZE,
45
)
46
);
packages/react-reconciler/src/ReactFiberHooks.js
+2
-5
@@ -404,7 +404,7 @@ export function useReducer<S, A>(
404
let didSkip = false;
405
do {
406
const updateExpirationTime = update.expirationTime;
407
- if (updateExpirationTime > renderExpirationTime) {
407
+ if (updateExpirationTime < renderExpirationTime) {
408
// Priority is insufficient. Skip this update. If this is the first
409
// skipped update, the previous update/state is the new base
410
// update/state.
@@ -414,10 +414,7 @@ export function useReducer<S, A>(
414
newBaseState = newState;
415
}
416
// Update the remaining priority in the queue.
417
- if (
418
- remainingExpirationTime === NoWork ||
419
- updateExpirationTime < remainingExpirationTime
420
- ) {
417
+ if (updateExpirationTime > remainingExpirationTime) {
418
remainingExpirationTime = updateExpirationTime;
419
}
420
} else {
packages/react-reconciler/src/ReactFiberNewContext.js
+5
-15
@@ -22,7 +22,6 @@ import warningWithoutStack from 'shared/warningWithoutStack';
22
import {isPrimaryRenderer} from './ReactFiberHostConfig';
23
import {createCursor, push, pop} from './ReactFiberStack';
24
import MAX_SIGNED_31_BIT_INT from './maxSigned31BitInt';
25
-import {NoWork} from './ReactFiberExpirationTime';
25
import {ContextProvider, ClassComponent} from 'shared/ReactWorkTags';
26
27
import invariant from 'shared/invariant';
@@ -169,17 +168,13 @@ export function propagateContextChange(
168
enqueueUpdate(fiber, update);
169
}
170
172
- if (
173
- fiber.expirationTime === NoWork ||
174
- fiber.expirationTime > renderExpirationTime
175
- ) {
171
+ if (fiber.expirationTime < renderExpirationTime) {
172
fiber.expirationTime = renderExpirationTime;
173
}
174
let alternate = fiber.alternate;
175
if (
176
alternate !== null &&
181
- (alternate.expirationTime === NoWork ||
182
- alternate.expirationTime > renderExpirationTime)
177
+ alternate.expirationTime < renderExpirationTime
178
) {
179
alternate.expirationTime = renderExpirationTime;
180
}
@@ -188,22 +183,17 @@ export function propagateContextChange(
183
let node = fiber.return;
184
while (node !== null) {
185
alternate = node.alternate;
191
- if (
192
- node.childExpirationTime === NoWork ||
193
- node.childExpirationTime > renderExpirationTime
194
- ) {
186
+ if (node.childExpirationTime < renderExpirationTime) {
187
node.childExpirationTime = renderExpirationTime;
188
if (
189
alternate !== null &&
198
- (alternate.childExpirationTime === NoWork ||
199
- alternate.childExpirationTime > renderExpirationTime)
190
+ alternate.childExpirationTime < renderExpirationTime
191
) {
192
alternate.childExpirationTime = renderExpirationTime;
193
}
194
} else if (
195
alternate !== null &&
205
- (alternate.childExpirationTime === NoWork ||
206
- alternate.childExpirationTime > renderExpirationTime)
196
+ alternate.childExpirationTime < renderExpirationTime
197
) {
198
alternate.childExpirationTime = renderExpirationTime;
199
} else {
packages/react-reconciler/src/ReactFiberPendingPriority.js
+20
-32
@@ -31,12 +31,12 @@ export function markPendingPriorityLevel(
31
// No other pending updates.
32
root.earliestPendingTime = root.latestPendingTime = expirationTime;
33
} else {
34
- if (earliestPendingTime > expirationTime) {
34
+ if (earliestPendingTime < expirationTime) {
35
// This is the earliest pending update.
36
root.earliestPendingTime = expirationTime;
37
} else {
38
const latestPendingTime = root.latestPendingTime;
39
- if (latestPendingTime < expirationTime) {
39
+ if (latestPendingTime > expirationTime) {
40
// This is the latest pending update
41
root.latestPendingTime = expirationTime;
42
}
@@ -65,12 +65,12 @@ export function markCommittedPriorityLevels(
65
// Let's see if the previous latest known pending level was just flushed.
66
const latestPendingTime = root.latestPendingTime;
67
if (latestPendingTime !== NoWork) {
68
- if (latestPendingTime < earliestRemainingTime) {
68
+ if (latestPendingTime > earliestRemainingTime) {
69
// We've flushed all the known pending levels.
70
root.earliestPendingTime = root.latestPendingTime = NoWork;
71
} else {
72
const earliestPendingTime = root.earliestPendingTime;
73
- if (earliestPendingTime < earliestRemainingTime) {
73
+ if (earliestPendingTime > earliestRemainingTime) {
74
// We've flushed the earliest known pending level. Set this to the
75
// latest pending time.
76
root.earliestPendingTime = root.latestPendingTime;
@@ -92,7 +92,7 @@ export function markCommittedPriorityLevels(
92
}
93
94
const latestSuspendedTime = root.latestSuspendedTime;
95
- if (earliestRemainingTime > latestSuspendedTime) {
95
+ if (earliestRemainingTime < latestSuspendedTime) {
96
// The earliest remaining level is later than all the suspended work. That
97
// means we've flushed all the suspended work.
98
root.earliestSuspendedTime = NoWork;
@@ -106,7 +106,7 @@ export function markCommittedPriorityLevels(
106
return;
107
}
108
109
- if (earliestRemainingTime < earliestSuspendedTime) {
109
+ if (earliestRemainingTime > earliestSuspendedTime) {
110
// The earliest remaining time is earlier than all the suspended work.
111
// Treat it as a pending update.
112
markPendingPriorityLevel(root, earliestRemainingTime);
@@ -128,10 +128,10 @@ export function hasLowerPriorityWork(
128
const latestPingedTime = root.latestPingedTime;
129
return (
130
(latestPendingTime !== NoWork &&
131
- latestPendingTime > erroredExpirationTime) ||
131
+ latestPendingTime < erroredExpirationTime) ||
132
(latestSuspendedTime !== NoWork &&
133
- latestSuspendedTime > erroredExpirationTime) ||
134
- (latestPingedTime !== NoWork && latestPingedTime > erroredExpirationTime)
133
+ latestSuspendedTime < erroredExpirationTime) ||
134
+ (latestPingedTime !== NoWork && latestPingedTime < erroredExpirationTime)
135
);
136
}
137
@@ -143,8 +143,8 @@ export function isPriorityLevelSuspended(
143
const latestSuspendedTime = root.latestSuspendedTime;
144
return (
145
earliestSuspendedTime !== NoWork &&
146
- expirationTime >= earliestSuspendedTime &&
147
- expirationTime <= latestSuspendedTime
146
+ expirationTime <= earliestSuspendedTime &&
147
+ expirationTime >= latestSuspendedTime
148
);
149
}
150
@@ -180,10 +180,10 @@ export function markSuspendedPriorityLevel(
180
// No other suspended levels.
181
root.earliestSuspendedTime = root.latestSuspendedTime = suspendedTime;
182
} else {
183
- if (earliestSuspendedTime > suspendedTime) {
183
+ if (earliestSuspendedTime < suspendedTime) {
184
// This is the earliest suspended level.
185
root.earliestSuspendedTime = suspendedTime;
186
- } else if (latestSuspendedTime < suspendedTime) {
186
+ } else if (latestSuspendedTime > suspendedTime) {
187
// This is the latest suspended level
188
root.latestSuspendedTime = suspendedTime;
189
}
@@ -202,7 +202,7 @@ export function markPingedPriorityLevel(
202
// is thrown out and not reused during the restarted render. One way to
203
// invalidate the progressed work is to restart at expirationTime + 1.
204
const latestPingedTime = root.latestPingedTime;
205
- if (latestPingedTime === NoWork || latestPingedTime < pingedTime) {
205
+ if (latestPingedTime === NoWork || latestPingedTime > pingedTime) {
206
root.latestPingedTime = pingedTime;
207
}
208
findNextExpirationTimeToWorkOn(pingedTime, root);
@@ -212,7 +212,7 @@ function clearPing(root, completedTime) {
212
// TODO: Track whether the root was pinged during the render phase. If so,
213
// we need to make sure we don't lose track of it.
214
const latestPingedTime = root.latestPingedTime;
215
- if (latestPingedTime !== NoWork && latestPingedTime <= completedTime) {
215
+ if (latestPingedTime !== NoWork && latestPingedTime >= completedTime) {
216
root.latestPingedTime = NoWork;
217
}
218
}
@@ -225,18 +225,10 @@ export function findEarliestOutstandingPriorityLevel(
225
226
const earliestPendingTime = root.earliestPendingTime;
227
const earliestSuspendedTime = root.earliestSuspendedTime;
228
- if (
229
- earliestExpirationTime === NoWork ||
230
- (earliestPendingTime !== NoWork &&
231
- earliestPendingTime < earliestExpirationTime)
232
- ) {
228
+ if (earliestPendingTime > earliestExpirationTime) {
229
earliestExpirationTime = earliestPendingTime;
230
}
235
- if (
236
- earliestExpirationTime === NoWork ||
237
- (earliestSuspendedTime !== NoWork &&
238
- earliestSuspendedTime < earliestExpirationTime)
239
- ) {
231
+ if (earliestSuspendedTime > earliestExpirationTime) {
232
earliestExpirationTime = earliestSuspendedTime;
233
}
234
return earliestExpirationTime;
@@ -247,7 +239,7 @@ export function didExpireAtExpirationTime(
239
currentTime: ExpirationTime,
240
): void {
241
const expirationTime = root.expirationTime;
250
- if (expirationTime !== NoWork && currentTime >= expirationTime) {
242
+ if (expirationTime !== NoWork && currentTime <= expirationTime) {
243
// The root has expired. Flush all work up to the current time.
244
root.nextExpirationTimeToWorkOn = currentTime;
245
}
@@ -269,7 +261,7 @@ function findNextExpirationTimeToWorkOn(completedExpirationTime, root) {
261
if (
262
nextExpirationTimeToWorkOn === NoWork &&
263
(completedExpirationTime === NoWork ||
272
- latestSuspendedTime > completedExpirationTime)
264
+ latestSuspendedTime < completedExpirationTime)
265
) {
266
// The lowest priority suspended work is the work most likely to be
267
// committed next. Let's start rendering it again, so that if it times out,
@@ -278,11 +270,7 @@ function findNextExpirationTimeToWorkOn(completedExpirationTime, root) {
270
}
271
272
let expirationTime = nextExpirationTimeToWorkOn;
281
- if (
282
- expirationTime !== NoWork &&
283
- earliestSuspendedTime !== NoWork &&
284
- earliestSuspendedTime < expirationTime
285
- ) {
273
+ if (expirationTime !== NoWork && earliestSuspendedTime > expirationTime) {
274
// Expire using the earliest known expiration time.
275
expirationTime = earliestSuspendedTime;
276
}
packages/react-reconciler/src/ReactFiberScheduler.js
+32
-72
@@ -241,8 +241,8 @@ if (__DEV__) {
241
};
242
}
243
244
-// Used to ensure computeUniqueAsyncExpiration is monotonically increasing.
245
-let lastUniqueAsyncExpiration: number = 0;
244
+// Used to ensure computeUniqueAsyncExpiration is monotonically decreasing.
245
+let lastUniqueAsyncExpiration: number = Sync - 1;
246
247
// Represents the expiration time that incoming updates should use. (If this
248
// is NoWork, use the default strategy: async updates in async mode, sync
@@ -605,9 +605,7 @@ function commitRoot(root: FiberRoot, finishedWork: Fiber): void {
605
const updateExpirationTimeBeforeCommit = finishedWork.expirationTime;
606
const childExpirationTimeBeforeCommit = finishedWork.childExpirationTime;
607
const earliestRemainingTimeBeforeCommit =
608
- updateExpirationTimeBeforeCommit === NoWork ||
609
- (childExpirationTimeBeforeCommit !== NoWork &&
610
- childExpirationTimeBeforeCommit < updateExpirationTimeBeforeCommit)
608
+ childExpirationTimeBeforeCommit > updateExpirationTimeBeforeCommit
609
? childExpirationTimeBeforeCommit
610
: updateExpirationTimeBeforeCommit;
611
markCommittedPriorityLevels(root, earliestRemainingTimeBeforeCommit);
@@ -798,9 +796,7 @@ function commitRoot(root: FiberRoot, finishedWork: Fiber): void {
796
const updateExpirationTimeAfterCommit = finishedWork.expirationTime;
797
const childExpirationTimeAfterCommit = finishedWork.childExpirationTime;
798
const earliestRemainingTimeAfterCommit =
801
- updateExpirationTimeAfterCommit === NoWork ||
802
- (childExpirationTimeAfterCommit !== NoWork &&
803
- childExpirationTimeAfterCommit < updateExpirationTimeAfterCommit)
799
+ childExpirationTimeAfterCommit > updateExpirationTimeAfterCommit
800
? childExpirationTimeAfterCommit
801
: updateExpirationTimeAfterCommit;
802
if (earliestRemainingTimeAfterCommit === NoWork) {
@@ -841,10 +837,7 @@ function commitRoot(root: FiberRoot, finishedWork: Fiber): void {
837
// Only decrement the pending interaction count if we're done.
838
// If there's still work at the current priority,
839
// That indicates that we are waiting for suspense data.
844
- if (
845
- earliestRemainingTimeAfterCommit === NoWork ||
846
- scheduledExpirationTime < earliestRemainingTimeAfterCommit
847
- ) {
840
+ if (scheduledExpirationTime > earliestRemainingTimeAfterCommit) {
841
pendingInteractionMap.delete(scheduledExpirationTime);
842
843
scheduledInteractions.forEach(interaction => {
@@ -904,18 +897,10 @@ function resetChildExpirationTime(
897
while (child !== null) {
898
const childUpdateExpirationTime = child.expirationTime;
899
const childChildExpirationTime = child.childExpirationTime;
907
- if (
908
- newChildExpirationTime === NoWork ||
909
- (childUpdateExpirationTime !== NoWork &&
910
- childUpdateExpirationTime < newChildExpirationTime)
911
- ) {
900
+ if (childUpdateExpirationTime > newChildExpirationTime) {
901
newChildExpirationTime = childUpdateExpirationTime;
902
}
914
- if (
915
- newChildExpirationTime === NoWork ||
916
- (childChildExpirationTime !== NoWork &&
917
- childChildExpirationTime < newChildExpirationTime)
918
- ) {
903
+ if (childChildExpirationTime > newChildExpirationTime) {
904
newChildExpirationTime = childChildExpirationTime;
905
}
906
if (shouldBubbleActualDurations) {
@@ -931,18 +916,10 @@ function resetChildExpirationTime(
916
while (child !== null) {
917
const childUpdateExpirationTime = child.expirationTime;
918
const childChildExpirationTime = child.childExpirationTime;
934
- if (
935
- newChildExpirationTime === NoWork ||
936
- (childUpdateExpirationTime !== NoWork &&
937
- childUpdateExpirationTime < newChildExpirationTime)
938
- ) {
919
+ if (childUpdateExpirationTime > newChildExpirationTime) {
920
newChildExpirationTime = childUpdateExpirationTime;
921
}
941
- if (
942
- newChildExpirationTime === NoWork ||
943
- (childChildExpirationTime !== NoWork &&
944
- childChildExpirationTime < newChildExpirationTime)
945
- ) {
922
+ if (childChildExpirationTime > newChildExpirationTime) {
923
newChildExpirationTime = childChildExpirationTime;
924
}
925
child = child.sibling;
@@ -1244,7 +1221,7 @@ function renderRoot(root: FiberRoot, isYieldy: boolean): void {
1221
const interactions: Set<Interaction> = new Set();
1222
root.pendingInteractionMap.forEach(
1223
(scheduledInteractions, scheduledExpirationTime) => {
1247
- if (scheduledExpirationTime <= expirationTime) {
1224
+ if (scheduledExpirationTime >= expirationTime) {
1225
scheduledInteractions.forEach(interaction =>
1226
interactions.add(interaction),
1227
);
@@ -1550,11 +1527,11 @@ function computeThreadID(
1527
function computeUniqueAsyncExpiration(): ExpirationTime {
1528
const currentTime = requestCurrentTime();
1529
let result = computeAsyncExpiration(currentTime);
1553
- if (result <= lastUniqueAsyncExpiration) {
1530
+ if (result >= lastUniqueAsyncExpiration) {
1531
// Since we assume the current time monotonically increases, we only hit
1532
// this branch when computeUniqueAsyncExpiration is fired multiple times
1533
// within a 200ms window (or whatever the async bucket size is).
1557
- result = lastUniqueAsyncExpiration + 1;
1534
+ result = lastUniqueAsyncExpiration - 1;
1535
}
1536
lastUniqueAsyncExpiration = result;
1537
return lastUniqueAsyncExpiration;
@@ -1589,7 +1566,7 @@ function computeExpirationForFiber(currentTime: ExpirationTime, fiber: Fiber) {
1566
// If we're in the middle of rendering a tree, do not update at the same
1567
// expiration time that is already rendering.
1568
if (nextRoot !== null && expirationTime === nextRenderExpirationTime) {
1592
- expirationTime += 1;
1569
+ expirationTime -= 1;
1570
}
1571
} else {
1572
// This is a sync update
@@ -1600,7 +1577,10 @@ function computeExpirationForFiber(currentTime: ExpirationTime, fiber: Fiber) {
1577
// This is an interactive update. Keep track of the lowest pending
1578
// interactive expiration time. This allows us to synchronously flush
1579
// all interactive updates when needed.
1603
- if (expirationTime > lowestPriorityPendingInteractiveExpirationTime) {
1580
+ if (
1581
+ lowestPriorityPendingInteractiveExpirationTime === NoWork ||
1582
+ expirationTime < lowestPriorityPendingInteractiveExpirationTime
1583
+ ) {
1584
lowestPriorityPendingInteractiveExpirationTime = expirationTime;
1585
}
1586
}
@@ -1694,18 +1674,11 @@ function scheduleWorkToRoot(fiber: Fiber, expirationTime): FiberRoot | null {
1674
}
1675
1676
// Update the source fiber's expiration time
1697
- if (
1698
- fiber.expirationTime === NoWork ||
1699
- fiber.expirationTime > expirationTime
1700
- ) {
1677
+ if (fiber.expirationTime < expirationTime) {
1678
fiber.expirationTime = expirationTime;
1679
}
1680
let alternate = fiber.alternate;
1704
- if (
1705
- alternate !== null &&
1706
- (alternate.expirationTime === NoWork ||
1707
- alternate.expirationTime > expirationTime)
1708
- ) {
1681
+ if (alternate !== null && alternate.expirationTime < expirationTime) {
1682
alternate.expirationTime = expirationTime;
1683
}
1684
// Walk the parent path to the root and update the child expiration time.
@@ -1716,22 +1689,17 @@ function scheduleWorkToRoot(fiber: Fiber, expirationTime): FiberRoot | null {
1689
} else {
1690
while (node !== null) {
1691
alternate = node.alternate;
1719
- if (
1720
- node.childExpirationTime === NoWork ||
1721
- node.childExpirationTime > expirationTime
1722
- ) {
1692
+ if (node.childExpirationTime < expirationTime) {
1693
node.childExpirationTime = expirationTime;
1694
if (
1695
alternate !== null &&
1726
- (alternate.childExpirationTime === NoWork ||
1727
- alternate.childExpirationTime > expirationTime)
1696
+ alternate.childExpirationTime < expirationTime
1697
) {
1698
alternate.childExpirationTime = expirationTime;
1699
}
1700
} else if (
1701
alternate !== null &&
1733
- (alternate.childExpirationTime === NoWork ||
1734
- alternate.childExpirationTime > expirationTime)
1702
+ alternate.childExpirationTime < expirationTime
1703
) {
1704
alternate.childExpirationTime = expirationTime;
1705
}
@@ -1806,7 +1774,7 @@ function scheduleWork(fiber: Fiber, expirationTime: ExpirationTime) {
1774
if (
1775
!isWorking &&
1776
nextRenderExpirationTime !== NoWork &&
1809
- expirationTime < nextRenderExpirationTime
1777
+ expirationTime > nextRenderExpirationTime
1778
) {
1779
// This is an interruption. (Used for performance tracking.)
1780
interruptedBy = fiber;
@@ -1911,7 +1879,7 @@ function scheduleCallbackWithExpirationTime(
1879
) {
1880
if (callbackExpirationTime !== NoWork) {
1881
// A callback is already scheduled. Check its expiration time (timeout).
1914
- if (expirationTime > callbackExpirationTime) {
1882
+ if (expirationTime < callbackExpirationTime) {
1883
// Existing callback has sufficient timeout. Exit.
1884
return;
1885
} else {
@@ -2083,10 +2051,7 @@ function addRootToSchedule(root: FiberRoot, expirationTime: ExpirationTime) {
2051
} else {
2052
// This root is already scheduled, but its priority may have increased.
2053
const remainingExpirationTime = root.expirationTime;
2086
- if (
2087
- remainingExpirationTime === NoWork ||
2088
- expirationTime < remainingExpirationTime
2089
- ) {
2054
+ if (expirationTime > remainingExpirationTime) {
2055
// Update the priority.
2056
root.expirationTime = expirationTime;
2057
}
@@ -2135,10 +2100,7 @@ function findHighestPriorityRoot() {
2100
}
2101
root = previousScheduledRoot.nextScheduledRoot;
2102
} else {
2138
- if (
2139
- highestPriorityWork === NoWork ||
2140
- remainingExpirationTime < highestPriorityWork
2141
- ) {
2103
+ if (remainingExpirationTime > highestPriorityWork) {
2104
// Update the priority, if it's higher
2105
highestPriorityWork = remainingExpirationTime;
2106
highestPriorityRoot = root;
@@ -2214,7 +2176,7 @@ function performWork(minExpirationTime: ExpirationTime, isYieldy: boolean) {
2176
currentSchedulerTime = currentRendererTime;
2177
2178
if (enableUserTimingAPI) {
2217
- const didExpire = nextFlushedExpirationTime < currentRendererTime;
2179
+ const didExpire = nextFlushedExpirationTime > currentRendererTime;
2180
const timeout = expirationTimeToMs(nextFlushedExpirationTime);
2181
stopRequestCallbackTimer(didExpire, timeout);
2182
}
@@ -2222,14 +2184,13 @@ function performWork(minExpirationTime: ExpirationTime, isYieldy: boolean) {
2184
while (
2185
nextFlushedRoot !== null &&
2186
nextFlushedExpirationTime !== NoWork &&
2225
- (minExpirationTime === NoWork ||
2226
- minExpirationTime >= nextFlushedExpirationTime) &&
2227
- !(didYield && currentRendererTime < nextFlushedExpirationTime)
2187
+ minExpirationTime <= nextFlushedExpirationTime &&
2188
+ !(didYield && currentRendererTime > nextFlushedExpirationTime)
2189
) {
2190
performWorkOnRoot(
2191
nextFlushedRoot,
2192
nextFlushedExpirationTime,
2232
- currentRendererTime < nextFlushedExpirationTime,
2193
+ currentRendererTime > nextFlushedExpirationTime,
2194
);
2195
findHighestPriorityRoot();
2196
recomputeCurrentRendererTime();
@@ -2239,8 +2200,7 @@ function performWork(minExpirationTime: ExpirationTime, isYieldy: boolean) {
2200
while (
2201
nextFlushedRoot !== null &&
2202
nextFlushedExpirationTime !== NoWork &&
2242
- (minExpirationTime === NoWork ||
2243
- minExpirationTime >= nextFlushedExpirationTime)
2203
+ minExpirationTime <= nextFlushedExpirationTime
2204
) {
2205
performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime, false);
2206
findHighestPriorityRoot();
@@ -2395,7 +2355,7 @@ function completeRoot(
2355
): void {
2356
// Check if there's a batch that matches this expiration time.
2357
const firstBatch = root.firstBatch;
2398
- if (firstBatch !== null && firstBatch._expirationTime <= expirationTime) {
2358
+ if (firstBatch !== null && firstBatch._expirationTime >= expirationTime) {
2359
if (completedBatches === null) {
2360
completedBatches = [firstBatch];
2361
} else {
packages/react-reconciler/src/ReactUpdateQueue.js
+4
-10
@@ -425,7 +425,7 @@ export function processUpdateQueue<State>(
425
let resultState = newBaseState;
426
while (update !== null) {
427
const updateExpirationTime = update.expirationTime;
428
- if (updateExpirationTime > renderExpirationTime) {
428
+ if (updateExpirationTime < renderExpirationTime) {
429
// This update does not have sufficient priority. Skip it.
430
if (newFirstUpdate === null) {
431
// This is the first skipped update. It will be the first update in
@@ -437,10 +437,7 @@ export function processUpdateQueue<State>(
437
}
438
// Since this update will remain in the list, update the remaining
439
// expiration time.
440
- if (
441
- newExpirationTime === NoWork ||
442
- newExpirationTime > updateExpirationTime
443
- ) {
440
+ if (newExpirationTime < updateExpirationTime) {
441
newExpirationTime = updateExpirationTime;
442
}
443
} else {
@@ -476,7 +473,7 @@ export function processUpdateQueue<State>(
473
update = queue.firstCapturedUpdate;
474
while (update !== null) {
475
const updateExpirationTime = update.expirationTime;
479
- if (updateExpirationTime > renderExpirationTime) {
476
+ if (updateExpirationTime < renderExpirationTime) {
477
// This update does not have sufficient priority. Skip it.
478
if (newFirstCapturedUpdate === null) {
479
// This is the first skipped captured update. It will be the first
@@ -490,10 +487,7 @@ export function processUpdateQueue<State>(
487
}
488
// Since this update will remain in the list, update the remaining
489
// expiration time.
493
- if (
494
- newExpirationTime === NoWork ||
495
- newExpirationTime > updateExpirationTime
496
- ) {
490
+ if (newExpirationTime < updateExpirationTime) {
491
newExpirationTime = updateExpirationTime;
492
}
493
} else {