diff --git a/React/Base/RCTBridgeModule.h b/React/Base/RCTBridgeModule.h index 559c141e352af4..31aaeffd2dfee7 100644 --- a/React/Base/RCTBridgeModule.h +++ b/React/Base/RCTBridgeModule.h @@ -15,6 +15,7 @@ @class RCTModuleRegistry; @class RCTViewRegistry; @class RCTBundleManager; +@class RCTCallableJSModules; /** * The type of a block that is capable of sending a response to a bridged @@ -146,6 +147,17 @@ RCT_EXTERN_C_END */ @property (nonatomic, weak, readwrite) RCTBundleManager *bundleManager; +/** + * A reference to an RCTCallableJSModules. Useful for modules that need to + * call into methods on JavaScript modules registered as callable with + * React Native. + * + * To implement this in your module, just add `@synthesize callableJSModules = + * _callableJSModules;`. If using Swift, add `@objc var callableJSModules: + * RCTCallableJSModules!` to your module. + */ +@property (nonatomic, weak, readwrite) RCTCallableJSModules *callableJSModules; + /** * A reference to the RCTBridge. Useful for modules that require access * to bridge features, such as sending events or making JS calls. This @@ -443,3 +455,24 @@ typedef UIView * (^RCTBridgelessComponentViewProvider)(NSNumber *); - (UIView *)viewForReactTag:(NSNumber *)reactTag; @end + +typedef void (^RCTBridgelessJSModuleMethodInvoker)( + NSString *moduleName, + NSString *methodName, + NSArray *args, + dispatch_block_t onComplete); + +/** + * A class that allows NativeModules to call methods on JavaScript modules registered + * as callable with React Native. + */ +@interface RCTCallableJSModules : NSObject +- (void)setBridge:(RCTBridge *)bridge; +- (void)setBridgelessJSModuleMethodInvoker:(RCTBridgelessJSModuleMethodInvoker)bridgelessJSModuleMethodInvoker; + +- (void)invokeModule:(NSString *)moduleName method:(NSString *)methodName withArgs:(NSArray *)args; +- (void)invokeModule:(NSString *)moduleName + method:(NSString *)methodName + withArgs:(NSArray *)args + onComplete:(dispatch_block_t)onComplete; +@end diff --git a/React/Base/RCTCallableJSModules.m b/React/Base/RCTCallableJSModules.m new file mode 100644 index 00000000000000..316d4dc56e4ee1 --- /dev/null +++ b/React/Base/RCTCallableJSModules.m @@ -0,0 +1,47 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTBridge.h" +#import "RCTBridgeModule.h" + +@implementation RCTCallableJSModules { + RCTBridgelessJSModuleMethodInvoker _bridgelessJSModuleMethodInvoker; + __weak RCTBridge *_bridge; +} + +- (void)setBridge:(RCTBridge *)bridge +{ + _bridge = bridge; +} + +- (void)setBridgelessJSModuleMethodInvoker:(RCTBridgelessJSModuleMethodInvoker)bridgelessJSModuleMethodInvoker +{ + _bridgelessJSModuleMethodInvoker = bridgelessJSModuleMethodInvoker; +} + +- (void)invokeModule:(NSString *)moduleName method:(NSString *)methodName withArgs:(NSArray *)args +{ + [self invokeModule:moduleName method:methodName withArgs:args onComplete:NULL]; +} + +- (void)invokeModule:(NSString *)moduleName + method:(NSString *)methodName + withArgs:(NSArray *)args + onComplete:(dispatch_block_t)onComplete +{ + RCTBridge *bridge = _bridge; + if (bridge) { + [bridge enqueueJSCall:moduleName method:methodName args:args completion:onComplete]; + return; + } + + if (_bridgelessJSModuleMethodInvoker) { + _bridgelessJSModuleMethodInvoker(moduleName, methodName, args, onComplete); + } +} + +@end