Skip to content

Commit

Permalink
Use runtime scheduler in the old architecture (#39057)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #39057

## Changelog:
[iOS][Changed] - Use the runtime scheduler in the old Architecture

## Facebook

Reviewed By: sammy-SC

Differential Revision: D48430129

fbshipit-source-id: ed1a1d27da531ba01b46afdd9d33213aea6bdeee
  • Loading branch information
cipolleschi authored and facebook-github-bot committed Aug 24, 2023
1 parent c0f2618 commit 2692f20
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 63 deletions.
19 changes: 14 additions & 5 deletions packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
*/

#import "RCTAppDelegate.h"
#import <React/RCTCxxBridgeDelegate.h>
#import <React/RCTRootView.h>
#import <React/RCTSurfacePresenterBridgeAdapter.h>
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
#import "RCTAppSetupUtils.h"
#import "RCTLegacyInteropComponents.h"

Expand All @@ -15,12 +18,10 @@
#import <React/RCTBundleURLProvider.h>
#import <React/RCTComponentViewFactory.h>
#import <React/RCTComponentViewProtocol.h>
#import <React/RCTCxxBridgeDelegate.h>
#import <React/RCTFabricSurface.h>
#import <React/RCTLegacyViewManagerInteropComponentView.h>
#import <React/RCTSurfaceHostingProxyRootView.h>
#import <React/RCTSurfacePresenter.h>
#import <React/RCTSurfacePresenterBridgeAdapter.h>
#import <ReactCommon/RCTContextContainerHandling.h>
#if USE_HERMES
#import <ReactCommon/RCTHermesInstance.h>
Expand All @@ -39,17 +40,20 @@

@interface RCTAppDelegate () <
RCTTurboModuleManagerDelegate,
RCTCxxBridgeDelegate,
RCTComponentViewFactoryComponentProvider,
RCTContextContainerHandling> {
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
facebook::react::ContextContainer::Shared _contextContainer;
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler;
}
@end

#endif

@interface RCTAppDelegate () <RCTCxxBridgeDelegate> {
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler;
}
@end

@implementation RCTAppDelegate {
#if RCT_NEW_ARCH_ENABLED
RCTHost *_reactHost;
Expand Down Expand Up @@ -173,11 +177,11 @@ - (BOOL)runtimeSchedulerEnabled
return YES;
}

#if RCT_NEW_ARCH_ENABLED
#pragma mark - RCTCxxBridgeDelegate
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
{
_runtimeScheduler = std::make_shared<facebook::react::RuntimeScheduler>(RCTRuntimeExecutorFromBridge(bridge));
#if RCT_NEW_ARCH_ENABLED
std::shared_ptr<facebook::react::CallInvoker> callInvoker =
std::make_shared<facebook::react::RuntimeSchedulerCallInvoker>(_runtimeScheduler);
RCTTurboModuleManager *turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
Expand All @@ -186,8 +190,13 @@ - (BOOL)runtimeSchedulerEnabled
_contextContainer->erase("RuntimeScheduler");
_contextContainer->insert("RuntimeScheduler", _runtimeScheduler);
return RCTAppSetupDefaultJsExecutorFactory(bridge, turboModuleManager, _runtimeScheduler);
#else
return RCTAppSetupJsExecutorFactoryForOldArch(bridge, _runtimeScheduler);
#endif
}

#if RCT_NEW_ARCH_ENABLED

#pragma mark - RCTTurboModuleManagerDelegate

- (Class)getModuleClassFromName:(const char *)name
Expand Down
10 changes: 8 additions & 2 deletions packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

#ifdef __cplusplus

#if RCT_NEW_ARCH_ENABLED
#import <memory>

#ifndef RCT_USE_HERMES
#if __has_include(<reacthermes/HermesExecutorFactory.h>)
Expand All @@ -27,21 +27,27 @@
#import <React/JSCExecutorFactory.h>
#endif

#if RCT_NEW_ARCH_ENABLED
#import <ReactCommon/RCTTurboModuleManager.h>
#endif

#if RCT_NEW_ARCH_ENABLED
// Forward declaration to decrease compilation coupling
namespace facebook::react {
class RuntimeScheduler;
}

#if RCT_NEW_ARCH_ENABLED

RCT_EXTERN id<RCTTurboModule> RCTAppSetupDefaultModuleFromClass(Class moduleClass);

std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupDefaultJsExecutorFactory(
RCTBridge *bridge,
RCTTurboModuleManager *turboModuleManager,
std::shared_ptr<facebook::react::RuntimeScheduler> const &runtimeScheduler);
#else
std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupJsExecutorFactoryForOldArch(
RCTBridge *bridge,
std::shared_ptr<facebook::react::RuntimeScheduler> const &runtimeScheduler);
#endif

#endif // __cplusplus
Expand Down
33 changes: 27 additions & 6 deletions packages/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

#import "RCTAppSetupUtils.h"

#import <React/RCTJSIExecutorRuntimeInstaller.h>
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
#import <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h>

#if RCT_NEW_ARCH_ENABLED
// Turbo Module
#import <React/CoreModulesPlugins.h>
Expand All @@ -16,14 +20,11 @@
#import <React/RCTGIFImageDecoder.h>
#import <React/RCTHTTPRequestHandler.h>
#import <React/RCTImageLoader.h>
#import <React/RCTJSIExecutorRuntimeInstaller.h>
#import <React/RCTNetworking.h>

// Fabric
#import <React/RCTFabricSurface.h>
#import <React/RCTSurfaceHostingProxyRootView.h>
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
#import <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h>
#endif

#ifdef FB_SONARKIT_ENABLED
Expand Down Expand Up @@ -120,13 +121,13 @@ void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled)
* NativeModule.
*/
[turboModuleManager moduleForName:"RCTDevMenu"];
#endif
#endif // end RCT_DEV

