diff --git a/enums.py b/enums.py
index d43dd6c147..76b1355120 100755
--- a/enums.py
+++ b/enums.py
@@ -76,6 +76,9 @@
# Absolute nodes will resolve percentages against the inner size of
# their containing node, not the padding box
("AbsolutePercentAgainstInnerSize", 1 << 2),
+ # Applies a FitContent constraint in the main axis during flex basis
+ # computation for non-measure container nodes
+ ("FlexBasisFitContentInMainAxis", 1 << 3),
# Enable all incorrect behavior (preserve compatibility)
("All", 0x7FFFFFFF),
# Enable all errata except for "StretchFlexBasis" (Defaults behavior
diff --git a/gentest/fixtures/YGFlexBasisFitContentInMainAxisTest.html b/gentest/fixtures/YGFlexBasisFitContentInMainAxisTest.html
new file mode 100644
index 0000000000..56883e121f
--- /dev/null
+++ b/gentest/fixtures/YGFlexBasisFitContentInMainAxisTest.html
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/java/com/facebook/yoga/YogaErrata.java b/java/com/facebook/yoga/YogaErrata.java
index e0521b3fbb..3bd711beb5 100644
--- a/java/com/facebook/yoga/YogaErrata.java
+++ b/java/com/facebook/yoga/YogaErrata.java
@@ -14,6 +14,7 @@ public enum YogaErrata {
STRETCH_FLEX_BASIS(1),
ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING(2),
ABSOLUTE_PERCENT_AGAINST_INNER_SIZE(4),
+ FLEX_BASIS_FIT_CONTENT_IN_MAIN_AXIS(8),
ALL(2147483647),
CLASSIC(2147483646);
@@ -33,6 +34,7 @@ public static YogaErrata fromInt(int value) {
case 1: return STRETCH_FLEX_BASIS;
case 2: return ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING;
case 4: return ABSOLUTE_PERCENT_AGAINST_INNER_SIZE;
+ case 8: return FLEX_BASIS_FIT_CONTENT_IN_MAIN_AXIS;
case 2147483647: return ALL;
case 2147483646: return CLASSIC;
default: throw new IllegalArgumentException("Unknown enum value: " + value);
diff --git a/java/tests/generated/com/facebook/yoga/YGFlexBasisFitContentInMainAxisTest.java b/java/tests/generated/com/facebook/yoga/YGFlexBasisFitContentInMainAxisTest.java
new file mode 100644
index 0000000000..b41f3354b2
--- /dev/null
+++ b/java/tests/generated/com/facebook/yoga/YGFlexBasisFitContentInMainAxisTest.java
@@ -0,0 +1,458 @@
+/*
+ * 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.
+ *
+ * @generated SignedSource<<205adc3d98df4a065aef1c7cabfc7170>>
+ * generated by gentest/gentest-driver.ts from gentest/fixtures/YGFlexBasisFitContentInMainAxisTest.html
+ */
+
+package com.facebook.yoga;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import com.facebook.yoga.utils.TestUtils;
+
+@RunWith(Parameterized.class)
+public class YGFlexBasisFitContentInMainAxisTest {
+ @Parameterized.Parameters(name = "{0}")
+ public static Iterable nodeFactories() {
+ return TestParametrization.nodeFactories();
+ }
+
+ @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory;
+
+ @Test
+ public void test_container_child_overflows_definite_parent_column() {
+ YogaConfig config = YogaConfigFactory.create();
+
+ final YogaNode root = createNode(config);
+ root.setPositionType(YogaPositionType.ABSOLUTE);
+ root.setWidth(200f);
+ root.setHeight(300f);
+
+ final YogaNode root_child0 = createNode(config);
+ root.addChildAt(root_child0, 0);
+
+ final YogaNode root_child0_child0 = createNode(config);
+ root_child0_child0.setWidth(50f);
+ root_child0_child0.setHeight(500f);
+ root_child0.addChildAt(root_child0_child0, 0);
+ root.setDirection(YogaDirection.LTR);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(200f, root.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
+ assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child0_child0.getLayoutHeight(), 0.0f);
+
+ root.setDirection(YogaDirection.RTL);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(200f, root.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(150f, root_child0_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
+ assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child0_child0.getLayoutHeight(), 0.0f);
+ }
+
+ @Test
+ public void test_container_child_overflows_definite_parent_row() {
+ YogaConfig config = YogaConfigFactory.create();
+
+ final YogaNode root = createNode(config);
+ root.setFlexDirection(YogaFlexDirection.ROW);
+ root.setPositionType(YogaPositionType.ABSOLUTE);
+ root.setWidth(300f);
+ root.setHeight(200f);
+
+ final YogaNode root_child0 = createNode(config);
+ root.addChildAt(root_child0, 0);
+
+ final YogaNode root_child0_child0 = createNode(config);
+ root_child0_child0.setWidth(500f);
+ root_child0_child0.setHeight(50f);
+ root_child0.addChildAt(root_child0_child0, 0);
+ root.setDirection(YogaDirection.LTR);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(300f, root.getLayoutWidth(), 0.0f);
+ assertEquals(200f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(500f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
+ assertEquals(500f, root_child0_child0.getLayoutWidth(), 0.0f);
+ assertEquals(50f, root_child0_child0.getLayoutHeight(), 0.0f);
+
+ root.setDirection(YogaDirection.RTL);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(300f, root.getLayoutWidth(), 0.0f);
+ assertEquals(200f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(-200f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(500f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
+ assertEquals(500f, root_child0_child0.getLayoutWidth(), 0.0f);
+ assertEquals(50f, root_child0_child0.getLayoutHeight(), 0.0f);
+ }
+
+ @Test
+ public void test_container_child_within_bounds_column() {
+ YogaConfig config = YogaConfigFactory.create();
+
+ final YogaNode root = createNode(config);
+ root.setPositionType(YogaPositionType.ABSOLUTE);
+ root.setWidth(200f);
+ root.setHeight(300f);
+
+ final YogaNode root_child0 = createNode(config);
+ root.addChildAt(root_child0, 0);
+
+ final YogaNode root_child0_child0 = createNode(config);
+ root_child0_child0.setWidth(50f);
+ root_child0_child0.setHeight(100f);
+ root_child0.addChildAt(root_child0_child0, 0);
+ root.setDirection(YogaDirection.LTR);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(200f, root.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(100f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
+ assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f);
+ assertEquals(100f, root_child0_child0.getLayoutHeight(), 0.0f);
+
+ root.setDirection(YogaDirection.RTL);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(200f, root.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(100f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(150f, root_child0_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
+ assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f);
+ assertEquals(100f, root_child0_child0.getLayoutHeight(), 0.0f);
+ }
+
+ @Test
+ public void test_multiple_container_children_overflow_column() {
+ YogaConfig config = YogaConfigFactory.create();
+
+ final YogaNode root = createNode(config);
+ root.setPositionType(YogaPositionType.ABSOLUTE);
+ root.setWidth(200f);
+ root.setHeight(300f);
+
+ final YogaNode root_child0 = createNode(config);
+ root.addChildAt(root_child0, 0);
+
+ final YogaNode root_child0_child0 = createNode(config);
+ root_child0_child0.setHeight(400f);
+ root_child0.addChildAt(root_child0_child0, 0);
+
+ final YogaNode root_child1 = createNode(config);
+ root.addChildAt(root_child1, 1);
+
+ final YogaNode root_child1_child0 = createNode(config);
+ root_child1_child0.setHeight(500f);
+ root_child1.addChildAt(root_child1_child0, 0);
+ root.setDirection(YogaDirection.LTR);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(200f, root.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(400f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0_child0.getLayoutWidth(), 0.0f);
+ assertEquals(400f, root_child0_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child1.getLayoutX(), 0.0f);
+ assertEquals(400f, root_child1.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child1.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child1.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child1_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child1_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child1_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child1_child0.getLayoutHeight(), 0.0f);
+
+ root.setDirection(YogaDirection.RTL);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(200f, root.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(400f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0_child0.getLayoutWidth(), 0.0f);
+ assertEquals(400f, root_child0_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child1.getLayoutX(), 0.0f);
+ assertEquals(400f, root_child1.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child1.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child1.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child1_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child1_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child1_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child1_child0.getLayoutHeight(), 0.0f);
+ }
+
+ @Test
+ public void test_scroll_container_column() {
+ YogaConfig config = YogaConfigFactory.create();
+
+ final YogaNode root = createNode(config);
+ root.setPositionType(YogaPositionType.ABSOLUTE);
+ root.setOverflow(YogaOverflow.SCROLL);
+ root.setWidth(200f);
+ root.setHeight(300f);
+
+ final YogaNode root_child0 = createNode(config);
+ root.addChildAt(root_child0, 0);
+
+ final YogaNode root_child0_child0 = createNode(config);
+ root_child0_child0.setHeight(500f);
+ root_child0.addChildAt(root_child0_child0, 0);
+ root.setDirection(YogaDirection.LTR);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(200f, root.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child0_child0.getLayoutHeight(), 0.0f);
+
+ root.setDirection(YogaDirection.RTL);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(200f, root.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child0_child0.getLayoutHeight(), 0.0f);
+ }
+
+ @Test
+ public void test_explicit_and_container_children_column() {
+ YogaConfig config = YogaConfigFactory.create();
+
+ final YogaNode root = createNode(config);
+ root.setPositionType(YogaPositionType.ABSOLUTE);
+ root.setWidth(200f);
+ root.setHeight(300f);
+
+ final YogaNode root_child0 = createNode(config);
+ root_child0.setHeight(100f);
+ root.addChildAt(root_child0, 0);
+
+ final YogaNode root_child1 = createNode(config);
+ root.addChildAt(root_child1, 1);
+
+ final YogaNode root_child1_child0 = createNode(config);
+ root_child1_child0.setHeight(500f);
+ root_child1.addChildAt(root_child1_child0, 0);
+ root.setDirection(YogaDirection.LTR);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(200f, root.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(100f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child1.getLayoutX(), 0.0f);
+ assertEquals(100f, root_child1.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child1.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child1.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child1_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child1_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child1_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child1_child0.getLayoutHeight(), 0.0f);
+
+ root.setDirection(YogaDirection.RTL);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(200f, root.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(100f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child1.getLayoutX(), 0.0f);
+ assertEquals(100f, root_child1.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child1.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child1.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child1_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child1_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child1_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child1_child0.getLayoutHeight(), 0.0f);
+ }
+
+ @Test
+ public void test_flex_basis_in_scroll_content_container() {
+ YogaConfig config = YogaConfigFactory.create();
+
+ final YogaNode root = createNode(config);
+ root.setPositionType(YogaPositionType.ABSOLUTE);
+ root.setOverflow(YogaOverflow.SCROLL);
+ root.setWidth(200f);
+ root.setHeight(300f);
+
+ final YogaNode root_child0 = createNode(config);
+ root.addChildAt(root_child0, 0);
+
+ final YogaNode root_child0_child0 = createNode(config);
+ root_child0_child0.setFlexBasis(200f);
+ root_child0.addChildAt(root_child0_child0, 0);
+
+ final YogaNode root_child0_child1 = createNode(config);
+ root_child0_child1.setFlexBasis(300f);
+ root_child0.addChildAt(root_child0_child1, 1);
+ root.setDirection(YogaDirection.LTR);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(200f, root.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0_child0.getLayoutWidth(), 0.0f);
+ assertEquals(200f, root_child0_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0_child1.getLayoutX(), 0.0f);
+ assertEquals(200f, root_child0_child1.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0_child1.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root_child0_child1.getLayoutHeight(), 0.0f);
+
+ root.setDirection(YogaDirection.RTL);
+ root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
+
+ assertEquals(0f, root.getLayoutX(), 0.0f);
+ assertEquals(0f, root.getLayoutY(), 0.0f);
+ assertEquals(200f, root.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0.getLayoutWidth(), 0.0f);
+ assertEquals(500f, root_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f);
+ assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0_child0.getLayoutWidth(), 0.0f);
+ assertEquals(200f, root_child0_child0.getLayoutHeight(), 0.0f);
+
+ assertEquals(0f, root_child0_child1.getLayoutX(), 0.0f);
+ assertEquals(200f, root_child0_child1.getLayoutY(), 0.0f);
+ assertEquals(200f, root_child0_child1.getLayoutWidth(), 0.0f);
+ assertEquals(300f, root_child0_child1.getLayoutHeight(), 0.0f);
+ }
+
+ private YogaNode createNode(YogaConfig config) {
+ return mNodeFactory.create(config);
+ }
+}
diff --git a/javascript/src/generated/YGEnums.ts b/javascript/src/generated/YGEnums.ts
index f389fe2fdf..3a870db8c2 100644
--- a/javascript/src/generated/YGEnums.ts
+++ b/javascript/src/generated/YGEnums.ts
@@ -58,6 +58,7 @@ export enum Errata {
StretchFlexBasis = 1,
AbsolutePositionWithoutInsetsExcludesPadding = 2,
AbsolutePercentAgainstInnerSize = 4,
+ FlexBasisFitContentInMainAxis = 8,
All = 2147483647,
Classic = 2147483646,
}
@@ -169,6 +170,7 @@ const constants = {
ERRATA_STRETCH_FLEX_BASIS: Errata.StretchFlexBasis,
ERRATA_ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING: Errata.AbsolutePositionWithoutInsetsExcludesPadding,
ERRATA_ABSOLUTE_PERCENT_AGAINST_INNER_SIZE: Errata.AbsolutePercentAgainstInnerSize,
+ ERRATA_FLEX_BASIS_FIT_CONTENT_IN_MAIN_AXIS: Errata.FlexBasisFitContentInMainAxis,
ERRATA_ALL: Errata.All,
ERRATA_CLASSIC: Errata.Classic,
EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS: ExperimentalFeature.WebFlexBasis,
diff --git a/javascript/tests/generated/YGFlexBasisFitContentInMainAxisTest.test.ts b/javascript/tests/generated/YGFlexBasisFitContentInMainAxisTest.test.ts
new file mode 100644
index 0000000000..85c657fed5
--- /dev/null
+++ b/javascript/tests/generated/YGFlexBasisFitContentInMainAxisTest.test.ts
@@ -0,0 +1,490 @@
+/**
+ * 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.
+ *
+ * @generated SignedSource<>
+ * generated by gentest/gentest-driver.ts from gentest/fixtures/YGFlexBasisFitContentInMainAxisTest.html
+ */
+
+import { instrinsicSizeMeasureFunc } from '../tools/utils.ts'
+import Yoga from 'yoga-layout';
+import {
+ Align,
+ BoxSizing,
+ Direction,
+ Display,
+ Edge,
+ Errata,
+ ExperimentalFeature,
+ FlexDirection,
+ Gutter,
+ Justify,
+ MeasureMode,
+ Overflow,
+ PositionType,
+ Unit,
+ Wrap,
+} from 'yoga-layout';
+
+test('container_child_overflows_definite_parent_column', () => {
+ const config = Yoga.Config.create();
+ let root;
+
+ try {
+ root = Yoga.Node.create(config);
+ root.setPositionType(PositionType.Absolute);
+ root.setWidth(200);
+ root.setHeight(300);
+
+ const root_child0 = Yoga.Node.create(config);
+ root.insertChild(root_child0, 0);
+
+ const root_child0_child0 = Yoga.Node.create(config);
+ root_child0_child0.setWidth(50);
+ root_child0_child0.setHeight(500);
+ root_child0.insertChild(root_child0_child0, 0);
+ root.calculateLayout(undefined, undefined, Direction.LTR);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(200);
+ expect(root.getComputedHeight()).toBe(300);
+
+ expect(root_child0.getComputedLeft()).toBe(0);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(200);
+ expect(root_child0.getComputedHeight()).toBe(500);
+
+ expect(root_child0_child0.getComputedLeft()).toBe(0);
+ expect(root_child0_child0.getComputedTop()).toBe(0);
+ expect(root_child0_child0.getComputedWidth()).toBe(50);
+ expect(root_child0_child0.getComputedHeight()).toBe(500);
+
+ root.calculateLayout(undefined, undefined, Direction.RTL);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(200);
+ expect(root.getComputedHeight()).toBe(300);
+
+ expect(root_child0.getComputedLeft()).toBe(0);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(200);
+ expect(root_child0.getComputedHeight()).toBe(500);
+
+ expect(root_child0_child0.getComputedLeft()).toBe(150);
+ expect(root_child0_child0.getComputedTop()).toBe(0);
+ expect(root_child0_child0.getComputedWidth()).toBe(50);
+ expect(root_child0_child0.getComputedHeight()).toBe(500);
+ } finally {
+ if (typeof root !== 'undefined') {
+ root.freeRecursive();
+ }
+
+ config.free();
+ }
+});
+test('container_child_overflows_definite_parent_row', () => {
+ const config = Yoga.Config.create();
+ let root;
+
+ try {
+ root = Yoga.Node.create(config);
+ root.setFlexDirection(FlexDirection.Row);
+ root.setPositionType(PositionType.Absolute);
+ root.setWidth(300);
+ root.setHeight(200);
+
+ const root_child0 = Yoga.Node.create(config);
+ root.insertChild(root_child0, 0);
+
+ const root_child0_child0 = Yoga.Node.create(config);
+ root_child0_child0.setWidth(500);
+ root_child0_child0.setHeight(50);
+ root_child0.insertChild(root_child0_child0, 0);
+ root.calculateLayout(undefined, undefined, Direction.LTR);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(300);
+ expect(root.getComputedHeight()).toBe(200);
+
+ expect(root_child0.getComputedLeft()).toBe(0);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(500);
+ expect(root_child0.getComputedHeight()).toBe(200);
+
+ expect(root_child0_child0.getComputedLeft()).toBe(0);
+ expect(root_child0_child0.getComputedTop()).toBe(0);
+ expect(root_child0_child0.getComputedWidth()).toBe(500);
+ expect(root_child0_child0.getComputedHeight()).toBe(50);
+
+ root.calculateLayout(undefined, undefined, Direction.RTL);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(300);
+ expect(root.getComputedHeight()).toBe(200);
+
+ expect(root_child0.getComputedLeft()).toBe(-200);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(500);
+ expect(root_child0.getComputedHeight()).toBe(200);
+
+ expect(root_child0_child0.getComputedLeft()).toBe(0);
+ expect(root_child0_child0.getComputedTop()).toBe(0);
+ expect(root_child0_child0.getComputedWidth()).toBe(500);
+ expect(root_child0_child0.getComputedHeight()).toBe(50);
+ } finally {
+ if (typeof root !== 'undefined') {
+ root.freeRecursive();
+ }
+
+ config.free();
+ }
+});
+test('container_child_within_bounds_column', () => {
+ const config = Yoga.Config.create();
+ let root;
+
+ try {
+ root = Yoga.Node.create(config);
+ root.setPositionType(PositionType.Absolute);
+ root.setWidth(200);
+ root.setHeight(300);
+
+ const root_child0 = Yoga.Node.create(config);
+ root.insertChild(root_child0, 0);
+
+ const root_child0_child0 = Yoga.Node.create(config);
+ root_child0_child0.setWidth(50);
+ root_child0_child0.setHeight(100);
+ root_child0.insertChild(root_child0_child0, 0);
+ root.calculateLayout(undefined, undefined, Direction.LTR);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(200);
+ expect(root.getComputedHeight()).toBe(300);
+
+ expect(root_child0.getComputedLeft()).toBe(0);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(200);
+ expect(root_child0.getComputedHeight()).toBe(100);
+
+ expect(root_child0_child0.getComputedLeft()).toBe(0);
+ expect(root_child0_child0.getComputedTop()).toBe(0);
+ expect(root_child0_child0.getComputedWidth()).toBe(50);
+ expect(root_child0_child0.getComputedHeight()).toBe(100);
+
+ root.calculateLayout(undefined, undefined, Direction.RTL);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(200);
+ expect(root.getComputedHeight()).toBe(300);
+
+ expect(root_child0.getComputedLeft()).toBe(0);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(200);
+ expect(root_child0.getComputedHeight()).toBe(100);
+
+ expect(root_child0_child0.getComputedLeft()).toBe(150);
+ expect(root_child0_child0.getComputedTop()).toBe(0);
+ expect(root_child0_child0.getComputedWidth()).toBe(50);
+ expect(root_child0_child0.getComputedHeight()).toBe(100);
+ } finally {
+ if (typeof root !== 'undefined') {
+ root.freeRecursive();
+ }
+
+ config.free();
+ }
+});
+test('multiple_container_children_overflow_column', () => {
+ const config = Yoga.Config.create();
+ let root;
+
+ try {
+ root = Yoga.Node.create(config);
+ root.setPositionType(PositionType.Absolute);
+ root.setWidth(200);
+ root.setHeight(300);
+
+ const root_child0 = Yoga.Node.create(config);
+ root.insertChild(root_child0, 0);
+
+ const root_child0_child0 = Yoga.Node.create(config);
+ root_child0_child0.setHeight(400);
+ root_child0.insertChild(root_child0_child0, 0);
+
+ const root_child1 = Yoga.Node.create(config);
+ root.insertChild(root_child1, 1);
+
+ const root_child1_child0 = Yoga.Node.create(config);
+ root_child1_child0.setHeight(500);
+ root_child1.insertChild(root_child1_child0, 0);
+ root.calculateLayout(undefined, undefined, Direction.LTR);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(200);
+ expect(root.getComputedHeight()).toBe(300);
+
+ expect(root_child0.getComputedLeft()).toBe(0);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(200);
+ expect(root_child0.getComputedHeight()).toBe(400);
+
+ expect(root_child0_child0.getComputedLeft()).toBe(0);
+ expect(root_child0_child0.getComputedTop()).toBe(0);
+ expect(root_child0_child0.getComputedWidth()).toBe(200);
+ expect(root_child0_child0.getComputedHeight()).toBe(400);
+
+ expect(root_child1.getComputedLeft()).toBe(0);
+ expect(root_child1.getComputedTop()).toBe(400);
+ expect(root_child1.getComputedWidth()).toBe(200);
+ expect(root_child1.getComputedHeight()).toBe(500);
+
+ expect(root_child1_child0.getComputedLeft()).toBe(0);
+ expect(root_child1_child0.getComputedTop()).toBe(0);
+ expect(root_child1_child0.getComputedWidth()).toBe(200);
+ expect(root_child1_child0.getComputedHeight()).toBe(500);
+
+ root.calculateLayout(undefined, undefined, Direction.RTL);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(200);
+ expect(root.getComputedHeight()).toBe(300);
+
+ expect(root_child0.getComputedLeft()).toBe(0);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(200);
+ expect(root_child0.getComputedHeight()).toBe(400);
+
+ expect(root_child0_child0.getComputedLeft()).toBe(0);
+ expect(root_child0_child0.getComputedTop()).toBe(0);
+ expect(root_child0_child0.getComputedWidth()).toBe(200);
+ expect(root_child0_child0.getComputedHeight()).toBe(400);
+
+ expect(root_child1.getComputedLeft()).toBe(0);
+ expect(root_child1.getComputedTop()).toBe(400);
+ expect(root_child1.getComputedWidth()).toBe(200);
+ expect(root_child1.getComputedHeight()).toBe(500);
+
+ expect(root_child1_child0.getComputedLeft()).toBe(0);
+ expect(root_child1_child0.getComputedTop()).toBe(0);
+ expect(root_child1_child0.getComputedWidth()).toBe(200);
+ expect(root_child1_child0.getComputedHeight()).toBe(500);
+ } finally {
+ if (typeof root !== 'undefined') {
+ root.freeRecursive();
+ }
+
+ config.free();
+ }
+});
+test('scroll_container_column', () => {
+ const config = Yoga.Config.create();
+ let root;
+
+ try {
+ root = Yoga.Node.create(config);
+ root.setPositionType(PositionType.Absolute);
+ root.setOverflow(Overflow.Scroll);
+ root.setWidth(200);
+ root.setHeight(300);
+
+ const root_child0 = Yoga.Node.create(config);
+ root.insertChild(root_child0, 0);
+
+ const root_child0_child0 = Yoga.Node.create(config);
+ root_child0_child0.setHeight(500);
+ root_child0.insertChild(root_child0_child0, 0);
+ root.calculateLayout(undefined, undefined, Direction.LTR);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(200);
+ expect(root.getComputedHeight()).toBe(300);
+
+ expect(root_child0.getComputedLeft()).toBe(0);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(200);
+ expect(root_child0.getComputedHeight()).toBe(500);
+
+ expect(root_child0_child0.getComputedLeft()).toBe(0);
+ expect(root_child0_child0.getComputedTop()).toBe(0);
+ expect(root_child0_child0.getComputedWidth()).toBe(200);
+ expect(root_child0_child0.getComputedHeight()).toBe(500);
+
+ root.calculateLayout(undefined, undefined, Direction.RTL);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(200);
+ expect(root.getComputedHeight()).toBe(300);
+
+ expect(root_child0.getComputedLeft()).toBe(0);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(200);
+ expect(root_child0.getComputedHeight()).toBe(500);
+
+ expect(root_child0_child0.getComputedLeft()).toBe(0);
+ expect(root_child0_child0.getComputedTop()).toBe(0);
+ expect(root_child0_child0.getComputedWidth()).toBe(200);
+ expect(root_child0_child0.getComputedHeight()).toBe(500);
+ } finally {
+ if (typeof root !== 'undefined') {
+ root.freeRecursive();
+ }
+
+ config.free();
+ }
+});
+test('explicit_and_container_children_column', () => {
+ const config = Yoga.Config.create();
+ let root;
+
+ try {
+ root = Yoga.Node.create(config);
+ root.setPositionType(PositionType.Absolute);
+ root.setWidth(200);
+ root.setHeight(300);
+
+ const root_child0 = Yoga.Node.create(config);
+ root_child0.setHeight(100);
+ root.insertChild(root_child0, 0);
+
+ const root_child1 = Yoga.Node.create(config);
+ root.insertChild(root_child1, 1);
+
+ const root_child1_child0 = Yoga.Node.create(config);
+ root_child1_child0.setHeight(500);
+ root_child1.insertChild(root_child1_child0, 0);
+ root.calculateLayout(undefined, undefined, Direction.LTR);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(200);
+ expect(root.getComputedHeight()).toBe(300);
+
+ expect(root_child0.getComputedLeft()).toBe(0);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(200);
+ expect(root_child0.getComputedHeight()).toBe(100);
+
+ expect(root_child1.getComputedLeft()).toBe(0);
+ expect(root_child1.getComputedTop()).toBe(100);
+ expect(root_child1.getComputedWidth()).toBe(200);
+ expect(root_child1.getComputedHeight()).toBe(500);
+
+ expect(root_child1_child0.getComputedLeft()).toBe(0);
+ expect(root_child1_child0.getComputedTop()).toBe(0);
+ expect(root_child1_child0.getComputedWidth()).toBe(200);
+ expect(root_child1_child0.getComputedHeight()).toBe(500);
+
+ root.calculateLayout(undefined, undefined, Direction.RTL);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(200);
+ expect(root.getComputedHeight()).toBe(300);
+
+ expect(root_child0.getComputedLeft()).toBe(0);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(200);
+ expect(root_child0.getComputedHeight()).toBe(100);
+
+ expect(root_child1.getComputedLeft()).toBe(0);
+ expect(root_child1.getComputedTop()).toBe(100);
+ expect(root_child1.getComputedWidth()).toBe(200);
+ expect(root_child1.getComputedHeight()).toBe(500);
+
+ expect(root_child1_child0.getComputedLeft()).toBe(0);
+ expect(root_child1_child0.getComputedTop()).toBe(0);
+ expect(root_child1_child0.getComputedWidth()).toBe(200);
+ expect(root_child1_child0.getComputedHeight()).toBe(500);
+ } finally {
+ if (typeof root !== 'undefined') {
+ root.freeRecursive();
+ }
+
+ config.free();
+ }
+});
+test('flex_basis_in_scroll_content_container', () => {
+ const config = Yoga.Config.create();
+ let root;
+
+ try {
+ root = Yoga.Node.create(config);
+ root.setPositionType(PositionType.Absolute);
+ root.setOverflow(Overflow.Scroll);
+ root.setWidth(200);
+ root.setHeight(300);
+
+ const root_child0 = Yoga.Node.create(config);
+ root.insertChild(root_child0, 0);
+
+ const root_child0_child0 = Yoga.Node.create(config);
+ root_child0_child0.setFlexBasis(200);
+ root_child0.insertChild(root_child0_child0, 0);
+
+ const root_child0_child1 = Yoga.Node.create(config);
+ root_child0_child1.setFlexBasis(300);
+ root_child0.insertChild(root_child0_child1, 1);
+ root.calculateLayout(undefined, undefined, Direction.LTR);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(200);
+ expect(root.getComputedHeight()).toBe(300);
+
+ expect(root_child0.getComputedLeft()).toBe(0);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(200);
+ expect(root_child0.getComputedHeight()).toBe(500);
+
+ expect(root_child0_child0.getComputedLeft()).toBe(0);
+ expect(root_child0_child0.getComputedTop()).toBe(0);
+ expect(root_child0_child0.getComputedWidth()).toBe(200);
+ expect(root_child0_child0.getComputedHeight()).toBe(200);
+
+ expect(root_child0_child1.getComputedLeft()).toBe(0);
+ expect(root_child0_child1.getComputedTop()).toBe(200);
+ expect(root_child0_child1.getComputedWidth()).toBe(200);
+ expect(root_child0_child1.getComputedHeight()).toBe(300);
+
+ root.calculateLayout(undefined, undefined, Direction.RTL);
+
+ expect(root.getComputedLeft()).toBe(0);
+ expect(root.getComputedTop()).toBe(0);
+ expect(root.getComputedWidth()).toBe(200);
+ expect(root.getComputedHeight()).toBe(300);
+
+ expect(root_child0.getComputedLeft()).toBe(0);
+ expect(root_child0.getComputedTop()).toBe(0);
+ expect(root_child0.getComputedWidth()).toBe(200);
+ expect(root_child0.getComputedHeight()).toBe(500);
+
+ expect(root_child0_child0.getComputedLeft()).toBe(0);
+ expect(root_child0_child0.getComputedTop()).toBe(0);
+ expect(root_child0_child0.getComputedWidth()).toBe(200);
+ expect(root_child0_child0.getComputedHeight()).toBe(200);
+
+ expect(root_child0_child1.getComputedLeft()).toBe(0);
+ expect(root_child0_child1.getComputedTop()).toBe(200);
+ expect(root_child0_child1.getComputedWidth()).toBe(200);
+ expect(root_child0_child1.getComputedHeight()).toBe(300);
+ } finally {
+ if (typeof root !== 'undefined') {
+ root.freeRecursive();
+ }
+
+ config.free();
+ }
+});
diff --git a/tests/YGDefaultValuesTest.cpp b/tests/YGDefaultValuesTest.cpp
index 09c74ce8c6..d52f4878f3 100644
--- a/tests/YGDefaultValuesTest.cpp
+++ b/tests/YGDefaultValuesTest.cpp
@@ -118,7 +118,10 @@ TEST(YogaTest, assert_webdefault_values_reset) {
TEST(YogaTest, assert_legacy_stretch_behaviour) {
YGConfig* config = YGConfigNew();
- YGConfigSetErrata(config, YGErrataStretchFlexBasis);
+ YGConfigSetErrata(
+ config,
+ static_cast(
+ YGErrataStretchFlexBasis | YGErrataFlexBasisFitContentInMainAxis));
YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root, 500);
YGNodeStyleSetHeight(root, 500);
diff --git a/tests/YGFlexBasisFitContentInMainAxisTest.cpp b/tests/YGFlexBasisFitContentInMainAxisTest.cpp
new file mode 100644
index 0000000000..3cbc6abc67
--- /dev/null
+++ b/tests/YGFlexBasisFitContentInMainAxisTest.cpp
@@ -0,0 +1,310 @@
+/*
+ * 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.
+ */
+
+#include
+#include
+
+// Tests for the FlexBasisFitContentInMainAxis errata.
+//
+// For non-scroll container nodes, FitContent and MaxContent produce the same
+// final dimensions (both use content-based sizing). The errata primarily
+// affects re-measurement/caching behavior (performance), not layout values.
+//
+// The one visible layout difference is Check 1: when mainAxisSize is NaN
+// (e.g. inside a scroll content container), the errata causes flex-basis
+// to be ignored, while the corrected behavior accepts positive flex-basis
+// regardless of mainAxisSize.
+
+// Verify that container children produce the same layout regardless of errata
+// when the child's content overflows a definite-height column parent.
+// FitContent and MaxContent both resolve to content size for containers.
+TEST(YogaTest, flex_basis_fit_content_errata_column_same_layout) {
+ // With errata
+ {
+ YGConfigRef config = YGConfigNew();
+ YGConfigSetErrata(config, YGErrataFlexBasisFitContentInMainAxis);
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetWidth(root, 200);
+ YGNodeStyleSetHeight(root, 300);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetWidth(root_child0_child0, 50);
+ YGNodeStyleSetHeight(root_child0_child0, 500);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ // Container child gets content height (500) even with FitContent errata,
+ // because FitContent and MaxContent produce the same result for containers.
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeFreeRecursive(root);
+ YGConfigFree(config);
+ }
+
+ // Without errata (same result)
+ {
+ YGConfigRef config = YGConfigNew();
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetWidth(root, 200);
+ YGNodeStyleSetHeight(root, 300);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetWidth(root_child0_child0, 50);
+ YGNodeStyleSetHeight(root_child0_child0, 500);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeFreeRecursive(root);
+ YGConfigFree(config);
+ }
+}
+
+// Same test but for row direction.
+TEST(YogaTest, flex_basis_fit_content_errata_row_same_layout) {
+ // With errata
+ {
+ YGConfigRef config = YGConfigNew();
+ YGConfigSetErrata(config, YGErrataFlexBasisFitContentInMainAxis);
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+ YGNodeStyleSetWidth(root, 300);
+ YGNodeStyleSetHeight(root, 200);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetWidth(root_child0_child0, 500);
+ YGNodeStyleSetHeight(root_child0_child0, 50);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeFreeRecursive(root);
+ YGConfigFree(config);
+ }
+
+ // Without errata (same result)
+ {
+ YGConfigRef config = YGConfigNew();
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+ YGNodeStyleSetWidth(root, 300);
+ YGNodeStyleSetHeight(root, 200);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetWidth(root_child0_child0, 500);
+ YGNodeStyleSetHeight(root_child0_child0, 50);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeFreeRecursive(root);
+ YGConfigFree(config);
+ }
+}
+
+// Scroll containers use MaxContent in main axis regardless of errata.
+TEST(YogaTest, flex_basis_fit_content_errata_scroll_same_layout) {
+ // With errata
+ {
+ YGConfigRef config = YGConfigNew();
+ YGConfigSetErrata(config, YGErrataFlexBasisFitContentInMainAxis);
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetWidth(root, 200);
+ YGNodeStyleSetHeight(root, 300);
+ YGNodeStyleSetOverflow(root, YGOverflowScroll);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetHeight(root_child0_child0, 500);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeFreeRecursive(root);
+ YGConfigFree(config);
+ }
+
+ // Without errata (same result)
+ {
+ YGConfigRef config = YGConfigNew();
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetWidth(root, 200);
+ YGNodeStyleSetHeight(root, 300);
+ YGNodeStyleSetOverflow(root, YGOverflowScroll);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetHeight(root_child0_child0, 500);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeFreeRecursive(root);
+ YGConfigFree(config);
+ }
+}
+
+// With errata: flex-basis is ignored when mainAxisSize is NaN, because the
+// old condition requires isDefined(mainAxisSize). Items inside a scroll
+// container's auto-height content container get height 0.
+TEST(YogaTest, flex_basis_in_scroll_content_with_errata) {
+ YGConfigRef config = YGConfigNew();
+ YGConfigSetErrata(config, YGErrataFlexBasisFitContentInMainAxis);
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetWidth(root, 200);
+ YGNodeStyleSetHeight(root, 300);
+ YGNodeStyleSetOverflow(root, YGOverflowScroll);
+
+ // Content container: auto height, measured with MaxContent by scroll parent
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetFlexBasis(root_child0_child0, 200);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+ YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetFlexBasis(root_child0_child1, 300);
+ YGNodeInsertChild(root_child0, root_child0_child1, 1);
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ // Content container has 0 height because items' flex-basis is ignored
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0));
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child1));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child1));
+
+ YGNodeFreeRecursive(root);
+ YGConfigFree(config);
+}
+
+// Without errata: flex-basis is respected even when mainAxisSize is NaN.
+// The corrected condition accepts positive resolvedFlexBasis regardless
+// of mainAxisSize, so items get their specified flex-basis heights.
+TEST(YogaTest, flex_basis_in_scroll_content_without_errata) {
+ YGConfigRef config = YGConfigNew();
+ // No errata (default: Errata::None)
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetWidth(root, 200);
+ YGNodeStyleSetHeight(root, 300);
+ YGNodeStyleSetOverflow(root, YGOverflowScroll);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetFlexBasis(root_child0_child0, 200);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+ YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetFlexBasis(root_child0_child1, 300);
+ YGNodeInsertChild(root_child0, root_child0_child1, 1);
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ // Content container has height 500 (200 + 300 from items' flex-basis)
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0_child0));
+
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child0_child1));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child1));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0_child1));
+
+ YGNodeFreeRecursive(root);
+ YGConfigFree(config);
+}
diff --git a/tests/YGScaleChangeTest.cpp b/tests/YGScaleChangeTest.cpp
index 11de9c079c..525cce7e27 100644
--- a/tests/YGScaleChangeTest.cpp
+++ b/tests/YGScaleChangeTest.cpp
@@ -42,7 +42,10 @@ TEST(YogaTest, scale_change_invalidates_layout) {
TEST(YogaTest, errata_config_change_relayout) {
YGConfig* config = YGConfigNew();
- YGConfigSetErrata(config, YGErrataStretchFlexBasis);
+ YGConfigSetErrata(
+ config,
+ static_cast(
+ YGErrataStretchFlexBasis | YGErrataFlexBasisFitContentInMainAxis));
YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root, 500);
YGNodeStyleSetHeight(root, 500);
diff --git a/tests/generated/YGFlexBasisFitContentInMainAxisTest.cpp b/tests/generated/YGFlexBasisFitContentInMainAxisTest.cpp
new file mode 100644
index 0000000000..5f882b3483
--- /dev/null
+++ b/tests/generated/YGFlexBasisFitContentInMainAxisTest.cpp
@@ -0,0 +1,446 @@
+/*
+ * 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.
+ *
+ * clang-format off
+ * @generated SignedSource<<95958793a3aaa59510b88cf0cecf7676>>
+ * generated by gentest/gentest-driver.ts from gentest/fixtures/YGFlexBasisFitContentInMainAxisTest.html
+ */
+
+#include
+#include
+#include "../util/TestUtil.h"
+
+TEST(YogaTest, container_child_overflows_definite_parent_column) {
+ YGConfigRef config = YGConfigNew();
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute);
+ YGNodeStyleSetWidth(root, 200);
+ YGNodeStyleSetHeight(root, 300);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetWidth(root_child0_child0, 50);
+ YGNodeStyleSetHeight(root_child0_child0, 500);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+ ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+ ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeFreeRecursive(root);
+
+ YGConfigFree(config);
+}
+
+TEST(YogaTest, container_child_overflows_definite_parent_row) {
+ YGConfigRef config = YGConfigNew();
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+ YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute);
+ YGNodeStyleSetWidth(root, 300);
+ YGNodeStyleSetHeight(root, 200);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetWidth(root_child0_child0, 500);
+ YGNodeStyleSetHeight(root_child0_child0, 50);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(-200, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeFreeRecursive(root);
+
+ YGConfigFree(config);
+}
+
+TEST(YogaTest, container_child_within_bounds_column) {
+ YGConfigRef config = YGConfigNew();
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute);
+ YGNodeStyleSetWidth(root, 200);
+ YGNodeStyleSetHeight(root, 300);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetWidth(root_child0_child0, 50);
+ YGNodeStyleSetHeight(root_child0_child0, 100);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+ ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+ ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeFreeRecursive(root);
+
+ YGConfigFree(config);
+}
+
+TEST(YogaTest, multiple_container_children_overflow_column) {
+ YGConfigRef config = YGConfigNew();
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute);
+ YGNodeStyleSetWidth(root, 200);
+ YGNodeStyleSetHeight(root, 300);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetHeight(root_child0_child0, 400);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+ YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child1, 1);
+
+ YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetHeight(root_child1_child0, 500);
+ YGNodeInsertChild(root_child1, root_child1_child0, 0);
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root_child0_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+ ASSERT_FLOAT_EQ(400, YGNodeLayoutGetTop(root_child1));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child1));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child1_child0));
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root_child0_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+ ASSERT_FLOAT_EQ(400, YGNodeLayoutGetTop(root_child1));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child1));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child1_child0));
+
+ YGNodeFreeRecursive(root);
+
+ YGConfigFree(config);
+}
+
+TEST(YogaTest, scroll_container_column) {
+ YGConfigRef config = YGConfigNew();
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute);
+ YGNodeStyleSetOverflow(root, YGOverflowScroll);
+ YGNodeStyleSetWidth(root, 200);
+ YGNodeStyleSetHeight(root, 300);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetHeight(root_child0_child0, 500);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0_child0));
+
+ YGNodeFreeRecursive(root);
+
+ YGConfigFree(config);
+}
+
+TEST(YogaTest, explicit_and_container_children_column) {
+ YGConfigRef config = YGConfigNew();
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute);
+ YGNodeStyleSetWidth(root, 200);
+ YGNodeStyleSetHeight(root, 300);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetHeight(root_child0, 100);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child1, 1);
+
+ YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetHeight(root_child1_child0, 500);
+ YGNodeInsertChild(root_child1, root_child1_child0, 0);
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+ ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child1));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child1_child0));
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+ ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child1));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child1_child0));
+
+ YGNodeFreeRecursive(root);
+
+ YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_basis_in_scroll_content_container) {
+ YGConfigRef config = YGConfigNew();
+
+ YGNodeRef root = YGNodeNewWithConfig(config);
+ YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute);
+ YGNodeStyleSetOverflow(root, YGOverflowScroll);
+ YGNodeStyleSetWidth(root, 200);
+ YGNodeStyleSetHeight(root, 300);
+
+ YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+ YGNodeInsertChild(root, root_child0, 0);
+
+ YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetFlexBasis(root_child0_child0, 200);
+ YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+ YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config);
+ YGNodeStyleSetFlexBasis(root_child0_child1, 300);
+ YGNodeInsertChild(root_child0, root_child0_child1, 1);
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child0_child1));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child1));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0_child1));
+
+ YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+ ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0_child0));
+
+ ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child0_child1));
+ ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child1));
+ ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0_child1));
+
+ YGNodeFreeRecursive(root);
+
+ YGConfigFree(config);
+}
diff --git a/yoga/YGEnums.cpp b/yoga/YGEnums.cpp
index 4bdace6b7a..3e63b509b7 100644
--- a/yoga/YGEnums.cpp
+++ b/yoga/YGEnums.cpp
@@ -111,6 +111,8 @@ const char* YGErrataToString(const YGErrata value) {
return "absolute-position-without-insets-excludes-padding";
case YGErrataAbsolutePercentAgainstInnerSize:
return "absolute-percent-against-inner-size";
+ case YGErrataFlexBasisFitContentInMainAxis:
+ return "flex-basis-fit-content-in-main-axis";
case YGErrataAll:
return "all";
case YGErrataClassic:
diff --git a/yoga/YGEnums.h b/yoga/YGEnums.h
index bb83bcfac9..c0bc7a04e4 100644
--- a/yoga/YGEnums.h
+++ b/yoga/YGEnums.h
@@ -64,6 +64,7 @@ YG_ENUM_DECL(
YGErrataStretchFlexBasis = 1,
YGErrataAbsolutePositionWithoutInsetsExcludesPadding = 2,
YGErrataAbsolutePercentAgainstInnerSize = 4,
+ YGErrataFlexBasisFitContentInMainAxis = 8,
YGErrataAll = 2147483647,
YGErrataClassic = 2147483646)
YG_DEFINE_ENUM_FLAG_OPERATORS(YGErrata)
diff --git a/yoga/algorithm/CalculateLayout.cpp b/yoga/algorithm/CalculateLayout.cpp
index 81a5f3b8a0..5e9350b2f9 100644
--- a/yoga/algorithm/CalculateLayout.cpp
+++ b/yoga/algorithm/CalculateLayout.cpp
@@ -94,7 +94,10 @@ static void computeFlexBasisForChild(
const bool isColumnStyleDimDefined =
child->hasDefiniteLength(Dimension::Height, ownerHeight);
- if (resolvedFlexBasis.isDefined() && yoga::isDefined(mainAxisSize)) {
+ if (resolvedFlexBasis.isDefined() &&
+ (yoga::isDefined(mainAxisSize) ||
+ (!node->hasErrata(Errata::FlexBasisFitContentInMainAxis) &&
+ resolvedFlexBasis.unwrap() > 0))) {
if (child->getLayout().computedFlexBasis.isUndefined() ||
(child->getConfig()->isExperimentalFeatureEnabled(
ExperimentalFeature::WebFlexBasis) &&
@@ -156,19 +159,57 @@ static void computeFlexBasisForChild(
// The W3C spec doesn't say anything about the 'overflow' property, but all
// major browsers appear to implement the following logic.
- if ((!isMainAxisRow && node->style().overflow() == Overflow::Scroll) ||
- node->style().overflow() != Overflow::Scroll) {
- if (yoga::isUndefined(childWidth) && yoga::isDefined(width)) {
- childWidth = width;
- childWidthSizingMode = SizingMode::FitContent;
+ //
+ // In the cross axis, children should always be bounded by the parent's
+ // available space (FitContent). In the main axis, the flex basis should
+ // be the child's intrinsic size under max-content constraint.
+ //
+ // The legacy behavior (FlexBasisFitContentInMainAxis errata) applies a
+ // FitContent constraint in the main axis for non-scroll containers, which
+ // causes unnecessary re-measurement and cascading clones when the parent's
+ // content-determined size changes (e.g. when a sibling's height changes
+ // in a ScrollView).
+ //
+ // The corrected behavior leaves the main axis unconstrained for container
+ // children (no measure function), and preserves the FitContent constraint
+ // for measure function nodes (e.g. text) to support text wrapping.
+ if (node->hasErrata(Errata::FlexBasisFitContentInMainAxis)) {
+ // Legacy behavior: apply FitContent in both axes (except main axis for
+ // scroll containers).
+ if ((!isMainAxisRow && node->style().overflow() == Overflow::Scroll) ||
+ node->style().overflow() != Overflow::Scroll) {
+ if (yoga::isUndefined(childWidth) && yoga::isDefined(width)) {
+ childWidth = width;
+ childWidthSizingMode = SizingMode::FitContent;
+ }
}
- }
- if ((isMainAxisRow && node->style().overflow() == Overflow::Scroll) ||
- node->style().overflow() != Overflow::Scroll) {
- if (yoga::isUndefined(childHeight) && yoga::isDefined(height)) {
- childHeight = height;
- childHeightSizingMode = SizingMode::FitContent;
+ if ((isMainAxisRow && node->style().overflow() == Overflow::Scroll) ||
+ node->style().overflow() != Overflow::Scroll) {
+ if (yoga::isUndefined(childHeight) && yoga::isDefined(height)) {
+ childHeight = height;
+ childHeightSizingMode = SizingMode::FitContent;
+ }
+ }
+ } else {
+ // Corrected behavior: only apply FitContent in the cross axis, or in
+ // the main axis for measure function nodes in non-scroll containers.
+ if (!isMainAxisRow ||
+ (child->hasMeasureFunc() &&
+ node->style().overflow() != Overflow::Scroll)) {
+ if (yoga::isUndefined(childWidth) && yoga::isDefined(width)) {
+ childWidth = width;
+ childWidthSizingMode = SizingMode::FitContent;
+ }
+ }
+
+ if (isMainAxisRow ||
+ (child->hasMeasureFunc() &&
+ node->style().overflow() != Overflow::Scroll)) {
+ if (yoga::isUndefined(childHeight) && yoga::isDefined(height)) {
+ childHeight = height;
+ childHeightSizingMode = SizingMode::FitContent;
+ }
}
}
@@ -537,6 +578,8 @@ static float computeFlexBasisForChildren(
yoga::Node* const node,
const float availableInnerWidth,
const float availableInnerHeight,
+ const float ownerWidth,
+ const float ownerHeight,
SizingMode widthSizingMode,
SizingMode heightSizingMode,
Direction direction,
@@ -598,8 +641,8 @@ static float computeFlexBasisForChildren(
availableInnerWidth,
widthSizingMode,
availableInnerHeight,
- availableInnerWidth,
- availableInnerHeight,
+ ownerWidth,
+ ownerHeight,
heightSizingMode,
direction,
layoutMarkerData,
@@ -1421,12 +1464,56 @@ static void calculateLayoutImpl(
// STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM
+ // When this node is measured with MaxContent (corrected
+ // FlexBasisFitContentInMainAxis behavior), availableInnerHeight/Width is NaN.
+ // To preserve percentage resolution for descendants, derive a definite
+ // owner-size from the parent-provided ownerHeight/ownerWidth.
+ float ownerWidthForChildren = availableInnerWidth;
+ float ownerHeightForChildren = availableInnerHeight;
+
+ if (!node->hasErrata(Errata::FlexBasisFitContentInMainAxis)) {
+ // Do not propagate the fallback when this node is a direct child of a
+ // scroll container. In scroll contexts, the scroll axis is intentionally
+ // indefinite and percentage-based children should not resolve against the
+ // viewport size.
+ const auto* owner = node->getOwner();
+ const bool isChildOfScrollContainer =
+ owner != nullptr && owner->style().overflow() == Overflow::Scroll;
+
+ if (!isChildOfScrollContainer) {
+ if (yoga::isUndefined(ownerWidthForChildren) &&
+ yoga::isDefined(ownerWidth)) {
+ ownerWidthForChildren = calculateAvailableInnerDimension(
+ node,
+ direction,
+ Dimension::Width,
+ ownerWidth - marginAxisRow,
+ paddingAndBorderAxisRow,
+ ownerWidth,
+ ownerWidth);
+ }
+ if (yoga::isUndefined(ownerHeightForChildren) &&
+ yoga::isDefined(ownerHeight)) {
+ ownerHeightForChildren = calculateAvailableInnerDimension(
+ node,
+ direction,
+ Dimension::Height,
+ ownerHeight - marginAxisColumn,
+ paddingAndBorderAxisColumn,
+ ownerHeight,
+ ownerWidth);
+ }
+ }
+ }
+
// Computed basis + margins + gap
float totalMainDim = 0;
totalMainDim += computeFlexBasisForChildren(
node,
availableInnerWidth,
availableInnerHeight,
+ ownerWidthForChildren,
+ ownerHeightForChildren,
widthSizingMode,
heightSizingMode,
direction,
diff --git a/yoga/enums/Errata.h b/yoga/enums/Errata.h
index 2f47a94175..86d8409b15 100644
--- a/yoga/enums/Errata.h
+++ b/yoga/enums/Errata.h
@@ -20,6 +20,7 @@ enum class Errata : uint32_t {
StretchFlexBasis = YGErrataStretchFlexBasis,
AbsolutePositionWithoutInsetsExcludesPadding = YGErrataAbsolutePositionWithoutInsetsExcludesPadding,
AbsolutePercentAgainstInnerSize = YGErrataAbsolutePercentAgainstInnerSize,
+ FlexBasisFitContentInMainAxis = YGErrataFlexBasisFitContentInMainAxis,
All = YGErrataAll,
Classic = YGErrataClassic,
};