Skip to content

Commit

Permalink
Track separate SuspendedOnAction flag by rethrowing a separate Suspen…
Browse files Browse the repository at this point in the history
…seActionException sentinel (#31554)

This lets us track separately if something was suspended on an Action
using useActionState rather than suspended on Data.

This approach feels quite bloated and it seems like we'd eventually
might want to read more information about the Promise that suspended and
the context it suspended in. As a more general reason for suspending.

The way useActionState works in combination with the prewarming is quite
unfortunate because 1) it renders blocking to update the isPending flag
whether you use it or not 2) it prewarms and suspends the useActionState
3) then it does another third render to get back into the useActionState
position again.

DiffTrain build for [92c0f5f](92c0f5f)
  • Loading branch information
sebmarkbage committed Nov 15, 2024
1 parent 19e9146 commit 3730bd5
Show file tree
Hide file tree
Showing 22 changed files with 806 additions and 421 deletions.
2 changes: 1 addition & 1 deletion compiled-rn/VERSION_NATIVE_FB
Original file line number Diff line number Diff line change
@@ -1 +1 @@
19.0.0-native-fb-053b3cb0-20241115
19.0.0-native-fb-92c0f5f8-20241115
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<3e3e3ab04b05778d88f6aafd134993f1>>
* @generated SignedSource<<df1411609bc9c5e85b8a7b20de8a1f9f>>
*/

"use strict";
Expand Down Expand Up @@ -420,5 +420,5 @@ __DEV__ &&
exports.useFormStatus = function () {
return resolveDispatcher().useHostTransitionStatus();
};
exports.version = "19.0.0-native-fb-053b3cb0-20241115";
exports.version = "19.0.0-native-fb-92c0f5f8-20241115";
})();
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<2a06ae239fe7eae90241857be36d10c0>>
* @generated SignedSource<<c3f45a69015bd1d46d18acabea50d00a>>
*/

