@@ -1069,30 +1069,42 @@ function commitNestedUnmounts(
1069
1069
}
1070
1070
1071
1071
function detachFiberMutation ( fiber : Fiber ) {
1072
- // Cut off the return pointers to disconnect it from the tree. Ideally, we
1073
- // should clear the child pointer of the parent alternate to let this
1072
+ // Cut off the return pointer to disconnect it from the tree.
1073
+ // This enables us to detect and warn against state updates on an unmounted component.
1074
+ // It also prevents events from bubbling from within disconnected components.
1075
+ //
1076
+ // Ideally, we should also clear the child pointer of the parent alternate to let this
1074
1077
// get GC:ed but we don't know which for sure which parent is the current
1075
- // one so we'll settle for GC:ing the subtree of this child. This child
1076
- // itself will be GC:ed when the parent updates the next time.
1077
- // Note: we cannot null out sibling here, otherwise it can cause issues
1078
- // with findDOMNode and how it requires the sibling field to carry out
1079
- // traversal in a later effect. See PR #16820. We now clear the sibling
1080
- // field after effects, see: detachFiberAfterEffects.
1078
+ // one so we'll settle for GC:ing the subtree of this child.
1079
+ // This child itself will be GC:ed when the parent updates the next time.
1081
1080
//
1082
- // Don't disconnect stateNode now; it will be detached in detachFiberAfterEffects.
1083
- // It may be required if the current component is an error boundary,
1084
- // and one of its descendants throws while unmounting a passive effect.
1085
- fiber . alternate = null ;
1081
+ // Note that we can't clear child or sibling pointers yet.
1082
+ // They're needed for passive effects and for findDOMNode.
1083
+ // We defer those fields, and all other cleanup, to the passive phase (see detachFiberAfterEffects).
1084
+ const alternate = fiber . alternate ;
1085
+ if ( alternate !== null ) {
1086
+ alternate . return = null ;
1087
+ fiber . alternate = null ;
1088
+ }
1089
+ fiber . return = null ;
1090
+ }
1091
+
1092
+ export function detachFiberAfterEffects ( fiber : Fiber ) : void {
1093
+ // Null out fields to improve GC for references that may be lingering (e.g. DevTools).
1094
+ // Note that we already cleared the return pointer in detachFiberMutation().
1086
1095
fiber . child = null ;
1087
1096
fiber . deletions = null ;
1088
1097
fiber . dependencies = null ;
1089
- fiber . firstEffect = null ;
1090
- fiber . lastEffect = null ;
1091
1098
fiber . memoizedProps = null ;
1092
1099
fiber . memoizedState = null ;
1093
1100
fiber . pendingProps = null ;
1094
- fiber . return = null ;
1101
+ fiber . sibling = null ;
1102
+ fiber . stateNode = null ;
1095
1103
fiber . updateQueue = null ;
1104
+ fiber . nextEffect = null ;
1105
+ fiber . firstEffect = null ;
1106
+ fiber . lastEffect = null ;
1107
+
1096
1108
if ( __DEV__ ) {
1097
1109
fiber . _debugOwner = null ;
1098
1110
}
0 commit comments