@samitouri / QOS-React-2 / commits / 7a4336c404

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 }