@@ -892,58 +892,39 @@ export function performConcurrentWorkOnRoot(
892892 let exitStatus = shouldTimeSlice
893893 ? renderRootConcurrent ( root , lanes )
894894 : renderRootSync ( root , lanes ) ;
895- if ( exitStatus !== RootInProgress ) {
896- if ( exitStatus === RootErrored ) {
897- // If something threw an error, try rendering one more time. We'll
898- // render synchronously to block concurrent data mutations, and we'll
899- // includes all pending updates are included. If it still fails after
900- // the second attempt, we'll give up and commit the resulting tree.
901- const originallyAttemptedLanes = lanes ;
902- const errorRetryLanes = getLanesToRetrySynchronouslyOnError (
903- root ,
904- originallyAttemptedLanes ,
905- ) ;
906- if ( errorRetryLanes !== NoLanes ) {
907- lanes = errorRetryLanes ;
908- exitStatus = recoverFromConcurrentError (
909- root ,
910- originallyAttemptedLanes ,
911- errorRetryLanes ,
912- ) ;
913- }
914- }
915- if ( exitStatus === RootFatalErrored ) {
916- const fatalError = workInProgressRootFatalError ;
917- prepareFreshStack ( root , NoLanes ) ;
918- markRootSuspended ( root , lanes ) ;
919- ensureRootIsScheduled ( root ) ;
920- throw fatalError ;
921- }
922895
923- if ( exitStatus === RootDidNotComplete ) {
924- // The render unwound without completing the tree. This happens in special
925- // cases where need to exit the current render without producing a
926- // consistent tree or committing.
927- markRootSuspended ( root , lanes ) ;
928- } else {
929- // The render completed.
930-
931- // Check if this render may have yielded to a concurrent event, and if so,
932- // confirm that any newly rendered stores are consistent.
933- // TODO: It's possible that even a concurrent render may never have yielded
934- // to the main thread, if it was fast enough, or if it expired. We could
935- // skip the consistency check in that case, too.
936- const renderWasConcurrent = ! includesBlockingLane ( root , lanes ) ;
937- const finishedWork : Fiber = ( root . current . alternate : any ) ;
938- if (
939- renderWasConcurrent &&
940- ! isRenderConsistentWithExternalStores ( finishedWork )
941- ) {
942- // A store was mutated in an interleaved event. Render again,
943- // synchronously, to block further mutations.
944- exitStatus = renderRootSync ( root , lanes ) ;
896+ if ( exitStatus !== RootInProgress ) {
897+ let renderWasConcurrent = shouldTimeSlice ;
898+ do {
899+ if ( exitStatus === RootDidNotComplete ) {
900+ // The render unwound without completing the tree. This happens in special
901+ // cases where need to exit the current render without producing a
902+ // consistent tree or committing.
903+ markRootSuspended ( root , lanes ) ;
904+ } else {
905+ // The render completed.
906+
907+ // Check if this render may have yielded to a concurrent event, and if so,
908+ // confirm that any newly rendered stores are consistent.
909+ // TODO: It's possible that even a concurrent render may never have yielded
910+ // to the main thread, if it was fast enough, or if it expired. We could
911+ // skip the consistency check in that case, too.
912+ const finishedWork : Fiber = ( root . current . alternate : any ) ;
913+ if (
914+ renderWasConcurrent &&
915+ ! isRenderConsistentWithExternalStores ( finishedWork )
916+ ) {
917+ // A store was mutated in an interleaved event. Render again,
918+ // synchronously, to block further mutations.
919+ exitStatus = renderRootSync ( root , lanes ) ;
920+ // We assume the tree is now consistent because we didn't yield to any
921+ // concurrent events.
922+ renderWasConcurrent = false ;
923+ // Need to check the exit status again.
924+ continue ;
925+ }
945926
946- // We need to check again if something threw
927+ // Check if something threw
947928 if ( exitStatus === RootErrored ) {
948929 const originallyAttemptedLanes = lanes ;
949930 const errorRetryLanes = getLanesToRetrySynchronouslyOnError (
@@ -957,8 +938,7 @@ export function performConcurrentWorkOnRoot(
957938 originallyAttemptedLanes ,
958939 errorRetryLanes ,
959940 ) ;
960- // We assume the tree is now consistent because we didn't yield to any
961- // concurrent events.
941+ renderWasConcurrent = false ;
962942 }
963943 }
964944 if ( exitStatus === RootFatalErrored ) {
@@ -969,16 +949,14 @@ export function performConcurrentWorkOnRoot(
969949 throw fatalError ;
970950 }
971951
972- // FIXME: Need to check for RootDidNotComplete again. The factoring here
973- // isn't ideal.
952+ // We now have a consistent tree. The next step is either to commit it,
953+ // or, if something suspended, wait to commit it after a timeout.
954+ root . finishedWork = finishedWork ;
955+ root . finishedLanes = lanes ;
956+ finishConcurrentRender ( root , exitStatus , finishedWork , lanes ) ;
974957 }
975-
976- // We now have a consistent tree. The next step is either to commit it,
977- // or, if something suspended, wait to commit it after a timeout.
978- root . finishedWork = finishedWork ;
979- root . finishedLanes = lanes ;
980- finishConcurrentRender ( root , exitStatus , finishedWork , lanes ) ;
981- }
958+ break ;
959+ } while ( true ) ;
982960 }
983961
984962 ensureRootIsScheduled ( root ) ;
0 commit comments