From 0a323a8ce10ab4d70683a7e7e144c95cb5916057 Mon Sep 17 00:00:00 2001 From: Eric Rozell Date: Thu, 29 Sep 2022 09:15:21 -0700 Subject: [PATCH] Stale flex basis value used with cached values Summary: We're occasionally seeing text truncation occur on Windows. It appears to occur when a cached main axis value is supplied to the flex basis computation for children, resulting in a stale flex basis value getting used. This diff just contributes a unit test that reliably reproduces this case. Differential Revision: D39929963 fbshipit-source-id: 5bae1de3f1498dbc45e42a76184d4269e01a12da --- tests/YGMeasureCacheTest.cpp | 93 +++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/tests/YGMeasureCacheTest.cpp b/tests/YGMeasureCacheTest.cpp index 60ad6f47c5..e1b6fbe60a 100644 --- a/tests/YGMeasureCacheTest.cpp +++ b/tests/YGMeasureCacheTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * 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. @@ -61,6 +61,41 @@ static YGSize _measure_84_49( }; } +static YGSize _real_text_measurement_example( + YGNodeRef node, + float width, + YGMeasureMode widthMode, + float height, + YGMeasureMode heightMode) { + if (YGFloatsEqual(width, 1000.f) && widthMode == YGMeasureModeAtMost && + heightMode == YGMeasureModeUndefined) { + return YGSize{ + .width = 502.f, + .height = 20.f, + }; + } else if ( + YGFloatsEqual(width, 501) && widthMode == YGMeasureModeAtMost && + heightMode == YGMeasureModeUndefined) { + return YGSize{ + .width = 462.f, + .height = 40.f, + }; + } else if ( + YGFloatsEqual(width, 501) && widthMode == YGMeasureModeAtMost && + heightMode == YGMeasureModeAtMost) { + return YGSize{ + .width = 462.f, + .height = height, + }; + } else { + // Unexpected measurement constraint + return YGSize{ + .width = 0.f, + .height = 0.f, + }; + } +} + TEST(YogaTest, measure_once_single_flexible_child) { const YGNodeRef root = YGNodeNew(); YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); @@ -180,3 +215,59 @@ TEST( ASSERT_EQ(1, measureCount); } + +TEST(YogaTest, avoid_stale_flex_basis) { + const YGNodeRef scroll = YGNodeNew(); + YGNodeStyleSetOverflow(scroll, YGOverflowScroll); + YGNodeStyleSetFlexGrow(scroll, 1); + YGNodeStyleSetFlexShrink(scroll, 1); + YGNodeStyleSetFlexDirection(scroll, YGFlexDirectionColumn); + + const YGNodeRef scrollContainer = YGNodeNew(); + YGNodeInsertChild(scroll, scrollContainer, 0); + + const YGNodeRef outerRow = YGNodeNew(); + YGNodeStyleSetFlexDirection(outerRow, YGFlexDirectionRow); + YGNodeInsertChild(scrollContainer, outerRow, 0); + + const YGNodeRef flexGrow = YGNodeNew(); + YGNodeStyleSetFlexGrow(flexGrow, 1); + YGNodeInsertChild(outerRow, flexGrow, 0); + + const YGNodeRef flex = YGNodeNew(); + YGNodeStyleSetFlex(flex, 1); + YGNodeInsertChild(flexGrow, flex, 0); + + const YGNodeRef innerRow = YGNodeNew(); + YGNodeStyleSetFlexDirection(innerRow, YGFlexDirectionRow); + YGNodeInsertChild(flex, innerRow, 0); + + const YGNodeRef view = YGNodeNew(); + YGNodeInsertChild(innerRow, view, 0); + + const YGNodeRef leaf = YGNodeNew(); + leaf->setMeasureFunc(_real_text_measurement_example); + YGNodeInsertChild(view, leaf, 0); + + // First measure + YGNodeCalculateLayout(scroll, 1000, 1000, YGDirectionLTR); + ASSERT_FLOAT_EQ(502, YGNodeLayoutGetWidth(leaf)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(leaf)); + + // Second measure + YGNodeCalculateLayout(scroll, 501, 1000, YGDirectionLTR); + ASSERT_FLOAT_EQ(462, YGNodeLayoutGetWidth(leaf)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(leaf)); + + // Third measure + YGNodeCalculateLayout(scroll, 502, 1000, YGDirectionLTR); + ASSERT_FLOAT_EQ(502, YGNodeLayoutGetWidth(leaf)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(leaf)); + + // Fourth measure + YGNodeCalculateLayout(scroll, 501, 1000, YGDirectionLTR); + ASSERT_FLOAT_EQ(462, YGNodeLayoutGetWidth(leaf)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(leaf)); + + YGNodeFreeRecursive(scroll); +}