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 eb07acd5df2386..abfbf15920c3bb 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<<6b632ac7553ae149fa42a67efde5acfa>> + * @generated SignedSource<> */ /** @@ -468,6 +468,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun useTurboModules(): Boolean = accessor.useTurboModules() + /** + * Outset the culling context frame with the provided ratio. The culling context frame size will be outset by width * ratio on the left and right, and height * ratio on the top and bottom. + */ + @JvmStatic + public fun viewCullingOutsetRatio(): Double = accessor.viewCullingOutsetRatio() + /** * Sets a hysteresis window for transition between prerender and hidden modes. */ 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 91a6990138d11f..65796a5915ee1d 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<> */ /** @@ -93,6 +93,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var useShadowNodeStateOnCloneCache: Boolean? = null private var useTurboModuleInteropCache: Boolean? = null private var useTurboModulesCache: Boolean? = null + private var viewCullingOutsetRatioCache: Double? = null private var virtualViewHysteresisRatioCache: Double? = null private var virtualViewPrerenderRatioCache: Double? = null @@ -753,6 +754,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun viewCullingOutsetRatio(): Double { + var cached = viewCullingOutsetRatioCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.viewCullingOutsetRatio() + viewCullingOutsetRatioCache = cached + } + return cached + } + override fun virtualViewHysteresisRatio(): Double { var cached = virtualViewHysteresisRatioCache 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 98d05d177e36dd..339184e78d6825 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<<26dce1945df5641ab84cbca9eaf2b10f>> + * @generated SignedSource<<3254fef626b10ef21d8d9ee1bdbb1880>> */ /** @@ -174,6 +174,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun useTurboModules(): Boolean + @DoNotStrip @JvmStatic public external fun viewCullingOutsetRatio(): Double + @DoNotStrip @JvmStatic public external fun virtualViewHysteresisRatio(): Double @DoNotStrip @JvmStatic public external fun virtualViewPrerenderRatio(): Double 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 d08bd81b443420..21f217aa1a0cf7 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<<11051ece1b61fd4bf4ca003a3b7fc4f9>> + * @generated SignedSource<<9f7eb1bb5e24fd8ee87accf60209cce3>> */ /** @@ -169,6 +169,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun useTurboModules(): Boolean = false + override fun viewCullingOutsetRatio(): Double = 0.0 + override fun virtualViewHysteresisRatio(): Double = 0.0 override fun virtualViewPrerenderRatio(): Double = 5.0 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 eb575e5159bc20..b3a0d648332bf5 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<<66fa583c37021750123a483ab0ccb030>> + * @generated SignedSource<<9e6e04ca37edd1ad9265b74e251ff4de>> */ /** @@ -97,6 +97,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var useShadowNodeStateOnCloneCache: Boolean? = null private var useTurboModuleInteropCache: Boolean? = null private var useTurboModulesCache: Boolean? = null + private var viewCullingOutsetRatioCache: Double? = null private var virtualViewHysteresisRatioCache: Double? = null private var virtualViewPrerenderRatioCache: Double? = null @@ -830,6 +831,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } + override fun viewCullingOutsetRatio(): Double { + var cached = viewCullingOutsetRatioCache + if (cached == null) { + cached = currentProvider.viewCullingOutsetRatio() + accessedFeatureFlags.add("viewCullingOutsetRatio") + viewCullingOutsetRatioCache = cached + } + return cached + } + override fun virtualViewHysteresisRatio(): Double { var cached = virtualViewHysteresisRatioCache if (cached == null) { 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 06e0872a916529..48c2b385d8c5df 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<<65e895433fc609bd7c2b5d7faa507f46>> */ /** @@ -169,6 +169,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun useTurboModules(): Boolean + @DoNotStrip public fun viewCullingOutsetRatio(): Double + @DoNotStrip public fun virtualViewHysteresisRatio(): Double @DoNotStrip public fun virtualViewPrerenderRatio(): Double 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 8170bb1fcd34c6..a7c8a8f100b105 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<<8e1821e9a153a4b725890cb4a7f262ee>> + * @generated SignedSource<<7a0a26494846d6b4881bea01beabb9d6>> */ /** @@ -477,6 +477,12 @@ class ReactNativeFeatureFlagsJavaProvider return method(javaProvider_); } + double viewCullingOutsetRatio() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("viewCullingOutsetRatio"); + return method(javaProvider_); + } + double virtualViewHysteresisRatio() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("virtualViewHysteresisRatio"); @@ -858,6 +864,11 @@ bool JReactNativeFeatureFlagsCxxInterop::useTurboModules( return ReactNativeFeatureFlags::useTurboModules(); } +double JReactNativeFeatureFlagsCxxInterop::viewCullingOutsetRatio( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::viewCullingOutsetRatio(); +} + double JReactNativeFeatureFlagsCxxInterop::virtualViewHysteresisRatio( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::virtualViewHysteresisRatio(); @@ -1118,6 +1129,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "useTurboModules", JReactNativeFeatureFlagsCxxInterop::useTurboModules), + makeNativeMethod( + "viewCullingOutsetRatio", + JReactNativeFeatureFlagsCxxInterop::viewCullingOutsetRatio), makeNativeMethod( "virtualViewHysteresisRatio", JReactNativeFeatureFlagsCxxInterop::virtualViewHysteresisRatio), 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 9670480569e55f..829762419d1732 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<<5be2ec52bda638a1eac837c402149b9f>> + * @generated SignedSource<> */ /** @@ -249,6 +249,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool useTurboModules( facebook::jni::alias_ref); + static double viewCullingOutsetRatio( + facebook::jni::alias_ref); + static double virtualViewHysteresisRatio( 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 4473f6df66a974..58db55d5ea4890 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<> */ /** @@ -318,6 +318,10 @@ bool ReactNativeFeatureFlags::useTurboModules() { return getAccessor().useTurboModules(); } +double ReactNativeFeatureFlags::viewCullingOutsetRatio() { + return getAccessor().viewCullingOutsetRatio(); +} + double ReactNativeFeatureFlags::virtualViewHysteresisRatio() { return getAccessor().virtualViewHysteresisRatio(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 2a8d97a0b9e6db..581252fd33e94f 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<<559a8be87c24238e70fceded8ac962a0>> */ /** @@ -404,6 +404,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool useTurboModules(); + /** + * Outset the culling context frame with the provided ratio. The culling context frame size will be outset by width * ratio on the left and right, and height * ratio on the top and bottom. + */ + RN_EXPORT static double viewCullingOutsetRatio(); + /** * Sets a hysteresis window for transition between prerender and hidden modes. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 8263cb0cf18306..1b108ff32fc673 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<<908baa1dbc4608be4b6407ffd670c066>> + * @generated SignedSource<<379732a049a8539a1cde814996ff4791>> */ /** @@ -1343,6 +1343,24 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() { return flagValue.value(); } +double ReactNativeFeatureFlagsAccessor::viewCullingOutsetRatio() { + auto flagValue = viewCullingOutsetRatio_.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(73, "viewCullingOutsetRatio"); + + flagValue = currentProvider_->viewCullingOutsetRatio(); + viewCullingOutsetRatio_ = flagValue; + } + + return flagValue.value(); +} + double ReactNativeFeatureFlagsAccessor::virtualViewHysteresisRatio() { auto flagValue = virtualViewHysteresisRatio_.load(); @@ -1352,7 +1370,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewHysteresisRatio() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(73, "virtualViewHysteresisRatio"); + markFlagAsAccessed(74, "virtualViewHysteresisRatio"); flagValue = currentProvider_->virtualViewHysteresisRatio(); virtualViewHysteresisRatio_ = flagValue; @@ -1370,7 +1388,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(74, "virtualViewPrerenderRatio"); + markFlagAsAccessed(75, "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 ede7746b6dc2b0..1dd1f037dd38af 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<> + * @generated SignedSource<> */ /** @@ -105,6 +105,7 @@ class ReactNativeFeatureFlagsAccessor { bool useShadowNodeStateOnClone(); bool useTurboModuleInterop(); bool useTurboModules(); + double viewCullingOutsetRatio(); double virtualViewHysteresisRatio(); double virtualViewPrerenderRatio(); @@ -118,7 +119,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 75> accessedFeatureFlags_; + std::array, 76> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> cdpInteractionMetricsEnabled_; @@ -193,6 +194,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> useShadowNodeStateOnClone_; std::atomic> useTurboModuleInterop_; std::atomic> useTurboModules_; + std::atomic> viewCullingOutsetRatio_; std::atomic> virtualViewHysteresisRatio_; std::atomic> virtualViewPrerenderRatio_; }; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 2b407600c30d4b..832f87dfcc7ad6 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<<5e6ee2118acc15edb9da813bb43978f3>> + * @generated SignedSource<> */ /** @@ -319,6 +319,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + double viewCullingOutsetRatio() override { + return 0.0; + } + double virtualViewHysteresisRatio() override { return 0.0; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index 126f07e6bd44c4..e02953c8afa28c 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<<00b4d80631374e0714c8aa9f65060220>> */ /** @@ -702,6 +702,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::useTurboModules(); } + double viewCullingOutsetRatio() override { + auto value = values_["viewCullingOutsetRatio"]; + if (!value.isNull()) { + return value.getDouble(); + } + + return ReactNativeFeatureFlagsDefaults::viewCullingOutsetRatio(); + } + double virtualViewHysteresisRatio() override { auto value = values_["virtualViewHysteresisRatio"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index b8c7ca07366f3b..de16d29eac4260 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<<4d141c52bc66225656194eeb8786f475>> + * @generated SignedSource<> */ /** @@ -98,6 +98,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool useShadowNodeStateOnClone() = 0; virtual bool useTurboModuleInterop() = 0; virtual bool useTurboModules() = 0; + virtual double viewCullingOutsetRatio() = 0; virtual double virtualViewHysteresisRatio() = 0; virtual double virtualViewPrerenderRatio() = 0; }; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 761cb2a2ea44da..beb3ea906aecd3 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<<27c7bc7a528da06ffe2bcea48211f6bd>> */ /** @@ -409,6 +409,11 @@ bool NativeReactNativeFeatureFlags::useTurboModules( return ReactNativeFeatureFlags::useTurboModules(); } +double NativeReactNativeFeatureFlags::viewCullingOutsetRatio( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::viewCullingOutsetRatio(); +} + double NativeReactNativeFeatureFlags::virtualViewHysteresisRatio( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::virtualViewHysteresisRatio(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 5a064f078cc5f8..59c6518e663620 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<<2dcd8b3add6f1fdc1bf378714deb41d7>> + * @generated SignedSource<<39140c882a6faa0403d3a59806c6bea5>> */ /** @@ -182,6 +182,8 @@ class NativeReactNativeFeatureFlags bool useTurboModules(jsi::Runtime& runtime); + double viewCullingOutsetRatio(jsi::Runtime& runtime); + double virtualViewHysteresisRatio(jsi::Runtime& runtime); double virtualViewPrerenderRatio(jsi::Runtime& runtime); diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/internal/CullingContext.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/internal/CullingContext.cpp index 8294edb254b157..609fc268e122d2 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/internal/CullingContext.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/internal/CullingContext.cpp @@ -32,6 +32,20 @@ CullingContext CullingContext::adjustCullingContextIfNeeded( /* includeTransform */ true); cullingContext.frame.size = scrollViewShadowNode->getLayoutMetrics().frame.size; + + // Enlarge the frame if an outset ratio is defined + auto outsetRatio = ReactNativeFeatureFlags::viewCullingOutsetRatio(); + if (outsetRatio > 0) { + auto xOutset = static_cast( + floor(cullingContext.frame.size.width * outsetRatio)); + auto yOutset = static_cast( + floor(cullingContext.frame.size.height * outsetRatio)); + cullingContext.frame.origin.x -= xOutset; + cullingContext.frame.origin.y -= yOutset; + cullingContext.frame.size.width += 2.0f * xOutset; + cullingContext.frame.size.height += 2.0f * yOutset; + } + cullingContext.transform = Transform::Identity(); if (layoutMetrics.layoutDirection == LayoutDirection::RightToLeft) { diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 31caaddc0a5fde..dbec8f146278a3 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -825,6 +825,17 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'canary', }, + viewCullingOutsetRatio: { + defaultValue: 0, + metadata: { + dateAdded: '2025-09-18', + description: + 'Outset the culling context frame with the provided ratio. The culling context frame size will be outset by width * ratio on the left and right, and height * ratio on the top and bottom.', + expectedReleaseValue: 0, + purpose: 'experimentation', + }, + ossReleaseStage: 'none', + }, virtualViewHysteresisRatio: { defaultValue: 0, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 8db688c63c65a9..6636a2647e2a62 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<<44c491f4078e75b8b77ee346ac802a70>> + * @generated SignedSource<> * @flow strict * @noformat */ @@ -123,6 +123,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{ useShadowNodeStateOnClone: Getter, useTurboModuleInterop: Getter, useTurboModules: Getter, + viewCullingOutsetRatio: Getter, virtualViewHysteresisRatio: Getter, virtualViewPrerenderRatio: Getter, }>; @@ -498,6 +499,10 @@ export const useTurboModuleInterop: Getter = createNativeFlagGetter('us * When enabled, NativeModules will be executed by using the TurboModule system */ export const useTurboModules: Getter = createNativeFlagGetter('useTurboModules', false); +/** + * Outset the culling context frame with the provided ratio. The culling context frame size will be outset by width * ratio on the left and right, and height * ratio on the top and bottom. + */ +export const viewCullingOutsetRatio: Getter = createNativeFlagGetter('viewCullingOutsetRatio', 0); /** * Sets a hysteresis window for transition between prerender and hidden modes. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 0a72c27c6a7570..659f86c042876f 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<<18ae10cff4e5611d4774252917f57c13>> + * @generated SignedSource<<765a2f99602c00c38047e25ce805af86>> * @flow strict * @noformat */ @@ -98,6 +98,7 @@ export interface Spec extends TurboModule { +useShadowNodeStateOnClone?: () => boolean; +useTurboModuleInterop?: () => boolean; +useTurboModules?: () => boolean; + +viewCullingOutsetRatio?: () => number; +virtualViewHysteresisRatio?: () => number; +virtualViewPrerenderRatio?: () => number; }