From a74c51cb189eae0d26550592d57d7c9b10875229 Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Sun, 15 Nov 2020 23:25:34 -0600 Subject: [PATCH] Add separate ChildDeletion flag In the old, effect list implementation, the Deletion flag is is set on each deleted fiber. In the new, subtreeTag implementation, the Deletion flag is set on the parent of each deleted fiber, and the deleted fibers themselves are pushed to the `deletions` array. To better distinguish between these two uses, I've added a separate ChildDeletion flag. That way we can, if desired, maintain both implementations simultaneously, as we bisect to find the performance regression that we're currently investigating. --- .../react-reconciler/src/ReactFiberFlags.js | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberFlags.js b/packages/react-reconciler/src/ReactFiberFlags.js index da8255c6e8d11..518abbee11050 100644 --- a/packages/react-reconciler/src/ReactFiberFlags.js +++ b/packages/react-reconciler/src/ReactFiberFlags.js @@ -12,48 +12,49 @@ import {enableCreateEventHandleAPI} from 'shared/ReactFeatureFlags'; export type Flags = number; // Don't change these two values. They're used by React Dev Tools. -export const NoFlags = /* */ 0b0000000000000000000; -export const PerformedWork = /* */ 0b0000000000000000001; +export const NoFlags = /* */ 0b00000000000000000000; +export const PerformedWork = /* */ 0b00000000000000000001; // You can change the rest (and add more). -export const Placement = /* */ 0b0000000000000000010; -export const Update = /* */ 0b0000000000000000100; -export const PlacementAndUpdate = /* */ 0b0000000000000000110; -export const Deletion = /* */ 0b0000000000000001000; -export const ContentReset = /* */ 0b0000000000000010000; -export const Callback = /* */ 0b0000000000000100000; -export const DidCapture = /* */ 0b0000000000001000000; -export const Ref = /* */ 0b0000000000010000000; -export const Snapshot = /* */ 0b0000000000100000000; -export const Passive = /* */ 0b0000000001000000000; -export const Hydrating = /* */ 0b0000000010000000000; -export const HydratingAndUpdate = /* */ 0b0000000010000000100; -export const Visibility = /* */ 0b0000000100000000000; +export const Placement = /* */ 0b00000000000000000010; +export const Update = /* */ 0b00000000000000000100; +export const PlacementAndUpdate = /* */ Placement | Update; +export const Deletion = /* */ 0b00000000000000001000; +export const ChildDeletion = /* */ 0b00000000000000010000; +export const ContentReset = /* */ 0b00000000000000100000; +export const Callback = /* */ 0b00000000000001000000; +export const DidCapture = /* */ 0b00000000000010000000; +export const Ref = /* */ 0b00000000000100000000; +export const Snapshot = /* */ 0b00000000001000000000; +export const Passive = /* */ 0b00000000010000000000; +export const Hydrating = /* */ 0b00000000100000000000; +export const HydratingAndUpdate = /* */ Hydrating | Update; +export const Visibility = /* */ 0b00000001000000000000; export const LifecycleEffectMask = Passive | Update | Callback | Ref | Snapshot; // Union of all commit flags (flags with the lifetime of a particular commit) -export const HostEffectMask = /* */ 0b0000000111111111111; +export const HostEffectMask = /* */ 0b00000001111111111111; // These are not really side effects, but we still reuse this field. -export const Incomplete = /* */ 0b0000001000000000000; -export const ShouldCapture = /* */ 0b0000010000000000000; +export const Incomplete = /* */ 0b00000010000000000000; +export const ShouldCapture = /* */ 0b00000100000000000000; // TODO (effects) Remove this bit once the new reconciler is synced to the old. -export const PassiveUnmountPendingDev = /* */ 0b0000100000000000000; -export const ForceUpdateForLegacySuspense = /* */ 0b0001000000000000000; +export const PassiveUnmountPendingDev = /* */ 0b00001000000000000000; +export const ForceUpdateForLegacySuspense = /* */ 0b00010000000000000000; // Static tags describe aspects of a fiber that are not specific to a render, // e.g. a fiber uses a passive effect (even if there are no updates on this particular render). // This enables us to defer more work in the unmount case, // since we can defer traversing the tree during layout to look for Passive effects, // and instead rely on the static flag as a signal that there may be cleanup work. -export const PassiveStatic = /* */ 0b0010000000000000000; +export const PassiveStatic = /* */ 0b00100000000000000000; // These flags allow us to traverse to fibers that have effects on mount // without traversing the entire tree after every commit for // double invoking -export const MountLayoutDev = /* */ 0b0100000000000000000; -export const MountPassiveDev = /* */ 0b1000000000000000000; +export const MountLayoutDev = /* */ 0b01000000000000000000; +export const MountPassiveDev = /* */ 0b10000000000000000000; // Groups of flags that are used in the commit phase to skip over trees that // don't contain effects, by checking subtreeFlags. @@ -65,13 +66,19 @@ export const BeforeMutationMask = // fire beforeblur // TODO: Only need to visit Deletions during BeforeMutation phase if an // element is focused. - Deletion | Visibility + ChildDeletion | Visibility : 0); export const MutationMask = - Placement | Update | Deletion | ContentReset | Ref | Hydrating | Visibility; + Placement | + Update | + ChildDeletion | + ContentReset | + Ref | + Hydrating | + Visibility; export const LayoutMask = Update | Callback | Ref; -export const PassiveMask = Passive | Deletion; +export const PassiveMask = Passive | ChildDeletion; // Union of tags that don't get reset on clones. // This allows certain concepts to persist without recalculting them,