Skip to content

Commit 7211ef1

Browse files
sammy-SCfacebook-github-bot
authored andcommitted
Enable RuntimeScheduler in old architecture (#37523)
Summary: ## Changelog: [IOS] [FIXED] - unexpected useEffects flushing semantics Pull Request resolved: #37523 Test Plan: Run RNTester with old architecture and make sure RuntimeScheduler is used. Reviewed By: cipolleschi Differential Revision: D46078324 Pulled By: sammy-SC fbshipit-source-id: 5f18cbe60e6c9c753c373f175ba413b79288a928
1 parent b98de92 commit 7211ef1

30 files changed

+787
-261
lines changed

packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,41 @@
66
*/
77

88
#import "RCTAppDelegate.h"
9+
#import <React/RCTCxxBridgeDelegate.h>
910
#import <React/RCTRootView.h>
11+
#import <React/RCTRuntimeExecutorFromBridge.h>
12+
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
13+
1014
#import "RCTAppSetupUtils.h"
1115

1216
#if RCT_NEW_ARCH_ENABLED
1317
#import <React/CoreModulesPlugins.h>
1418
#import <React/RCTComponentViewFactory.h>
1519
#import <React/RCTComponentViewProtocol.h>
16-
#import <React/RCTCxxBridgeDelegate.h>
1720
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
1821
#import <React/RCTLegacyViewManagerInteropComponentView.h>
1922
#import <React/RCTSurfacePresenter.h>
2023
#import <React/RCTSurfacePresenterBridgeAdapter.h>
2124
#import <ReactCommon/RCTTurboModuleManager.h>
2225
#import <react/config/ReactNativeConfig.h>
23-
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
2426
#import <react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.h>
2527
#import "RCTLegacyInteropComponents.h"
2628

2729
static NSString *const kRNConcurrentRoot = @"concurrentRoot";
2830

29-
@interface RCTAppDelegate () <
30-
RCTTurboModuleManagerDelegate,
31-
RCTCxxBridgeDelegate,
32-
RCTComponentViewFactoryComponentProvider> {
31+
@interface RCTAppDelegate () <RCTTurboModuleManagerDelegate, RCTComponentViewFactoryComponentProvider> {
3332
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
3433
facebook::react::ContextContainer::Shared _contextContainer;
35-
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler;
3634
}
3735
@end
3836

3937
#endif
4038

39+
@interface RCTAppDelegate () <RCTCxxBridgeDelegate> {
40+
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler;
41+
}
42+
@end
43+
4144
@implementation RCTAppDelegate
4245

4346
#if RCT_NEW_ARCH_ENABLED
@@ -129,11 +132,11 @@ - (UIViewController *)createRootViewController
129132
return [UIViewController new];
130133
}
131134

132-
#if RCT_NEW_ARCH_ENABLED
133135
#pragma mark - RCTCxxBridgeDelegate
134136
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
135137
{
136138
_runtimeScheduler = std::make_shared<facebook::react::RuntimeScheduler>(RCTRuntimeExecutorFromBridge(bridge));
139+
#if RCT_NEW_ARCH_ENABLED
137140
std::shared_ptr<facebook::react::CallInvoker> callInvoker =
138141
std::make_shared<facebook::react::RuntimeSchedulerCallInvoker>(_runtimeScheduler);
139142
RCTTurboModuleManager *turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
@@ -142,8 +145,13 @@ - (UIViewController *)createRootViewController
142145
_contextContainer->erase("RuntimeScheduler");
143146
_contextContainer->insert("RuntimeScheduler", _runtimeScheduler);
144147
return RCTAppSetupDefaultJsExecutorFactory(bridge, turboModuleManager, _runtimeScheduler);
148+
#else
149+
return RCTAppSetupJsExecutorFactoryForOldArch(bridge, _runtimeScheduler);
150+
#endif
145151
}
146152

153+
#if RCT_NEW_ARCH_ENABLED
154+
147155
#pragma mark - RCTTurboModuleManagerDelegate
148156

149157
- (Class)getModuleClassFromName:(const char *)name

packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
#ifdef __cplusplus
1313

14-
#if RCT_NEW_ARCH_ENABLED
14+
#import <memory>
1515

1616
#ifndef RCT_USE_HERMES
1717
#if __has_include(<reacthermes/HermesExecutorFactory.h>)
@@ -27,21 +27,27 @@
2727
#import <React/JSCExecutorFactory.h>
2828
#endif
2929

30+
#if RCT_NEW_ARCH_ENABLED
3031
#import <ReactCommon/RCTTurboModuleManager.h>
3132
#endif
3233

33-
#if RCT_NEW_ARCH_ENABLED
3434
// Forward declaration to decrease compilation coupling
3535
namespace facebook::react {
3636
class RuntimeScheduler;
3737
}
3838

39+
#if RCT_NEW_ARCH_ENABLED
3940
RCT_EXTERN id<RCTTurboModule> RCTAppSetupDefaultModuleFromClass(Class moduleClass);
4041

4142
std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupDefaultJsExecutorFactory(
4243
RCTBridge *bridge,
4344
RCTTurboModuleManager *turboModuleManager,
4445
std::shared_ptr<facebook::react::RuntimeScheduler> const &runtimeScheduler);
46+
47+
#else
48+
std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupJsExecutorFactoryForOldArch(
49+
RCTBridge *bridge,
50+
std::shared_ptr<facebook::react::RuntimeScheduler> const &runtimeScheduler);
4551
#endif
4652

4753
#endif // __cplusplus

packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77

88
#import "RCTAppSetupUtils.h"
99

10+
#import <React/RCTJSIExecutorRuntimeInstaller.h>
11+
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
12+
#import <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h>
13+
1014
#if RCT_NEW_ARCH_ENABLED
1115
// Turbo Module
1216
#import <React/CoreModulesPlugins.h>
@@ -15,7 +19,6 @@
1519
#import <React/RCTGIFImageDecoder.h>
1620
#import <React/RCTHTTPRequestHandler.h>
1721
#import <React/RCTImageLoader.h>
18-
#import <React/RCTJSIExecutorRuntimeInstaller.h>
1922
#import <React/RCTLocalAssetImageLoader.h>
2023
#import <React/RCTNetworking.h>
2124

@@ -135,4 +138,25 @@ void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled)
135138
}));
136139
}
137140

