@@ -22,7 +22,10 @@ import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
22
22
import type { UpdateQueue } from './ReactUpdateQueue.new' ;
23
23
import type { FunctionComponentUpdateQueue } from './ReactFiberHooks.new' ;
24
24
import type { Wakeable } from 'shared/ReactTypes' ;
25
- import type { OffscreenState } from './ReactFiberOffscreenComponent' ;
25
+ import type {
26
+ OffscreenState ,
27
+ OffscreenInstance ,
28
+ } from './ReactFiberOffscreenComponent' ;
26
29
import type { HookFlags } from './ReactHookEffectTags' ;
27
30
import type { Cache } from './ReactFiberCacheComponent.new' ;
28
31
import type { RootState } from './ReactFiberRoot.new' ;
@@ -1072,68 +1075,80 @@ function commitTransitionProgress(
1072
1075
finishedRoot : FiberRoot ,
1073
1076
offscreenFiber : Fiber ,
1074
1077
) {
1075
- // This function adds suspense boundaries to the root
1076
- // or tracing marker's pendingSuspenseBoundaries map.
1077
- // When a suspense boundary goes from a resolved to a fallback
1078
- // state we add the boundary to the map, and when it goes from
1079
- // a fallback to a resolved state, we remove the boundary from
1080
- // the map.
1081
-
1082
- // We use stateNode on the Offscreen component as a stable object
1083
- // that doesnt change from render to render. This way we can
1084
- // distinguish between different Offscreen instances (vs. the same
1085
- // Offscreen instance with different fibers)
1086
- const offscreenInstance : OffscreenInstance = offscreenFiber . stateNode ;
1087
-
1088
- let prevState : SuspenseState | null = null ;
1089
- const previousFiber = offscreenFiber . alternate ;
1090
- if ( previousFiber !== null && previousFiber . memoizedState !== null ) {
1091
- prevState = previousFiber . memoizedState ;
1092
- }
1093
- const nextState : SuspenseState | null = offscreenFiber . memoizedState ;
1094
-
1095
- const wasHidden = prevState !== null ;
1096
- const isHidden = nextState !== null ;
1097
-
1098
- const rootState : RootState = finishedRoot . current . memoizedState ;
1099
- // TODO(luna) move pendingSuspenseBoundaries and transitions from
1100
- // HostRoot fiber to FiberRoot
1101
- const rootPendingBoundaries = rootState . pendingSuspenseBoundaries ;
1102
-
1103
- // If there is a name on the suspense boundary, store that in
1104
- // the pending boundaries.
1105
- let name = null ;
1106
- const parent = offscreenFiber . return ;
1107
- if (
1108
- parent !== null &&
1109
- parent . tag === SuspenseComponent &&
1110
- parent . memoizedProps . unstable_name
1111
- ) {
1112
- name = parent . memoizedProps . unstable_name ;
1113
- }
1078
+ if ( enableTransitionTracing ) {
1079
+ // This function adds suspense boundaries to the root
1080
+ // or tracing marker's pendingSuspenseBoundaries map.
1081
+ // When a suspense boundary goes from a resolved to a fallback
1082
+ // state we add the boundary to the map, and when it goes from
1083
+ // a fallback to a resolved state, we remove the boundary from
1084
+ // the map.
1085
+
1086
+ // We use stateNode on the Offscreen component as a stable object
1087
+ // that doesnt change from render to render. This way we can
1088
+ // distinguish between different Offscreen instances (vs. the same
1089
+ // Offscreen instance with different fibers)
1090
+ const offscreenInstance : OffscreenInstance = offscreenFiber . stateNode ;
1091
+
1092
+ let prevState : SuspenseState | null = null ;
1093
+ const previousFiber = offscreenFiber . alternate ;
1094
+ if ( previousFiber !== null && previousFiber . memoizedState !== null ) {
1095
+ prevState = previousFiber . memoizedState ;
1096
+ }
1097
+ const nextState : SuspenseState | null = offscreenFiber . memoizedState ;
1098
+
1099
+ const wasHidden = prevState !== null ;
1100
+ const isHidden = nextState !== null ;
1101
+
1102
+ const rootState : RootState = finishedRoot . current . memoizedState ;
1103
+ // TODO(luna) move pendingSuspenseBoundaries and transitions from
1104
+ // HostRoot fiber to FiberRoot
1105
+ const rootPendingBoundaries = rootState . pendingSuspenseBoundaries ;
1106
+ const rootTransitions = rootState . transitions ;
1107
+
1108
+ // If there is a name on the suspense boundary, store that in
1109
+ // the pending boundaries.
1110
+ let name = null ;
1111
+ const parent = offscreenFiber . return ;
1112
+ if (
1113
+ parent !== null &&
1114
+ parent . tag === SuspenseComponent &&
1115
+ parent . memoizedProps . unstable_name
1116
+ ) {
1117
+ name = parent . memoizedProps . unstable_name ;
1118
+ }
1114
1119
1115
- if ( rootPendingBoundaries !== null ) {
1116
- if ( previousFiber === null ) {
1117
- // Initial mount
1118
- if ( isHidden ) {
1119
- rootPendingBoundaries . set ( offscreenInstance , {
1120
- name,
1121
- } ) ;
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 ) ;
1120
+ if ( rootPendingBoundaries !== null ) {
1121
+ if ( previousFiber === null ) {
1122
+ // Initial mount
1123
+ if ( isHidden ) {
1124
+ rootPendingBoundaries . set ( offscreenInstance , {
1125
+ name,
1126
+ } ) ;
1127
+ }
1128
+ } else {
1129
+ if ( wasHidden && ! isHidden ) {
1130
+ // The suspense boundary went from hidden to visible. Remove
1131
+ // the boundary from the pending suspense boundaries set
1132
+ // if it's there
1133
+ if ( rootPendingBoundaries . has ( offscreenInstance ) ) {
1134
+ rootPendingBoundaries . delete ( offscreenInstance ) ;
1135
+
1136
+ if ( rootPendingBoundaries . size === 0 && rootTransitions !== null ) {
1137
+ rootTransitions . forEach ( transition => {
1138
+ addTransitionCompleteCallbackToPendingTransition ( {
1139
+ transitionName : transition . name ,
1140
+ startTime : transition . startTime ,
1141
+ } ) ;
1142
+ } ) ;
1143
+ }
1144
+ }
1145
+ } else if ( ! wasHidden && isHidden ) {
1146
+ // The suspense boundaries was just hidden. Add the boundary
1147
+ // to the pending boundary set if it's there
1148
+ rootPendingBoundaries . set ( offscreenInstance , {
1149
+ name,
1150
+ } ) ;
1130
1151
}
1131
- } else if ( ! wasHidden && isHidden ) {
1132
- // The suspense boundaries was just hidden. Add the boundary
1133
- // to the pending boundary set if it's there
1134
- rootPendingBoundaries . set ( offscreenInstance , {
1135
- name,
1136
- } ) ;
1137
1152
}
1138
1153
}
1139
1154
}
@@ -2823,12 +2838,15 @@ function commitPassiveMountOnFiber(
2823
2838
// Get the transitions that were initiatized during the render
2824
2839
// and add a start transition callback for each of them
2825
2840
const state = finishedWork . memoizedState ;
2841
+ // TODO Since it's a mutable field, this should live on the FiberRoot
2826
2842
if ( state . transitions === null ) {
2827
2843
state . transitions = new Set ( [ ] ) ;
2828
2844
}
2829
2845
const pendingTransitions = state . transitions ;
2846
+ const pendingSuspenseBoundaries = state . pendingSuspenseBoundaries ;
2830
2847
2831
- if ( committedTransitions != null ) {
2848
+ // Initial render
2849
+ if ( committedTransitions !== null ) {
2832
2850
committedTransitions . forEach ( transition => {
2833
2851
addTransitionStartCallbackToPendingTransition ( {
2834
2852
transitionName : transition . name ,
@@ -2837,28 +2855,20 @@ function commitPassiveMountOnFiber(
2837
2855
pendingTransitions . add ( transition ) ;
2838
2856
} ) ;
2839
2857
2840
- clearTransitionsForLanes ( finishedRoot , committedLanes ) ;
2841
- }
2842
-
2843
- const pendingSuspenseBoundaries = state . pendingSuspenseBoundaries ;
2844
- const processedTransitions = new Set ( ) ;
2845
- // process the lazy transitions list by filtering duplicate transitions
2846
- // and calling the transition complete callback on all transitions
2847
- // if there are no more pending suspense boundaries
2848
- pendingTransitions . forEach ( transition => {
2849
- if ( ! processedTransitions . has ( transition ) ) {
2850
- if (
2851
- pendingSuspenseBoundaries === null ||
2852
- pendingSuspenseBoundaries . size === 0
2853
- ) {
2858
+ if (
2859
+ pendingSuspenseBoundaries === null ||
2860
+ pendingSuspenseBoundaries . size === 0
2861
+ ) {
2862
+ pendingTransitions . forEach ( transition => {
2854
2863
addTransitionCompleteCallbackToPendingTransition ( {
2855
2864
transitionName : transition . name ,
2856
2865
startTime : transition . startTime ,
2857
2866
} ) ;
2858
- }
2859
- processedTransitions . add ( transition ) ;
2867
+ } ) ;
2860
2868
}
2861
- } ) ;
2869
+
2870
+ clearTransitionsForLanes ( finishedRoot , committedLanes ) ;
2871
+ }
2862
2872
2863
2873
// If there are no more pending suspense boundaries we
2864
2874
// clear the transitions because they are all complete.
@@ -2922,7 +2932,7 @@ function commitPassiveMountOnFiber(
2922
2932
// Add all the transitions saved in the update queue during
2923
2933
// the render phase (ie the transitions associated with this boundary)
2924
2934
// into the transitions set.
2925
- if ( transitions != null ) {
2935
+ if ( transitions !== null ) {
2926
2936
if ( prevTransitions === null ) {
2927
2937
// We only have one instance of the transitions set
2928
2938
// because we update it only during the commit phase. We
0 commit comments