Skip to content

Commit 92d7497

Browse files
committed
Use invokeGuardedCallback in place of Fiber try-catch blocks
1 parent 03f0e7a commit 92d7497

File tree

2 files changed

+26
-36
lines changed

2 files changed

+26
-36
lines changed

src/renderers/shared/fiber/ReactFiberCommitWork.js

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ var {
2626
} = ReactTypeOfWork;
2727
var { commitCallbacks } = require('ReactFiberUpdateQueue');
2828
var { onCommitUnmount } = require('ReactFiberDevToolsHook');
29+
var { invokeGuardedCallback } = require('ReactErrorUtils');
2930

3031
var {
3132
Placement,
@@ -52,24 +53,14 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
5253
getPublicInstance,
5354
} = config;
5455

55-
// Capture errors so they don't interrupt unmounting.
56-
function safelyCallComponentWillUnmount(current, instance) {
57-
try {
58-
instance.componentWillUnmount();
59-
} catch (error) {
60-
captureError(current, error);
61-
}
62-
}
63-
6456
// Capture errors so they don't interrupt unmounting.
6557
function safelyDetachRef(current : Fiber) {
66-
try {
67-
const ref = current.ref;
68-
if (ref !== null) {
69-
ref(null);
58+
const ref = current.ref;
59+
if (ref !== null) {
60+
const refError = invokeGuardedCallback(null, ref, null, null);
61+
if (refError !== null) {
62+
captureError(current, refError);
7063
}
71-
} catch (error) {
72-
captureError(current, error);
7364
}
7465
}
7566

@@ -341,7 +332,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
341332
safelyDetachRef(current);
342333
const instance = current.stateNode;
343334
if (typeof instance.componentWillUnmount === 'function') {
344-
safelyCallComponentWillUnmount(current, instance);
335+
const unmountError = invokeGuardedCallback(null, instance.componentWillUnmount, instance);
336+
if (unmountError) {
337+
captureError(current, unmountError);
338+
}
345339
}
346340
return;
347341
}

src/renderers/shared/fiber/ReactFiberScheduler.js

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ var {
3434
getStackAddendumByWorkInProgressFiber,
3535
} = require('ReactComponentTreeHook');
3636
var { logCapturedError } = require('ReactFiberErrorLogger');
37+
var { invokeGuardedCallback } = require('ReactErrorUtils');
3738

3839
var ReactFiberBeginWork = require('ReactFiberBeginWork');
3940
var ReactFiberCompleteWork = require('ReactFiberCompleteWork');
@@ -130,6 +131,9 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
130131
// Keeps track of whether we're currently in a work loop.
131132
let isPerformingWork : boolean = false;
132133

134+
// Keeps track of whether the current deadline has expired.
135+
let deadlineHasExpired : boolean = false;
136+
133137
// Keeps track of whether we should should batch sync updates.
134138
let isBatchingUpdates : boolean = false;
135139

@@ -377,9 +381,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
377381
// ref unmounts.
378382
nextEffect = firstEffect;
379383
while (nextEffect !== null) {
380-
try {
381-
commitAllHostEffects(finishedWork);
382-
} catch (error) {
384+
const error = invokeGuardedCallback(null, commitAllHostEffects, null, finishedWork);
385+
if (error !== null) {
383386
invariant(
384387
nextEffect !== null,
385388
'Should have next effect. This error is likely caused by a bug ' +
@@ -407,9 +410,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
407410
// This pass also triggers any renderer-specific initial effects.
408411
nextEffect = firstEffect;
409412
while (nextEffect !== null) {
410-
try {
411-
commitAllLifeCycles(finishedWork, nextEffect);
412-
} catch (error) {
413+
const error = invokeGuardedCallback(null, commitAllLifeCycles, null, finishedWork);
414+
if (error !== null) {
413415
invariant(
414416
nextEffect !== null,
415417
'Should have next effect. This error is likely caused by a bug ' +
@@ -638,7 +640,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
638640
}
639641
}
640642

641-
function workLoop(priorityLevel, deadline : Deadline | null, deadlineHasExpired : boolean) : boolean {
643+
function workLoop(priorityLevel, deadline : Deadline | null) {
642644
// Clear any errors.
643645
clearErrors();
644646

@@ -706,8 +708,6 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
706708
if (hostRootTimeMarker) {
707709
console.timeEnd(hostRootTimeMarker);
708710
}
709-
710-
return deadlineHasExpired;
711711
}
712712

713713
function performWork(priorityLevel : PriorityLevel, deadline : Deadline | null) {
@@ -718,7 +718,6 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
718718
);
719719
isPerformingWork = true;
720720
const isPerformingDeferredWork = Boolean(deadline);
721-
let deadlineHasExpired = false;
722721

723722
// This outer loop exists so that we can restart the work loop after
724723
// catching an error. It also lets us flush Task work at the end of a
@@ -739,17 +738,15 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
739738
// Nothing in performWork should be allowed to throw. All unsafe
740739
// operations must happen within workLoop, which is extracted to a
741740
// separate function so that it can be optimized by the JS engine.
742-
try {
743-
priorityContextBeforeReconciliation = priorityContext;
744-
priorityContext = nextPriorityLevel;
745-
deadlineHasExpired = workLoop(priorityLevel, deadline, deadlineHasExpired);
746-
} catch (error) {
741+
priorityContextBeforeReconciliation = priorityContext;
742+
const error = invokeGuardedCallback(null, workLoop, null, priorityLevel, deadline);
743+
// Reset the priority context to its value before reconcilation.
744+
priorityContext = priorityContextBeforeReconciliation;
745+
746+
if (error !== null) {
747747
// We caught an error during either the begin or complete phases.
748748
const failedWork = nextUnitOfWork;
749749
if (failedWork !== null) {
750-
// Reset the priority context to its value before reconcilation.
751-
priorityContext = priorityContextBeforeReconciliation;
752-
753750
// "Capture" the error by finding the nearest boundary. If there is no
754751
// error boundary, the nearest host container acts as one. If
755752
// captureError returns null, the error was intentionally ignored.
@@ -780,8 +777,6 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
780777
// inside resetAfterCommit.
781778
fatalError = error;
782779
}
783-
} finally {
784-
priorityContext = priorityContextBeforeReconciliation;
785780
}
786781

787782
// Stop performing work
@@ -824,6 +819,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
824819

825820
// We're done performing work. Time to clean up.
826821
isPerformingWork = false;
822+
deadlineHasExpired = false;
827823
fatalError = null;
828824
firstUncaughtError = null;
829825
capturedErrors = null;

0 commit comments

Comments
 (0)