@@ -1066,10 +1066,7 @@ function reappearLayoutEffectsOnFiber(node: Fiber) {
10661066 }
10671067}
10681068
1069- function commitTransitionProgress (
1070- finishedRoot : FiberRoot ,
1071- offscreenFiber : Fiber ,
1072- ) {
1069+ function commitTransitionProgress ( offscreenFiber : Fiber ) {
10731070 if ( enableTransitionTracing ) {
10741071 // This function adds suspense boundaries to the root
10751072 // or tracing marker's pendingSuspenseBoundaries map.
@@ -1094,12 +1091,7 @@ function commitTransitionProgress(
10941091 const wasHidden = prevState !== null ;
10951092 const isHidden = nextState !== null ;
10961093
1097- const rootState : RootState = finishedRoot . current . memoizedState ;
1098- // TODO(luna) move pendingSuspenseBoundaries and transitions from
1099- // HostRoot fiber to FiberRoot
1100- const rootPendingBoundaries = rootState . pendingSuspenseBoundaries ;
1101- const rootTransitions = rootState . transitions ;
1102-
1094+ const pendingMarkers = offscreenInstance . pendingMarkers ;
11031095 // If there is a name on the suspense boundary, store that in
11041096 // the pending boundaries.
11051097 let name = null ;
@@ -1112,38 +1104,26 @@ function commitTransitionProgress(
11121104 name = parent . memoizedProps . unstable_name ;
11131105 }
11141106
1115- if ( rootPendingBoundaries !== null ) {
1116- if ( previousFiber === null ) {
1117- // Initial mount
1118- if ( isHidden ) {
1119- rootPendingBoundaries . set ( offscreenInstance , {
1107+ if ( ! wasHidden && isHidden ) {
1108+ // The suspense boundaries was just hidden. Add the boundary
1109+ // to the pending boundary set if it's there
1110+ if ( pendingMarkers !== null ) {
1111+ pendingMarkers . forEach ( pendingBoundaries => {
1112+ pendingBoundaries . set ( offscreenInstance , {
11201113 name,
11211114 } ) ;
1122- }
1123- } else {
1124- if ( wasHidden && ! isHidden ) {
1125- // The suspense boundary went from hidden to visible. Remove
1126- // the boundary from the pending suspense boundaries set
1127- // if it's there
1128- if ( rootPendingBoundaries . has ( offscreenInstance ) ) {
1129- rootPendingBoundaries . delete ( offscreenInstance ) ;
1130-
1131- if ( rootPendingBoundaries . size === 0 && rootTransitions !== null ) {
1132- rootTransitions . forEach ( transition => {
1133- addTransitionCompleteCallbackToPendingTransition ( {
1134- transitionName : transition . name ,
1135- startTime : transition . startTime ,
1136- } ) ;
1137- } ) ;
1138- }
1115+ } ) ;
1116+ }
1117+ } else if ( wasHidden && ! isHidden ) {
1118+ // The suspense boundary went from hidden to visible. Remove
1119+ // the boundary from the pending suspense boundaries set
1120+ // if it's there
1121+ if ( pendingMarkers !== null ) {
1122+ pendingMarkers . forEach ( pendingBoundaries => {
1123+ if ( pendingBoundaries . has ( offscreenInstance ) ) {
1124+ pendingBoundaries . delete ( offscreenInstance ) ;
11391125 }
1140- } else if ( ! wasHidden && isHidden ) {
1141- // The suspense boundaries was just hidden. Add the boundary
1142- // to the pending boundary set if it's there
1143- rootPendingBoundaries . set ( offscreenInstance , {
1144- name,
1145- } ) ;
1146- }
1126+ } ) ;
11471127 }
11481128 }
11491129 }
@@ -2830,45 +2810,46 @@ function commitPassiveMountOnFiber(
28302810 // Get the transitions that were initiatized during the render
28312811 // and add a start transition callback for each of them
28322812 const state = finishedWork . memoizedState ;
2833- // TODO Since it's a mutable field, this should live on the FiberRoot
2834- if ( state . transitions === null ) {
2835- state . transitions = new Set ( [ ] ) ;
2836- }
2837- const pendingTransitions = state . transitions ;
2838- const pendingSuspenseBoundaries = state . pendingSuspenseBoundaries ;
2839-
2813+ let incompleteTransitions = state . incompleteTransitions ;
28402814 // Initial render
28412815 if ( committedTransitions !== null ) {
2816+ if ( state . incompleteTransitions === null ) {
2817+ state . incompleteTransitions = incompleteTransitions = new Map ( ) ;
2818+ }
2819+
28422820 committedTransitions . forEach ( transition => {
28432821 addTransitionStartCallbackToPendingTransition ( {
28442822 transitionName : transition . name ,
28452823 startTime : transition . startTime ,
28462824 } ) ;
2847- pendingTransitions . add ( transition ) ;
2825+
2826+ if ( ! incompleteTransitions . has ( transition ) ) {
2827+ incompleteTransitions . set ( transition , null ) ;
2828+ }
28482829 } ) ;
28492830
2850- if (
2851- pendingSuspenseBoundaries === null ||
2852- pendingSuspenseBoundaries . size === 0
2853- ) {
2854- pendingTransitions . forEach ( transition => {
2831+ clearTransitionsForLanes ( finishedRoot , committedLanes ) ;
2832+ }
2833+
2834+ if ( incompleteTransitions !== null ) {
2835+ incompleteTransitions . forEach ( ( pendingBoundaries , transition ) => {
2836+ if ( pendingBoundaries === null || pendingBoundaries . size === 0 ) {
28552837 addTransitionCompleteCallbackToPendingTransition ( {
28562838 transitionName : transition . name ,
28572839 startTime : transition . startTime ,
28582840 } ) ;
2859- } ) ;
2860- }
2861-
2862- clearTransitionsForLanes ( finishedRoot , committedLanes ) ;
2841+ incompleteTransitions . delete ( transition ) ;
2842+ }
2843+ } ) ;
28632844 }
28642845
28652846 // If there are no more pending suspense boundaries we
28662847 // clear the transitions because they are all complete.
28672848 if (
2868- pendingSuspenseBoundaries === null ||
2869- pendingSuspenseBoundaries . size === 0
2849+ incompleteTransitions === null ||
2850+ incompleteTransitions . size === 0
28702851 ) {
2871- state . transitions = null ;
2852+ state . incompleteTransitions = null ;
28722853 }
28732854 }
28742855 break ;
@@ -2909,39 +2890,58 @@ function commitPassiveMountOnFiber(
29092890 const isFallback = finishedWork . memoizedState ;
29102891 const queue = ( finishedWork . updateQueue : any ) ;
29112892 const rootMemoizedState = finishedRoot . current . memoizedState ;
2893+ const instance = finishedWork . stateNode ;
29122894
29132895 if ( queue !== null ) {
2914- // We have one instance of the pendingSuspenseBoundaries map.
2915- // We only need one because we update it during the commit phase.
2916- // We instantiate a new Map if we haven't already
2917- if ( rootMemoizedState . pendingSuspenseBoundaries === null ) {
2918- rootMemoizedState . pendingSuspenseBoundaries = new Map ( ) ;
2919- }
2920-
29212896 if ( isFallback ) {
29222897 const transitions = queue . transitions ;
2923- let prevTransitions = finishedWork . memoizedState . transitions ;
2924- // Add all the transitions saved in the update queue during
2925- // the render phase (ie the transitions associated with this boundary)
2926- // into the transitions set.
2927- if ( transitions !== null ) {
2928- if ( prevTransitions === null ) {
2929- // We only have one instance of the transitions set
2930- // because we update it only during the commit phase. We
2931- // will create the set on a as needed basis in the commit phase
2932- finishedWork . memoizedState . transitions = prevTransitions = new Set ( ) ;
2933- }
2898+ let prevTransitions = instance . transitions ;
2899+ let rootIncompleteTransitions =
2900+ rootMemoizedState . incompleteTransitions ;
2901+
2902+ // We lazily instantiate transition tracing relevant maps
2903+ // and sets in the commit phase as we need to use them. We only
2904+ // instantiate them in the fallback phase on an as needed basis
2905+ if ( rootMemoizedState . incompleteTransitions === null ) {
2906+ rootMemoizedState . incompleteTransitions = rootIncompleteTransitions = new Map ( ) ;
2907+ }
2908+ if ( instance . pendingMarkers === null ) {
2909+ instance . pendingMarkers = new Set ( ) ;
2910+ }
2911+ if ( transitions !== null && prevTransitions === null ) {
2912+ instance . transitions = prevTransitions = new Set ( ) ;
2913+ }
29342914
2915+ if ( transitions !== null ) {
29352916 transitions . forEach ( transition => {
2917+ // Add all the transitions saved in the update queue during
2918+ // the render phase (ie the transitions associated with this boundary)
2919+ // into the transitions set.
29362920 prevTransitions . add ( transition ) ;
2921+
2922+ // Add the root transition's pending suspense boundary set to
2923+ // the queue's marker set. We will iterate through the marker
2924+ // set when we toggle state on the suspense boundary and
2925+ // add or remove the pending suspense boundaries as needed.
2926+ if ( ! rootIncompleteTransitions . has ( transition ) ) {
2927+ rootIncompleteTransitions . set ( transition , new Map ( ) ) ;
2928+ }
2929+ instance . pendingMarkers . add (
2930+ rootIncompleteTransitions . get ( transition ) ,
2931+ ) ;
29372932 } ) ;
29382933 }
29392934 }
2940- }
29412935
2942- commitTransitionProgress ( finishedRoot , finishedWork ) ;
2936+ commitTransitionProgress ( finishedWork ) ;
29432937
2944- finishedWork . updateQueue = null ;
2938+ if (
2939+ instance . pendingMarkers === null ||
2940+ instance . pendingMarkers . size === 0
2941+ ) {
2942+ finishedWork . updateQueue = null ;
2943+ }
2944+ }
29452945 }
29462946
29472947 break ;
0 commit comments