Add static version of Passive subtree tag (#19510)

Creates new subtree tag, PassiveStatic, that represents whether a
tree contains any passive effect hooks.

It corresponds to the PassiveStatic effect tag, which represents the
same concept for an individual fiber.

This allows us to remove the PassiveStatic effect tag from PassiveMask.
Its presence was causing us to schedule a passive effect phase callback
on every render, instead of only when something changed. That's now
fixed; this is reflected in the SchedulerProfiler tests.

(The naming is getting really confusing. Need to do some bikeshedding.)
This commit is contained in:
Andrew Clark 2020-08-01 08:15:46 -05:00 committed by GitHub
parent a1c0864d19
commit 93a0c28305
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 18 additions and 11 deletions

View File

@ -149,6 +149,7 @@ import {
Mutation as MutationSubtreeTag,
Layout as LayoutSubtreeTag,
Passive as PassiveSubtreeTag,
PassiveStatic as PassiveStaticSubtreeTag,
} from './ReactSubtreeTags';
import {
NoLanePriority,
@ -1901,6 +1902,9 @@ function resetChildLanes(completedWork: Fiber) {
if ((effectTag & PassiveMask) !== NoEffect) {
subtreeTag |= PassiveSubtreeTag;
}
if ((effectTag & PassiveStatic) !== NoEffect) {
subtreeTag |= PassiveStaticSubtreeTag;
}
// 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).
@ -1951,6 +1955,9 @@ function resetChildLanes(completedWork: Fiber) {
if ((effectTag & PassiveMask) !== NoEffect) {
subtreeTag |= PassiveSubtreeTag;
}
if ((effectTag & PassiveStatic) !== NoEffect) {
subtreeTag |= PassiveStaticSubtreeTag;
}
child = child.sibling;
}
@ -2784,8 +2791,9 @@ function flushPassiveUnmountEffects(firstChild: Fiber): void {
for (let i = 0; i < deletions.length; i++) {
const fiberToDelete = deletions[i];
// If this fiber (or anything below it) has passive effects then traverse the subtree.
const primaryEffectTag = fiberToDelete.effectTag & PassiveMask;
const primarySubtreeTag = fiberToDelete.subtreeTag & PassiveSubtreeTag;
const primaryEffectTag = fiberToDelete.effectTag & PassiveStatic;
const primarySubtreeTag =
fiberToDelete.subtreeTag & PassiveStaticSubtreeTag;
if (
primarySubtreeTag !== NoSubtreeTag ||
primaryEffectTag !== NoEffect
@ -2837,7 +2845,7 @@ function flushPassiveUnmountEffectsInsideOfDeletedTree(
// Note that this requires checking subtreeTag of the current Fiber,
// rather than the subtreeTag/effectsTag of the first child,
// since that would not cover passive effects in siblings.
const primarySubtreeTag = fiber.subtreeTag & PassiveSubtreeTag;
const primarySubtreeTag = fiber.subtreeTag & PassiveStaticSubtreeTag;
if (primarySubtreeTag !== NoSubtreeTag) {
flushPassiveUnmountEffectsInsideOfDeletedTree(child);
}

View File

@ -51,7 +51,7 @@ export const PassiveStatic = /* */ 0b1000000000000000;
export const BeforeMutationMask = /* */ 0b0000001100001010;
export const MutationMask = /* */ 0b0000010010011110;
export const LayoutMask = /* */ 0b0000000010100100;
export const PassiveMask = /* */ 0b1000001000001000;
export const PassiveMask = /* */ 0b0000001000001000;
// Union of tags that don't get reset on clones.
// This allows certain concepts to persist without recalculting them,

View File

@ -9,8 +9,9 @@
export type SubtreeTag = number;
export const NoEffect = /* */ 0b0000;
export const BeforeMutation = /* */ 0b0001;
export const Mutation = /* */ 0b0010;
export const Layout = /* */ 0b0100;
export const Passive = /* */ 0b1000;
export const NoEffect = /* */ 0b00000;
export const BeforeMutation = /* */ 0b00001;
export const Mutation = /* */ 0b00010;
export const Layout = /* */ 0b00100;
export const Passive = /* */ 0b01000;
export const PassiveStatic = /* */ 0b10000;

View File

@ -526,8 +526,6 @@ describe('SchedulingProfiler', () => {
'--layout-effects-start-1024',
'--layout-effects-stop',
'--commit-stop',
'--passive-effects-start-1024',
'--passive-effects-stop',
]);
}
});