mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fabric: Introducing SurfaceHandler
Summary: This implements `SurfaceHandler`, a new primitive for controlling the Surface life-cycle that ensures ownership, preserves state, maintains internal invariants, and simplifies surface manipulation from the application side. For now, all this is an unused code. The coming diff will introduce an experiment that will route all surfaceId-based APIs to SurfaceHandler-based ones. Changelog: [Internal] Fabric-specific internal change. Reviewed By: sammy-SC Differential Revision: D24290777 fbshipit-source-id: f2ff2b58e6d46e971a548f9f02113a1c783c4940
This commit is contained in:
committed by
Facebook GitHub Bot
parent
7186c4de4f
commit
7a290d1596
@@ -81,6 +81,7 @@ Scheduler::Scheduler(
|
||||
|
||||
uiManager->setBackgroundExecutor(schedulerToolbox.backgroundExecutor);
|
||||
uiManager->setDelegate(this);
|
||||
uiManager->setRuntimeExecutor(runtimeExecutor_);
|
||||
uiManager->setComponentDescriptorRegistry(componentDescriptorRegistry_);
|
||||
|
||||
runtimeExecutor_([=](jsi::Runtime &runtime) {
|
||||
@@ -179,6 +180,16 @@ Scheduler::~Scheduler() {
|
||||
}
|
||||
}
|
||||
|
||||
void Scheduler::registerSurface(
|
||||
SurfaceHandler const &surfaceHandler) const noexcept {
|
||||
surfaceHandler.setUIManager(uiManager_.get());
|
||||
}
|
||||
|
||||
void Scheduler::unregisterSurface(
|
||||
SurfaceHandler const &surfaceHandler) const noexcept {
|
||||
surfaceHandler.setUIManager(nullptr);
|
||||
}
|
||||
|
||||
void Scheduler::startSurface(
|
||||
SurfaceId surfaceId,
|
||||
const std::string &moduleName,
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <react/renderer/mounting/MountingOverrideDelegate.h>
|
||||
#include <react/renderer/scheduler/SchedulerDelegate.h>
|
||||
#include <react/renderer/scheduler/SchedulerToolbox.h>
|
||||
#include <react/renderer/scheduler/SurfaceHandler.h>
|
||||
#include <react/renderer/uimanager/UIManagerAnimationDelegate.h>
|
||||
#include <react/renderer/uimanager/UIManagerBinding.h>
|
||||
#include <react/renderer/uimanager/UIManagerDelegate.h>
|
||||
@@ -40,6 +41,14 @@ class Scheduler final : public UIManagerDelegate {
|
||||
|
||||
#pragma mark - Surface Management
|
||||
|
||||
/*
|
||||
* Registers and unregisters a `SurfaceHandler` object in the `Scheduler`.
|
||||
* All registered `SurfaceHandler` objects must be unregistered
|
||||
* (with the same `Scheduler`) before their deallocation.
|
||||
*/
|
||||
void registerSurface(SurfaceHandler const &surfaceHandler) const noexcept;
|
||||
void unregisterSurface(SurfaceHandler const &surfaceHandler) const noexcept;
|
||||
|
||||
void startSurface(
|
||||
SurfaceId surfaceId,
|
||||
const std::string &moduleName,
|
||||
@@ -73,7 +82,7 @@ class Scheduler final : public UIManagerDelegate {
|
||||
/*
|
||||
* This is broken. Please do not use.
|
||||
* `ComponentDescriptor`s are not designed to be used outside of `UIManager`,
|
||||
* there is no any garantees about their lifetime.
|
||||
* there is no any guarantees about their lifetime.
|
||||
*/
|
||||
ComponentDescriptor const *
|
||||
findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN(
|
||||
@@ -119,6 +128,8 @@ class Scheduler final : public UIManagerDelegate {
|
||||
void uiManagerDidClearJSResponder() override;
|
||||
|
||||
private:
|
||||
friend class SurfaceHandler;
|
||||
|
||||
SchedulerDelegate *delegate_;
|
||||
SharedComponentDescriptorRegistry componentDescriptorRegistry_;
|
||||
RuntimeExecutor runtimeExecutor_;
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* 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 "SurfaceHandler.h"
|
||||
|
||||
#include <react/renderer/scheduler/Scheduler.h>
|
||||
#include <react/renderer/uimanager/UIManager.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
using Status = SurfaceHandler::Status;
|
||||
using DisplayMode = SurfaceHandler::DisplayMode;
|
||||
|
||||
SurfaceHandler::SurfaceHandler(
|
||||
std::string const &moduleName,
|
||||
SurfaceId surfaceId) noexcept {
|
||||
parameters_.moduleName = moduleName;
|
||||
parameters_.surfaceId = surfaceId;
|
||||
}
|
||||
|
||||
SurfaceHandler::SurfaceHandler(SurfaceHandler &&other) noexcept {
|
||||
operator=(std::move(other));
|
||||
}
|
||||
|
||||
SurfaceHandler &SurfaceHandler::operator=(SurfaceHandler &&other) noexcept {
|
||||
std::unique_lock<better::shared_mutex> lock1(linkMutex_, std::defer_lock);
|
||||
std::unique_lock<better::shared_mutex> lock2(
|
||||
parametersMutex_, std::defer_lock);
|
||||
std::unique_lock<better::shared_mutex> lock3(
|
||||
other.linkMutex_, std::defer_lock);
|
||||
std::unique_lock<better::shared_mutex> lock4(
|
||||
other.parametersMutex_, std::defer_lock);
|
||||
std::lock(lock1, lock2, lock3, lock4);
|
||||
|
||||
link_ = other.link_;
|
||||
parameters_ = other.parameters_;
|
||||
|
||||
other.link_ = Link{};
|
||||
other.parameters_ = Parameters{};
|
||||
return *this;
|
||||
}
|
||||
|
||||
#pragma mark - Surface Life-Cycle Management
|
||||
|
||||
Status SurfaceHandler::getStatus() const noexcept {
|
||||
std::shared_lock<better::shared_mutex> lock(linkMutex_);
|
||||
return link_.status;
|
||||
}
|
||||
|
||||
void SurfaceHandler::start() const noexcept {
|
||||
{
|
||||
std::unique_lock<better::shared_mutex> lock(linkMutex_);
|
||||
assert(link_.status == Status::Registered && "Surface must be registered.");
|
||||
|
||||
auto parameters = Parameters{};
|
||||
{
|
||||
std::shared_lock<better::shared_mutex> parametersLock(parametersMutex_);
|
||||
parameters = parameters_;
|
||||
}
|
||||
|
||||
link_.shadowTree = &link_.uiManager->startSurface(
|
||||
parameters.surfaceId,
|
||||
parameters.moduleName,
|
||||
parameters.props,
|
||||
parameters.layoutConstraints,
|
||||
parameters.layoutContext);
|
||||
|
||||
link_.status = Status::Running;
|
||||
|
||||
applyDisplayMode(parameters.displayMode);
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceHandler::stop() const noexcept {
|
||||
std::unique_lock<better::shared_mutex> lock(linkMutex_);
|
||||
assert(link_.status == Status::Running && "Surface must be running.");
|
||||
|
||||
link_.status = Status::Registered;
|
||||
link_.shadowTree = nullptr;
|
||||
link_.uiManager->stopSurface(parameters_.surfaceId);
|
||||
}
|
||||
|
||||
void SurfaceHandler::setDisplayMode(DisplayMode displayMode) const noexcept {
|
||||
{
|
||||
std::unique_lock<better::shared_mutex> lock(parametersMutex_);
|
||||
if (parameters_.displayMode == displayMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
parameters_.displayMode = displayMode;
|
||||
}
|
||||
|
||||
{
|
||||
std::shared_lock<better::shared_mutex> lock(linkMutex_);
|
||||
|
||||
if (link_.status != Status::Running) {
|
||||
return;
|
||||
}
|
||||
|
||||
applyDisplayMode(displayMode);
|
||||
}
|
||||
}
|
||||
|
||||
DisplayMode SurfaceHandler::getDisplayMode() const noexcept {
|
||||
std::shared_lock<better::shared_mutex> lock(parametersMutex_);
|
||||
return parameters_.displayMode;
|
||||
}
|
||||
|
||||
#pragma mark - Accessors
|
||||
|
||||
SurfaceId SurfaceHandler::getSurfaceId() const noexcept {
|
||||
std::shared_lock<better::shared_mutex> lock(parametersMutex_);
|
||||
return parameters_.surfaceId;
|
||||
}
|
||||
|
||||
std::string SurfaceHandler::getModuleName() const noexcept {
|
||||
std::shared_lock<better::shared_mutex> lock(parametersMutex_);
|
||||
return parameters_.moduleName;
|
||||
}
|
||||
|
||||
void SurfaceHandler::setProps(folly::dynamic const &props) const noexcept {
|
||||
std::unique_lock<better::shared_mutex> lock(parametersMutex_);
|
||||
parameters_.props = props;
|
||||
}
|
||||
|
||||
folly::dynamic SurfaceHandler::getProps() const noexcept {
|
||||
std::shared_lock<better::shared_mutex> lock(parametersMutex_);
|
||||
return parameters_.props;
|
||||
}
|
||||
|
||||
std::shared_ptr<MountingCoordinator const>
|
||||
SurfaceHandler::getMountingCoordinator() const noexcept {
|
||||
std::shared_lock<better::shared_mutex> lock(linkMutex_);
|
||||
assert(link_.status != Status::Unregistered && "Surface must be registered.");
|
||||
assert(link_.shadowTree && "`link_.shadowTree` must not be null.");
|
||||
return link_.shadowTree->getMountingCoordinator();
|
||||
}
|
||||
|
||||
#pragma mark - Layout
|
||||
|
||||
Size SurfaceHandler::measure(
|
||||
LayoutConstraints const &layoutConstraints,
|
||||
LayoutContext const &layoutContext) const noexcept {
|
||||
std::shared_lock<better::shared_mutex> lock(linkMutex_);
|
||||
|
||||
if (link_.status != Status::Running) {
|
||||
return layoutConstraints.clamp({0, 0});
|
||||
}
|
||||
|
||||
assert(link_.shadowTree && "`link_.shadowTree` must not be null.");
|
||||
|
||||
auto currentRootShadowNode =
|
||||
link_.shadowTree->getCurrentRevision().rootShadowNode;
|
||||
|
||||
auto rootShadowNode =
|
||||
currentRootShadowNode->clone(layoutConstraints, layoutContext);
|
||||
rootShadowNode->layoutIfNeeded();
|
||||
return rootShadowNode->getLayoutMetrics().frame.size;
|
||||
}
|
||||
|
||||
void SurfaceHandler::constraintLayout(
|
||||
LayoutConstraints const &layoutConstraints,
|
||||
LayoutContext const &layoutContext) const noexcept {
|
||||
{
|
||||
std::unique_lock<better::shared_mutex> lock(parametersMutex_);
|
||||
|
||||
if (parameters_.layoutConstraints == layoutConstraints &&
|
||||
parameters_.layoutContext == layoutContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
parameters_.layoutConstraints = layoutConstraints;
|
||||
parameters_.layoutContext = layoutContext;
|
||||
}
|
||||
|
||||
{
|
||||
std::shared_lock<better::shared_mutex> lock(linkMutex_);
|
||||
|
||||
if (link_.status != Status::Running) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(link_.shadowTree && "`link_.shadowTree` must not be null.");
|
||||
link_.shadowTree->commit([&](RootShadowNode const &oldRootShadowNode) {
|
||||
return oldRootShadowNode.clone(layoutConstraints, layoutContext);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
LayoutConstraints SurfaceHandler::getLayoutConstraints() const noexcept {
|
||||
std::shared_lock<better::shared_mutex> lock(parametersMutex_);
|
||||
return parameters_.layoutConstraints;
|
||||
}
|
||||
|
||||
LayoutContext SurfaceHandler::getLayoutContext() const noexcept {
|
||||
std::shared_lock<better::shared_mutex> lock(parametersMutex_);
|
||||
return parameters_.layoutContext;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
void SurfaceHandler::applyDisplayMode(DisplayMode displayMode) const noexcept {
|
||||
assert(link_.status == Status::Running && "Surface must be running.");
|
||||
assert(link_.shadowTree && "`link_.shadowTree` must not be null.");
|
||||
|
||||
switch (displayMode) {
|
||||
case DisplayMode::Visible:
|
||||
link_.shadowTree->setCommitMode(ShadowTree::CommitMode::Normal);
|
||||
break;
|
||||
case DisplayMode::Suspended:
|
||||
link_.shadowTree->setCommitMode(ShadowTree::CommitMode::Suspended);
|
||||
break;
|
||||
case DisplayMode::Hidden:
|
||||
link_.shadowTree->setCommitMode(ShadowTree::CommitMode::Normal);
|
||||
// Getting a current revision.
|
||||
auto revision = link_.shadowTree->getCurrentRevision();
|
||||
// Committing an empty tree to force mounting to disassemble view
|
||||
// hierarchy.
|
||||
link_.shadowTree->commitEmptyTree();
|
||||
link_.shadowTree->setCommitMode(ShadowTree::CommitMode::Suspended);
|
||||
// Committing the current revision back. It will be mounted only when
|
||||
// `DisplayMode` is changed back to `Normal`.
|
||||
link_.shadowTree->commit([&](RootShadowNode const &oldRootShadowNode) {
|
||||
return std::static_pointer_cast<RootShadowNode>(
|
||||
revision.rootShadowNode->ShadowNode::clone(ShadowNodeFragment{}));
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceHandler::setUIManager(UIManager const *uiManager) const noexcept {
|
||||
std::unique_lock<better::shared_mutex> lock(linkMutex_);
|
||||
|
||||
assert(link_.status != Status::Running && "Surface must not be running.");
|
||||
|
||||
if (link_.uiManager == uiManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
link_.uiManager = uiManager;
|
||||
link_.status = uiManager ? Status::Registered : Status::Unregistered;
|
||||
}
|
||||
|
||||
SurfaceHandler::~SurfaceHandler() noexcept {
|
||||
assert(
|
||||
link_.status == Status::Unregistered &&
|
||||
"`SurfaceHandler` must be unregistered (or moved-from) before deallocation.");
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* 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 <memory>
|
||||
|
||||
#include <react/renderer/core/LayoutConstraints.h>
|
||||
#include <react/renderer/core/LayoutContext.h>
|
||||
#include <react/renderer/core/ReactPrimitives.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class Scheduler;
|
||||
class ShadowTree;
|
||||
class MountingCoordinator;
|
||||
class UIManager;
|
||||
|
||||
/*
|
||||
* Represents a running React Native surface and provides control over it.
|
||||
* The instances of this class are movable only.
|
||||
* The instances of this class can be safely deallocated only if `status` is
|
||||
* `Unregistered`; this is a way to enforce internal consistency and
|
||||
* deallocation ordering constraints the core relies on.
|
||||
*
|
||||
*
|
||||
* Even though all methods of the class are thread-safe, the consumer side must
|
||||
* ensure the logical consistency of some methods (e.g. calling `stop` for
|
||||
* non-running surface will crash).
|
||||
*/
|
||||
class SurfaceHandler final {
|
||||
public:
|
||||
/*
|
||||
* Represents a status of the `SurfaceHandler` instance.
|
||||
*/
|
||||
enum class Status {
|
||||
/*
|
||||
* Newly created, moved-from, or already-unregistered instances. The only
|
||||
* state in which the object can be safely deallocated.
|
||||
*/
|
||||
Unregistered,
|
||||
|
||||
/*
|
||||
* Registered instances that have an internal reference to a `UIManager`
|
||||
* instance and ready to start a surface.
|
||||
*/
|
||||
Registered,
|
||||
|
||||
/*
|
||||
* Registered and running instances.
|
||||
*/
|
||||
Running,
|
||||
};
|
||||
|
||||
/*
|
||||
* Defines how visual side effects (views, images, text, and so on) are
|
||||
* mounted (on not) on the screen.
|
||||
*/
|
||||
enum class DisplayMode {
|
||||
/*
|
||||
* The surface is running normally. All visual side-effects will be rendered
|
||||
* on the screen.
|
||||
*/
|
||||
Visible,
|
||||
|
||||
/*
|
||||
* The surface is `Suspended`. All new (committed after switching to the
|
||||
* mode) visual side-effects will *not* be mounted on the screen (the screen
|
||||
* will stop updating).
|
||||
*
|
||||
* The mode can be used for preparing a surface for possible future use.
|
||||
* The surface will be prepared without spending computing resources
|
||||
* on mounting, and then can be instantly mounted if needed.
|
||||
*/
|
||||
Suspended,
|
||||
|
||||
/*
|
||||
* The surface is `Hidden`. All previously mounted visual side-effects
|
||||
* will be unmounted, and all new (committed after switching to the mode)
|
||||
* visual side-effects will *not* be mounted on the screen until the mode is
|
||||
* switched back to `normal`.
|
||||
*
|
||||
* The mode can be used for temporarily freeing computing resources of
|
||||
* off-the-screen surfaces.
|
||||
*/
|
||||
Hidden,
|
||||
};
|
||||
|
||||
/*
|
||||
* Can be constructed anytime with a `moduleName` and a `surfaceId`.
|
||||
*/
|
||||
SurfaceHandler(std::string const &moduleName, SurfaceId surfaceId) noexcept;
|
||||
~SurfaceHandler() noexcept;
|
||||
|
||||
/*
|
||||
* Movable-only.
|
||||
*/
|
||||
SurfaceHandler(SurfaceHandler &&SurfaceHandler) noexcept;
|
||||
SurfaceHandler(SurfaceHandler const &SurfaceHandler) noexcept = delete;
|
||||
SurfaceHandler &operator=(SurfaceHandler &&other) noexcept;
|
||||
SurfaceHandler &operator=(SurfaceHandler const &other) noexcept = delete;
|
||||
|
||||
#pragma mark - Surface Life-Cycle Management
|
||||
|
||||
/*
|
||||
* Returns a momentum value of the status.
|
||||
*/
|
||||
Status getStatus() const noexcept;
|
||||
|
||||
/*
|
||||
* Starts or stops the surface.
|
||||
* Can not be called when the status is `Unregistered`.
|
||||
* `start()` must not be called for a running surface, and `stop()` must not
|
||||
* be called for a not running surface.
|
||||
*/
|
||||
void start() const noexcept;
|
||||
void stop() const noexcept;
|
||||
|
||||
/*
|
||||
* Sets (and gets) the runnnig mode.
|
||||
* The running mode can be changed anytime (even for `Unregistered` surface).
|
||||
*/
|
||||
void setDisplayMode(DisplayMode displayMode) const noexcept;
|
||||
DisplayMode getDisplayMode() const noexcept;
|
||||
|
||||
#pragma mark - Accessors
|
||||
|
||||
SurfaceId getSurfaceId() const noexcept;
|
||||
std::string getModuleName() const noexcept;
|
||||
|
||||
/*
|
||||
* Provides access for surface props.
|
||||
* Props can be changed anytime (even for `Unregistered` surface).
|
||||
*/
|
||||
void setProps(folly::dynamic const &props) const noexcept;
|
||||
folly::dynamic getProps() const noexcept;
|
||||
|
||||
/*
|
||||
* Returns a `MountingCoordinator` instance associated with a running surface.
|
||||
* Can be not be called when the status is `Unregistered`.
|
||||
* The returning value cannot be `nullptr`.
|
||||
*/
|
||||
std::shared_ptr<MountingCoordinator const> getMountingCoordinator()
|
||||
const noexcept;
|
||||
|
||||
#pragma mark - Layout
|
||||
|
||||
/*
|
||||
* Measures the surface with given layout constraints and layout context.
|
||||
* Returns zero size if called on the stopped or unregistered surface.
|
||||
*/
|
||||
Size measure(
|
||||
LayoutConstraints const &layoutConstraints,
|
||||
LayoutContext const &layoutContext) const noexcept;
|
||||
|
||||
/*
|
||||
* Sets layout constraints and layout context for the surface.
|
||||
*/
|
||||
void constraintLayout(
|
||||
LayoutConstraints const &layoutConstraints,
|
||||
LayoutContext const &layoutContext) const noexcept;
|
||||
|
||||
/*
|
||||
* Returns layout constraints and layout context associated with the surface.
|
||||
*/
|
||||
LayoutConstraints getLayoutConstraints() const noexcept;
|
||||
LayoutContext getLayoutContext() const noexcept;
|
||||
|
||||
private:
|
||||
friend class Scheduler;
|
||||
|
||||
/*
|
||||
* Must be called by `Scheduler` during registration process.
|
||||
*/
|
||||
void setUIManager(UIManager const *uiManager) const noexcept;
|
||||
|
||||
void applyDisplayMode(DisplayMode displayMode) const noexcept;
|
||||
|
||||
#pragma mark - Link & Parameters
|
||||
|
||||
/*
|
||||
* All data members of the class are split into two groups (`Link` and
|
||||
* `Parameters`) that require separate synchronization. This way it's easier
|
||||
* to see that proper lock is acquired. Separate synchronization is needed to
|
||||
* prevent deadlocks.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Represents parameters of the surface. Parameters can be changed
|
||||
* independently from controlling the running state
|
||||
* (registering/unregistering, starting/stopping) of the surface.
|
||||
* Changing parameters requires acquiring a unique lock; reading needs only
|
||||
* a shared lock.
|
||||
*/
|
||||
struct Parameters {
|
||||
std::string moduleName{};
|
||||
SurfaceId surfaceId{};
|
||||
DisplayMode displayMode{DisplayMode::Visible};
|
||||
folly::dynamic props{};
|
||||
LayoutConstraints layoutConstraints{};
|
||||
LayoutContext layoutContext{};
|
||||
};
|
||||
|
||||
/*
|
||||
* Represents an underlying link to a `ShadowTree` and an `UIMananger`.
|
||||
* Registering, unregistering, starting, and stopping the surface requires
|
||||
* acquiring a unique lock; other access needs only a shared lock.
|
||||
*/
|
||||
struct Link {
|
||||
Status status{Status::Unregistered};
|
||||
UIManager const *uiManager{};
|
||||
ShadowTree const *shadowTree{};
|
||||
};
|
||||
|
||||
/*
|
||||
* `link_` and `linkMutex_` pair.
|
||||
*/
|
||||
mutable better::shared_mutex linkMutex_;
|
||||
mutable Link link_;
|
||||
|
||||
/*
|
||||
* `parameters_` and `parametersMutex_` pair.
|
||||
*/
|
||||
mutable better::shared_mutex parametersMutex_;
|
||||
mutable Parameters parameters_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -127,6 +127,62 @@ void UIManager::clearJSResponder() const {
|
||||
}
|
||||
}
|
||||
|
||||
ShadowTree const &UIManager::startSurface(
|
||||
SurfaceId surfaceId,
|
||||
std::string const &moduleName,
|
||||
folly::dynamic const &props,
|
||||
LayoutConstraints const &layoutConstraints,
|
||||
LayoutContext const &layoutContext) const {
|
||||
SystraceSection s("UIManager::startSurface");
|
||||
|
||||
auto shadowTree = std::make_unique<ShadowTree>(
|
||||
surfaceId, layoutConstraints, layoutContext, *this);
|
||||
auto shadowTreePointer = shadowTree.get();
|
||||
shadowTreeRegistry_.add(std::move(shadowTree));
|
||||
|
||||
runtimeExecutor_([=](jsi::Runtime &runtime) {
|
||||
auto uiManagerBinding = UIManagerBinding::getBinding(runtime);
|
||||
if (!uiManagerBinding) {
|
||||
return;
|
||||
}
|
||||
|
||||
uiManagerBinding->startSurface(runtime, surfaceId, moduleName, props);
|
||||
});
|
||||
|
||||
return *shadowTreePointer;
|
||||
}
|
||||
|
||||
void UIManager::stopSurface(SurfaceId surfaceId) const {
|
||||
SystraceSection s("UIManager::stopSurface");
|
||||
|
||||
// Stop any ongoing animations.
|
||||
stopSurfaceForAnimationDelegate(surfaceId);
|
||||
|
||||
// Waiting for all concurrent commits to be finished and unregistering the
|
||||
// `ShadowTree`.
|
||||
auto shadowTree = getShadowTreeRegistry().remove(surfaceId);
|
||||
|
||||
// As part of stopping a Surface, we need to properly destroy all
|
||||
// mounted views, so we need to commit an empty tree to trigger all
|
||||
// side-effects (including destroying and removing mounted views).
|
||||
if (shadowTree) {
|
||||
shadowTree->commitEmptyTree();
|
||||
}
|
||||
|
||||
// We execute JavaScript/React part of the process at the very end to minimize
|
||||
// any visible side-effects of stopping the Surface. Any possible commits from
|
||||
// the JavaScript side will not be able to reference a `ShadowTree` and will
|
||||
// fail silently.
|
||||
runtimeExecutor_([=](jsi::Runtime &runtime) {
|
||||
auto uiManagerBinding = UIManagerBinding::getBinding(runtime);
|
||||
if (!uiManagerBinding) {
|
||||
return;
|
||||
}
|
||||
|
||||
uiManagerBinding->stopSurface(runtime, surfaceId);
|
||||
});
|
||||
}
|
||||
|
||||
ShadowNode::Shared UIManager::getNewestCloneOfShadowNode(
|
||||
ShadowNode const &shadowNode) const {
|
||||
auto ancestorShadowNode = ShadowNode::Shared{};
|
||||
@@ -279,6 +335,10 @@ void UIManager::setBackgroundExecutor(
|
||||
backgroundExecutor_ = backgroundExecutor;
|
||||
}
|
||||
|
||||
void UIManager::setRuntimeExecutor(RuntimeExecutor const &runtimeExecutor) {
|
||||
runtimeExecutor_ = runtimeExecutor;
|
||||
}
|
||||
|
||||
void UIManager::visitBinding(
|
||||
std::function<void(UIManagerBinding const &uiManagerBinding)> callback,
|
||||
jsi::Runtime &runtime) const {
|
||||
@@ -354,7 +414,7 @@ void UIManager::setAnimationDelegate(UIManagerAnimationDelegate *delegate) {
|
||||
animationDelegate_ = delegate;
|
||||
}
|
||||
|
||||
void UIManager::stopSurfaceForAnimationDelegate(SurfaceId surfaceId) {
|
||||
void UIManager::stopSurfaceForAnimationDelegate(SurfaceId surfaceId) const {
|
||||
if (animationDelegate_ != nullptr) {
|
||||
animationDelegate_->stopSurface(surfaceId);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <folly/dynamic.h>
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
#include <ReactCommon/RuntimeExecutor.h>
|
||||
|
||||
#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h>
|
||||
#include <react/renderer/core/RawValue.h>
|
||||
#include <react/renderer/core/ShadowNode.h>
|
||||
@@ -42,6 +44,8 @@ class UIManager final : public ShadowTreeDelegate {
|
||||
void setDelegate(UIManagerDelegate *delegate);
|
||||
UIManagerDelegate *getDelegate();
|
||||
|
||||
void setRuntimeExecutor(RuntimeExecutor const &runtimeExecutor);
|
||||
|
||||
void setBackgroundExecutor(BackgroundExecutor const &backgroundExecutor);
|
||||
|
||||
/**
|
||||
@@ -54,7 +58,7 @@ class UIManager final : public ShadowTreeDelegate {
|
||||
/**
|
||||
* Execute stopSurface on any UIMAnagerAnimationDelegate.
|
||||
*/
|
||||
void stopSurfaceForAnimationDelegate(SurfaceId surfaceId);
|
||||
void stopSurfaceForAnimationDelegate(SurfaceId surfaceId) const;
|
||||
|
||||
void animationTick();
|
||||
|
||||
@@ -77,6 +81,17 @@ class UIManager final : public ShadowTreeDelegate {
|
||||
ShadowNode::Shared getNewestCloneOfShadowNode(
|
||||
ShadowNode const &shadowNode) const;
|
||||
|
||||
#pragma mark - Surface Start & Stop
|
||||
|
||||
ShadowTree const &startSurface(
|
||||
SurfaceId surfaceId,
|
||||
std::string const &moduleName,
|
||||
folly::dynamic const &props,
|
||||
LayoutConstraints const &layoutConstraints,
|
||||
LayoutContext const &layoutContext) const;
|
||||
|
||||
void stopSurface(SurfaceId surfaceId) const;
|
||||
|
||||
#pragma mark - ShadowTreeDelegate
|
||||
|
||||
void shadowTreeDidFinishTransaction(
|
||||
@@ -91,6 +106,7 @@ class UIManager final : public ShadowTreeDelegate {
|
||||
private:
|
||||
friend class UIManagerBinding;
|
||||
friend class Scheduler;
|
||||
friend class SurfaceHandler;
|
||||
|
||||
ShadowNode::Shared createNode(
|
||||
Tag tag,
|
||||
@@ -164,6 +180,7 @@ class UIManager final : public ShadowTreeDelegate {
|
||||
UIManagerDelegate *delegate_;
|
||||
UIManagerAnimationDelegate *animationDelegate_{nullptr};
|
||||
UIManagerBinding *uiManagerBinding_;
|
||||
RuntimeExecutor runtimeExecutor_{};
|
||||
ShadowTreeRegistry shadowTreeRegistry_{};
|
||||
BackgroundExecutor backgroundExecutor_{};
|
||||
|
||||
|
||||
@@ -798,7 +798,7 @@ SPEC CHECKSUMS:
|
||||
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
|
||||
DoubleConversion: cde416483dac037923206447da6e1454df403714
|
||||
FBLazyVector: 91e874a8823933a268c38765a88cbd5dba1fa024
|
||||
FBReactNativeSpec: f413828a0c0ca7fb738e67dd90281e454d353a46
|
||||
FBReactNativeSpec: 17a863c5e24969051850a3acab3a06069bb06e7f
|
||||
Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365
|
||||
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
|
||||
Flipper-Folly: e4493b013c02d9347d5e0cb4d128680239f6c78a
|
||||
|
||||
Reference in New Issue
Block a user