Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a16ac10

Browse files
committedMar 23, 2021
Detach sibling pointers in old child list
When a fiber is deleted, it's still part of the previous (alternate) parent fiber's list of children. Because children are a linked list, an earlier sibling that's still alive will be connected to the deleted fiber via its alternate: live fiber --alternate--> previous live fiber --sibling--> deleted fiber We can't disconnect `alternate` on nodes that haven't been deleted yet, but we can disconnect the `sibling` and `child` pointers. Will use this feature flag to test the memory impact.
1 parent 82c7916 commit a16ac10

12 files changed

+66
-0
lines changed
 

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
enableScopeAPI,
3737
enableStrictEffects,
3838
enableStrongMemoryCleanup,
39+
enableDetachOldChildList,
3940
} from 'shared/ReactFeatureFlags';
4041
import {
4142
FunctionComponent,
@@ -2323,6 +2324,33 @@ function commitPassiveUnmountEffects_begin() {
23232324
detachFiberAfterEffects(alternate);
23242325
}
23252326
}
2327+
2328+
if (enableDetachOldChildList) {
2329+
// A fiber was deleted from this parent fiber, but it's still part of
2330+
// the previous (alternate) parent fiber's list of children. Because
2331+
// children are a linked list, an earlier sibling that's still alive
2332+
// will be connected to the deleted fiber via its `alternate`:
2333+
//
2334+
// live fiber
2335+
// --alternate--> previous live fiber
2336+
// --sibling--> deleted fiber
2337+
//
2338+
// We can't disconnect `alternate` on nodes that haven't been deleted
2339+
// yet, but we can disconnect the `sibling` and `child` pointers.
2340+
const previousFiber = fiber.alternate;
2341+
if (previousFiber !== null) {
2342+
let detachedChild = previousFiber.child;
2343+
if (detachedChild !== null) {
2344+
previousFiber.child = null;
2345+
do {
2346+
const detachedSibling = detachedChild.sibling;
2347+
detachedChild.sibling = null;
2348+
detachedChild = detachedSibling;
2349+
} while (detachedChild !== null);
2350+
}
2351+
}
2352+
}
2353+
23262354
nextEffect = fiber;
23272355
}
23282356
}

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
enableScopeAPI,
3737
enableStrictEffects,
3838
enableStrongMemoryCleanup,
39+
enableDetachOldChildList,
3940
} from 'shared/ReactFeatureFlags';
4041
import {
4142
FunctionComponent,
@@ -2323,6 +2324,33 @@ function commitPassiveUnmountEffects_begin() {
23232324
detachFiberAfterEffects(alternate);
23242325
}
23252326
}
2327+
2328+
if (enableDetachOldChildList) {
2329+
// A fiber was deleted from this parent fiber, but it's still part of
2330+
// the previous (alternate) parent fiber's list of children. Because
2331+
// children are a linked list, an earlier sibling that's still alive
2332+
// will be connected to the deleted fiber via its `alternate`:
2333+
//
2334+
// live fiber
2335+
// --alternate--> previous live fiber
2336+
// --sibling--> deleted fiber
2337+
//
2338+
// We can't disconnect `alternate` on nodes that haven't been deleted
2339+
// yet, but we can disconnect the `sibling` and `child` pointers.
2340+
const previousFiber = fiber.alternate;
2341+
if (previousFiber !== null) {
2342+
let detachedChild = previousFiber.child;
2343+
if (detachedChild !== null) {
2344+
previousFiber.child = null;
2345+
do {
2346+
const detachedSibling = detachedChild.sibling;
2347+
detachedChild.sibling = null;
2348+
detachedChild = detachedSibling;
2349+
} while (detachedChild !== null);
2350+
}
2351+
}
2352+
}
2353+
23262354
nextEffect = fiber;
23272355
}
23282356
}

‎packages/shared/ReactFeatureFlags.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ export const skipUnmountedBoundaries = false;
114114

115115
// When a node is unmounted, recurse into the Fiber subtree and clean out references.
116116
export const enableStrongMemoryCleanup = false;
117+
export const enableDetachOldChildList = false;
117118

118119
// --------------------------
119120
// Future APIs to be deprecated

