Skip to content

Commit

Permalink
Track the largest suspense config expiration separately
Browse files Browse the repository at this point in the history
This ensures that if we've scheduled lower pri work that doesn't have a
suspenseConfig, we don't consider its expiration as the timeout.
  • Loading branch information
sebmarkbage committed May 16, 2019
1 parent 92d60cd commit f66d761
Showing 1 changed file with 18 additions and 15 deletions.
33 changes: 18 additions & 15 deletions packages/react-reconciler/src/ReactFiberScheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ let workInProgressRootExitStatus: RootExitStatus = RootIncomplete;
// because we deal mostly with expiration times in the hot path, so this avoids
// the conversion happening in the hot path.
let workInProgressRootLatestProcessedExpirationTime: ExpirationTime = Sync;
let workInProgressRootLatestSuspenseTimeout: ExpirationTime = Sync;
let workInProgressRootCanSuspendUsingConfig: null | SuspenseConfig = null;

let nextEffect: Fiber | null = null;
Expand Down Expand Up @@ -734,6 +735,7 @@ function prepareFreshStack(root, expirationTime) {
renderExpirationTime = expirationTime;
workInProgressRootExitStatus = RootIncomplete;
workInProgressRootLatestProcessedExpirationTime = Sync;
workInProgressRootLatestSuspenseTimeout = Sync;
workInProgressRootCanSuspendUsingConfig = null;

if (__DEV__) {
Expand Down Expand Up @@ -949,6 +951,7 @@ function renderRoot(
workInProgressRootExitStatus === RootSuspendedWithDelay;
let msUntilTimeout = computeMsUntilTimeout(
workInProgressRootLatestProcessedExpirationTime,
workInProgressRootLatestSuspenseTimeout,
expirationTime,
workInProgressRootCanSuspendUsingConfig,
shouldDelay,
Expand All @@ -973,14 +976,14 @@ function renderRoot(
// The work completed. Ready to commit.
if (
!isSync &&
workInProgressRootLatestProcessedExpirationTime !== Sync &&
workInProgressRootLatestSuspenseTimeout !== Sync &&
workInProgressRootCanSuspendUsingConfig !== null
) {
// If we have exceeded the minimum loading delay, which probably
// means we have shown a spinner already, we might have to suspend
// a bit longer to ensure that the spinner is shown for enough time.
const msUntilTimeout = computeMsUntilSuspenseLoadingDelay(
workInProgressRootLatestProcessedExpirationTime,
workInProgressRootLatestSuspenseTimeout,
expirationTime,
workInProgressRootCanSuspendUsingConfig,
);
Expand Down Expand Up @@ -1011,15 +1014,12 @@ export function markRenderEventTimeAndConfig(
workInProgressRootLatestProcessedExpirationTime = expirationTime;
}
if (suspenseConfig !== null) {
// Most of the time we only have one config and getting wrong is not bad.
// We pick the config with the lowest timeout because we'll use it to
// reverse engineer the event time if we end up using JND and we want to
// error on the side of suspending less time.
if (
workInProgressRootCanSuspendUsingConfig === null ||
workInProgressRootCanSuspendUsingConfig.timeoutMs <
suspenseConfig.timeoutMs
expirationTime < workInProgressRootLatestSuspenseTimeout &&
expirationTime > Never
) {
workInProgressRootLatestSuspenseTimeout = expirationTime;
// Most of the time we only have one config and getting wrong is not bad.
workInProgressRootCanSuspendUsingConfig = suspenseConfig;
}
}
Expand Down Expand Up @@ -1974,7 +1974,7 @@ function jnd(timeElapsed: number) {
}

function computeMsUntilSuspenseLoadingDelay(
mostRecentEventTime: ExpirationTime,
latestTimeout: ExpirationTime,
committedExpirationTime: ExpirationTime,
suspenseConfig: SuspenseConfig,
) {
Expand All @@ -1992,7 +1992,7 @@ function computeMsUntilSuspenseLoadingDelay(
// Compute the time until this render pass would expire.
const currentTimeMs: number = now();
const eventTimeMs: number = inferTimeFromExpirationTime(
mostRecentEventTime,
latestTimeout,
suspenseConfig,
);
const timeElapsed = currentTimeMs - eventTimeMs;
Expand All @@ -2008,6 +2008,7 @@ function computeMsUntilSuspenseLoadingDelay(

function computeMsUntilTimeout(
mostRecentEventTime: ExpirationTime,
suspenseTimeout: ExpirationTime,
committedExpirationTime: ExpirationTime,
suspenseConfig: null | SuspenseConfig,
shouldDelay: boolean,
Expand All @@ -2019,17 +2020,19 @@ function computeMsUntilTimeout(

// Compute the time until this render pass would expire.
const currentTimeMs: number = now();
const timeUntilExpirationMs =
expirationTimeToMs(committedExpirationTime) - currentTimeMs;

if (suspenseConfig !== null && shouldDelay) {
return timeUntilExpirationMs;
if (suspenseTimeout !== Sync && shouldDelay) {
const timeUntilTimeoutMs =
expirationTimeToMs(suspenseTimeout) - currentTimeMs;
return timeUntilTimeoutMs;
}

const eventTimeMs: number = inferTimeFromExpirationTime(
mostRecentEventTime,
suspenseConfig,
);
const timeUntilExpirationMs =
expirationTimeToMs(committedExpirationTime) - currentTimeMs;
let timeElapsed = currentTimeMs - eventTimeMs;
if (timeElapsed < 0) {
// We get this wrong some time since we estimate the time.
Expand Down

0 comments on commit f66d761

Please sign in to comment.