mirror of
https://github.com/hanzoai/react.git
synced 2026-09-24 17:02:27 +00:00
Flip expiration times (#13912)
See https://github.com/facebook/react/pull/13912 commit messages for how this was done.
This commit is contained in:
+1
-1
@@ -400,7 +400,7 @@ ReactRoot.prototype.createBatch = function(): Batch {
|
||||
let insertBefore = firstBatch;
|
||||
while (
|
||||
insertBefore !== null &&
|
||||
insertBefore._expirationTime <= expirationTime
|
||||
insertBefore._expirationTime >= expirationTime
|
||||
) {
|
||||
insertAfter = insertBefore;
|
||||
insertBefore = insertBefore._next;
|
||||
|
||||
+3
-2
@@ -956,9 +956,10 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
|
||||
rootID: string = DEFAULT_ROOT_ID,
|
||||
) {
|
||||
const root: any = roots.get(rootID);
|
||||
const expiration = NoopRenderer.computeUniqueAsyncExpiration();
|
||||
const batch = {
|
||||
_defer: true,
|
||||
_expirationTime: 1,
|
||||
_expirationTime: expiration,
|
||||
_onComplete: () => {
|
||||
root.firstBatch = null;
|
||||
},
|
||||
@@ -969,7 +970,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
|
||||
expect(actual).toEqual(expectedFlush);
|
||||
return (expectedCommit: Array<mixed>) => {
|
||||
batch._defer = false;
|
||||
NoopRenderer.flushRoot(root, 1);
|
||||
NoopRenderer.flushRoot(root, expiration);
|
||||
expect(yieldedValues).toEqual(expectedCommit);
|
||||
};
|
||||
},
|
||||
|
||||
+5
-16
@@ -265,10 +265,7 @@ function updateMemoComponent(
|
||||
return child;
|
||||
}
|
||||
let currentChild = ((current.child: any): Fiber); // This is always exactly one child
|
||||
if (
|
||||
updateExpirationTime === NoWork ||
|
||||
updateExpirationTime > renderExpirationTime
|
||||
) {
|
||||
if (updateExpirationTime < renderExpirationTime) {
|
||||
// This will be the props with resolved defaultProps,
|
||||
// unlike current.memoizedProps which will be the unresolved ones.
|
||||
const prevProps = currentChild.memoizedProps;
|
||||
@@ -302,11 +299,7 @@ function updateSimpleMemoComponent(
|
||||
updateExpirationTime,
|
||||
renderExpirationTime: ExpirationTime,
|
||||
): null | Fiber {
|
||||
if (
|
||||
current !== null &&
|
||||
(updateExpirationTime === NoWork ||
|
||||
updateExpirationTime > renderExpirationTime)
|
||||
) {
|
||||
if (current !== null && updateExpirationTime < renderExpirationTime) {
|
||||
const prevProps = current.memoizedProps;
|
||||
if (
|
||||
shallowEqual(prevProps, nextProps) &&
|
||||
@@ -1471,10 +1464,7 @@ function bailoutOnAlreadyFinishedWork(
|
||||
|
||||
// Check if the children have any pending work.
|
||||
const childExpirationTime = workInProgress.childExpirationTime;
|
||||
if (
|
||||
childExpirationTime === NoWork ||
|
||||
childExpirationTime > renderExpirationTime
|
||||
) {
|
||||
if (childExpirationTime < renderExpirationTime) {
|
||||
// The children don't have any work either. We can skip them.
|
||||
// TODO: Once we add back resuming, we should check if the children are
|
||||
// a work-in-progress set. If so, we need to transfer their effects.
|
||||
@@ -1500,8 +1490,7 @@ function beginWork(
|
||||
if (
|
||||
oldProps === newProps &&
|
||||
!hasLegacyContextChanged() &&
|
||||
(updateExpirationTime === NoWork ||
|
||||
updateExpirationTime > renderExpirationTime)
|
||||
updateExpirationTime < renderExpirationTime
|
||||
) {
|
||||
// This fiber does not have any pending work. Bailout without entering
|
||||
// the begin phase. There's still some bookkeeping we that needs to be done
|
||||
@@ -1550,7 +1539,7 @@ function beginWork(
|
||||
primaryChildFragment.childExpirationTime;
|
||||
if (
|
||||
primaryChildExpirationTime !== NoWork &&
|
||||
primaryChildExpirationTime <= renderExpirationTime
|
||||
primaryChildExpirationTime >= renderExpirationTime
|
||||
) {
|
||||
// The primary children have pending work. Use the normal path
|
||||
// to attempt to render the primary children again.
|
||||
|
||||
@@ -12,20 +12,20 @@ import MAX_SIGNED_31_BIT_INT from './maxSigned31BitInt';
|
||||
export type ExpirationTime = number;
|
||||
|
||||
export const NoWork = 0;
|
||||
export const Sync = 1;
|
||||
export const Never = MAX_SIGNED_31_BIT_INT;
|
||||
export const Never = 1;
|
||||
export const Sync = MAX_SIGNED_31_BIT_INT;
|
||||
|
||||
const UNIT_SIZE = 10;
|
||||
const MAGIC_NUMBER_OFFSET = 2;
|
||||
const MAGIC_NUMBER_OFFSET = MAX_SIGNED_31_BIT_INT - 1;
|
||||
|
||||
// 1 unit of expiration time represents 10ms.
|
||||
export function msToExpirationTime(ms: number): ExpirationTime {
|
||||
// Always add an offset so that we don't clash with the magic number for NoWork.
|
||||
return ((ms / UNIT_SIZE) | 0) + MAGIC_NUMBER_OFFSET;
|
||||
return MAGIC_NUMBER_OFFSET - ((ms / UNIT_SIZE) | 0);
|
||||
}
|
||||
|
||||
export function expirationTimeToMs(expirationTime: ExpirationTime): number {
|
||||
return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE;
|
||||
return (MAGIC_NUMBER_OFFSET - expirationTime) * UNIT_SIZE;
|
||||
}
|
||||
|
||||
function ceiling(num: number, precision: number): number {
|
||||
@@ -38,9 +38,9 @@ function computeExpirationBucket(
|
||||
bucketSizeMs,
|
||||
): ExpirationTime {
|
||||
return (
|
||||
MAGIC_NUMBER_OFFSET +
|
||||
MAGIC_NUMBER_OFFSET -
|
||||
ceiling(
|
||||
currentTime - MAGIC_NUMBER_OFFSET + expirationInMs / UNIT_SIZE,
|
||||
MAGIC_NUMBER_OFFSET - currentTime + expirationInMs / UNIT_SIZE,
|
||||
bucketSizeMs / UNIT_SIZE,
|
||||
)
|
||||
);
|
||||
|
||||
+2
-5
@@ -404,7 +404,7 @@ export function useReducer<S, A>(
|
||||
let didSkip = false;
|
||||
do {
|
||||
const updateExpirationTime = update.expirationTime;
|
||||
if (updateExpirationTime > renderExpirationTime) {
|
||||
if (updateExpirationTime < renderExpirationTime) {
|
||||
// Priority is insufficient. Skip this update. If this is the first
|
||||
// skipped update, the previous update/state is the new base
|
||||
// update/state.
|
||||
@@ -414,10 +414,7 @@ export function useReducer<S, A>(
|
||||
newBaseState = newState;
|
||||
}
|
||||
// Update the remaining priority in the queue.
|
||||
if (
|
||||
remainingExpirationTime === NoWork ||
|
||||
updateExpirationTime < remainingExpirationTime
|
||||
) {
|
||||
if (updateExpirationTime > remainingExpirationTime) {
|
||||
remainingExpirationTime = updateExpirationTime;
|
||||
}
|
||||
} else {
|
||||
|
||||
+5
-15
@@ -22,7 +22,6 @@ import warningWithoutStack from 'shared/warningWithoutStack';
|
||||
import {isPrimaryRenderer} from './ReactFiberHostConfig';
|
||||
import {createCursor, push, pop} from './ReactFiberStack';
|
||||
import MAX_SIGNED_31_BIT_INT from './maxSigned31BitInt';
|
||||
import {NoWork} from './ReactFiberExpirationTime';
|
||||
import {ContextProvider, ClassComponent} from 'shared/ReactWorkTags';
|
||||
|
||||
import invariant from 'shared/invariant';
|
||||
@@ -169,17 +168,13 @@ export function propagateContextChange(
|
||||
enqueueUpdate(fiber, update);
|
||||
}
|
||||
|
||||
if (
|
||||
fiber.expirationTime === NoWork ||
|
||||
fiber.expirationTime > renderExpirationTime
|
||||
) {
|
||||
if (fiber.expirationTime < renderExpirationTime) {
|
||||
fiber.expirationTime = renderExpirationTime;
|
||||
}
|
||||
let alternate = fiber.alternate;
|
||||
if (
|
||||
alternate !== null &&
|
||||
(alternate.expirationTime === NoWork ||
|
||||
alternate.expirationTime > renderExpirationTime)
|
||||
alternate.expirationTime < renderExpirationTime
|
||||
) {
|
||||
alternate.expirationTime = renderExpirationTime;
|
||||
}
|
||||
@@ -188,22 +183,17 @@ export function propagateContextChange(
|
||||
let node = fiber.return;
|
||||
while (node !== null) {
|
||||
alternate = node.alternate;
|
||||
if (
|
||||
node.childExpirationTime === NoWork ||
|
||||
node.childExpirationTime > renderExpirationTime
|
||||
) {
|
||||
if (node.childExpirationTime < renderExpirationTime) {
|
||||
node.childExpirationTime = renderExpirationTime;
|
||||
if (
|
||||
alternate !== null &&
|
||||
(alternate.childExpirationTime === NoWork ||
|
||||
alternate.childExpirationTime > renderExpirationTime)
|
||||
alternate.childExpirationTime < renderExpirationTime
|
||||
) {
|
||||
alternate.childExpirationTime = renderExpirationTime;
|
||||
}
|
||||
} else if (
|
||||
alternate !== null &&
|
||||
(alternate.childExpirationTime === NoWork ||
|
||||
alternate.childExpirationTime > renderExpirationTime)
|
||||
alternate.childExpirationTime < renderExpirationTime
|
||||
) {
|
||||
alternate.childExpirationTime = renderExpirationTime;
|
||||
} else {
|
||||
|
||||
+20
-32
@@ -31,12 +31,12 @@ export function markPendingPriorityLevel(
|
||||
// No other pending updates.
|
||||
root.earliestPendingTime = root.latestPendingTime = expirationTime;
|
||||
} else {
|
||||
if (earliestPendingTime > expirationTime) {
|
||||
if (earliestPendingTime < expirationTime) {
|
||||
// This is the earliest pending update.
|
||||
root.earliestPendingTime = expirationTime;
|
||||
} else {
|
||||
const latestPendingTime = root.latestPendingTime;
|
||||
if (latestPendingTime < expirationTime) {
|
||||
if (latestPendingTime > expirationTime) {
|
||||
// This is the latest pending update
|
||||
root.latestPendingTime = expirationTime;
|
||||
}
|
||||
@@ -65,12 +65,12 @@ export function markCommittedPriorityLevels(
|
||||
// Let's see if the previous latest known pending level was just flushed.
|
||||
const latestPendingTime = root.latestPendingTime;
|
||||
if (latestPendingTime !== NoWork) {
|
||||
if (latestPendingTime < earliestRemainingTime) {
|
||||
if (latestPendingTime > earliestRemainingTime) {
|
||||
// We've flushed all the known pending levels.
|
||||
root.earliestPendingTime = root.latestPendingTime = NoWork;
|
||||
} else {
|
||||
const earliestPendingTime = root.earliestPendingTime;
|
||||
if (earliestPendingTime < earliestRemainingTime) {
|
||||
if (earliestPendingTime > earliestRemainingTime) {
|
||||
// We've flushed the earliest known pending level. Set this to the
|
||||
// latest pending time.
|
||||
root.earliestPendingTime = root.latestPendingTime;
|
||||
@@ -92,7 +92,7 @@ export function markCommittedPriorityLevels(
|
||||
}
|
||||
|
||||
const latestSuspendedTime = root.latestSuspendedTime;
|
||||
if (earliestRemainingTime > latestSuspendedTime) {
|
||||
if (earliestRemainingTime < latestSuspendedTime) {
|
||||
// The earliest remaining level is later than all the suspended work. That
|
||||
// means we've flushed all the suspended work.
|
||||
root.earliestSuspendedTime = NoWork;
|
||||
@@ -106,7 +106,7 @@ export function markCommittedPriorityLevels(
|
||||
return;
|
||||
}
|
||||
|
||||
if (earliestRemainingTime < earliestSuspendedTime) {
|
||||
if (earliestRemainingTime > earliestSuspendedTime) {
|
||||
// The earliest remaining time is earlier than all the suspended work.
|
||||
// Treat it as a pending update.
|
||||
markPendingPriorityLevel(root, earliestRemainingTime);
|
||||
@@ -128,10 +128,10 @@ export function hasLowerPriorityWork(
|
||||
const latestPingedTime = root.latestPingedTime;
|
||||
return (
|
||||
(latestPendingTime !== NoWork &&
|
||||
latestPendingTime > erroredExpirationTime) ||
|
||||
latestPendingTime < erroredExpirationTime) ||
|
||||
(latestSuspendedTime !== NoWork &&
|
||||
latestSuspendedTime > erroredExpirationTime) ||
|
||||
(latestPingedTime !== NoWork && latestPingedTime > erroredExpirationTime)
|
||||
latestSuspendedTime < erroredExpirationTime) ||
|
||||
(latestPingedTime !== NoWork && latestPingedTime < erroredExpirationTime)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -143,8 +143,8 @@ export function isPriorityLevelSuspended(
|
||||
const latestSuspendedTime = root.latestSuspendedTime;
|
||||
return (
|
||||
earliestSuspendedTime !== NoWork &&
|
||||
expirationTime >= earliestSuspendedTime &&
|
||||
expirationTime <= latestSuspendedTime
|
||||
expirationTime <= earliestSuspendedTime &&
|
||||
expirationTime >= latestSuspendedTime
|
||||
);
|
||||
}
|
||||
|
||||
@@ -180,10 +180,10 @@ export function markSuspendedPriorityLevel(
|
||||
// No other suspended levels.
|
||||
root.earliestSuspendedTime = root.latestSuspendedTime = suspendedTime;
|
||||
} else {
|
||||
if (earliestSuspendedTime > suspendedTime) {
|
||||
if (earliestSuspendedTime < suspendedTime) {
|
||||
// This is the earliest suspended level.
|
||||
root.earliestSuspendedTime = suspendedTime;
|
||||
} else if (latestSuspendedTime < suspendedTime) {
|
||||
} else if (latestSuspendedTime > suspendedTime) {
|
||||
// This is the latest suspended level
|
||||
root.latestSuspendedTime = suspendedTime;
|
||||
}
|
||||
@@ -202,7 +202,7 @@ export function markPingedPriorityLevel(
|
||||
// is thrown out and not reused during the restarted render. One way to
|
||||
// invalidate the progressed work is to restart at expirationTime + 1.
|
||||
const latestPingedTime = root.latestPingedTime;
|
||||
if (latestPingedTime === NoWork || latestPingedTime < pingedTime) {
|
||||
if (latestPingedTime === NoWork || latestPingedTime > pingedTime) {
|
||||
root.latestPingedTime = pingedTime;
|
||||
}
|
||||
findNextExpirationTimeToWorkOn(pingedTime, root);
|
||||
@@ -212,7 +212,7 @@ function clearPing(root, completedTime) {
|
||||
// TODO: Track whether the root was pinged during the render phase. If so,
|
||||
// we need to make sure we don't lose track of it.
|
||||
const latestPingedTime = root.latestPingedTime;
|
||||
if (latestPingedTime !== NoWork && latestPingedTime <= completedTime) {
|
||||
if (latestPingedTime !== NoWork && latestPingedTime >= completedTime) {
|
||||
root.latestPingedTime = NoWork;
|
||||
}
|
||||
}
|
||||
@@ -225,18 +225,10 @@ export function findEarliestOutstandingPriorityLevel(
|
||||
|
||||
const earliestPendingTime = root.earliestPendingTime;
|
||||
const earliestSuspendedTime = root.earliestSuspendedTime;
|
||||
if (
|
||||
earliestExpirationTime === NoWork ||
|
||||
(earliestPendingTime !== NoWork &&
|
||||
earliestPendingTime < earliestExpirationTime)
|
||||
) {
|
||||
if (earliestPendingTime > earliestExpirationTime) {
|
||||
earliestExpirationTime = earliestPendingTime;
|
||||
}
|
||||
if (
|
||||
earliestExpirationTime === NoWork ||
|
||||
(earliestSuspendedTime !== NoWork &&
|
||||
earliestSuspendedTime < earliestExpirationTime)
|
||||
) {
|
||||
if (earliestSuspendedTime > earliestExpirationTime) {
|
||||
earliestExpirationTime = earliestSuspendedTime;
|
||||
}
|
||||
return earliestExpirationTime;
|
||||
@@ -247,7 +239,7 @@ export function didExpireAtExpirationTime(
|
||||
currentTime: ExpirationTime,
|
||||
): void {
|
||||
const expirationTime = root.expirationTime;
|
||||
if (expirationTime !== NoWork && currentTime >= expirationTime) {
|
||||
if (expirationTime !== NoWork && currentTime <= expirationTime) {
|
||||
// The root has expired. Flush all work up to the current time.
|
||||
root.nextExpirationTimeToWorkOn = currentTime;
|
||||
}
|
||||
@@ -269,7 +261,7 @@ function findNextExpirationTimeToWorkOn(completedExpirationTime, root) {
|
||||
if (
|
||||
nextExpirationTimeToWorkOn === NoWork &&
|
||||
(completedExpirationTime === NoWork ||
|
||||
latestSuspendedTime > completedExpirationTime)
|
||||
latestSuspendedTime < completedExpirationTime)
|
||||
) {
|
||||
// The lowest priority suspended work is the work most likely to be
|
||||
// committed next. Let's start rendering it again, so that if it times out,
|
||||
@@ -278,11 +270,7 @@ function findNextExpirationTimeToWorkOn(completedExpirationTime, root) {
|
||||
}
|
||||
|
||||
let expirationTime = nextExpirationTimeToWorkOn;
|
||||
if (
|
||||
expirationTime !== NoWork &&
|
||||
earliestSuspendedTime !== NoWork &&
|
||||
earliestSuspendedTime < expirationTime
|
||||
) {
|
||||
if (expirationTime !== NoWork && earliestSuspendedTime > expirationTime) {
|
||||
// Expire using the earliest known expiration time.
|
||||
expirationTime = earliestSuspendedTime;
|
||||
}
|
||||
|
||||
+32
-72
@@ -241,8 +241,8 @@ if (__DEV__) {
|
||||
};
|
||||
}
|
||||
|
||||
// Used to ensure computeUniqueAsyncExpiration is monotonically increasing.
|
||||
let lastUniqueAsyncExpiration: number = 0;
|
||||
// Used to ensure computeUniqueAsyncExpiration is monotonically decreasing.
|
||||
let lastUniqueAsyncExpiration: number = Sync - 1;
|
||||
|
||||
// Represents the expiration time that incoming updates should use. (If this
|
||||
// is NoWork, use the default strategy: async updates in async mode, sync
|
||||
@@ -605,9 +605,7 @@ function commitRoot(root: FiberRoot, finishedWork: Fiber): void {
|
||||
const updateExpirationTimeBeforeCommit = finishedWork.expirationTime;
|
||||
const childExpirationTimeBeforeCommit = finishedWork.childExpirationTime;
|
||||
const earliestRemainingTimeBeforeCommit =
|
||||
updateExpirationTimeBeforeCommit === NoWork ||
|
||||
(childExpirationTimeBeforeCommit !== NoWork &&
|
||||
childExpirationTimeBeforeCommit < updateExpirationTimeBeforeCommit)
|
||||
childExpirationTimeBeforeCommit > updateExpirationTimeBeforeCommit
|
||||
? childExpirationTimeBeforeCommit
|
||||
: updateExpirationTimeBeforeCommit;
|
||||
markCommittedPriorityLevels(root, earliestRemainingTimeBeforeCommit);
|
||||
@@ -798,9 +796,7 @@ function commitRoot(root: FiberRoot, finishedWork: Fiber): void {
|
||||
const updateExpirationTimeAfterCommit = finishedWork.expirationTime;
|
||||
const childExpirationTimeAfterCommit = finishedWork.childExpirationTime;
|
||||
const earliestRemainingTimeAfterCommit =
|
||||
updateExpirationTimeAfterCommit === NoWork ||
|
||||
(childExpirationTimeAfterCommit !== NoWork &&
|
||||
childExpirationTimeAfterCommit < updateExpirationTimeAfterCommit)
|
||||
childExpirationTimeAfterCommit > updateExpirationTimeAfterCommit
|
||||
? childExpirationTimeAfterCommit
|
||||
: updateExpirationTimeAfterCommit;
|
||||
if (earliestRemainingTimeAfterCommit === NoWork) {
|
||||
@@ -841,10 +837,7 @@ function commitRoot(root: FiberRoot, finishedWork: Fiber): void {
|
||||
// Only decrement the pending interaction count if we're done.
|
||||
// If there's still work at the current priority,
|
||||
// That indicates that we are waiting for suspense data.
|
||||
if (
|
||||
earliestRemainingTimeAfterCommit === NoWork ||
|
||||
scheduledExpirationTime < earliestRemainingTimeAfterCommit
|
||||
) {
|
||||
if (scheduledExpirationTime > earliestRemainingTimeAfterCommit) {
|
||||
pendingInteractionMap.delete(scheduledExpirationTime);
|
||||
|
||||
scheduledInteractions.forEach(interaction => {
|
||||
@@ -904,18 +897,10 @@ function resetChildExpirationTime(
|
||||
while (child !== null) {
|
||||
const childUpdateExpirationTime = child.expirationTime;
|
||||
const childChildExpirationTime = child.childExpirationTime;
|
||||
if (
|
||||
newChildExpirationTime === NoWork ||
|
||||
(childUpdateExpirationTime !== NoWork &&
|
||||
childUpdateExpirationTime < newChildExpirationTime)
|
||||
) {
|
||||
if (childUpdateExpirationTime > newChildExpirationTime) {
|
||||
newChildExpirationTime = childUpdateExpirationTime;
|
||||
}
|
||||
if (
|
||||
newChildExpirationTime === NoWork ||
|
||||
(childChildExpirationTime !== NoWork &&
|
||||
childChildExpirationTime < newChildExpirationTime)
|
||||
) {
|
||||
if (childChildExpirationTime > newChildExpirationTime) {
|
||||
newChildExpirationTime = childChildExpirationTime;
|
||||
}
|
||||
if (shouldBubbleActualDurations) {
|
||||
@@ -931,18 +916,10 @@ function resetChildExpirationTime(
|
||||
while (child !== null) {
|
||||
const childUpdateExpirationTime = child.expirationTime;
|
||||
const childChildExpirationTime = child.childExpirationTime;
|
||||
if (
|
||||
newChildExpirationTime === NoWork ||
|
||||
(childUpdateExpirationTime !== NoWork &&
|
||||
childUpdateExpirationTime < newChildExpirationTime)
|
||||
) {
|
||||
if (childUpdateExpirationTime > newChildExpirationTime) {
|
||||
newChildExpirationTime = childUpdateExpirationTime;
|
||||
}
|
||||
if (
|
||||
newChildExpirationTime === NoWork ||
|
||||
(childChildExpirationTime !== NoWork &&
|
||||
childChildExpirationTime < newChildExpirationTime)
|
||||
) {
|
||||
if (childChildExpirationTime > newChildExpirationTime) {
|
||||
newChildExpirationTime = childChildExpirationTime;
|
||||
}
|
||||
child = child.sibling;
|
||||
@@ -1244,7 +1221,7 @@ function renderRoot(root: FiberRoot, isYieldy: boolean): void {
|
||||
const interactions: Set<Interaction> = new Set();
|
||||
root.pendingInteractionMap.forEach(
|
||||
(scheduledInteractions, scheduledExpirationTime) => {
|
||||
if (scheduledExpirationTime <= expirationTime) {
|
||||
if (scheduledExpirationTime >= expirationTime) {
|
||||
scheduledInteractions.forEach(interaction =>
|
||||
interactions.add(interaction),
|
||||
);
|
||||
@@ -1550,11 +1527,11 @@ function computeThreadID(
|
||||
function computeUniqueAsyncExpiration(): ExpirationTime {
|
||||
const currentTime = requestCurrentTime();
|
||||
let result = computeAsyncExpiration(currentTime);
|
||||
if (result <= lastUniqueAsyncExpiration) {
|
||||
if (result >= lastUniqueAsyncExpiration) {
|
||||
// Since we assume the current time monotonically increases, we only hit
|
||||
// this branch when computeUniqueAsyncExpiration is fired multiple times
|
||||
// within a 200ms window (or whatever the async bucket size is).
|
||||
result = lastUniqueAsyncExpiration + 1;
|
||||
result = lastUniqueAsyncExpiration - 1;
|
||||
}
|
||||
lastUniqueAsyncExpiration = result;
|
||||
return lastUniqueAsyncExpiration;
|
||||
@@ -1589,7 +1566,7 @@ function computeExpirationForFiber(currentTime: ExpirationTime, fiber: Fiber) {
|
||||
// If we're in the middle of rendering a tree, do not update at the same
|
||||
// expiration time that is already rendering.
|
||||
if (nextRoot !== null && expirationTime === nextRenderExpirationTime) {
|
||||
expirationTime += 1;
|
||||
expirationTime -= 1;
|
||||
}
|
||||
} else {
|
||||
// This is a sync update
|
||||
@@ -1600,7 +1577,10 @@ function computeExpirationForFiber(currentTime: ExpirationTime, fiber: Fiber) {
|
||||
// This is an interactive update. Keep track of the lowest pending
|
||||
// interactive expiration time. This allows us to synchronously flush
|
||||
// all interactive updates when needed.
|
||||
if (expirationTime > lowestPriorityPendingInteractiveExpirationTime) {
|
||||
if (
|
||||
lowestPriorityPendingInteractiveExpirationTime === NoWork ||
|
||||
expirationTime < lowestPriorityPendingInteractiveExpirationTime
|
||||
) {
|
||||
lowestPriorityPendingInteractiveExpirationTime = expirationTime;
|
||||
}
|
||||
}
|
||||
@@ -1694,18 +1674,11 @@ function scheduleWorkToRoot(fiber: Fiber, expirationTime): FiberRoot | null {
|
||||
}
|
||||
|
||||
// Update the source fiber's expiration time
|
||||
if (
|
||||
fiber.expirationTime === NoWork ||
|
||||
fiber.expirationTime > expirationTime
|
||||
) {
|
||||
if (fiber.expirationTime < expirationTime) {
|
||||
fiber.expirationTime = expirationTime;
|
||||
}
|
||||
let alternate = fiber.alternate;
|
||||
if (
|
||||
alternate !== null &&
|
||||
(alternate.expirationTime === NoWork ||
|
||||
alternate.expirationTime > expirationTime)
|
||||
) {
|
||||
if (alternate !== null && alternate.expirationTime < expirationTime) {
|
||||
alternate.expirationTime = expirationTime;
|
||||
}
|
||||
// Walk the parent path to the root and update the child expiration time.
|
||||
@@ -1716,22 +1689,17 @@ function scheduleWorkToRoot(fiber: Fiber, expirationTime): FiberRoot | null {
|
||||
} else {
|
||||
while (node !== null) {
|
||||
alternate = node.alternate;
|
||||
if (
|
||||
node.childExpirationTime === NoWork ||
|
||||
node.childExpirationTime > expirationTime
|
||||
) {
|
||||
if (node.childExpirationTime < expirationTime) {
|
||||
node.childExpirationTime = expirationTime;
|
||||
if (
|
||||
alternate !== null &&
|
||||
(alternate.childExpirationTime === NoWork ||
|
||||
alternate.childExpirationTime > expirationTime)
|
||||
alternate.childExpirationTime < expirationTime
|
||||
) {
|
||||
alternate.childExpirationTime = expirationTime;
|
||||
}
|
||||
} else if (
|
||||
alternate !== null &&
|
||||
(alternate.childExpirationTime === NoWork ||
|
||||
alternate.childExpirationTime > expirationTime)
|
||||
alternate.childExpirationTime < expirationTime
|
||||
) {
|
||||
alternate.childExpirationTime = expirationTime;
|
||||
}
|
||||
@@ -1806,7 +1774,7 @@ function scheduleWork(fiber: Fiber, expirationTime: ExpirationTime) {
|
||||
if (
|
||||
!isWorking &&
|
||||
nextRenderExpirationTime !== NoWork &&
|
||||
expirationTime < nextRenderExpirationTime
|
||||
expirationTime > nextRenderExpirationTime
|
||||
) {
|
||||
// This is an interruption. (Used for performance tracking.)
|
||||
interruptedBy = fiber;
|
||||
@@ -1911,7 +1879,7 @@ function scheduleCallbackWithExpirationTime(
|
||||
) {
|
||||
if (callbackExpirationTime !== NoWork) {
|
||||
// A callback is already scheduled. Check its expiration time (timeout).
|
||||
if (expirationTime > callbackExpirationTime) {
|
||||
if (expirationTime < callbackExpirationTime) {
|
||||
// Existing callback has sufficient timeout. Exit.
|
||||
return;
|
||||
} else {
|
||||
@@ -2083,10 +2051,7 @@ function addRootToSchedule(root: FiberRoot, expirationTime: ExpirationTime) {
|
||||
} else {
|
||||
// This root is already scheduled, but its priority may have increased.
|
||||
const remainingExpirationTime = root.expirationTime;
|
||||
if (
|
||||
remainingExpirationTime === NoWork ||
|
||||
expirationTime < remainingExpirationTime
|
||||
) {
|
||||
if (expirationTime > remainingExpirationTime) {
|
||||
// Update the priority.
|
||||
root.expirationTime = expirationTime;
|
||||
}
|
||||
@@ -2135,10 +2100,7 @@ function findHighestPriorityRoot() {
|
||||
}
|
||||
root = previousScheduledRoot.nextScheduledRoot;
|
||||
} else {
|
||||
if (
|
||||
highestPriorityWork === NoWork ||
|
||||
remainingExpirationTime < highestPriorityWork
|
||||
) {
|
||||
if (remainingExpirationTime > highestPriorityWork) {
|
||||
// Update the priority, if it's higher
|
||||
highestPriorityWork = remainingExpirationTime;
|
||||
highestPriorityRoot = root;
|
||||
@@ -2214,7 +2176,7 @@ function performWork(minExpirationTime: ExpirationTime, isYieldy: boolean) {
|
||||
currentSchedulerTime = currentRendererTime;
|
||||
|
||||
if (enableUserTimingAPI) {
|
||||
const didExpire = nextFlushedExpirationTime < currentRendererTime;
|
||||
const didExpire = nextFlushedExpirationTime > currentRendererTime;
|
||||
const timeout = expirationTimeToMs(nextFlushedExpirationTime);
|
||||
stopRequestCallbackTimer(didExpire, timeout);
|
||||
}
|
||||
@@ -2222,14 +2184,13 @@ function performWork(minExpirationTime: ExpirationTime, isYieldy: boolean) {
|
||||
while (
|
||||
nextFlushedRoot !== null &&
|
||||
nextFlushedExpirationTime !== NoWork &&
|
||||
(minExpirationTime === NoWork ||
|
||||
minExpirationTime >= nextFlushedExpirationTime) &&
|
||||
!(didYield && currentRendererTime < nextFlushedExpirationTime)
|
||||
minExpirationTime <= nextFlushedExpirationTime &&
|
||||
!(didYield && currentRendererTime > nextFlushedExpirationTime)
|
||||
) {
|
||||
performWorkOnRoot(
|
||||
nextFlushedRoot,
|
||||
nextFlushedExpirationTime,
|
||||
currentRendererTime < nextFlushedExpirationTime,
|
||||
currentRendererTime > nextFlushedExpirationTime,
|
||||
);
|
||||
findHighestPriorityRoot();
|
||||
recomputeCurrentRendererTime();
|
||||
@@ -2239,8 +2200,7 @@ function performWork(minExpirationTime: ExpirationTime, isYieldy: boolean) {
|
||||
while (
|
||||
nextFlushedRoot !== null &&
|
||||
nextFlushedExpirationTime !== NoWork &&
|
||||
(minExpirationTime === NoWork ||
|
||||
minExpirationTime >= nextFlushedExpirationTime)
|
||||
minExpirationTime <= nextFlushedExpirationTime
|
||||
) {
|
||||
performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime, false);
|
||||
findHighestPriorityRoot();
|
||||
@@ -2395,7 +2355,7 @@ function completeRoot(
|
||||
): void {
|
||||
// Check if there's a batch that matches this expiration time.
|
||||
const firstBatch = root.firstBatch;
|
||||
if (firstBatch !== null && firstBatch._expirationTime <= expirationTime) {
|
||||
if (firstBatch !== null && firstBatch._expirationTime >= expirationTime) {
|
||||
if (completedBatches === null) {
|
||||
completedBatches = [firstBatch];
|
||||
} else {
|
||||
|
||||
+4
-10
@@ -425,7 +425,7 @@ export function processUpdateQueue<State>(
|
||||
let resultState = newBaseState;
|
||||
while (update !== null) {
|
||||
const updateExpirationTime = update.expirationTime;
|
||||
if (updateExpirationTime > renderExpirationTime) {
|
||||
if (updateExpirationTime < renderExpirationTime) {
|
||||
// This update does not have sufficient priority. Skip it.
|
||||
if (newFirstUpdate === null) {
|
||||
// This is the first skipped update. It will be the first update in
|
||||
@@ -437,10 +437,7 @@ export function processUpdateQueue<State>(
|
||||
}
|
||||
// Since this update will remain in the list, update the remaining
|
||||
// expiration time.
|
||||
if (
|
||||
newExpirationTime === NoWork ||
|
||||
newExpirationTime > updateExpirationTime
|
||||
) {
|
||||
if (newExpirationTime < updateExpirationTime) {
|
||||
newExpirationTime = updateExpirationTime;
|
||||
}
|
||||
} else {
|
||||
@@ -476,7 +473,7 @@ export function processUpdateQueue<State>(
|
||||
update = queue.firstCapturedUpdate;
|
||||
while (update !== null) {
|
||||
const updateExpirationTime = update.expirationTime;
|
||||
if (updateExpirationTime > renderExpirationTime) {
|
||||
if (updateExpirationTime < renderExpirationTime) {
|
||||
// This update does not have sufficient priority. Skip it.
|
||||
if (newFirstCapturedUpdate === null) {
|
||||
// This is the first skipped captured update. It will be the first
|
||||
@@ -490,10 +487,7 @@ export function processUpdateQueue<State>(
|
||||
}
|
||||
// Since this update will remain in the list, update the remaining
|
||||
// expiration time.
|
||||
if (
|
||||
newExpirationTime === NoWork ||
|
||||
newExpirationTime > updateExpirationTime
|
||||
) {
|
||||
if (newExpirationTime < updateExpirationTime) {
|
||||
newExpirationTime = updateExpirationTime;
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user