Skip to content

Commit

Permalink
Be less strict with method parsing of TurboModule Interop Layer
Browse files Browse the repository at this point in the history
Summary:
We have instance of apps crashing when enabling the New Architecture because of the TurboModule interop layer.

What's happening is that when the module is loaded, the TM Interop Layer tries to parse the method definition to expose them in JS. However, for some libraries in the Legacy Architecture, it is possible to define a method in Objective-C and to define a different signature in Swift.

For example, the [`RNBluetoothClassic` library](https://github.com/kenjdavidson/react-native-bluetooth-classic) defines a selector in objective-c which [has the signature](https://github.com/kenjdavidson/react-native-bluetooth-classic/blob/main/ios/RNBluetoothClassic.m#L134-L136)

```
RCT_EXTERN_METHOD(available: (NSString *)deviceId
                  resolver: (RCTPromiseResolveBlock)resolve
                  rejecter: (RCTPromiseRejectBlock)reject)
```

And the method is inmplemented in Swift with [the signature](https://github.com/kenjdavidson/react-native-bluetooth-classic/blob/main/ios/RNBluetoothClassic.swift#L502-L505):

```
func availableFromDevice(
        _ deviceId: String,
        resolver resolve: RCTPromiseResolveBlock,
        rejecter reject: RCTPromiseRejectBlock
    )
```

When the TurboModule interop layer tries to parse the method, it receives the `accept:resolver:rejecter:` signature, but that signature is not actually defined in as a method in the module instance, and it crashes.

This crash was not happening in the Old Architecture, which was handling this case gracefully. Notice that the specific method from the example is not working in the Old Architecture either. However, the app is not crashing in the old architecture.

This change adds the same graceful behaviors plus it adds a warning in development to notify the developer about which methods couldn't be found in the interface.

## Changelog:
[iOS][Fixed] - Avoid crashing the app when the InteropLayer can't find some methods in the native implementation.

Differential Revision: D68901734
  • Loading branch information
cipolleschi authored and facebook-github-bot committed Jan 30, 2025
1 parent 566a45e commit 6a43243
Showing 1 changed file with 9 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@
NSArray<RCTMethodArgument *> *arguments;
SEL objCMethodSelector = NSSelectorFromString(RCTParseMethodSignature(methodInfo->objcName, &arguments));
NSMethodSignature *objCMethodSignature = [moduleClass instanceMethodSignatureForSelector:objCMethodSelector];
if (objCMethodSignature == nullptr) {
RCTLogWarn(
@"The objective-c `%s` method signature for the JS method `%@` can not be found in the ObjecitveC definition of the %s module.\nThe `%@` JS method will not be available.",
methodInfo->objcName,
jsMethodName,
moduleName.c_str(),
jsMethodName);
continue;
}
std::string objCMethodReturnType = [objCMethodSignature methodReturnType];

if (objCMethodSignature.numberOfArguments - 2 != [arguments count]) {
Expand Down

0 comments on commit 6a43243

Please sign in to comment.