From 63149256c0e19ecbd008d1bf8f0ff1e79bb63cf2 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Fri, 7 Mar 2025 03:27:21 -0800 Subject: [PATCH] Handle null params in the Interop TM layer (#49873) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/49873 In the old architecture, when we were passing a `null` value as a parameter in a function that accepted nullable parameter, the null value was mapped to `nil` on iOS. After my changes in [d4236791e2](https://github.com/facebook/react-native/commit/d4236791e238a614d2fadf5c5659874d983ab029), in the New Architecture, through the interop layer, legacy modules were receiving an `NSNull` object instead of nil. This was breaking those modules which started crashing or observing undesired behavior. This change fixes the issue by making sure that, in those cases, a `nil` value is passed. Note that nested objects in the old architecture were correctly receiving NSNull, so nested objects were behaving correctly already. ## Changelog: [iOS][Fixed] - Properly pass `nil` for nullable parameters instead of `NSNull` for legacy modules Reviewed By: javache Differential Revision: D70723460 fbshipit-source-id: 384f48b6dbb3f54c369b31b6d2ee06069fa3591c --- .../platform/ios/ReactCommon/RCTInteropTurboModule.mm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm index 9ff56383832..740a202bca7 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm @@ -446,6 +446,15 @@ void ObjCInteropTurboModule::setInvocationArg( if (objCArgType == @encode(id)) { id arg = RCTConvertTo(selector, objCArg); + + // Handle the special case where there is an argument and it must be nil + // Without this check, the JS side will receive an object. + // See: discussion at + // https://github.com/facebook/react-native/pull/49250#issuecomment-2668465893 + if (arg == [NSNull null]) { + return; + } + if (arg) { [retainedObjectsForInvocation addObject:arg]; }