Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove LayoutStatic check from commit phase #21249

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
158 changes: 82 additions & 76 deletions packages/react-reconciler/src/ReactFiberCommitWork.new.js
Expand Up @@ -81,8 +81,6 @@ import {
MutationMask,
LayoutMask,
PassiveMask,
LayoutStatic,
RefStatic,
} from './ReactFiberFlags';
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
import invariant from 'shared/invariant';
Expand Down Expand Up @@ -1027,14 +1025,18 @@ function hideOrUnhideAllChildren(finishedWork, isHidden) {
const current = finishedWork.alternate;
const wasHidden = current !== null && current.memoizedState !== null;

// Only hide the top-most host nodes.
let hiddenHostSubtreeRoot = null;

if (supportsMutation) {
// We only have the top Fiber that was inserted but we need to recurse down its
// children to find all the terminal nodes.
let node: Fiber = finishedWork;
while (true) {
if (node.tag === HostComponent) {
const instance = node.stateNode;
if (isHidden) {
if (isHidden && hiddenHostSubtreeRoot === null) {
hiddenHostSubtreeRoot = node;
hideInstance(instance);
} else {
unhideInstance(node.stateNode, node.memoizedProps);
Expand All @@ -1043,24 +1045,21 @@ function hideOrUnhideAllChildren(finishedWork, isHidden) {
if (enableSuspenseLayoutEffectSemantics && isModernRoot) {
// This method is called during mutation; it should detach refs within a hidden subtree.
// Attaching refs should be done elsewhere though (during layout).
if ((node.flags & RefStatic) !== NoFlags) {
if (isHidden) {
safelyDetachRef(node, finishedWork);
}
// TODO (Offscreen) Also check: flags & RefStatic
if (isHidden) {
safelyDetachRef(node, finishedWork);
}

if (
(node.subtreeFlags & (RefStatic | LayoutStatic)) !== NoFlags &&
node.child !== null
) {
// TODO (Offscreen) Also check: subtreeFlags & (RefStatic | LayoutStatic)
if (node.child !== null) {
node.child.return = node;
node = node.child;
continue;
}
}
} else if (node.tag === HostText) {
const instance = node.stateNode;
if (isHidden) {
if (isHidden && hiddenHostSubtreeRoot === null) {
hideTextInstance(instance);
} else {
unhideTextInstance(instance, node.memoizedProps);
Expand All @@ -1075,43 +1074,42 @@ function hideOrUnhideAllChildren(finishedWork, isHidden) {
// Don't search any deeper. This tree should remain hidden.
} else if (enableSuspenseLayoutEffectSemantics && isModernRoot) {
// When a mounted Suspense subtree gets hidden again, destroy any nested layout effects.
if ((node.flags & (RefStatic | LayoutStatic)) !== NoFlags) {
switch (node.tag) {
case FunctionComponent:
case ForwardRef:
case MemoComponent:
case SimpleMemoComponent: {
// Note that refs are attached by the useImperativeHandle() hook, not by commitAttachRef()
if (isHidden && !wasHidden) {
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
node.mode & ProfileMode
) {
try {
startLayoutEffectTimer();
commitHookEffectListUnmount(HookLayout, node, finishedWork);
} finally {
recordLayoutEffectDuration(node);
}
} else {
// TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic)
switch (node.tag) {
case FunctionComponent:
case ForwardRef:
case MemoComponent:
case SimpleMemoComponent: {
// Note that refs are attached by the useImperativeHandle() hook, not by commitAttachRef()
if (isHidden && !wasHidden) {
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
node.mode & ProfileMode
) {
try {
startLayoutEffectTimer();
commitHookEffectListUnmount(HookLayout, node, finishedWork);
} finally {
recordLayoutEffectDuration(node);
}
} else {
commitHookEffectListUnmount(HookLayout, node, finishedWork);
}
break;
}
case ClassComponent: {
if (isHidden && !wasHidden) {
if ((node.flags & RefStatic) !== NoFlags) {
safelyDetachRef(node, finishedWork);
}
const instance = node.stateNode;
if (typeof instance.componentWillUnmount === 'function') {
safelyCallComponentWillUnmount(node, finishedWork, instance);
}
break;
}
case ClassComponent: {
if (isHidden && !wasHidden) {
// TODO (Offscreen) Check: flags & RefStatic
safelyDetachRef(node, finishedWork);

const instance = node.stateNode;
if (typeof instance.componentWillUnmount === 'function') {
safelyCallComponentWillUnmount(node, finishedWork, instance);
}
break;
}
break;
}
}

Expand All @@ -1133,8 +1131,18 @@ function hideOrUnhideAllChildren(finishedWork, isHidden) {
if (node.return === null || node.return === finishedWork) {
return;
}

if (hiddenHostSubtreeRoot === node) {
hiddenHostSubtreeRoot = null;
}

node = node.return;
}

if (hiddenHostSubtreeRoot === node) {
hiddenHostSubtreeRoot = null;
}

node.sibling.return = node.return;
node = node.sibling;
}
Expand Down Expand Up @@ -2378,11 +2386,9 @@ function commitLayoutEffects_begin(
if (enableSuspenseLayoutEffectSemantics && isModernRoot) {
const visibilityChanged =
!offscreenSubtreeIsHidden && offscreenSubtreeWasHidden;
if (
visibilityChanged &&
(fiber.subtreeFlags & LayoutStatic) !== NoFlags &&
firstChild !== null
) {

// TODO (Offscreen) Also check: subtreeFlags & LayoutStatic
if (visibilityChanged && firstChild !== null) {
// We've just shown or hidden a Offscreen tree that contains layout effects.
// We only enter this code path for subtrees that are updated,
// because newly mounted ones would pass the LayoutMask check above.
Expand Down Expand Up @@ -2417,42 +2423,42 @@ function commitLayoutMountEffects_complete(
// Inside of an Offscreen subtree that changed visibility during this commit.
// If this subtree was hidden, layout effects will have already been destroyed (during mutation phase)
// but if it was just shown, we need to (re)create the effects now.
if ((fiber.flags & LayoutStatic) !== NoFlags) {
switch (fiber.tag) {
case FunctionComponent:
case ForwardRef:
case SimpleMemoComponent: {
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
fiber.mode & ProfileMode
) {
try {
startLayoutEffectTimer();
safelyCallCommitHookLayoutEffectListMount(fiber, fiber.return);
} finally {
recordLayoutEffectDuration(fiber);
}
} else {
// TODO (Offscreen) Check: flags & LayoutStatic
switch (fiber.tag) {
case FunctionComponent:
case ForwardRef:
case SimpleMemoComponent: {
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
fiber.mode & ProfileMode
) {
try {
startLayoutEffectTimer();
safelyCallCommitHookLayoutEffectListMount(fiber, fiber.return);
} finally {
recordLayoutEffectDuration(fiber);
}
break;
} else {
safelyCallCommitHookLayoutEffectListMount(fiber, fiber.return);
}
case ClassComponent: {
const instance = fiber.stateNode;
break;
}
case ClassComponent: {
const instance = fiber.stateNode;
if (typeof instance.componentDidMount === 'function') {
safelyCallComponentDidMount(fiber, fiber.return, instance);
break;
}
break;
}
}

if ((fiber.flags & RefStatic) !== NoFlags) {
switch (fiber.tag) {
case ClassComponent:
case HostComponent:
safelyAttachRef(fiber, fiber.return);
break;
}
// TODO (Offscreen) Check flags & RefStatic
switch (fiber.tag) {
case ClassComponent:
case HostComponent:
safelyAttachRef(fiber, fiber.return);
break;
}
} else if ((fiber.flags & LayoutMask) !== NoFlags) {
const current = fiber.alternate;
Expand Down