@@ -275,19 +275,17 @@ let interruptedBy: Fiber | null = null;
275275
276276let stashedWorkInProgressProperties ;
277277let replayUnitOfWork ;
278- let mayReplayFailedUnitOfWork ;
279278let isReplayingFailedUnitOfWork ;
280279let originalReplayError ;
281280let rethrowOriginalError ;
282281if ( __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 ) {
0 commit comments