Skip to content

Showing a hidden subtree again lays out shadow nodes the committed tree still uses - #59948

Open
casos92 wants to merge 1 commit into
react:mainfrom
casos92:export-D131235535
Open

casos92 wants to merge 1 commit into
react:mainfrom
casos92:export-D131235535

Conversation

@casos92

@casos92 casos92 commented Nov 11, 2026

Copy link
Copy Markdown

Summary:
The Bug

Showing a subtree hidden with <Activity mode="hidden"> again can abort debug builds with Attempt to mutate a sealed object (Sealable::ensureUnsealed, from YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector). Release builds have no assertion, so the same layout pass silently changes shadow nodes that the committed tree still uses.

The Cause

React keeps the instance of a hidden host component, commits a display: none clone of it that shares its children, and appends the instance itself again when the subtree is shown. Since react/yoga#2055, zeroing out a display: none subtree no longer clones children that are already zeroed out, so the committed tree can share a child that the kept instance owns. The instance was never appended, so it has no owner, and appending it again adopts it in place. Its layout then treats the shared child as its own and lays it out in place.

The Fix

YogaLayoutableShadowNode records when a node is cloned while it has no owner. Appending such a node clones it instead of adopting it in place, so the shared children get cloned before they are laid out. The clone is marked dirty, so children that hold a layout zeroed out under the hidden clone are laid out again. react/yoga#2055's optimization stays in place.

Changelog:
[General][Fixed] - Fix showing a subtree hidden with <Activity> laying out shadow nodes in place that the committed tree still uses, which crashed debug builds

Differential Revision: D131235535

…ee still uses

Summary:
**The Bug**

Showing a subtree hidden with `<Activity mode="hidden">` again can abort debug builds with `Attempt to mutate a sealed object` (`Sealable::ensureUnsealed`, from `YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector`). Release builds have no assertion, so the same layout pass silently changes shadow nodes that the committed tree still uses.

**The Cause**

React keeps the instance of a hidden host component, commits a `display: none` clone of it that shares its children, and appends the instance itself again when the subtree is shown. Since react/yoga#2055, zeroing out a `display: none` subtree no longer clones children that are already zeroed out, so the committed tree can share a child that the kept instance owns. The instance was never appended, so it has no owner, and appending it again adopts it in place. Its layout then treats the shared child as its own and lays it out in place.

**The Fix**

`YogaLayoutableShadowNode` records when a node is cloned while it has no owner. Appending such a node clones it instead of adopting it in place, so the shared children get cloned before they are laid out. The clone is marked dirty, so children that hold a layout zeroed out under the hidden clone are laid out again. react/yoga#2055's optimization stays in place.

Changelog:
[General][Fixed] - Fix showing a subtree hidden with `<Activity>` laying out shadow nodes in place that the committed tree still uses, which crashed debug builds

Differential Revision: D131235535
@meta-codesync

meta-codesync Bot commented Nov 11, 2026

Copy link
Copy Markdown

@casos92 has exported this pull request. If you are a Meta employee, you can view the originating Diff in D131235535.

@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 Nov 11, 2026

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. meta-exported p: Facebook Partner: Facebook Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant