Skip to content

Commit

Permalink
Add BindingsInstaller for TurboModules on iOS
Browse files Browse the repository at this point in the history
Kudo committed May 10, 2024
1 parent f34d530 commit 56b721f
Showing 6 changed files with 94 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -154,9 +154,20 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule {

} // namespace facebook::react

@class RCTTurboModuleBindingsInstaller;

@protocol RCTTurboModule <NSObject>

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params;

@optional

/**
* Implements this function if a TurboModule needs to install its own JSI bindings.
*/
- (RCTTurboModuleBindingsInstaller *)createBindingsInstaller;

@end

/**
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import <Foundation/Foundation.h>

#ifdef __cplusplus
#import <ReactCommon/TurboModule.h>
#endif

NS_ASSUME_NONNULL_BEGIN

/**
* This class is a holder for a RCTTurboModule to get the facebook::react::TurboModule::BindingsInstaller.
*/
@interface RCTTurboModuleBindingsInstaller : NSObject

- (instancetype)init NS_UNAVAILABLE;

#ifdef __cplusplus
- (instancetype)initWithBindingsInstaller:(facebook::react::TurboModule::BindingsInstaller)bindingsInstaller
NS_DESIGNATED_INITIALIZER;

- (facebook::react::TurboModule::BindingsInstaller)get;
#endif

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import "RCTTurboModuleBindingsInstaller.h"

@implementation RCTTurboModuleBindingsInstaller {
facebook::react::TurboModule::BindingsInstaller _bindingsInstaller;
}

- (instancetype)initWithBindingsInstaller:(facebook::react::TurboModule::BindingsInstaller)bindingsInstaller
{
if (self = [super init]) {
_bindingsInstaller = bindingsInstaller;
}

return self;
}

- (facebook::react::TurboModule::BindingsInstaller)get
{
return _bindingsInstaller;
}

@end
Original file line number Diff line number Diff line change
@@ -30,6 +30,7 @@
#import <React/RCTRuntimeExecutorModule.h>
#import <React/RCTUtils.h>
#import <ReactCommon/CxxTurboModuleUtils.h>
#import <ReactCommon/RCTTurboModuleBindingsInstaller.h>
#import <ReactCommon/TurboCxxModule.h>
#import <ReactCommon/TurboModulePerfLogger.h>
#import <ReactCommon/TurboModuleUtils.h>
@@ -306,6 +307,7 @@ - (instancetype)initWithBridgeProxy:(RCTBridgeProxy *)bridgeProxy
*/

- (std::shared_ptr<TurboModule>)provideTurboModule:(const char *)moduleName
withRuntime:(facebook::jsi::Runtime *)runtime
{
auto turboModuleLookup = _turboModuleCache.find(moduleName);
if (turboModuleLookup != _turboModuleCache.end()) {
@@ -409,6 +411,14 @@ - (instancetype)initWithBridgeProxy:(RCTBridgeProxy *)bridgeProxy
RCTLogError(@"TurboModule \"%@\"'s getTurboModule: method returned nil.", moduleClass);
}
_turboModuleCache.insert({moduleName, turboModule});

if ([module respondsToSelector:@selector(createBindingsInstaller)]) {
RCTTurboModuleBindingsInstaller *installer =
(RCTTurboModuleBindingsInstaller *)[module performSelector:@selector(createBindingsInstaller)];
if (installer != nil) {
installer.get(*runtime);
}
}
return turboModule;
}

@@ -921,7 +931,8 @@ - (void)installJSBindings:(facebook::jsi::Runtime &)runtime
* aren't any strong references to it in ObjC. Hence, we give
* __turboModuleProxy a strong reference to TurboModuleManager.
*/
auto turboModuleProvider = [self](const std::string &name) -> std::shared_ptr<react::TurboModule> {
auto turboModuleProvider = [self,
runtime = &runtime](const std::string &name) -> std::shared_ptr<react::TurboModule> {
auto moduleName = name.c_str();

TurboModulePerfLogger::moduleJSRequireBeginningStart(moduleName);
@@ -935,7 +946,7 @@ - (void)installJSBindings:(facebook::jsi::Runtime &)runtime
* Additionally, if a TurboModule with the name `name` isn't found, then we
* trigger an assertion failure.
*/
auto turboModule = [self provideTurboModule:moduleName];
auto turboModule = [self provideTurboModule:moduleName withRuntime:runtime];

if (moduleWasNotInitialized && [self moduleIsInitialized:moduleName]) {
[self->_bridge.performanceLogger markStopForTag:RCTPLTurboModuleSetup];
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
*/

#import <Foundation/Foundation.h>
#import <ReactCommon/RCTTurboModuleBindingsInstaller.h>

#import "RCTNativeSampleTurboModuleSpec.h"

@@ -15,4 +16,6 @@
*/
@interface RCTSampleTurboModule : NSObject <NativeSampleTurboModuleSpec>

- (RCTTurboModuleBindingsInstaller *)createBindingsInstaller;

@end
Original file line number Diff line number Diff line change
@@ -35,6 +35,13 @@ - (dispatch_queue_t)methodQueue
return std::make_shared<NativeSampleTurboModuleSpecJSI>(params);
}

- (RCTTurboModuleBindingsInstaller *)createBindingsInstaller;
{
return [[RCTTurboModuleBindingsInstaller alloc] initWithBindingsInstaller:[](facebook::jsi::Runtime &runtime) {
runtime.global().setProperty(runtime, "__SampleTurboModuleJSIBindings", "Hello JSI!");
}];
}

// Backward compatible invalidation
- (void)invalidate
{

0 comments on commit 56b721f

Please sign in to comment.