diff --git a/packages/react-native/React/Base/RCTRuntimeExecutionModule.h b/packages/react-native/React/Base/RCTRuntimeExecutionModule.h new file mode 100644 index 00000000000000..32a4fdecdfb63f --- /dev/null +++ b/packages/react-native/React/Base/RCTRuntimeExecutionModule.h @@ -0,0 +1,18 @@ +/* + * 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. + */ + +@class RCTRuntimeExecutorProvider; + +/** + * Have your module conform to this protocol to access the RuntimeExecutor. + * Only available in the bridgeless runtime. + */ +@protocol RCTRuntimeExecutionModule + +@property (nonatomic, nullable, readwrite) RCTRuntimeExecutorProvider *runtimeExecutorProvider; + +@end diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTRuntimeExecutorProvider.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTRuntimeExecutorProvider.h new file mode 100644 index 00000000000000..de27bd045544fd --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTRuntimeExecutorProvider.h @@ -0,0 +1,31 @@ +/* + * 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 +#import + +typedef void (^RCTJSIRuntimeHandlingBlock)(facebook::jsi::Runtime &runtime); +typedef void (^RCTRuntimeExecutor)(_Nonnull RCTJSIRuntimeHandlingBlock); + +NS_ASSUME_NONNULL_BEGIN + +@interface RCTRuntimeExecutorProvider : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + Initializes an object that wraps ways to access the RuntimeExecutor. + + @param runtimeExecutorBlock A block that provides thread-safe access to jsi::runtime. + */ +- (instancetype)initWithRuntimeExecutor:(facebook::react::RuntimeExecutor)runtimeExecutor NS_DESIGNATED_INITIALIZER; + +- (RCTRuntimeExecutor)runtimeExecutor; + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTRuntimeExecutorProvider.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTRuntimeExecutorProvider.mm new file mode 100644 index 00000000000000..1ee0ccd563974e --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTRuntimeExecutorProvider.mm @@ -0,0 +1,38 @@ +/* + * 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 "RCTRuntimeExecutorProvider.h" + +@implementation RCTRuntimeExecutorProvider { + facebook::react::RuntimeExecutor _runtimeExecutor; +} + +#pragma mark - Initializer + +- (instancetype)initWithRuntimeExecutor:(facebook::react::RuntimeExecutor)runtimeExecutor +{ + if (self = [super init]) { + _runtimeExecutor = runtimeExecutor; + } + + return self; +} + +#pragma mark - Public API + +- (RCTRuntimeExecutor)runtimeExecutor +{ + __weak __typeof(self) weakSelf = self; + return ^(RCTJSIRuntimeHandlingBlock block) { + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf && strongSelf->_runtimeExecutor) { + strongSelf->_runtimeExecutor([=](facebook::jsi::Runtime &runtime) { block(runtime); }); + } + }; +} + +@end diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h index 1ef120d83dced6..014745be16d1ee 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h @@ -15,8 +15,11 @@ #import #import #import + #import "RCTTurboModule.h" +@class RCTTurboModuleManager; + @protocol RCTTurboModuleManagerDelegate /** @@ -52,6 +55,12 @@ @end +@protocol RCTTurboModuleManagerRuntimeHandler + +- (facebook::react::RuntimeExecutor)runtimeExecutorForTurboModuleManager:(RCTTurboModuleManager *)turboModuleManager; + +@end + @interface RCTTurboModuleManager : NSObject - (instancetype)initWithBridge:(RCTBridge *)bridge @@ -67,4 +76,6 @@ - (void)invalidate; +@property (nonatomic, weak, readwrite) id runtimeHandler; + @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 997737d1a0c387..14c0621a4098eb 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 @@ -7,6 +7,7 @@ #import "RCTTurboModuleManager.h" #import "RCTInteropTurboModule.h" +#import "RCTRuntimeExecutorProvider.h" #import #import @@ -24,8 +25,8 @@ #import #import #import +#import #import -#import #import #import #import @@ -676,6 +677,13 @@ - (BOOL)_shouldCreateObjCModule:(Class)moduleClass } } + // This is a more performant alternative for conformsToProtocol:@protocol(RCTRuntimeExecutionModule) + if ([module respondsToSelector:@selector(setRuntimeExecutorProvider:)]) { + RCTRuntimeExecutorProvider *runtimeExecutorProvider = [[RCTRuntimeExecutorProvider alloc] + initWithRuntimeExecutor:[_runtimeHandler runtimeExecutorForTurboModuleManager:self]]; + [(id)module setRuntimeExecutorProvider:runtimeExecutorProvider]; + } + /** * 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: diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm index 6a5644353bb4eb..9aaef33e9afa89 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm @@ -63,7 +63,7 @@ void RCTInstanceSetRuntimeDiagnosticFlags(NSString *flags) sRuntimeDiagnosticFlags = [flags copy]; } -@interface RCTInstance () +@interface RCTInstance () @end @implementation RCTInstance { @@ -208,6 +208,17 @@ - (Class)getModuleClassFromName:(const char *)name return nullptr; } +#pragma mark - RCTTurboModuleManagerRuntimeHandler + +- (RuntimeExecutor)runtimeExecutorForTurboModuleManager:(RCTTurboModuleManager *)turboModuleManager +{ + if (_valid) { + return _reactInstance->getBufferedRuntimeExecutor(); + } + + return nullptr; +} + #pragma mark - Private - (void)_start @@ -259,6 +270,7 @@ - (void)_start bridgeModuleDecorator:_bridgeModuleDecorator delegate:self jsInvoker:std::make_shared(bufferedRuntimeExecutor)]; + _turboModuleManager.runtimeHandler = self; #if RCT_DEV /**