Skip to content

Commit dc6d185

Browse files
sammy-SCmeta-codesync[bot]
authored andcommitted
Re-land: fixYogaFlexBasisFitContentInMainAxis (#1917)
Summary: X-link: react/react-native#56064 Pull Request resolved: #1917 Re-land of D94658492 with fixes, which was reverted in D95669495. ## Context D94658492 added the `fixYogaFlexBasisFitContentInMainAxis` flag to avoid unnecessary re-measurement cascades in Yoga. When Yoga computes flex basis for container children, the legacy behavior applies a `FitContent` constraint in the main axis, bounding the child's measurement by the parent's available space. This creates a dependency between the child's flex basis and the parent's content-determined size — when one sibling changes size, all siblings get re-measured and their shadow nodes get cloned unnecessarily. The fix switches from `FitContent` to `MaxContent` for non-measure container children under auto-height parents, making each child's flex basis independent of the parent's size. ## What went wrong D94658492 modeled the fix as a `YogaErrata` bit (`FLEX_BASIS_FIT_CONTENT_IN_MAIN_AXIS`). Errata flags are bitmasks, and apps that opt into `ALL` or `CLASSIC` errata (like IGVR and Airwave) inadvertently picked up the new behavior without explicitly enabling the feature flag, causing breakages. ## What changed in this re-land This diff models the fix as a `YogaExperimentalFeature` (`FIX_FLEX_BASIS_FIT_CONTENT`) instead of a `YogaErrata` bit. Experimental features are individually opt-in, so existing apps won't accidentally pick up the change. This diff only wires up the RN feature flag infrastructure (flag defaults to `false`). The iOS MobileConfig override and the Yoga layout logic will be landed in follow-up diffs. changelog: [internal] Reviewed By: javache, NickGerleman Differential Revision: D95852922 fbshipit-source-id: e2b1aa7a5d8f340011123679f721c62396b5caa5
1 parent 4ced43e commit dc6d185

12 files changed

Lines changed: 1737 additions & 13 deletions

File tree

enums.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/env python3
1+
#!/usr/bin/env fbpython
22
# Copyright (c) Meta Platforms, Inc. and affiliates.
33
#
44
# This source code is licensed under the MIT license found in the
@@ -66,6 +66,9 @@
6666
"ExperimentalFeature": [
6767
# Mimic web flex-basis behavior (experiment may be broken)
6868
"WebFlexBasis",
69+
# Fix flex basis computation to not apply FitContent constraint in the
70+
# main axis for non-measure container nodes
71+
"FixFlexBasisFitContent",
6972
],
7073
"Gutter": ["Column", "Row", "All"],
7174
"GridTrackType": ["Auto", "Points", "Percent", "Fr", "Minmax"],
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<!-- Container child with content overflowing definite column parent.
2+
Flex basis uses content size regardless of ExperimentalFeature state,
3+
because FitContent and MaxContent produce the same result for containers. -->
4+
<div id="container_child_overflows_definite_parent_column"
5+
style="width: 200px; height: 300px;">
6+
<div>
7+
<div style="height: 500px; width: 50px;"></div>
8+
</div>
9+
</div>
10+
11+
<!-- Row variant: container child overflows definite row parent. -->
12+
<div id="container_child_overflows_definite_parent_row"
13+
style="width: 300px; height: 200px; flex-direction: row;">
14+
<div>
15+
<div style="width: 500px; height: 50px;"></div>
16+
</div>
17+
</div>
18+
19+
<!-- Container child content fits within parent bounds.
20+
Same behavior with and without feature (no capping needed). -->
21+
<div id="container_child_within_bounds_column"
22+
style="width: 200px; height: 300px;">
23+
<div>
24+
<div style="height: 100px; width: 50px;"></div>
25+
</div>
26+
</div>
27+
28+
<!-- Multiple container children, both overflowing definite column parent. -->
29+
<div id="multiple_container_children_overflow_column"
30+
style="width: 200px; height: 300px;">
31+
<div>
32+
<div style="height: 400px;"></div>
33+
</div>
34+
<div>
35+
<div style="height: 500px;"></div>
36+
</div>
37+
</div>
38+
39+
<!-- Scroll container: children always use MaxContent in main axis.
40+
Same behavior with and without feature. -->
41+
<div id="scroll_container_column"
42+
style="width: 200px; height: 300px; overflow: scroll;">
43+
<div>
44+
<div style="height: 500px;"></div>
45+
</div>
46+
</div>
47+
48+
<!-- Mix of explicit-height child and overflowing container child. -->
49+
<div id="explicit_and_container_children_column"
50+
style="width: 200px; height: 300px;">
51+
<div style="height: 100px;"></div>
52+
<div>
53+
<div style="height: 500px;"></div>
54+
</div>
55+
</div>
56+
57+
<!-- Items with flex-basis inside a scroll container's auto-height
58+
content container. With FixFlexBasisFitContent, flex-basis is
59+
respected even when the content container's main axis size is
60+
indefinite (NaN). Without the feature, flex-basis would be ignored. -->
61+
<div id="flex_basis_in_scroll_content_container"
62+
data-experiments="FixFlexBasisFitContent"
63+
style="width: 200px; height: 300px; overflow: scroll;">
64+
<div>
65+
<div style="flex-basis: 200px;"></div>
66+
<div style="flex-basis: 300px;"></div>
67+
</div>
68+
</div>

java/com/facebook/yoga/YogaExperimentalFeature.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
package com.facebook.yoga;
1111

1212
public enum YogaExperimentalFeature {
13-
WEB_FLEX_BASIS(0);
13+
WEB_FLEX_BASIS(0),
14+
FIX_FLEX_BASIS_FIT_CONTENT(1);
1415

1516
private final int mIntValue;
1617

@@ -25,6 +26,7 @@ public int intValue() {
2526
public static YogaExperimentalFeature fromInt(int value) {
2627
switch (value) {
2728
case 0: return WEB_FLEX_BASIS;
29+
case 1: return FIX_FLEX_BASIS_FIT_CONTENT;
2830
default: throw new IllegalArgumentException("Unknown enum value: " + value);
2931
}
3032
}

0 commit comments

Comments
 (0)