141+
#else
142+
143+
std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupJsExecutorFactoryForOldArch(
144+
RCTBridge *bridge,
145+
std::shared_ptr<facebook::react::RuntimeScheduler> const &runtimeScheduler)
146+
{
147+
#if RCT_USE_HERMES
148+
return std::make_unique<facebook::react::HermesExecutorFactory>(
149+
#else
150+
return std::make_unique<facebook::react::JSCExecutorFactory>(
151+
#endif
152+
facebook::react::RCTJSIExecutorRuntimeInstaller([bridge, runtimeScheduler](facebook::jsi::Runtime &runtime) {
153+
if (!bridge) {
154+
return;
155+
}
156+
if (runtimeScheduler) {
157+
facebook::react::RuntimeSchedulerBinding::createAndInstallIfNeeded(runtime, runtimeScheduler);
158+
}
159+
}));
160+
}
161+
138162
#endif

packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ header_search_paths = [
4848
"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core",
4949
"$(PODS_CONFIGURATION_BUILD_DIR)/React-NativeModulesApple/React_NativeModulesApple.framework/Headers",
5050
"$(PODS_CONFIGURATION_BUILD_DIR)/React-RCTFabric/RCTFabric.framework/Headers/",
51+
"$(PODS_CONFIGURATION_BUILD_DIR)/React-utils/React_utils.framework/Headers/",
52+
"$(PODS_CONFIGURATION_BUILD_DIR)/React-debug/React_debug.framework/Headers/",
53+
"$(PODS_CONFIGURATION_BUILD_DIR)/React-runtimescheduler/React_runtimescheduler.framework/Headers/",
5154
] : []).map{|p| "\"#{p}\""}.join(" ")
5255

