Skip to content

Commit 7d52f8c

Browse files
committed
Use invokeGuardedCallback in place of Fiber try-catch blocks
1 parent aacb461 commit 7d52f8c

File tree

2 files changed

+51
-36
lines changed

2 files changed

+51
-36
lines changed

src/renderers/shared/fiber/ReactFiberCommitWork.js

Lines changed: 20 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,19 @@ 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) {
69-
ref(null);
58+
const ref = current.ref;
59+
if (ref) {
60+
let refError;
61+
if (__DEV__) {
62+
refError = invokeGuardedCallback('detachref', ref, null, null);
63+
} else {
64+
refError = invokeGuardedCallback(null, ref, null, null);
65+
}
66+
if (refError) {
67+
captureError(current, refError);
7068
}
71-
} catch (error) {
72-
captureError(current, error);
7369
}
7470
}
7571

@@ -341,7 +337,15 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
341337
safelyDetachRef(current);
342338
const instance = current.stateNode;
343339
if (typeof instance.componentWillUnmount === 'function') {
344-
safelyCallComponentWillUnmount(current, instance);
340+
let unmountError;
341+
if (__DEV__) {
342+
unmountError = invokeGuardedCallback('componentwillunmount', instance.componentWillUnmount, instance);
343+
} else {
344+
unmountError = invokeGuardedCallback(null, instance.componentWillUnmount, instance);
345+
}
346+
if (unmountError) {
347+
captureError(current, unmountError);
348+
}
345349
}
346350
return;
347351
}

src/renderers/shared/fiber/ReactFiberScheduler.js

Lines changed: 31 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,13 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
377381
// ref unmounts.
378382
nextEffect = firstEffect;
379383
while (nextEffect) {
380-
try {
381-
commitAllHostEffects(finishedWork);
382-
} catch (error) {
384+
let error;
385+
if (__DEV__) {
386+
error = invokeGuardedCallback('commitphase1', commitAllHostEffects, null, finishedWork);
387+
} else {
388+
error = invokeGuardedCallback(null, commitAllHostEffects, null, finishedWork);
389+
}
390+
if (error !== null) {
383391
invariant(
384392
nextEffect != null,
385393
'Should have next effect. This error is likely caused by a bug ' +
@@ -407,9 +415,13 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
407415
// This pass also triggers any renderer-specific initial effects.
408416
nextEffect = firstEffect;
409417
while (nextEffect) {
410-
try {
411-
commitAllLifeCycles(finishedWork, nextEffect);
412-
} catch (error) {
418+
let error;
419+
if (__DEV__) {
420+
error = invokeGuardedCallback('commitphase2', commitAllLifeCycles, null, finishedWork);
421+
} else {
422+
error = invokeGuardedCallback(null, commitAllLifeCycles, null, finishedWork);
423+
}
424+
if (error !== null) {
413425
invariant(
414426
nextEffect != null,
415427
'Should have next effect. This error is likely caused by a bug ' +
@@ -638,7 +650,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
638650
}
639651
}
640652

641-
function workLoop(priorityLevel, deadline : Deadline | null, deadlineHasExpired : boolean) : boolean {
653+
function workLoop(priorityLevel, deadline : Deadline | null) {
642654
// Clear any errors.
643655
clearErrors();
644656

@@ -706,8 +718,6 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
706718
if (hostRootTimeMarker) {
707719
console.timeEnd(hostRootTimeMarker);
708720
}
709-
710-
return deadlineHasExpired;
711721
}
712722

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

723732
// This outer loop exists so that we can restart the work loop after
724733
// catching an error. It also lets us flush Task work at the end of a
@@ -739,17 +748,20 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
739748
// Nothing in performWork should be allowed to throw. All unsafe
740749
// operations must happen within workLoop, which is extracted to a
741750
// 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) {
751+
let error;
752+
priorityContextBeforeReconciliation = priorityContext;
753+
if (__DEV__) {
754+
error = invokeGuardedCallback('performwork', workLoop, null, priorityLevel, deadline);
755+
} else {
756+
error = invokeGuardedCallback(null, workLoop, null, priorityLevel, deadline);
757+
}
758+
// Reset the priority context to its value before reconcilation.
759+
priorityContext = priorityContextBeforeReconciliation;
760+
761+
if (error !== null) {
747762
// We caught an error during either the begin or complete phases.
748763
const failedWork = nextUnitOfWork;
749764
if (failedWork) {
750-
// Reset the priority context to its value before reconcilation.
751-
priorityContext = priorityContextBeforeReconciliation;
752-
753765
// "Capture" the error by finding the nearest boundary. If there is no
754766
// error boundary, the nearest host container acts as one. If
755767
// captureError returns null, the error was intentionally ignored.
@@ -780,8 +792,6 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
780792
// inside resetAfterCommit.
781793
fatalError = error;
782794
}
783-
} finally {
784-
priorityContext = priorityContextBeforeReconciliation;
785795
}
786796

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

825835
// We're done performing work. Time to clean up.
826836
isPerformingWork = false;
837+
deadlineHasExpired = false;
827838
fatalError = null;
828839
firstUncaughtError = null;
829840
capturedErrors = null;

0 commit comments

Comments
 (0)