From 9d5029c87326e682e559d4b7b331b95c02f68296 Mon Sep 17 00:00:00 2001 From: 5ZYSZ3K Date: Tue, 16 Jun 2026 15:29:19 -0700 Subject: [PATCH] fix: yoga crash with display:none Summary: It fixes this issue: https://github.com/react/react-native/issues/52349 Basically, in some rare cases, having an element with `display:none` style caused the app to crash. It was caused by a stale `hasNewLayout` flag on the hidden view That flag was always set in `computeFlexBasisForChildren` for elements with `display:none` style, but could be never consumed/reset, because of a cache hit or something. Since such elements contribute nothing to the layout sizes, I made the change to actually touch them only during actual layout passes ## Changelog: [GENERAL] [FIXED] - Crash: YogaLayoutableShadowNode.cpp: function layout: assertion failed (YGNodeGetOwner(childYogaNode) == &yogaNode_) https://github.com/react/react-native/issues/52349 X-link: https://github.com/react/react-native/pull/57197 Reviewed By: christophpurrer Differential Revision: D108796888 Pulled By: javache --- yoga/algorithm/CalculateLayout.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/yoga/algorithm/CalculateLayout.cpp b/yoga/algorithm/CalculateLayout.cpp index 1db7a5c21a..6e7814be2a 100644 --- a/yoga/algorithm/CalculateLayout.cpp +++ b/yoga/algorithm/CalculateLayout.cpp @@ -615,9 +615,18 @@ static float computeFlexBasisForChildren( for (auto child : children) { child->processDimensions(); if (child->style().display() == Display::None) { - zeroOutLayoutRecursively(child); - child->setHasNewLayout(true); - child->setDirty(false); + // Only mutate display: none children during layout passes. Zeroing them + // out during measure-only passes contributes nothing to the measurement, + // but sets `hasNewLayout` on nodes the parent's layout pass may never + // visit (e.g. when its layout is restored from cache, skipping + // `cloneChildrenIfNeeded()`). Such a leaked flag survives the commit and + // is copied into lazily-shared clones, later tripping the ownership + // assertion in `YogaLayoutableShadowNode::layout`. + if (performLayout) { + zeroOutLayoutRecursively(child); + child->setHasNewLayout(true); + child->setDirty(false); + } continue; } if (performLayout) {