From fef4cffa1b581984b439b2a9474eb7207ca03449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nishan=20=28o=5E=E2=96=BD=5Eo=29?= Date: Mon, 19 Oct 2026 00:15:45 +0530 Subject: [PATCH 1/2] Fix flex shrink sizes when the first pass freezes items The second pass divided the remaining free space by the shrink total minus the frozen items' factors, and in float that subtraction leaves a residual (#2038, #1651). Sum the factors of the items that are not frozen instead, which is exactly 0 when none remain, and then send items to their lower bound (#931). --- tests/YGFlexShrinkAllFrozenTest.cpp | 186 ++++++++++++++++++++++++++++ yoga/algorithm/CalculateLayout.cpp | 39 ++++-- 2 files changed, 213 insertions(+), 12 deletions(-) create mode 100644 tests/YGFlexShrinkAllFrozenTest.cpp diff --git a/tests/YGFlexShrinkAllFrozenTest.cpp b/tests/YGFlexShrinkAllFrozenTest.cpp new file mode 100644 index 0000000000..18e5f65813 --- /dev/null +++ b/tests/YGFlexShrinkAllFrozenTest.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// Regression tests for flex shrink after the first pass freezes items: +// https://github.com/react/yoga/issues/2038, #1651 and #931. + +#include +#include + +namespace { + +const bool kWithoutErrata[] = {false, true}; + +YGConfigRef newConfig(bool withoutErrata) { + YGConfigRef config = YGConfigNew(); + if (withoutErrata) { + YGConfigSetErrata(config, YGErrataNone); + } + return config; +} + +// root (350 x 350) > row > [box, sibling (600 x 23)]. The box is the only +// shrinkable item, and its basis comes from its aspectRatio and the stretched +// height: 23 * 22/24 = 21.083334. +YGNodeRef newAspectRatioRow( + YGConfigRef config, + float shrink, + YGNodeRef* box, + YGNodeRef* sibling) { + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root, 350.0f); + YGNodeStyleSetHeight(root, 350.0f); + + YGNodeRef row = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(row, YGFlexDirectionRow); + YGNodeInsertChild(root, row, 0); + + *box = YGNodeNewWithConfig(config); + YGNodeStyleSetAspectRatio(*box, 22.0f / 24.0f); + YGNodeStyleSetFlexShrink(*box, shrink); + YGNodeInsertChild(row, *box, 0); + + *sibling = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(*sibling, 600.0f); + YGNodeStyleSetHeight(*sibling, 23.0f); + YGNodeInsertChild(row, *sibling, 1); + + return root; +} + +} // namespace + +// https://github.com/react/yoga/issues/2038 +// All items freeze at their minWidth. Removing them from the float total left a +// residual instead of 0. +TEST(YGFlexShrinkAllFrozen, all_items_frozen_at_min_width) { + for (bool withoutErrata : kWithoutErrata) { + YGConfigRef config = newConfig(withoutErrata); + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 350.0f); + YGNodeStyleSetHeight(root, 50.0f); + + const float widths[] = {100.1f, 200.3f, 300.7f}; + const float minWidths[] = {90.0f, 190.0f, 290.0f}; + for (size_t i = 0; i < 3; i++) { + YGNodeRef child = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(child, widths[i]); + YGNodeStyleSetMinWidth(child, minWidths[i]); + YGNodeStyleSetFlexShrink(child, 1.0f); + YGNodeInsertChild(root, child, i); + } + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + for (size_t i = 0; i < 3; i++) { + EXPECT_EQ(minWidths[i], YGNodeLayoutGetWidth(YGNodeGetChild(root, i))) + << "withoutErrata " << withoutErrata << ", child[" << i << "]"; + } + + YGNodeFreeRecursive(root); + YGConfigFree(config); + } +} + +// https://github.com/react/yoga/issues/931 +// An item with flexShrink 0.25 freezes at minHeight 25, but basis * (1 - +// flexShrink) left it at 113. +TEST(YGFlexShrinkAllFrozen, issue_931_shrink_below_one_freezes_at_min_height) { + for (bool withoutErrata : kWithoutErrata) { + YGConfigRef config = newConfig(withoutErrata); + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root, 500.0f); + YGNodeStyleSetHeight(root, 400.0f); + + YGNodeRef shrinking = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(shrinking, 100.0f); + YGNodeStyleSetHeight(shrinking, 100.0f); + YGNodeStyleSetMinHeight(shrinking, 25.0f); + YGNodeStyleSetMaxHeight(shrinking, 300.0f); + YGNodeStyleSetFlexBasis(shrinking, 150.0f); + YGNodeStyleSetFlexGrow(shrinking, 0.33f); + YGNodeStyleSetFlexShrink(shrinking, 0.25f); + YGNodeInsertChild(root, shrinking, 0); + + YGNodeRef fixed = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(fixed, 100.0f); + YGNodeStyleSetHeight(fixed, 200.0f); + YGNodeStyleSetMaxHeight(fixed, 200.0f); + YGNodeStyleSetFlexGrow(fixed, 1.0f); + YGNodeStyleSetFlexShrink(fixed, 0.0f); + YGNodeInsertChild(root, fixed, 1); + + YGNodeRef basis = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(basis, 100.0f); + YGNodeStyleSetMinHeight(basis, 200.0f); + YGNodeStyleSetFlexBasis(basis, 200.0f); + YGNodeStyleSetFlexShrink(basis, 0.0f); + YGNodeInsertChild(root, basis, 2); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + EXPECT_EQ(25.0f, YGNodeLayoutGetHeight(shrinking)) + << "withoutErrata " << withoutErrata; + + YGNodeFreeRecursive(root); + YGConfigFree(config); + } +} + +// https://github.com/react/yoga/issues/2038 +// The box freezes at 0, and freezing it left a 2^-19 residual. Shrink factors +// from #2039. +TEST(YGFlexShrinkAllFrozen, aspect_ratio_sole_shrinkable_item) { + const float shrinkFactors[] = { + 1.0f, 2.0f, 3.0f, 6.0f, 9.0f, 11.0f, 12.0f, 19.0f, 22.0f, 999.0f}; + + for (bool withoutErrata : kWithoutErrata) { + for (float shrink : shrinkFactors) { + YGConfigRef config = newConfig(withoutErrata); + YGNodeRef box = nullptr; + YGNodeRef sibling = nullptr; + YGNodeRef root = newAspectRatioRow(config, shrink, &box, &sibling); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + EXPECT_EQ(0.0f, YGNodeLayoutGetWidth(box)) + << "withoutErrata " << withoutErrata << ", flexShrink " << shrink; + EXPECT_EQ(0.0f, YGNodeLayoutGetHeight(box)) + << "withoutErrata " << withoutErrata << ", flexShrink " << shrink; + EXPECT_EQ(0.0f, YGNodeLayoutGetLeft(sibling)) + << "withoutErrata " << withoutErrata << ", flexShrink " << shrink; + + YGNodeFreeRecursive(root); + YGConfigFree(config); + } + } +} + +// https://github.com/react/yoga/issues/2038 +// With flexShrink 0 the box keeps its aspectRatio basis (21.08 x 23, rounded to +// 21 x 23). From #2039. +TEST(YGFlexShrinkAllFrozen, unshrinkable_item_keeps_aspect_ratio_basis) { + for (bool withoutErrata : kWithoutErrata) { + YGConfigRef config = newConfig(withoutErrata); + YGNodeRef box = nullptr; + YGNodeRef sibling = nullptr; + YGNodeRef root = newAspectRatioRow(config, 0.0f, &box, &sibling); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + EXPECT_EQ(21.0f, YGNodeLayoutGetWidth(box)) + << "withoutErrata " << withoutErrata; + EXPECT_EQ(23.0f, YGNodeLayoutGetHeight(box)) + << "withoutErrata " << withoutErrata; + EXPECT_EQ(21.0f, YGNodeLayoutGetLeft(sibling)) + << "withoutErrata " << withoutErrata; + + YGNodeFreeRecursive(root); + YGConfigFree(config); + } +} diff --git a/yoga/algorithm/CalculateLayout.cpp b/yoga/algorithm/CalculateLayout.cpp index e8998c0693..4214e31163 100644 --- a/yoga/algorithm/CalculateLayout.cpp +++ b/yoga/algorithm/CalculateLayout.cpp @@ -1104,16 +1104,11 @@ static float distributeFreeSpaceSecondPass( if (flexShrinkScaledFactor != 0) { float childSize = YGUndefined; - // Use a relative epsilon guard instead of exact equality: after the - // first pass removes all constrained items, - // totalFlexShrinkScaledFactors may be near-zero rather than exactly 0 - // due to floating-point cancellation. Dividing by a near-zero value - // produces a gigantic childSize that overwhelms the min/max clamp. - const float shrinkFactorMagnitude = - std::abs(flexLine.layout.totalFlexShrinkScaledFactors); - if (yoga::isDefined(flexLine.layout.totalFlexShrinkScaledFactors) && - shrinkFactorMagnitude < 1e-6f) { - childSize = childFlexBasis + flexShrinkScaledFactor; + // No item is left to share the free space with. Set item size to the + // smallest size, and let the clamp below raise it to the item's lower + // bound. + if (flexLine.layout.totalFlexShrinkScaledFactors == 0) { + childSize = 0; } else { childSize = childFlexBasis + (flexLine.layout.remainingFreeSpace / @@ -1300,6 +1295,14 @@ static void distributeFreeSpaceFirstPass( const float originalTotalFlexShrinkScaledFactors = flexLine.layout.totalFlexShrinkScaledFactors; + // Only read when useRunningTotals is set. + float runningTotalFlexShrinkScaledFactors = + originalTotalFlexShrinkScaledFactors; + // Sum of the factors of the unfrozen items, for the second pass. It is + // summed, not subtracted from the total, so it is exactly 0 when every item + // froze (https://github.com/react/yoga/issues/2038). + float unfrozenTotalFlexShrinkScaledFactors = 0; + for (auto currentLineChild : flexLine.itemsInFlow) { float childFlexBasis = boundAxisWithinMinAndMax( currentLineChild, @@ -1313,13 +1316,14 @@ static void distributeFreeSpaceFirstPass( if (flexLine.layout.remainingFreeSpace < 0) { flexShrinkScaledFactor = -currentLineChild->resolveFlexShrink() * childFlexBasis; + bool isFrozen = false; // Is this child able to shrink? if (yoga::isDefined(flexShrinkScaledFactor) && flexShrinkScaledFactor != 0) { baseMainSize = childFlexBasis + flexLine.layout.remainingFreeSpace / - (useRunningTotals ? flexLine.layout.totalFlexShrinkScaledFactors + (useRunningTotals ? runningTotalFlexShrinkScaledFactors : originalTotalFlexShrinkScaledFactors) * flexShrinkScaledFactor; boundMainSize = boundAxisWithAutoMin( @@ -1336,11 +1340,18 @@ static void distributeFreeSpaceFirstPass( // resulting in the item's size calculation being identical in the // first and second passes. deltaFreeSpace += boundMainSize - childFlexBasis; - flexLine.layout.totalFlexShrinkScaledFactors -= + runningTotalFlexShrinkScaledFactors -= (-currentLineChild->resolveFlexShrink() * currentLineChild->getLayout().computedFlexBasis.unwrap()); + isFrozen = true; } } + + if (!isFrozen && currentLineChild->isNodeFlexible()) { + unfrozenTotalFlexShrinkScaledFactors += + -currentLineChild->resolveFlexShrink() * + currentLineChild->getLayout().computedFlexBasis.unwrap(); + } } else if ( yoga::isDefined(flexLine.layout.remainingFreeSpace) && flexLine.layout.remainingFreeSpace > 0) { @@ -1373,6 +1384,10 @@ static void distributeFreeSpaceFirstPass( } } } + if (flexLine.layout.remainingFreeSpace < 0) { + flexLine.layout.totalFlexShrinkScaledFactors = + unfrozenTotalFlexShrinkScaledFactors; + } flexLine.layout.remainingFreeSpace -= deltaFreeSpace; } From c875527c627a1fe9067947b9002e86ea9a41a16c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nishan=20=28o=5E=E2=96=BD=5Eo=29?= Date: Tue, 20 Oct 2026 00:21:30 +0530 Subject: [PATCH 2/2] Treat a positive flex shrink total as float residual After the first pass subtracts the frozen items' scaled shrink factors, float cancellation can leave a residual instead of 0. When the residual was positive, the second pass divided by it and sized items in the billions (#2038, #1651). With non-negative flexShrink a real total is never positive, so positive totals now use the existing near-zero fallback. Negative residuals and all other layouts are unchanged. --- tests/YGFlexShrinkAllFrozenTest.cpp | 165 ++++++++++++++++++++-------- yoga/algorithm/CalculateLayout.cpp | 43 +++----- 2 files changed, 135 insertions(+), 73 deletions(-) diff --git a/tests/YGFlexShrinkAllFrozenTest.cpp b/tests/YGFlexShrinkAllFrozenTest.cpp index 18e5f65813..b6d71800dd 100644 --- a/tests/YGFlexShrinkAllFrozenTest.cpp +++ b/tests/YGFlexShrinkAllFrozenTest.cpp @@ -6,7 +6,7 @@ */ // Regression tests for flex shrink after the first pass freezes items: -// https://github.com/react/yoga/issues/2038, #1651 and #931. +// https://github.com/react/yoga/issues/2038 and #1651. #include #include @@ -52,6 +52,15 @@ YGNodeRef newAspectRatioRow( return root; } +YGSize measureHeightFromContext( + YGNodeConstRef node, + float /*width*/, + YGMeasureMode /*widthMode*/, + float /*height*/, + YGMeasureMode /*heightMode*/) { + return YGSize{1.0f, *static_cast(YGNodeGetContext(node))}; +} + } // namespace // https://github.com/react/yoga/issues/2038 @@ -87,51 +96,6 @@ TEST(YGFlexShrinkAllFrozen, all_items_frozen_at_min_width) { } } -// https://github.com/react/yoga/issues/931 -// An item with flexShrink 0.25 freezes at minHeight 25, but basis * (1 - -// flexShrink) left it at 113. -TEST(YGFlexShrinkAllFrozen, issue_931_shrink_below_one_freezes_at_min_height) { - for (bool withoutErrata : kWithoutErrata) { - YGConfigRef config = newConfig(withoutErrata); - YGNodeRef root = YGNodeNewWithConfig(config); - YGNodeStyleSetWidth(root, 500.0f); - YGNodeStyleSetHeight(root, 400.0f); - - YGNodeRef shrinking = YGNodeNewWithConfig(config); - YGNodeStyleSetWidth(shrinking, 100.0f); - YGNodeStyleSetHeight(shrinking, 100.0f); - YGNodeStyleSetMinHeight(shrinking, 25.0f); - YGNodeStyleSetMaxHeight(shrinking, 300.0f); - YGNodeStyleSetFlexBasis(shrinking, 150.0f); - YGNodeStyleSetFlexGrow(shrinking, 0.33f); - YGNodeStyleSetFlexShrink(shrinking, 0.25f); - YGNodeInsertChild(root, shrinking, 0); - - YGNodeRef fixed = YGNodeNewWithConfig(config); - YGNodeStyleSetWidth(fixed, 100.0f); - YGNodeStyleSetHeight(fixed, 200.0f); - YGNodeStyleSetMaxHeight(fixed, 200.0f); - YGNodeStyleSetFlexGrow(fixed, 1.0f); - YGNodeStyleSetFlexShrink(fixed, 0.0f); - YGNodeInsertChild(root, fixed, 1); - - YGNodeRef basis = YGNodeNewWithConfig(config); - YGNodeStyleSetWidth(basis, 100.0f); - YGNodeStyleSetMinHeight(basis, 200.0f); - YGNodeStyleSetFlexBasis(basis, 200.0f); - YGNodeStyleSetFlexShrink(basis, 0.0f); - YGNodeInsertChild(root, basis, 2); - - YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); - - EXPECT_EQ(25.0f, YGNodeLayoutGetHeight(shrinking)) - << "withoutErrata " << withoutErrata; - - YGNodeFreeRecursive(root); - YGConfigFree(config); - } -} - // https://github.com/react/yoga/issues/2038 // The box freezes at 0, and freezing it left a 2^-19 residual. Shrink factors // from #2039. @@ -184,3 +148,112 @@ TEST(YGFlexShrinkAllFrozen, unshrinkable_item_keeps_aspect_ratio_basis) { YGConfigFree(config); } } + +// https://github.com/react/yoga/issues/2038 +// The residual grows with the size of the total: here it is about 0.0078, far +// above any fixed near-zero threshold, but it is still positive. Pixel rounding +// is off so that each item can be compared with its exact minWidth. +TEST(YGFlexShrinkAllFrozen, large_total_residual_is_not_divided_by) { + for (bool withoutErrata : kWithoutErrata) { + YGConfigRef config = newConfig(withoutErrata); + YGConfigSetPointScaleFactor(config, 0.0f); + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 1000.0f); + YGNodeStyleSetHeight(root, 50.0f); + + const float widths[] = {10000.1f, 30000.7f, 34567.8f}; + for (size_t i = 0; i < 3; i++) { + YGNodeRef child = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(child, widths[i]); + YGNodeStyleSetMinWidth(child, widths[i] - 50.0f); + YGNodeStyleSetFlexShrink(child, 1.0f); + YGNodeInsertChild(root, child, i); + } + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + for (size_t i = 0; i < 3; i++) { + EXPECT_EQ( + widths[i] - 50.0f, YGNodeLayoutGetWidth(YGNodeGetChild(root, i))) + << "withoutErrata " << withoutErrata << ", child[" << i << "]"; + } + + YGNodeFreeRecursive(root); + YGConfigFree(config); + } +} + +// https://github.com/react/yoga/issues/2038 +// A tiny item stays unfrozen while the others freeze. Its factor (-1e-5) is +// below the float precision of the total, so the total after removing the +// frozen items was a positive residual instead of the tiny item's factor. +TEST(YGFlexShrinkAllFrozen, tiny_item_remains_after_others_freeze) { + for (bool withoutErrata : kWithoutErrata) { + YGConfigRef config = newConfig(withoutErrata); + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 350.0f); + YGNodeStyleSetHeight(root, 50.0f); + + const float widths[] = {100.1f, 200.3f, 300.7f, 0.00001f}; + const float minWidths[] = {90.0f, 190.0f, 290.0f, 0.0f}; + for (size_t i = 0; i < 4; i++) { + YGNodeRef child = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(child, widths[i]); + YGNodeStyleSetMinWidth(child, minWidths[i]); + YGNodeStyleSetFlexShrink(child, 1.0f); + YGNodeInsertChild(root, child, i); + } + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + for (size_t i = 0; i < 4; i++) { + EXPECT_EQ(minWidths[i], YGNodeLayoutGetWidth(YGNodeGetChild(root, i))) + << "withoutErrata " << withoutErrata << ", child[" << i << "]"; + } + + YGNodeFreeRecursive(root); + YGConfigFree(config); + } +} + +// https://github.com/react/yoga/issues/1651 +// Measured items freeze at their lower bound, which is 0 with the default +// errata and the content height without (automatic minimum size). The residual +// made them millions of points tall. +TEST(YGFlexShrinkAllFrozen, issue_1651_measured_items_freeze_at_lower_bound) { + for (bool withoutErrata : kWithoutErrata) { + YGConfigRef config = newConfig(withoutErrata); + YGConfigSetUseWebDefaults(config, true); + YGConfigSetPointScaleFactor(config, 100.0f); + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionColumn); + YGNodeStyleSetHeight(root, 99.0f); + + float heights[] = {10.01f, 10.01f, 12.01f}; + for (size_t i = 0; i < 3; i++) { + YGNodeRef child = YGNodeNewWithConfig(config); + YGNodeSetContext(child, &heights[i]); + YGNodeSetMeasureFunc(child, measureHeightFromContext); + YGNodeInsertChild(root, child, i); + } + YGNodeStyleSetMargin(YGNodeGetChild(root, 0), YGEdgeBottom, 100.0f); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + float top = 0.0f; + for (size_t i = 0; i < 3; i++) { + YGNodeRef child = YGNodeGetChild(root, i); + const float height = withoutErrata ? heights[i] : 0.0f; + EXPECT_FLOAT_EQ(height, YGNodeLayoutGetHeight(child)) + << "withoutErrata " << withoutErrata << ", child[" << i << "]"; + EXPECT_FLOAT_EQ(top, YGNodeLayoutGetTop(child)) + << "withoutErrata " << withoutErrata << ", child[" << i << "]"; + top += height + (i == 0 ? 100.0f : 0.0f); + } + + YGNodeFreeRecursive(root); + YGConfigFree(config); + } +} diff --git a/yoga/algorithm/CalculateLayout.cpp b/yoga/algorithm/CalculateLayout.cpp index 4214e31163..8526f148a7 100644 --- a/yoga/algorithm/CalculateLayout.cpp +++ b/yoga/algorithm/CalculateLayout.cpp @@ -1104,11 +1104,20 @@ static float distributeFreeSpaceSecondPass( if (flexShrinkScaledFactor != 0) { float childSize = YGUndefined; - // No item is left to share the free space with. Set item size to the - // smallest size, and let the clamp below raise it to the item's lower - // bound. - if (flexLine.layout.totalFlexShrinkScaledFactors == 0) { - childSize = 0; + // Use a relative epsilon guard instead of exact equality: after the + // first pass removes all constrained items, + // totalFlexShrinkScaledFactors may be near-zero rather than exactly 0 + // due to floating-point cancellation. Dividing by a near-zero value + // produces a gigantic childSize that overwhelms the min/max clamp. + // A positive total is always such a residual: with non-negative + // flexShrink a real total is never positive + // (https://github.com/react/yoga/issues/2038). + const float shrinkFactorMagnitude = + std::abs(flexLine.layout.totalFlexShrinkScaledFactors); + if (yoga::isDefined(flexLine.layout.totalFlexShrinkScaledFactors) && + (shrinkFactorMagnitude < 1e-6f || + flexLine.layout.totalFlexShrinkScaledFactors > 0)) { + childSize = childFlexBasis + flexShrinkScaledFactor; } else { childSize = childFlexBasis + (flexLine.layout.remainingFreeSpace / @@ -1295,14 +1304,6 @@ static void distributeFreeSpaceFirstPass( const float originalTotalFlexShrinkScaledFactors = flexLine.layout.totalFlexShrinkScaledFactors; - // Only read when useRunningTotals is set. - float runningTotalFlexShrinkScaledFactors = - originalTotalFlexShrinkScaledFactors; - // Sum of the factors of the unfrozen items, for the second pass. It is - // summed, not subtracted from the total, so it is exactly 0 when every item - // froze (https://github.com/react/yoga/issues/2038). - float unfrozenTotalFlexShrinkScaledFactors = 0; - for (auto currentLineChild : flexLine.itemsInFlow) { float childFlexBasis = boundAxisWithinMinAndMax( currentLineChild, @@ -1316,14 +1317,13 @@ static void distributeFreeSpaceFirstPass( if (flexLine.layout.remainingFreeSpace < 0) { flexShrinkScaledFactor = -currentLineChild->resolveFlexShrink() * childFlexBasis; - bool isFrozen = false; // Is this child able to shrink? if (yoga::isDefined(flexShrinkScaledFactor) && flexShrinkScaledFactor != 0) { baseMainSize = childFlexBasis + flexLine.layout.remainingFreeSpace / - (useRunningTotals ? runningTotalFlexShrinkScaledFactors + (useRunningTotals ? flexLine.layout.totalFlexShrinkScaledFactors : originalTotalFlexShrinkScaledFactors) * flexShrinkScaledFactor; boundMainSize = boundAxisWithAutoMin( @@ -1340,18 +1340,11 @@ static void distributeFreeSpaceFirstPass( // resulting in the item's size calculation being identical in the // first and second passes. deltaFreeSpace += boundMainSize - childFlexBasis; - runningTotalFlexShrinkScaledFactors -= + flexLine.layout.totalFlexShrinkScaledFactors -= (-currentLineChild->resolveFlexShrink() * currentLineChild->getLayout().computedFlexBasis.unwrap()); - isFrozen = true; } } - - if (!isFrozen && currentLineChild->isNodeFlexible()) { - unfrozenTotalFlexShrinkScaledFactors += - -currentLineChild->resolveFlexShrink() * - currentLineChild->getLayout().computedFlexBasis.unwrap(); - } } else if ( yoga::isDefined(flexLine.layout.remainingFreeSpace) && flexLine.layout.remainingFreeSpace > 0) { @@ -1384,10 +1377,6 @@ static void distributeFreeSpaceFirstPass( } } } - if (flexLine.layout.remainingFreeSpace < 0) { - flexLine.layout.totalFlexShrinkScaledFactors = - unfrozenTotalFlexShrinkScaledFactors; - } flexLine.layout.remainingFreeSpace -= deltaFreeSpace; }