Skip to content

Commit 5e4cbcf

Browse files
adityasharatmeta-codesync[bot]
authored andcommitted
Spec-correct CSS Flexbox §4.5 auto-min-size opt-in on YGConfig (re-land) (#57015)
Summary: X-link: react/yoga#1968 Re-land of D105720159, originally reverted (revert: 0e642b96c7e2) due to a latent NPE in `ReactProgressBarViewManager.kt` and Instagram-internal `ReactSwitchManager.kt` — both fixed in the prior diffs in this stack. Crash and broken e2e tests reported in T273821098 / P2359486686. This re-land additionally fixes a correctness gap in the original D105720159 design: it claimed "Default configs carry the bit (preserves today's behaviour); existing trees see no change" — but `LayoutConformance::Strict` in `YogaLayoutableShadowNode::resolveErrata` returned `YGErrataNone`, which clears every errata bit *including* the new `MinSizeUndefinedInsteadOfAuto` (bit 8). Since `react-strict-dom` sets `experimental_layoutConformance="strict"` on every native View, this implicitly opts every RSD-using surface into the new auto-min probe. That's the exact path Airwave's tests took to hit the original NPE. Change: `LayoutConformance::Strict` now returns `YGErrataMinSizeUndefinedInsteadOfAuto` instead of `YGErrataNone`. Strict mode keeps every other CSS conformance behavior intact; only the new auto-min feature stays opt-in via explicit `YGConfig` setup. This matches the design pattern Litho uses in the child diff (`ComponentsConfiguration.useAutoMinSize` flag, gated independently of any strict-mode plumbing). Original summary follows: X-link: react/yoga#1966 Pull Request resolved: #57015 Implements CSS Flexbox §4.5 automatic minimum sizing in Yoga. When opted in on a `YGConfig`, every flex item whose main-axis `min-{width,height}` is undefined receives a content-derived floor — `min(min-content, specified-size, max-size)` plus any aspect-ratio-transferred lower bound — so it cannot shrink below the size CSS browsers would honor. How to opt in: clear the new `YGErrataMinSizeUndefinedInsteadOfAuto` errata bit on the config. Default configs carry the bit (preserves today's behaviour); existing trees see no change. The bit is added to `YGErrataClassic` so consumers using that constant continue to get the same default. **`LayoutConformance::Strict` also keeps the bit set** — the new feature is strictly opt-in, not inferred from strict-mode CSS conformance. See D105720159 for full details on precedence rules, container recursion semantics, and per-item opt-outs. Changelog: [General][Added] - Add CSS Flexbox §4.5 automatic minimum sizing. Opt in by clearing the new `YGErrataMinSizeUndefinedInsteadOfAuto` errata bit on `YGConfig`. Differential Revision: D107183851
1 parent f85b15b commit 5e4cbcf

50 files changed

Lines changed: 933 additions & 91 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<86c797c19cc585b74714ca3aa75bbd6d>>
7+
* @generated SignedSource<<7e91da9df64ce42424101d7d72356c4a>>
88
*/
99

1010
/**
@@ -168,6 +168,12 @@ public object ReactNativeFeatureFlags {
168168
@JvmStatic
169169
public fun enableFabricLogs(): Boolean = accessor.enableFabricLogs()
170170

171+
/**
172+
* Enables CSS Flexbox §4.5 automatic minimum sizing under strict layout conformance. When enabled, a flex item with an undefined main-axis `min-width`/`min-height` under strict conformance receives a content-derived minimum size (per spec) instead of an undefined (0) minimum. Defaults off so the behaviour can be ramped independently of strict conformance.
173+
*/
174+
@JvmStatic
175+
public fun enableFlexboxAutoMinSizeInStrictMode(): Boolean = accessor.enableFlexboxAutoMinSizeInStrictMode()
176+
171177
/**
172178
* Enables font scale changes updating layout for measurable nodes.
173179
*/

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<d71556cf1226fe6a41dd388568153d3a>>
7+
* @generated SignedSource<<3c0e10dee93b76f3e66ca79d26f2b4f2>>
88
*/
99

1010
/**
@@ -43,6 +43,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
4343
private var enableExclusivePropsUpdateAndroidCache: Boolean? = null
4444
private var enableFabricCommitBranchingCache: Boolean? = null
4545
private var enableFabricLogsCache: Boolean? = null
46+
private var enableFlexboxAutoMinSizeInStrictModeCache: Boolean? = null
4647
private var enableFontScaleChangesUpdatingLayoutCache: Boolean? = null
4748
private var enableIOSTextBaselineOffsetPerLineCache: Boolean? = null
4849
private var enableIOSViewClipToPaddingBoxCache: Boolean? = null
@@ -315,6 +316,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
315316
return cached
316317
}
317318

319+
override fun enableFlexboxAutoMinSizeInStrictMode(): Boolean {
320+
var cached = enableFlexboxAutoMinSizeInStrictModeCache
321+
if (cached == null) {
322+
cached = ReactNativeFeatureFlagsCxxInterop.enableFlexboxAutoMinSizeInStrictMode()
323+
enableFlexboxAutoMinSizeInStrictModeCache = cached
324+
}
325+
return cached
326+
}
327+
318328
override fun enableFontScaleChangesUpdatingLayout(): Boolean {
319329
var cached = enableFontScaleChangesUpdatingLayoutCache
320330
if (cached == null) {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<2ee82b1e1dcae3ea10dbd92549d65a6c>>
7+
* @generated SignedSource<<e9cc7d01ac1884710f131fbf375f3502>>
88
*/
99

1010
/**
@@ -74,6 +74,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
7474

7575
@DoNotStrip @JvmStatic public external fun enableFabricLogs(): Boolean
7676

77+
@DoNotStrip @JvmStatic public external fun enableFlexboxAutoMinSizeInStrictMode(): Boolean
78+
7779
@DoNotStrip @JvmStatic public external fun enableFontScaleChangesUpdatingLayout(): Boolean
7880

7981
@DoNotStrip @JvmStatic public external fun enableIOSTextBaselineOffsetPerLine(): Boolean

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<738a114e73ddb940fb14efd0dff79d1b>>
7+
* @generated SignedSource<<061d668cf04041f4d3d2f48f11dc739f>>
88
*/
99

1010
/**
@@ -69,6 +69,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
6969

7070
override fun enableFabricLogs(): Boolean = false
7171

72+
override fun enableFlexboxAutoMinSizeInStrictMode(): Boolean = false
73+
7274
override fun enableFontScaleChangesUpdatingLayout(): Boolean = true
7375

7476
override fun enableIOSTextBaselineOffsetPerLine(): Boolean = false

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<d5b84c7e0c58f61d891e0dd63f61b4c0>>
7+
* @generated SignedSource<<fa85d53197cbdce6b1373fbadf3cf2b9>>
88
*/
99

1010
/**
@@ -47,6 +47,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
4747
private var enableExclusivePropsUpdateAndroidCache: Boolean? = null
4848
private var enableFabricCommitBranchingCache: Boolean? = null
4949
private var enableFabricLogsCache: Boolean? = null
50+
private var enableFlexboxAutoMinSizeInStrictModeCache: Boolean? = null
5051
private var enableFontScaleChangesUpdatingLayoutCache: Boolean? = null
5152
private var enableIOSTextBaselineOffsetPerLineCache: Boolean? = null
5253
private var enableIOSViewClipToPaddingBoxCache: Boolean? = null
@@ -342,6 +343,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
342343
return cached
343344
}
344345

346+
override fun enableFlexboxAutoMinSizeInStrictMode(): Boolean {
347+
var cached = enableFlexboxAutoMinSizeInStrictModeCache
348+
if (cached == null) {
349+
cached = currentProvider.enableFlexboxAutoMinSizeInStrictMode()
350+
accessedFeatureFlags.add("enableFlexboxAutoMinSizeInStrictMode")
351+
enableFlexboxAutoMinSizeInStrictModeCache = cached
352+
}
353+
return cached
354+
}
355+
345356
override fun enableFontScaleChangesUpdatingLayout(): Boolean {
346357
var cached = enableFontScaleChangesUpdatingLayoutCache
347358
if (cached == null) {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<c481d046dea2f8c8ca77b70d41f86430>>
7+
* @generated SignedSource<<21e8d5e2a4a37e0a51f25609b80f4924>>
88
*/
99

1010
/**
@@ -25,6 +25,8 @@ public open class ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android :
2525

2626
override fun cxxNativeAnimatedEnabled(): Boolean = true
2727

28+
override fun enableFlexboxAutoMinSizeInStrictMode(): Boolean = true
29+
2830
override fun enableRuntimeSchedulerQueueClearingOnError(): Boolean = true
2931

3032
override fun enableSchedulerDelegateInvalidation(): Boolean = true

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<a3dbeb4eec6efecc4fc355b15a984e58>>
7+
* @generated SignedSource<<a460b28871fc3f928dcc2d1a3bf66422>>
88
*/
99

1010
/**
@@ -69,6 +69,8 @@ public interface ReactNativeFeatureFlagsProvider {
6969

7070
@DoNotStrip public fun enableFabricLogs(): Boolean
7171

72+
@DoNotStrip public fun enableFlexboxAutoMinSizeInStrictMode(): Boolean
73+
7274
@DoNotStrip public fun enableFontScaleChangesUpdatingLayout(): Boolean
7375

7476
@DoNotStrip public fun enableIOSTextBaselineOffsetPerLine(): Boolean

packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfig.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,23 @@ public abstract class YogaConfig {
1919

2020
public abstract fun setErrata(errata: YogaErrata)
2121

22+
/**
23+
* Sets the errata bitmask directly from an [Int]. Use this when combining multiple [YogaErrata]
24+
* values (e.g., `YogaErrata.CLASSIC.intValue() and
25+
* YogaErrata.STRETCH_FLEX_BASIS.intValue().inv()`) — the [YogaErrata] enum cannot represent
26+
* arbitrary bitmask combinations.
27+
*/
28+
public abstract fun setErrata(errata: Int)
29+
2230
public abstract fun getErrata(): YogaErrata
2331

32+
/**
33+
* Returns the errata bitmask as a raw [Int]. Use this companion to [setErrata] (Int) when the
34+
* stored bitmask combines bits in a way the [YogaErrata] enum cannot represent — calling
35+
* [getErrata] in that case throws [IllegalArgumentException] from `YogaErrata.fromInt`.
36+
*/
37+
public abstract fun getErrataInt(): Int
38+
2439
public abstract fun setLogger(logger: YogaLogger?)
2540

2641
public abstract fun getLogger(): YogaLogger?

packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfigJNIBase.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,15 @@ private constructor(@JvmField protected var nativePointer: Long) : YogaConfig()
5050
YogaNative.jni_YGConfigSetErrataJNI(nativePointer, errata.intValue())
5151
}
5252

