Skip to content

Commit 82c7916

Browse files
bgirardacdlite
authored andcommitted
Add feature flag: enableStrongMemoryCleanup
Add a feature flag that will test doing a recursive clean of an unmount node. This will disconnect the fiber graph making leaks less severe.
1 parent 00d4f95 commit 82c7916

20 files changed

+83
-2
lines changed

packages/react-art/src/ReactARTHostConfig.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,3 +471,7 @@ export function afterActiveInstanceBlur() {
471471
export function preparePortalMount(portalInstance: any): void {
472472
// noop
473473
}
474+
475+
export function unmountNode(node: any): void {
476+
// noop
477+
}

packages/react-dom/src/client/ReactDOMComponentTree.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,17 @@ const internalEventHandlersKey = '__reactEvents$' + randomKey;
4343
const internalEventHandlerListenersKey = '__reactListeners$' + randomKey;
4444
const internalEventHandlesSetKey = '__reactHandles$' + randomKey;
4545

46+
export function unmountNode(
47+
node: Instance | TextInstance | SuspenseInstance | ReactScopeInstance,
48+
): void {
49+
delete (node: any)[internalInstanceKey];
50+
delete (node: any)[internalPropsKey];
51+
delete (node: any)[internalContainerInstanceKey];
52+
delete (node: any)[internalEventHandlersKey];
53+
delete (node: any)[internalEventHandlerListenersKey];
54+
delete (node: any)[internalEventHandlesSetKey];
55+
}
56+
4657
export function precacheFiberNode(
4758
hostInst: Fiber,
4859
node: Instance | TextInstance | SuspenseInstance | ReactScopeInstance,

packages/react-dom/src/client/ReactDOMHostConfig.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
getFiberFromScopeInstance,
2525
getInstanceFromNode as getInstanceFromNodeDOMTree,
2626
isContainerMarkedAsRoot,
27+
unmountNode as unmountNodeFromDOMTree,
2728
} from './ReactDOMComponentTree';
2829
import {hasRole} from './DOMAccessibilityRoles';
2930
import {
@@ -1209,3 +1210,7 @@ export function setupIntersectionObserver(
12091210
},
12101211
};
12111212
}
1213+
1214+
export function unmountNode(node: any): void {
1215+
unmountNodeFromDOMTree(node);
1216+
}

packages/react-native-renderer/src/ReactFabricHostConfig.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,3 +481,7 @@ export function afterActiveInstanceBlur() {
481481
export function preparePortalMount(portalInstance: Instance): void {
482482
// noop
483483
}
484+
485+
export function unmountNode(node: any): void {
486+
// noop
487+
}

packages/react-native-renderer/src/ReactNativeHostConfig.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,3 +538,7 @@ export function afterActiveInstanceBlur() {
538538
export function preparePortalMount(portalInstance: Instance): void {
539539
// noop
540540
}
541+
542+
export function unmountNode(node: any): void {
543+
// noop
544+
}

packages/react-noop-renderer/src/createReactNoop.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
420420
getInstanceFromScope() {
421421
throw new Error('Not yet implemented.');
422422
},
423+
424+
unmountNode() {},
423425
};
424426

425427
const hostConfig = useMutation

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
enableSuspenseCallback,
3636
enableScopeAPI,
3737
enableStrictEffects,
38+
enableStrongMemoryCleanup,
3839
} from 'shared/ReactFeatureFlags';
3940
import {
4041
FunctionComponent,
@@ -60,6 +61,7 @@ import {
6061
hasCaughtError,
6162
clearCaughtError,
6263
} from 'shared/ReactErrorUtils';
64+
import {unmountNode} from './ReactFiberHostConfig';
6365
import {
6466
NoFlags,
6567
ContentReset,
@@ -1212,9 +1214,24 @@ function detachFiberMutation(fiber: Fiber) {
12121214
fiber.return = null;
12131215
}
12141216

1215-
export function detachFiberAfterEffects(fiber: Fiber): void {
1217+
export function detachFiberAfterEffects(
1218+
fiber: Fiber,
1219+
recurseIntoSibbling: ?boolean,
1220+
): void {
12161221
// Null out fields to improve GC for references that may be lingering (e.g. DevTools).
12171222
// Note that we already cleared the return pointer in detachFiberMutation().
1223+
if (enableStrongMemoryCleanup) {
1224+
if (fiber.child) {
1225+
detachFiberAfterEffects(fiber.child, true);
1226+
}
1227+
if (fiber.sibling && recurseIntoSibbling === true) {
1228+
detachFiberAfterEffects(fiber.sibling, true);
1229+
}
1230+
if (fiber.stateNode) {
1231+
unmountNode(fiber.stateNode);
1232+
}
1233+
fiber.return = null;
1234+
}
12181235
fiber.alternate = null;
12191236
fiber.child = null;
12201237
fiber.deletions = null;

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
enableSuspenseCallback,
3636
enableScopeAPI,
3737
enableStrictEffects,
38+
enableStrongMemoryCleanup,
3839
} from 'shared/ReactFeatureFlags';
3940
import {
4041
FunctionComponent,
@@ -60,6 +61,7 @@ import {
6061
hasCaughtError,
6162
clearCaughtError,
6263
} from 'shared/ReactErrorUtils';
64+
import {unmountNode} from './ReactFiberHostConfig';
6365
import {
6466
NoFlags,
6567
ContentReset,
@@ -1212,9 +1214,24 @@ function detachFiberMutation(fiber: Fiber) {
12121214
fiber.return = null;
12131215
}
12141216

1215-
export function detachFiberAfterEffects(fiber: Fiber): void {
1217+
export function detachFiberAfterEffects(
1218+
fiber: Fiber,
1219+
recurseIntoSibbling: ?boolean,
1220+
): void {
12161221
// Null out fields to improve GC for references that may be lingering (e.g. DevTools).
12171222
// Note that we already cleared the return pointer in detachFiberMutation().
1223+
if (enableStrongMemoryCleanup) {
1224+
if (fiber.child) {
1225+
detachFiberAfterEffects(fiber.child, true);
1226+
}
1227+
if (fiber.sibling && recurseIntoSibbling === true) {
1228+
detachFiberAfterEffects(fiber.sibling, true);
1229+
}
1230+
if (fiber.stateNode) {
1231+
unmountNode(fiber.stateNode);
1232+
}
1233+
fiber.return = null;
1234+
}
12181235
fiber.alternate = null;
12191236
fiber.child = null;
12201237
fiber.deletions = null;

packages/react-reconciler/src/forks/ReactFiberHostConfig.custom.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export const preparePortalMount = $$$hostConfig.preparePortalMount;
7373
export const prepareScopeUpdate = $$$hostConfig.preparePortalMount;
7474
export const getInstanceFromScope = $$$hostConfig.getInstanceFromScope;
7575
export const getCurrentEventPriority = $$$hostConfig.getCurrentEventPriority;
76+
export const unmountNode = $$$hostConfig.unmountNode;
7677

7778
// -------------------
7879
// Microtasks

packages/react-test-renderer/src/ReactTestHostConfig.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,3 +360,7 @@ export function prepareScopeUpdate(scopeInstance: Object, inst: Object): void {
360360
export function getInstanceFromScope(scopeInstance: Object): null | Object {
361361
return nodeToInstanceMap.get(scopeInstance) || null;
362362
}
363+
364+
export function unmountNode(node: any): void {
365+
// noop
366+
}

0 commit comments

Comments
 (0)