Allow transitions to interrupt Suspensey commits (#26531)

I originally made it so that a Suspensey commit — i.e. a commit that's
waiting for a stylesheet, image, or font to load before proceeding —
could not be interrupted by transitions. My reasoning was that Suspensey
commits always time out after a short interval, anyway, so if the
incoming update isn't urgent, it's better to wait to commit the current
frame instead of throwing it away.

I don't think this rationale was correct, for a few reasons. There are
some cases where we'll suspend for a longer duration, like stylesheets —
it's nearly always a bad idea to show content before its styles have
loaded, so we're going to be extend this timeout to be really long.

But even in the case where the timeout is shorter, like fonts, if you
get a new update, it's possible (even likely) that update will allow us
to avoid showing a fallback, like by navigating to a different page. So
we might as well try.

The behavior now matches our behavior for interrupting a suspended
render phase (i.e. `use`), which makes sense because they're not that
conceptually different.

DiffTrain build for commit https://github.com/facebook/react/commit/888874673f81c08d9c3cfd4a56e2e93fd728894c.
This commit is contained in:
acdlite
2023-03-31 19:40:33 +00:00
parent ee546aa020
commit a4a493a01c
13 changed files with 94 additions and 70 deletions
@@ -19639,12 +19639,14 @@ function scheduleTaskForRootDuringMicrotask(root, currentTime) {
var existingCallbackNode = root.callbackNode;
if (
// Check if there's nothing to work on
nextLanes === NoLanes || // If this root is currently suspended and waiting for data to resolve, don't
// schedule a task to render it. We'll either wait for a ping, or wait to
// receive an update.
(isWorkLoopSuspendedOnData() && root === workInProgressRoot) || // We should only interrupt a pending commit if the new update
// is urgent.
(root.cancelPendingCommit !== null && includesOnlyNonUrgentLanes(nextLanes))
//
// Suspended render phase
(root === workInProgressRoot && isWorkLoopSuspendedOnData()) || // Suspended commit phase
root.cancelPendingCommit !== null
) {
// Fast path: There's nothing to work on.
if (existingCallbackNode !== null) {
@@ -20023,8 +20025,10 @@ function scheduleUpdateOnFiber(root, fiber, lane, eventTime) {
// finish loading.
if (
workInProgressSuspendedReason === SuspendedOnData &&
root === workInProgressRoot
// Suspended render phase
(root === workInProgressRoot &&
workInProgressSuspendedReason === SuspendedOnData) || // Suspended commit phase
root.cancelPendingCommit !== null
) {
// The incoming update might unblock the current render. Interrupt the
// current attempt and restart from the top.
@@ -23865,7 +23869,7 @@ function createFiberRoot(
return root;
}
var ReactVersion = "18.3.0-next-09c8d2563-20230331";
var ReactVersion = "18.3.0-next-888874673-20230331";
// Might add PROFILE later.
@@ -6332,8 +6332,8 @@ function scheduleTaskForRootDuringMicrotask(root, currentTime) {
pingedLanes = root.callbackNode;
if (
0 === suspendedLanes ||
(2 === workInProgressSuspendedReason && root === currentTime) ||
(null !== root.cancelPendingCommit && 0 === (suspendedLanes & 42))
(root === currentTime && 2 === workInProgressSuspendedReason) ||
null !== root.cancelPendingCommit
)
return (
null !== pingedLanes &&
@@ -6433,10 +6433,12 @@ function requestUpdateLane(fiber) {
return 0 !== fiber ? fiber : 32;
}
function scheduleUpdateOnFiber(root, fiber, lane, eventTime) {
2 === workInProgressSuspendedReason &&
root === workInProgressRoot &&
(prepareFreshStack(root, 0),
markRootSuspended(root, workInProgressRootRenderLanes));
if (
(root === workInProgressRoot && 2 === workInProgressSuspendedReason) ||
null !== root.cancelPendingCommit
)
prepareFreshStack(root, 0),
markRootSuspended(root, workInProgressRootRenderLanes);
markRootUpdated(root, lane, eventTime);
if (0 === (executionContext & 2) || root !== workInProgressRoot)
root === workInProgressRoot &&
@@ -8672,7 +8674,7 @@ var devToolsConfig$jscomp$inline_1026 = {
throw Error("TestRenderer does not support findFiberByHostInstance()");
},
bundleType: 0,
version: "18.3.0-next-09c8d2563-20230331",
version: "18.3.0-next-888874673-20230331",
rendererPackageName: "react-test-renderer"
};
var internals$jscomp$inline_1218 = {
@@ -8703,7 +8705,7 @@ var internals$jscomp$inline_1218 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-next-09c8d2563-20230331"
reconcilerVersion: "18.3.0-next-888874673-20230331"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1219 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
@@ -6669,8 +6669,8 @@ function scheduleTaskForRootDuringMicrotask(root, currentTime) {
pingedLanes = root.callbackNode;
if (
0 === suspendedLanes ||
(2 === workInProgressSuspendedReason && root === currentTime) ||
(null !== root.cancelPendingCommit && 0 === (suspendedLanes & 42))
(root === currentTime && 2 === workInProgressSuspendedReason) ||
null !== root.cancelPendingCommit
)
return (
null !== pingedLanes &&
@@ -6771,10 +6771,12 @@ function requestUpdateLane(fiber) {
return 0 !== fiber ? fiber : 32;
}
function scheduleUpdateOnFiber(root, fiber, lane, eventTime) {
2 === workInProgressSuspendedReason &&
root === workInProgressRoot &&
(prepareFreshStack(root, 0),
markRootSuspended(root, workInProgressRootRenderLanes));
if (
(root === workInProgressRoot && 2 === workInProgressSuspendedReason) ||
null !== root.cancelPendingCommit
)
prepareFreshStack(root, 0),
markRootSuspended(root, workInProgressRootRenderLanes);
markRootUpdated(root, lane, eventTime);
if (0 === (executionContext & 2) || root !== workInProgressRoot)
root === workInProgressRoot &&
@@ -9097,7 +9099,7 @@ var devToolsConfig$jscomp$inline_1068 = {
throw Error("TestRenderer does not support findFiberByHostInstance()");
},
bundleType: 0,
version: "18.3.0-next-09c8d2563-20230331",
version: "18.3.0-next-888874673-20230331",
rendererPackageName: "react-test-renderer"
};
var internals$jscomp$inline_1259 = {
@@ -9128,7 +9130,7 @@ var internals$jscomp$inline_1259 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-next-09c8d2563-20230331"
reconcilerVersion: "18.3.0-next-888874673-20230331"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1260 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
@@ -27,7 +27,7 @@ if (
}
"use strict";
var ReactVersion = "18.3.0-next-09c8d2563-20230331";
var ReactVersion = "18.3.0-next-888874673-20230331";
// ATTENTION
// When adding new symbols to this file,
@@ -639,4 +639,4 @@ exports.useSyncExternalStore = function (
);
};
exports.useTransition = useTransition;
exports.version = "18.3.0-next-09c8d2563-20230331";
exports.version = "18.3.0-next-888874673-20230331";
@@ -642,7 +642,7 @@ exports.useSyncExternalStore = function (
);
};
exports.useTransition = useTransition;
exports.version = "18.3.0-next-09c8d2563-20230331";
exports.version = "18.3.0-next-888874673-20230331";
/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
if (
@@ -1 +1 @@
09c8d2563300621dc91258a4c2839210e2fbdf0e
888874673f81c08d9c3cfd4a56e2e93fd728894c
@@ -22708,12 +22708,14 @@ function scheduleTaskForRootDuringMicrotask(root, currentTime) {
var existingCallbackNode = root.callbackNode;
if (
// Check if there's nothing to work on
nextLanes === NoLanes || // If this root is currently suspended and waiting for data to resolve, don't
// schedule a task to render it. We'll either wait for a ping, or wait to
// receive an update.
(isWorkLoopSuspendedOnData() && root === workInProgressRoot) || // We should only interrupt a pending commit if the new update
// is urgent.
(root.cancelPendingCommit !== null && includesOnlyNonUrgentLanes(nextLanes))
//
// Suspended render phase
(root === workInProgressRoot && isWorkLoopSuspendedOnData()) || // Suspended commit phase
root.cancelPendingCommit !== null
) {
// Fast path: There's nothing to work on.
if (existingCallbackNode !== null) {
@@ -23089,8 +23091,10 @@ function scheduleUpdateOnFiber(root, fiber, lane, eventTime) {
// finish loading.
if (
workInProgressSuspendedReason === SuspendedOnData &&
root === workInProgressRoot
// Suspended render phase
(root === workInProgressRoot &&
workInProgressSuspendedReason === SuspendedOnData) || // Suspended commit phase
root.cancelPendingCommit !== null
) {
// The incoming update might unblock the current render. Interrupt the
// current attempt and restart from the top.
@@ -27141,7 +27145,7 @@ function createFiberRoot(
return root;
}
var ReactVersion = "18.3.0-next-09c8d2563-20230331";
var ReactVersion = "18.3.0-next-888874673-20230331";
function createPortal$1(
children,
@@ -7444,8 +7444,8 @@ function scheduleTaskForRootDuringMicrotask(root, currentTime) {
pingedLanes = root.callbackNode;
if (
0 === suspendedLanes ||
(2 === workInProgressSuspendedReason && root === currentTime) ||
(null !== root.cancelPendingCommit && 0 === (suspendedLanes & 42))
(root === currentTime && 2 === workInProgressSuspendedReason) ||
null !== root.cancelPendingCommit
)
return (
null !== pingedLanes &&
@@ -7555,10 +7555,12 @@ function requestUpdateLane(fiber) {
return fiber;
}
function scheduleUpdateOnFiber(root, fiber, lane, eventTime) {
2 === workInProgressSuspendedReason &&
root === workInProgressRoot &&
(prepareFreshStack(root, 0),
markRootSuspended(root, workInProgressRootRenderLanes));
if (
(root === workInProgressRoot && 2 === workInProgressSuspendedReason) ||
null !== root.cancelPendingCommit
)
prepareFreshStack(root, 0),
markRootSuspended(root, workInProgressRootRenderLanes);
markRootUpdated(root, lane, eventTime);
if (0 === (executionContext & 2) || root !== workInProgressRoot)
root === workInProgressRoot &&
@@ -9543,7 +9545,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1046 = {
findFiberByHostInstance: getInstanceFromNode,
bundleType: 0,
version: "18.3.0-next-09c8d2563-20230331",
version: "18.3.0-next-888874673-20230331",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForViewTag: function () {
@@ -9585,7 +9587,7 @@ var internals$jscomp$inline_1291 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-next-09c8d2563-20230331"
reconcilerVersion: "18.3.0-next-888874673-20230331"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1292 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
@@ -7971,8 +7971,8 @@ function scheduleTaskForRootDuringMicrotask(root, currentTime) {
pingedLanes = root.callbackNode;
if (
0 === suspendedLanes ||
(2 === workInProgressSuspendedReason && root === currentTime) ||
(null !== root.cancelPendingCommit && 0 === (suspendedLanes & 42))
(root === currentTime && 2 === workInProgressSuspendedReason) ||
null !== root.cancelPendingCommit
)
return (
null !== pingedLanes &&
@@ -8083,10 +8083,12 @@ function requestUpdateLane(fiber) {
return fiber;
}
function scheduleUpdateOnFiber(root, fiber, lane, eventTime) {
2 === workInProgressSuspendedReason &&
root === workInProgressRoot &&
(prepareFreshStack(root, 0),
markRootSuspended(root, workInProgressRootRenderLanes));
if (
(root === workInProgressRoot && 2 === workInProgressSuspendedReason) ||
null !== root.cancelPendingCommit
)
prepareFreshStack(root, 0),
markRootSuspended(root, workInProgressRootRenderLanes);
markRootUpdated(root, lane, eventTime);
if (0 === (executionContext & 2) || root !== workInProgressRoot)
isDevToolsPresent && addFiberToLanesMap(root, fiber, lane),
@@ -10251,7 +10253,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1124 = {
findFiberByHostInstance: getInstanceFromNode,
bundleType: 0,
version: "18.3.0-next-09c8d2563-20230331",
version: "18.3.0-next-888874673-20230331",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForViewTag: function () {
@@ -10306,7 +10308,7 @@ var roots = new Map(),
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-next-09c8d2563-20230331"
reconcilerVersion: "18.3.0-next-888874673-20230331"
});
exports.createPortal = function (children, containerTag) {
return createPortal$1(
@@ -23248,12 +23248,14 @@ function scheduleTaskForRootDuringMicrotask(root, currentTime) {
var existingCallbackNode = root.callbackNode;
if (
// Check if there's nothing to work on
nextLanes === NoLanes || // If this root is currently suspended and waiting for data to resolve, don't
// schedule a task to render it. We'll either wait for a ping, or wait to
// receive an update.
(isWorkLoopSuspendedOnData() && root === workInProgressRoot) || // We should only interrupt a pending commit if the new update
// is urgent.
(root.cancelPendingCommit !== null && includesOnlyNonUrgentLanes(nextLanes))
//
// Suspended render phase
(root === workInProgressRoot && isWorkLoopSuspendedOnData()) || // Suspended commit phase
root.cancelPendingCommit !== null
) {
// Fast path: There's nothing to work on.
if (existingCallbackNode !== null) {
@@ -23629,8 +23631,10 @@ function scheduleUpdateOnFiber(root, fiber, lane, eventTime) {
// finish loading.
if (
workInProgressSuspendedReason === SuspendedOnData &&
root === workInProgressRoot
// Suspended render phase
(root === workInProgressRoot &&
workInProgressSuspendedReason === SuspendedOnData) || // Suspended commit phase
root.cancelPendingCommit !== null
) {
// The incoming update might unblock the current render. Interrupt the
// current attempt and restart from the top.
@@ -27681,7 +27685,7 @@ function createFiberRoot(
return root;
}
var ReactVersion = "18.3.0-next-09c8d2563-20230331";
var ReactVersion = "18.3.0-next-888874673-20230331";
function createPortal$1(
children,
@@ -7706,8 +7706,8 @@ function scheduleTaskForRootDuringMicrotask(root, currentTime) {
pingedLanes = root.callbackNode;
if (
0 === suspendedLanes ||
(2 === workInProgressSuspendedReason && root === currentTime) ||
(null !== root.cancelPendingCommit && 0 === (suspendedLanes & 42))
(root === currentTime && 2 === workInProgressSuspendedReason) ||
null !== root.cancelPendingCommit
)
return (
null !== pingedLanes &&
@@ -7804,10 +7804,12 @@ function requestUpdateLane(fiber) {
return 0 !== fiber ? fiber : 32;
}
function scheduleUpdateOnFiber(root, fiber, lane, eventTime) {
2 === workInProgressSuspendedReason &&
root === workInProgressRoot &&
(prepareFreshStack(root, 0),
markRootSuspended(root, workInProgressRootRenderLanes));
if (
(root === workInProgressRoot && 2 === workInProgressSuspendedReason) ||
null !== root.cancelPendingCommit
)
prepareFreshStack(root, 0),
markRootSuspended(root, workInProgressRootRenderLanes);
markRootUpdated(root, lane, eventTime);
if (0 === (executionContext & 2) || root !== workInProgressRoot)
root === workInProgressRoot &&
@@ -9799,7 +9801,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1105 = {
findFiberByHostInstance: getInstanceFromTag,
bundleType: 0,
version: "18.3.0-next-09c8d2563-20230331",
version: "18.3.0-next-888874673-20230331",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForViewTag: function () {
@@ -9841,7 +9843,7 @@ var internals$jscomp$inline_1357 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-next-09c8d2563-20230331"
reconcilerVersion: "18.3.0-next-888874673-20230331"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1358 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
@@ -8233,8 +8233,8 @@ function scheduleTaskForRootDuringMicrotask(root, currentTime) {
pingedLanes = root.callbackNode;
if (
0 === suspendedLanes ||
(2 === workInProgressSuspendedReason && root === currentTime) ||
(null !== root.cancelPendingCommit && 0 === (suspendedLanes & 42))
(root === currentTime && 2 === workInProgressSuspendedReason) ||
null !== root.cancelPendingCommit
)
return (
null !== pingedLanes &&
@@ -8332,10 +8332,12 @@ function requestUpdateLane(fiber) {
return 0 !== fiber ? fiber : 32;
}
function scheduleUpdateOnFiber(root, fiber, lane, eventTime) {
2 === workInProgressSuspendedReason &&
root === workInProgressRoot &&
(prepareFreshStack(root, 0),
markRootSuspended(root, workInProgressRootRenderLanes));
if (
(root === workInProgressRoot && 2 === workInProgressSuspendedReason) ||
null !== root.cancelPendingCommit
)
prepareFreshStack(root, 0),
markRootSuspended(root, workInProgressRootRenderLanes);
markRootUpdated(root, lane, eventTime);
if (0 === (executionContext & 2) || root !== workInProgressRoot)
isDevToolsPresent && addFiberToLanesMap(root, fiber, lane),
@@ -10507,7 +10509,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1183 = {
findFiberByHostInstance: getInstanceFromTag,
bundleType: 0,
version: "18.3.0-next-09c8d2563-20230331",
version: "18.3.0-next-888874673-20230331",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForViewTag: function () {
@@ -10562,7 +10564,7 @@ var roots = new Map(),
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-next-09c8d2563-20230331"
reconcilerVersion: "18.3.0-next-888874673-20230331"
});
exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {
computeComponentStackForErrorReporting: function (reactTag) {