Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add withSuspenseConfig API #15593

Merged
merged 14 commits into from
May 16, 2019
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Track the largest suspense config expiration separately
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
commit 367354d64d7ca136b272fe4736bfad4ab092d0c5
27 changes: 15 additions & 12 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 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 @@ -2001,13 +2001,14 @@ function computeMsUntilSuspenseLoadingDelay(
// have to wait any additional time.
return 0;
}
const msUntilTimeout = timeElapsed - loadingDelayMs - minLoadingDurationMs;
const msUntilTimeout = loadingDelayMs + minLoadingDurationMs - timeElapsed;
// This is the value that is passed to `setTimeout`.
return msUntilTimeout;
}

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