diff --git a/packages/react-native/React/Base/RCTRuntimeExecutorModule.h b/packages/react-native/React/Base/RCTRuntimeExecutorModule.h new file mode 100644 index 00000000000000..fd05fe2c54e123 --- /dev/null +++ b/packages/react-native/React/Base/RCTRuntimeExecutorModule.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 RCTRuntimeExecutor; + +/** + * Have your module conform to this protocol to access the RuntimeExecutor. + * Only available in the bridgeless runtime. + */ +@protocol RCTRuntimeExecutorModule + +@property (nonatomic, nullable, readwrite) RCTRuntimeExecutor *runtimeExecutor; + +@end diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTRuntimeExecutor.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTRuntimeExecutor.h new file mode 100644 index 00000000000000..191e94f3b0ddbd --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTRuntimeExecutor.h @@ -0,0 +1,30 @@ +/* + * 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 + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^RCTJSIRuntimeHandlingBlock)(facebook::jsi::Runtime &runtime); + +@interface RCTRuntimeExecutor : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + Initializes an object that wraps ways to access the RuntimeExecutor. + + @param runtimeExecutor The instance of RuntimeExecutor. + */ +- (instancetype)initWithRuntimeExecutor:(facebook::react::RuntimeExecutor)runtimeExecutor NS_DESIGNATED_INITIALIZER; + +- (void)execute:(RCTJSIRuntimeHandlingBlock)block; + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTRuntimeExecutor.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTRuntimeExecutor.mm new file mode 100644 index 00000000000000..87538efb0d9148 --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTRuntimeExecutor.mm @@ -0,0 +1,34 @@ +/* + * 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 "RCTRuntimeExecutor.h" + +@implementation RCTRuntimeExecutor { + 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 + +- (void)execute:(RCTJSIRuntimeHandlingBlock)block +{ + if (_runtimeExecutor) { + _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..09ea2122987fce 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 "RCTRuntimeExecutor.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(RCTRuntimeExecutorModule) + if ([module respondsToSelector:@selector(setRuntimeExecutor:)]) { + RCTRuntimeExecutor *runtimeExecutor = [[RCTRuntimeExecutor alloc] + initWithRuntimeExecutor:[_runtimeHandler runtimeExecutorForTurboModuleManager:self]]; + [(id)module setRuntimeExecutor:runtimeExecutor]; + } + /** * 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 /**