mirror of
https://github.com/status-im/react-native.git
synced 2025-02-21 13:48:13 +00:00
Fabric: Start/stop Surface calls were moved down to C++ layer
Summary: There is no need to make JS calls to start or stop React Native apps; Scheduler does it automatically. Yay! With this change (because we have to change Scheduler API) we are starting slow process migrating away from using term `reactRootTag` when we refer to running a ReactNative app (aka Surface). We will use `surfaceId` instead. We plan to slowly and gracefully retire `reactTag` term entity replacing it with several appropriate entities specific for particular usage, e.g. `viewId` (some id which makes sense for mounting), `surfaceId`, `nodeId` (unique id representing nodes which were cloned from the original one), or `eventTarget`. Reviewed By: mdvacca Differential Revision: D9999336 fbshipit-source-id: bbc7303c195b070b8c235c9ca35546d1dc693e98
This commit is contained in:
parent
b91f6d1e93
commit
c69313fc52
@ -39,17 +39,19 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (instancetype)initWithContextContainer:(std::shared_ptr<void>)contextContatiner;
|
||||
|
||||
- (void)registerRootTag:(ReactTag)tag;
|
||||
- (void)startSurfaceWithSurfaceId:(facebook::react::SurfaceId)surfaceId
|
||||
moduleName:(NSString *)moduleName
|
||||
initailProps:(NSDictionary *)initialProps;
|
||||
|
||||
- (void)unregisterRootTag:(ReactTag)tag;
|
||||
- (void)stopSurfaceWithSurfaceId:(facebook::react::SurfaceId)surfaceId;
|
||||
|
||||
- (CGSize)measureWithLayoutConstraints:(facebook::react::LayoutConstraints)layoutConstraints
|
||||
layoutContext:(facebook::react::LayoutContext)layoutContext
|
||||
rootTag:(ReactTag)rootTag;
|
||||
|
||||
- (void)constraintLayoutWithLayoutConstraints:(facebook::react::LayoutConstraints)layoutConstraints
|
||||
- (CGSize)measureSurfaceWithLayoutConstraints:(facebook::react::LayoutConstraints)layoutConstraints
|
||||
layoutContext:(facebook::react::LayoutContext)layoutContext
|
||||
rootTag:(ReactTag)rootTag;
|
||||
surfaceId:(facebook::react::SurfaceId)surfaceId;
|
||||
|
||||
- (void)constraintSurfaceLayoutWithLayoutConstraints:(facebook::react::LayoutConstraints)layoutConstraints
|
||||
layoutContext:(facebook::react::LayoutContext)layoutContext
|
||||
surfaceId:(facebook::react::SurfaceId)surfaceId;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -11,6 +11,8 @@
|
||||
#import <fabric/uimanager/Scheduler.h>
|
||||
#import <fabric/uimanager/SchedulerDelegate.h>
|
||||
|
||||
#import <React/RCTFollyConvert.h>
|
||||
|
||||
#import "RCTConversions.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
@ -55,28 +57,34 @@ private:
|
||||
_scheduler->setDelegate(nullptr);
|
||||
}
|
||||
|
||||
- (void)registerRootTag:(ReactTag)tag
|
||||
- (void)startSurfaceWithSurfaceId:(SurfaceId)surfaceId
|
||||
moduleName:(NSString *)moduleName
|
||||
initailProps:(NSDictionary *)initialProps
|
||||
{
|
||||
_scheduler->registerRootTag(tag);
|
||||
_scheduler->startSurface(
|
||||
surfaceId,
|
||||
RCTStringFromNSString(moduleName),
|
||||
convertIdToFollyDynamic(initialProps)
|
||||
);
|
||||
}
|
||||
|
||||
- (void)unregisterRootTag:(ReactTag)tag
|
||||
- (void)stopSurfaceWithSurfaceId:(SurfaceId)surfaceId
|
||||
{
|
||||
_scheduler->unregisterRootTag(tag);
|
||||
_scheduler->stopSurface(surfaceId);
|
||||
}
|
||||
|
||||
- (CGSize)measureWithLayoutConstraints:(LayoutConstraints)layoutConstraints
|
||||
layoutContext:(LayoutContext)layoutContext
|
||||
rootTag:(ReactTag)rootTag
|
||||
{
|
||||
return RCTCGSizeFromSize(_scheduler->measure(rootTag, layoutConstraints, layoutContext));
|
||||
}
|
||||
|
||||
- (void)constraintLayoutWithLayoutConstraints:(LayoutConstraints)layoutConstraints
|
||||
- (CGSize)measureSurfaceWithLayoutConstraints:(LayoutConstraints)layoutConstraints
|
||||
layoutContext:(LayoutContext)layoutContext
|
||||
rootTag:(ReactTag)rootTag
|
||||
surfaceId:(SurfaceId)surfaceId
|
||||
{
|
||||
_scheduler->constraintLayout(rootTag, layoutConstraints, layoutContext);
|
||||
return RCTCGSizeFromSize(_scheduler->measureSurface(surfaceId, layoutConstraints, layoutContext));
|
||||
}
|
||||
|
||||
- (void)constraintSurfaceLayoutWithLayoutConstraints:(LayoutConstraints)layoutConstraints
|
||||
layoutContext:(LayoutContext)layoutContext
|
||||
surfaceId:(SurfaceId)surfaceId
|
||||
{
|
||||
_scheduler->constraintSurfaceLayout(surfaceId, layoutConstraints, layoutContext);
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -150,9 +150,9 @@ using namespace facebook::react;
|
||||
layoutConstraints.minimumSize = RCTSizeFromCGSize(minimumSize);
|
||||
layoutConstraints.maximumSize = RCTSizeFromCGSize(maximumSize);
|
||||
|
||||
return [_scheduler measureWithLayoutConstraints:layoutConstraints
|
||||
layoutContext:layoutContext
|
||||
rootTag:surface.rootTag];
|
||||
return [_scheduler measureSurfaceWithLayoutConstraints:layoutConstraints
|
||||
layoutContext:layoutContext
|
||||
surfaceId:surface.rootTag];
|
||||
}
|
||||
|
||||
- (void)setMinimumSize:(CGSize)minimumSize
|
||||
@ -167,9 +167,9 @@ using namespace facebook::react;
|
||||
layoutConstraints.minimumSize = RCTSizeFromCGSize(minimumSize);
|
||||
layoutConstraints.maximumSize = RCTSizeFromCGSize(maximumSize);
|
||||
|
||||
[_scheduler constraintLayoutWithLayoutConstraints:layoutConstraints
|
||||
layoutContext:layoutContext
|
||||
rootTag:surface.rootTag];
|
||||
[_scheduler constraintSurfaceLayoutWithLayoutConstraints:layoutConstraints
|
||||
layoutContext:layoutContext
|
||||
surfaceId:surface.rootTag];
|
||||
}
|
||||
|
||||
- (void)startSurface:(RCTFabricSurface *)surface
|
||||
@ -177,27 +177,21 @@ using namespace facebook::react;
|
||||
[_mountingManager.componentViewRegistry dequeueComponentViewWithName:@"Root" tag:surface.rootTag];
|
||||
|
||||
[self createSchedulerIfNeeded];
|
||||
[_scheduler registerRootTag:surface.rootTag];
|
||||
|
||||
[_scheduler startSurfaceWithSurfaceId:surface.rootTag
|
||||
moduleName:surface.moduleName
|
||||
initailProps:surface.properties];
|
||||
|
||||
[self setMinimumSize:surface.minimumSize
|
||||
maximumSize:surface.maximumSize
|
||||
surface:surface];
|
||||
|
||||
// TODO: Move this down to Scheduler.
|
||||
NSDictionary *applicationParameters = @{
|
||||
@"rootTag": @(surface.rootTag),
|
||||
@"initialProps": surface.properties,
|
||||
};
|
||||
[self->_batchedBridge enqueueJSCall:@"AppRegistry" method:@"runApplication" args:@[surface.moduleName, applicationParameters] completion:NULL];
|
||||
}
|
||||
|
||||
- (void)stopSurface:(RCTFabricSurface *)surface
|
||||
{
|
||||
// TODO: Move this down to Scheduler.
|
||||
[_batchedBridge enqueueJSCall:@"ReactFabric" method:@"unmountComponentAtNode" args:@[@(surface.rootTag)] completion:NULL];
|
||||
|
||||
[self ensureSchedulerDoesExist];
|
||||
[_scheduler unregisterRootTag:surface.rootTag];
|
||||
|
||||
[_scheduler stopSurfaceWithSurfaceId:surface.rootTag];
|
||||
|
||||
UIView<RCTComponentViewProtocol> *rootView = [_mountingManager.componentViewRegistry componentViewByTag:surface.rootTag];
|
||||
[_mountingManager.componentViewRegistry enqueueComponentViewWithName:@"Root" tag:surface.rootTag componentView:rootView];
|
||||
|
@ -22,6 +22,11 @@ namespace react {
|
||||
using Tag = int32_t;
|
||||
using InstanceHandle = struct InstanceHandleDummyStruct {} *;
|
||||
|
||||
/*
|
||||
* An id of a running Surface instance that is used to refer to the instance.
|
||||
*/
|
||||
using SurfaceId = int32_t;
|
||||
|
||||
/*
|
||||
* `RawProps` represents untyped map with props comes from JavaScript side.
|
||||
*/
|
||||
|
@ -106,7 +106,7 @@ static const std::string componentNameByReactViewName(std::string viewName) {
|
||||
FabricUIManager::~FabricUIManager() {
|
||||
(*executor_)([this] {
|
||||
uninstaller_();
|
||||
}, EventBeatBasedExecutor::Mode::Synchronous);
|
||||
});
|
||||
}
|
||||
|
||||
void FabricUIManager::setComponentDescriptorRegistry(const SharedComponentDescriptorRegistry &componentDescriptorRegistry) {
|
||||
@ -129,6 +129,14 @@ void FabricUIManager::setDispatchEventToTargetFunction(std::function<DispatchEve
|
||||
dispatchEventToTargetFunction_ = dispatchEventFunction;
|
||||
}
|
||||
|
||||
void FabricUIManager::setStartSurfaceFunction(std::function<StartSurface> startSurfaceFunction) {
|
||||
startSurfaceFunction_ = startSurfaceFunction;
|
||||
}
|
||||
|
||||
void FabricUIManager::setStopSurfaceFunction(std::function<StopSurface> stopSurfaceFunction) {
|
||||
stopSurfaceFunction_ = stopSurfaceFunction;
|
||||
}
|
||||
|
||||
void FabricUIManager::dispatchEventToTarget(const EventTarget *eventTarget, const std::string &type, const folly::dynamic &payload) const {
|
||||
if (eventTarget) {
|
||||
dispatchEventToTargetFunction_(
|
||||
@ -146,6 +154,18 @@ void FabricUIManager::dispatchEventToTarget(const EventTarget *eventTarget, cons
|
||||
}
|
||||
}
|
||||
|
||||
void FabricUIManager::startSurface(SurfaceId surfaceId, const std::string &moduleName, const folly::dynamic &initialProps) const {
|
||||
(*executor_)([this, surfaceId, moduleName, initialProps] {
|
||||
startSurfaceFunction_(surfaceId, moduleName, initialProps);
|
||||
});
|
||||
}
|
||||
|
||||
void FabricUIManager::stopSurface(SurfaceId surfaceId) const {
|
||||
(*executor_)([this, surfaceId] {
|
||||
stopSurfaceFunction_(surfaceId);
|
||||
});
|
||||
}
|
||||
|
||||
SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int rootTag, folly::dynamic props, SharedEventTarget eventTarget) const {
|
||||
isLoggingEnabled && LOG(INFO) << "FabricUIManager::createNode(tag: " << tag << ", name: " << viewName << ", rootTag: " << rootTag << ", props: " << props << ")";
|
||||
|
||||
|
@ -32,6 +32,9 @@ using UIManagerUninstaller = void ();
|
||||
using DispatchEventToEmptyTargetFunction = void (const EventHandler &eventHandler, const std::string &type, const folly::dynamic &payload);
|
||||
using DispatchEventToTargetFunction = void (const EventHandler &eventHandler, const EventTarget &eventTarget, const std::string &type, const folly::dynamic &payload);
|
||||
|
||||
using StartSurface = void (SurfaceId surfaceId, const std::string &moduleName, const folly::dynamic &initalProps);
|
||||
using StopSurface = void (SurfaceId surfaceId);
|
||||
|
||||
class FabricUIManager {
|
||||
public:
|
||||
|
||||
@ -61,10 +64,14 @@ public:
|
||||
*/
|
||||
void setDispatchEventToEmptyTargetFunction(std::function<DispatchEventToEmptyTargetFunction> dispatchEventFunction);
|
||||
void setDispatchEventToTargetFunction(std::function<DispatchEventToTargetFunction> dispatchEventFunction);
|
||||
void setStartSurfaceFunction(std::function<StartSurface>);
|
||||
void setStopSurfaceFunction(std::function<StopSurface>);
|
||||
|
||||
#pragma mark - Native-facing Interface
|
||||
|
||||
void dispatchEventToTarget(const EventTarget *eventTarget, const std::string &type, const folly::dynamic &payload) const;
|
||||
void startSurface(SurfaceId surfaceId, const std::string &moduleName, const folly::dynamic &initialProps) const;
|
||||
void stopSurface(SurfaceId surfaceId) const;
|
||||
|
||||
#pragma mark - JavaScript/React-facing Interface
|
||||
|
||||
@ -86,12 +93,13 @@ public:
|
||||
void registerEventHandler(UniqueEventHandler eventHandler) const;
|
||||
|
||||
private:
|
||||
|
||||
SharedComponentDescriptorRegistry componentDescriptorRegistry_;
|
||||
UIManagerDelegate *delegate_;
|
||||
mutable UniqueEventHandler eventHandler_;
|
||||
std::function<DispatchEventToEmptyTargetFunction> dispatchEventToEmptyTargetFunction_;
|
||||
std::function<DispatchEventToTargetFunction> dispatchEventToTargetFunction_;
|
||||
std::function<StartSurface> startSurfaceFunction_;
|
||||
std::function<StopSurface> stopSurfaceFunction_;
|
||||
|
||||
std::unique_ptr<EventBeatBasedExecutor> executor_;
|
||||
std::function<UIManagerInstaller> installer_;
|
||||
|
@ -51,14 +51,30 @@ Scheduler::~Scheduler() {
|
||||
uiManager_->setDelegate(nullptr);
|
||||
}
|
||||
|
||||
void Scheduler::registerRootTag(Tag rootTag) {
|
||||
auto shadowTree = std::make_unique<ShadowTree>(rootTag);
|
||||
void Scheduler::startSurface(
|
||||
SurfaceId surfaceId,
|
||||
const std::string &moduleName,
|
||||
const folly::dynamic &initialProps
|
||||
) const {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
auto shadowTree = std::make_unique<ShadowTree>(surfaceId);
|
||||
shadowTree->setDelegate(this);
|
||||
shadowTreeRegistry_.emplace(rootTag, std::move(shadowTree));
|
||||
shadowTreeRegistry_.emplace(surfaceId, std::move(shadowTree));
|
||||
|
||||
#ifndef ANDROID
|
||||
uiManager_->startSurface(surfaceId, moduleName, initialProps);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Scheduler::unregisterRootTag(Tag rootTag) {
|
||||
const auto &iterator = shadowTreeRegistry_.find(rootTag);
|
||||
void Scheduler::stopSurface(SurfaceId surfaceId) const {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
#ifndef ANDROID
|
||||
uiManager_->stopSurface(surfaceId);
|
||||
#endif
|
||||
|
||||
const auto &iterator = shadowTreeRegistry_.find(surfaceId);
|
||||
const auto &shadowTree = iterator->second;
|
||||
assert(shadowTree);
|
||||
// As part of stopping the Surface, we have to commit an empty tree.
|
||||
@ -67,14 +83,24 @@ void Scheduler::unregisterRootTag(Tag rootTag) {
|
||||
shadowTreeRegistry_.erase(iterator);
|
||||
}
|
||||
|
||||
Size Scheduler::measure(const Tag &rootTag, const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const {
|
||||
const auto &shadowTree = shadowTreeRegistry_.at(rootTag);
|
||||
Size Scheduler::measureSurface(
|
||||
SurfaceId surfaceId,
|
||||
const LayoutConstraints &layoutConstraints,
|
||||
const LayoutContext &layoutContext
|
||||
) const {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
const auto &shadowTree = shadowTreeRegistry_.at(surfaceId);
|
||||
assert(shadowTree);
|
||||
return shadowTree->measure(layoutConstraints, layoutContext);
|
||||
}
|
||||
|
||||
void Scheduler::constraintLayout(const Tag &rootTag, const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) {
|
||||
const auto &shadowTree = shadowTreeRegistry_.at(rootTag);
|
||||
void Scheduler::constraintSurfaceLayout(
|
||||
SurfaceId surfaceId,
|
||||
const LayoutConstraints &layoutConstraints,
|
||||
const LayoutContext &layoutContext
|
||||
) const {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
const auto &shadowTree = shadowTreeRegistry_.at(surfaceId);
|
||||
assert(shadowTree);
|
||||
return shadowTree->constraintLayout(layoutConstraints, layoutContext);
|
||||
}
|
||||
@ -91,7 +117,7 @@ SchedulerDelegate *Scheduler::getDelegate() const {
|
||||
|
||||
#pragma mark - ShadowTreeDelegate
|
||||
|
||||
void Scheduler::shadowTreeDidCommit(const ShadowTree &shadowTree, const ShadowViewMutationList &mutations) {
|
||||
void Scheduler::shadowTreeDidCommit(const ShadowTree &shadowTree, const ShadowViewMutationList &mutations) const {
|
||||
if (delegate_) {
|
||||
delegate_->schedulerDidFinishTransaction(shadowTree.getRootTag(), mutations);
|
||||
}
|
||||
@ -100,6 +126,8 @@ void Scheduler::shadowTreeDidCommit(const ShadowTree &shadowTree, const ShadowVi
|
||||
#pragma mark - UIManagerDelegate
|
||||
|
||||
void Scheduler::uiManagerDidFinishTransaction(Tag rootTag, const SharedShadowNodeUnsharedList &rootChildNodes) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
const auto iterator = shadowTreeRegistry_.find(rootTag);
|
||||
if (iterator == shadowTreeRegistry_.end()) {
|
||||
// This might happen during surface unmounting/deallocation process
|
||||
|
@ -6,6 +6,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include <fabric/core/ComponentDescriptor.h>
|
||||
#include <fabric/core/LayoutConstraints.h>
|
||||
@ -28,17 +29,30 @@ class Scheduler final:
|
||||
public ShadowTreeDelegate {
|
||||
|
||||
public:
|
||||
|
||||
Scheduler(const SharedContextContainer &contextContainer);
|
||||
~Scheduler();
|
||||
|
||||
#pragma mark - Shadow Tree Management
|
||||
#pragma mark - Surface Management
|
||||
|
||||
void registerRootTag(Tag rootTag);
|
||||
void unregisterRootTag(Tag rootTag);
|
||||
void startSurface(
|
||||
SurfaceId surfaceId,
|
||||
const std::string &moduleName,
|
||||
const folly::dynamic &initialProps
|
||||
) const;
|
||||
|
||||
Size measure(const Tag &rootTag, const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const;
|
||||
void constraintLayout(const Tag &rootTag, const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext);
|
||||
void stopSurface(SurfaceId surfaceId) const;
|
||||
|
||||
Size measureSurface(
|
||||
SurfaceId surfaceId,
|
||||
const LayoutConstraints &layoutConstraints,
|
||||
const LayoutContext &layoutContext
|
||||
) const;
|
||||
|
||||
void constraintSurfaceLayout(
|
||||
SurfaceId surfaceId,
|
||||
const LayoutConstraints &layoutConstraints,
|
||||
const LayoutContext &layoutContext
|
||||
) const;
|
||||
|
||||
#pragma mark - Delegate
|
||||
|
||||
@ -57,7 +71,7 @@ public:
|
||||
|
||||
#pragma mark - ShadowTreeDelegate
|
||||
|
||||
void shadowTreeDidCommit(const ShadowTree &shadowTree, const ShadowViewMutationList &mutations) override;
|
||||
void shadowTreeDidCommit(const ShadowTree &shadowTree, const ShadowViewMutationList &mutations) const override;
|
||||
|
||||
#pragma mark - Deprecated
|
||||
|
||||
@ -69,7 +83,8 @@ public:
|
||||
private:
|
||||
SchedulerDelegate *delegate_;
|
||||
std::shared_ptr<FabricUIManager> uiManager_;
|
||||
std::unordered_map<Tag, std::unique_ptr<ShadowTree>> shadowTreeRegistry_;
|
||||
mutable std::mutex mutex_;
|
||||
mutable std::unordered_map<SurfaceId, std::unique_ptr<ShadowTree>> shadowTreeRegistry_; // Protected by `mutex_`.
|
||||
SharedEventDispatcher eventDispatcher_;
|
||||
SharedContextContainer contextContainer_;
|
||||
};
|
||||
|
@ -165,11 +165,11 @@ void ShadowTree::toggleEventEmitters(const ShadowViewMutationList &mutations) {
|
||||
|
||||
#pragma mark - Delegate
|
||||
|
||||
void ShadowTree::setDelegate(ShadowTreeDelegate *delegate) {
|
||||
void ShadowTree::setDelegate(ShadowTreeDelegate const *delegate) {
|
||||
delegate_ = delegate;
|
||||
}
|
||||
|
||||
ShadowTreeDelegate *ShadowTree::getDelegate() const {
|
||||
ShadowTreeDelegate const *ShadowTree::getDelegate() const {
|
||||
return delegate_;
|
||||
}
|
||||
|
||||
|
@ -68,8 +68,8 @@ public:
|
||||
* The delegate is stored as a raw pointer, so the owner must null
|
||||
* the pointer before being destroyed.
|
||||
*/
|
||||
void setDelegate(ShadowTreeDelegate *delegate);
|
||||
ShadowTreeDelegate *getDelegate() const;
|
||||
void setDelegate(ShadowTreeDelegate const *delegate);
|
||||
ShadowTreeDelegate const *getDelegate() const;
|
||||
|
||||
private:
|
||||
|
||||
@ -85,7 +85,7 @@ private:
|
||||
|
||||
const Tag rootTag_;
|
||||
SharedRootShadowNode rootShadowNode_;
|
||||
ShadowTreeDelegate *delegate_;
|
||||
ShadowTreeDelegate const *delegate_;
|
||||
mutable std::mutex commitMutex_;
|
||||
};
|
||||
|
||||
|
@ -21,7 +21,7 @@ public:
|
||||
/*
|
||||
* Called right after Shadow Tree commit a new state of the the tree.
|
||||
*/
|
||||
virtual void shadowTreeDidCommit(const ShadowTree &shadowTree, const ShadowViewMutationList &mutations) = 0;
|
||||
virtual void shadowTreeDidCommit(const ShadowTree &shadowTree, const ShadowViewMutationList &mutations) const = 0;
|
||||
|
||||
virtual ~ShadowTreeDelegate() noexcept = default;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user