From 05a4232dd591e2d43f192d69ca14a04f4a3fb6a1 Mon Sep 17 00:00:00 2001 From: Phillip Pan Date: Fri, 3 May 2024 16:38:26 -0700 Subject: [PATCH] add forward compatibility for bridgeless CallInvoker API (#44376) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44376 Changelog: [Internal] In order to make migration a little bit cleaner, I thought it would be nice to implement forward compatibility for RCTCallInvokerModule. This way, the consumer doesn't have to have branching logic when they try to retrieve the callInvoker in their code, and can remove a callsite to the bridge. Reviewed By: RSNara Differential Revision: D56807993 fbshipit-source-id: 6c9aa74db15e04b8ab632d230b3e525363a4d1ca --- .../React/Base/RCTBridgeModuleDecorator.m | 2 +- .../react-native/React/Base/RCTModuleData.h | 18 +++++---- .../react-native/React/Base/RCTModuleData.mm | 38 +++++++++++-------- .../React/CxxBridge/RCTCxxBridge.mm | 11 +++++- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/packages/react-native/React/Base/RCTBridgeModuleDecorator.m b/packages/react-native/React/Base/RCTBridgeModuleDecorator.m index 4111ef01911..7f8e15417bc 100644 --- a/packages/react-native/React/Base/RCTBridgeModuleDecorator.m +++ b/packages/react-native/React/Base/RCTBridgeModuleDecorator.m @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#include "RCTBridgeModuleDecorator.h" +#import "RCTBridgeModuleDecorator.h" @implementation RCTBridgeModuleDecorator diff --git a/packages/react-native/React/Base/RCTModuleData.h b/packages/react-native/React/Base/RCTModuleData.h index 6e3c0cbf5d7..1e884eca364 100644 --- a/packages/react-native/React/Base/RCTModuleData.h +++ b/packages/react-native/React/Base/RCTModuleData.h @@ -12,13 +12,21 @@ @protocol RCTBridgeMethod; @protocol RCTBridgeModule; @class RCTBridge; +@class RCTModuleData; @class RCTModuleRegistry; @class RCTViewRegistry; @class RCTBundleManager; @class RCTCallableJSModules; +@class RCTCallInvoker; typedef id (^RCTBridgeModuleProvider)(void); +@protocol RCTModuleDataCallInvokerProvider + +- (RCTCallInvoker *)callInvokerForModuleData:(RCTModuleData *)moduleData; + +@end + @interface RCTModuleData : NSObject - (instancetype)initWithModuleClass:(Class)moduleClass @@ -28,14 +36,6 @@ typedef id (^RCTBridgeModuleProvider)(void); bundleManager:(RCTBundleManager *)bundleManager callableJSModules:(RCTCallableJSModules *)callableJSModules; -- (instancetype)initWithModuleClass:(Class)moduleClass - moduleProvider:(RCTBridgeModuleProvider)moduleProvider - bridge:(RCTBridge *)bridge - moduleRegistry:(RCTModuleRegistry *)moduleRegistry - viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED - bundleManager:(RCTBundleManager *)bundleManager - callableJSModules:(RCTCallableJSModules *)callableJSModules NS_DESIGNATED_INITIALIZER; - - (instancetype)initWithModuleInstance:(id)instance bridge:(RCTBridge *)bridge moduleRegistry:(RCTModuleRegistry *)moduleRegistry @@ -110,4 +110,6 @@ typedef id (^RCTBridgeModuleProvider)(void); */ @property (nonatomic, assign, readonly) BOOL implementsPartialBatchDidFlush; +@property (nonatomic, weak, readwrite) id callInvokerProvider; + @end diff --git a/packages/react-native/React/Base/RCTModuleData.mm b/packages/react-native/React/Base/RCTModuleData.mm index 8f03a0c9058..8e033c7cfbf 100644 --- a/packages/react-native/React/Base/RCTModuleData.mm +++ b/packages/react-native/React/Base/RCTModuleData.mm @@ -16,6 +16,7 @@ #import "RCTBridge+Private.h" #import "RCTBridge.h" #import "RCTBridgeModuleDecorator.h" +#import "RCTCallInvokerModule.h" #import "RCTConstants.h" #import "RCTInitializing.h" #import "RCTLog.h" @@ -87,24 +88,24 @@ int32_t getUniqueId() bundleManager:(RCTBundleManager *)bundleManager callableJSModules:(RCTCallableJSModules *)callableJSModules { - return [self initWithModuleClass:moduleClass - moduleProvider:^id { - return [moduleClass new]; - } - bridge:bridge - moduleRegistry:moduleRegistry - viewRegistry_DEPRECATED:viewRegistry_DEPRECATED - bundleManager:bundleManager - callableJSModules:callableJSModules]; + return [self _initWithModuleClass:moduleClass + moduleProvider:^id { + return [moduleClass new]; + } + bridge:bridge + moduleRegistry:moduleRegistry + viewRegistry_DEPRECATED:viewRegistry_DEPRECATED + bundleManager:bundleManager + callableJSModules:callableJSModules]; } -- (instancetype)initWithModuleClass:(Class)moduleClass - moduleProvider:(RCTBridgeModuleProvider)moduleProvider - bridge:(RCTBridge *)bridge - moduleRegistry:(RCTModuleRegistry *)moduleRegistry - viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED - bundleManager:(RCTBundleManager *)bundleManager - callableJSModules:(RCTCallableJSModules *)callableJSModules +- (instancetype)_initWithModuleClass:(Class)moduleClass + moduleProvider:(RCTBridgeModuleProvider)moduleProvider + bridge:(RCTBridge *)bridge + moduleRegistry:(RCTModuleRegistry *)moduleRegistry + viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED + bundleManager:(RCTBundleManager *)bundleManager + callableJSModules:(RCTCallableJSModules *)callableJSModules { if (self = [super init]) { _bridge = bridge; @@ -201,6 +202,11 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init); bundleManager:_bundleManager callableJSModules:_callableJSModules]; [moduleDecorator attachInteropAPIsToModule:_instance]; + + // This is a more performant alternative for conformsToProtocol:@protocol(RCTCallInvokerModule) + if ([_instance respondsToSelector:@selector(setCallInvoker:)]) { + [(id)_instance setCallInvoker:[self.callInvokerProvider callInvokerForModuleData:self]]; + } } [self setUpMethodQueue]; diff --git a/packages/react-native/React/CxxBridge/RCTCxxBridge.mm b/packages/react-native/React/CxxBridge/RCTCxxBridge.mm index 4d33f024081..044862f821c 100644 --- a/packages/react-native/React/CxxBridge/RCTCxxBridge.mm +++ b/packages/react-native/React/CxxBridge/RCTCxxBridge.mm @@ -15,6 +15,7 @@ #import #import #import +#import #import #import #import @@ -168,7 +169,7 @@ static void registerPerformanceLoggerHooks(RCTPerformanceLogger *performanceLogg }; } -@interface RCTCxxBridge () +@interface RCTCxxBridge () @property (nonatomic, weak, readonly) RCTBridge *parentBridge; @property (nonatomic, assign, readonly) BOOL moduleSetupComplete; @@ -767,6 +768,7 @@ struct RCTInstanceCallback : public InstanceCallback { viewRegistry_DEPRECATED:_viewRegistry_DEPRECATED bundleManager:_bundleManager callableJSModules:_callableJSModules]; + moduleData.callInvokerProvider = self; BridgeNativeModulePerfLogger::moduleDataCreateEnd([moduleName UTF8String], moduleDataId); _moduleDataByName[moduleName] = moduleData; @@ -1595,4 +1597,11 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithBundleURL return _reactInstance ? _reactInstance->getDecoratedNativeMethodCallInvoker(nativeInvoker) : nullptr; } +#pragma mark - RCTModuleDataCallInvokerProvider + +- (RCTCallInvoker *)callInvokerForModuleData:(RCTModuleData *)moduleData +{ + return [[RCTCallInvoker alloc] initWithCallInvoker:self.jsCallInvoker]; +} + @end