Skip to content

Commit d1d5fef

Browse files
committed
Handle errors that occur on unwind
1 parent 6c390fe commit d1d5fef

File tree

1 file changed

+39
-31
lines changed

1 file changed

+39
-31
lines changed

packages/react-reconciler/src/ReactFiberWorkLoop.js

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
688688
workLoopConcurrent();
689689
break;
690690
} catch (thrownValue) {
691-
handleError(root, workInProgress, thrownValue);
691+
handleError(root, thrownValue);
692692
}
693693
} while (true);
694694
resetContextDependencies();
@@ -1031,7 +1031,7 @@ function performSyncWorkOnRoot(root) {
10311031
workLoopSync();
10321032
break;
10331033
} catch (thrownValue) {
1034-
handleError(root, workInProgress, thrownValue);
1034+
handleError(root, thrownValue);
10351035
}
10361036
} while (true);
10371037
resetContextDependencies();
@@ -1322,38 +1322,46 @@ function prepareFreshStack(root, expirationTime) {
13221322
}
13231323
}
13241324

1325-
function handleError(root, sourceFiber, thrownValue) {
1326-
// Reset module-level state that was set during the render phase.
1327-
resetContextDependencies();
1328-
resetHooks();
1325+
function handleError(root, thrownValue) {
1326+
do {
1327+
try {
1328+
// Reset module-level state that was set during the render phase.
1329+
resetContextDependencies();
1330+
resetHooks();
13291331

1330-
if (workInProgress === null || workInProgress.return === null) {
1331-
// Expected to be working on a non-root fiber. This is a fatal error
1332-
// because there's no ancestor that can handle it; the root is
1333-
// supposed to capture all errors that weren't caught by an error
1334-
// boundary.
1335-
workInProgressRootExitStatus = RootFatalErrored;
1336-
workInProgressRootFatalError = thrownValue;
1337-
return null;
1338-
}
1332+
if (workInProgress === null || workInProgress.return === null) {
1333+
// Expected to be working on a non-root fiber. This is a fatal error
1334+
// because there's no ancestor that can handle it; the root is
1335+
// supposed to capture all errors that weren't caught by an error
1336+
// boundary.
1337+
workInProgressRootExitStatus = RootFatalErrored;
1338+
workInProgressRootFatalError = thrownValue;
1339+
return null;
1340+
}
13391341

1340-
if (enableProfilerTimer && sourceFiber.mode & ProfileMode) {
1341-
// Record the time spent rendering before an error was thrown. This
1342-
// avoids inaccurate Profiler durations in the case of a
1343-
// suspended render.
1344-
stopProfilerTimerIfRunningAndRecordDelta(sourceFiber, true);
1345-
}
1342+
if (enableProfilerTimer && workInProgress.mode & ProfileMode) {
1343+
// Record the time spent rendering before an error was thrown. This
1344+
// avoids inaccurate Profiler durations in the case of a
1345+
// suspended render.
1346+
stopProfilerTimerIfRunningAndRecordDelta(workInProgress, true);
1347+
}
13461348

1347-
throwException(
1348-
root,
1349-
workInProgress.return,
1350-
sourceFiber,
1351-
thrownValue,
1352-
renderExpirationTime,
1353-
);
1354-
// TODO: This is not wrapped in a try-catch, so if the complete phase
1355-
// throws, we won't capture it.
1356-
workInProgress = completeUnitOfWork(sourceFiber);
1349+
throwException(
1350+
root,
1351+
workInProgress.return,
1352+
workInProgress,
1353+
thrownValue,
1354+
renderExpirationTime,
1355+
);
1356+
workInProgress = completeUnitOfWork(workInProgress);
1357+
} catch (yetAnotherThrownValue) {
1358+
// Something in the return path also threw.
1359+
thrownValue = yetAnotherThrownValue;
1360+
continue;
1361+
}
1362+
// Return to the normal work loop.
1363+
return;
1364+
} while (true);
13571365
}
13581366

13591367
function pushDispatcher(root) {

0 commit comments

Comments
 (0)