Skip to content

Commit c536679

Browse files
author
Brian Vaughn
committed
More cleanup of passive effects TODOs
* Re-added sibling/return/child fiber detaches. * Clear deletions array properly after mutation or passive effects
1 parent 42f8426 commit c536679

File tree

2 files changed

+37
-28
lines changed

2 files changed

+37
-28
lines changed

packages/react-reconciler/src/ReactFiberCommitWork.new.js

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -881,17 +881,10 @@ function commitUnmount(
881881
if ((tag & HookPassive) !== NoHookEffect) {
882882
effect.tag |= HookHasEffect;
883883

884-
// subtreeTags currently bubble in resetChildLanes which doens't get called for unmounted subtrees.
885-
// So we need to bubble this up manually to the root (or to the nearest ancestor that already has it).
884+
// subtreeTags bubble in resetChildLanes which doens't get called for unmounted subtrees.
885+
// So in the case of unmounts, we need to bubble passive effects explicitly.
886886
let ancestor = current.return;
887887
while (ancestor !== null) {
888-
if (
889-
(ancestor.subtreeTag & PassiveSubtreeTag) !==
890-
NoSubtreeTag
891-
) {
892-
break;
893-
}
894-
895888
ancestor.subtreeTag |= PassiveSubtreeTag;
896889
const alternate = ancestor.alternate;
897890
if (alternate !== null) {
@@ -1035,8 +1028,11 @@ function commitNestedUnmounts(
10351028
}
10361029

10371030
function detachFiberMutation(fiber: Fiber) {
1038-
// Cut off the return pointers to disconnect it from the tree. Ideally, we
1039-
// should clear the child pointer of the parent alternate to let this
1031+
// Cut off the return pointers to disconnect it from the tree.
1032+
// Note that we can't clear child or sibling pointers yet,
1033+
// because they may be required for passive effects.
1034+
// These pointers will be cleared in a separate pass.
1035+
// Ideally, we should clear the child pointer of the parent alternate to let this
10401036
// get GC:ed but we don't know which for sure which parent is the current
10411037
// one so we'll settle for GC:ing the subtree of this child. This child
10421038
// itself will be GC:ed when the parent updates the next time.
@@ -1045,8 +1041,6 @@ function detachFiberMutation(fiber: Fiber) {
10451041
// traversal in a later effect. See PR #16820. We now clear the sibling
10461042
// field after effects, see: detachFiberAfterEffects.
10471043
fiber.alternate = null;
1048-
// TODO (effects) Don't clear this yet because Passive effects might need it.
1049-
//fiber.child = null;
10501044
fiber.dependencies = null;
10511045
fiber.firstEffect = null;
10521046
fiber.lastEffect = null;
@@ -1055,8 +1049,6 @@ function detachFiberMutation(fiber: Fiber) {
10551049
fiber.pendingProps = null;
10561050
fiber.return = null;
10571051
fiber.stateNode = null;
1058-
// TODO (effects) Don't clear this yet because Passive effects might need it.
1059-
//fiber.updateQueue = null;
10601052
if (__DEV__) {
10611053
fiber._debugOwner = null;
10621054
}

packages/react-reconciler/src/ReactFiberWorkLoop.new.js

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2406,15 +2406,16 @@ function commitMutationEffects(
24062406
) {
24072407
let fiber = firstChild;
24082408
while (fiber !== null) {
2409-
if (fiber.deletions !== null) {
2410-
commitMutationEffectsDeletions(
2411-
fiber.deletions,
2412-
root,
2413-
renderPriorityLevel,
2414-
);
2409+
const deletions = fiber.deletions;
2410+
if (deletions !== null) {
2411+
commitMutationEffectsDeletions(deletions, root, renderPriorityLevel);
24152412

2416-
// TODO (effects) Detach sibling pointers for deleted Fibers
2417-
// TODO (effects) Clear deletion arrays
2413+
// If there are no pending passive effects, clear the deletions Array.
2414+
const primaryEffectTag = fiber.effectTag & PassiveMask;
2415+
const primarySubtreeTag = fiber.subtreeTag & PassiveSubtreeTag;
2416+
if (primaryEffectTag === NoEffect && primarySubtreeTag === NoSubtreeTag) {
2417+
fiber.deletions = null;
2418+
}
24182419
}
24192420

24202421
if (fiber.child !== null) {
@@ -2548,7 +2549,13 @@ function commitMutationEffectsDeletions(
25482549
captureCommitPhaseError(childToDelete, error);
25492550
}
25502551
}
2551-
// Don't clear the Deletion effect yet; we also use it to know when we need to detach refs later.
2552+
2553+
// If there are no pending passive effects, it's safe to detach remaining pointers now.
2554+
const primarySubtreeTag = childToDelete.subtreeTag & PassiveSubtreeTag;
2555+
const primaryEffectTag = childToDelete.effectTag & PassiveMask;
2556+
if (primarySubtreeTag === NoSubtreeTag && primaryEffectTag === NoEffect) {
2557+
detachFiberAfterEffects(childToDelete);
2558+
}
25522559
}
25532560
}
25542561

@@ -2777,15 +2784,21 @@ function flushPassiveUnmountEffects(firstChild: Fiber): void {
27772784
for (let i = 0; i < deletions.length; i++) {
27782785
const fiberToDelete = deletions[i];
27792786
// If this fiber (or anything below it) has passive effects then traverse the subtree.
2780-
const primaryEffectTag = fiberToDelete.effectTag & (Passive | Update);
2787+
const primaryEffectTag = fiberToDelete.effectTag & PassiveMask;
27812788
const primarySubtreeTag = fiberToDelete.subtreeTag & PassiveSubtreeTag;
27822789
if (
27832790
primarySubtreeTag !== NoSubtreeTag ||
27842791
primaryEffectTag !== NoEffect
27852792
) {
27862793
flushPassiveUnmountEffects(fiberToDelete);
27872794
}
2795+
2796+
// Now that passive effects have been processed, it's safe to detach lingering pointers.
2797+
detachFiberAfterEffects(fiberToDelete);
27882798
}
2799+
2800+
// Clear deletions now that passive effects have been procssed.
2801+
fiber.deletions = null;
27892802
}
27902803

27912804
const didBailout =
@@ -2809,7 +2822,7 @@ function flushPassiveUnmountEffects(firstChild: Fiber): void {
28092822
case ForwardRef:
28102823
case SimpleMemoComponent:
28112824
case Block: {
2812-
const primaryEffectTag = fiber.effectTag & (Passive | Update);
2825+
const primaryEffectTag = fiber.effectTag & PassiveMask;
28132826
if (primaryEffectTag !== NoEffect) {
28142827
flushPassiveUnmountEffectsImpl(fiber);
28152828
}
@@ -2934,8 +2947,6 @@ function flushPassiveEffectsImpl() {
29342947
flushPassiveUnmountEffects(root.current);
29352948
flushPassiveMountEffects(root.current);
29362949

2937-
// TODO (effects) Detach sibling pointers for deleted Fibers
2938-
29392950
if (enableProfilerTimer && enableProfilerCommitHooks) {
29402951
const profilerEffects = pendingPassiveProfilerEffects;
29412952
pendingPassiveProfilerEffects = [];
@@ -4034,3 +4045,9 @@ export function act(callback: () => Thenable<mixed>): Thenable<void> {
40344045
};
40354046
}
40364047
}
4048+
4049+
function detachFiberAfterEffects(fiber: Fiber): void {
4050+
fiber.child = null;
4051+
fiber.sibling = null;
4052+
fiber.updateQueue = null;
4053+
}

0 commit comments

Comments
 (0)