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 3e856366795..d5da0c09122 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<<62715a19c87a010716eb7d2e904258fa>> + * @generated SignedSource<> */ /** @@ -174,6 +174,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun enableMainQueueModulesOnIOS(): Boolean = accessor.enableMainQueueModulesOnIOS() + /** + * Enable NSNull conversion when handling module arguments on iOS + */ + @JvmStatic + public fun enableModuleArgumentNSNullConversionIOS(): Boolean = accessor.enableModuleArgumentNSNullConversionIOS() + /** * Parse CSS strings using the Fabric CSS parser instead of ViewConfig processing */ 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 917536c853f..504ef330da3 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<<53e2f9241b9b3396b1ddf5893c7f3c4e>> + * @generated SignedSource<<4665e190f626b377f37e14c1c19f809d>> */ /** @@ -44,6 +44,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var enableLayoutAnimationsOnAndroidCache: Boolean? = null private var enableLayoutAnimationsOnIOSCache: Boolean? = null private var enableMainQueueModulesOnIOSCache: Boolean? = null + private var enableModuleArgumentNSNullConversionIOSCache: Boolean? = null private var enableNativeCSSParsingCache: Boolean? = null private var enableNetworkEventReportingCache: Boolean? = null private var enableNewBackgroundAndBorderDrawablesCache: Boolean? = null @@ -287,6 +288,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun enableModuleArgumentNSNullConversionIOS(): Boolean { + var cached = enableModuleArgumentNSNullConversionIOSCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.enableModuleArgumentNSNullConversionIOS() + enableModuleArgumentNSNullConversionIOSCache = cached + } + return cached + } + override fun enableNativeCSSParsing(): Boolean { var cached = enableNativeCSSParsingCache 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 18aea3d585c..a71962aa0f9 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<<918dcdb416bb3e2e3f83cded78e06363>> + * @generated SignedSource<> */ /** @@ -76,6 +76,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun enableMainQueueModulesOnIOS(): Boolean + @DoNotStrip @JvmStatic public external fun enableModuleArgumentNSNullConversionIOS(): Boolean + @DoNotStrip @JvmStatic public external fun enableNativeCSSParsing(): Boolean @DoNotStrip @JvmStatic public external fun enableNetworkEventReporting(): 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 df1df830bc6..ac1ff11dfe1 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<<7151e167c4e45a732a341a2cfcf67b58>> + * @generated SignedSource<> */ /** @@ -71,6 +71,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun enableMainQueueModulesOnIOS(): Boolean = false + override fun enableModuleArgumentNSNullConversionIOS(): Boolean = true + override fun enableNativeCSSParsing(): Boolean = false override fun enableNetworkEventReporting(): 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 b849113bc6a..f8adedd3474 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<> */ /** @@ -48,6 +48,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var enableLayoutAnimationsOnAndroidCache: Boolean? = null private var enableLayoutAnimationsOnIOSCache: Boolean? = null private var enableMainQueueModulesOnIOSCache: Boolean? = null + private var enableModuleArgumentNSNullConversionIOSCache: Boolean? = null private var enableNativeCSSParsingCache: Boolean? = null private var enableNetworkEventReportingCache: Boolean? = null private var enableNewBackgroundAndBorderDrawablesCache: Boolean? = null @@ -315,6 +316,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } + override fun enableModuleArgumentNSNullConversionIOS(): Boolean { + var cached = enableModuleArgumentNSNullConversionIOSCache + if (cached == null) { + cached = currentProvider.enableModuleArgumentNSNullConversionIOS() + accessedFeatureFlags.add("enableModuleArgumentNSNullConversionIOS") + enableModuleArgumentNSNullConversionIOSCache = cached + } + return cached + } + override fun enableNativeCSSParsing(): Boolean { var cached = enableNativeCSSParsingCache 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 b89f5292d55..b57eba090b6 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<<722ed5b36a043d4eadb095f092c95707>> + * @generated SignedSource<<1e5562ce20c0735c926c1cb029b93e18>> */ /** @@ -71,6 +71,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun enableMainQueueModulesOnIOS(): Boolean + @DoNotStrip public fun enableModuleArgumentNSNullConversionIOS(): Boolean + @DoNotStrip public fun enableNativeCSSParsing(): Boolean @DoNotStrip public fun enableNetworkEventReporting(): Boolean 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 e70adc38cc1..db038b4ff4d 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<<422a5922cfe14a1c5f7c0728410dbe8a>> + * @generated SignedSource<<078954ede626079b7d36ab63cdbab761>> */ /** @@ -183,6 +183,12 @@ class ReactNativeFeatureFlagsJavaProvider return method(javaProvider_); } + bool enableModuleArgumentNSNullConversionIOS() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableModuleArgumentNSNullConversionIOS"); + return method(javaProvider_); + } + bool enableNativeCSSParsing() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableNativeCSSParsing"); @@ -463,6 +469,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableMainQueueModulesOnIOS( return ReactNativeFeatureFlags::enableMainQueueModulesOnIOS(); } +bool JReactNativeFeatureFlagsCxxInterop::enableModuleArgumentNSNullConversionIOS( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::enableModuleArgumentNSNullConversionIOS(); +} + bool JReactNativeFeatureFlagsCxxInterop::enableNativeCSSParsing( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::enableNativeCSSParsing(); @@ -696,6 +707,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "enableMainQueueModulesOnIOS", JReactNativeFeatureFlagsCxxInterop::enableMainQueueModulesOnIOS), + makeNativeMethod( + "enableModuleArgumentNSNullConversionIOS", + JReactNativeFeatureFlagsCxxInterop::enableModuleArgumentNSNullConversionIOS), makeNativeMethod( "enableNativeCSSParsing", JReactNativeFeatureFlagsCxxInterop::enableNativeCSSParsing), 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 8de4854606c..5ebb4a3db76 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<<18d7c9c2577450a0bb7e6da91b8597ed>> + * @generated SignedSource<<083e45ab99622254be46213ba07c586b>> */ /** @@ -102,6 +102,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool enableMainQueueModulesOnIOS( facebook::jni::alias_ref); + static bool enableModuleArgumentNSNullConversionIOS( + facebook::jni::alias_ref); + static bool enableNativeCSSParsing( 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 2cab45a1578..4d38e66d3ca 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<<9f34463a7cddcfd1a76631041297c4b7>> + * @generated SignedSource<> */ /** @@ -122,6 +122,10 @@ bool ReactNativeFeatureFlags::enableMainQueueModulesOnIOS() { return getAccessor().enableMainQueueModulesOnIOS(); } +bool ReactNativeFeatureFlags::enableModuleArgumentNSNullConversionIOS() { + return getAccessor().enableModuleArgumentNSNullConversionIOS(); +} + bool ReactNativeFeatureFlags::enableNativeCSSParsing() { return getAccessor().enableNativeCSSParsing(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index e175480022e..77d3a6b8a79 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<> */ /** @@ -159,6 +159,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool enableMainQueueModulesOnIOS(); + /** + * Enable NSNull conversion when handling module arguments on iOS + */ + RN_EXPORT static bool enableModuleArgumentNSNullConversionIOS(); + /** * Parse CSS strings using the Fabric CSS parser instead of ViewConfig processing */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index b46a6ac59a9..e146b039da7 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<> + * @generated SignedSource<<955524ea199666cfdd38ab4b73efcd2a>> */ /** @@ -461,6 +461,24 @@ bool ReactNativeFeatureFlagsAccessor::enableMainQueueModulesOnIOS() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::enableModuleArgumentNSNullConversionIOS() { + auto flagValue = enableModuleArgumentNSNullConversionIOS_.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(24, "enableModuleArgumentNSNullConversionIOS"); + + flagValue = currentProvider_->enableModuleArgumentNSNullConversionIOS(); + enableModuleArgumentNSNullConversionIOS_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::enableNativeCSSParsing() { auto flagValue = enableNativeCSSParsing_.load(); @@ -470,7 +488,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(24, "enableNativeCSSParsing"); + markFlagAsAccessed(25, "enableNativeCSSParsing"); flagValue = currentProvider_->enableNativeCSSParsing(); enableNativeCSSParsing_ = flagValue; @@ -488,7 +506,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(25, "enableNetworkEventReporting"); + markFlagAsAccessed(26, "enableNetworkEventReporting"); flagValue = currentProvider_->enableNetworkEventReporting(); enableNetworkEventReporting_ = flagValue; @@ -506,7 +524,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNewBackgroundAndBorderDrawables() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(26, "enableNewBackgroundAndBorderDrawables"); + markFlagAsAccessed(27, "enableNewBackgroundAndBorderDrawables"); flagValue = currentProvider_->enableNewBackgroundAndBorderDrawables(); enableNewBackgroundAndBorderDrawables_ = flagValue; @@ -524,7 +542,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(27, "enablePreparedTextLayout"); + markFlagAsAccessed(28, "enablePreparedTextLayout"); flagValue = currentProvider_->enablePreparedTextLayout(); enablePreparedTextLayout_ = flagValue; @@ -542,7 +560,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(28, "enablePropsUpdateReconciliationAndroid"); + markFlagAsAccessed(29, "enablePropsUpdateReconciliationAndroid"); flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid(); enablePropsUpdateReconciliationAndroid_ = flagValue; @@ -560,7 +578,7 @@ bool ReactNativeFeatureFlagsAccessor::enableResourceTimingAPI() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(29, "enableResourceTimingAPI"); + markFlagAsAccessed(30, "enableResourceTimingAPI"); flagValue = currentProvider_->enableResourceTimingAPI(); enableResourceTimingAPI_ = flagValue; @@ -578,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSynchronousStateUpdates() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(30, "enableSynchronousStateUpdates"); + markFlagAsAccessed(31, "enableSynchronousStateUpdates"); flagValue = currentProvider_->enableSynchronousStateUpdates(); enableSynchronousStateUpdates_ = flagValue; @@ -596,7 +614,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(31, "enableViewCulling"); + markFlagAsAccessed(32, "enableViewCulling"); flagValue = currentProvider_->enableViewCulling(); enableViewCulling_ = flagValue; @@ -614,7 +632,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(32, "enableViewRecycling"); + markFlagAsAccessed(33, "enableViewRecycling"); flagValue = currentProvider_->enableViewRecycling(); enableViewRecycling_ = flagValue; @@ -632,7 +650,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(33, "enableViewRecyclingForText"); + markFlagAsAccessed(34, "enableViewRecyclingForText"); flagValue = currentProvider_->enableViewRecyclingForText(); enableViewRecyclingForText_ = flagValue; @@ -650,7 +668,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(34, "enableViewRecyclingForView"); + markFlagAsAccessed(35, "enableViewRecyclingForView"); flagValue = currentProvider_->enableViewRecyclingForView(); enableViewRecyclingForView_ = flagValue; @@ -668,7 +686,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(35, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + markFlagAsAccessed(36, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; @@ -686,7 +704,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(36, "fuseboxEnabledRelease"); + markFlagAsAccessed(37, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -704,7 +722,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(37, "fuseboxNetworkInspectionEnabled"); + markFlagAsAccessed(38, "fuseboxNetworkInspectionEnabled"); flagValue = currentProvider_->fuseboxNetworkInspectionEnabled(); fuseboxNetworkInspectionEnabled_ = flagValue; @@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::incorporateMaxLinesDuringAndroidLayout() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "incorporateMaxLinesDuringAndroidLayout"); + markFlagAsAccessed(39, "incorporateMaxLinesDuringAndroidLayout"); flagValue = currentProvider_->incorporateMaxLinesDuringAndroidLayout(); incorporateMaxLinesDuringAndroidLayout_ = flagValue; @@ -740,7 +758,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(39, "traceTurboModulePromiseRejectionsOnAndroid"); + markFlagAsAccessed(40, "traceTurboModulePromiseRejectionsOnAndroid"); flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid(); traceTurboModulePromiseRejectionsOnAndroid_ = flagValue; @@ -758,7 +776,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(40, "updateRuntimeShadowNodeReferencesOnCommit"); + markFlagAsAccessed(41, "updateRuntimeShadowNodeReferencesOnCommit"); flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit(); updateRuntimeShadowNodeReferencesOnCommit_ = flagValue; @@ -776,7 +794,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(41, "useAlwaysAvailableJSErrorHandling"); + markFlagAsAccessed(42, "useAlwaysAvailableJSErrorHandling"); flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling(); useAlwaysAvailableJSErrorHandling_ = flagValue; @@ -794,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::useAndroidTextLayoutWidthDirectly() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(42, "useAndroidTextLayoutWidthDirectly"); + markFlagAsAccessed(43, "useAndroidTextLayoutWidthDirectly"); flagValue = currentProvider_->useAndroidTextLayoutWidthDirectly(); useAndroidTextLayoutWidthDirectly_ = flagValue; @@ -812,7 +830,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(43, "useFabricInterop"); + markFlagAsAccessed(44, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -830,7 +848,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(44, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(45, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -848,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(45, "useOptimizedEventBatchingOnAndroid"); + markFlagAsAccessed(46, "useOptimizedEventBatchingOnAndroid"); flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid(); useOptimizedEventBatchingOnAndroid_ = flagValue; @@ -866,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(46, "useRawPropsJsiValue"); + markFlagAsAccessed(47, "useRawPropsJsiValue"); flagValue = currentProvider_->useRawPropsJsiValue(); useRawPropsJsiValue_ = flagValue; @@ -884,7 +902,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(47, "useShadowNodeStateOnClone"); + markFlagAsAccessed(48, "useShadowNodeStateOnClone"); flagValue = currentProvider_->useShadowNodeStateOnClone(); useShadowNodeStateOnClone_ = flagValue; @@ -902,7 +920,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(48, "useTurboModuleInterop"); + markFlagAsAccessed(49, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -920,7 +938,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(49, "useTurboModules"); + markFlagAsAccessed(50, "useTurboModules"); flagValue = currentProvider_->useTurboModules(); useTurboModules_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 0dac38c1d3f..b08975c91ca 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<> */ /** @@ -56,6 +56,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableLayoutAnimationsOnAndroid(); bool enableLayoutAnimationsOnIOS(); bool enableMainQueueModulesOnIOS(); + bool enableModuleArgumentNSNullConversionIOS(); bool enableNativeCSSParsing(); bool enableNetworkEventReporting(); bool enableNewBackgroundAndBorderDrawables(); @@ -93,7 +94,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 50> accessedFeatureFlags_; + std::array, 51> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> animatedShouldSignalBatch_; @@ -119,6 +120,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableLayoutAnimationsOnAndroid_; std::atomic> enableLayoutAnimationsOnIOS_; std::atomic> enableMainQueueModulesOnIOS_; + std::atomic> enableModuleArgumentNSNullConversionIOS_; std::atomic> enableNativeCSSParsing_; std::atomic> enableNetworkEventReporting_; std::atomic> enableNewBackgroundAndBorderDrawables_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index e61d8d45dea..9b6fcd9ffed 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<<4c463bb7d1aa97478abe0e74955aa854>> + * @generated SignedSource<> */ /** @@ -123,6 +123,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool enableModuleArgumentNSNullConversionIOS() override { + return true; + } + bool enableNativeCSSParsing() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index 03429d3c955..a66b05c7b57 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<<75a1b352cffa84394393992484dcb33c>> */ /** @@ -261,6 +261,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::enableMainQueueModulesOnIOS(); } + bool enableModuleArgumentNSNullConversionIOS() override { + auto value = values_["enableModuleArgumentNSNullConversionIOS"]; + if (!value.isNull()) { + return value.getBool(); + } + + return ReactNativeFeatureFlagsDefaults::enableModuleArgumentNSNullConversionIOS(); + } + bool enableNativeCSSParsing() override { auto value = values_["enableNativeCSSParsing"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 7345df9164e..b82ab921dd7 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<<53bd41086143a19f52e1e96025b24c76>> + * @generated SignedSource<<57a8881e00c4208f97c4eccac202a3bb>> */ /** @@ -49,6 +49,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableLayoutAnimationsOnAndroid() = 0; virtual bool enableLayoutAnimationsOnIOS() = 0; virtual bool enableMainQueueModulesOnIOS() = 0; + virtual bool enableModuleArgumentNSNullConversionIOS() = 0; virtual bool enableNativeCSSParsing() = 0; virtual bool enableNetworkEventReporting() = 0; virtual bool enableNewBackgroundAndBorderDrawables() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/iostests/RCTTurboModuleTests.mm b/packages/react-native/ReactCommon/react/nativemodule/core/iostests/RCTTurboModuleTests.mm index ec9b15ecc61..bdbaf4b7905 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/iostests/RCTTurboModuleTests.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/core/iostests/RCTTurboModuleTests.mm @@ -9,14 +9,21 @@ #import #import +#import #import using namespace facebook::react; -@protocol RCTTestTurboModule +@interface RCTTestTurboModule : NSObject -- (void)testMethodWhichTakesObject:(id)object; +@end + +@implementation RCTTestTurboModule + +RCT_EXPORT_MODULE() + +RCT_EXPORT_METHOD(testMethodWhichTakesObject : (id)object) {} @end @@ -37,13 +44,13 @@ class StubNativeMethodCallInvoker : public NativeMethodCallInvoker { @implementation RCTTurboModuleTests { std::unique_ptr module_; - id instance_; + RCTTestTurboModule *instance_; } - (void)setUp { [super setUp]; - instance_ = OCMProtocolMock(@protocol(RCTTestTurboModule)); + instance_ = OCMClassMock([RCTTestTurboModule class]); ObjCTurboModule::InitParams params = { .moduleName = "TestModule", @@ -82,11 +89,14 @@ class StubNativeMethodCallInvoker : public NativeMethodCallInvoker { OCMVerify(OCMTimes(1), [instance_ testMethodWhichTakesObject:@{@"foo" : @"bar"}]); // Object with key without value - args[0].asObject(*rt).setProperty(*rt, "foo", "facebook::jsi::Value::undefined()"); + args[0].asObject(*rt).setProperty(*rt, "foo", facebook::jsi::Value::null()); module_->invokeObjCMethod( *rt, VoidKind, "testMethodWhichTakesObject", @selector(testMethodWhichTakesObject:), args, 1); - // FIXME this should be called with @{@"foo": kCFNull} - OCMVerify(OCMTimes(1), [instance_ testMethodWhichTakesObject:@{}]); + if (ReactNativeFeatureFlags::enableModuleArgumentNSNullConversionIOS()) { + OCMVerify(OCMTimes(1), [instance_ testMethodWhichTakesObject:@{@"foo" : (id)kCFNull}]); + } else { + OCMVerify(OCMTimes(2), [instance_ testMethodWhichTakesObject:@{}]); + } // Null args[0] = facebook::jsi::Value::null(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm index e8ad078da5f..99148bf1446 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm @@ -18,6 +18,7 @@ #import #import #import +#import #include @@ -622,7 +623,9 @@ void ObjCTurboModule::setInvocationArg( /** * Convert arg to ObjC objects. */ - id objCArg = convertJSIValueToObjCObject(runtime, arg, jsInvoker_); + BOOL enableModuleArgumentNSNullConversionIOS = ReactNativeFeatureFlags::enableModuleArgumentNSNullConversionIOS(); + id objCArg = TurboModuleConvertUtils::convertJSIValueToObjCObject( + runtime, arg, jsInvoker_, enableModuleArgumentNSNullConversionIOS); if (objCArg) { NSString *methodNameNSString = @(methodName); @@ -640,6 +643,10 @@ void ObjCTurboModule::setInvocationArg( id (*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend; id convertedObjCArg = convert([RCTConvert class], rctConvertSelector, objCArg); + if (enableModuleArgumentNSNullConversionIOS && convertedObjCArg == [NSNull null]) { + return; + } + [inv setArgument:(void *)&convertedObjCArg atIndex:i + 2]; if (convertedObjCArg) { [retainedObjectsForInvocation addObject:convertedObjCArg]; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index db7577c3a23..4eb297ef981 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<<74f011324e9d4647fa757f29b602c6c3>> + * @generated SignedSource<<167e35bd99451cbe24a2bb54db5c66b9>> */ /** @@ -164,6 +164,11 @@ bool NativeReactNativeFeatureFlags::enableMainQueueModulesOnIOS( return ReactNativeFeatureFlags::enableMainQueueModulesOnIOS(); } +bool NativeReactNativeFeatureFlags::enableModuleArgumentNSNullConversionIOS( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::enableModuleArgumentNSNullConversionIOS(); +} + bool NativeReactNativeFeatureFlags::enableNativeCSSParsing( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::enableNativeCSSParsing(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 18d0bc43060..ebb08d4febb 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<<2b33a7fe9086343c427f06cc62c67a62>> + * @generated SignedSource<<196bc6e1f0196c39029c3d2a45d3254b>> */ /** @@ -85,6 +85,8 @@ class NativeReactNativeFeatureFlags bool enableMainQueueModulesOnIOS(jsi::Runtime& runtime); + bool enableModuleArgumentNSNullConversionIOS(jsi::Runtime& runtime); + bool enableNativeCSSParsing(jsi::Runtime& runtime); bool enableNetworkEventReporting(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 781e267ba30..00eeb4034dc 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -299,6 +299,16 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, + enableModuleArgumentNSNullConversionIOS: { + defaultValue: true, + metadata: { + description: + 'Enable NSNull conversion when handling module arguments on iOS', + expectedReleaseValue: true, + purpose: 'release', + }, + ossReleaseStage: 'none', + }, enableNativeCSSParsing: { defaultValue: false, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 105233cc641..d4ade2d6080 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<> + * @generated SignedSource<> * @flow strict * @noformat */ @@ -74,6 +74,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{ enableLayoutAnimationsOnAndroid: Getter, enableLayoutAnimationsOnIOS: Getter, enableMainQueueModulesOnIOS: Getter, + enableModuleArgumentNSNullConversionIOS: Getter, enableNativeCSSParsing: Getter, enableNetworkEventReporting: Getter, enableNewBackgroundAndBorderDrawables: Getter, @@ -277,6 +278,10 @@ export const enableLayoutAnimationsOnIOS: Getter = createNativeFlagGett * Makes modules requiring main queue setup initialize on the main thread, during React Native init. */ export const enableMainQueueModulesOnIOS: Getter = createNativeFlagGetter('enableMainQueueModulesOnIOS', false); +/** + * Enable NSNull conversion when handling module arguments on iOS + */ +export const enableModuleArgumentNSNullConversionIOS: Getter = createNativeFlagGetter('enableModuleArgumentNSNullConversionIOS', true); /** * Parse CSS strings using the Fabric CSS parser instead of ViewConfig processing */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index e8df6ffde41..8f94a77f2bd 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<<620ba7ace3df80067aa6ba1ed44aec60>> + * @generated SignedSource<> * @flow strict * @noformat */ @@ -49,6 +49,7 @@ export interface Spec extends TurboModule { +enableLayoutAnimationsOnAndroid?: () => boolean; +enableLayoutAnimationsOnIOS?: () => boolean; +enableMainQueueModulesOnIOS?: () => boolean; + +enableModuleArgumentNSNullConversionIOS?: () => boolean; +enableNativeCSSParsing?: () => boolean; +enableNetworkEventReporting?: () => boolean; +enableNewBackgroundAndBorderDrawables?: () => boolean;