Skip to content

Add a Fantom test for display: none subtrees not being cloned again - #59706

Draft
shubh73 wants to merge 1 commit into
react:mainfrom
shubh73:skip-recloning-zeroed-display-none
Draft

shubh73 wants to merge 1 commit into
react:mainfrom
shubh73:skip-recloning-zeroed-display-none

Conversation

@shubh73

@shubh73 shubh73 commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Summary:

react/yoga#2055 stops zeroOutLayoutRecursively from cloning display: none subtrees that are already zeroed out. Without it, every commit that lays out the parent of a hidden view clones every node under it (yogaNodeCloneCallbackConnector → cloneChildInPlace), and YogaLayoutableShadowNode::layout() never settles those clones because it doesn't descend into display: none. React commits re-run layout along the path to a change, so even a colour change pays it. On Android the differ then walks the freshly cloned subtrees too, since useTraitHiddenOnAndroid is off by default.

The cost grows with every screen kept mounted with display: none:

  • <Activity mode="hidden">
  • React Navigation 8 (alpha) stack, drawer and custom tabs (ActivityView)
  • React Navigation 7 with detachInactiveScreens={false} (Screen.tsx) or freezeOnBlur (react-freeze)
  • Expo Router headless tabs (expo-router/ui) (TabSlot.tsx)

#59113 fixed the related case where those subtrees dirtied their ancestors.

The Yoga change reaches React Native through the Yoga sync. This PR adds a Fantom test for it, so it should land after the sync. It's a draft until then.

On an OPPO CPH2667 (Android 16, RNTester release build), with N hidden screens of about 500 nodes each, the change brings the extra time per update to the visible screen at N = 10 from +13.0 ms to +5.9 ms. The details are in react/yoga#2055. Most of what remains is the differ walk that useTraitHiddenOnAndroid skips: with the flag on as well, it's +1.8 ms.

Changelog:

[INTERNAL] [ADDED] - Fantom test for display: none subtrees not being cloned on every commit

Test Plan:

View-hiddenSubtrees-itest.js adds two tests:

  • lays out a screen shown again after updates while it was hidden: hidden screens are updated while hidden and then shown, and must lay out the same as screens that were never hidden. This covers resizes around them, content added and removed while hidden, display: contents, nested display: none and non-absolute screens. It passes with and without Don't clone zeroed out display: none subtrees on every layout pass yoga#2055.
  • does not clone a hidden subtree when its parent is laid out again: a hidden descendant's ShadowNode revision must stay the same across React commits and a setNativeProps commit that lay out its parent. It fails on main ("Expected 1 but received 3") and passes with Don't clone zeroed out display: none subtrees on every layout pass yoga#2055 applied to the vendored copy.
yarn fantom packages/react-native/Libraries/Components/View/__tests__/View-hiddenSubtrees-itest.js

With react/yoga#2055 applied to the vendored copy and a Debug tester (react_native_assert on), the rest of the Fantom suite doesn't change.

🤖 Generated with Claude Code

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 31, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Oct 31, 2026
Tests that a hidden subtree isn't cloned on every commit that lays out
its parent, through React commits and setNativeProps, and that hidden
screens lay out the same as never-hidden ones once shown again.

The second test depends on react/yoga#2055 and fails until that change
is synced into the vendored copy of Yoga.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shubh73
shubh73 force-pushed the skip-recloning-zeroed-display-none branch from d0c6c7d to ec757d9 Compare October 31, 2026 02:11
@shubh73 shubh73 changed the title Don't clone zeroed out display: none subtrees on every layout pass Add a Fantom test for display: none subtrees not being cloned again Oct 31, 2026
@shubh73
shubh73 marked this pull request as draft October 31, 2026 02:11

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant