Skip to content

Commit

Permalink
Report uncaught errors in DEV
Browse files Browse the repository at this point in the history
  • Loading branch information
gaearon committed Jun 23, 2021
1 parent 6b33d24 commit 3add2a8
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 16 deletions.
46 changes: 38 additions & 8 deletions packages/react-reconciler/src/ReactFiberCommitWork.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ import {
} from './ReactHookEffectTags';
import {didWarnAboutReassigningProps} from './ReactFiberBeginWork.new';
import {doesFiberContain} from './ReactFiberTreeReflection';
import {invokeGuardedCallback} from 'shared/ReactErrorUtils';

let didWarnAboutUndefinedSnapshotBeforeUpdate: Set<mixed> | null = null;
if (__DEV__) {
Expand All @@ -160,6 +161,19 @@ let nextEffect: Fiber | null = null;
let inProgressLanes: Lanes | null = null;
let inProgressRoot: FiberRoot | null = null;

function reportUncaughtErrorInDEV(error) {
// Wrapping each small part of the commit phase into a guarded
// callback is a bit too slow (https://github.com/facebook/react/pull/21666).
// But we rely on it to surface errors to DEV tools like overlays
// (https://github.com/facebook/react/issues/21712).
// As a compromise, rethrow only caught errors in a guard.
if (__DEV__) {
invokeGuardedCallback(null, () => {
throw error;
});
}
}

const callComponentWillUnmountWithTimer = function(current, instance) {
instance.props = current.memoizedProps;
instance.state = current.memoizedState;
Expand All @@ -186,8 +200,9 @@ function safelyCallCommitHookLayoutEffectListMount(
) {
try {
commitHookEffectListMount(HookLayout, current);
} catch (unmountError) {
captureCommitPhaseError(current, nearestMountedAncestor, unmountError);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(current, nearestMountedAncestor, error);
}
}

Expand All @@ -199,8 +214,9 @@ function safelyCallComponentWillUnmount(
) {
try {
callComponentWillUnmountWithTimer(current, instance);
} catch (unmountError) {
captureCommitPhaseError(current, nearestMountedAncestor, unmountError);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(current, nearestMountedAncestor, error);
}
}

Expand All @@ -212,17 +228,19 @@ function safelyCallComponentDidMount(
) {
try {
instance.componentDidMount();
} catch (unmountError) {
captureCommitPhaseError(current, nearestMountedAncestor, unmountError);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(current, nearestMountedAncestor, error);
}
}

// Capture errors so they don't interrupt mounting.
function safelyAttachRef(current: Fiber, nearestMountedAncestor: Fiber | null) {
try {
commitAttachRef(current);
} catch (unmountError) {
captureCommitPhaseError(current, nearestMountedAncestor, unmountError);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(current, nearestMountedAncestor, error);
}
}

Expand All @@ -246,6 +264,7 @@ function safelyDetachRef(current: Fiber, nearestMountedAncestor: Fiber | null) {
ref(null);
}
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(current, nearestMountedAncestor, error);
}
} else {
Expand All @@ -262,6 +281,7 @@ function safelyCallDestroy(
try {
destroy();
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(current, nearestMountedAncestor, error);
}
}
Expand Down Expand Up @@ -323,6 +343,7 @@ function commitBeforeMutationEffects_complete() {
try {
commitBeforeMutationEffectsOnFiber(fiber);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
resetCurrentDebugFiberInDEV();
Expand Down Expand Up @@ -2065,6 +2086,7 @@ function commitMutationEffects_begin(root: FiberRoot) {
try {
commitDeletion(root, childToDelete, fiber);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(childToDelete, fiber, error);
}
}
Expand All @@ -2087,6 +2109,7 @@ function commitMutationEffects_complete(root: FiberRoot) {
try {
commitMutationEffectsOnFiber(fiber, root);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
resetCurrentDebugFiberInDEV();
Expand Down Expand Up @@ -2329,6 +2352,7 @@ function commitLayoutMountEffects_complete(
try {
commitLayoutEffectOnFiber(root, current, fiber, committedLanes);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
resetCurrentDebugFiberInDEV();
Expand Down Expand Up @@ -2382,6 +2406,7 @@ function commitPassiveMountEffects_complete(
try {
commitPassiveMountOnFiber(root, fiber);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
resetCurrentDebugFiberInDEV();
Expand Down Expand Up @@ -2664,6 +2689,7 @@ function invokeLayoutEffectMountInDEV(fiber: Fiber): void {
try {
commitHookEffectListMount(HookLayout | HookHasEffect, fiber);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
break;
Expand All @@ -2673,6 +2699,7 @@ function invokeLayoutEffectMountInDEV(fiber: Fiber): void {
try {
instance.componentDidMount();
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
break;
Expand All @@ -2692,6 +2719,7 @@ function invokePassiveEffectMountInDEV(fiber: Fiber): void {
try {
commitHookEffectListMount(HookPassive | HookHasEffect, fiber);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
break;
Expand All @@ -2715,6 +2743,7 @@ function invokeLayoutEffectUnmountInDEV(fiber: Fiber): void {
fiber.return,
);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
break;
Expand Down Expand Up @@ -2745,6 +2774,7 @@ function invokePassiveEffectUnmountInDEV(fiber: Fiber): void {
fiber.return,
);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
}
Expand Down
46 changes: 38 additions & 8 deletions packages/react-reconciler/src/ReactFiberCommitWork.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ import {
} from './ReactHookEffectTags';
import {didWarnAboutReassigningProps} from './ReactFiberBeginWork.old';
import {doesFiberContain} from './ReactFiberTreeReflection';
import {invokeGuardedCallback} from 'shared/ReactErrorUtils';

let didWarnAboutUndefinedSnapshotBeforeUpdate: Set<mixed> | null = null;
if (__DEV__) {
Expand All @@ -160,6 +161,19 @@ let nextEffect: Fiber | null = null;
let inProgressLanes: Lanes | null = null;
let inProgressRoot: FiberRoot | null = null;

function reportUncaughtErrorInDEV(error) {
// Wrapping each small part of the commit phase into a guarded
// callback is a bit too slow (https://github.com/facebook/react/pull/21666).
// But we rely on it to surface errors to DEV tools like overlays
// (https://github.com/facebook/react/issues/21712).
// As a compromise, rethrow only caught errors in a guard.
if (__DEV__) {
invokeGuardedCallback(null, () => {
throw error;
});
}
}

const callComponentWillUnmountWithTimer = function(current, instance) {
instance.props = current.memoizedProps;
instance.state = current.memoizedState;
Expand All @@ -186,8 +200,9 @@ function safelyCallCommitHookLayoutEffectListMount(
) {
try {
commitHookEffectListMount(HookLayout, current);
} catch (unmountError) {
captureCommitPhaseError(current, nearestMountedAncestor, unmountError);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(current, nearestMountedAncestor, error);
}
}

Expand All @@ -199,8 +214,9 @@ function safelyCallComponentWillUnmount(
) {
try {
callComponentWillUnmountWithTimer(current, instance);
} catch (unmountError) {
captureCommitPhaseError(current, nearestMountedAncestor, unmountError);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(current, nearestMountedAncestor, error);
}
}

Expand All @@ -212,17 +228,19 @@ function safelyCallComponentDidMount(
) {
try {
instance.componentDidMount();
} catch (unmountError) {
captureCommitPhaseError(current, nearestMountedAncestor, unmountError);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(current, nearestMountedAncestor, error);
}
}

// Capture errors so they don't interrupt mounting.
function safelyAttachRef(current: Fiber, nearestMountedAncestor: Fiber | null) {
try {
commitAttachRef(current);
} catch (unmountError) {
captureCommitPhaseError(current, nearestMountedAncestor, unmountError);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(current, nearestMountedAncestor, error);
}
}

Expand All @@ -246,6 +264,7 @@ function safelyDetachRef(current: Fiber, nearestMountedAncestor: Fiber | null) {
ref(null);
}
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(current, nearestMountedAncestor, error);
}
} else {
Expand All @@ -262,6 +281,7 @@ function safelyCallDestroy(
try {
destroy();
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(current, nearestMountedAncestor, error);
}
}
Expand Down Expand Up @@ -323,6 +343,7 @@ function commitBeforeMutationEffects_complete() {
try {
commitBeforeMutationEffectsOnFiber(fiber);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
resetCurrentDebugFiberInDEV();
Expand Down Expand Up @@ -2065,6 +2086,7 @@ function commitMutationEffects_begin(root: FiberRoot) {
try {
commitDeletion(root, childToDelete, fiber);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(childToDelete, fiber, error);
}
}
Expand All @@ -2087,6 +2109,7 @@ function commitMutationEffects_complete(root: FiberRoot) {
try {
commitMutationEffectsOnFiber(fiber, root);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
resetCurrentDebugFiberInDEV();
Expand Down Expand Up @@ -2329,6 +2352,7 @@ function commitLayoutMountEffects_complete(
try {
commitLayoutEffectOnFiber(root, current, fiber, committedLanes);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
resetCurrentDebugFiberInDEV();
Expand Down Expand Up @@ -2382,6 +2406,7 @@ function commitPassiveMountEffects_complete(
try {
commitPassiveMountOnFiber(root, fiber);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
resetCurrentDebugFiberInDEV();
Expand Down Expand Up @@ -2664,6 +2689,7 @@ function invokeLayoutEffectMountInDEV(fiber: Fiber): void {
try {
commitHookEffectListMount(HookLayout | HookHasEffect, fiber);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
break;
Expand All @@ -2673,6 +2699,7 @@ function invokeLayoutEffectMountInDEV(fiber: Fiber): void {
try {
instance.componentDidMount();
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
break;
Expand All @@ -2692,6 +2719,7 @@ function invokePassiveEffectMountInDEV(fiber: Fiber): void {
try {
commitHookEffectListMount(HookPassive | HookHasEffect, fiber);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
break;
Expand All @@ -2715,6 +2743,7 @@ function invokeLayoutEffectUnmountInDEV(fiber: Fiber): void {
fiber.return,
);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
break;
Expand Down Expand Up @@ -2745,6 +2774,7 @@ function invokePassiveEffectUnmountInDEV(fiber: Fiber): void {
fiber.return,
);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
}
}
Expand Down

0 comments on commit 3add2a8

Please sign in to comment.