@@ -892,58 +892,39 @@ export function performConcurrentWorkOnRoot(
892
892
let exitStatus = shouldTimeSlice
893
893
? renderRootConcurrent ( root , lanes )
894
894
: 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
- }
922
895
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
+ }
945
926
946
- // We need to check again if something threw
927
+ // Check if something threw
947
928
if ( exitStatus === RootErrored ) {
948
929
const originallyAttemptedLanes = lanes ;
949
930
const errorRetryLanes = getLanesToRetrySynchronouslyOnError (
@@ -957,8 +938,7 @@ export function performConcurrentWorkOnRoot(
957
938
originallyAttemptedLanes ,
958
939
errorRetryLanes ,
959
940
) ;
960
- // We assume the tree is now consistent because we didn't yield to any
961
- // concurrent events.
941
+ renderWasConcurrent = false ;
962
942
}
963
943
}
964
944
if ( exitStatus === RootFatalErrored ) {
@@ -969,16 +949,14 @@ export function performConcurrentWorkOnRoot(
969
949
throw fatalError ;
970
950
}
971
951
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 ) ;
974
957
}
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 ) ;
982
960
}
983
961
984
962
ensureRootIsScheduled ( root ) ;
0 commit comments