#if RCT_USE_HERMES
return std::make_unique<facebook::react::HermesExecutorFactory>(
#else
return std::make_unique<facebook::react::JSCExecutorFactory>(
#endif
#endif // end RCT_USE_HERMES
facebook::react::RCTJSIExecutorRuntimeInstaller(
[turboModuleManager, bridge, runtimeScheduler](facebook::jsi::Runtime &runtime) {
if (!bridge || !turboModuleManager) {
Expand All @@ -139,4 +140,24 @@ void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled)
}));
}

#endif
#else // else !RCT_NEW_ARCH_ENABLED

std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupJsExecutorFactoryForOldArch(
RCTBridge *bridge,
std::shared_ptr<facebook::react::RuntimeScheduler> const &runtimeScheduler)
{
#if RCT_USE_HERMES
return std::make_unique<facebook::react::HermesExecutorFactory>(
#else
return std::make_unique<facebook::react::JSCExecutorFactory>(
#endif // end RCT_USE_HERMES
facebook::react::RCTJSIExecutorRuntimeInstaller([bridge, runtimeScheduler](facebook::jsi::Runtime &runtime) {
if (!bridge) {
return;
}
if (runtimeScheduler) {
facebook::react::RuntimeSchedulerBinding::createAndInstallIfNeeded(runtime, runtimeScheduler);
}
}));
}
#endif // end RCT_NEW_ARCH_ENABLED
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ Pod::Spec.new do |s|
s.dependency "React-CoreModules"
s.dependency "React-nativeconfig"
s.dependency "React-runtimescheduler"
s.dependency "React-RCTFabric"

if is_new_arch_enabled
s.dependency "React-BridgelessCore"
Expand All @@ -110,7 +111,6 @@ Pod::Spec.new do |s|

if is_new_arch_enabled
s.dependency "React-Fabric"
s.dependency "React-RCTFabric"
s.dependency "React-graphics"
s.dependency "React-utils"
s.dependency "React-debug"
Expand Down
60 changes: 30 additions & 30 deletions packages/react-native/scripts/cocoapods/__tests__/codegen-test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenFileAlreadyExists_doNothing(

# Arrange
FileMock.mocked_existing_files([
@prefix + "/React/Fabric/" + @third_party_provider_header,
@prefix + "/React/Fabric/" + @third_party_provider_implementation,
@base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_header,
@base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_implementation,
])

# Act
Expand All @@ -58,8 +58,8 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenFileAlreadyExists_doNothing(
assert_equal(Pathname.pwd_invocation_count, 1)
assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1)
assert_equal(FileMock.exist_invocation_params, [
@prefix + "/React/Fabric/" + @third_party_provider_header,
@prefix + "/React/Fabric/" + @third_party_provider_implementation,
@base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_header,
@base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_implementation,
])
assert_equal(DirMock.exist_invocation_params, [])
assert_equal(Pod::UI.collected_messages, [])
Expand All @@ -84,7 +84,7 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenHeaderMissingAndCodegenMissi
assert_equal(Pathname.pwd_invocation_count, 1)
assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1)
assert_equal(FileMock.exist_invocation_params, [
@prefix + "/React/Fabric/" + @third_party_provider_header
@base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_header
])
assert_equal(DirMock.exist_invocation_params, [
@base_path + "/"+ @prefix + "/../react-native-codegen",
Expand All @@ -100,8 +100,8 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenImplementationMissingAndCode

# Arrange
FileMock.mocked_existing_files([
@prefix + "/React/Fabric/" + @third_party_provider_header,
@prefix + "/React/Fabric/tmpSchemaList.txt"
@base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_header,
@base_path + "/" + @prefix + "/React/Fabric/tmpSchemaList.txt"
])

DirMock.mocked_existing_dirs([
Expand All @@ -116,9 +116,9 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenImplementationMissingAndCode
assert_equal(Pathname.pwd_invocation_count, 1)
assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1)
assert_equal(FileMock.exist_invocation_params, [
@prefix + "/React/Fabric/" + @third_party_provider_header,
@prefix + "/React/Fabric/" + @third_party_provider_implementation,
@prefix + "/React/Fabric/tmpSchemaList.txt",
@base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_header,
@base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_implementation,
@base_path + "/" + @prefix + "/React/Fabric/tmpSchemaList.txt",
])
assert_equal(DirMock.exist_invocation_params, [
@base_path + "/"+ @prefix + "/../react-native-codegen",
Expand All @@ -127,20 +127,20 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenImplementationMissingAndCode
assert_equal(Pod::UI.collected_messages, ["[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider"])
assert_equal($collected_commands, [])
assert_equal(FileMock.open_invocation_count, 1)
assert_equal(FileMock.open_files_with_mode[@prefix + "/React/Fabric/tmpSchemaList.txt"], 'w')
assert_equal(FileMock.open_files_with_mode[@prefix + "/React/Fabric/tmpSchemaList.txt"], nil)
assert_equal(FileMock.open_files[0].collected_write, ["[]"])
assert_equal(FileMock.open_files[0].fsync_invocation_count, 1)
assert_equal(Pod::Executable.executed_commands[0], {
"command" => "node",
"arguments" => [
@base_path + "/" + @prefix + "/scripts/generate-provider-cli.js",
"--platform", 'ios',
"--schemaListPath", @prefix + "/React/Fabric/tmpSchemaList.txt",
"--outputDir", @prefix + "/React/Fabric"
"--schemaListPath", @base_path + "/" + @prefix + "/React/Fabric/tmpSchemaList.txt",
"--outputDir", @base_path + "/" + @prefix + "/React/Fabric"
]
})
assert_equal(FileMock.delete_invocation_count, 1)
assert_equal(FileMock.deleted_files, [ @prefix + "/React/Fabric/tmpSchemaList.txt"])
assert_equal(FileMock.deleted_files, [ @base_path + "/" + @prefix + "/React/Fabric/tmpSchemaList.txt"])
end

def testCheckAndGenerateEmptyThirdPartyProvider_whenBothMissing_buildCodegen()
Expand All @@ -156,8 +156,8 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenBothMissing_buildCodegen()
assert_equal(Pathname.pwd_invocation_count, 1)
assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1)
assert_equal(FileMock.exist_invocation_params, [
@prefix + "/React/Fabric/" + @third_party_provider_header,
@prefix + "/React/Fabric/" + @tmp_schema_list_file
@base_path + "/" + @prefix + "/React/Fabric/" + @third_party_provider_header,
@base_path + "/" + @prefix + "/React/Fabric/" + @tmp_schema_list_file
])
assert_equal(DirMock.exist_invocation_params, [
@base_path + "/" + @prefix + "/../react-native-codegen",
Expand All @@ -176,18 +176,18 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenBothMissing_buildCodegen()
"arguments" => [
@base_path + "/" + @prefix + "/scripts/generate-provider-cli.js",
"--platform", 'ios',
"--schemaListPath", @prefix + "/React/Fabric/" + @tmp_schema_list_file,
"--outputDir", @prefix + "/React/Fabric"
"--schemaListPath", @base_path + "/" + @prefix + "/React/Fabric/" + @tmp_schema_list_file,
"--outputDir", @base_path + "/" + @prefix + "/React/Fabric"
]
})
end

def testCheckAndGenerateEmptyThirdPartyProvider_withAbsoluteReactNativePath_buildCodegen()
# Arrange
rn_path = '/Users/distiller/react-native/packages/react-native'
rn_path = 'packages/react-native'
codegen_cli_path = rn_path + "/../@react-native/codegen"
DirMock.mocked_existing_dirs([
codegen_cli_path,
@base_path + "/" + codegen_cli_path,
])

# Act
Expand All @@ -197,28 +197,28 @@ def testCheckAndGenerateEmptyThirdPartyProvider_withAbsoluteReactNativePath_buil
assert_equal(Pathname.pwd_invocation_count, 1)
assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1)
assert_equal(FileMock.exist_invocation_params, [
rn_path + "/React/Fabric/" + @third_party_provider_header,
rn_path + "/React/Fabric/" + @tmp_schema_list_file
@base_path + "/" + rn_path + "/React/Fabric/" + @third_party_provider_header,
@base_path + "/" + rn_path + "/React/Fabric/" + @tmp_schema_list_file
])
assert_equal(DirMock.exist_invocation_params, [
rn_path + "/../react-native-codegen",
codegen_cli_path,
codegen_cli_path + "/lib",
@base_path + "/" + rn_path + "/../react-native-codegen",
@base_path + "/" + codegen_cli_path,
@base_path + "/" + codegen_cli_path + "/lib",
])
assert_equal(Pod::UI.collected_messages, [
"[Codegen] building #{codegen_cli_path}.",
"[Codegen] building #{@base_path + "/" + codegen_cli_path}.",
"[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider"
])
assert_equal($collected_commands, [rn_path + "/../@react-native/codegen/scripts/oss/build.sh"])
assert_equal($collected_commands, [@base_path + "/" + rn_path + "/../@react-native/codegen/scripts/oss/build.sh"])
assert_equal(FileMock.open_files[0].collected_write, ["[]"])
assert_equal(FileMock.open_files[0].fsync_invocation_count, 1)
assert_equal(Pod::Executable.executed_commands[0], {
"command" => "node",
"arguments" => [
rn_path + "/scripts/generate-provider-cli.js",
@base_path + "/" + rn_path + "/scripts/generate-provider-cli.js",
"--platform", 'ios',
"--schemaListPath", rn_path + "/React/Fabric/" + @tmp_schema_list_file,
"--outputDir", rn_path + "/React/Fabric"
"--schemaListPath", @base_path + "/" + rn_path + "/React/Fabric/" + @tmp_schema_list_file,
"--outputDir", @base_path + "/" + rn_path + "/React/Fabric"
]
})
end
Expand Down
14 changes: 1 addition & 13 deletions packages/react-native/scripts/cocoapods/__tests__/fabric-test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def teardown
# ================== #
# TEST - setupFabric #
# ================== #
def test_setupFabric_whenNewArchDisabled_installsPods
def test_setupFabric_installsPods
# Arrange
prefix = "../.."

Expand All @@ -33,18 +33,6 @@ def test_setupFabric_whenNewArchDisabled_installsPods
check_installed_pods(prefix)
end

def test_setupFabric_whenNewArchEnabled_installPods
# Arrange
prefix = "../.."
ENV['RCT_NEW_ARCH_ENABLED'] = "1"

# Act
setup_fabric!(:react_native_path => prefix, new_arch_enabled: true)

# Assert
check_installed_pods(prefix)
end

def check_installed_pods(prefix)
assert_equal(6, $podInvocationCount)

Expand Down
2 changes: 1 addition & 1 deletion packages/react-native/scripts/cocoapods/codegen.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def checkAndGenerateEmptyThirdPartyProvider!(react_native_path, new_arch_enabled

relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd)

output_dir = "#{react_native_path}/React/Fabric"
output_dir = "#{relative_installation_root}/#{react_native_path}/React/Fabric"

provider_h_path = "#{output_dir}/RCTThirdPartyFabricComponentsProvider.h"
provider_cpp_path ="#{output_dir}/RCTThirdPartyFabricComponentsProvider.mm"
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native/scripts/cocoapods/fabric.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# It sets up the Fabric dependencies.
#
# @parameter react_native_path: relative path to react-native
def setup_fabric!(react_native_path: "../node_modules/react-native", new_arch_enabled: false)
def setup_fabric!(react_native_path: "../node_modules/react-native")
pod 'React-Fabric', :path => "#{react_native_path}/ReactCommon"
pod 'React-graphics', :path => "#{react_native_path}/ReactCommon/react/renderer/graphics"
pod 'React-RCTFabric', :path => "#{react_native_path}/React", :modular_headers => true
Expand Down

0 comments on commit 2692f20

Please sign in to comment.