5356
Pod::Spec.new do |s|
@@ -80,6 +83,7 @@ Pod::Spec.new do |s|
8083
s.dependency "React-RCTImage"
8184
s.dependency "React-NativeModulesApple"
8285
s.dependency "React-CoreModules"
86+
s.dependency "React-runtimescheduler"
8387

8488
if ENV['USE_HERMES'] == nil || ENV['USE_HERMES'] == "1"
8589
s.dependency "React-hermes"
@@ -91,6 +95,8 @@ Pod::Spec.new do |s|
9195
s.dependency "React-Fabric"
9296
s.dependency "React-RCTFabric"
9397
s.dependency "React-graphics"
98+
s.dependency "React-utils"
99+
s.dependency "React-debug"
94100

95101
s.script_phases = {
96102
:name => "Generate Legacy Components Interop",

packages/react-native/React-Core.podspec

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,13 @@ Pod::Spec.new do |s|
126126
end
127127

128128
s.dependency "RCT-Folly", folly_version
129-
s.dependency "React-cxxreact", version
130-
s.dependency "React-perflogger", version
131-
s.dependency "React-jsi", version
132-
s.dependency "React-jsiexecutor", version
129+
s.dependency "React-cxxreact"
130+
s.dependency "React-perflogger"
131+
s.dependency "React-jsi"
132+
s.dependency "React-jsiexecutor"
133+
s.dependency "React-utils"
133134
s.dependency "SocketRocket", socket_rocket_version
135+
s.dependency "React-runtimeexecutor"
134136
s.dependency "Yoga"
135137
s.dependency "glog"
136138

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import <Foundation/Foundation.h>
9+
#ifdef __cplusplus
10+
#import <ReactCommon/RuntimeExecutor.h>
11+
12+
NS_ASSUME_NONNULL_BEGIN
13+
14+
@class RCTBridge;
15+
16+
facebook::react::RuntimeExecutor RCTRuntimeExecutorFromBridge(RCTBridge *bridge);
17+
18+
NS_ASSUME_NONNULL_END
19+
#endif
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import "RCTRuntimeExecutorFromBridge.h"
9+
#import <React/RCTAssert.h>
10+
#import <React/RCTBridge+Private.h>
11+
#import <cxxreact/MessageQueueThread.h>
12+
#import <react/utils/ManagedObjectWrapper.h>
13+
14+
using namespace facebook::react;
15+
16+
@interface RCTBridge ()
17+
- (std::shared_ptr<MessageQueueThread>)jsMessageThread;
18+
- (void)invokeAsync:(std::function<void()> &&)func;
19+
@end
20+
21+
RuntimeExecutor RCTRuntimeExecutorFromBridge(RCTBridge *bridge)
22+
{
23+
RCTAssert(bridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil.");
24+
25+
auto bridgeWeakWrapper = wrapManagedObjectWeakly([bridge batchedBridge] ?: bridge);
26+
27+
RuntimeExecutor runtimeExecutor = [bridgeWeakWrapper](
28+
std::function<void(facebook::jsi::Runtime & runtime)> &&callback) {
29+
RCTBridge *bridge = unwrapManagedObjectWeakly(bridgeWeakWrapper);
30+
31+
RCTAssert(bridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil at the moment of scheduling a call.");
32+
33+
[bridge invokeAsync:[bridgeWeakWrapper, callback = std::move(callback)]() {
34+
RCTCxxBridge *batchedBridge = (RCTCxxBridge *)unwrapManagedObjectWeakly(bridgeWeakWrapper);
35+
36+
RCTAssert(batchedBridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil at the moment of invocation.");
37+
38+
if (!batchedBridge) {
39+
return;
40+
}
41+
42+
auto runtime = (facebook::jsi::Runtime *)(batchedBridge.runtime);
43+
44+
RCTAssert(
45+
runtime, @"RCTRuntimeExecutorFromBridge: Bridge must have a valid jsi::Runtime at the moment of invocation.");
46+
47+
if (!runtime) {
48+
return;
49+
}
50+
51+
callback(*runtime);
52+
}];
53+
};
54+
55+
return runtimeExecutor;
56+
}

packages/react-native/React/Fabric/RCTSurfacePresenterBridgeAdapter.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
*/
77

88
#import <Foundation/Foundation.h>
9-
#import <ReactCommon/RuntimeExecutor.h>
109
#import <UIKit/UIKit.h>
1110
#import <react/utils/ContextContainer.h>
1211

@@ -15,8 +14,6 @@ NS_ASSUME_NONNULL_BEGIN
1514
@class RCTSurfacePresenter;
1615
@class RCTBridge;
1716

18-
facebook::react::RuntimeExecutor RCTRuntimeExecutorFromBridge(RCTBridge *bridge);
19-
2017
/*
2118
* Controls a life-cycle of a Surface Presenter based on Bridge's life-cycle.
2219
* We are moving away from using Bridge.

packages/react-native/React/Fabric/RCTSurfacePresenterBridgeAdapter.mm

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#import <React/RCTConstants.h>
1616
#import <React/RCTImageLoader.h>
1717
#import <React/RCTImageLoaderWithAttributionProtocol.h>
18+
#import <React/RCTRuntimeExecutorFromBridge.h>
1819
#import <React/RCTSurfacePresenter.h>
1920
#import <React/RCTSurfacePresenterStub.h>
2021

@@ -42,43 +43,6 @@ - (void)invokeAsync:(std::function<void()> &&)func;
4243
return contextContainer;
4344
}
4445

45-
RuntimeExecutor RCTRuntimeExecutorFromBridge(RCTBridge *bridge)
46-
{
47-
RCTAssert(bridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil.");
48-
49-
auto bridgeWeakWrapper = wrapManagedObjectWeakly([bridge batchedBridge] ?: bridge);
50-
51-
RuntimeExecutor runtimeExecutor = [bridgeWeakWrapper](
52-
std::function<void(facebook::jsi::Runtime & runtime)> &&callback) {
53-
RCTBridge *bridge = unwrapManagedObjectWeakly(bridgeWeakWrapper);
54-
55-
RCTAssert(bridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil at the moment of scheduling a call.");
56-
57-
[bridge invokeAsync:[bridgeWeakWrapper, callback = std::move(callback)]() {
58-
RCTCxxBridge *batchedBridge = (RCTCxxBridge *)unwrapManagedObjectWeakly(bridgeWeakWrapper);
59-
60-
RCTAssert(batchedBridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil at the moment of invocation.");
61-
62-
if (!batchedBridge) {
63-
return;
64-
}
65-
66-
auto runtime = (facebook::jsi::Runtime *)(batchedBridge.runtime);
67-
68-
RCTAssert(
69-
runtime, @"RCTRuntimeExecutorFromBridge: Bridge must have a valid jsi::Runtime at the moment of invocation.");
70-
71-
if (!runtime) {
72-
return;
73-
}
74-
75-
callback(*runtime);
76-
}];
77-
};
78-
79-
return runtimeExecutor;
80-
}
81-
8246
@implementation RCTSurfacePresenterBridgeAdapter {
8347
RCTSurfacePresenter *_Nullable _surfacePresenter;
8448
__weak RCTBridge *_bridge;

packages/react-native/React/React-RCTFabric.podspec

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ header_search_paths = [
3030
"\"$(PODS_ROOT)/Headers/Private/Yoga\"",
3131
"\"$(PODS_ROOT)/Headers/Public/React-Codegen\"",
3232
"\"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"",
33-
3433
]
3534

3635
if ENV['USE_FRAMEWORKS']
@@ -43,6 +42,9 @@ if ENV['USE_FRAMEWORKS']
4342
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\""
4443
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-ImageManager/React_ImageManager.framework/Headers\""
4544
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\""
45+
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\""
46+
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\""
47+
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-runtimescheduler/React_runtimescheduler.framework/Headers\""
4648
end
4749

4850
Pod::Spec.new do |s|
@@ -79,6 +81,8 @@ Pod::Spec.new do |s|
7981
s.dependency "Yoga"
8082
s.dependency "React-RCTText"
8183
s.dependency "React-FabricImage"
84+
s.dependency "React-utils"
85+
s.dependency "React-runtimescheduler"
8286

8387
if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1"
8488
s.dependency "hermes-engine"

0 commit comments

Comments
 (0)