Add BindingsInstaller for TurboModules on iOS (#44486)

Summary:
Add synchronous JS bindings installation for TurboModules. That would help some 3rd party JSI based modules to install JS bindings easier.
Re-create from https://github.com/facebook/react-native/issues/43110 but for iOS

## Changelog:

[IOS] [ADDED] - Add BindingsInstaller for TurboModules

Pull Request resolved: https://github.com/facebook/react-native/pull/44486

Test Plan: Added test in RN-Tester TurboModule test case

Reviewed By: javache

Differential Revision: D57224891

Pulled By: philIip

fbshipit-source-id: fabe5c4f8d2087ac9a465f2cb90d884b83265a68
This commit is contained in:
Kudo Chien
2024-05-29 20:34:25 -07:00
committed by Facebook GitHub Bot
parent 775713cef7
commit bed487e24b
3 changed files with 43 additions and 4 deletions
@@ -30,6 +30,7 @@
#import <React/RCTRuntimeExecutorModule.h>
#import <React/RCTUtils.h>
#import <ReactCommon/CxxTurboModuleUtils.h>
#import <ReactCommon/RCTTurboModuleWithJSIBindings.h>
#import <ReactCommon/TurboCxxModule.h>
#import <ReactCommon/TurboModulePerfLogger.h>
#import <ReactCommon/TurboModuleUtils.h>
@@ -300,7 +301,7 @@ static Class getFallbackClassFromName(const char *name)
* (for now).
*/
- (std::shared_ptr<TurboModule>)provideTurboModule:(const char *)moduleName
- (std::shared_ptr<TurboModule>)provideTurboModule:(const char *)moduleName runtime:(jsi::Runtime *)runtime
{
auto turboModuleLookup = _turboModuleCache.find(moduleName);
if (turboModuleLookup != _turboModuleCache.end()) {
@@ -404,6 +405,10 @@ static Class getFallbackClassFromName(const char *name)
RCTLogError(@"TurboModule \"%@\"'s getTurboModule: method returned nil.", moduleClass);
}
_turboModuleCache.insert({moduleName, turboModule});
if ([module respondsToSelector:@selector(installJSIBindingsWithRuntime:)]) {
[(id<RCTTurboModuleWithJSIBindings>)module installJSIBindingsWithRuntime:*runtime];
}
return turboModule;
}
@@ -766,7 +771,7 @@ static Class getFallbackClassFromName(const char *name)
* Attach method queue to id<RCTBridgeModule> object.
* This is necessary because the id<RCTBridgeModule> object can be eagerly created/initialized before the method
* queue is required. The method queue is required for an id<RCTBridgeModule> for JS -> Native calls. So, we need it
* before we create the id<RCTBridgeModule>'s TurboModule jsi::HostObject in provideTurboModule:.
* before we create the id<RCTBridgeModule>'s TurboModule jsi::HostObject in provideTurboModule:runtime:.
*/
objc_setAssociatedObject(module, &kAssociatedMethodQueueKey, methodQueue, OBJC_ASSOCIATION_RETAIN);
@@ -916,7 +921,8 @@ static Class getFallbackClassFromName(const char *name)
* 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);
@@ -930,7 +936,7 @@ static Class getFallbackClassFromName(const char *name)
* 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 runtime:runtime];
if (moduleWasNotInitialized && [self moduleIsInitialized:moduleName]) {
[self->_bridge.performanceLogger markStopForTag:RCTPLTurboModuleSetup];
@@ -0,0 +1,20 @@
/*
* 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
#include <jsi/jsi.h>
#endif
@protocol RCTTurboModuleWithJSIBindings <NSObject>
#ifdef __cplusplus
- (void)installJSIBindingsWithRuntime:(facebook::jsi::Runtime &)runtime;
#endif
@end
@@ -10,10 +10,14 @@
#import <React/RCTAssert.h>
#import <React/RCTUtils.h>
#import <ReactCommon/RCTTurboModuleWithJSIBindings.h>
#import <UIKit/UIKit.h>
using namespace facebook::react;
@interface RCTSampleTurboModule () <RCTTurboModuleWithJSIBindings>
@end
@implementation RCTSampleTurboModule
// Backward-compatible export
@@ -66,6 +70,15 @@ RCT_EXPORT_MODULE()
return [self getConstants];
}
#pragma mark - RCTTurboModuleWithJSIBindings
- (void)installJSIBindingsWithRuntime:(facebook::jsi::Runtime &)runtime
{
runtime.global().setProperty(runtime, "__SampleTurboModuleJSIBindings", "Hello JSI!");
}
#pragma mark - Spec Methods
RCT_EXPORT_METHOD(voidFunc)
{
// Nothing to do