@@ -2406,15 +2406,16 @@ function commitMutationEffects(
2406
2406
) {
2407
2407
let fiber = firstChild ;
2408
2408
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 ) ;
2415
2412
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
+ }
2418
2419
}
2419
2420
2420
2421
if ( fiber . child !== null ) {
@@ -2548,7 +2549,13 @@ function commitMutationEffectsDeletions(
2548
2549
captureCommitPhaseError ( childToDelete , error ) ;
2549
2550
}
2550
2551
}
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
+ }
2552
2559
}
2553
2560
}
2554
2561
@@ -2777,15 +2784,21 @@ function flushPassiveUnmountEffects(firstChild: Fiber): void {
2777
2784
for ( let i = 0 ; i < deletions . length ; i ++ ) {
2778
2785
const fiberToDelete = deletions [ i ] ;
2779
2786
// 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 ;
2781
2788
const primarySubtreeTag = fiberToDelete . subtreeTag & PassiveSubtreeTag ;
2782
2789
if (
2783
2790
primarySubtreeTag !== NoSubtreeTag ||
2784
2791
primaryEffectTag !== NoEffect
2785
2792
) {
2786
2793
flushPassiveUnmountEffects ( fiberToDelete ) ;
2787
2794
}
2795
+
2796
+ // Now that passive effects have been processed, it's safe to detach lingering pointers.
2797
+ detachFiberAfterEffects ( fiberToDelete ) ;
2788
2798
}
2799
+
2800
+ // Clear deletions now that passive effects have been procssed.
2801
+ fiber . deletions = null ;
2789
2802
}
2790
2803
2791
2804
const didBailout =
@@ -2809,7 +2822,7 @@ function flushPassiveUnmountEffects(firstChild: Fiber): void {
2809
2822
case ForwardRef :
2810
2823
case SimpleMemoComponent :
2811
2824
case Block : {
2812
- const primaryEffectTag = fiber . effectTag & ( Passive | Update ) ;
2825
+ const primaryEffectTag = fiber . effectTag & PassiveMask ;
2813
2826
if ( primaryEffectTag !== NoEffect ) {
2814
2827
flushPassiveUnmountEffectsImpl ( fiber ) ;
2815
2828
}
@@ -2934,8 +2947,6 @@ function flushPassiveEffectsImpl() {
2934
2947
flushPassiveUnmountEffects ( root . current ) ;
2935
2948
flushPassiveMountEffects ( root . current ) ;
2936
2949
2937
- // TODO (effects) Detach sibling pointers for deleted Fibers
2938
-
2939
2950
if ( enableProfilerTimer && enableProfilerCommitHooks ) {
2940
2951
const profilerEffects = pendingPassiveProfilerEffects ;
2941
2952
pendingPassiveProfilerEffects = [ ] ;
@@ -4034,3 +4045,9 @@ export function act(callback: () => Thenable<mixed>): Thenable<void> {
4034
4045
} ;
4035
4046
}
4036
4047
}
4048
+
4049
+ function detachFiberAfterEffects ( fiber : Fiber ) : void {
4050
+ fiber . child = null ;
4051
+ fiber . sibling = null ;
4052
+ fiber . updateQueue = null ;
4053
+ }
0 commit comments