From 968bd9505757ef927afe5fd4f755ebbf766a557b Mon Sep 17 00:00:00 2001 From: Kudo Chien Date: Wed, 8 May 2024 20:12:19 +0800 Subject: [PATCH] add ios support --- .../platform/ios/ReactCommon/RCTTurboModule.h | 11 +++++++ .../RCTTurboModuleBindingsInstaller.h | 32 +++++++++++++++++++ .../RCTTurboModuleBindingsInstaller.mm | 28 ++++++++++++++++ .../ios/ReactCommon/RCTTurboModuleManager.mm | 14 ++++++++ .../ios/ReactCommon/RCTSampleTurboModule.h | 3 ++ .../ios/ReactCommon/RCTSampleTurboModule.mm | 7 ++++ .../TurboModule/SampleTurboModuleExample.js | 6 +--- 7 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleBindingsInstaller.h create mode 100644 packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleBindingsInstaller.mm diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h index 97348d0641624b..a426758a37f35c 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h @@ -154,9 +154,20 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { } // namespace facebook::react +@class RCTTurboModuleBindingsInstaller; + @protocol RCTTurboModule + - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params; + +@optional + +/** + * Implements this function if a TurboModule needs to install its own JSI bindings. + */ +- (RCTTurboModuleBindingsInstaller *)createBindingsInstaller; + @end /** diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleBindingsInstaller.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleBindingsInstaller.h new file mode 100644 index 00000000000000..4f46ea73a3a64f --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleBindingsInstaller.h @@ -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 + +#ifdef __cplusplus +#import +#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 diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleBindingsInstaller.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleBindingsInstaller.mm new file mode 100644 index 00000000000000..573f444c15e21b --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleBindingsInstaller.mm @@ -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 diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm index 94273910964e22..e092136899db4c 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm @@ -30,6 +30,7 @@ #import #import #import +#import #import #import #import @@ -187,6 +188,7 @@ static Class getFallbackClassFromName(const char *name) @implementation RCTTurboModuleManager { std::shared_ptr _jsInvoker; + facebook::jsi::Runtime *_runtime; __weak id _delegate; __weak RCTBridge *_bridge; @@ -705,6 +707,14 @@ - (BOOL)_shouldCreateObjCModule:(Class)moduleClass [(id)module setCallInvoker:callInvoker]; } + if ([module respondsToSelector:@selector(createBindingsInstaller)]) { + RCTTurboModuleBindingsInstaller *installer = + (RCTTurboModuleBindingsInstaller *)[module performSelector:@selector(createBindingsInstaller)]; + if (installer != nil && _runtime) { + installer.get(*_runtime); + } + } + /** * Some modules need their own queues, but don't provide any, so we need to create it for them. * These modules typically have the following: @@ -914,6 +924,8 @@ - (BOOL)_requiresMainQueueSetup:(Class)moduleClass - (void)installJSBindings:(facebook::jsi::Runtime &)runtime { + _runtime = &runtime; + /** * We keep TurboModuleManager alive until the JS VM is deleted. * It is perfectly valid to only use/create TurboModules from JS. @@ -1026,12 +1038,14 @@ - (void)bridgeDidInvalidateModules:(NSNotification *)notification } [self _invalidateModules]; + _runtime = nullptr; } - (void)invalidate { [self _enterInvalidatingState]; [self _invalidateModules]; + _runtime = nullptr; } - (void)_enterInvalidatingState diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.h index 76e080b0197e28..62d5771e4ae83a 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.h @@ -6,6 +6,7 @@ */ #import +#import #import "RCTNativeSampleTurboModuleSpec.h" @@ -15,4 +16,6 @@ */ @interface RCTSampleTurboModule : NSObject +- (RCTTurboModuleBindingsInstaller *)createBindingsInstaller; + @end diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm index 8a286dcfd33665..f2798da141c5f4 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm @@ -35,6 +35,13 @@ - (dispatch_queue_t)methodQueue return std::make_shared(params); } +- (RCTTurboModuleBindingsInstaller *)createBindingsInstaller; +{ + return [[RCTTurboModuleBindingsInstaller alloc] initWithBindingsInstaller:[](facebook::jsi::Runtime &runtime) { + runtime.global().setProperty(runtime, "__SampleTurboModuleJSIBindings", "Hello JSI!"); + }]; +} + // Backward compatible invalidation - (void)invalidate { diff --git a/packages/rn-tester/js/examples/TurboModule/SampleTurboModuleExample.js b/packages/rn-tester/js/examples/TurboModule/SampleTurboModuleExample.js index ac6f10662d64e7..6d6d4aeed910db 100644 --- a/packages/rn-tester/js/examples/TurboModule/SampleTurboModuleExample.js +++ b/packages/rn-tester/js/examples/TurboModule/SampleTurboModuleExample.js @@ -14,7 +14,6 @@ import styles from './TurboModuleExampleCommon'; import * as React from 'react'; import { FlatList, - Platform, RootTagContext, Text, TouchableOpacity, @@ -198,10 +197,7 @@ class SampleTurboModuleExample extends React.Component<{||}, State> { 'Cannot load this example because TurboModule is not configured.', ); } - if ( - global.__SampleTurboModuleJSIBindings == null && - Platform.OS === 'android' // TODO: Add iOS support - ) { + if (global.__SampleTurboModuleJSIBindings == null) { throw new Error( 'The JSI bindings for SampleTurboModule are not installed.', );