Use recursion to traverse during passive mount phase
This converts the layout phase to iterate over its effects recursively instead of iteratively. This makes it easier to track contextual information, like whether a fiber is inside a hidden tree. We already made this change for the mutation phase. See 481dece for more context.
Andrew Clark committed
Jul 12, 2022 at 15:02 UTC
7a4336c4040bb26d8fe143f96d842acae4c728b5
2 files changed
+112
-96
packages/react-reconciler/src/ReactFiberCommitWork.new.js
+56
-48
@@ -2843,70 +2843,37 @@ export function commitPassiveMountEffects(
2843
committedLanes: Lanes,
2844
committedTransitions: Array<Transition> | null,
2845
): void {
2846
- nextEffect = finishedWork;
2847
- commitPassiveMountEffects_begin(
2848
- finishedWork,
2846
+ setCurrentDebugFiberInDEV(finishedWork);
2847
+ commitPassiveMountOnFiber(
2848
root,
2849
+ finishedWork,
2850
committedLanes,
2851
committedTransitions,
2852
);
2853
+ resetCurrentDebugFiberInDEV();
2854
}
2855
2855
-function commitPassiveMountEffects_begin(
2856
- subtreeRoot: Fiber,
2856
+function recursivelyTraversePassiveMountEffects(
2857
root: FiberRoot,
2858
+ parentFiber: Fiber,
2859
committedLanes: Lanes,
2860
committedTransitions: Array<Transition> | null,
2861
) {
2861
- while (nextEffect !== null) {
2862
- const fiber = nextEffect;
2863
- const firstChild = fiber.child;
2864
- if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) {
2865
- firstChild.return = fiber;
2866
- nextEffect = firstChild;
2867
- } else {
2868
- commitPassiveMountEffects_complete(
2869
- subtreeRoot,
2862
+ const prevDebugFiber = getCurrentDebugFiberInDEV();
2863
+ if (parentFiber.subtreeFlags & PassiveMask) {
2864
+ let child = parentFiber.child;
2865
+ while (child !== null) {
2866
+ setCurrentDebugFiberInDEV(child);
2867
+ commitPassiveMountOnFiber(
2868
root,
2869
+ child,
2870
committedLanes,
2871
committedTransitions,
2872
);
2873
+ child = child.sibling;
2874
}
2875
}
2876
-}
2877
-
2878
-function commitPassiveMountEffects_complete(
2879
- subtreeRoot: Fiber,
2880
- root: FiberRoot,
2881
- committedLanes: Lanes,
2882
- committedTransitions: Array<Transition> | null,
2883
-) {
2884
- while (nextEffect !== null) {
2885
- const fiber = nextEffect;
2886
-
2887
- setCurrentDebugFiberInDEV(fiber);
2888
- commitPassiveMountOnFiber(
2889
- root,
2890
- fiber,
2891
- committedLanes,
2892
- committedTransitions,
2893
- );
2894
- resetCurrentDebugFiberInDEV();
2895
-
2896
- if (fiber === subtreeRoot) {
2897
- nextEffect = null;
2898
- return;
2899
- }
2900
-
2901
- const sibling = fiber.sibling;
2902
- if (sibling !== null) {
2903
- sibling.return = fiber.return;
2904
- nextEffect = sibling;
2905
- return;
2906
- }
2907
-
2908
- nextEffect = fiber.return;
2909
- }
2876
+ setCurrentDebugFiberInDEV(prevDebugFiber);
2877
}
2878
2879
function commitPassiveMountOnFiber(
@@ -2920,6 +2887,12 @@ function commitPassiveMountOnFiber(
2887
case FunctionComponent:
2888
case ForwardRef:
2889
case SimpleMemoComponent: {
2890
+ recursivelyTraversePassiveMountEffects(
2891
+ finishedRoot,
2892
+ finishedWork,
2893
+ committedLanes,
2894
+ committedTransitions,
2895
+ );
2896
if (flags & Passive) {
2897
if (
2898
enableProfilerTimer &&
@@ -2950,6 +2923,12 @@ function commitPassiveMountOnFiber(
2923
break;
2924
}
2925
case HostRoot: {
2926
+ recursivelyTraversePassiveMountEffects(
2927
+ finishedRoot,
2928
+ finishedWork,
2929
+ committedLanes,
2930
+ committedTransitions,
2931
+ );
2932
if (flags & Passive) {
2933
if (enableCache) {
2934
let previousCache: Cache | null = null;
@@ -3000,6 +2979,12 @@ function commitPassiveMountOnFiber(
2979
}
2980
case LegacyHiddenComponent:
2981
case OffscreenComponent: {
2982
+ recursivelyTraversePassiveMountEffects(
2983
+ finishedRoot,
2984
+ finishedWork,
2985
+ committedLanes,
2986
+ committedTransitions,
2987
+ );
2988
if (flags & Passive) {
2989
if (enableCache) {
2990
let previousCache: Cache | null = null;
@@ -3087,6 +3072,12 @@ function commitPassiveMountOnFiber(
3072
break;
3073
}
3074
case CacheComponent: {
3075
+ recursivelyTraversePassiveMountEffects(
3076
+ finishedRoot,
3077
+ finishedWork,
3078
+ committedLanes,
3079
+ committedTransitions,
3080
+ );
3081
if (flags & Passive) {
3082
if (enableCache) {
3083
let previousCache: Cache | null = null;
@@ -3111,6 +3102,12 @@ function commitPassiveMountOnFiber(
3102
}
3103
case TracingMarkerComponent: {
3104
if (enableTransitionTracing) {
3105
+ recursivelyTraversePassiveMountEffects(
3106
+ finishedRoot,
3107
+ finishedWork,
3108
+ committedLanes,
3109
+ committedTransitions,
3110
+ );
3111
if (flags & Passive) {
3112
// Get the transitions that were initiatized during the render
3113
// and add a start transition callback for each of them
@@ -3130,7 +3127,18 @@ function commitPassiveMountOnFiber(
3127
instance.pendingBoundaries = null;
3128
}
3129
}
3130
+ break;
3131
}
3132
+ // Intentional fallthrough to next branch
3133
+ }
3134
+ // eslint-disable-next-line-no-fallthrough
3135
+ default: {
3136
+ recursivelyTraversePassiveMountEffects(
3137
+ finishedRoot,
3138
+ finishedWork,
3139
+ committedLanes,
3140
+ committedTransitions,
3141
+ );
3142
break;
3143
}
3144
}
packages/react-reconciler/src/ReactFiberCommitWork.old.js
+56
-48
@@ -2843,70 +2843,37 @@ export function commitPassiveMountEffects(
2843
committedLanes: Lanes,
2844
committedTransitions: Array<Transition> | null,
2845
): void {
2846
- nextEffect = finishedWork;
2847
- commitPassiveMountEffects_begin(
2848
- finishedWork,
2846
+ setCurrentDebugFiberInDEV(finishedWork);
2847
+ commitPassiveMountOnFiber(
2848
root,
2849
+ finishedWork,
2850
committedLanes,
2851
committedTransitions,
2852
);
2853
+ resetCurrentDebugFiberInDEV();
2854
}
2855
2855
-function commitPassiveMountEffects_begin(
2856
- subtreeRoot: Fiber,
2856
+function recursivelyTraversePassiveMountEffects(
2857
root: FiberRoot,
2858
+ parentFiber: Fiber,
2859
committedLanes: Lanes,
2860
committedTransitions: Array<Transition> | null,
2861
) {
2861
- while (nextEffect !== null) {
2862
- const fiber = nextEffect;
2863
- const firstChild = fiber.child;
2864
- if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) {
2865
- firstChild.return = fiber;
2866
- nextEffect = firstChild;
2867
- } else {
2868
- commitPassiveMountEffects_complete(
2869
- subtreeRoot,
2862
+ const prevDebugFiber = getCurrentDebugFiberInDEV();
2863
+ if (parentFiber.subtreeFlags & PassiveMask) {
2864
+ let child = parentFiber.child;
2865
+ while (child !== null) {
2866
+ setCurrentDebugFiberInDEV(child);
2867
+ commitPassiveMountOnFiber(
2868
root,
2869
+ child,
2870
committedLanes,
2871
committedTransitions,
2872
);
2873
+ child = child.sibling;
2874
}
2875
}
2876
-}
2877
-
2878
-function commitPassiveMountEffects_complete(
2879
- subtreeRoot: Fiber,
2880
- root: FiberRoot,
2881
- committedLanes: Lanes,
2882
- committedTransitions: Array<Transition> | null,
2883
-) {
2884
- while (nextEffect !== null) {
2885
- const fiber = nextEffect;
2886
-
2887
- setCurrentDebugFiberInDEV(fiber);
2888
- commitPassiveMountOnFiber(
2889
- root,
2890
- fiber,
2891
- committedLanes,
2892
- committedTransitions,
2893
- );
2894
- resetCurrentDebugFiberInDEV();
2895
-
2896
- if (fiber === subtreeRoot) {
2897
- nextEffect = null;
2898
- return;
2899
- }
2900
-
2901
- const sibling = fiber.sibling;
2902
- if (sibling !== null) {
2903
- sibling.return = fiber.return;
2904
- nextEffect = sibling;
2905
- return;
2906
- }
2907
-
2908
- nextEffect = fiber.return;
2909
- }
2876
+ setCurrentDebugFiberInDEV(prevDebugFiber);
2877
}
2878
2879
function commitPassiveMountOnFiber(
@@ -2920,6 +2887,12 @@ function commitPassiveMountOnFiber(
2887
case FunctionComponent:
2888
case ForwardRef:
2889
case SimpleMemoComponent: {
2890
+ recursivelyTraversePassiveMountEffects(
2891
+ finishedRoot,
2892
+ finishedWork,
2893
+ committedLanes,
2894
+ committedTransitions,
2895
+ );
2896
if (flags & Passive) {
2897
if (
2898
enableProfilerTimer &&
@@ -2950,6 +2923,12 @@ function commitPassiveMountOnFiber(
2923
break;
2924
}
2925
case HostRoot: {
2926
+ recursivelyTraversePassiveMountEffects(
2927
+ finishedRoot,
2928
+ finishedWork,
2929
+ committedLanes,
2930
+ committedTransitions,
2931
+ );
2932
if (flags & Passive) {
2933
if (enableCache) {
2934
let previousCache: Cache | null = null;
@@ -3000,6 +2979,12 @@ function commitPassiveMountOnFiber(
2979
}
2980
case LegacyHiddenComponent:
2981
case OffscreenComponent: {
2982
+ recursivelyTraversePassiveMountEffects(
2983
+ finishedRoot,
2984
+ finishedWork,
2985
+ committedLanes,
2986
+ committedTransitions,
2987
+ );
2988
if (flags & Passive) {
2989
if (enableCache) {
2990
let previousCache: Cache | null = null;
@@ -3087,6 +3072,12 @@ function commitPassiveMountOnFiber(
3072
break;
3073
}
3074
case CacheComponent: {
3075
+ recursivelyTraversePassiveMountEffects(
3076
+ finishedRoot,
3077
+ finishedWork,
3078
+ committedLanes,
3079
+ committedTransitions,
3080
+ );
3081
if (flags & Passive) {
3082
if (enableCache) {
3083
let previousCache: Cache | null = null;
@@ -3111,6 +3102,12 @@ function commitPassiveMountOnFiber(
3102
}
3103
case TracingMarkerComponent: {
3104
if (enableTransitionTracing) {
3105
+ recursivelyTraversePassiveMountEffects(
3106
+ finishedRoot,
3107
+ finishedWork,
3108
+ committedLanes,
3109
+ committedTransitions,
3110
+ );
3111
if (flags & Passive) {
3112
// Get the transitions that were initiatized during the render
3113
// and add a start transition callback for each of them
@@ -3130,7 +3127,18 @@ function commitPassiveMountOnFiber(
3127
instance.pendingBoundaries = null;
3128
}
3129
}
3130
+ break;
3131
}
3132
+ // Intentional fallthrough to next branch
3133
+ }
3134
+ // eslint-disable-next-line-no-fallthrough
3135
+ default: {
3136
+ recursivelyTraversePassiveMountEffects(
3137
+ finishedRoot,
3138
+ finishedWork,
3139
+ committedLanes,
3140
+ committedTransitions,
3141
+ );
3142
break;
3143
}
3144
}