diff --git a/React/Fabric/RCTScheduler.h b/React/Fabric/RCTScheduler.h index bebdaedcfe8..a48ef1f0592 100644 --- a/React/Fabric/RCTScheduler.h +++ b/React/Fabric/RCTScheduler.h @@ -14,6 +14,7 @@ #import #import #import +#import #import NS_ASSUME_NONNULL_BEGIN @@ -36,8 +37,7 @@ NS_ASSUME_NONNULL_BEGIN @property (atomic, weak, nullable) id delegate; -- (instancetype)initWithContextContainer:(facebook::react::ContextContainer::Shared)contextContatiner - componentRegistryFactory:(facebook::react::ComponentRegistryFactory)componentRegistryFactory; +- (instancetype)initWithToolbox:(facebook::react::SchedulerToolbox)toolbox; - (void)startSurfaceWithSurfaceId:(facebook::react::SurfaceId)surfaceId moduleName:(NSString *)moduleName diff --git a/React/Fabric/RCTScheduler.mm b/React/Fabric/RCTScheduler.mm index 185e012fed6..a21051f04fb 100644 --- a/React/Fabric/RCTScheduler.mm +++ b/React/Fabric/RCTScheduler.mm @@ -43,12 +43,11 @@ class SchedulerDelegateProxy : public SchedulerDelegate { std::shared_ptr _delegateProxy; } -- (instancetype)initWithContextContainer:(ContextContainer::Shared)contextContainer - componentRegistryFactory:(ComponentRegistryFactory)componentRegistryFactory +- (instancetype)initWithToolbox:(facebook::react::SchedulerToolbox)toolbox { if (self = [super init]) { _delegateProxy = std::make_shared((__bridge void *)self); - _scheduler = std::make_shared(contextContainer, componentRegistryFactory); + _scheduler = std::make_shared(toolbox); _scheduler->setDelegate(_delegateProxy.get()); } diff --git a/React/Fabric/RCTSurfacePresenter.mm b/React/Fabric/RCTSurfacePresenter.mm index 06c8c5cab72..0892963a39b 100644 --- a/React/Fabric/RCTSurfacePresenter.mm +++ b/React/Fabric/RCTSurfacePresenter.mm @@ -31,6 +31,7 @@ #import #import #import +#import #import #import @@ -203,8 +204,22 @@ using namespace facebook::react; createComponentDescriptorRegistryWithParameters:{eventDispatcher, contextContainer}]; }; - _scheduler = [[RCTScheduler alloc] initWithContextContainer:self.contextContainer - componentRegistryFactory:componentRegistryFactory]; + auto runtimeExecutor = [self _runtimeExecutor]; + + auto toolbox = SchedulerToolbox{}; + toolbox.contextContainer = _contextContainer; + toolbox.componentRegistryFactory = componentRegistryFactory; + toolbox.runtimeExecutor = runtimeExecutor; + + toolbox.synchronousEventBeatFactory = [runtimeExecutor]() { + return std::make_unique(runtimeExecutor); + }; + + toolbox.asynchronousEventBeatFactory = [runtimeExecutor]() { + return std::make_unique(runtimeExecutor); + }; + + _scheduler = [[RCTScheduler alloc] initWithToolbox:toolbox]; _scheduler.delegate = self; return _scheduler; @@ -212,18 +227,8 @@ using namespace facebook::react; @synthesize contextContainer = _contextContainer; -- (ContextContainer::Shared)contextContainer +- (RuntimeExecutor)_runtimeExecutor { - std::lock_guard lock(_contextContainerMutex); - - if (_contextContainer) { - return _contextContainer; - } - - _contextContainer = std::make_shared(); - - _contextContainer->registerInstance(_reactNativeConfig, "ReactNativeConfig"); - auto messageQueueThread = _batchedBridge.jsMessageThread; if (messageQueueThread) { // Make sure initializeBridge completed @@ -239,20 +244,25 @@ using namespace facebook::react; [((RCTCxxBridge *)_batchedBridge) invokeAsync:[runtime, callback = std::move(callback)]() { callback(*runtime); }]; }; - EventBeatFactory synchronousBeatFactory = [runtimeExecutor]() { - return std::make_unique(runtimeExecutor); - }; + return runtimeExecutor; +} - EventBeatFactory asynchronousBeatFactory = [runtimeExecutor]() { - return std::make_unique(runtimeExecutor); - }; +- (ContextContainer::Shared)contextContainer +{ + std::lock_guard lock(_contextContainerMutex); - _contextContainer->registerInstance(synchronousBeatFactory, "synchronous"); - _contextContainer->registerInstance(asynchronousBeatFactory, "asynchronous"); - - _contextContainer->registerInstance(runtimeExecutor, "runtime-executor"); + if (_contextContainer) { + return _contextContainer; + } + _contextContainer = std::make_shared(); + // Please do not add stuff here; `SurfacePresenter` must not alter `ContextContainer`. + // Those two pieces eventually should be moved out there: + // * `RCTImageLoader` should be moved to `RNImageComponentView`. + // * `ReactNativeConfig` should be set by outside product code. + _contextContainer->registerInstance(_reactNativeConfig, "ReactNativeConfig"); _contextContainer->registerInstance(wrapManagedObject([_bridge imageLoader]), "RCTImageLoader"); + return _contextContainer; } @@ -390,7 +400,6 @@ using namespace facebook::react; { std::lock_guard lock(_schedulerMutex); _scheduler = nil; - _contextContainer = nil; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp index e38edd549d7..9d2a6c12cac 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -136,16 +137,15 @@ void Binding::installFabricUIManager( std::shared_ptr config = std::make_shared(reactNativeConfig); contextContainer->registerInstance(config, "ReactNativeConfig"); - contextContainer->registerInstance( - synchronousBeatFactory, "synchronous"); - contextContainer->registerInstance( - asynchronousBeatFactory, "asynchronous"); contextContainer->registerInstance(javaUIManager_, "FabricUIManager"); - contextContainer->registerInstance(runtimeExecutor, "runtime-executor"); - - scheduler_ = std::make_shared( - contextContainer, componentsRegistry->buildRegistryFunction); + auto toolbox = SchedulerToolbox{}; + toolbox.contextContainer = contextContainer; + toolbox.componentRegistryFactory = componentsRegistry->buildRegistryFunction; + toolbox.runtimeExecutor = runtimeExecutor; + toolbox.synchronousEventBeatFactory = synchronousBeatFactory; + toolbox.asynchronousEventBeatFactory = asynchronousBeatFactory; + scheduler_ = std::make_shared(toolbox); scheduler_->setDelegate(this); } diff --git a/ReactCommon/fabric/uimanager/Scheduler.cpp b/ReactCommon/fabric/uimanager/Scheduler.cpp index aab1121d934..1eb3fcd969f 100644 --- a/ReactCommon/fabric/uimanager/Scheduler.cpp +++ b/ReactCommon/fabric/uimanager/Scheduler.cpp @@ -18,19 +18,11 @@ namespace facebook { namespace react { -Scheduler::Scheduler( - ContextContainer::Shared const &contextContainer, - ComponentRegistryFactory buildRegistryFunction) { - const auto asynchronousEventBeatFactory = - contextContainer->getInstance("asynchronous"); - const auto synchronousEventBeatFactory = - contextContainer->getInstance("synchronous"); - - runtimeExecutor_ = - contextContainer->getInstance("runtime-executor"); +Scheduler::Scheduler(SchedulerToolbox schedulerToolbox) { + runtimeExecutor_ = schedulerToolbox.runtimeExecutor; reactNativeConfig_ = - contextContainer->getInstance>( + schedulerToolbox.contextContainer->getInstance>( "ReactNativeConfig"); auto uiManager = std::make_unique(); @@ -55,11 +47,11 @@ Scheduler::Scheduler( auto eventDispatcher = std::make_shared( eventPipe, statePipe, - synchronousEventBeatFactory, - asynchronousEventBeatFactory); + schedulerToolbox.synchronousEventBeatFactory, + schedulerToolbox.asynchronousEventBeatFactory); - componentDescriptorRegistry_ = - buildRegistryFunction(eventDispatcher, contextContainer); + componentDescriptorRegistry_ = schedulerToolbox.componentRegistryFactory( + eventDispatcher, schedulerToolbox.contextContainer); rootComponentDescriptor_ = std::make_unique(eventDispatcher); @@ -72,7 +64,7 @@ Scheduler::Scheduler( UIManagerBinding::install(runtime, uiManagerBinding_); }); - contextContainer->registerInstance( + schedulerToolbox.contextContainer->registerInstance( std::weak_ptr( componentDescriptorRegistry_), "ComponentDescriptorRegistry_DO_NOT_USE_PRETTY_PLEASE"); diff --git a/ReactCommon/fabric/uimanager/Scheduler.h b/ReactCommon/fabric/uimanager/Scheduler.h index ea4469ac3ed..6cd4322501c 100644 --- a/ReactCommon/fabric/uimanager/Scheduler.h +++ b/ReactCommon/fabric/uimanager/Scheduler.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -31,9 +32,7 @@ namespace react { */ class Scheduler final : public UIManagerDelegate, public ShadowTreeDelegate { public: - Scheduler( - ContextContainer::Shared const &contextContainer, - ComponentRegistryFactory buildRegistryFunction); + Scheduler(SchedulerToolbox schedulerToolbox); ~Scheduler(); #pragma mark - Surface Management diff --git a/ReactCommon/fabric/uimanager/SchedulerToolbox.cpp b/ReactCommon/fabric/uimanager/SchedulerToolbox.cpp new file mode 100644 index 00000000000..c02009d00d3 --- /dev/null +++ b/ReactCommon/fabric/uimanager/SchedulerToolbox.cpp @@ -0,0 +1,6 @@ +// Copyright (c) Facebook, Inc. and its affiliates. + +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +#include "SchedulerToolbox.h" diff --git a/ReactCommon/fabric/uimanager/SchedulerToolbox.h b/ReactCommon/fabric/uimanager/SchedulerToolbox.h new file mode 100644 index 00000000000..083609c6ad9 --- /dev/null +++ b/ReactCommon/fabric/uimanager/SchedulerToolbox.h @@ -0,0 +1,47 @@ +// Copyright (c) Facebook, Inc. and its affiliates. + +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include +#include +#include + +namespace facebook { +namespace react { + +/* + * Contains all external dependencies of Scheduler. + * Copyable. + */ +struct SchedulerToolbox final { + /* + * Represents general purpose DI container for product components/needs. + * Must not be `nullptr`. + */ + ContextContainer::Shared contextContainer; + + /* + * Represents externally managed, lazily available collection of components. + */ + ComponentRegistryFactory componentRegistryFactory; + + /* + * Represents running JavaScript VM and associated execution queue. + */ + RuntimeExecutor runtimeExecutor; + + /* + * Asynchronous & synchronous event beats. + * Represent connections with the platform-specific run loops and general + * purpose background queue. + */ + EventBeatFactory asynchronousEventBeatFactory; + EventBeatFactory synchronousEventBeatFactory; +}; + +} // namespace react +} // namespace facebook