diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.js b/packages/react-reconciler/src/ReactFiberCommitWork.js index 93f2a476bd8bc..b7b17a080b172 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.js @@ -59,6 +59,7 @@ import { enableComponentPerformanceTrack, enableViewTransition, enableFragmentRefs, + enableEagerAlternateStateNodeCleanup, } from 'shared/ReactFeatureFlags'; import { FunctionComponent, @@ -2170,6 +2171,20 @@ function commitMutationEffectsOnFiber( } } } + } else { + if (enableEagerAlternateStateNodeCleanup) { + if (supportsPersistence) { + if (finishedWork.alternate !== null) { + // `finishedWork.alternate.stateNode` is pointing to a stale shadow + // node at this point, retaining it and its subtree. To reclaim + // memory, point `alternate.stateNode` to new shadow node. This + // prevents shadow node from staying in memory longer than it + // needs to. The correct behaviour of this is checked by test in + // React Native: ShadowNodeReferenceCounter-itest.js#L150 + finishedWork.alternate.stateNode = finishedWork.stateNode; + } + } + } } break; } diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 217b095a29aa2..13c1121c95eaa 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -141,6 +141,8 @@ export const enablePersistedModeClonedFlag = false; export const enableShallowPropDiffing = false; +export const enableEagerAlternateStateNodeCleanup = true; + /** * Enables an expiration time for retry lanes to avoid starvation. */ diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js b/packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js index 29a49ae366c81..aa413984e8f38 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js @@ -22,6 +22,7 @@ export const enableObjectFiber = __VARIANT__; export const enableHiddenSubtreeInsertionEffectCleanup = __VARIANT__; export const enablePersistedModeClonedFlag = __VARIANT__; export const enableShallowPropDiffing = __VARIANT__; +export const enableEagerAlternateStateNodeCleanup = __VARIANT__; export const passChildrenWhenCloningPersistedNodes = __VARIANT__; export const enableFastAddPropertiesInDiffing = __VARIANT__; export const enableLazyPublicInstanceInFabric = __VARIANT__; diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index 8383c0dc351b5..d885f9f71642e 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -24,6 +24,7 @@ export const { enableObjectFiber, enablePersistedModeClonedFlag, enableShallowPropDiffing, + enableEagerAlternateStateNodeCleanup, passChildrenWhenCloningPersistedNodes, enableFastAddPropertiesInDiffing, enableLazyPublicInstanceInFabric, diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index acc04dfb055bb..301552857f870 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -49,6 +49,7 @@ export const enableSchedulingProfiler = __PROFILE__; export const enableComponentPerformanceTrack = false; export const enableScopeAPI = false; export const enableShallowPropDiffing = false; +export const enableEagerAlternateStateNodeCleanup = false; export const enableSuspenseAvoidThisFallback = false; export const enableSuspenseCallback = false; export const enableTaint = true; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index 4e51e7260e901..9d8a1808d9923 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -62,6 +62,7 @@ export const enableInfiniteRenderLoopDetection = false; export const renameElementSymbol = true; export const enableShallowPropDiffing = false; +export const enableEagerAlternateStateNodeCleanup = false; export const enableYieldingBeforePassive = true; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js index c9bd058f1fef8..4a9fb9737ac04 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js @@ -47,6 +47,7 @@ export const enableSchedulingProfiler = __PROFILE__; export const enableComponentPerformanceTrack = false; export const enableScopeAPI = false; export const enableShallowPropDiffing = false; +export const enableEagerAlternateStateNodeCleanup = false; export const enableSuspenseAvoidThisFallback = false; export const enableSuspenseCallback = false; export const enableTaint = true; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index baceb1e6b727c..2858799494842 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -71,6 +71,7 @@ export const renameElementSymbol = false; export const enableObjectFiber = false; export const enableShallowPropDiffing = false; +export const enableEagerAlternateStateNodeCleanup = false; export const enableHydrationLaneScheduling = true; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index 5ecd0073edd3f..4869d77741d05 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -107,6 +107,8 @@ export const disableLegacyMode = true; export const enableShallowPropDiffing = false; +export const enableEagerAlternateStateNodeCleanup = false; + export const enableLazyPublicInstanceInFabric = false; export const enableGestureTransition = false;