Skip to content

Commit

Permalink
Combine Flags and SubtreeFlags types (facebook#19775)
Browse files Browse the repository at this point in the history
Because the `subtreeFlags` is the union of all the flags present in
a subtree, we can use the same type as `flags`.

One practical benefit is that we can bubble up the flags from the
children with a single `|=` operator.

Structurally, everything else about the effect algorithm is unchanged.
  • Loading branch information
acdlite committed Sep 4, 2020
1 parent 1665443 commit 7baf9d4
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 113 deletions.
7 changes: 3 additions & 4 deletions packages/react-reconciler/src/ReactFiber.new.js
Expand Up @@ -30,7 +30,6 @@ import {
enableBlocksAPI,
} from 'shared/ReactFeatureFlags';
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
import {NoFlags as NoSubtreeEffect} from './ReactSubtreeFlags';
import {ConcurrentRoot, BlockingRoot} from './ReactRootTags';
import {
IndeterminateComponent,
Expand Down Expand Up @@ -145,7 +144,7 @@ function FiberNode(

// Effects
this.flags = NoFlags;
this.subtreeFlags = NoSubtreeEffect;
this.subtreeFlags = NoFlags;
this.deletions = null;

this.lanes = NoLanes;
Expand Down Expand Up @@ -284,7 +283,7 @@ export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {
workInProgress.type = current.type;

// We already have an alternate.
workInProgress.subtreeFlags = NoSubtreeEffect;
workInProgress.subtreeFlags = NoFlags;
workInProgress.deletions = null;

if (enableProfilerTimer) {
Expand Down Expand Up @@ -372,7 +371,7 @@ export function resetWorkInProgress(workInProgress: Fiber, renderLanes: Lanes) {
workInProgress.lanes = renderLanes;

workInProgress.child = null;
workInProgress.subtreeFlags = NoSubtreeEffect;
workInProgress.subtreeFlags = NoFlags;
workInProgress.memoizedProps = null;
workInProgress.memoizedState = null;
workInProgress.updateQueue = null;
Expand Down
10 changes: 2 additions & 8 deletions packages/react-reconciler/src/ReactFiberCommitWork.new.js
Expand Up @@ -71,6 +71,7 @@ import {
Placement,
Snapshot,
Update,
PassiveMask,
} from './ReactFiberFlags';
import getComponentName from 'shared/getComponentName';
import invariant from 'shared/invariant';
Expand Down Expand Up @@ -130,10 +131,6 @@ import {
Passive as HookPassive,
} from './ReactHookEffectTags';
import {didWarnAboutReassigningProps} from './ReactFiberBeginWork.new';
import {
NoFlags as NoSubtreeFlags,
Passive as PassiveSubtreeFlags,
} from './ReactSubtreeFlags';

let didWarnAboutUndefinedSnapshotBeforeUpdate: Set<mixed> | null = null;
if (__DEV__) {
Expand Down Expand Up @@ -595,10 +592,7 @@ function commitLifeCycles(
commitHookEffectListMount(HookLayout | HookHasEffect, finishedWork);
}

if (
(finishedWork.subtreeFlags & PassiveSubtreeFlags) !==
NoSubtreeFlags
) {
if ((finishedWork.subtreeFlags & PassiveMask) !== NoFlags) {
schedulePassiveEffectCallback();
}
return;
Expand Down
3 changes: 1 addition & 2 deletions packages/react-reconciler/src/ReactFiberCompleteWork.new.js
Expand Up @@ -67,7 +67,6 @@ import {
Snapshot,
MutationMask,
} from './ReactFiberFlags';
import {NoFlags as NoSubtreeFlags, Mutation} from './ReactSubtreeFlags';
import invariant from 'shared/invariant';

import {
Expand Down Expand Up @@ -166,7 +165,7 @@ function hadNoMutationsEffects(current: null | Fiber, completedWork: Fiber) {
if ((child.flags & MutationMask) !== NoFlags) {
return false;
}
if ((child.subtreeFlags & Mutation) !== NoSubtreeFlags) {
if ((child.subtreeFlags & MutationMask) !== NoFlags) {
return false;
}
child = child.sibling;
Expand Down
110 changes: 31 additions & 79 deletions packages/react-reconciler/src/ReactFiberWorkLoop.new.js
Expand Up @@ -139,15 +139,8 @@ import {
MutationMask,
LayoutMask,
PassiveMask,
StaticMask,
} from './ReactFiberFlags';
import {
NoFlags as NoSubtreeFlags,
BeforeMutation as BeforeMutationSubtreeFlags,
Mutation as MutationSubtreeFlags,
Layout as LayoutSubtreeFlags,
Passive as PassiveSubtreeFlags,
PassiveStatic as PassiveStaticSubtreeFlags,
} from './ReactSubtreeFlags';
import {
NoLanePriority,
SyncLanePriority,
Expand Down Expand Up @@ -1766,7 +1759,7 @@ function completeUnitOfWork(unitOfWork: Fiber): void {
if (returnFiber !== null) {
// Mark the parent fiber as incomplete
returnFiber.flags |= Incomplete;
returnFiber.subtreeFlags = NoSubtreeFlags;
returnFiber.subtreeFlags = NoFlags;
returnFiber.deletions = null;
}
}
Expand Down Expand Up @@ -1809,7 +1802,7 @@ function resetChildLanes(completedWork: Fiber) {
completedWork.alternate.child === completedWork.child;

let newChildLanes = NoLanes;
let subtreeFlags = NoSubtreeFlags;
let subtreeFlags = NoFlags;

if (!didBailout) {
// Bubble up the earliest expiration time.
Expand All @@ -1827,23 +1820,7 @@ function resetChildLanes(completedWork: Fiber) {
);

subtreeFlags |= child.subtreeFlags;

const flags = child.flags;
if ((flags & BeforeMutationMask) !== NoFlags) {
subtreeFlags |= BeforeMutationSubtreeFlags;
}
if ((flags & MutationMask) !== NoFlags) {
subtreeFlags |= MutationSubtreeFlags;
}
if ((flags & LayoutMask) !== NoFlags) {
subtreeFlags |= LayoutSubtreeFlags;
}
if ((flags & PassiveMask) !== NoFlags) {
subtreeFlags |= PassiveSubtreeFlags;
}
if ((flags & PassiveStatic) !== NoFlags) {
subtreeFlags |= PassiveStaticSubtreeFlags;
}
subtreeFlags |= child.flags;

// When a fiber is cloned, its actualDuration is reset to 0. This value will
// only be updated if work is done on the fiber (i.e. it doesn't bailout).
Expand Down Expand Up @@ -1880,23 +1857,7 @@ function resetChildLanes(completedWork: Fiber) {
);

subtreeFlags |= child.subtreeFlags;

const flags = child.flags;
if ((flags & BeforeMutationMask) !== NoFlags) {
subtreeFlags |= BeforeMutationSubtreeFlags;
}
if ((flags & MutationMask) !== NoFlags) {
subtreeFlags |= MutationSubtreeFlags;
}
if ((flags & LayoutMask) !== NoFlags) {
subtreeFlags |= LayoutSubtreeFlags;
}
if ((flags & PassiveMask) !== NoFlags) {
subtreeFlags |= PassiveSubtreeFlags;
}
if ((flags & PassiveStatic) !== NoFlags) {
subtreeFlags |= PassiveStaticSubtreeFlags;
}
subtreeFlags |= child.flags;

child = child.sibling;
}
Expand All @@ -1917,13 +1878,12 @@ function resetChildLanes(completedWork: Fiber) {
mergeLanes(child.lanes, child.childLanes),
);

// Preserve passive static flag even in the case of a bailout;
// otherwise a subsequent unmount may bailout before calling destroy functions.
subtreeFlags |= child.subtreeFlags & PassiveStaticSubtreeFlags;
const flags = child.flags;
if ((flags & PassiveStatic) !== NoFlags) {
subtreeFlags |= PassiveStaticSubtreeFlags;
}
// "Static" flags share the lifetime of the fiber/hook they belong to,
// so we should bubble those up even during a bailout. All the other
// flags have a lifetime only of a single render + commit, so we should
// ignore them.
subtreeFlags |= child.subtreeFlags & StaticMask;
subtreeFlags |= child.flags & StaticMask;

treeBaseDuration += child.treeBaseDuration;
child = child.sibling;
Expand All @@ -1949,13 +1909,12 @@ function resetChildLanes(completedWork: Fiber) {
mergeLanes(child.lanes, child.childLanes),
);

// Preserve passive static flag even in the case of a bailout;
// otherwise a subsequent unmount may bailout before calling destroy functions.
subtreeFlags |= child.subtreeFlags & PassiveStaticSubtreeFlags;
const flags = child.flags;
if ((flags & PassiveStatic) !== NoFlags) {
subtreeFlags |= PassiveStaticSubtreeFlags;
}
// "Static" flags share the lifetime of the fiber/hook they belong to,
// so we should bubble those up even during a bailout. All the other
// flags have a lifetime only of a single render + commit, so we should
// ignore them.
subtreeFlags |= child.subtreeFlags & StaticMask;
subtreeFlags |= child.flags & StaticMask;

child = child.sibling;
}
Expand Down Expand Up @@ -2067,11 +2026,8 @@ function commitRootImpl(root, renderPriorityLevel) {
// Reconsider whether this is necessary.
const subtreeHasEffects =
(finishedWork.subtreeFlags &
(BeforeMutationSubtreeFlags |
MutationSubtreeFlags |
LayoutSubtreeFlags |
PassiveSubtreeFlags)) !==
NoSubtreeFlags;
(BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !==
NoFlags;
const rootHasEffect =
(finishedWork.flags &
(BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !==
Expand Down Expand Up @@ -2152,7 +2108,7 @@ function commitRootImpl(root, renderPriorityLevel) {

// If there are pending passive effects, schedule a callback to process them.
if (
(finishedWork.subtreeFlags & PassiveSubtreeFlags) !== NoSubtreeFlags ||
(finishedWork.subtreeFlags & PassiveMask) !== NoFlags ||
(finishedWork.flags & PassiveMask) !== NoFlags
) {
if (!rootDoesHavePassiveEffects) {
Expand Down Expand Up @@ -2306,9 +2262,8 @@ function commitBeforeMutationEffects(firstChild: Fiber) {
}

if (fiber.child !== null) {
const primarySubtreeFlags =
fiber.subtreeFlags & BeforeMutationSubtreeFlags;
if (primarySubtreeFlags !== NoSubtreeFlags) {
const primarySubtreeFlags = fiber.subtreeFlags & BeforeMutationMask;
if (primarySubtreeFlags !== NoFlags) {
commitBeforeMutationEffects(fiber.child);
}
}
Expand Down Expand Up @@ -2402,8 +2357,8 @@ function commitMutationEffects(
}

if (fiber.child !== null) {
const primarySubtreeFlags = fiber.subtreeFlags & MutationSubtreeFlags;
if (primarySubtreeFlags !== NoSubtreeFlags) {
const mutationFlags = fiber.subtreeFlags & MutationMask;
if (mutationFlags !== NoFlags) {
commitMutationEffects(fiber.child, root, renderPriorityLevel);
}
}
Expand Down Expand Up @@ -2560,8 +2515,8 @@ function commitLayoutEffects(
let fiber = firstChild;
while (fiber !== null) {
if (fiber.child !== null) {
const primarySubtreeFlags = fiber.subtreeFlags & LayoutSubtreeFlags;
if (primarySubtreeFlags !== NoSubtreeFlags) {
const primarySubtreeFlags = fiber.subtreeFlags & LayoutMask;
if (primarySubtreeFlags !== NoFlags) {
commitLayoutEffects(fiber.child, root, committedLanes);
}
}
Expand Down Expand Up @@ -2662,9 +2617,9 @@ export function enqueuePendingPassiveProfilerEffect(fiber: Fiber): void {
function flushPassiveMountEffects(firstChild: Fiber): void {
let fiber = firstChild;
while (fiber !== null) {
const primarySubtreeFlags = fiber.subtreeFlags & PassiveSubtreeFlags;
const primarySubtreeFlags = fiber.subtreeFlags & PassiveMask;

if (fiber.child !== null && primarySubtreeFlags !== NoSubtreeFlags) {
if (fiber.child !== null && primarySubtreeFlags !== NoFlags) {
flushPassiveMountEffects(fiber.child);
}

Expand Down Expand Up @@ -2698,8 +2653,8 @@ function flushPassiveUnmountEffects(firstChild: Fiber): void {
// Note that this requires checking subtreeFlags of the current Fiber,
// rather than the subtreeFlags/effectsTag of the first child,
// since that would not cover passive effects in siblings.
const primarySubtreeFlags = fiber.subtreeFlags & PassiveSubtreeFlags;
if (primarySubtreeFlags !== NoSubtreeFlags) {
const passiveFlags = fiber.subtreeFlags & PassiveMask;
if (passiveFlags !== NoFlags) {
flushPassiveUnmountEffects(child);
}
}
Expand All @@ -2719,10 +2674,7 @@ function flushPassiveUnmountEffectsInsideOfDeletedTree(
fiberToDelete: Fiber,
nearestMountedAncestor: Fiber,
): void {
if (
(fiberToDelete.subtreeFlags & PassiveStaticSubtreeFlags) !==
NoSubtreeFlags
) {
if ((fiberToDelete.subtreeFlags & PassiveStatic) !== NoFlags) {
// If any children have passive effects then traverse the subtree.
// Note that this requires checking subtreeFlags of the current Fiber,
// rather than the subtreeFlags/effectsTag of the first child,
Expand Down
3 changes: 1 addition & 2 deletions packages/react-reconciler/src/ReactInternalTypes.js
Expand Up @@ -20,7 +20,6 @@ import type {SuspenseInstance} from './ReactFiberHostConfig';
import type {WorkTag} from './ReactWorkTags';
import type {TypeOfMode} from './ReactTypeOfMode';
import type {Flags} from './ReactFiberFlags';
import type {SubtreeFlags} from './ReactSubtreeFlags';
import type {Lane, LanePriority, Lanes, LaneMap} from './ReactFiberLane';
import type {HookType} from './ReactFiberHooks.old';
import type {RootTag} from './ReactRootTags';
Expand Down Expand Up @@ -119,7 +118,7 @@ export type Fiber = {|

// Effect
flags: Flags,
subtreeFlags: SubtreeFlags,
subtreeFlags: Flags,
deletions: Array<Fiber> | null,

// Singly linked list fast path to the next fiber with side-effects.
Expand Down
18 changes: 0 additions & 18 deletions packages/react-reconciler/src/ReactSubtreeFlags.js

This file was deleted.

0 comments on commit 7baf9d4

Please sign in to comment.