Use ShadowNodeFamily in state updates

Summary:
Changelog: [internal]

`ShadowNodeFamily` can be used as target in state updates instead of `ShadowNode`.

Reviewed By: shergin

Differential Revision: D19517428

fbshipit-source-id: 6831357e749239d5afec1dfd2d44a26ca6553e51
This commit is contained in:
Samuel Susla
2020-02-03 06:25:26 -08:00
committed by Facebook Github Bot
parent 1041ad5651
commit 595e954b13
11 changed files with 41 additions and 37 deletions
@@ -116,7 +116,7 @@ class ComponentDescriptor {
* State's data.
*/
virtual State::Shared createState(
const State::Shared &previousState,
ShadowNodeFamily::Shared const &family,
const StateData::Shared &data) const = 0;
/*
@@ -132,22 +132,17 @@ class ConcreteComponentDescriptor : public ComponentDescriptor {
}
virtual State::Shared createState(
const State::Shared &previousState,
ShadowNodeFamily::Shared const &family,
const StateData::Shared &data) const override {
if (std::is_same<ConcreteStateData, StateData>::value) {
// Default case: Returning `null` for nodes that don't use `State`.
return nullptr;
}
assert(previousState && "Provided `previousState` is nullptr.");
assert(data && "Provided `data` is nullptr.");
assert(
dynamic_cast<ConcreteState const *>(previousState.get()) &&
"Provided `previousState` has an incompatible type.");
return std::make_shared<const ConcreteState>(
std::move(*std::static_pointer_cast<ConcreteStateData>(data)),
*std::static_pointer_cast<const ConcreteState>(previousState));
std::move(*std::static_pointer_cast<ConcreteStateData>(data)), family);
}
virtual ShadowNodeFamily::Shared createFamily(
@@ -49,6 +49,10 @@ ComponentName ShadowNodeFamily::getComponentName() const {
return componentName_;
}
const ComponentDescriptor &ShadowNodeFamily::getComponentDescriptor() const {
return componentDescriptor_;
}
AncestorList ShadowNodeFamily::getAncestors(
ShadowNode const &ancestorShadowNode) const {
auto families = better::small_vector<ShadowNodeFamily const *, 64>{};
@@ -120,19 +124,14 @@ void ShadowNodeFamily::setTarget(StateTarget &&target) const {
}
void ShadowNodeFamily::dispatchRawState(
std::function<StateData::Shared()> &&stateData,
StateUpdate &&stateUpdate,
EventPriority priority) const {
auto eventDispatcher = eventDispatcher_.lock();
if (!eventDispatcher || !target_) { // why do we check !target_ here?
if (!eventDispatcher) {
return;
}
eventDispatcher->dispatchStateUpdate(
{[=]() -> std::pair<StateTarget, StateData::Shared> {
auto target = getTarget();
return {std::move(target), stateData()};
}},
priority);
eventDispatcher->dispatchStateUpdate(std::move(stateUpdate), priority);
}
} // namespace react
@@ -54,6 +54,11 @@ class ShadowNodeFamily {
ComponentHandle getComponentHandle() const;
ComponentName getComponentName() const;
/*
* Returns a concrete `ComponentDescriptor` that manages nodes of this type.
*/
const ComponentDescriptor &getComponentDescriptor() const;
/*
* Returns a list of all ancestors of the node relative to the given ancestor.
* The list starts from the given ancestor node and ends with the parent node
@@ -76,9 +81,8 @@ class ShadowNodeFamily {
/*
* Dispatches a state update with given priority.
*/
void dispatchRawState(
std::function<StateData::Shared()> &&stateData,
EventPriority priority) const;
void dispatchRawState(StateUpdate &&stateUpdate, EventPriority priority)
const;
private:
friend ShadowNode;
@@ -70,14 +70,14 @@ class ConcreteState : public State {
std::function<Data(const Data &oldData)> callback,
EventPriority priority = EventPriority::AsynchronousBatched) const {
family_->dispatchRawState(
{[family = family_,
callback = std::move(callback)]() -> StateData::Shared {
{[family = family_, callback = std::move(callback)]()
-> std::pair<SharedShadowNodeFamily const &, StateData::Shared> {
auto target = family->getTarget();
auto oldState = target.getShadowNode().getState();
auto oldData = std::static_pointer_cast<const ConcreteState>(oldState)
->getData();
auto newData = std::make_shared<Data>(callback(oldData));
return newData;
return {family, newData};
}},
priority);
}
+4 -1
View File
@@ -15,8 +15,11 @@
namespace facebook {
namespace react {
class ShadowNodeFamily;
using SharedShadowNodeFamily = std::shared_ptr<ShadowNodeFamily const>;
using StatePipe = std::function<
void(const StateData::Shared &data, const StateTarget &target)>;
void(const StateData::Shared &data, SharedShadowNodeFamily const &family)>;
} // namespace react
} // namespace facebook
@@ -10,7 +10,8 @@
namespace facebook {
namespace react {
std::pair<StateTarget, StateData::Shared> StateUpdate::operator()() const {
std::pair<SharedShadowNodeFamily const &, StateData::Shared> StateUpdate::
operator()() const {
return callback_();
}
+6 -3
View File
@@ -10,7 +10,6 @@
#include <functional>
#include <react/core/StateData.h>
#include <react/core/StateTarget.h>
namespace facebook {
namespace react {
@@ -18,16 +17,20 @@ namespace react {
/*
* Carries some logic and additional information about state update transaction.
*/
class ShadowNodeFamily;
using SharedShadowNodeFamily = std::shared_ptr<ShadowNodeFamily const>;
class StateUpdate {
public:
std::pair<StateTarget, StateData::Shared> operator()() const;
std::pair<SharedShadowNodeFamily const &, StateData::Shared> operator()()
const;
/*
* The current implementation simply uses `std::function` inside that captures
* everything which is needed to perform state update. That will be probably
* changed in the future.
*/
std::function<std::pair<StateTarget, StateData::Shared>()> callback_;
std::function<std::pair<SharedShadowNodeFamily const &, StateData::Shared>()>
callback_;
};
} // namespace react
+2 -2
View File
@@ -45,8 +45,8 @@ Scheduler::Scheduler(
auto statePipe = [uiManager](
const StateData::Shared &data,
const StateTarget &stateTarget) {
uiManager->updateState(stateTarget.getShadowNode(), data);
SharedShadowNodeFamily const &family) {
uiManager->updateState(family, data);
};
eventDispatcher_ = std::make_shared<EventDispatcher>(
+6 -7
View File
@@ -194,18 +194,17 @@ LayoutMetrics UIManager::getRelativeLayoutMetrics(
}
void UIManager::updateState(
ShadowNode const &shadowNode,
ShadowNodeFamily::Shared const &family,
StateData::Shared const &rawStateData) const {
auto &componentDescriptor = family->getComponentDescriptor();
auto state = componentDescriptor.createState(family, rawStateData);
shadowTreeRegistry_.visit(
shadowNode.getSurfaceId(), [&](ShadowTree const &shadowTree) {
family->getSurfaceId(), [&](ShadowTree const &shadowTree) {
shadowTree.tryCommit([&](RootShadowNode::Shared const
&oldRootShadowNode) {
return oldRootShadowNode->clone(
shadowNode.getFamily(), [&](ShadowNode const &oldShadowNode) {
auto &componentDescriptor =
oldShadowNode.getComponentDescriptor();
auto state = componentDescriptor.createState(
oldShadowNode.getState(), rawStateData);
*family, [&](ShadowNode const &oldShadowNode) {
return oldShadowNode.clone({
/* .props = */ ShadowNodeFragment::propsPlaceholder(),
/* .children = */ ShadowNodeFragment::childrenPlaceholder(),
+1 -1
View File
@@ -107,7 +107,7 @@ class UIManager final : public ShadowTreeDelegate {
* and performs a commit.
*/
void updateState(
ShadowNode const &shadowNode,
ShadowNodeFamily::Shared const &family,
StateData::Shared const &rawStateData) const;
void dispatchCommand(