Fix: Stylesheet in error UI suspends indefinitely (#27265)

This fixes the regression test added in the previous commit. The
"Suspensey commit" implementation relies on the
`shouldRemainOnPreviousScreen` function to determine whether to 1)
suspend the commit 2) activate a parent fallback and schedule a retry.
The issue was that we were sometimes attempting option 2 even when there
was no parent fallback.

Part of the reason this bug landed is due to how `throwException` is
structured. In the case of Suspensey commits, we pass a special "noop"
thenable to `throwException` as a way to trigger the Suspense path. This
special thenable must never have a listener attached to it. This is not
a great way to structure the logic, it's just a consequence of how the
code evolved over time. We should refactor it into multiple functions so
we can trigger a fallback directly without having to check the type. In
the meantime, I added an internal warning to help detect similar
mistakes in the future.

DiffTrain build for commit https://github.com/facebook/react/commit/dd480ef923930c8906a02664b01bcdea50707b5d.
This commit is contained in:
acdlite
2023-08-22 15:27:20 +00:00
parent 5043aee3c6
commit 98164cb40c
13 changed files with 331 additions and 316 deletions
@@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<a90e685585292cdb00d4e8ba1b363382>>
* @generated SignedSource<<f4e294d7d90195ed2bc85d15207c702c>>
*/
'use strict';
@@ -4071,7 +4071,14 @@ var SuspenseyCommitException = new Error(
// for now this will do.
var noopSuspenseyCommitThenable = {
then: function () {}
then: function () {
{
error(
"Internal React error: A listener was unexpectedly attached to a " +
'"noop" thenable. This is a bug in React. Please file an issue.'
);
}
}
};
function createThenableState() {
// The ThenableState is created the first time a component suspends. If it
@@ -11072,10 +11079,16 @@ function throwException(
suspenseBoundary.updateQueue = new Set([wakeable]);
} else {
retryQueue.add(wakeable);
} // We only attach ping listeners in concurrent mode. Legacy
// Suspense always commits fallbacks synchronously, so there are
// no pings.
if (suspenseBoundary.mode & ConcurrentMode) {
attachPingListener(root, wakeable, rootRenderLanes);
}
}
break;
return;
}
case OffscreenComponent: {
@@ -11106,28 +11119,21 @@ function throwException(
_retryQueue.add(wakeable);
}
}
attachPingListener(root, wakeable, rootRenderLanes);
}
break;
} // Fall through
return;
}
}
default: {
throw new Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This " +
"is a bug in React."
);
}
} // We only attach ping listeners in concurrent mode. Legacy Suspense always
// commits fallbacks synchronously, so there are no pings.
if (suspenseBoundary.mode & ConcurrentMode) {
attachPingListener(root, wakeable, rootRenderLanes);
}
return;
throw new Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This " +
"is a bug in React."
);
} else {
// No boundary was found. Unless this is a sync update, this is OK.
// We can suspend and wait for more data to arrive.
@@ -20983,9 +20989,19 @@ function shouldRemainOnPreviousScreen() {
// on the previous screen, versus showing a fallback as soon as possible. It
// takes into account both the priority of render and also whether showing a
// fallback would produce a desirable user experience.
// TODO: Once `use` has fully replaced the `throw promise` pattern, we should
var handler = getSuspenseHandler();
if (handler === null) {
// There's no Suspense boundary that can provide a fallback. We have no
// choice but to remain on the previous screen.
// NOTE: We do this even for sync updates, for lack of any better option. In
// the future, we may change how we handle this, like by putting the whole
// root into a "detached" mode.
return true;
} // TODO: Once `use` has fully replaced the `throw promise` pattern, we should
// be able to remove the equivalent check in finishConcurrentRender, and rely
// just on this one.
if (includesOnlyTransitions(workInProgressRootRenderLanes)) {
if (getShellBoundary() === null) {
// We're rendering inside the "shell" of the app. Activating the nearest
@@ -21001,26 +21017,21 @@ function shouldRemainOnPreviousScreen() {
}
}
var handler = getSuspenseHandler();
if (handler === null);
else {
if (
includesOnlyRetries(workInProgressRootRenderLanes) || // In this context, an OffscreenLane counts as a Retry
// TODO: It's become increasingly clear that Retries and Offscreen are
// deeply connected. They probably can be unified further.
includesSomeLane(workInProgressRootRenderLanes, OffscreenLane)
) {
// During a retry, we can suspend rendering if the nearest Suspense boundary
// is the boundary of the "shell", because we're guaranteed not to block
// any new content from appearing.
//
// The reason we must check if this is a retry is because it guarantees
// that suspending the work loop won't block an actual update, because
// retries don't "update" anything; they fill in fallbacks that were left
// behind by a previous transition.
return handler === getShellBoundary();
}
if (
includesOnlyRetries(workInProgressRootRenderLanes) || // In this context, an OffscreenLane counts as a Retry
// TODO: It's become increasingly clear that Retries and Offscreen are
// deeply connected. They probably can be unified further.
includesSomeLane(workInProgressRootRenderLanes, OffscreenLane)
) {
// During a retry, we can suspend rendering if the nearest Suspense boundary
// is the boundary of the "shell", because we're guaranteed not to block
// any new content from appearing.
//
// The reason we must check if this is a retry is because it guarantees
// that suspending the work loop won't block an actual update, because
// retries don't "update" anything; they fill in fallbacks that were left
// behind by a previous transition.
return handler === getShellBoundary();
} // For all other Lanes besides Transitions and Retries, we should not wait
// for the data to load.
@@ -23966,7 +23977,7 @@ function createFiberRoot(
return root;
}
var ReactVersion = "18.3.0-canary-e76a5aca7-20230822";
var ReactVersion = "18.3.0-canary-dd480ef92-20230822";
// Might add PROFILE later.
@@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<855c2a9f51c40c6c16565d44997b08cb>>
* @generated SignedSource<<433e051293b336d0e7452d6c87975a14>>
*/
"use strict";
@@ -6731,23 +6731,20 @@ function handleThrow(root, thrownValue) {
ReactCurrentOwner.current = null;
thrownValue === SuspenseException
? ((thrownValue = getSuspendedThenable()),
(workInProgressRootRenderLanes & 8388480) ===
workInProgressRootRenderLanes
? (root = null === shellBoundary ? !0 : !1)
: ((root = suspenseHandlerStackCursor.current),
(root =
null === root ||
((workInProgressRootRenderLanes & 125829120) !==
workInProgressRootRenderLanes &&
0 === (workInProgressRootRenderLanes & 1073741824))
? !1
: root === shellBoundary)),
(root = suspenseHandlerStackCursor.current),
(workInProgressSuspendedReason =
root &&
0 === (workInProgressRootSkippedLanes & 268435455) &&
0 === (workInProgressRootInterleavedUpdatedLanes & 268435455)
? 2
: 3))
(null !== root &&
((workInProgressRootRenderLanes & 8388480) ===
workInProgressRootRenderLanes
? null !== shellBoundary
: ((workInProgressRootRenderLanes & 125829120) !==
workInProgressRootRenderLanes &&
0 === (workInProgressRootRenderLanes & 1073741824)) ||
root !== shellBoundary)) ||
0 !== (workInProgressRootSkippedLanes & 268435455) ||
0 !== (workInProgressRootInterleavedUpdatedLanes & 268435455)
? 3
: 2))
: thrownValue === SuspenseyCommitException
? ((thrownValue = getSuspendedThenable()),
(workInProgressSuspendedReason = 4))
@@ -7074,8 +7071,10 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) {
null === retryQueue
? (suspenseBoundary.updateQueue = new Set([wakeable]))
: retryQueue.add(wakeable);
suspenseBoundary.mode & 1 &&
attachPingListener(root, wakeable, thrownValue);
}
break;
break a;
case 22:
if (suspenseBoundary.mode & 1) {
suspenseBoundary.flags |= 65536;
@@ -7096,20 +7095,18 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) {
? (offscreenQueue.retryQueue = new Set([wakeable]))
: retryQueue$29.add(wakeable);
}
attachPingListener(root, wakeable, thrownValue);
}
break;
break a;
}
default:
throw Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This is a bug in React."
);
}
suspenseBoundary.mode & 1 &&
attachPingListener(root, wakeable, thrownValue);
break a;
} else if (1 === root.tag) {
throw Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This is a bug in React."
);
}
if (1 === root.tag) {
attachPingListener(root, wakeable, thrownValue);
renderDidSuspendDelayIfPossible();
break a;
@@ -8615,7 +8612,7 @@ var devToolsConfig$jscomp$inline_1029 = {
throw Error("TestRenderer does not support findFiberByHostInstance()");
},
bundleType: 0,
version: "18.3.0-canary-e76a5aca7-20230822",
version: "18.3.0-canary-dd480ef92-20230822",
rendererPackageName: "react-test-renderer"
};
var internals$jscomp$inline_1228 = {
@@ -8646,7 +8643,7 @@ var internals$jscomp$inline_1228 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-canary-e76a5aca7-20230822"
reconcilerVersion: "18.3.0-canary-dd480ef92-20230822"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1229 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
@@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<ecceacf440b4791ce7dad51926bafd21>>
* @generated SignedSource<<e6092a9eaf897724b4998006d8d964b1>>
*/
"use strict";
@@ -7071,23 +7071,20 @@ function handleThrow(root, thrownValue) {
ReactCurrentOwner.current = null;
thrownValue === SuspenseException
? ((thrownValue = getSuspendedThenable()),
(workInProgressRootRenderLanes & 8388480) ===
workInProgressRootRenderLanes
? (root = null === shellBoundary ? !0 : !1)
: ((root = suspenseHandlerStackCursor.current),
(root =
null === root ||
((workInProgressRootRenderLanes & 125829120) !==
workInProgressRootRenderLanes &&
0 === (workInProgressRootRenderLanes & 1073741824))
? !1
: root === shellBoundary)),
(root = suspenseHandlerStackCursor.current),
(workInProgressSuspendedReason =
root &&
0 === (workInProgressRootSkippedLanes & 268435455) &&
0 === (workInProgressRootInterleavedUpdatedLanes & 268435455)
? 2
: 3))
(null !== root &&
((workInProgressRootRenderLanes & 8388480) ===
workInProgressRootRenderLanes
? null !== shellBoundary
: ((workInProgressRootRenderLanes & 125829120) !==
workInProgressRootRenderLanes &&
0 === (workInProgressRootRenderLanes & 1073741824)) ||
root !== shellBoundary)) ||
0 !== (workInProgressRootSkippedLanes & 268435455) ||
0 !== (workInProgressRootInterleavedUpdatedLanes & 268435455)
? 3
: 2))
: thrownValue === SuspenseyCommitException
? ((thrownValue = getSuspendedThenable()),
(workInProgressSuspendedReason = 4))
@@ -7426,8 +7423,10 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) {
null === retryQueue
? (suspenseBoundary.updateQueue = new Set([wakeable]))
: retryQueue.add(wakeable);
suspenseBoundary.mode & 1 &&
attachPingListener(root, wakeable, thrownValue);
}
break;
break a;
case 22:
if (suspenseBoundary.mode & 1) {
suspenseBoundary.flags |= 65536;
@@ -7448,20 +7447,18 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) {
? (offscreenQueue.retryQueue = new Set([wakeable]))
: retryQueue$29.add(wakeable);
}
attachPingListener(root, wakeable, thrownValue);
}
break;
break a;
}
default:
throw Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This is a bug in React."
);
}
suspenseBoundary.mode & 1 &&
attachPingListener(root, wakeable, thrownValue);
break a;
} else if (1 === root.tag) {
throw Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This is a bug in React."
);
}
if (1 === root.tag) {
attachPingListener(root, wakeable, thrownValue);
renderDidSuspendDelayIfPossible();
break a;
@@ -9041,7 +9038,7 @@ var devToolsConfig$jscomp$inline_1071 = {
throw Error("TestRenderer does not support findFiberByHostInstance()");
},
bundleType: 0,
version: "18.3.0-canary-e76a5aca7-20230822",
version: "18.3.0-canary-dd480ef92-20230822",
rendererPackageName: "react-test-renderer"
};
var internals$jscomp$inline_1269 = {
@@ -9072,7 +9069,7 @@ var internals$jscomp$inline_1269 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-canary-e76a5aca7-20230822"
reconcilerVersion: "18.3.0-canary-dd480ef92-20230822"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1270 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
@@ -27,7 +27,7 @@ if (
}
"use strict";
var ReactVersion = "18.3.0-canary-e76a5aca7-20230822";
var ReactVersion = "18.3.0-canary-dd480ef92-20230822";
// ATTENTION
// When adding new symbols to this file,
@@ -616,4 +616,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactCurrentDispatcher.current.useTransition();
};
exports.version = "18.3.0-canary-e76a5aca7-20230822";
exports.version = "18.3.0-canary-dd480ef92-20230822";
@@ -619,7 +619,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactCurrentDispatcher.current.useTransition();
};
exports.version = "18.3.0-canary-e76a5aca7-20230822";
exports.version = "18.3.0-canary-dd480ef92-20230822";
/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
if (
@@ -1 +1 @@
e76a5aca781abdc237f044131790ea615b500532
dd480ef923930c8906a02664b01bcdea50707b5d
@@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<275858edcfc5ae0f3e1651eeaaeca34f>>
* @generated SignedSource<<75239e23e920b7033825cf9cc46cee37>>
*/
'use strict';
@@ -7790,7 +7790,14 @@ var SuspenseyCommitException = new Error(
// for now this will do.
var noopSuspenseyCommitThenable = {
then: function () {}
then: function () {
{
error(
"Internal React error: A listener was unexpectedly attached to a " +
'"noop" thenable. This is a bug in React. Please file an issue.'
);
}
}
};
function createThenableState() {
// The ThenableState is created the first time a component suspends. If it
@@ -14959,10 +14966,16 @@ function throwException(
suspenseBoundary.updateQueue = new Set([wakeable]);
} else {
retryQueue.add(wakeable);
} // We only attach ping listeners in concurrent mode. Legacy
// Suspense always commits fallbacks synchronously, so there are
// no pings.
if (suspenseBoundary.mode & ConcurrentMode) {
attachPingListener(root, wakeable, rootRenderLanes);
}
}
break;
return;
}
case OffscreenComponent: {
@@ -14993,28 +15006,21 @@ function throwException(
_retryQueue.add(wakeable);
}
}
attachPingListener(root, wakeable, rootRenderLanes);
}
break;
} // Fall through
return;
}
}
default: {
throw new Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This " +
"is a bug in React."
);
}
} // We only attach ping listeners in concurrent mode. Legacy Suspense always
// commits fallbacks synchronously, so there are no pings.
if (suspenseBoundary.mode & ConcurrentMode) {
attachPingListener(root, wakeable, rootRenderLanes);
}
return;
throw new Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This " +
"is a bug in React."
);
} else {
// No boundary was found. Unless this is a sync update, this is OK.
// We can suspend and wait for more data to arrive.
@@ -23848,9 +23854,19 @@ function shouldRemainOnPreviousScreen() {
// on the previous screen, versus showing a fallback as soon as possible. It
// takes into account both the priority of render and also whether showing a
// fallback would produce a desirable user experience.
// TODO: Once `use` has fully replaced the `throw promise` pattern, we should
var handler = getSuspenseHandler();
if (handler === null) {
// There's no Suspense boundary that can provide a fallback. We have no
// choice but to remain on the previous screen.
// NOTE: We do this even for sync updates, for lack of any better option. In
// the future, we may change how we handle this, like by putting the whole
// root into a "detached" mode.
return true;
} // TODO: Once `use` has fully replaced the `throw promise` pattern, we should
// be able to remove the equivalent check in finishConcurrentRender, and rely
// just on this one.
if (includesOnlyTransitions(workInProgressRootRenderLanes)) {
if (getShellBoundary() === null) {
// We're rendering inside the "shell" of the app. Activating the nearest
@@ -23866,26 +23882,21 @@ function shouldRemainOnPreviousScreen() {
}
}
var handler = getSuspenseHandler();
if (handler === null);
else {
if (
includesOnlyRetries(workInProgressRootRenderLanes) || // In this context, an OffscreenLane counts as a Retry
// TODO: It's become increasingly clear that Retries and Offscreen are
// deeply connected. They probably can be unified further.
includesSomeLane(workInProgressRootRenderLanes, OffscreenLane)
) {
// During a retry, we can suspend rendering if the nearest Suspense boundary
// is the boundary of the "shell", because we're guaranteed not to block
// any new content from appearing.
//
// The reason we must check if this is a retry is because it guarantees
// that suspending the work loop won't block an actual update, because
// retries don't "update" anything; they fill in fallbacks that were left
// behind by a previous transition.
return handler === getShellBoundary();
}
if (
includesOnlyRetries(workInProgressRootRenderLanes) || // In this context, an OffscreenLane counts as a Retry
// TODO: It's become increasingly clear that Retries and Offscreen are
// deeply connected. They probably can be unified further.
includesSomeLane(workInProgressRootRenderLanes, OffscreenLane)
) {
// During a retry, we can suspend rendering if the nearest Suspense boundary
// is the boundary of the "shell", because we're guaranteed not to block
// any new content from appearing.
//
// The reason we must check if this is a retry is because it guarantees
// that suspending the work loop won't block an actual update, because
// retries don't "update" anything; they fill in fallbacks that were left
// behind by a previous transition.
return handler === getShellBoundary();
} // For all other Lanes besides Transitions and Retries, we should not wait
// for the data to load.
@@ -27005,7 +27016,7 @@ function createFiberRoot(
return root;
}
var ReactVersion = "18.3.0-canary-191221fc";
var ReactVersion = "18.3.0-canary-64e46017";
function createPortal$1(
children,
@@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<3106445be52c70579494ac9a4777c8df>>
* @generated SignedSource<<a07e5e05f488236a06128ef01e09c2f5>>
*/
"use strict";
@@ -7732,23 +7732,20 @@ function handleThrow(root, thrownValue) {
ReactCurrentOwner.current = null;
thrownValue === SuspenseException
? ((thrownValue = getSuspendedThenable()),
(workInProgressRootRenderLanes & 8388480) ===
workInProgressRootRenderLanes
? (root = null === shellBoundary ? !0 : !1)
: ((root = suspenseHandlerStackCursor.current),
(root =
null === root ||
((workInProgressRootRenderLanes & 125829120) !==
workInProgressRootRenderLanes &&
0 === (workInProgressRootRenderLanes & 1073741824))
? !1
: root === shellBoundary)),
(root = suspenseHandlerStackCursor.current),
(workInProgressSuspendedReason =
root &&
0 === (workInProgressRootSkippedLanes & 268435455) &&
0 === (workInProgressRootInterleavedUpdatedLanes & 268435455)
? 2
: 3))
(null !== root &&
((workInProgressRootRenderLanes & 8388480) ===
workInProgressRootRenderLanes
? null !== shellBoundary
: ((workInProgressRootRenderLanes & 125829120) !==
workInProgressRootRenderLanes &&
0 === (workInProgressRootRenderLanes & 1073741824)) ||
root !== shellBoundary)) ||
0 !== (workInProgressRootSkippedLanes & 268435455) ||
0 !== (workInProgressRootInterleavedUpdatedLanes & 268435455)
? 3
: 2))
: thrownValue === SuspenseyCommitException
? ((thrownValue = getSuspendedThenable()),
(workInProgressSuspendedReason = 4))
@@ -8066,8 +8063,10 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) {
null === retryQueue
? (suspenseBoundary.updateQueue = new Set([wakeable]))
: retryQueue.add(wakeable);
suspenseBoundary.mode & 1 &&
attachPingListener(root, wakeable, thrownValue);
}
break;
break a;
case 22:
if (suspenseBoundary.mode & 1) {
suspenseBoundary.flags |= 65536;
@@ -8088,20 +8087,18 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) {
? (offscreenQueue.retryQueue = new Set([wakeable]))
: retryQueue$32.add(wakeable);
}
attachPingListener(root, wakeable, thrownValue);
}
break;
break a;
}
default:
throw Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This is a bug in React."
);
}
suspenseBoundary.mode & 1 &&
attachPingListener(root, wakeable, thrownValue);
break a;
} else if (1 === root.tag) {
throw Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This is a bug in React."
);
}
if (1 === root.tag) {
attachPingListener(root, wakeable, thrownValue);
renderDidSuspendDelayIfPossible();
break a;
@@ -9421,7 +9418,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1040 = {
findFiberByHostInstance: getInstanceFromNode,
bundleType: 0,
version: "18.3.0-canary-25ec80db",
version: "18.3.0-canary-9812ca1f",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForInstance: getInspectorDataForInstance,
@@ -9464,7 +9461,7 @@ var internals$jscomp$inline_1282 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-canary-25ec80db"
reconcilerVersion: "18.3.0-canary-9812ca1f"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1283 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
@@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<c1ea48b0dca5ef0a4eef09df56e52033>>
* @generated SignedSource<<d24f6fd9c468c7ff219382320fbd627a>>
*/
@@ -8263,23 +8263,20 @@ function handleThrow(root, thrownValue) {
ReactCurrentOwner.current = null;
thrownValue === SuspenseException
? ((thrownValue = getSuspendedThenable()),
(workInProgressRootRenderLanes & 8388480) ===
workInProgressRootRenderLanes
? (root = null === shellBoundary ? !0 : !1)
: ((root = suspenseHandlerStackCursor.current),
(root =
null === root ||
((workInProgressRootRenderLanes & 125829120) !==
workInProgressRootRenderLanes &&
0 === (workInProgressRootRenderLanes & 1073741824))
? !1
: root === shellBoundary)),
(root = suspenseHandlerStackCursor.current),
(workInProgressSuspendedReason =
root &&
0 === (workInProgressRootSkippedLanes & 268435455) &&
0 === (workInProgressRootInterleavedUpdatedLanes & 268435455)
? 2
: 3))
(null !== root &&
((workInProgressRootRenderLanes & 8388480) ===
workInProgressRootRenderLanes
? null !== shellBoundary
: ((workInProgressRootRenderLanes & 125829120) !==
workInProgressRootRenderLanes &&
0 === (workInProgressRootRenderLanes & 1073741824)) ||
root !== shellBoundary)) ||
0 !== (workInProgressRootSkippedLanes & 268435455) ||
0 !== (workInProgressRootInterleavedUpdatedLanes & 268435455)
? 3
: 2))
: thrownValue === SuspenseyCommitException
? ((thrownValue = getSuspendedThenable()),
(workInProgressSuspendedReason = 4))
@@ -8664,8 +8661,10 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) {
null === retryQueue
? (suspenseBoundary.updateQueue = new Set([wakeable]))
: retryQueue.add(wakeable);
suspenseBoundary.mode & 1 &&
attachPingListener(root, wakeable, thrownValue);
}
break;
break a;
case 22:
if (suspenseBoundary.mode & 1) {
suspenseBoundary.flags |= 65536;
@@ -8686,20 +8685,18 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) {
? (offscreenQueue.retryQueue = new Set([wakeable]))
: retryQueue$35.add(wakeable);
}
attachPingListener(root, wakeable, thrownValue);
}
break;
break a;
}
default:
throw Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This is a bug in React."
);
}
suspenseBoundary.mode & 1 &&
attachPingListener(root, wakeable, thrownValue);
break a;
} else if (1 === root.tag) {
throw Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This is a bug in React."
);
}
if (1 === root.tag) {
attachPingListener(root, wakeable, thrownValue);
renderDidSuspendDelayIfPossible();
break a;
@@ -10129,7 +10126,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1118 = {
findFiberByHostInstance: getInstanceFromNode,
bundleType: 0,
version: "18.3.0-canary-d46b694e",
version: "18.3.0-canary-67d29d89",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForInstance: getInspectorDataForInstance,
@@ -10185,7 +10182,7 @@ var roots = new Map(),
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-canary-d46b694e"
reconcilerVersion: "18.3.0-canary-67d29d89"
});
exports.createPortal = function (children, containerTag) {
return createPortal$1(
@@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<096b1c8462af119e22314cca6718f66f>>
* @generated SignedSource<<c5864c0cab35ace8ea22b15a3fd75fde>>
*/
'use strict';
@@ -8107,7 +8107,14 @@ var SuspenseyCommitException = new Error(
// for now this will do.
var noopSuspenseyCommitThenable = {
then: function () {}
then: function () {
{
error(
"Internal React error: A listener was unexpectedly attached to a " +
'"noop" thenable. This is a bug in React. Please file an issue.'
);
}
}
};
function createThenableState() {
// The ThenableState is created the first time a component suspends. If it
@@ -15276,10 +15283,16 @@ function throwException(
suspenseBoundary.updateQueue = new Set([wakeable]);
} else {
retryQueue.add(wakeable);
} // We only attach ping listeners in concurrent mode. Legacy
// Suspense always commits fallbacks synchronously, so there are
// no pings.
if (suspenseBoundary.mode & ConcurrentMode) {
attachPingListener(root, wakeable, rootRenderLanes);
}
}
break;
return;
}
case OffscreenComponent: {
@@ -15310,28 +15323,21 @@ function throwException(
_retryQueue.add(wakeable);
}
}
attachPingListener(root, wakeable, rootRenderLanes);
}
break;
} // Fall through
return;
}
}
default: {
throw new Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This " +
"is a bug in React."
);
}
} // We only attach ping listeners in concurrent mode. Legacy Suspense always
// commits fallbacks synchronously, so there are no pings.
if (suspenseBoundary.mode & ConcurrentMode) {
attachPingListener(root, wakeable, rootRenderLanes);
}
return;
throw new Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This " +
"is a bug in React."
);
} else {
// No boundary was found. Unless this is a sync update, this is OK.
// We can suspend and wait for more data to arrive.
@@ -24362,9 +24368,19 @@ function shouldRemainOnPreviousScreen() {
// on the previous screen, versus showing a fallback as soon as possible. It
// takes into account both the priority of render and also whether showing a
// fallback would produce a desirable user experience.
// TODO: Once `use` has fully replaced the `throw promise` pattern, we should
var handler = getSuspenseHandler();
if (handler === null) {
// There's no Suspense boundary that can provide a fallback. We have no
// choice but to remain on the previous screen.
// NOTE: We do this even for sync updates, for lack of any better option. In
// the future, we may change how we handle this, like by putting the whole
// root into a "detached" mode.
return true;
} // TODO: Once `use` has fully replaced the `throw promise` pattern, we should
// be able to remove the equivalent check in finishConcurrentRender, and rely
// just on this one.
if (includesOnlyTransitions(workInProgressRootRenderLanes)) {
if (getShellBoundary() === null) {
// We're rendering inside the "shell" of the app. Activating the nearest
@@ -24380,26 +24396,21 @@ function shouldRemainOnPreviousScreen() {
}
}
var handler = getSuspenseHandler();
if (handler === null);
else {
if (
includesOnlyRetries(workInProgressRootRenderLanes) || // In this context, an OffscreenLane counts as a Retry
// TODO: It's become increasingly clear that Retries and Offscreen are
// deeply connected. They probably can be unified further.
includesSomeLane(workInProgressRootRenderLanes, OffscreenLane)
) {
// During a retry, we can suspend rendering if the nearest Suspense boundary
// is the boundary of the "shell", because we're guaranteed not to block
// any new content from appearing.
//
// The reason we must check if this is a retry is because it guarantees
// that suspending the work loop won't block an actual update, because
// retries don't "update" anything; they fill in fallbacks that were left
// behind by a previous transition.
return handler === getShellBoundary();
}
if (
includesOnlyRetries(workInProgressRootRenderLanes) || // In this context, an OffscreenLane counts as a Retry
// TODO: It's become increasingly clear that Retries and Offscreen are
// deeply connected. They probably can be unified further.
includesSomeLane(workInProgressRootRenderLanes, OffscreenLane)
) {
// During a retry, we can suspend rendering if the nearest Suspense boundary
// is the boundary of the "shell", because we're guaranteed not to block
// any new content from appearing.
//
// The reason we must check if this is a retry is because it guarantees
// that suspending the work loop won't block an actual update, because
// retries don't "update" anything; they fill in fallbacks that were left
// behind by a previous transition.
return handler === getShellBoundary();
} // For all other Lanes besides Transitions and Retries, we should not wait
// for the data to load.
@@ -27519,7 +27530,7 @@ function createFiberRoot(
return root;
}
var ReactVersion = "18.3.0-canary-439c5f24";
var ReactVersion = "18.3.0-canary-2a0c5fa6";
function createPortal$1(
children,
@@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<51235cc0d10c7c67758da65bf9e82cd7>>
* @generated SignedSource<<3912084f06749c92cbe914e3b90809c6>>
*/
"use strict";
@@ -7981,23 +7981,20 @@ function handleThrow(root, thrownValue) {
ReactCurrentOwner.current = null;
thrownValue === SuspenseException
? ((thrownValue = getSuspendedThenable()),
(workInProgressRootRenderLanes & 8388480) ===
workInProgressRootRenderLanes
? (root = null === shellBoundary ? !0 : !1)
: ((root = suspenseHandlerStackCursor.current),
(root =
null === root ||
((workInProgressRootRenderLanes & 125829120) !==
workInProgressRootRenderLanes &&
0 === (workInProgressRootRenderLanes & 1073741824))
? !1
: root === shellBoundary)),
(root = suspenseHandlerStackCursor.current),
(workInProgressSuspendedReason =
root &&
0 === (workInProgressRootSkippedLanes & 268435455) &&
0 === (workInProgressRootInterleavedUpdatedLanes & 268435455)
? 2
: 3))
(null !== root &&
((workInProgressRootRenderLanes & 8388480) ===
workInProgressRootRenderLanes
? null !== shellBoundary
: ((workInProgressRootRenderLanes & 125829120) !==
workInProgressRootRenderLanes &&
0 === (workInProgressRootRenderLanes & 1073741824)) ||
root !== shellBoundary)) ||
0 !== (workInProgressRootSkippedLanes & 268435455) ||
0 !== (workInProgressRootInterleavedUpdatedLanes & 268435455)
? 3
: 2))
: thrownValue === SuspenseyCommitException
? ((thrownValue = getSuspendedThenable()),
(workInProgressSuspendedReason = 4))
@@ -8315,8 +8312,10 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) {
null === retryQueue
? (suspenseBoundary.updateQueue = new Set([wakeable]))
: retryQueue.add(wakeable);
suspenseBoundary.mode & 1 &&
attachPingListener(root, wakeable, thrownValue);
}
break;
break a;
case 22:
if (suspenseBoundary.mode & 1) {
suspenseBoundary.flags |= 65536;
@@ -8337,20 +8336,18 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) {
? (offscreenQueue.retryQueue = new Set([wakeable]))
: retryQueue$34.add(wakeable);
}
attachPingListener(root, wakeable, thrownValue);
}
break;
break a;
}
default:
throw Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This is a bug in React."
);
}
suspenseBoundary.mode & 1 &&
attachPingListener(root, wakeable, thrownValue);
break a;
} else if (1 === root.tag) {
throw Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This is a bug in React."
);
}
if (1 === root.tag) {
attachPingListener(root, wakeable, thrownValue);
renderDidSuspendDelayIfPossible();
break a;
@@ -9677,7 +9674,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1095 = {
findFiberByHostInstance: getInstanceFromTag,
bundleType: 0,
version: "18.3.0-canary-37d552e6",
version: "18.3.0-canary-5a0cdf8c",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForInstance: getInspectorDataForInstance,
@@ -9720,7 +9717,7 @@ var internals$jscomp$inline_1351 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-canary-37d552e6"
reconcilerVersion: "18.3.0-canary-5a0cdf8c"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1352 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
@@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<db5216c118a6ffba38296edfa8b84596>>
* @generated SignedSource<<652f44316e146b8f03b47dda41701ba7>>
*/
@@ -8512,23 +8512,20 @@ function handleThrow(root, thrownValue) {
ReactCurrentOwner.current = null;
thrownValue === SuspenseException
? ((thrownValue = getSuspendedThenable()),
(workInProgressRootRenderLanes & 8388480) ===
workInProgressRootRenderLanes
? (root = null === shellBoundary ? !0 : !1)
: ((root = suspenseHandlerStackCursor.current),
(root =
null === root ||
((workInProgressRootRenderLanes & 125829120) !==
workInProgressRootRenderLanes &&
0 === (workInProgressRootRenderLanes & 1073741824))
? !1
: root === shellBoundary)),
(root = suspenseHandlerStackCursor.current),
(workInProgressSuspendedReason =
root &&
0 === (workInProgressRootSkippedLanes & 268435455) &&
0 === (workInProgressRootInterleavedUpdatedLanes & 268435455)
? 2
: 3))
(null !== root &&
((workInProgressRootRenderLanes & 8388480) ===
workInProgressRootRenderLanes
? null !== shellBoundary
: ((workInProgressRootRenderLanes & 125829120) !==
workInProgressRootRenderLanes &&
0 === (workInProgressRootRenderLanes & 1073741824)) ||
root !== shellBoundary)) ||
0 !== (workInProgressRootSkippedLanes & 268435455) ||
0 !== (workInProgressRootInterleavedUpdatedLanes & 268435455)
? 3
: 2))
: thrownValue === SuspenseyCommitException
? ((thrownValue = getSuspendedThenable()),
(workInProgressSuspendedReason = 4))
@@ -8913,8 +8910,10 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) {
null === retryQueue
? (suspenseBoundary.updateQueue = new Set([wakeable]))
: retryQueue.add(wakeable);
suspenseBoundary.mode & 1 &&
attachPingListener(root, wakeable, thrownValue);
}
break;
break a;
case 22:
if (suspenseBoundary.mode & 1) {
suspenseBoundary.flags |= 65536;
@@ -8935,20 +8934,18 @@ function throwAndUnwindWorkLoop(unitOfWork, thrownValue) {
? (offscreenQueue.retryQueue = new Set([wakeable]))
: retryQueue$37.add(wakeable);
}
attachPingListener(root, wakeable, thrownValue);
}
break;
break a;
}
default:
throw Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This is a bug in React."
);
}
suspenseBoundary.mode & 1 &&
attachPingListener(root, wakeable, thrownValue);
break a;
} else if (1 === root.tag) {
throw Error(
"Unexpected Suspense handler tag (" +
suspenseBoundary.tag +
"). This is a bug in React."
);
}
if (1 === root.tag) {
attachPingListener(root, wakeable, thrownValue);
renderDidSuspendDelayIfPossible();
break a;
@@ -10385,7 +10382,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1173 = {
findFiberByHostInstance: getInstanceFromTag,
bundleType: 0,
version: "18.3.0-canary-1af01c24",
version: "18.3.0-canary-c231d0c6",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForInstance: getInspectorDataForInstance,
@@ -10441,7 +10438,7 @@ var roots = new Map(),
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-canary-1af01c24"
reconcilerVersion: "18.3.0-canary-c231d0c6"
});
exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {
computeComponentStackForErrorReporting: function (reactTag) {