Skip to content

Add delegate forwarding for getModuleClassFromName: and getModuleInstanceFromClass: in RCTReactNativeFactory #916

@CAMOBAP

Description

@CAMOBAP

Introduction

The RCTReactNativeFactory implementation is inconsistent in how it handles RCTTurboModuleManagerDelegate methods:

  • getTurboModule:jsInvoker: checks if the delegate implements the method first, then falls back to default implementation
  • getModuleClassFromName: and getModuleInstanceFromClass: skip the delegate check and go straight to default implementations

This prevents clients from providing custom implementations via their custom getModuleClassFromName: and getModuleInstanceFromClass: implementations.

Details

I need to provide custom implementations for specific Objective-C TurboModules in my RCTTurboModuleManagerDelegate. Currently, this is only possible for C++ TurboModules via getTurboModule:jsInvoker:, but not for Objective-C TurboModules because getModuleClassFromName: and getModuleInstanceFromClass: aren't called on the factory's delegate by RCTReactNativeFactory.

The proposed change adds delegate checking to both methods - calling the factory's delegate implementation if it exists, then falling back to own implementation. This makes them consistent with getTurboModule:jsInvoker:.

Here's my current diff showing the proposed changes:

--- a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm
+++ b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm
@@ -163,6 +163,9 @@ - (BOOL)bridgelessEnabled
 
 - (Class)getModuleClassFromName:(const char *)name
 {
+  if ([_delegate respondsToSelector:@selector(getModuleClassFromName:)]) {
+    return [_delegate getModuleClassFromName:name];
+  }
 #if RN_DISABLE_OSS_PLUGIN_HEADER
   return RCTTurboModulePluginClassProvider(name);
 #else
@@ -190,6 +193,13 @@ - (Class)getModuleClassFromName:(const char *)name
 
 - (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass
 {
+  if ([_delegate respondsToSelector:@selector(getModuleInstanceFromClass:)]) {
+    id<RCTTurboModule> delegateResult = [_delegate getModuleInstanceFromClass:moduleClass];
+    if (delegateResult != nil) {
+      return delegateResult;
+    }
+  }
+
 #if USE_OSS_CODEGEN
   if (self.delegate.dependencyProvider == nil) {
     [NSException raise:@"ReactNativeFactoryDelegate dependencyProvider is nil"

This change ensures both methods follow the same pattern: check if the delegate implements the method, call it if available, otherwise fall back to the default implementation.

Discussion points

I would like to evaluate my idea first to see if there are any objections. I will prepare PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions