Skip to content

Commit

Permalink
Fix: Selective hydration causing incorrect thenable type passed to De…
Browse files Browse the repository at this point in the history
…vTools (#26275)

Selective hydration is implemented by suspending the current render
using a special internal opaque object. This is conceptually similar to
suspending with a thenable in userspace, but the opaque object should
not leak outside of the reconciler.

We were accidentally passing this object to DevTool's
markComponentSuspended function, which expects an actual thenable. This
happens in the error handling path (handleThrow).

The fix is to check for the exception reason before calling
markComponentSuspended. There was already a naive check in place, but it
didn't account for all possible enum values of the exception reason.
  • Loading branch information
acdlite committed Mar 1, 2023
1 parent 67a61d5 commit 4111002
Showing 1 changed file with 28 additions and 13 deletions.
41 changes: 28 additions & 13 deletions packages/react-reconciler/src/ReactFiberWorkLoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -1846,19 +1846,34 @@ function handleThrow(root: FiberRoot, thrownValue: any): void {

if (enableSchedulingProfiler) {
markComponentRenderStopped();
if (workInProgressSuspendedReason !== SuspendedOnError) {
const wakeable: Wakeable = (thrownValue: any);
markComponentSuspended(
erroredWork,
wakeable,
workInProgressRootRenderLanes,
);
} else {
markComponentErrored(
erroredWork,
thrownValue,
workInProgressRootRenderLanes,
);
switch (workInProgressSuspendedReason) {
case SuspendedOnError: {
markComponentErrored(
erroredWork,
thrownValue,
workInProgressRootRenderLanes,
);
break;
}
case SuspendedOnData:
case SuspendedOnImmediate:
case SuspendedOnDeprecatedThrowPromise:
case SuspendedAndReadyToUnwind: {
const wakeable: Wakeable = (thrownValue: any);
markComponentSuspended(
erroredWork,
wakeable,
workInProgressRootRenderLanes,
);
break;
}
case SuspendedOnHydration: {
// This is conceptually like a suspend, but it's not associated with
// a particular wakeable. DevTools doesn't seem to care about this case,
// currently. It's similar to if the component were interrupted, which
// we don't mark with a special function.
break;
}
}
}
}
Expand Down

0 comments on commit 4111002

Please sign in to comment.