Remove wrong return pointer warning
I'm about to refactor part of the commit phase to use recursion instead of iteration. As part of that change, we will no longer assign the `return` pointer when traversing into a subtree. So I'm disabling the internal warning that fires if the return pointer is not consistent with the parent during the commit phase. I had originally added this warning to help prevent mistakes when traversing the tree iteratively, but since we're intentionally switching to recursion instead, we don't need it.
Andrew Clark committed
Apr 6, 2022 at 23:01 UTC
ea7b2ec2898c615f648aec30fcbcf73aed156583
3 files changed
+24
-103
packages/react-dom/src/__tests__/ReactWrongReturnPointer-test.js
-45
@@ -153,51 +153,6 @@ function resolveMostRecentTextCache(text) {
153
154
const resolveText = resolveMostRecentTextCache;
155
156
-// Don't feel too guilty if you have to delete this test.
157
-// @gate dfsEffectsRefactor
158
-// @gate __DEV__
159
-test('warns in DEV if return pointer is inconsistent', async () => {
160
- const {useRef, useLayoutEffect} = React;
161
-
162
- let ref = null;
163
- function App({text}) {
164
- ref = useRef(null);
165
- return (
166
- <>
167
- <Sibling text={text} />
168
- <div ref={ref}>{text}</div>
169
- </>
170
- );
171
- }
172
-
173
- function Sibling({text}) {
174
- useLayoutEffect(() => {
175
- if (text === 'B') {
176
- // Mutate the return pointer of the div to point to the wrong alternate.
177
- // This simulates the most common type of return pointer inconsistency.
178
- const current = ref.current.fiber;
179
- const workInProgress = current.alternate;
180
- workInProgress.return = current.return;
181
- }
182
- }, [text]);
183
- return null;
184
- }
185
-
186
- const root = ReactNoop.createRoot();
187
- await act(async () => {
188
- root.render(<App text="A" />);
189
- });
190
-
191
- spyOnDev(console, 'error');
192
- await act(async () => {
193
- root.render(<App text="B" />);
194
- });
195
- expect(console.error.calls.count()).toBe(1);
196
- expect(console.error.calls.argsFor(0)[0]).toMatch(
197
- 'Internal React error: Return pointer is inconsistent with parent.',
198
- );
199
-});
200
-
156
// @gate enableCache
157
// @gate enableSuspenseList
158
test('regression (#20932): return pointer is correct before entering deleted tree', async () => {
packages/react-reconciler/src/ReactFiberCommitWork.new.js
+12
-29
@@ -360,7 +360,7 @@ function commitBeforeMutationEffects_begin() {
360
(fiber.subtreeFlags & BeforeMutationMask) !== NoFlags &&
361
child !== null
362
) {
363
- ensureCorrectReturnPointer(child, fiber);
363
+ child.return = fiber;
364
nextEffect = child;
365
} else {
366
commitBeforeMutationEffects_complete();
@@ -382,7 +382,7 @@ function commitBeforeMutationEffects_complete() {
382
383
const sibling = fiber.sibling;
384
if (sibling !== null) {
385
- ensureCorrectReturnPointer(sibling, fiber.return);
385
+ sibling.return = fiber.return;
386
nextEffect = sibling;
387
return;
388
}
@@ -2185,7 +2185,7 @@ function commitMutationEffects_begin(root: FiberRoot, lanes: Lanes) {
2185
2186
const child = fiber.child;
2187
if ((fiber.subtreeFlags & MutationMask) !== NoFlags && child !== null) {
2188
- ensureCorrectReturnPointer(child, fiber);
2188
+ child.return = fiber;
2189
nextEffect = child;
2190
} else {
2191
commitMutationEffects_complete(root, lanes);
@@ -2207,7 +2207,7 @@ function commitMutationEffects_complete(root: FiberRoot, lanes: Lanes) {
2207
2208
const sibling = fiber.sibling;
2209
if (sibling !== null) {
2210
- ensureCorrectReturnPointer(sibling, fiber.return);
2210
+ sibling.return = fiber.return;
2211
nextEffect = sibling;
2212
return;
2213
}
@@ -2425,7 +2425,7 @@ function commitLayoutEffects_begin(
2425
}
2426
2427
if ((fiber.subtreeFlags & LayoutMask) !== NoFlags && firstChild !== null) {
2428
- ensureCorrectReturnPointer(firstChild, fiber);
2428
+ firstChild.return = fiber;
2429
nextEffect = firstChild;
2430
} else {
2431
commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes);
@@ -2459,7 +2459,7 @@ function commitLayoutMountEffects_complete(
2459
2460
const sibling = fiber.sibling;
2461
if (sibling !== null) {
2462
- ensureCorrectReturnPointer(sibling, fiber.return);
2462
+ sibling.return = fiber.return;
2463
nextEffect = sibling;
2464
return;
2465
}
@@ -2628,7 +2628,7 @@ function commitPassiveMountEffects_begin(
2628
const fiber = nextEffect;
2629
const firstChild = fiber.child;
2630
if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) {
2631
- ensureCorrectReturnPointer(firstChild, fiber);
2631
+ firstChild.return = fiber;
2632
nextEffect = firstChild;
2633
} else {
2634
commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes);
@@ -2662,7 +2662,7 @@ function commitPassiveMountEffects_complete(
2662
2663
const sibling = fiber.sibling;
2664
if (sibling !== null) {
2665
- ensureCorrectReturnPointer(sibling, fiber.return);
2665
+ sibling.return = fiber.return;
2666
nextEffect = sibling;
2667
return;
2668
}
@@ -2849,7 +2849,7 @@ function commitPassiveUnmountEffects_begin() {
2849
}
2850
2851
if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && child !== null) {
2852
- ensureCorrectReturnPointer(child, fiber);
2852
+ child.return = fiber;
2853
nextEffect = child;
2854
} else {
2855
commitPassiveUnmountEffects_complete();
@@ -2868,7 +2868,7 @@ function commitPassiveUnmountEffects_complete() {
2868
2869
const sibling = fiber.sibling;
2870
if (sibling !== null) {
2871
- ensureCorrectReturnPointer(sibling, fiber.return);
2871
+ sibling.return = fiber.return;
2872
nextEffect = sibling;
2873
return;
2874
}
@@ -2923,7 +2923,7 @@ function commitPassiveUnmountEffectsInsideOfDeletedTree_begin(
2923
// TODO: Only traverse subtree if it has a PassiveStatic flag. (But, if we
2924
// do this, still need to handle `deletedTreeCleanUpLevel` correctly.)
2925
if (child !== null) {
2926
- ensureCorrectReturnPointer(child, fiber);
2926
+ child.return = fiber;
2927
nextEffect = child;
2928
} else {
2929
commitPassiveUnmountEffectsInsideOfDeletedTree_complete(
@@ -2961,7 +2961,7 @@ function commitPassiveUnmountEffectsInsideOfDeletedTree_complete(
2961
}
2962
2963
if (sibling !== null) {
2964
- ensureCorrectReturnPointer(sibling, returnFiber);
2964
+ sibling.return = returnFiber;
2965
nextEffect = sibling;
2966
return;
2967
}
@@ -3039,23 +3039,6 @@ function commitPassiveUnmountInsideDeletedTreeOnFiber(
3039
}
3040
}
3041
3042
-let didWarnWrongReturnPointer = false;
3043
-function ensureCorrectReturnPointer(fiber, expectedReturnFiber) {
3044
- if (__DEV__) {
3045
- if (!didWarnWrongReturnPointer && fiber.return !== expectedReturnFiber) {
3046
- didWarnWrongReturnPointer = true;
3047
- console.error(
3048
- 'Internal React error: Return pointer is inconsistent ' +
3049
- 'with parent.',
3050
- );
3051
- }
3052
- }
3053
-
3054
- // TODO: Remove this assignment once we're confident that it won't break
3055
- // anything, by checking the warning logs for the above invariant
3056
- fiber.return = expectedReturnFiber;
3057
-}
3058
-
3042
// TODO: Reuse reappearLayoutEffects traversal here?
3043
function invokeLayoutEffectMountInDEV(fiber: Fiber): void {
3044
if (__DEV__ && enableStrictEffects) {
packages/react-reconciler/src/ReactFiberCommitWork.old.js
+12
-29
@@ -360,7 +360,7 @@ function commitBeforeMutationEffects_begin() {
360
(fiber.subtreeFlags & BeforeMutationMask) !== NoFlags &&
361
child !== null
362
) {
363
- ensureCorrectReturnPointer(child, fiber);
363
+ child.return = fiber;
364
nextEffect = child;
365
} else {
366
commitBeforeMutationEffects_complete();
@@ -382,7 +382,7 @@ function commitBeforeMutationEffects_complete() {
382
383
const sibling = fiber.sibling;
384
if (sibling !== null) {
385
- ensureCorrectReturnPointer(sibling, fiber.return);
385
+ sibling.return = fiber.return;
386
nextEffect = sibling;
387
return;
388
}
@@ -2185,7 +2185,7 @@ function commitMutationEffects_begin(root: FiberRoot, lanes: Lanes) {
2185
2186
const child = fiber.child;
2187
if ((fiber.subtreeFlags & MutationMask) !== NoFlags && child !== null) {
2188
- ensureCorrectReturnPointer(child, fiber);
2188
+ child.return = fiber;
2189
nextEffect = child;
2190
} else {
2191
commitMutationEffects_complete(root, lanes);
@@ -2207,7 +2207,7 @@ function commitMutationEffects_complete(root: FiberRoot, lanes: Lanes) {
2207
2208
const sibling = fiber.sibling;
2209
if (sibling !== null) {
2210
- ensureCorrectReturnPointer(sibling, fiber.return);
2210
+ sibling.return = fiber.return;
2211
nextEffect = sibling;
2212
return;
2213
}
@@ -2425,7 +2425,7 @@ function commitLayoutEffects_begin(
2425
}
2426
2427
if ((fiber.subtreeFlags & LayoutMask) !== NoFlags && firstChild !== null) {
2428
- ensureCorrectReturnPointer(firstChild, fiber);
2428
+ firstChild.return = fiber;
2429
nextEffect = firstChild;
2430
} else {
2431
commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes);
@@ -2459,7 +2459,7 @@ function commitLayoutMountEffects_complete(
2459
2460
const sibling = fiber.sibling;
2461
if (sibling !== null) {
2462
- ensureCorrectReturnPointer(sibling, fiber.return);
2462
+ sibling.return = fiber.return;
2463
nextEffect = sibling;
2464
return;
2465
}
@@ -2628,7 +2628,7 @@ function commitPassiveMountEffects_begin(
2628
const fiber = nextEffect;
2629
const firstChild = fiber.child;
2630
if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) {
2631
- ensureCorrectReturnPointer(firstChild, fiber);
2631
+ firstChild.return = fiber;
2632
nextEffect = firstChild;
2633
} else {
2634
commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes);
@@ -2662,7 +2662,7 @@ function commitPassiveMountEffects_complete(
2662
2663
const sibling = fiber.sibling;
2664
if (sibling !== null) {
2665
- ensureCorrectReturnPointer(sibling, fiber.return);
2665
+ sibling.return = fiber.return;
2666
nextEffect = sibling;
2667
return;
2668
}
@@ -2849,7 +2849,7 @@ function commitPassiveUnmountEffects_begin() {
2849
}
2850
2851
if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && child !== null) {
2852
- ensureCorrectReturnPointer(child, fiber);
2852
+ child.return = fiber;
2853
nextEffect = child;
2854
} else {
2855
commitPassiveUnmountEffects_complete();
@@ -2868,7 +2868,7 @@ function commitPassiveUnmountEffects_complete() {
2868
2869
const sibling = fiber.sibling;
2870
if (sibling !== null) {
2871
- ensureCorrectReturnPointer(sibling, fiber.return);
2871
+ sibling.return = fiber.return;
2872
nextEffect = sibling;
2873
return;
2874
}
@@ -2923,7 +2923,7 @@ function commitPassiveUnmountEffectsInsideOfDeletedTree_begin(
2923
// TODO: Only traverse subtree if it has a PassiveStatic flag. (But, if we
2924
// do this, still need to handle `deletedTreeCleanUpLevel` correctly.)
2925
if (child !== null) {
2926
- ensureCorrectReturnPointer(child, fiber);
2926
+ child.return = fiber;
2927
nextEffect = child;
2928
} else {
2929
commitPassiveUnmountEffectsInsideOfDeletedTree_complete(
@@ -2961,7 +2961,7 @@ function commitPassiveUnmountEffectsInsideOfDeletedTree_complete(
2961
}
2962
2963
if (sibling !== null) {
2964
- ensureCorrectReturnPointer(sibling, returnFiber);
2964
+ sibling.return = returnFiber;
2965
nextEffect = sibling;
2966
return;
2967
}
@@ -3039,23 +3039,6 @@ function commitPassiveUnmountInsideDeletedTreeOnFiber(
3039
}
3040
}
3041
3042
-let didWarnWrongReturnPointer = false;
3043
-function ensureCorrectReturnPointer(fiber, expectedReturnFiber) {
3044
- if (__DEV__) {
3045
- if (!didWarnWrongReturnPointer && fiber.return !== expectedReturnFiber) {
3046
- didWarnWrongReturnPointer = true;
3047
- console.error(
3048
- 'Internal React error: Return pointer is inconsistent ' +
3049
- 'with parent.',
3050
- );
3051
- }
3052
- }
3053
-
3054
- // TODO: Remove this assignment once we're confident that it won't break
3055
- // anything, by checking the warning logs for the above invariant
3056
- fiber.return = expectedReturnFiber;
3057
-}
3058
-
3042
// TODO: Reuse reappearLayoutEffects traversal here?
3043
function invokeLayoutEffectMountInDEV(fiber: Fiber): void {
3044
if (__DEV__ && enableStrictEffects) {