‎packages/shared/forks/ReactFeatureFlags.native-fb.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const enableFilterEmptyStringAttributesDOM = false;
4747
export const disableNativeComponentFrames = false;
4848
export const skipUnmountedBoundaries = false;
4949
export const enableStrongMemoryCleanup = false;
50+
export const enableDetachOldChildList = false;
5051

5152
export const enableNewReconciler = false;
5253
export const deferRenderPhaseUpdateToNextBatch = true;

‎packages/shared/forks/ReactFeatureFlags.native-oss.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export const enableFilterEmptyStringAttributesDOM = false;
4646
export const disableNativeComponentFrames = false;
4747
export const skipUnmountedBoundaries = false;
4848
export const enableStrongMemoryCleanup = false;
49+
export const enableDetachOldChildList = false;
4950

5051
export const enableNewReconciler = false;
5152
export const deferRenderPhaseUpdateToNextBatch = true;

‎packages/shared/forks/ReactFeatureFlags.test-renderer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export const enableFilterEmptyStringAttributesDOM = false;
4646
export const disableNativeComponentFrames = false;
4747
export const skipUnmountedBoundaries = false;
4848
export const enableStrongMemoryCleanup = false;
49+
export const enableDetachOldChildList = false;
4950

5051
export const enableNewReconciler = false;
5152
export const deferRenderPhaseUpdateToNextBatch = true;

‎packages/shared/forks/ReactFeatureFlags.test-renderer.native.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export const enableFilterEmptyStringAttributesDOM = false;
4646
export const disableNativeComponentFrames = false;
4747
export const skipUnmountedBoundaries = false;
4848
export const enableStrongMemoryCleanup = false;
49+
export const enableDetachOldChildList = false;
4950

5051
export const enableNewReconciler = false;
5152
export const deferRenderPhaseUpdateToNextBatch = true;

‎packages/shared/forks/ReactFeatureFlags.test-renderer.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export const enableFilterEmptyStringAttributesDOM = false;
4646
export const disableNativeComponentFrames = false;
4747
export const skipUnmountedBoundaries = false;
4848
export const enableStrongMemoryCleanup = false;
49+
export const enableDetachOldChildList = false;
4950

5051
export const enableNewReconciler = false;
5152
export const deferRenderPhaseUpdateToNextBatch = true;

‎packages/shared/forks/ReactFeatureFlags.testing.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export const enableFilterEmptyStringAttributesDOM = false;
4646
export const disableNativeComponentFrames = false;
4747
export const skipUnmountedBoundaries = false;
4848
export const enableStrongMemoryCleanup = false;
49+
export const enableDetachOldChildList = false;
4950

5051
export const enableNewReconciler = false;
5152
export const deferRenderPhaseUpdateToNextBatch = true;

‎packages/shared/forks/ReactFeatureFlags.testing.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export const enableFilterEmptyStringAttributesDOM = false;
4646
export const disableNativeComponentFrames = false;
4747
export const skipUnmountedBoundaries = true;
4848
export const enableStrongMemoryCleanup = false;
49+
export const enableDetachOldChildList = false;
4950

5051
export const enableNewReconciler = false;
5152
export const deferRenderPhaseUpdateToNextBatch = true;

‎packages/shared/forks/ReactFeatureFlags.www-dynamic.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export const createRootStrictEffectsByDefault = false;
5353
export const enableStrictEffects = false;
5454
export const enableUseRefAccessWarning = __VARIANT__;
5555
export const enableStrongMemoryCleanup = __VARIANT__;
56+
export const enableDetachOldChildList = __VARIANT__;
5657

5758
export const enableProfilerNestedUpdateScheduledHook = __VARIANT__;
5859
export const disableSchedulerTimeoutInWorkLoop = __VARIANT__;

‎packages/shared/forks/ReactFeatureFlags.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export const {
3434
enableSyncMicroTasks,
3535
enableLazyContextPropagation,
3636
enableStrongMemoryCleanup,
37+
enableDetachOldChildList,
3738
} = dynamicFeatureFlags;
3839

3940
// On WWW, __EXPERIMENTAL__ is used for a new modern build.

0 commit comments

Comments
 (0)
Please sign in to comment.