diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index 79365f7c6447..da6e95c22538 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<86c797c19cc585b74714ca3aa75bbd6d>> + * @generated SignedSource<<7e91da9df64ce42424101d7d72356c4a>> */ /** @@ -168,6 +168,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun enableFabricLogs(): Boolean = accessor.enableFabricLogs() + /** + * 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. + */ + @JvmStatic + public fun enableFlexboxAutoMinSizeInStrictMode(): Boolean = accessor.enableFlexboxAutoMinSizeInStrictMode() + /** * Enables font scale changes updating layout for measurable nodes. */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index 305ce615168b..6a4a6eb0c535 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * 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 SignedSource<<3c0e10dee93b76f3e66ca79d26f2b4f2>> */ /** @@ -43,6 +43,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var enableExclusivePropsUpdateAndroidCache: Boolean? = null private var enableFabricCommitBranchingCache: Boolean? = null private var enableFabricLogsCache: Boolean? = null + private var enableFlexboxAutoMinSizeInStrictModeCache: Boolean? = null private var enableFontScaleChangesUpdatingLayoutCache: Boolean? = null private var enableIOSTextBaselineOffsetPerLineCache: Boolean? = null private var enableIOSViewClipToPaddingBoxCache: Boolean? = null @@ -315,6 +316,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun enableFlexboxAutoMinSizeInStrictMode(): Boolean { + var cached = enableFlexboxAutoMinSizeInStrictModeCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.enableFlexboxAutoMinSizeInStrictMode() + enableFlexboxAutoMinSizeInStrictModeCache = cached + } + return cached + } + override fun enableFontScaleChangesUpdatingLayout(): Boolean { var cached = enableFontScaleChangesUpdatingLayoutCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index dc2b84bde267..bd059df9c407 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<2ee82b1e1dcae3ea10dbd92549d65a6c>> + * @generated SignedSource<> */ /** @@ -74,6 +74,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun enableFabricLogs(): Boolean + @DoNotStrip @JvmStatic public external fun enableFlexboxAutoMinSizeInStrictMode(): Boolean + @DoNotStrip @JvmStatic public external fun enableFontScaleChangesUpdatingLayout(): Boolean @DoNotStrip @JvmStatic public external fun enableIOSTextBaselineOffsetPerLine(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index f8139daac1e9..818eb338551d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<738a114e73ddb940fb14efd0dff79d1b>> + * @generated SignedSource<<061d668cf04041f4d3d2f48f11dc739f>> */ /** @@ -69,6 +69,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun enableFabricLogs(): Boolean = false + override fun enableFlexboxAutoMinSizeInStrictMode(): Boolean = false + override fun enableFontScaleChangesUpdatingLayout(): Boolean = true override fun enableIOSTextBaselineOffsetPerLine(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index 8f53fbccb447..26fa9891b568 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * 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 SignedSource<> */ /** @@ -47,6 +47,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var enableExclusivePropsUpdateAndroidCache: Boolean? = null private var enableFabricCommitBranchingCache: Boolean? = null private var enableFabricLogsCache: Boolean? = null + private var enableFlexboxAutoMinSizeInStrictModeCache: Boolean? = null private var enableFontScaleChangesUpdatingLayoutCache: Boolean? = null private var enableIOSTextBaselineOffsetPerLineCache: Boolean? = null private var enableIOSViewClipToPaddingBoxCache: Boolean? = null @@ -342,6 +343,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } + override fun enableFlexboxAutoMinSizeInStrictMode(): Boolean { + var cached = enableFlexboxAutoMinSizeInStrictModeCache + if (cached == null) { + cached = currentProvider.enableFlexboxAutoMinSizeInStrictMode() + accessedFeatureFlags.add("enableFlexboxAutoMinSizeInStrictMode") + enableFlexboxAutoMinSizeInStrictModeCache = cached + } + return cached + } + override fun enableFontScaleChangesUpdatingLayout(): Boolean { var cached = enableFontScaleChangesUpdatingLayoutCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.kt index 2050dc944bc0..0e61201288d8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.kt @@ -4,7 +4,7 @@ * 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 SignedSource<<21e8d5e2a4a37e0a51f25609b80f4924>> */ /** @@ -25,6 +25,8 @@ public open class ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android : override fun cxxNativeAnimatedEnabled(): Boolean = true + override fun enableFlexboxAutoMinSizeInStrictMode(): Boolean = true + override fun enableRuntimeSchedulerQueueClearingOnError(): Boolean = true override fun enableSchedulerDelegateInvalidation(): Boolean = true diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index 48cd9d2cfdbd..c16a9d890a16 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * 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 SignedSource<> */ /** @@ -69,6 +69,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun enableFabricLogs(): Boolean + @DoNotStrip public fun enableFlexboxAutoMinSizeInStrictMode(): Boolean + @DoNotStrip public fun enableFontScaleChangesUpdatingLayout(): Boolean @DoNotStrip public fun enableIOSTextBaselineOffsetPerLine(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfig.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfig.kt index 157d17253421..f030c21a75d0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfig.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfig.kt @@ -19,8 +19,23 @@ public abstract class YogaConfig { public abstract fun setErrata(errata: YogaErrata) + /** + * Sets the errata bitmask directly from an [Int]. Use this when combining multiple [YogaErrata] + * values (e.g., `YogaErrata.CLASSIC.intValue() and + * YogaErrata.STRETCH_FLEX_BASIS.intValue().inv()`) — the [YogaErrata] enum cannot represent + * arbitrary bitmask combinations. + */ + public abstract fun setErrata(errata: Int) + public abstract fun getErrata(): YogaErrata + /** + * Returns the errata bitmask as a raw [Int]. Use this companion to [setErrata] (Int) when the + * stored bitmask combines bits in a way the [YogaErrata] enum cannot represent — calling + * [getErrata] in that case throws [IllegalArgumentException] from `YogaErrata.fromInt`. + */ + public abstract fun getErrataInt(): Int + public abstract fun setLogger(logger: YogaLogger?) public abstract fun getLogger(): YogaLogger? diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfigJNIBase.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfigJNIBase.kt index 01c9b099742a..855e930e0b93 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfigJNIBase.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfigJNIBase.kt @@ -50,9 +50,15 @@ private constructor(@JvmField protected var nativePointer: Long) : YogaConfig() YogaNative.jni_YGConfigSetErrataJNI(nativePointer, errata.intValue()) } + public override fun setErrata(errata: Int) { + YogaNative.jni_YGConfigSetErrataJNI(nativePointer, errata) + } + public override fun getErrata(): YogaErrata = YogaErrata.fromInt(YogaNative.jni_YGConfigGetErrataJNI(nativePointer)) + public override fun getErrataInt(): Int = YogaNative.jni_YGConfigGetErrataJNI(nativePointer) + public override fun setLogger(logger: YogaLogger?) { _logger = logger YogaNative.jni_YGConfigSetLoggerJNI(nativePointer, logger) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaErrata.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaErrata.kt index 940f2861e1d3..eccbd2f3e821 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaErrata.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaErrata.kt @@ -14,6 +14,7 @@ public enum class YogaErrata(public val intValue: Int) { STRETCH_FLEX_BASIS(1), ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING(2), ABSOLUTE_PERCENT_AGAINST_INNER_SIZE(4), + MIN_SIZE_UNDEFINED_INSTEAD_OF_AUTO(8), ALL(2147483647), CLASSIC(2147483646); @@ -27,6 +28,7 @@ public enum class YogaErrata(public val intValue: Int) { 1 -> STRETCH_FLEX_BASIS 2 -> ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING 4 -> ABSOLUTE_PERCENT_AGAINST_INNER_SIZE + 8 -> MIN_SIZE_UNDEFINED_INSTEAD_OF_AUTO 2147483647 -> ALL 2147483646 -> CLASSIC else -> throw IllegalArgumentException("Unknown enum value: $value") diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNative.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNative.kt index 5ce6a02872b4..c00957b14db0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNative.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNative.kt @@ -311,6 +311,22 @@ public object YogaNative { @JvmStatic public external fun jni_YGNodeSetHasMeasureFuncJNI(nativePointer: Long, hasMeasureFunc: Boolean) + @JvmStatic + public external fun jni_YGNodeSetHasMinContentMeasureFuncJNI( + nativePointer: Long, + hasMinContentMeasureFunc: Boolean, + ) + + @JvmStatic + public external fun jni_YGNodeSetMinContentWidthJNI(nativePointer: Long, minContentWidth: Float) + + @JvmStatic + public external fun jni_YGNodeSetMinContentHeightJNI(nativePointer: Long, minContentHeight: Float) + + @JvmStatic public external fun jni_YGNodeGetMinContentWidthJNI(nativePointer: Long): Float + + @JvmStatic public external fun jni_YGNodeGetMinContentHeightJNI(nativePointer: Long): Float + @JvmStatic public external fun jni_YGNodeSetHasBaselineFuncJNI(nativePointer: Long, hasMeasureFunc: Boolean) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.kt index a807dc5ccee1..08b84232c855 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.kt @@ -228,6 +228,16 @@ public abstract class YogaNode : YogaProps { abstract override fun setMeasureFunction(measureFunction: YogaMeasureFunction?) + abstract override fun setMinContentMeasureFunction(measureFunction: YogaMeasureFunction?) + + abstract override fun setMinContentWidth(minContentWidth: Float) + + abstract override fun setMinContentHeight(minContentHeight: Float) + + abstract override fun getMinContentWidth(): Float + + abstract override fun getMinContentHeight(): Float + abstract override fun setBaselineFunction(yogaBaselineFunction: YogaBaselineFunction?) public abstract val isMeasureDefined: Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.kt index 3312896c1c3e..4fea8ae7e7cd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.kt @@ -16,6 +16,7 @@ public abstract class YogaNodeJNIBase : YogaNode, Cloneable { private var config: YogaConfig? = null private var children: MutableList? = null private var measureFunction: YogaMeasureFunction? = null + private var minContentMeasureFunction: YogaMeasureFunction? = null private var baselineFunction: YogaBaselineFunction? = null protected var nativePointer: Long = 0 @@ -46,6 +47,7 @@ public abstract class YogaNodeJNIBase : YogaNode, Cloneable { override fun reset() { measureFunction = null + minContentMeasureFunction = null baselineFunction = null data = null arr = null @@ -524,6 +526,25 @@ public abstract class YogaNodeJNIBase : YogaNode, Cloneable { YogaNative.jni_YGNodeSetHasMeasureFuncJNI(nativePointer, measureFunction != null) } + override fun setMinContentMeasureFunction(measureFunction: YogaMeasureFunction?) { + this.minContentMeasureFunction = measureFunction + YogaNative.jni_YGNodeSetHasMinContentMeasureFuncJNI(nativePointer, measureFunction != null) + } + + override fun setMinContentWidth(minContentWidth: Float) { + YogaNative.jni_YGNodeSetMinContentWidthJNI(nativePointer, minContentWidth) + } + + override fun setMinContentHeight(minContentHeight: Float) { + YogaNative.jni_YGNodeSetMinContentHeightJNI(nativePointer, minContentHeight) + } + + override fun getMinContentWidth(): Float = + YogaNative.jni_YGNodeGetMinContentWidthJNI(nativePointer) + + override fun getMinContentHeight(): Float = + YogaNative.jni_YGNodeGetMinContentHeightJNI(nativePointer) + override fun setAlwaysFormsContainingBlock(alwaysFormsContainingBlock: Boolean) { YogaNative.jni_YGNodeSetAlwaysFormsContainingBlockJNI( nativePointer, @@ -547,6 +568,27 @@ public abstract class YogaNodeJNIBase : YogaNode, Cloneable { ) } + // Native callback invoked by Yoga during the CSS Flexbox §4.5 auto-min + // probe when a min-content measure function is registered. Mirrors + // [measure]; see that method's note on non-overridability. + @DoNotStrip + public fun measureMinContent( + width: Float, + widthMode: Int, + height: Float, + heightMode: Int, + ): Long { + val mf = + checkNotNull(minContentMeasureFunction) { "Min-content measure function isn't defined!" } + return mf.measure( + this, + width, + YogaMeasureMode.fromInt(widthMode), + height, + YogaMeasureMode.fromInt(heightMode), + ) + } + override fun setBaselineFunction(yogaBaselineFunction: YogaBaselineFunction?) { baselineFunction = yogaBaselineFunction YogaNative.jni_YGNodeSetHasBaselineFuncJNI(nativePointer, yogaBaselineFunction != null) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaProps.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaProps.kt index 0d22ced8ccba..c155635ef885 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaProps.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaProps.kt @@ -125,6 +125,28 @@ public interface YogaProps { public fun setMeasureFunction(measureFunction: YogaMeasureFunction?) + public fun setMinContentMeasureFunction(measureFunction: YogaMeasureFunction?) + + /** + * Sets the static min-content width used by the CSS Flexbox §4.5 automatic minimum sizing probe. + * Pass `YogaConstants.UNDEFINED` to clear. See `YGNodeSetMinContentWidth` in the Yoga C API for + * full precedence rules. + */ + public fun setMinContentWidth(minContentWidth: Float) + + /** + * Sets the static min-content height used by the CSS Flexbox §4.5 automatic minimum sizing probe. + * Pass `YogaConstants.UNDEFINED` to clear. See `YGNodeSetMinContentHeight` in the Yoga C API for + * full precedence rules. + */ + public fun setMinContentHeight(minContentHeight: Float) + + /** Returns the static min-content width, or `YogaConstants.UNDEFINED` if not set. */ + public fun getMinContentWidth(): Float + + /** Returns the static min-content height, or `YogaConstants.UNDEFINED` if not set. */ + public fun getMinContentHeight(): Float + public fun setBaselineFunction(yogaBaselineFunction: YogaBaselineFunction?) /* Mutable properties - getter and setter with matching types */ diff --git a/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNIVanilla.cpp b/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNIVanilla.cpp index c5fdd8c79130..4afd9d5c2da5 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNIVanilla.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNIVanilla.cpp @@ -683,6 +683,83 @@ static void jni_YGNodeSetHasMeasureFuncJNI( static_cast(hasMeasureFunc) ? YGJNIMeasureFunc : nullptr); } +static YGSize YGJNIMinContentMeasureFunc( + YGNodeConstRef node, + float width, + YGMeasureMode widthMode, + float height, + YGMeasureMode heightMode) { + if (auto obj = YGNodeJobject(node)) { + YGTransferLayoutDirection(node, obj.get()); + JNIEnv* env = getCurrentEnv(); + auto objectClass = facebook::yoga::vanillajni::make_local_ref( + env, env->GetObjectClass(obj.get())); + // NOLINTNEXTLINE(misc-misplaced-const) + static const jmethodID methodId = facebook::yoga::vanillajni::getMethodId( + env, objectClass.get(), "measureMinContent", "(FIFI)J"); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + const auto measureResult = facebook::yoga::vanillajni::callLongMethod( + env, obj.get(), methodId, width, widthMode, height, heightMode); + + uint32_t wBits = 0xFFFFFFFF & (measureResult >> 32); + uint32_t hBits = 0xFFFFFFFF & measureResult; + auto measuredWidth = std::bit_cast(wBits); + auto measuredHeight = std::bit_cast(hBits); + + return YGSize{measuredWidth, measuredHeight}; + } else { + return YGSize{ + widthMode == YGMeasureModeUndefined ? 0 : width, + heightMode == YGMeasureModeUndefined ? 0 : height, + }; + } +} + +static void jni_YGNodeSetHasMinContentMeasureFuncJNI( + JNIEnv* /*env*/, + jobject /*obj*/, + jlong nativePointer, + jboolean hasMinContentMeasureFunc) { + YGNodeSetMinContentMeasureFunc( + _jlong2YGNodeRef(nativePointer), + static_cast(hasMinContentMeasureFunc) ? YGJNIMinContentMeasureFunc + : nullptr); +} + +static void jni_YGNodeSetMinContentWidthJNI( + JNIEnv* /*env*/, + jobject /*obj*/, + jlong nativePointer, + jfloat minContentWidth) { + YGNodeSetMinContentWidth( + _jlong2YGNodeRef(nativePointer), static_cast(minContentWidth)); +} + +static void jni_YGNodeSetMinContentHeightJNI( + JNIEnv* /*env*/, + jobject /*obj*/, + jlong nativePointer, + jfloat minContentHeight) { + YGNodeSetMinContentHeight( + _jlong2YGNodeRef(nativePointer), static_cast(minContentHeight)); +} + +static jfloat jni_YGNodeGetMinContentWidthJNI( + JNIEnv* /*env*/, + jobject /*obj*/, + jlong nativePointer) { + return static_cast( + YGNodeGetMinContentWidth(_jlong2YGNodeRef(nativePointer))); +} + +static jfloat jni_YGNodeGetMinContentHeightJNI( + JNIEnv* /*env*/, + jobject /*obj*/, + jlong nativePointer) { + return static_cast( + YGNodeGetMinContentHeight(_jlong2YGNodeRef(nativePointer))); +} + static float YGJNIBaselineFunc(YGNodeConstRef node, float width, float height) { if (auto obj = YGNodeJobject(node)) { JNIEnv* env = getCurrentEnv(); @@ -1058,6 +1135,23 @@ static JNINativeMethod methods[] = { {"jni_YGNodeSetHasMeasureFuncJNI", "(JZ)V", (void*)jni_YGNodeSetHasMeasureFuncJNI}, + // NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast) + {"jni_YGNodeSetHasMinContentMeasureFuncJNI", + "(JZ)V", + (void*)jni_YGNodeSetHasMinContentMeasureFuncJNI}, + {"jni_YGNodeSetMinContentWidthJNI", + "(JF)V", + (void*)jni_YGNodeSetMinContentWidthJNI}, + {"jni_YGNodeSetMinContentHeightJNI", + "(JF)V", + (void*)jni_YGNodeSetMinContentHeightJNI}, + {"jni_YGNodeGetMinContentWidthJNI", + "(J)F", + (void*)jni_YGNodeGetMinContentWidthJNI}, + {"jni_YGNodeGetMinContentHeightJNI", + "(J)F", + (void*)jni_YGNodeGetMinContentHeightJNI}, + // NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast) {"jni_YGNodeStyleGetGapJNI", "(JI)J", (void*)jni_YGNodeStyleGetGapJNI}, {"jni_YGNodeStyleSetGapJNI", "(JIF)V", (void*)jni_YGNodeStyleSetGapJNI}, {"jni_YGNodeStyleSetGapPercentJNI", diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index 6739e6bbd6f0..7906170ed532 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<99f843dd0784f9fe372f943767e2033c>> + * @generated SignedSource<> */ /** @@ -177,6 +177,12 @@ class ReactNativeFeatureFlagsJavaProvider return method(javaProvider_); } + bool enableFlexboxAutoMinSizeInStrictMode() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableFlexboxAutoMinSizeInStrictMode"); + return method(javaProvider_); + } + bool enableFontScaleChangesUpdatingLayout() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableFontScaleChangesUpdatingLayout"); @@ -680,6 +686,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableFabricLogs( return ReactNativeFeatureFlags::enableFabricLogs(); } +bool JReactNativeFeatureFlagsCxxInterop::enableFlexboxAutoMinSizeInStrictMode( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::enableFlexboxAutoMinSizeInStrictMode(); +} + bool JReactNativeFeatureFlagsCxxInterop::enableFontScaleChangesUpdatingLayout( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::enableFontScaleChangesUpdatingLayout(); @@ -1100,6 +1111,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "enableFabricLogs", JReactNativeFeatureFlagsCxxInterop::enableFabricLogs), + makeNativeMethod( + "enableFlexboxAutoMinSizeInStrictMode", + JReactNativeFeatureFlagsCxxInterop::enableFlexboxAutoMinSizeInStrictMode), makeNativeMethod( "enableFontScaleChangesUpdatingLayout", JReactNativeFeatureFlagsCxxInterop::enableFontScaleChangesUpdatingLayout), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index dd0b77894e26..ee17298bb295 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<05716b6ab8139bc31b962f9158acd6b6>> + * @generated SignedSource<<746da63dcbec1bb165731e7380993659>> */ /** @@ -99,6 +99,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool enableFabricLogs( facebook::jni::alias_ref); + static bool enableFlexboxAutoMinSizeInStrictMode( + facebook::jni::alias_ref); + static bool enableFontScaleChangesUpdatingLayout( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index 52b1f286fd63..e0afab4aa719 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * 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 SignedSource<<38e26847bb30888adaf6a965dae07cfb>> */ /** @@ -118,6 +118,10 @@ bool ReactNativeFeatureFlags::enableFabricLogs() { return getAccessor().enableFabricLogs(); } +bool ReactNativeFeatureFlags::enableFlexboxAutoMinSizeInStrictMode() { + return getAccessor().enableFlexboxAutoMinSizeInStrictMode(); +} + bool ReactNativeFeatureFlags::enableFontScaleChangesUpdatingLayout() { return getAccessor().enableFontScaleChangesUpdatingLayout(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index ab8a57dd6046..1e167a5a44b5 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * 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 SignedSource<<6958847f0d788c06cf64478ee2c36386>> */ /** @@ -154,6 +154,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool enableFabricLogs(); + /** + * 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. + */ + RN_EXPORT static bool enableFlexboxAutoMinSizeInStrictMode(); + /** * Enables font scale changes updating layout for measurable nodes. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 20cb03981c57..0c001f924d8d 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<802368c8b05006c737ab106bcb9ecf00>> + * @generated SignedSource<<78640fe49801cfa03638739e712c5e92>> */ /** @@ -443,6 +443,24 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricLogs() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::enableFlexboxAutoMinSizeInStrictMode() { + auto flagValue = enableFlexboxAutoMinSizeInStrictMode_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(23, "enableFlexboxAutoMinSizeInStrictMode"); + + flagValue = currentProvider_->enableFlexboxAutoMinSizeInStrictMode(); + enableFlexboxAutoMinSizeInStrictMode_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::enableFontScaleChangesUpdatingLayout() { auto flagValue = enableFontScaleChangesUpdatingLayout_.load(); @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFontScaleChangesUpdatingLayout() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(23, "enableFontScaleChangesUpdatingLayout"); + markFlagAsAccessed(24, "enableFontScaleChangesUpdatingLayout"); flagValue = currentProvider_->enableFontScaleChangesUpdatingLayout(); enableFontScaleChangesUpdatingLayout_ = flagValue; @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSTextBaselineOffsetPerLine() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(24, "enableIOSTextBaselineOffsetPerLine"); + markFlagAsAccessed(25, "enableIOSTextBaselineOffsetPerLine"); flagValue = currentProvider_->enableIOSTextBaselineOffsetPerLine(); enableIOSTextBaselineOffsetPerLine_ = flagValue; @@ -488,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSViewClipToPaddingBox() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(25, "enableIOSViewClipToPaddingBox"); + markFlagAsAccessed(26, "enableIOSViewClipToPaddingBox"); flagValue = currentProvider_->enableIOSViewClipToPaddingBox(); enableIOSViewClipToPaddingBox_ = flagValue; @@ -506,7 +524,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImagePrefetchingAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(26, "enableImagePrefetchingAndroid"); + markFlagAsAccessed(27, "enableImagePrefetchingAndroid"); flagValue = currentProvider_->enableImagePrefetchingAndroid(); enableImagePrefetchingAndroid_ = flagValue; @@ -524,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImageRequestDowngradingForNonVisible // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(27, "enableImageRequestDowngradingForNonVisibleImages"); + markFlagAsAccessed(28, "enableImageRequestDowngradingForNonVisibleImages"); flagValue = currentProvider_->enableImageRequestDowngradingForNonVisibleImages(); enableImageRequestDowngradingForNonVisibleImages_ = flagValue; @@ -542,7 +560,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImmediateUpdateModeForContentOffsetC // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(28, "enableImmediateUpdateModeForContentOffsetChanges"); + markFlagAsAccessed(29, "enableImmediateUpdateModeForContentOffsetChanges"); flagValue = currentProvider_->enableImmediateUpdateModeForContentOffsetChanges(); enableImmediateUpdateModeForContentOffsetChanges_ = flagValue; @@ -560,7 +578,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImperativeFocus() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(29, "enableImperativeFocus"); + markFlagAsAccessed(30, "enableImperativeFocus"); flagValue = currentProvider_->enableImperativeFocus(); enableImperativeFocus_ = flagValue; @@ -578,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::enableInteropViewManagerClassLookUpOptimiz // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(30, "enableInteropViewManagerClassLookUpOptimizationIOS"); + markFlagAsAccessed(31, "enableInteropViewManagerClassLookUpOptimizationIOS"); flagValue = currentProvider_->enableInteropViewManagerClassLookUpOptimizationIOS(); enableInteropViewManagerClassLookUpOptimizationIOS_ = flagValue; @@ -596,7 +614,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIntersectionObserverByDefault() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(31, "enableIntersectionObserverByDefault"); + markFlagAsAccessed(32, "enableIntersectionObserverByDefault"); flagValue = currentProvider_->enableIntersectionObserverByDefault(); enableIntersectionObserverByDefault_ = flagValue; @@ -614,7 +632,7 @@ bool ReactNativeFeatureFlagsAccessor::enableKeyEvents() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(32, "enableKeyEvents"); + markFlagAsAccessed(33, "enableKeyEvents"); flagValue = currentProvider_->enableKeyEvents(); enableKeyEvents_ = flagValue; @@ -632,7 +650,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(33, "enableLayoutAnimationsOnAndroid"); + markFlagAsAccessed(34, "enableLayoutAnimationsOnAndroid"); flagValue = currentProvider_->enableLayoutAnimationsOnAndroid(); enableLayoutAnimationsOnAndroid_ = flagValue; @@ -650,7 +668,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(34, "enableLayoutAnimationsOnIOS"); + markFlagAsAccessed(35, "enableLayoutAnimationsOnIOS"); flagValue = currentProvider_->enableLayoutAnimationsOnIOS(); enableLayoutAnimationsOnIOS_ = flagValue; @@ -668,7 +686,7 @@ bool ReactNativeFeatureFlagsAccessor::enableModuleArgumentNSNullConversionIOS() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(35, "enableModuleArgumentNSNullConversionIOS"); + markFlagAsAccessed(36, "enableModuleArgumentNSNullConversionIOS"); flagValue = currentProvider_->enableModuleArgumentNSNullConversionIOS(); enableModuleArgumentNSNullConversionIOS_ = flagValue; @@ -686,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::enableMutationObserverByDefault() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(36, "enableMutationObserverByDefault"); + markFlagAsAccessed(37, "enableMutationObserverByDefault"); flagValue = currentProvider_->enableMutationObserverByDefault(); enableMutationObserverByDefault_ = flagValue; @@ -704,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNativeCSSParsing() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(37, "enableNativeCSSParsing"); + markFlagAsAccessed(38, "enableNativeCSSParsing"); flagValue = currentProvider_->enableNativeCSSParsing(); enableNativeCSSParsing_ = flagValue; @@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNetworkEventReporting() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "enableNetworkEventReporting"); + markFlagAsAccessed(39, "enableNetworkEventReporting"); flagValue = currentProvider_->enableNetworkEventReporting(); enableNetworkEventReporting_ = flagValue; @@ -740,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePreparedTextLayout() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(39, "enablePreparedTextLayout"); + markFlagAsAccessed(40, "enablePreparedTextLayout"); flagValue = currentProvider_->enablePreparedTextLayout(); enablePreparedTextLayout_ = flagValue; @@ -758,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePropsUpdateReconciliationAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(40, "enablePropsUpdateReconciliationAndroid"); + markFlagAsAccessed(41, "enablePropsUpdateReconciliationAndroid"); flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid(); enablePropsUpdateReconciliationAndroid_ = flagValue; @@ -776,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::enableRuntimeSchedulerQueueClearingOnError // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(41, "enableRuntimeSchedulerQueueClearingOnError"); + markFlagAsAccessed(42, "enableRuntimeSchedulerQueueClearingOnError"); flagValue = currentProvider_->enableRuntimeSchedulerQueueClearingOnError(); enableRuntimeSchedulerQueueClearingOnError_ = flagValue; @@ -794,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSchedulerDelegateInvalidation() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(42, "enableSchedulerDelegateInvalidation"); + markFlagAsAccessed(43, "enableSchedulerDelegateInvalidation"); flagValue = currentProvider_->enableSchedulerDelegateInvalidation(); enableSchedulerDelegateInvalidation_ = flagValue; @@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSwiftUIBasedFilters() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "enableSwiftUIBasedFilters"); + markFlagAsAccessed(44, "enableSwiftUIBasedFilters"); flagValue = currentProvider_->enableSwiftUIBasedFilters(); enableSwiftUIBasedFilters_ = flagValue; @@ -830,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewCulling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(44, "enableViewCulling"); + markFlagAsAccessed(45, "enableViewCulling"); flagValue = currentProvider_->enableViewCulling(); enableViewCulling_ = flagValue; @@ -848,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(45, "enableViewRecycling"); + markFlagAsAccessed(46, "enableViewRecycling"); flagValue = currentProvider_->enableViewRecycling(); enableViewRecycling_ = flagValue; @@ -866,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForImage() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(46, "enableViewRecyclingForImage"); + markFlagAsAccessed(47, "enableViewRecyclingForImage"); flagValue = currentProvider_->enableViewRecyclingForImage(); enableViewRecyclingForImage_ = flagValue; @@ -884,7 +902,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForScrollView() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(47, "enableViewRecyclingForScrollView"); + markFlagAsAccessed(48, "enableViewRecyclingForScrollView"); flagValue = currentProvider_->enableViewRecyclingForScrollView(); enableViewRecyclingForScrollView_ = flagValue; @@ -902,7 +920,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForText() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(48, "enableViewRecyclingForText"); + markFlagAsAccessed(49, "enableViewRecyclingForText"); flagValue = currentProvider_->enableViewRecyclingForText(); enableViewRecyclingForText_ = flagValue; @@ -920,7 +938,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForView() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(49, "enableViewRecyclingForView"); + markFlagAsAccessed(50, "enableViewRecyclingForView"); flagValue = currentProvider_->enableViewRecyclingForView(); enableViewRecyclingForView_ = flagValue; @@ -938,7 +956,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewContainerStateExperimenta // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(50, "enableVirtualViewContainerStateExperimental"); + markFlagAsAccessed(51, "enableVirtualViewContainerStateExperimental"); flagValue = currentProvider_->enableVirtualViewContainerStateExperimental(); enableVirtualViewContainerStateExperimental_ = flagValue; @@ -956,7 +974,7 @@ bool ReactNativeFeatureFlagsAccessor::fixDifferentiatorParentTagForUnflattenCase // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(51, "fixDifferentiatorParentTagForUnflattenCase"); + markFlagAsAccessed(52, "fixDifferentiatorParentTagForUnflattenCase"); flagValue = currentProvider_->fixDifferentiatorParentTagForUnflattenCase(); fixDifferentiatorParentTagForUnflattenCase_ = flagValue; @@ -974,7 +992,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(52, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + markFlagAsAccessed(53, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; @@ -992,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::fixYogaFlexBasisFitContentInMainAxis() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(53, "fixYogaFlexBasisFitContentInMainAxis"); + markFlagAsAccessed(54, "fixYogaFlexBasisFitContentInMainAxis"); flagValue = currentProvider_->fixYogaFlexBasisFitContentInMainAxis(); fixYogaFlexBasisFitContentInMainAxis_ = flagValue; @@ -1010,7 +1028,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxAssertSingleHostState() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(54, "fuseboxAssertSingleHostState"); + markFlagAsAccessed(55, "fuseboxAssertSingleHostState"); flagValue = currentProvider_->fuseboxAssertSingleHostState(); fuseboxAssertSingleHostState_ = flagValue; @@ -1028,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(55, "fuseboxEnabledRelease"); + markFlagAsAccessed(56, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -1046,7 +1064,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxFrameRecordingEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(56, "fuseboxFrameRecordingEnabled"); + markFlagAsAccessed(57, "fuseboxFrameRecordingEnabled"); flagValue = currentProvider_->fuseboxFrameRecordingEnabled(); fuseboxFrameRecordingEnabled_ = flagValue; @@ -1064,7 +1082,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxNetworkInspectionEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(57, "fuseboxNetworkInspectionEnabled"); + markFlagAsAccessed(58, "fuseboxNetworkInspectionEnabled"); flagValue = currentProvider_->fuseboxNetworkInspectionEnabled(); fuseboxNetworkInspectionEnabled_ = flagValue; @@ -1082,7 +1100,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxScreenshotCaptureEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(58, "fuseboxScreenshotCaptureEnabled"); + markFlagAsAccessed(59, "fuseboxScreenshotCaptureEnabled"); flagValue = currentProvider_->fuseboxScreenshotCaptureEnabled(); fuseboxScreenshotCaptureEnabled_ = flagValue; @@ -1100,7 +1118,7 @@ bool ReactNativeFeatureFlagsAccessor::hideOffscreenVirtualViewsOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(59, "hideOffscreenVirtualViewsOnIOS"); + markFlagAsAccessed(60, "hideOffscreenVirtualViewsOnIOS"); flagValue = currentProvider_->hideOffscreenVirtualViewsOnIOS(); hideOffscreenVirtualViewsOnIOS_ = flagValue; @@ -1118,7 +1136,7 @@ bool ReactNativeFeatureFlagsAccessor::optimizedAnimatedPropUpdates() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(60, "optimizedAnimatedPropUpdates"); + markFlagAsAccessed(61, "optimizedAnimatedPropUpdates"); flagValue = currentProvider_->optimizedAnimatedPropUpdates(); optimizedAnimatedPropUpdates_ = flagValue; @@ -1136,7 +1154,7 @@ bool ReactNativeFeatureFlagsAccessor::overrideBySynchronousMountPropsAtMountingA // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(61, "overrideBySynchronousMountPropsAtMountingAndroid"); + markFlagAsAccessed(62, "overrideBySynchronousMountPropsAtMountingAndroid"); flagValue = currentProvider_->overrideBySynchronousMountPropsAtMountingAndroid(); overrideBySynchronousMountPropsAtMountingAndroid_ = flagValue; @@ -1154,7 +1172,7 @@ bool ReactNativeFeatureFlagsAccessor::perfIssuesEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(62, "perfIssuesEnabled"); + markFlagAsAccessed(63, "perfIssuesEnabled"); flagValue = currentProvider_->perfIssuesEnabled(); perfIssuesEnabled_ = flagValue; @@ -1172,7 +1190,7 @@ bool ReactNativeFeatureFlagsAccessor::perfMonitorV2Enabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(63, "perfMonitorV2Enabled"); + markFlagAsAccessed(64, "perfMonitorV2Enabled"); flagValue = currentProvider_->perfMonitorV2Enabled(); perfMonitorV2Enabled_ = flagValue; @@ -1190,7 +1208,7 @@ double ReactNativeFeatureFlagsAccessor::preparedTextCacheSize() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(64, "preparedTextCacheSize"); + markFlagAsAccessed(65, "preparedTextCacheSize"); flagValue = currentProvider_->preparedTextCacheSize(); preparedTextCacheSize_ = flagValue; @@ -1208,7 +1226,7 @@ bool ReactNativeFeatureFlagsAccessor::preventShadowTreeCommitExhaustion() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(65, "preventShadowTreeCommitExhaustion"); + markFlagAsAccessed(66, "preventShadowTreeCommitExhaustion"); flagValue = currentProvider_->preventShadowTreeCommitExhaustion(); preventShadowTreeCommitExhaustion_ = flagValue; @@ -1226,7 +1244,7 @@ bool ReactNativeFeatureFlagsAccessor::redBoxV2Android() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(66, "redBoxV2Android"); + markFlagAsAccessed(67, "redBoxV2Android"); flagValue = currentProvider_->redBoxV2Android(); redBoxV2Android_ = flagValue; @@ -1244,7 +1262,7 @@ bool ReactNativeFeatureFlagsAccessor::redBoxV2IOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(67, "redBoxV2IOS"); + markFlagAsAccessed(68, "redBoxV2IOS"); flagValue = currentProvider_->redBoxV2IOS(); redBoxV2IOS_ = flagValue; @@ -1262,7 +1280,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldPressibilityUseW3CPointerEventsForHo // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(68, "shouldPressibilityUseW3CPointerEventsForHover"); + markFlagAsAccessed(69, "shouldPressibilityUseW3CPointerEventsForHover"); flagValue = currentProvider_->shouldPressibilityUseW3CPointerEventsForHover(); shouldPressibilityUseW3CPointerEventsForHover_ = flagValue; @@ -1280,7 +1298,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldTriggerResponderTransferOnScrollAndr // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(69, "shouldTriggerResponderTransferOnScrollAndroid"); + markFlagAsAccessed(70, "shouldTriggerResponderTransferOnScrollAndroid"); flagValue = currentProvider_->shouldTriggerResponderTransferOnScrollAndroid(); shouldTriggerResponderTransferOnScrollAndroid_ = flagValue; @@ -1298,7 +1316,7 @@ bool ReactNativeFeatureFlagsAccessor::skipActivityIdentityAssertionOnHostPause() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(70, "skipActivityIdentityAssertionOnHostPause"); + markFlagAsAccessed(71, "skipActivityIdentityAssertionOnHostPause"); flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause(); skipActivityIdentityAssertionOnHostPause_ = flagValue; @@ -1316,7 +1334,7 @@ bool ReactNativeFeatureFlagsAccessor::syncAndroidClipBoundsWithOverflow() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(71, "syncAndroidClipBoundsWithOverflow"); + markFlagAsAccessed(72, "syncAndroidClipBoundsWithOverflow"); flagValue = currentProvider_->syncAndroidClipBoundsWithOverflow(); syncAndroidClipBoundsWithOverflow_ = flagValue; @@ -1334,7 +1352,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(72, "traceTurboModulePromiseRejectionsOnAndroid"); + markFlagAsAccessed(73, "traceTurboModulePromiseRejectionsOnAndroid"); flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid(); traceTurboModulePromiseRejectionsOnAndroid_ = flagValue; @@ -1352,7 +1370,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommit( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(73, "updateRuntimeShadowNodeReferencesOnCommit"); + markFlagAsAccessed(74, "updateRuntimeShadowNodeReferencesOnCommit"); flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit(); updateRuntimeShadowNodeReferencesOnCommit_ = flagValue; @@ -1370,7 +1388,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommitT // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(74, "updateRuntimeShadowNodeReferencesOnCommitThread"); + markFlagAsAccessed(75, "updateRuntimeShadowNodeReferencesOnCommitThread"); flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommitThread(); updateRuntimeShadowNodeReferencesOnCommitThread_ = flagValue; @@ -1388,7 +1406,7 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(75, "useAlwaysAvailableJSErrorHandling"); + markFlagAsAccessed(76, "useAlwaysAvailableJSErrorHandling"); flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling(); useAlwaysAvailableJSErrorHandling_ = flagValue; @@ -1406,7 +1424,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(76, "useFabricInterop"); + markFlagAsAccessed(77, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -1424,7 +1442,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(77, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(78, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -1442,7 +1460,7 @@ bool ReactNativeFeatureFlagsAccessor::useNestedScrollViewAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(78, "useNestedScrollViewAndroid"); + markFlagAsAccessed(79, "useNestedScrollViewAndroid"); flagValue = currentProvider_->useNestedScrollViewAndroid(); useNestedScrollViewAndroid_ = flagValue; @@ -1460,7 +1478,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedViewRegistryOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(79, "useOptimizedViewRegistryOnAndroid"); + markFlagAsAccessed(80, "useOptimizedViewRegistryOnAndroid"); flagValue = currentProvider_->useOptimizedViewRegistryOnAndroid(); useOptimizedViewRegistryOnAndroid_ = flagValue; @@ -1478,7 +1496,7 @@ bool ReactNativeFeatureFlagsAccessor::useSharedAnimatedBackend() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(80, "useSharedAnimatedBackend"); + markFlagAsAccessed(81, "useSharedAnimatedBackend"); flagValue = currentProvider_->useSharedAnimatedBackend(); useSharedAnimatedBackend_ = flagValue; @@ -1496,7 +1514,7 @@ bool ReactNativeFeatureFlagsAccessor::useTraitHiddenOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(81, "useTraitHiddenOnAndroid"); + markFlagAsAccessed(82, "useTraitHiddenOnAndroid"); flagValue = currentProvider_->useTraitHiddenOnAndroid(); useTraitHiddenOnAndroid_ = flagValue; @@ -1514,7 +1532,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(82, "useTurboModuleInterop"); + markFlagAsAccessed(83, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -1532,7 +1550,7 @@ double ReactNativeFeatureFlagsAccessor::viewCullingOutsetRatio() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(83, "viewCullingOutsetRatio"); + markFlagAsAccessed(84, "viewCullingOutsetRatio"); flagValue = currentProvider_->viewCullingOutsetRatio(); viewCullingOutsetRatio_ = flagValue; @@ -1550,7 +1568,7 @@ bool ReactNativeFeatureFlagsAccessor::viewTransitionEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(84, "viewTransitionEnabled"); + markFlagAsAccessed(85, "viewTransitionEnabled"); flagValue = currentProvider_->viewTransitionEnabled(); viewTransitionEnabled_ = flagValue; @@ -1568,7 +1586,7 @@ bool ReactNativeFeatureFlagsAccessor::viewTransitionUseHardwareBitmapAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(85, "viewTransitionUseHardwareBitmapAndroid"); + markFlagAsAccessed(86, "viewTransitionUseHardwareBitmapAndroid"); flagValue = currentProvider_->viewTransitionUseHardwareBitmapAndroid(); viewTransitionUseHardwareBitmapAndroid_ = flagValue; @@ -1586,7 +1604,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(86, "virtualViewPrerenderRatio"); + markFlagAsAccessed(87, "virtualViewPrerenderRatio"); flagValue = currentProvider_->virtualViewPrerenderRatio(); virtualViewPrerenderRatio_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index bab489993007..3bd3cb987fb1 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6126d94aaf219c0d4a3ffe84c05b0fb2>> + * @generated SignedSource<<1974d5797f43e8f73b521ebfd46ce492>> */ /** @@ -55,6 +55,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableExclusivePropsUpdateAndroid(); bool enableFabricCommitBranching(); bool enableFabricLogs(); + bool enableFlexboxAutoMinSizeInStrictMode(); bool enableFontScaleChangesUpdatingLayout(); bool enableIOSTextBaselineOffsetPerLine(); bool enableIOSViewClipToPaddingBox(); @@ -130,7 +131,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 87> accessedFeatureFlags_; + std::array, 88> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> cdpInteractionMetricsEnabled_; @@ -155,6 +156,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableExclusivePropsUpdateAndroid_; std::atomic> enableFabricCommitBranching_; std::atomic> enableFabricLogs_; + std::atomic> enableFlexboxAutoMinSizeInStrictMode_; std::atomic> enableFontScaleChangesUpdatingLayout_; std::atomic> enableIOSTextBaselineOffsetPerLine_; std::atomic> enableIOSViewClipToPaddingBox_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 57e4fb09c82d..e0bebd010bc9 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * 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 SignedSource<<8dfc52502bd539e5e43d547f895a6d33>> */ /** @@ -119,6 +119,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool enableFlexboxAutoMinSizeInStrictMode() override { + return false; + } + bool enableFontScaleChangesUpdatingLayout() override { return true; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index 6a93f2ca138e..fcfa1eff96a5 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h @@ -4,7 +4,7 @@ * 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 SignedSource<<15bb8c904ef3116d0f6042623a150d8c>> */ /** @@ -252,6 +252,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::enableFabricLogs(); } + bool enableFlexboxAutoMinSizeInStrictMode() override { + auto value = values_["enableFlexboxAutoMinSizeInStrictMode"]; + if (!value.isNull()) { + return value.getBool(); + } + + return ReactNativeFeatureFlagsDefaults::enableFlexboxAutoMinSizeInStrictMode(); + } + bool enableFontScaleChangesUpdatingLayout() override { auto value = values_["enableFontScaleChangesUpdatingLayout"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.h index 1312fb2baa36..ac8522edf756 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.h @@ -4,7 +4,7 @@ * 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 SignedSource<> */ /** @@ -31,6 +31,10 @@ class ReactNativeFeatureFlagsOverridesOSSExperimental : public ReactNativeFeatur return true; } + bool enableFlexboxAutoMinSizeInStrictMode() override { + return true; + } + bool enableRuntimeSchedulerQueueClearingOnError() override { return true; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 1a9ac2e36714..f3781b150a1c 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<8a9430ba71722a75779e2b5fb6564f0e>> + * @generated SignedSource<> */ /** @@ -48,6 +48,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableExclusivePropsUpdateAndroid() = 0; virtual bool enableFabricCommitBranching() = 0; virtual bool enableFabricLogs() = 0; + virtual bool enableFlexboxAutoMinSizeInStrictMode() = 0; virtual bool enableFontScaleChangesUpdatingLayout() = 0; virtual bool enableIOSTextBaselineOffsetPerLine() = 0; virtual bool enableIOSViewClipToPaddingBox() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index b3d37e663da1..06f80646d7ae 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * 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 SignedSource<<34ba54f5915738fc4792567680679880>> */ /** @@ -159,6 +159,11 @@ bool NativeReactNativeFeatureFlags::enableFabricLogs( return ReactNativeFeatureFlags::enableFabricLogs(); } +bool NativeReactNativeFeatureFlags::enableFlexboxAutoMinSizeInStrictMode( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::enableFlexboxAutoMinSizeInStrictMode(); +} + bool NativeReactNativeFeatureFlags::enableFontScaleChangesUpdatingLayout( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::enableFontScaleChangesUpdatingLayout(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 2fc43feda73e..033fa3999427 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<9a21979a5eeb2f9daf8c061610199596>> + * @generated SignedSource<<32404575231774f230ece7a097ae08c5>> */ /** @@ -82,6 +82,8 @@ class NativeReactNativeFeatureFlags bool enableFabricLogs(jsi::Runtime& runtime); + bool enableFlexboxAutoMinSizeInStrictMode(jsi::Runtime& runtime); + bool enableFontScaleChangesUpdatingLayout(jsi::Runtime& runtime); bool enableIOSTextBaselineOffsetPerLine(jsi::Runtime& runtime); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index 2fe7f96c02ab..18296cfa3054 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -514,7 +514,19 @@ YGErrata YogaLayoutableShadowNode::resolveErrata(YGErrata defaultErrata) const { dynamic_cast(this)) { switch (layoutConformanceNode->getConcreteProps().mode) { case LayoutConformance::Strict: - return YGErrataNone; + // CSS Flexbox §4.5 automatic minimum sizing is the spec-compliant + // behaviour, so strict conformance should adopt it — but its probe + // walks measure callbacks with `AtMost 0`, which can surface latent + // bugs in platform measure overrides. Gate the rollout behind a + // feature flag so the behaviour can be ramped independently of strict + // conformance: when enabled, clear every errata bit (fully + // spec-compliant); when disabled (default), keep + // `MinSizeUndefinedInsteadOfAuto` set so strict subtrees preserve + // today's behaviour and the auto-min probe stays explicitly opt-in + // via `YogaConfig` setup. + return ReactNativeFeatureFlags::enableFlexboxAutoMinSizeInStrictMode() + ? YGErrataNone + : YGErrataMinSizeUndefinedInsteadOfAuto; case LayoutConformance::Compatibility: return YGErrataAll; } diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.cpp index 538b0b0847e3..1e823138684a 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.cpp @@ -117,6 +117,8 @@ const char* YGErrataToString(const YGErrata value) { return "absolute-position-without-insets-excludes-padding"; case YGErrataAbsolutePercentAgainstInnerSize: return "absolute-percent-against-inner-size"; + case YGErrataMinSizeUndefinedInsteadOfAuto: + return "min-size-undefined-instead-of-auto"; case YGErrataAll: return "all"; case YGErrataClassic: diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h index aa0b1d4350db..f96abdf2f58c 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h @@ -67,6 +67,7 @@ YG_ENUM_DECL( YGErrataStretchFlexBasis = 1, YGErrataAbsolutePositionWithoutInsetsExcludesPadding = 2, YGErrataAbsolutePercentAgainstInnerSize = 4, + YGErrataMinSizeUndefinedInsteadOfAuto = 8, YGErrataAll = 2147483647, YGErrataClassic = 2147483646) YG_DEFINE_ENUM_FLAG_OPERATORS(YGErrata) diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp index f55cab6be45d..7a4068efee2b 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp @@ -309,6 +309,32 @@ bool YGNodeHasMeasureFunc(YGNodeConstRef node) { return resolveRef(node)->hasMeasureFunc(); } +void YGNodeSetMinContentMeasureFunc( + YGNodeRef node, + YGMinContentMeasureFunc minContentMeasureFunc) { + resolveRef(node)->setMinContentMeasureFunc(minContentMeasureFunc); +} + +bool YGNodeHasMinContentMeasureFunc(YGNodeConstRef node) { + return resolveRef(node)->hasMinContentMeasureFunc(); +} + +void YGNodeSetMinContentWidth(YGNodeRef node, float minContentWidth) { + resolveRef(node)->setMinContentWidth(FloatOptional{minContentWidth}); +} + +void YGNodeSetMinContentHeight(YGNodeRef node, float minContentHeight) { + resolveRef(node)->setMinContentHeight(FloatOptional{minContentHeight}); +} + +float YGNodeGetMinContentWidth(YGNodeConstRef node) { + return resolveRef(node)->getMinContentWidth().unwrapOrDefault(YGUndefined); +} + +float YGNodeGetMinContentHeight(YGNodeConstRef node) { + return resolveRef(node)->getMinContentHeight().unwrapOrDefault(YGUndefined); +} + void YGNodeSetBaselineFunc(YGNodeRef node, YGBaselineFunc baselineFunc) { resolveRef(node)->setBaselineFunc(baselineFunc); } diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGNode.h b/packages/react-native/ReactCommon/yoga/yoga/YGNode.h index 8ff3130c3c70..7a9b0e1c3f12 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGNode.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGNode.h @@ -220,6 +220,75 @@ YG_EXPORT void YGNodeSetMeasureFunc(YGNodeRef node, YGMeasureFunc measureFunc); */ YG_EXPORT bool YGNodeHasMeasureFunc(YGNodeConstRef node); +/** + * Optional companion to `YGMeasureFunc` invoked by the CSS Flexbox §4.5 + * automatic minimum sizing path when probing this node for its min-content + * size along the main axis. + * + * The signature mirrors `YGMeasureFunc`. The algorithm calls this with + * `AtMost 0` along the probed axis and `Undefined` on the other. A + * min-content-aware Primitive can return its true minimum (e.g., `Image` + * and `Collection` along the scroll axis can return 0; text returns its + * longest-word width; etc.) without doing a full measure pass. + * + * When unset, the algorithm falls back to the regular `YGMeasureFunc` + * invoked with the same `AtMost 0` constraint — preserving today's + * behavior. Setting this is a perf opt-in for Primitives whose min-content + * size is cheap to compute or differs from what the regular measure would + * return. + */ +typedef YGSize (*YGMinContentMeasureFunc)( + YGNodeConstRef node, + float width, + YGMeasureMode widthMode, + float height, + YGMeasureMode heightMode); + +/** + * Provides a measure function specialised for min-content probes. See + * `YGMinContentMeasureFunc`. + */ +YG_EXPORT void YGNodeSetMinContentMeasureFunc( + YGNodeRef node, + YGMinContentMeasureFunc minContentMeasureFunc); + +/** + * Whether a min-content measure function is set. + */ +YG_EXPORT bool YGNodeHasMinContentMeasureFunc(YGNodeConstRef node); + +/** + * Static per-axis min-content size used by the CSS Flexbox §4.5 automatic + * minimum sizing probe. Pass `YGUndefined` to clear. + * + * When set, the algorithm's probe short-circuits at this node along the + * matching axis — skipping both the regular `YGMeasureFunc` / `YGMinContent + * MeasureFunc` callback path AND any container recursion. The most common + * use is declaring "0" for axes that have no min-content contribution per + * spec (e.g., images on both axes; scroll containers along their scroll + * axis). + * + * Precedence inside the probe is: + * 1. Static value via `YGNodeSetMinContentWidth/Height` (this API) + * 2. Dynamic callback via `YGNodeSetMinContentMeasureFunc` + * 3. Regular `YGMeasureFunc` with `AtMost 0` (today's default) + * 4. Container recursion (sum on main axis, max on cross) + * + * Static is preferred for known-constant values because it skips the JNI + * round-trip / native callback dispatch entirely. + */ +YG_EXPORT void YGNodeSetMinContentWidth(YGNodeRef node, float minContentWidth); +YG_EXPORT void YGNodeSetMinContentHeight( + YGNodeRef node, + float minContentHeight); + +/** + * Returns the static min-content size along the requested axis, or + * `YGUndefined` if not set. + */ +YG_EXPORT float YGNodeGetMinContentWidth(YGNodeConstRef node); +YG_EXPORT float YGNodeGetMinContentHeight(YGNodeConstRef node); + /** * @returns a defined offset to baseline (ascent). */ diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp index 4aa56cffa0cb..f48f261e31ff 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp @@ -653,6 +653,230 @@ static float computeFlexBasisForChildren( return totalOuterFlexBasis; } +// Returns the min-content size of `node` along `requestedAxis`, used by CSS +// Flexbox §4.5 automatic minimum sizing. +// +// Mirrors RenderCore FlexLayout's `AlgorithmBase::computeMinContentSize` / +// `measureMinContentMainSize` pair (see `xplat/flexlayout/flexlayout/ +// FlexboxAlgorithm.h`). Unlike FlexLayout, which crosses a JNI/bridge +// boundary for nested flex containers via thread-local min-content markers, +// Yoga's flex containers are native nodes — so this function recurses +// directly into containers rather than going through a measure callback. +// +// Algorithm: +// * Leaf with measure function: invoke it with `AtMost 0` on the +// requested axis and `Undefined` on the other. Text measure-funcs +// respond with longest-word width; image/collection-like measures +// respond with 0 along their scroll axis. +// * Empty leaf: return 0. +// * Container: iterate in-flow children. For each, take its +// min-content along the container's own main axis (sum into +// `mainTotal`) and along its cross axis (max into `crossMax`), +// plus the child's margins. Add the container's own padding and +// border on both ends of each axis. Project onto `requestedAxis`. +// +// Container-level recursion does no layout writes (no positions, no +// alignment, no flex distribution); only the descendant leaf measure +// callbacks observe state changes (the same ones a normal layout pass +// would invoke). Roughly equivalent to FlexLayout's dedicated +// `computeMinContentSize` cost: one measure call per leaf + linear walk +// per container. +static float computeMinContentMainSize( + yoga::Node* const node, + const FlexDirection requestedAxis, + const Direction ownerDirection, + const float ownerWidth, + const float ownerHeight) { + const bool wantRow = isRow(requestedAxis); + + // 1. Static value wins for any node (leaf or container). Short-circuits + // both the measure callback path AND any container recursion. The most + // common use is `YGNodeSetMinContentWidth(node, 0)` declaring no + // contribution per CSS-Images (Image) or CSS-Overflow (scroll + // containers along their scroll axis). + const FloatOptional staticMin = + wantRow ? node->getMinContentWidth() : node->getMinContentHeight(); + if (staticMin.isDefined()) { + return staticMin.unwrap(); + } + + if (node->hasMeasureFunc()) { + // 2. Dynamic min-content callback if set (for Primitives whose + // min-content depends on state). Otherwise fall back to the regular + // measure function with `AtMost 0`, which text measurers naturally + // answer with longest-word width. + const YGSize size = node->hasMinContentMeasureFunc() + ? node->measureMinContent( + wantRow ? 0.0f : YGUndefined, + wantRow ? MeasureMode::AtMost : MeasureMode::Undefined, + wantRow ? YGUndefined : 0.0f, + wantRow ? MeasureMode::Undefined : MeasureMode::AtMost) + : node->measure( + wantRow ? 0.0f : YGUndefined, + wantRow ? MeasureMode::AtMost : MeasureMode::Undefined, + wantRow ? YGUndefined : 0.0f, + wantRow ? MeasureMode::Undefined : MeasureMode::AtMost); + return wantRow ? size.width : size.height; + } + + if (node->getChildCount() == 0) { + return 0.0f; + } + + const Direction direction = node->resolveDirection(ownerDirection); + const FlexDirection nodeMainAxis = + resolveDirection(node->style().flexDirection(), direction); + const FlexDirection nodeCrossAxis = + resolveCrossDirection(nodeMainAxis, direction); + + float mainTotal = 0.0f; + float crossMax = 0.0f; + + for (size_t i = 0; i < node->getChildCount(); i++) { + auto* const child = node->getChild(i); + if (child->style().display() == Display::None || + child->style().positionType() == PositionType::Absolute) { + continue; + } + + float childMain = computeMinContentMainSize( + child, nodeMainAxis, direction, ownerWidth, ownerHeight); + childMain += child->style().computeMarginForAxis(nodeMainAxis, ownerWidth); + + float childCross = computeMinContentMainSize( + child, nodeCrossAxis, direction, ownerWidth, ownerHeight); + childCross += + child->style().computeMarginForAxis(nodeCrossAxis, ownerWidth); + + mainTotal += childMain; + crossMax = std::max(crossMax, childCross); + } + + mainTotal += node->style().computeFlexStartPaddingAndBorder( + nodeMainAxis, direction, ownerWidth) + + node->style().computeFlexEndPaddingAndBorder( + nodeMainAxis, direction, ownerWidth); + crossMax += node->style().computeFlexStartPaddingAndBorder( + nodeCrossAxis, direction, ownerWidth) + + node->style().computeFlexEndPaddingAndBorder( + nodeCrossAxis, direction, ownerWidth); + + const bool nodeMainIsRow = isRow(nodeMainAxis); + const float widthMin = nodeMainIsRow ? mainTotal : crossMax; + const float heightMin = nodeMainIsRow ? crossMax : mainTotal; + return wantRow ? widthMin : heightMin; +} + +// Computes the CSS Flexbox §4.5 automatic minimum main-axis size for +// `child`. Returns Undefined when no auto-min applies (feature off, explicit +// `min-{w,h}` already set, or `display:none`); 0 when the item's own +// `overflow != visible` (the spec's per-item escape hatch); or a concrete +// floor otherwise. +// +// Floor = min(content-size, specified-size) capped by max-size, with the +// transferred (aspect-ratio × cross-size) suggestion replacing the +// specified-size leg when the item has an aspect ratio but no specified +// main size. See https://www.w3.org/TR/css-flexbox-1/#min-size-auto. +static FloatOptional computeAutoMinMainSize( + yoga::Node* const child, + const FlexDirection mainAxis, + const Direction direction, + const float ownerMainAxisSize, + const float ownerWidth, + const float ownerHeight) { + if (child->hasErrata(Errata::MinSizeUndefinedInsteadOfAuto)) { + return FloatOptional{}; + } + if (child->style().display() == Display::None) { + return FloatOptional{}; + } + // Explicit `min-{w,h}` (including `0`) wins over auto. This is the + // CSS-spec opt-out (§4.5). + if (child->style().minDimension(dimension(mainAxis)).isDefined()) { + return FloatOptional{}; + } + // Per CSS §4.5: a flex item whose own `overflow` is not `visible` gets + // auto-min = 0 (let scroll/clip handle overflow rather than enforce a + // content-based minimum). + if (child->style().overflow() != Overflow::Visible) { + return FloatOptional{0.0f}; + } + + const Dimension mainDim = dimension(mainAxis); + const Dimension crossDim = + isRow(mainAxis) ? Dimension::Height : Dimension::Width; + const bool isMainAxisRow = isRow(mainAxis); + + // Specified size suggestion: the resolved main-axis style dimension. + const FloatOptional specifiedMain = child->getResolvedDimension( + direction, mainDim, ownerMainAxisSize, ownerWidth); + + // Transferred size suggestion: cross × aspect-ratio, if both are definite. + FloatOptional transferredMain; + const FloatOptional aspectRatio = child->style().aspectRatio(); + if (aspectRatio.isDefined()) { + const float crossOwner = isMainAxisRow ? ownerHeight : ownerWidth; + const FloatOptional crossResolved = child->getResolvedDimension( + direction, crossDim, crossOwner, ownerWidth); + if (crossResolved.isDefined()) { + const float ratio = aspectRatio.unwrap(); + const float crossValue = crossResolved.unwrap(); + transferredMain = FloatOptional{ + isMainAxisRow ? crossValue * ratio : crossValue / ratio}; + } + } + + // Content size suggestion: probe via min-content recursion. + const FloatOptional contentMain = FloatOptional{computeMinContentMainSize( + child, mainAxis, direction, ownerWidth, ownerHeight)}; + + // Combine per §4.5: floor = min(content, specified) when specified is + // definite; otherwise floor = min(content, transferred) when transferred + // applies (item has aspect-ratio + definite cross + no specified main); + // else floor = content. + FloatOptional floor = contentMain; + if (specifiedMain.isDefined()) { + if (floor.isUndefined() || specifiedMain < floor) { + floor = specifiedMain; + } + } else if (transferredMain.isDefined()) { + if (floor.isUndefined() || transferredMain < floor) { + floor = transferredMain; + } + } + + // §4.5: cap by the max main size. + const FloatOptional maxMain = child->style().resolvedMaxDimension( + direction, mainDim, ownerMainAxisSize, ownerWidth); + if (maxMain.isDefined() && floor > maxMain) { + floor = maxMain; + } + + if (floor.isUndefined() || floor.unwrap() < 0.0f) { + floor = FloatOptional{0.0f}; + } + return floor; +} + +// boundAxis with an additional lower bound from `child`'s cached +// `computedAutoMinMainSize`, applied on the main axis only. Used inside +// the flex-shrink distribution to honor CSS §4.5 auto-min while preserving +// the existing min/max/padding-and-border clamping. +static float boundAxisWithAutoMin( + const yoga::Node* const child, + const FlexDirection axis, + const Direction direction, + const float value, + const float axisSize, + const float widthSize) { + float bounded = boundAxis(child, axis, direction, value, axisSize, widthSize); + const FloatOptional autoMin = child->getLayout().computedAutoMinMainSize; + if (autoMin.isDefined() && bounded < autoMin.unwrap()) { + bounded = autoMin.unwrap(); + } + return bounded; +} + // It distributes the free space to the flexible items and ensures that the size // of the flex items abide the min and max constraints. At the end of this // function the child nodes would have proper size. Prior using this function @@ -711,7 +935,7 @@ static float distributeFreeSpaceSecondPass( flexShrinkScaledFactor; } - updatedMainSize = boundAxis( + updatedMainSize = boundAxisWithAutoMin( currentLineChild, mainAxis, direction, @@ -726,7 +950,7 @@ static float distributeFreeSpaceSecondPass( // Is this child able to grow? if (!std::isnan(flexGrowFactor) && flexGrowFactor != 0) { - updatedMainSize = boundAxis( + updatedMainSize = boundAxisWithAutoMin( currentLineChild, mainAxis, direction, @@ -891,7 +1115,7 @@ static void distributeFreeSpaceFirstPass( flexLine.layout.remainingFreeSpace / flexLine.layout.totalFlexShrinkScaledFactors * flexShrinkScaledFactor; - boundMainSize = boundAxis( + boundMainSize = boundAxisWithAutoMin( currentLineChild, mainAxis, direction, @@ -984,6 +1208,29 @@ static void resolveFlexibleLength( const uint32_t depth, const uint32_t generationCount) { const float originalFreeSpace = flexLine.layout.remainingFreeSpace; + + // CSS Flexbox §4.5: compute each item's automatic minimum main-axis size + // up front so the bounding helpers below can floor shrunk values. + // computeAutoMinMainSize returns Undefined when the feature is off or an + // explicit `min-{w,h}` already pins the floor, in which case the cached + // value is also Undefined and `boundAxisWithAutoMin` reduces to `boundAxis`. + if (!node->hasErrata(Errata::MinSizeUndefinedInsteadOfAuto)) { + for (auto currentLineChild : flexLine.itemsInFlow) { + currentLineChild->getLayout().computedAutoMinMainSize = + computeAutoMinMainSize( + currentLineChild, + mainAxis, + direction, + mainAxisOwnerSize, + availableInnerWidth, + availableInnerHeight); + } + } else { + for (auto currentLineChild : flexLine.itemsInFlow) { + currentLineChild->getLayout().computedAutoMinMainSize = FloatOptional{}; + } + } + // First pass: detect the flex items whose min/max constraints trigger distributeFreeSpaceFirstPass( flexLine, diff --git a/packages/react-native/ReactCommon/yoga/yoga/config/Config.h b/packages/react-native/ReactCommon/yoga/yoga/config/Config.h index 7bcffd1484c9..2f829fbdbc3a 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/config/Config.h +++ b/packages/react-native/ReactCommon/yoga/yoga/config/Config.h @@ -76,7 +76,7 @@ class YG_EXPORT Config : public ::YGConfig { uint32_t version_ = 0; ExperimentalFeatureSet experimentalFeatures_{}; - Errata errata_ = Errata::None; + Errata errata_ = Errata::MinSizeUndefinedInsteadOfAuto; float pointScaleFactor_ = 1.0f; void* context_ = nullptr; }; diff --git a/packages/react-native/ReactCommon/yoga/yoga/enums/Errata.h b/packages/react-native/ReactCommon/yoga/yoga/enums/Errata.h index 2f47a941751f..5f59ab16a4b3 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/enums/Errata.h +++ b/packages/react-native/ReactCommon/yoga/yoga/enums/Errata.h @@ -20,6 +20,7 @@ enum class Errata : uint32_t { StretchFlexBasis = YGErrataStretchFlexBasis, AbsolutePositionWithoutInsetsExcludesPadding = YGErrataAbsolutePositionWithoutInsetsExcludesPadding, AbsolutePercentAgainstInnerSize = YGErrataAbsolutePercentAgainstInnerSize, + MinSizeUndefinedInsteadOfAuto = YGErrataMinSizeUndefinedInsteadOfAuto, All = YGErrataAll, Classic = YGErrataClassic, }; diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h b/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h index 833dc927b296..24d353f50110 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h +++ b/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h @@ -27,6 +27,14 @@ struct LayoutResults { uint32_t computedFlexBasisGeneration = 0; FloatOptional computedFlexBasis = {}; + // Per-flex-item floor along the main axis derived from CSS Flexbox §4.5 + // automatic minimum sizing. Set by `resolveFlexibleLength` when the parent's + // config does NOT carry the `MinSizeUndefinedInsteadOfAuto` errata and the + // item has no explicit main-axis `min-{width,height}`. Read by the + // shrink/bound machinery to keep items at least this large. `Undefined` + // means "no auto-min applies." + FloatOptional computedAutoMinMainSize = {}; + // Instead of recomputing the entire layout every single time, we cache some // information to break early when nothing changed uint32_t generationCount = 0; diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp index d04127733d3f..692d33d9c4a1 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp @@ -36,6 +36,9 @@ Node::Node(Node&& node) noexcept nodeType_(node.nodeType_), context_(node.context_), measureFunc_(node.measureFunc_), + minContentMeasureFunc_(node.minContentMeasureFunc_), + minContentWidth_(node.minContentWidth_), + minContentHeight_(node.minContentHeight_), baselineFunc_(node.baselineFunc_), dirtiedFunc_(node.dirtiedFunc_), style_(std::move(node.style_)), @@ -79,6 +82,35 @@ YGSize Node::measure( return size; } +YGSize Node::measureMinContent( + float availableWidth, + MeasureMode widthMode, + float availableHeight, + MeasureMode heightMode) { + auto size = minContentMeasureFunc_( + this, + availableWidth, + unscopedEnum(widthMode), + availableHeight, + unscopedEnum(heightMode)); + + if (yoga::isUndefined(size.height) || size.height < 0 || + yoga::isUndefined(size.width) || size.width < 0) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + yoga::log( + this, + LogLevel::Warn, + "Min-content measure function returned an invalid dimension to Yoga: [width=%f, height=%f]", + size.width, + size.height); + size = { + .width = maxOrDefined(0.0f, size.width), + .height = maxOrDefined(0.0f, size.height)}; + } + + return size; +} + float Node::baseline(float width, float height) const { return baselineFunc_(this, width, height); } diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.h b/packages/react-native/ReactCommon/yoga/yoga/node/Node.h index d22c4c1ef040..74fd2c20d42e 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.h +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.h @@ -73,6 +73,24 @@ class YG_EXPORT Node : public ::YGNode { float availableHeight, MeasureMode heightMode); + bool hasMinContentMeasureFunc() const noexcept { + return minContentMeasureFunc_ != nullptr; + } + + YGSize measureMinContent( + float availableWidth, + MeasureMode widthMode, + float availableHeight, + MeasureMode heightMode); + + FloatOptional getMinContentWidth() const noexcept { + return minContentWidth_; + } + + FloatOptional getMinContentHeight() const noexcept { + return minContentHeight_; + } + bool hasBaselineFunc() const noexcept { return baselineFunc_ != nullptr; } @@ -220,6 +238,18 @@ class YG_EXPORT Node : public ::YGNode { void setMeasureFunc(YGMeasureFunc measureFunc); + void setMinContentMeasureFunc(YGMinContentMeasureFunc minContentMeasureFunc) { + minContentMeasureFunc_ = minContentMeasureFunc; + } + + void setMinContentWidth(FloatOptional minContentWidth) noexcept { + minContentWidth_ = minContentWidth; + } + + void setMinContentHeight(FloatOptional minContentHeight) noexcept { + minContentHeight_ = minContentHeight; + } + void setBaselineFunc(YGBaselineFunc baseLineFunc) { baselineFunc_ = baseLineFunc; } @@ -315,6 +345,9 @@ class YG_EXPORT Node : public ::YGNode { NodeType nodeType_ : bitCount() = NodeType::Default; void* context_ = nullptr; YGMeasureFunc measureFunc_ = nullptr; + YGMinContentMeasureFunc minContentMeasureFunc_ = nullptr; + FloatOptional minContentWidth_{}; + FloatOptional minContentHeight_{}; YGBaselineFunc baselineFunc_ = nullptr; YGDirtiedFunc dirtiedFunc_ = nullptr; Style style_; diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index c976861c56b4..98dfa7b6eab0 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -294,6 +294,17 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, + enableFlexboxAutoMinSizeInStrictMode: { + defaultValue: false, + metadata: { + dateAdded: '2026-06-02', + description: + '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.', + expectedReleaseValue: true, + purpose: 'experimentation', + }, + ossReleaseStage: 'experimental', + }, enableFontScaleChangesUpdatingLayout: { defaultValue: true, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 5e77c1dbd663..cf32422016e7 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<1f78266600508274a623ff1032fa7124>> + * @generated SignedSource<<77b178e216aa86a309f46cbf661d9122>> * @flow strict * @noformat */ @@ -70,6 +70,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{ enableExclusivePropsUpdateAndroid: Getter, enableFabricCommitBranching: Getter, enableFabricLogs: Getter, + enableFlexboxAutoMinSizeInStrictMode: Getter, enableFontScaleChangesUpdatingLayout: Getter, enableIOSTextBaselineOffsetPerLine: Getter, enableIOSViewClipToPaddingBox: Getter, @@ -292,6 +293,10 @@ export const enableFabricCommitBranching: Getter = createNativeFlagGett * This feature flag enables logs for Fabric. */ export const enableFabricLogs: Getter = createNativeFlagGetter('enableFabricLogs', false); +/** + * 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. + */ +export const enableFlexboxAutoMinSizeInStrictMode: Getter = createNativeFlagGetter('enableFlexboxAutoMinSizeInStrictMode', false); /** * Enables font scale changes updating layout for measurable nodes. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index a72acea15a4b..4955db9dab59 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<869507719729d76403ed47be393cc120>> + * @generated SignedSource<<98e126bdc863ff4848174f4bd55a5c5b>> * @flow strict * @noformat */ @@ -48,6 +48,7 @@ export interface Spec extends TurboModule { +enableExclusivePropsUpdateAndroid?: () => boolean; +enableFabricCommitBranching?: () => boolean; +enableFabricLogs?: () => boolean; + +enableFlexboxAutoMinSizeInStrictMode?: () => boolean; +enableFontScaleChangesUpdatingLayout?: () => boolean; +enableIOSTextBaselineOffsetPerLine?: () => boolean; +enableIOSViewClipToPaddingBox?: () => boolean; diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api index 5bbaffe84b69..f16ca8aab075 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api @@ -12960,6 +12960,7 @@ class facebook::yoga::Node : public YGNode { public Node(facebook::yoga::Node&& node) noexcept; public YGDirtiedFunc getDirtiedFunc() const; public YGSize measure(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); + public YGSize measureMinContent(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); public bool alwaysFormsContainingBlock() const; public bool getHasNewLayout() const; public bool hasBaselineFunc() const noexcept; @@ -12967,6 +12968,7 @@ class facebook::yoga::Node : public YGNode { public bool hasDefiniteLength(facebook::yoga::Dimension dimension, float ownerSize); public bool hasErrata(facebook::yoga::Errata errata) const; public bool hasMeasureFunc() const noexcept; + public bool hasMinContentMeasureFunc() const noexcept; public bool isDirty() const; public bool isLayoutDimensionDefined(facebook::yoga::FlexDirection axis); public bool isNodeFlexible(); @@ -12977,6 +12979,8 @@ class facebook::yoga::Node : public YGNode { public const facebook::yoga::Style& style() const; public const std::vector& getChildren() const; public facebook::yoga::Direction resolveDirection(facebook::yoga::Direction ownerDirection); + public facebook::yoga::FloatOptional getMinContentHeight() const noexcept; + public facebook::yoga::FloatOptional getMinContentWidth() const noexcept; public facebook::yoga::FloatOptional getResolvedDimension(facebook::yoga::Direction direction, facebook::yoga::Dimension dimension, float referenceLength, float ownerWidth) const; public facebook::yoga::FloatOptional resolveFlexBasis(facebook::yoga::Direction direction, facebook::yoga::FlexDirection flexDirection, float referenceLength, float ownerWidth) const; public facebook::yoga::LayoutResults& getLayout(); @@ -13030,6 +13034,9 @@ class facebook::yoga::Node : public YGNode { public void setLayoutPosition(float position, facebook::yoga::PhysicalEdge edge); public void setLineIndex(size_t lineIndex); public void setMeasureFunc(YGMeasureFunc measureFunc); + public void setMinContentHeight(facebook::yoga::FloatOptional minContentHeight) noexcept; + public void setMinContentMeasureFunc(YGMinContentMeasureFunc minContentMeasureFunc); + public void setMinContentWidth(facebook::yoga::FloatOptional minContentWidth) noexcept; public void setNodeType(facebook::yoga::NodeType nodeType); public void setOwner(facebook::yoga::Node* owner); public void setPosition(facebook::yoga::Direction direction, float ownerWidth, float ownerHeight); @@ -13279,6 +13286,7 @@ enum facebook::yoga::Errata : uint32_t { AbsolutePositionWithoutInsetsExcludesPadding, All, Classic, + MinSizeUndefinedInsteadOfAuto, None, StretchFlexBasis, } @@ -13538,6 +13546,7 @@ struct facebook::yoga::LayoutResults { public facebook::yoga::CachedMeasurement cachedLayout; public facebook::yoga::Direction direction() const; public facebook::yoga::Direction lastOwnerDirection; + public facebook::yoga::FloatOptional computedAutoMinMainSize; public facebook::yoga::FloatOptional computedFlexBasis; public float border(facebook::yoga::PhysicalEdge physicalEdge) const; public float dimension(facebook::yoga::Dimension axis) const; diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api index f41430b9759f..d4424d8efd10 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api @@ -12598,6 +12598,7 @@ class facebook::yoga::Node : public YGNode { public Node(facebook::yoga::Node&& node) noexcept; public YGDirtiedFunc getDirtiedFunc() const; public YGSize measure(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); + public YGSize measureMinContent(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); public bool alwaysFormsContainingBlock() const; public bool getHasNewLayout() const; public bool hasBaselineFunc() const noexcept; @@ -12605,6 +12606,7 @@ class facebook::yoga::Node : public YGNode { public bool hasDefiniteLength(facebook::yoga::Dimension dimension, float ownerSize); public bool hasErrata(facebook::yoga::Errata errata) const; public bool hasMeasureFunc() const noexcept; + public bool hasMinContentMeasureFunc() const noexcept; public bool isDirty() const; public bool isLayoutDimensionDefined(facebook::yoga::FlexDirection axis); public bool isNodeFlexible(); @@ -12615,6 +12617,8 @@ class facebook::yoga::Node : public YGNode { public const facebook::yoga::Style& style() const; public const std::vector& getChildren() const; public facebook::yoga::Direction resolveDirection(facebook::yoga::Direction ownerDirection); + public facebook::yoga::FloatOptional getMinContentHeight() const noexcept; + public facebook::yoga::FloatOptional getMinContentWidth() const noexcept; public facebook::yoga::FloatOptional getResolvedDimension(facebook::yoga::Direction direction, facebook::yoga::Dimension dimension, float referenceLength, float ownerWidth) const; public facebook::yoga::FloatOptional resolveFlexBasis(facebook::yoga::Direction direction, facebook::yoga::FlexDirection flexDirection, float referenceLength, float ownerWidth) const; public facebook::yoga::LayoutResults& getLayout(); @@ -12668,6 +12672,9 @@ class facebook::yoga::Node : public YGNode { public void setLayoutPosition(float position, facebook::yoga::PhysicalEdge edge); public void setLineIndex(size_t lineIndex); public void setMeasureFunc(YGMeasureFunc measureFunc); + public void setMinContentHeight(facebook::yoga::FloatOptional minContentHeight) noexcept; + public void setMinContentMeasureFunc(YGMinContentMeasureFunc minContentMeasureFunc); + public void setMinContentWidth(facebook::yoga::FloatOptional minContentWidth) noexcept; public void setNodeType(facebook::yoga::NodeType nodeType); public void setOwner(facebook::yoga::Node* owner); public void setPosition(facebook::yoga::Direction direction, float ownerWidth, float ownerHeight); @@ -12917,6 +12924,7 @@ enum facebook::yoga::Errata : uint32_t { AbsolutePositionWithoutInsetsExcludesPadding, All, Classic, + MinSizeUndefinedInsteadOfAuto, None, StretchFlexBasis, } @@ -13176,6 +13184,7 @@ struct facebook::yoga::LayoutResults { public facebook::yoga::CachedMeasurement cachedLayout; public facebook::yoga::Direction direction() const; public facebook::yoga::Direction lastOwnerDirection; + public facebook::yoga::FloatOptional computedAutoMinMainSize; public facebook::yoga::FloatOptional computedFlexBasis; public float border(facebook::yoga::PhysicalEdge physicalEdge) const; public float dimension(facebook::yoga::Dimension axis) const; diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api index b70b7f31f3e5..913210b87516 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api @@ -12813,6 +12813,7 @@ class facebook::yoga::Node : public YGNode { public Node(facebook::yoga::Node&& node) noexcept; public YGDirtiedFunc getDirtiedFunc() const; public YGSize measure(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); + public YGSize measureMinContent(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); public bool alwaysFormsContainingBlock() const; public bool getHasNewLayout() const; public bool hasBaselineFunc() const noexcept; @@ -12820,6 +12821,7 @@ class facebook::yoga::Node : public YGNode { public bool hasDefiniteLength(facebook::yoga::Dimension dimension, float ownerSize); public bool hasErrata(facebook::yoga::Errata errata) const; public bool hasMeasureFunc() const noexcept; + public bool hasMinContentMeasureFunc() const noexcept; public bool isDirty() const; public bool isLayoutDimensionDefined(facebook::yoga::FlexDirection axis); public bool isNodeFlexible(); @@ -12830,6 +12832,8 @@ class facebook::yoga::Node : public YGNode { public const facebook::yoga::Style& style() const; public const std::vector& getChildren() const; public facebook::yoga::Direction resolveDirection(facebook::yoga::Direction ownerDirection); + public facebook::yoga::FloatOptional getMinContentHeight() const noexcept; + public facebook::yoga::FloatOptional getMinContentWidth() const noexcept; public facebook::yoga::FloatOptional getResolvedDimension(facebook::yoga::Direction direction, facebook::yoga::Dimension dimension, float referenceLength, float ownerWidth) const; public facebook::yoga::FloatOptional resolveFlexBasis(facebook::yoga::Direction direction, facebook::yoga::FlexDirection flexDirection, float referenceLength, float ownerWidth) const; public facebook::yoga::LayoutResults& getLayout(); @@ -12883,6 +12887,9 @@ class facebook::yoga::Node : public YGNode { public void setLayoutPosition(float position, facebook::yoga::PhysicalEdge edge); public void setLineIndex(size_t lineIndex); public void setMeasureFunc(YGMeasureFunc measureFunc); + public void setMinContentHeight(facebook::yoga::FloatOptional minContentHeight) noexcept; + public void setMinContentMeasureFunc(YGMinContentMeasureFunc minContentMeasureFunc); + public void setMinContentWidth(facebook::yoga::FloatOptional minContentWidth) noexcept; public void setNodeType(facebook::yoga::NodeType nodeType); public void setOwner(facebook::yoga::Node* owner); public void setPosition(facebook::yoga::Direction direction, float ownerWidth, float ownerHeight); @@ -13132,6 +13139,7 @@ enum facebook::yoga::Errata : uint32_t { AbsolutePositionWithoutInsetsExcludesPadding, All, Classic, + MinSizeUndefinedInsteadOfAuto, None, StretchFlexBasis, } @@ -13391,6 +13399,7 @@ struct facebook::yoga::LayoutResults { public facebook::yoga::CachedMeasurement cachedLayout; public facebook::yoga::Direction direction() const; public facebook::yoga::Direction lastOwnerDirection; + public facebook::yoga::FloatOptional computedAutoMinMainSize; public facebook::yoga::FloatOptional computedFlexBasis; public float border(facebook::yoga::PhysicalEdge physicalEdge) const; public float dimension(facebook::yoga::Dimension axis) const; diff --git a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api index b687cb8ed556..4efd9d2a862a 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api @@ -14798,6 +14798,7 @@ class facebook::yoga::Node : public YGNode { public Node(facebook::yoga::Node&& node) noexcept; public YGDirtiedFunc getDirtiedFunc() const; public YGSize measure(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); + public YGSize measureMinContent(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); public bool alwaysFormsContainingBlock() const; public bool getHasNewLayout() const; public bool hasBaselineFunc() const noexcept; @@ -14805,6 +14806,7 @@ class facebook::yoga::Node : public YGNode { public bool hasDefiniteLength(facebook::yoga::Dimension dimension, float ownerSize); public bool hasErrata(facebook::yoga::Errata errata) const; public bool hasMeasureFunc() const noexcept; + public bool hasMinContentMeasureFunc() const noexcept; public bool isDirty() const; public bool isLayoutDimensionDefined(facebook::yoga::FlexDirection axis); public bool isNodeFlexible(); @@ -14815,6 +14817,8 @@ class facebook::yoga::Node : public YGNode { public const facebook::yoga::Style& style() const; public const std::vector& getChildren() const; public facebook::yoga::Direction resolveDirection(facebook::yoga::Direction ownerDirection); + public facebook::yoga::FloatOptional getMinContentHeight() const noexcept; + public facebook::yoga::FloatOptional getMinContentWidth() const noexcept; public facebook::yoga::FloatOptional getResolvedDimension(facebook::yoga::Direction direction, facebook::yoga::Dimension dimension, float referenceLength, float ownerWidth) const; public facebook::yoga::FloatOptional resolveFlexBasis(facebook::yoga::Direction direction, facebook::yoga::FlexDirection flexDirection, float referenceLength, float ownerWidth) const; public facebook::yoga::LayoutResults& getLayout(); @@ -14868,6 +14872,9 @@ class facebook::yoga::Node : public YGNode { public void setLayoutPosition(float position, facebook::yoga::PhysicalEdge edge); public void setLineIndex(size_t lineIndex); public void setMeasureFunc(YGMeasureFunc measureFunc); + public void setMinContentHeight(facebook::yoga::FloatOptional minContentHeight) noexcept; + public void setMinContentMeasureFunc(YGMinContentMeasureFunc minContentMeasureFunc); + public void setMinContentWidth(facebook::yoga::FloatOptional minContentWidth) noexcept; public void setNodeType(facebook::yoga::NodeType nodeType); public void setOwner(facebook::yoga::Node* owner); public void setPosition(facebook::yoga::Direction direction, float ownerWidth, float ownerHeight); @@ -15117,6 +15124,7 @@ enum facebook::yoga::Errata : uint32_t { AbsolutePositionWithoutInsetsExcludesPadding, All, Classic, + MinSizeUndefinedInsteadOfAuto, None, StretchFlexBasis, } @@ -15376,6 +15384,7 @@ struct facebook::yoga::LayoutResults { public facebook::yoga::CachedMeasurement cachedLayout; public facebook::yoga::Direction direction() const; public facebook::yoga::Direction lastOwnerDirection; + public facebook::yoga::FloatOptional computedAutoMinMainSize; public facebook::yoga::FloatOptional computedFlexBasis; public float border(facebook::yoga::PhysicalEdge physicalEdge) const; public float dimension(facebook::yoga::Dimension axis) const; diff --git a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api index c0dd7c1584c6..0ce9d19346d8 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api @@ -14497,6 +14497,7 @@ class facebook::yoga::Node : public YGNode { public Node(facebook::yoga::Node&& node) noexcept; public YGDirtiedFunc getDirtiedFunc() const; public YGSize measure(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); + public YGSize measureMinContent(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); public bool alwaysFormsContainingBlock() const; public bool getHasNewLayout() const; public bool hasBaselineFunc() const noexcept; @@ -14504,6 +14505,7 @@ class facebook::yoga::Node : public YGNode { public bool hasDefiniteLength(facebook::yoga::Dimension dimension, float ownerSize); public bool hasErrata(facebook::yoga::Errata errata) const; public bool hasMeasureFunc() const noexcept; + public bool hasMinContentMeasureFunc() const noexcept; public bool isDirty() const; public bool isLayoutDimensionDefined(facebook::yoga::FlexDirection axis); public bool isNodeFlexible(); @@ -14514,6 +14516,8 @@ class facebook::yoga::Node : public YGNode { public const facebook::yoga::Style& style() const; public const std::vector& getChildren() const; public facebook::yoga::Direction resolveDirection(facebook::yoga::Direction ownerDirection); + public facebook::yoga::FloatOptional getMinContentHeight() const noexcept; + public facebook::yoga::FloatOptional getMinContentWidth() const noexcept; public facebook::yoga::FloatOptional getResolvedDimension(facebook::yoga::Direction direction, facebook::yoga::Dimension dimension, float referenceLength, float ownerWidth) const; public facebook::yoga::FloatOptional resolveFlexBasis(facebook::yoga::Direction direction, facebook::yoga::FlexDirection flexDirection, float referenceLength, float ownerWidth) const; public facebook::yoga::LayoutResults& getLayout(); @@ -14567,6 +14571,9 @@ class facebook::yoga::Node : public YGNode { public void setLayoutPosition(float position, facebook::yoga::PhysicalEdge edge); public void setLineIndex(size_t lineIndex); public void setMeasureFunc(YGMeasureFunc measureFunc); + public void setMinContentHeight(facebook::yoga::FloatOptional minContentHeight) noexcept; + public void setMinContentMeasureFunc(YGMinContentMeasureFunc minContentMeasureFunc); + public void setMinContentWidth(facebook::yoga::FloatOptional minContentWidth) noexcept; public void setNodeType(facebook::yoga::NodeType nodeType); public void setOwner(facebook::yoga::Node* owner); public void setPosition(facebook::yoga::Direction direction, float ownerWidth, float ownerHeight); @@ -14816,6 +14823,7 @@ enum facebook::yoga::Errata : uint32_t { AbsolutePositionWithoutInsetsExcludesPadding, All, Classic, + MinSizeUndefinedInsteadOfAuto, None, StretchFlexBasis, } @@ -15075,6 +15083,7 @@ struct facebook::yoga::LayoutResults { public facebook::yoga::CachedMeasurement cachedLayout; public facebook::yoga::Direction direction() const; public facebook::yoga::Direction lastOwnerDirection; + public facebook::yoga::FloatOptional computedAutoMinMainSize; public facebook::yoga::FloatOptional computedFlexBasis; public float border(facebook::yoga::PhysicalEdge physicalEdge) const; public float dimension(facebook::yoga::Dimension axis) const; diff --git a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api index 1a2f6c30e468..d89406539fbc 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api @@ -14661,6 +14661,7 @@ class facebook::yoga::Node : public YGNode { public Node(facebook::yoga::Node&& node) noexcept; public YGDirtiedFunc getDirtiedFunc() const; public YGSize measure(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); + public YGSize measureMinContent(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); public bool alwaysFormsContainingBlock() const; public bool getHasNewLayout() const; public bool hasBaselineFunc() const noexcept; @@ -14668,6 +14669,7 @@ class facebook::yoga::Node : public YGNode { public bool hasDefiniteLength(facebook::yoga::Dimension dimension, float ownerSize); public bool hasErrata(facebook::yoga::Errata errata) const; public bool hasMeasureFunc() const noexcept; + public bool hasMinContentMeasureFunc() const noexcept; public bool isDirty() const; public bool isLayoutDimensionDefined(facebook::yoga::FlexDirection axis); public bool isNodeFlexible(); @@ -14678,6 +14680,8 @@ class facebook::yoga::Node : public YGNode { public const facebook::yoga::Style& style() const; public const std::vector& getChildren() const; public facebook::yoga::Direction resolveDirection(facebook::yoga::Direction ownerDirection); + public facebook::yoga::FloatOptional getMinContentHeight() const noexcept; + public facebook::yoga::FloatOptional getMinContentWidth() const noexcept; public facebook::yoga::FloatOptional getResolvedDimension(facebook::yoga::Direction direction, facebook::yoga::Dimension dimension, float referenceLength, float ownerWidth) const; public facebook::yoga::FloatOptional resolveFlexBasis(facebook::yoga::Direction direction, facebook::yoga::FlexDirection flexDirection, float referenceLength, float ownerWidth) const; public facebook::yoga::LayoutResults& getLayout(); @@ -14731,6 +14735,9 @@ class facebook::yoga::Node : public YGNode { public void setLayoutPosition(float position, facebook::yoga::PhysicalEdge edge); public void setLineIndex(size_t lineIndex); public void setMeasureFunc(YGMeasureFunc measureFunc); + public void setMinContentHeight(facebook::yoga::FloatOptional minContentHeight) noexcept; + public void setMinContentMeasureFunc(YGMinContentMeasureFunc minContentMeasureFunc); + public void setMinContentWidth(facebook::yoga::FloatOptional minContentWidth) noexcept; public void setNodeType(facebook::yoga::NodeType nodeType); public void setOwner(facebook::yoga::Node* owner); public void setPosition(facebook::yoga::Direction direction, float ownerWidth, float ownerHeight); @@ -14980,6 +14987,7 @@ enum facebook::yoga::Errata : uint32_t { AbsolutePositionWithoutInsetsExcludesPadding, All, Classic, + MinSizeUndefinedInsteadOfAuto, None, StretchFlexBasis, } @@ -15239,6 +15247,7 @@ struct facebook::yoga::LayoutResults { public facebook::yoga::CachedMeasurement cachedLayout; public facebook::yoga::Direction direction() const; public facebook::yoga::Direction lastOwnerDirection; + public facebook::yoga::FloatOptional computedAutoMinMainSize; public facebook::yoga::FloatOptional computedFlexBasis; public float border(facebook::yoga::PhysicalEdge physicalEdge) const; public float dimension(facebook::yoga::Dimension axis) const; diff --git a/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api index 2e43b23d2fc1..7a71384483aa 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api @@ -9925,6 +9925,7 @@ class facebook::yoga::Node : public YGNode { public Node(facebook::yoga::Node&& node) noexcept; public YGDirtiedFunc getDirtiedFunc() const; public YGSize measure(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); + public YGSize measureMinContent(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); public bool alwaysFormsContainingBlock() const; public bool getHasNewLayout() const; public bool hasBaselineFunc() const noexcept; @@ -9932,6 +9933,7 @@ class facebook::yoga::Node : public YGNode { public bool hasDefiniteLength(facebook::yoga::Dimension dimension, float ownerSize); public bool hasErrata(facebook::yoga::Errata errata) const; public bool hasMeasureFunc() const noexcept; + public bool hasMinContentMeasureFunc() const noexcept; public bool isDirty() const; public bool isLayoutDimensionDefined(facebook::yoga::FlexDirection axis); public bool isNodeFlexible(); @@ -9942,6 +9944,8 @@ class facebook::yoga::Node : public YGNode { public const facebook::yoga::Style& style() const; public const std::vector& getChildren() const; public facebook::yoga::Direction resolveDirection(facebook::yoga::Direction ownerDirection); + public facebook::yoga::FloatOptional getMinContentHeight() const noexcept; + public facebook::yoga::FloatOptional getMinContentWidth() const noexcept; public facebook::yoga::FloatOptional getResolvedDimension(facebook::yoga::Direction direction, facebook::yoga::Dimension dimension, float referenceLength, float ownerWidth) const; public facebook::yoga::FloatOptional resolveFlexBasis(facebook::yoga::Direction direction, facebook::yoga::FlexDirection flexDirection, float referenceLength, float ownerWidth) const; public facebook::yoga::LayoutResults& getLayout(); @@ -9995,6 +9999,9 @@ class facebook::yoga::Node : public YGNode { public void setLayoutPosition(float position, facebook::yoga::PhysicalEdge edge); public void setLineIndex(size_t lineIndex); public void setMeasureFunc(YGMeasureFunc measureFunc); + public void setMinContentHeight(facebook::yoga::FloatOptional minContentHeight) noexcept; + public void setMinContentMeasureFunc(YGMinContentMeasureFunc minContentMeasureFunc); + public void setMinContentWidth(facebook::yoga::FloatOptional minContentWidth) noexcept; public void setNodeType(facebook::yoga::NodeType nodeType); public void setOwner(facebook::yoga::Node* owner); public void setPosition(facebook::yoga::Direction direction, float ownerWidth, float ownerHeight); @@ -10244,6 +10251,7 @@ enum facebook::yoga::Errata : uint32_t { AbsolutePositionWithoutInsetsExcludesPadding, All, Classic, + MinSizeUndefinedInsteadOfAuto, None, StretchFlexBasis, } @@ -10503,6 +10511,7 @@ struct facebook::yoga::LayoutResults { public facebook::yoga::CachedMeasurement cachedLayout; public facebook::yoga::Direction direction() const; public facebook::yoga::Direction lastOwnerDirection; + public facebook::yoga::FloatOptional computedAutoMinMainSize; public facebook::yoga::FloatOptional computedFlexBasis; public float border(facebook::yoga::PhysicalEdge physicalEdge) const; public float dimension(facebook::yoga::Dimension axis) const; diff --git a/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api index e9700e2725df..3d680418ec12 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api @@ -9765,6 +9765,7 @@ class facebook::yoga::Node : public YGNode { public Node(facebook::yoga::Node&& node) noexcept; public YGDirtiedFunc getDirtiedFunc() const; public YGSize measure(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); + public YGSize measureMinContent(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); public bool alwaysFormsContainingBlock() const; public bool getHasNewLayout() const; public bool hasBaselineFunc() const noexcept; @@ -9772,6 +9773,7 @@ class facebook::yoga::Node : public YGNode { public bool hasDefiniteLength(facebook::yoga::Dimension dimension, float ownerSize); public bool hasErrata(facebook::yoga::Errata errata) const; public bool hasMeasureFunc() const noexcept; + public bool hasMinContentMeasureFunc() const noexcept; public bool isDirty() const; public bool isLayoutDimensionDefined(facebook::yoga::FlexDirection axis); public bool isNodeFlexible(); @@ -9782,6 +9784,8 @@ class facebook::yoga::Node : public YGNode { public const facebook::yoga::Style& style() const; public const std::vector& getChildren() const; public facebook::yoga::Direction resolveDirection(facebook::yoga::Direction ownerDirection); + public facebook::yoga::FloatOptional getMinContentHeight() const noexcept; + public facebook::yoga::FloatOptional getMinContentWidth() const noexcept; public facebook::yoga::FloatOptional getResolvedDimension(facebook::yoga::Direction direction, facebook::yoga::Dimension dimension, float referenceLength, float ownerWidth) const; public facebook::yoga::FloatOptional resolveFlexBasis(facebook::yoga::Direction direction, facebook::yoga::FlexDirection flexDirection, float referenceLength, float ownerWidth) const; public facebook::yoga::LayoutResults& getLayout(); @@ -9835,6 +9839,9 @@ class facebook::yoga::Node : public YGNode { public void setLayoutPosition(float position, facebook::yoga::PhysicalEdge edge); public void setLineIndex(size_t lineIndex); public void setMeasureFunc(YGMeasureFunc measureFunc); + public void setMinContentHeight(facebook::yoga::FloatOptional minContentHeight) noexcept; + public void setMinContentMeasureFunc(YGMinContentMeasureFunc minContentMeasureFunc); + public void setMinContentWidth(facebook::yoga::FloatOptional minContentWidth) noexcept; public void setNodeType(facebook::yoga::NodeType nodeType); public void setOwner(facebook::yoga::Node* owner); public void setPosition(facebook::yoga::Direction direction, float ownerWidth, float ownerHeight); @@ -10084,6 +10091,7 @@ enum facebook::yoga::Errata : uint32_t { AbsolutePositionWithoutInsetsExcludesPadding, All, Classic, + MinSizeUndefinedInsteadOfAuto, None, StretchFlexBasis, } @@ -10343,6 +10351,7 @@ struct facebook::yoga::LayoutResults { public facebook::yoga::CachedMeasurement cachedLayout; public facebook::yoga::Direction direction() const; public facebook::yoga::Direction lastOwnerDirection; + public facebook::yoga::FloatOptional computedAutoMinMainSize; public facebook::yoga::FloatOptional computedFlexBasis; public float border(facebook::yoga::PhysicalEdge physicalEdge) const; public float dimension(facebook::yoga::Dimension axis) const; diff --git a/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api index bf1acdc6eb1a..5905c2c857ad 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api @@ -9916,6 +9916,7 @@ class facebook::yoga::Node : public YGNode { public Node(facebook::yoga::Node&& node) noexcept; public YGDirtiedFunc getDirtiedFunc() const; public YGSize measure(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); + public YGSize measureMinContent(float availableWidth, facebook::yoga::MeasureMode widthMode, float availableHeight, facebook::yoga::MeasureMode heightMode); public bool alwaysFormsContainingBlock() const; public bool getHasNewLayout() const; public bool hasBaselineFunc() const noexcept; @@ -9923,6 +9924,7 @@ class facebook::yoga::Node : public YGNode { public bool hasDefiniteLength(facebook::yoga::Dimension dimension, float ownerSize); public bool hasErrata(facebook::yoga::Errata errata) const; public bool hasMeasureFunc() const noexcept; + public bool hasMinContentMeasureFunc() const noexcept; public bool isDirty() const; public bool isLayoutDimensionDefined(facebook::yoga::FlexDirection axis); public bool isNodeFlexible(); @@ -9933,6 +9935,8 @@ class facebook::yoga::Node : public YGNode { public const facebook::yoga::Style& style() const; public const std::vector& getChildren() const; public facebook::yoga::Direction resolveDirection(facebook::yoga::Direction ownerDirection); + public facebook::yoga::FloatOptional getMinContentHeight() const noexcept; + public facebook::yoga::FloatOptional getMinContentWidth() const noexcept; public facebook::yoga::FloatOptional getResolvedDimension(facebook::yoga::Direction direction, facebook::yoga::Dimension dimension, float referenceLength, float ownerWidth) const; public facebook::yoga::FloatOptional resolveFlexBasis(facebook::yoga::Direction direction, facebook::yoga::FlexDirection flexDirection, float referenceLength, float ownerWidth) const; public facebook::yoga::LayoutResults& getLayout(); @@ -9986,6 +9990,9 @@ class facebook::yoga::Node : public YGNode { public void setLayoutPosition(float position, facebook::yoga::PhysicalEdge edge); public void setLineIndex(size_t lineIndex); public void setMeasureFunc(YGMeasureFunc measureFunc); + public void setMinContentHeight(facebook::yoga::FloatOptional minContentHeight) noexcept; + public void setMinContentMeasureFunc(YGMinContentMeasureFunc minContentMeasureFunc); + public void setMinContentWidth(facebook::yoga::FloatOptional minContentWidth) noexcept; public void setNodeType(facebook::yoga::NodeType nodeType); public void setOwner(facebook::yoga::Node* owner); public void setPosition(facebook::yoga::Direction direction, float ownerWidth, float ownerHeight); @@ -10235,6 +10242,7 @@ enum facebook::yoga::Errata : uint32_t { AbsolutePositionWithoutInsetsExcludesPadding, All, Classic, + MinSizeUndefinedInsteadOfAuto, None, StretchFlexBasis, } @@ -10494,6 +10502,7 @@ struct facebook::yoga::LayoutResults { public facebook::yoga::CachedMeasurement cachedLayout; public facebook::yoga::Direction direction() const; public facebook::yoga::Direction lastOwnerDirection; + public facebook::yoga::FloatOptional computedAutoMinMainSize; public facebook::yoga::FloatOptional computedFlexBasis; public float border(facebook::yoga::PhysicalEdge physicalEdge) const; public float dimension(facebook::yoga::Dimension axis) const;