"use strict";
Expand Down Expand Up @@ -203,4 +203,4 @@ exports.useFormState = function (action, initialState, permalink) {
exports.useFormStatus = function () {
return ReactSharedInternals.H.useHostTransitionStatus();
};
exports.version = "19.0.0-native-fb-053b3cb0-20241115";
exports.version = "19.0.0-native-fb-92c0f5f8-20241115";
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<2a06ae239fe7eae90241857be36d10c0>>
* @generated SignedSource<<c3f45a69015bd1d46d18acabea50d00a>>
*/

"use strict";
Expand Down Expand Up @@ -203,4 +203,4 @@ exports.useFormState = function (action, initialState, permalink) {
exports.useFormStatus = function () {
return ReactSharedInternals.H.useHostTransitionStatus();
};
exports.version = "19.0.0-native-fb-053b3cb0-20241115";
exports.version = "19.0.0-native-fb-92c0f5f8-20241115";
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<8250ec2729361a93d60905157490a2ca>>
* @generated SignedSource<<788eb663ae34b8bde2b978355aed6494>>
*/

/*
Expand Down Expand Up @@ -4534,7 +4534,10 @@ __DEV__ &&
return thenable;
}
function checkIfUseWrappedInAsyncCatch(rejectedReason) {
if (rejectedReason === SuspenseException)
if (
rejectedReason === SuspenseException ||
rejectedReason === SuspenseActionException
)
throw Error(
"Hooks are not supported inside an async component. This error is often caused by accidentally adding `'use client'` to a module that was originally written for the server."
);
Expand Down Expand Up @@ -5566,6 +5569,7 @@ __DEV__ &&
} catch (x) {
if (
x === SuspenseException ||
x === SuspenseActionException ||
((returnFiber.mode & ConcurrentMode) === NoMode &&
"object" === typeof x &&
null !== x &&
Expand Down Expand Up @@ -6800,24 +6804,30 @@ __DEV__ &&
actionStateReducer
)[0];
stateHook = updateReducer(basicStateReducer)[0];
currentStateHook =
if (
"object" === typeof currentStateHook &&
null !== currentStateHook &&
"function" === typeof currentStateHook.then
? useThenable(currentStateHook)
: currentStateHook;
var actionQueueHook = updateWorkInProgressHook(),
actionQueue = actionQueueHook.queue,
)
try {
var state = useThenable(currentStateHook);
} catch (x) {
if (x === SuspenseException) throw SuspenseActionException;
throw x;
}
else state = currentStateHook;
currentStateHook = updateWorkInProgressHook();
var actionQueue = currentStateHook.queue,
dispatch = actionQueue.dispatch;
action !== actionQueueHook.memoizedState &&
action !== currentStateHook.memoizedState &&
((currentlyRenderingFiber$1.flags |= 2048),
pushEffect(
HasEffect | Passive,
actionStateActionEffect.bind(null, actionQueue, action),
{ destroy: void 0 },
null
));
return [currentStateHook, dispatch, stateHook];
return [state, dispatch, stateHook];
}
function actionStateActionEffect(actionQueue, action) {
actionQueue.action = action;
Expand Down Expand Up @@ -14950,7 +14960,8 @@ __DEV__ &&
isFlushingPassiveEffects && (didScheduleUpdateDuringPassiveEffects = !0);
if (
(root === workInProgressRoot &&
workInProgressSuspendedReason === SuspendedOnData) ||
(workInProgressSuspendedReason === SuspendedOnData ||
workInProgressSuspendedReason === SuspendedOnAction)) ||
null !== root.cancelPendingCommit
)
prepareFreshStack(root, 0),
Expand Down Expand Up @@ -15401,14 +15412,17 @@ __DEV__ &&
ReactSharedInternals.getCurrentStack = null;
isRendering = !1;
current = null;
thrownValue === SuspenseException
thrownValue === SuspenseException ||
thrownValue === SuspenseActionException
? ((thrownValue = getSuspendedThenable()),
(workInProgressSuspendedReason =
!enableSiblingPrerendering &&
shouldRemainOnPreviousScreen() &&
0 === (workInProgressRootSkippedLanes & 134217727) &&
0 === (workInProgressRootInterleavedUpdatedLanes & 134217727)
? SuspendedOnData
? thrownValue === SuspenseActionException
? SuspendedOnAction
: SuspendedOnData
: SuspendedOnImmediate))
: thrownValue === SuspenseyCommitException
? ((thrownValue = getSuspendedThenable()),
Expand Down Expand Up @@ -15447,6 +15461,7 @@ __DEV__ &&
);
break;
case SuspendedOnData:
case SuspendedOnAction:
case SuspendedOnImmediate:
case SuspendedOnDeprecatedThrowPromise:
case SuspendedAndReadyToContinue:
Expand Down Expand Up @@ -15539,6 +15554,7 @@ __DEV__ &&
break a;
case SuspendedOnImmediate:
case SuspendedOnData:
case SuspendedOnAction:
case SuspendedOnDeprecatedThrowPromise:
null === suspenseHandlerStackCursor.current && (lanes = !0);
var reason = workInProgressSuspendedReason;
Expand Down Expand Up @@ -15630,15 +15646,17 @@ __DEV__ &&
);
break;
case SuspendedOnData:
case SuspendedOnAction:
if (isThenableResolved(memoizedUpdaters)) {
workInProgressSuspendedReason = NotSuspended;
workInProgressThrownValue = null;
replaySuspendedUnitOfWork(lanes);
break;
}
lanes = function () {
workInProgressSuspendedReason === SuspendedOnData &&
workInProgressRoot === root &&
(workInProgressSuspendedReason !== SuspendedOnData &&
workInProgressSuspendedReason !== SuspendedOnAction) ||
workInProgressRoot !== root ||
(workInProgressSuspendedReason =
SuspendedAndReadyToContinue);
ensureRootIsScheduled(root);
Expand Down Expand Up @@ -15876,6 +15894,7 @@ __DEV__ &&
if (
((workInProgressRootDidSkipSuspendedSiblings = root = !0),
suspendedReason === SuspendedOnData ||
suspendedReason === SuspendedOnAction ||
suspendedReason === SuspendedOnImmediate ||
suspendedReason === SuspendedOnDeprecatedThrowPromise)
)
Expand Down Expand Up @@ -16646,7 +16665,8 @@ __DEV__ &&
if (
0 === suspendedLanes ||
(root === currentTime &&
workInProgressSuspendedReason === SuspendedOnData) ||
(workInProgressSuspendedReason === SuspendedOnData ||
workInProgressSuspendedReason === SuspendedOnAction)) ||
null !== root.cancelPendingCommit
)
return (
Expand Down Expand Up @@ -23238,11 +23258,14 @@ __DEV__ &&
"Hydration Mismatch Exception: This is not a real error, and should not leak into userspace. If you're seeing this, it's likely a bug in React."
),
SuspenseException = Error(
"Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`"
"Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`."
),
SuspenseyCommitException = Error(
"Suspense Exception: This is not a real error, and should not leak into userspace. If you're seeing this, it's likely a bug in React."
),
SuspenseActionException = Error(
"Suspense Exception: This is not a real error! It's an implementation detail of `useActionState` to interrupt the current render. You must either rethrow it immediately, or move the `useActionState` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary."
),
noopSuspenseyCommitThenable = {
then: function () {
error$jscomp$0(
Expand Down Expand Up @@ -24774,6 +24797,7 @@ __DEV__ &&
SuspendedOnDeprecatedThrowPromise = 6,
SuspendedAndReadyToContinue = 7,
SuspendedOnHydration = 8,
SuspendedOnAction = 9,
workInProgressSuspendedReason = NotSuspended,
workInProgressThrownValue = null,
workInProgressRootDidSkipSuspendedSiblings = !1,
Expand Down Expand Up @@ -25352,11 +25376,11 @@ __DEV__ &&
};
(function () {
var isomorphicReactPackageVersion = React.version;
if ("19.0.0-native-fb-053b3cb0-20241115" !== isomorphicReactPackageVersion)
if ("19.0.0-native-fb-92c0f5f8-20241115" !== isomorphicReactPackageVersion)
throw Error(
'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' +
(isomorphicReactPackageVersion +
"\n - react-dom: 19.0.0-native-fb-053b3cb0-20241115\nLearn more: https://react.dev/warnings/version-mismatch")
"\n - react-dom: 19.0.0-native-fb-92c0f5f8-20241115\nLearn more: https://react.dev/warnings/version-mismatch")
);
})();
("function" === typeof Map &&
Expand Down Expand Up @@ -25393,11 +25417,11 @@ __DEV__ &&
!(function () {
var internals = {
bundleType: 1,
version: "19.0.0-native-fb-053b3cb0-20241115",
version: "19.0.0-native-fb-92c0f5f8-20241115",
rendererPackageName: "react-dom",
currentDispatcherRef: ReactSharedInternals,
findFiberByHostInstance: getClosestInstanceFromNode,
reconcilerVersion: "19.0.0-native-fb-053b3cb0-20241115"
reconcilerVersion: "19.0.0-native-fb-92c0f5f8-20241115"
};
internals.overrideHookState = overrideHookState;
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
Expand Down Expand Up @@ -25541,5 +25565,5 @@ __DEV__ &&
listenToAllSupportedEvents(container);
return new ReactDOMHydrationRoot(initialChildren);
};
exports.version = "19.0.0-native-fb-053b3cb0-20241115";
exports.version = "19.0.0-native-fb-92c0f5f8-20241115";
})();
Loading

0 comments on commit 3730bd5

Please sign in to comment.