Skip to content

Commit 10eddb1

Browse files
committed
Start refactoring replay logic
1 parent 3c69a18 commit 10eddb1

File tree

2 files changed

+42
-49
lines changed

2 files changed

+42
-49
lines changed

packages/react-reconciler/src/ReactFiberScheduler.js

Lines changed: 42 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -275,19 +275,17 @@ let interruptedBy: Fiber | null = null;
275275

276276
let stashedWorkInProgressProperties;
277277
let replayUnitOfWork;
278-
let mayReplayFailedUnitOfWork;
279278
let isReplayingFailedUnitOfWork;
280279
let originalReplayError;
281280
let rethrowOriginalError;
282281
if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
283282
stashedWorkInProgressProperties = null;
284-
mayReplayFailedUnitOfWork = true;
285283
isReplayingFailedUnitOfWork = false;
286284
originalReplayError = null;
287285
replayUnitOfWork = (
288286
failedUnitOfWork: Fiber,
289287
thrownValue: mixed,
290-
isYieldy: boolean,
288+
current, workInProgress, renderExpirationTime
291289
) => {
292290
if (
293291
thrownValue !== null &&
@@ -340,7 +338,7 @@ if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
340338
// Replay the begin phase.
341339
isReplayingFailedUnitOfWork = true;
342340
originalReplayError = thrownValue;
343-
invokeGuardedCallback(null, workLoop, null, isYieldy);
341+
invokeGuardedCallback(null, beginWork, current, workInProgress, renderExpirationTime);
344342
isReplayingFailedUnitOfWork = false;
345343
originalReplayError = null;
346344
if (hasCaughtError()) {
@@ -954,10 +952,6 @@ function completeUnitOfWork(workInProgress: Fiber): Fiber | null {
954952
const siblingFiber = workInProgress.sibling;
955953

956954
if ((workInProgress.effectTag & Incomplete) === NoEffect) {
957-
if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
958-
// Don't replay if it fails during completion phase.
959-
mayReplayFailedUnitOfWork = false;
960-
}
961955
// This fiber completed.
962956
// Remember we're completing this unit so we can find a boundary if it fails.
963957
nextUnitOfWork = workInProgress;
@@ -981,10 +975,6 @@ function completeUnitOfWork(workInProgress: Fiber): Fiber | null {
981975
nextRenderExpirationTime,
982976
);
983977
}
984-
if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
985-
// We're out of completion phase so replaying is fine now.
986-
mayReplayFailedUnitOfWork = true;
987-
}
988978
stopWorkTimer(workInProgress);
989979
resetChildExpirationTime(workInProgress, nextRenderExpirationTime);
990980
if (__DEV__) {
@@ -1127,7 +1117,7 @@ function completeUnitOfWork(workInProgress: Fiber): Fiber | null {
11271117
return null;
11281118
}
11291119

1130-
function performUnitOfWork(workInProgress: Fiber): Fiber | null {
1120+
function performUnitOfWork(workInProgress: Fiber, isYieldy: boolean): Fiber | null {
11311121
// The current, flushed, state of this fiber is the alternate.
11321122
// Ideally nothing should rely on this, but relying on it here
11331123
// means that we don't need an additional field on the work in
@@ -1153,15 +1143,23 @@ function performUnitOfWork(workInProgress: Fiber): Fiber | null {
11531143
startProfilerTimer(workInProgress);
11541144
}
11551145

1156-
next = beginWork(current, workInProgress, nextRenderExpirationTime);
1146+
if (__DEV__) {
1147+
next = beginWorkInDEV(current, workInProgress, nextRenderExpirationTime, isYieldy);
1148+
} else {
1149+
next = beginWork(current, workInProgress, nextRenderExpirationTime);
1150+
}
11571151
workInProgress.memoizedProps = workInProgress.pendingProps;
11581152

11591153
if (workInProgress.mode & ProfileMode) {
11601154
// Record the render duration assuming we didn't bailout (or error).
11611155
stopProfilerTimerIfRunningAndRecordDelta(workInProgress, true);
11621156
}
11631157
} else {
1164-
next = beginWork(current, workInProgress, nextRenderExpirationTime);
1158+
if (__DEV__) {
1159+
next = beginWorkInDEV(current, workInProgress, nextRenderExpirationTime, isYieldy);
1160+
} else {
1161+
next = beginWork(current, workInProgress, nextRenderExpirationTime);
1162+
}
11651163
workInProgress.memoizedProps = workInProgress.pendingProps;
11661164
}
11671165

@@ -1193,13 +1191,40 @@ function workLoop(isYieldy) {
11931191
if (!isYieldy) {
11941192
// Flush work without yielding
11951193
while (nextUnitOfWork !== null) {
1196-
nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
1194+
nextUnitOfWork = performUnitOfWork(nextUnitOfWork, isYieldy);
11971195
}
11981196
} else {
11991197
// Flush asynchronous work until there's a higher priority event
12001198
while (nextUnitOfWork !== null && !shouldYieldToRenderer()) {
1201-
nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
1199+
nextUnitOfWork = performUnitOfWork(nextUnitOfWork, isYieldy);
1200+
}
1201+
}
1202+
}
1203+
1204+
function beginWorkInDEV(
1205+
current: Fiber | null,
1206+
workInProgress: Fiber,
1207+
renderExpirationTime: ExpirationTime,
1208+
isYieldy: boolean,
1209+
): Fiber | null {
1210+
try {
1211+
return beginWork(current, workInProgress, renderExpirationTime);
1212+
} catch (thrownValue) {
1213+
resetContextDependences();
1214+
resetHooks();
1215+
if (nextUnitOfWork === null) {
1216+
throw thrownValue;
1217+
}
1218+
if (__DEV__) {
1219+
// Reset global debug state
1220+
// We assume this is defined in DEV
1221+
(resetCurrentlyProcessingQueue: any)();
1222+
}
1223+
if (replayFailedUnitOfWorkWithInvokeGuardedCallback) {
1224+
const failedUnitOfWork: Fiber = nextUnitOfWork;
1225+
replayUnitOfWork(failedUnitOfWork, thrownValue, current, workInProgress, renderExpirationTime);
12021226
}
1227+
throw thrownValue;
12031228
}
12041229
}
12051230

@@ -1302,42 +1327,11 @@ function renderRoot(root: FiberRoot, isYieldy: boolean): void {
13021327
resetContextDependences();
13031328
resetHooks();
13041329

1305-
// Reset in case completion throws.
1306-
// This is only used in DEV and when replaying is on.
1307-
let mayReplay;
1308-
if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
1309-
mayReplay = mayReplayFailedUnitOfWork;
1310-
mayReplayFailedUnitOfWork = true;
1311-
}
1312-
13131330
if (nextUnitOfWork === null) {
13141331
// This is a fatal error.
13151332
didFatal = true;
13161333
onUncaughtError(thrownValue);
13171334
} else {
1318-
if (__DEV__) {
1319-
// Reset global debug state
1320-
// We assume this is defined in DEV
1321-
(resetCurrentlyProcessingQueue: any)();
1322-
}
1323-
1324-
if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
1325-
if (mayReplay) {
1326-
const failedUnitOfWork: Fiber = nextUnitOfWork;
1327-
replayUnitOfWork(failedUnitOfWork, thrownValue, isYieldy);
1328-
}
1329-
}
1330-
1331-
// TODO: we already know this isn't true in some cases.
1332-
// At least this shows a nicer error message until we figure out the cause.
1333-
// https://github.com/facebook/react/issues/12449#issuecomment-386727431
1334-
invariant(
1335-
nextUnitOfWork !== null,
1336-
'Failed to replay rendering after an error. This ' +
1337-
'is likely caused by a bug in React. Please file an issue ' +
1338-
'with a reproducing case to help us find it.',
1339-
);
1340-
13411335
const sourceFiber: Fiber = nextUnitOfWork;
13421336
let returnFiber = sourceFiber.return;
13431337
if (returnFiber === null) {

packages/react-reconciler/src/__tests__/ReactIncrementalErrorLogging-test.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,6 @@ describe('ReactIncrementalErrorLogging', () => {
186186
'render: 0',
187187
__DEV__ && 'render: 0', // replay
188188
'render: 1',
189-
__DEV__ && 'render: 1', // replay
190189
'componentWillUnmount: 0',
191190
].filter(Boolean),
192191
);

0 commit comments

Comments
 (0)