Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
248 changes: 117 additions & 131 deletions packages/react-reconciler/src/ReactFiberPendingPriority.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,26 @@ import type {ExpirationTime} from './ReactFiberExpirationTime';

import {NoWork} from './ReactFiberExpirationTime';

import {enableSuspense} from 'shared/ReactFeatureFlags';

// TODO: Offscreen updates

export function markPendingPriorityLevel(
root: FiberRoot,
expirationTime: ExpirationTime,
): void {
if (enableSuspense) {
// Update the latest and earliest pending times
const earliestPendingTime = root.earliestPendingTime;
if (earliestPendingTime === NoWork) {
// No other pending updates.
root.earliestPendingTime = root.latestPendingTime = expirationTime;
// Update the latest and earliest pending times
const earliestPendingTime = root.earliestPendingTime;
if (earliestPendingTime === NoWork) {
// No other pending updates.
root.earliestPendingTime = root.latestPendingTime = expirationTime;
} else {
if (earliestPendingTime > expirationTime) {
// This is the earliest pending update.
root.earliestPendingTime = expirationTime;
} else {
if (earliestPendingTime > expirationTime) {
// This is the earliest pending update.
root.earliestPendingTime = expirationTime;
} else {
const latestPendingTime = root.latestPendingTime;
if (latestPendingTime < expirationTime) {
// This is the latest pending update
root.latestPendingTime = expirationTime;
}
const latestPendingTime = root.latestPendingTime;
if (latestPendingTime < expirationTime) {
// This is the latest pending update
root.latestPendingTime = expirationTime;
}
}
}
Expand All @@ -46,114 +42,110 @@ export function markCommittedPriorityLevels(
currentTime: ExpirationTime,
earliestRemainingTime: ExpirationTime,
): void {
if (enableSuspense) {
if (earliestRemainingTime === NoWork) {
// Fast path. There's no remaining work. Clear everything.
root.earliestPendingTime = NoWork;
root.latestPendingTime = NoWork;
root.earliestSuspendedTime = NoWork;
root.latestSuspendedTime = NoWork;
root.latestPingedTime = NoWork;
return;
}
if (earliestRemainingTime === NoWork) {
// Fast path. There's no remaining work. Clear everything.
root.earliestPendingTime = NoWork;
root.latestPendingTime = NoWork;
root.earliestSuspendedTime = NoWork;
root.latestSuspendedTime = NoWork;
root.latestPingedTime = NoWork;
return;
}

// Let's see if the previous latest known pending level was just flushed.
const latestPendingTime = root.latestPendingTime;
if (latestPendingTime !== NoWork) {
if (latestPendingTime < earliestRemainingTime) {
// We've flushed all the known pending levels.
root.earliestPendingTime = root.latestPendingTime = NoWork;
} else {
const earliestPendingTime = root.earliestPendingTime;
if (earliestPendingTime < earliestRemainingTime) {
// We've flushed the earliest known pending level. Set this to the
// latest pending time.
root.earliestPendingTime = root.latestPendingTime;
}
// Let's see if the previous latest known pending level was just flushed.
const latestPendingTime = root.latestPendingTime;
if (latestPendingTime !== NoWork) {
if (latestPendingTime < earliestRemainingTime) {
// We've flushed all the known pending levels.
root.earliestPendingTime = root.latestPendingTime = NoWork;
} else {
const earliestPendingTime = root.earliestPendingTime;
if (earliestPendingTime < earliestRemainingTime) {
// We've flushed the earliest known pending level. Set this to the
// latest pending time.
root.earliestPendingTime = root.latestPendingTime;
}
}
}

// Now let's handle the earliest remaining level in the whole tree. We need to
// decide whether to treat it as a pending level or as suspended. Check
// it falls within the range of known suspended levels.

const earliestSuspendedTime = root.earliestSuspendedTime;
if (earliestSuspendedTime === NoWork) {
// There's no suspended work. Treat the earliest remaining level as a
// pending level.
markPendingPriorityLevel(root, earliestRemainingTime);
return;
}
// Now let's handle the earliest remaining level in the whole tree. We need to
// decide whether to treat it as a pending level or as suspended. Check
// it falls within the range of known suspended levels.

const latestSuspendedTime = root.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;
root.latestSuspendedTime = NoWork;
root.latestPingedTime = NoWork;

// There's no suspended work. Treat the earliest remaining level as a
// pending level.
markPendingPriorityLevel(root, earliestRemainingTime);
return;
}
const earliestSuspendedTime = root.earliestSuspendedTime;
if (earliestSuspendedTime === NoWork) {
// There's no suspended work. Treat the earliest remaining level as a
// pending level.
markPendingPriorityLevel(root, earliestRemainingTime);
return;
}

if (earliestRemainingTime < earliestSuspendedTime) {
// The earliest remaining time is earlier than all the suspended work.
// Treat it as a pending update.
markPendingPriorityLevel(root, earliestRemainingTime);
return;
}
const latestSuspendedTime = root.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;
root.latestSuspendedTime = NoWork;
root.latestPingedTime = NoWork;

// There's no suspended work. Treat the earliest remaining level as a
// pending level.
markPendingPriorityLevel(root, earliestRemainingTime);
return;
}

// The earliest remaining time falls within the range of known suspended
// levels. We should treat this as suspended work.
if (earliestRemainingTime < earliestSuspendedTime) {
// The earliest remaining time is earlier than all the suspended work.
// Treat it as a pending update.
markPendingPriorityLevel(root, earliestRemainingTime);
return;
}

// The earliest remaining time falls within the range of known suspended
// levels. We should treat this as suspended work.
}

export function markSuspendedPriorityLevel(
root: FiberRoot,
suspendedTime: ExpirationTime,
): void {
if (enableSuspense) {
// First, check the known pending levels and update them if needed.
const earliestPendingTime = root.earliestPendingTime;
const latestPendingTime = root.latestPendingTime;
if (earliestPendingTime === suspendedTime) {
if (latestPendingTime === suspendedTime) {
// Both known pending levels were suspended. Clear them.
root.earliestPendingTime = root.latestPendingTime = NoWork;
} else {
// The earliest pending level was suspended. Clear by setting it to the
// latest pending level.
root.earliestPendingTime = latestPendingTime;
}
} else if (latestPendingTime === suspendedTime) {
// The latest pending level was suspended. Clear by setting it to the
// First, check the known pending levels and update them if needed.
const earliestPendingTime = root.earliestPendingTime;
const latestPendingTime = root.latestPendingTime;
if (earliestPendingTime === suspendedTime) {
if (latestPendingTime === suspendedTime) {
// Both known pending levels were suspended. Clear them.
root.earliestPendingTime = root.latestPendingTime = NoWork;
} else {
// The earliest pending level was suspended. Clear by setting it to the
// latest pending level.
root.latestPendingTime = earliestPendingTime;
root.earliestPendingTime = latestPendingTime;
}
} else if (latestPendingTime === suspendedTime) {
// The latest pending level was suspended. Clear by setting it to the
// latest pending level.
root.latestPendingTime = earliestPendingTime;
}

// Next, if we're working on the lowest known suspended level, clear the ping.
// TODO: What if a promise suspends and pings before the root completes?
const latestSuspendedTime = root.latestSuspendedTime;
if (latestSuspendedTime === suspendedTime) {
root.latestPingedTime = NoWork;
}
// Next, if we're working on the lowest known suspended level, clear the ping.
// TODO: What if a promise suspends and pings before the root completes?
const latestSuspendedTime = root.latestSuspendedTime;
if (latestSuspendedTime === suspendedTime) {
root.latestPingedTime = NoWork;
}

// Finally, update the known suspended levels.
const earliestSuspendedTime = root.earliestSuspendedTime;
if (earliestSuspendedTime === NoWork) {
// No other suspended levels.
root.earliestSuspendedTime = root.latestSuspendedTime = suspendedTime;
} else {
if (earliestSuspendedTime > suspendedTime) {
// This is the earliest suspended level.
root.earliestSuspendedTime = suspendedTime;
} else if (latestSuspendedTime < suspendedTime) {
// This is the latest suspended level
root.latestSuspendedTime = suspendedTime;
}
// Finally, update the known suspended levels.
const earliestSuspendedTime = root.earliestSuspendedTime;
if (earliestSuspendedTime === NoWork) {
// No other suspended levels.
root.earliestSuspendedTime = root.latestSuspendedTime = suspendedTime;
} else {
if (earliestSuspendedTime > suspendedTime) {
// This is the earliest suspended level.
root.earliestSuspendedTime = suspendedTime;
} else if (latestSuspendedTime < suspendedTime) {
// This is the latest suspended level
root.latestSuspendedTime = suspendedTime;
}
}
}
Expand All @@ -162,35 +154,29 @@ export function markPingedPriorityLevel(
root: FiberRoot,
pingedTime: ExpirationTime,
): void {
if (enableSuspense) {
const latestSuspendedTime = root.latestSuspendedTime;
if (latestSuspendedTime !== NoWork && latestSuspendedTime <= pingedTime) {
const latestPingedTime = root.latestPingedTime;
if (latestPingedTime === NoWork || latestPingedTime < pingedTime) {
root.latestPingedTime = pingedTime;
}
const latestSuspendedTime = root.latestSuspendedTime;
if (latestSuspendedTime !== NoWork && latestSuspendedTime <= pingedTime) {
const latestPingedTime = root.latestPingedTime;
if (latestPingedTime === NoWork || latestPingedTime < pingedTime) {
root.latestPingedTime = pingedTime;
}
}
}

export function findNextPendingPriorityLevel(root: FiberRoot): ExpirationTime {
if (enableSuspense) {
const earliestSuspendedTime = root.earliestSuspendedTime;
const earliestPendingTime = root.earliestPendingTime;
if (earliestSuspendedTime === NoWork) {
// Fast path. There's no suspended work.
return earliestPendingTime;
}

// First, check if there's known pending work.
if (earliestPendingTime !== NoWork) {
return earliestPendingTime;
}
const earliestSuspendedTime = root.earliestSuspendedTime;
const earliestPendingTime = root.earliestPendingTime;
if (earliestSuspendedTime === NoWork) {
// Fast path. There's no suspended work.
return earliestPendingTime;
}

// Finally, if a suspended level was pinged, work on that. Otherwise there's
// nothing to work on.
return root.latestPingedTime;
} else {
return root.current.expirationTime;
// First, check if there's known pending work.
if (earliestPendingTime !== NoWork) {
return earliestPendingTime;
}

// Finally, if a suspended level was pinged, work on that. Otherwise there's
// nothing to work on.
return root.latestPingedTime;
}
Loading