53+
public override fun setErrata(errata: Int) {
54+
YogaNative.jni_YGConfigSetErrataJNI(nativePointer, errata)
55+
}
56+
5357
public override fun getErrata(): YogaErrata =
5458
YogaErrata.fromInt(YogaNative.jni_YGConfigGetErrataJNI(nativePointer))
5559

60+
public override fun getErrataInt(): Int = YogaNative.jni_YGConfigGetErrataJNI(nativePointer)
61+
5662
public override fun setLogger(logger: YogaLogger?) {
5763
_logger = logger
5864
YogaNative.jni_YGConfigSetLoggerJNI(nativePointer, logger)

packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaErrata.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public enum class YogaErrata(public val intValue: Int) {
1414
STRETCH_FLEX_BASIS(1),
1515
ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING(2),
1616
ABSOLUTE_PERCENT_AGAINST_INNER_SIZE(4),
17+
MIN_SIZE_UNDEFINED_INSTEAD_OF_AUTO(8),
1718
ALL(2147483647),
1819
CLASSIC(2147483646);
1920

@@ -27,6 +28,7 @@ public enum class YogaErrata(public val intValue: Int) {
2728
1 -> STRETCH_FLEX_BASIS
2829
2 -> ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING
2930
4 -> ABSOLUTE_PERCENT_AGAINST_INNER_SIZE
31+
8 -> MIN_SIZE_UNDEFINED_INSTEAD_OF_AUTO
3032
2147483647 -> ALL
3133
2147483646 -> CLASSIC
3234
else -> throw IllegalArgumentException("Unknown enum value: $value")

0 commit comments

Comments
 (0)