1066
}
1067
}
1068
1069
-function commitTransitionProgress(
1070
- finishedRoot: FiberRoot,
1071
- offscreenFiber: Fiber,
1072
-) {
1069
+function commitTransitionProgress(offscreenFiber: Fiber) {
1070
if (enableTransitionTracing) {
1071
// This function adds suspense boundaries to the root
1072
// or tracing marker's pendingSuspenseBoundaries map.
1091
const wasHidden = prevState !== null;
1092
const isHidden = nextState !== null;
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;
1095
// If there is a name on the suspense boundary, store that in
1096
// the pending boundaries.
1097
let name = null;
1104
name = parent.memoizedProps.unstable_name;
1105
}
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, {
1113
name,
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);
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
+ });
1127
}
1128
}
1129
}
2810
// Get the transitions that were initiatized during the render
2811
// and add a start transition callback for each of them
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;
2814
// Initial render
2815
if (committedTransitions !== null) {
2816
+ if (state.incompleteTransitions === null) {
2817
+ state.incompleteTransitions = incompleteTransitions = new Map();
2818
+ }
2819
+
2820
committedTransitions.forEach(transition => {
2821
addTransitionStartCallbackToPendingTransition({
2822
transitionName: transition.name,
2823
startTime: transition.startTime,
2824
});
2847
- pendingTransitions.add(transition);
2825
+
2826
+ if (!incompleteTransitions.has(transition)) {
2827
+ incompleteTransitions.set(transition, null);
2828
+ }
2829
});
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) {
2837
addTransitionCompleteCallbackToPendingTransition({
2838
transitionName: transition.name,
2839
startTime: transition.startTime,
2840
});
2859
- });
2860
- }
2861
-
2862
- clearTransitionsForLanes(finishedRoot, committedLanes);
2841
+ incompleteTransitions.delete(transition);
2842
+ }
2843
+ });
2844
}
2845
2846
// If there are no more pending suspense boundaries we
2847
// clear the transitions because they are all complete.
2848
if (
2868
- pendingSuspenseBoundaries === null ||
2869
- pendingSuspenseBoundaries.size === 0
2849
+ incompleteTransitions === null ||
2850
+ incompleteTransitions.size === 0
2851
) {
2871
- state.transitions = null;
2852
+ state.incompleteTransitions = null;
2853
}
2854
}
2855
break;
2890
const isFallback = finishedWork.memoizedState;
2891
const queue = (finishedWork.updateQueue: any);
2892
const rootMemoizedState = finishedRoot.current.memoizedState;
2893
+ const instance = finishedWork.stateNode;
2894
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
-
2896
if (isFallback) {
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
+ }
2915
2916
+ if (transitions !== null) {
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.
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
+ );
2933
});
2934
}
2935
}
2940
- }
2936
2942
- commitTransitionProgress(finishedRoot, finishedWork);
2937
+ commitTransitionProgress(finishedWork);
2938
2944
- finishedWork.updateQueue = null;
2939
+ if (
2940
+ instance.pendingMarkers === null ||
2941
+ instance.pendingMarkers.size === 0
2942
+ ) {
2943
+ finishedWork.updateQueue = null;
2944
+ }
2945
+ }
2946
}
2947
2948
break;