@@ -1066,10 +1066,7 @@ function reappearLayoutEffectsOnFiber(node: Fiber) {
1066
1066
}
1067
1067
}
1068
1068
1069
- function commitTransitionProgress (
1070
- finishedRoot : FiberRoot ,
1071
- offscreenFiber : Fiber ,
1072
- ) {
1069
+ function commitTransitionProgress ( offscreenFiber : Fiber ) {
1073
1070
if ( enableTransitionTracing ) {
1074
1071
// This function adds suspense boundaries to the root
1075
1072
// or tracing marker's pendingSuspenseBoundaries map.
@@ -1094,12 +1091,7 @@ function commitTransitionProgress(
1094
1091
const wasHidden = prevState !== null ;
1095
1092
const isHidden = nextState !== null ;
1096
1093
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 ;
1103
1095
// If there is a name on the suspense boundary, store that in
1104
1096
// the pending boundaries.
1105
1097
let name = null ;
@@ -1112,38 +1104,26 @@ function commitTransitionProgress(
1112
1104
name = parent . memoizedProps . unstable_name ;
1113
1105
}
1114
1106
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 , {
1120
1113
name,
1121
1114
} ) ;
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 ) ;
1139
1125
}
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
+ } ) ;
1147
1127
}
1148
1128
}
1149
1129
}
@@ -2830,45 +2810,46 @@ function commitPassiveMountOnFiber(
2830
2810
// Get the transitions that were initiatized during the render
2831
2811
// and add a start transition callback for each of them
2832
2812
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 ;
2840
2814
// Initial render
2841
2815
if ( committedTransitions !== null ) {
2816
+ if ( state . incompleteTransitions === null ) {
2817
+ state . incompleteTransitions = incompleteTransitions = new Map ( ) ;
2818
+ }
2819
+
2842
2820
committedTransitions . forEach ( transition => {
2843
2821
addTransitionStartCallbackToPendingTransition ( {
2844
2822
transitionName : transition . name ,
2845
2823
startTime : transition . startTime ,
2846
2824
} ) ;
2847
- pendingTransitions . add ( transition ) ;
2825
+
2826
+ if ( ! incompleteTransitions . has ( transition ) ) {
2827
+ incompleteTransitions . set ( transition , null ) ;
2828
+ }
2848
2829
} ) ;
2849
2830
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 ) {
2855
2837
addTransitionCompleteCallbackToPendingTransition ( {
2856
2838
transitionName : transition . name ,
2857
2839
startTime : transition . startTime ,
2858
2840
} ) ;
2859
- } ) ;
2860
- }
2861
-
2862
- clearTransitionsForLanes ( finishedRoot , committedLanes ) ;
2841
+ incompleteTransitions . delete ( transition ) ;
2842
+ }
2843
+ } ) ;
2863
2844
}
2864
2845
2865
2846
// If there are no more pending suspense boundaries we
2866
2847
// clear the transitions because they are all complete.
2867
2848
if (
2868
- pendingSuspenseBoundaries === null ||
2869
- pendingSuspenseBoundaries . size === 0
2849
+ incompleteTransitions === null ||
2850
+ incompleteTransitions . size === 0
2870
2851
) {
2871
- state . transitions = null ;
2852
+ state . incompleteTransitions = null ;
2872
2853
}
2873
2854
}
2874
2855
break ;
@@ -2909,39 +2890,59 @@ function commitPassiveMountOnFiber(
2909
2890
const isFallback = finishedWork . memoizedState ;
2910
2891
const queue = ( finishedWork . updateQueue : any ) ;
2911
2892
const rootMemoizedState = finishedRoot . current . memoizedState ;
2893
+ const instance = finishedWork . stateNode ;
2912
2894
2913
2895
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
-
2921
2896
if ( isFallback ) {
2922
2897
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
+ // TODO(luna): Move this to the fiber root
2907
+ rootMemoizedState . incompleteTransitions = rootIncompleteTransitions = new Map ( ) ;
2908
+ }
2909
+ if ( instance . pendingMarkers === null ) {
2910
+ instance . pendingMarkers = new Set ( ) ;
2911
+ }
2912
+ if ( transitions !== null && prevTransitions === null ) {
2913
+ instance . transitions = prevTransitions = new Set ( ) ;
2914
+ }
2934
2915
2916
+ if ( transitions !== null ) {
2935
2917
transitions . forEach ( transition => {
2918
+ // Add all the transitions saved in the update queue during
2919
+ // the render phase (ie the transitions associated with this boundary)
2920
+ // into the transitions set.
2936
2921
prevTransitions . add ( transition ) ;
2922
+
2923
+ // Add the root transition's pending suspense boundary set to
2924
+ // the queue's marker set. We will iterate through the marker
2925
+ // set when we toggle state on the suspense boundary and
2926
+ // add or remove the pending suspense boundaries as needed.
2927
+ if ( ! rootIncompleteTransitions . has ( transition ) ) {
2928
+ rootIncompleteTransitions . set ( transition , new Map ( ) ) ;
2929
+ }
2930
+ instance . pendingMarkers . add (
2931
+ rootIncompleteTransitions . get ( transition ) ,
2932
+ ) ;
2937
2933
} ) ;
2938
2934
}
2939
2935
}
2940
- }
2941
2936
2942
- commitTransitionProgress ( finishedRoot , finishedWork ) ;
2937
+ commitTransitionProgress ( finishedWork ) ;
2943
2938
2944
- finishedWork . updateQueue = null ;
2939
+ if (
2940
+ instance . pendingMarkers === null ||
2941
+ instance . pendingMarkers . size === 0
2942
+ ) {
2943
+ finishedWork . updateQueue = null ;
2944
+ }
2945
+ }
2945
2946
}
2946
2947
2947
2948
break ;
0 commit comments