From b7b1143b7b9f0b4893283471160d1ed0b3bf31be Mon Sep 17 00:00:00 2001 From: Jakub Piasecki Date: Mon, 13 Apr 2026 01:40:02 -0700 Subject: [PATCH] Fix node ownership when `display: contents` is used Summary: Changelog: [GENERAL][FIXED] Fixed Yoga node ownership when `display: contents` is used in absolutely positioned subtrees Fixes an edge case where nodes with `display: contents` weren't cloned properly inside absolutely positioned subtrees. Adds a test case covering this scenario. X-link: https://github.com/facebook/yoga/pull/1924 Differential Revision: D100581579 Pulled By: j-piasecki --- .../ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp | 1 + packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp index 181dfcb1b0de..4f14165d7e97 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp @@ -558,6 +558,7 @@ bool layoutAbsoluteDescendants( // we need to mutate these descendents. Make sure the path of // nodes to them is mutable before positioning. child->cloneChildrenIfNeeded(); + cleanupContentsNodesRecursively(child); const Direction childDirection = child->resolveDirection(currentNodeDirection); // By now all descendants of the containing block that are not absolute diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp index d42bd5f9e707..d04127733d3f 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp @@ -392,7 +392,12 @@ void Node::cloneChildrenIfNeeded() { child = resolveRef(config_->cloneNode(child, this, i)); child->setOwner(this); - if (child->hasContentsChildren()) [[unlikely]] { + if (child->style().display() == Display::Contents) [[unlikely]] { + // The contents node's children are treated as children of the + // contents node's parent for layout purposes, so they need + // to be cloned as well. + child->cloneChildrenIfNeeded(); + } else if (child->hasContentsChildren()) [[unlikely]] { child->cloneContentsChildrenIfNeeded(); } }