diff --git a/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h b/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h index 7f7b82d9adb..8d1403b890b 100644 --- a/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h +++ b/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h @@ -126,14 +126,15 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { } return std::make_shared( - ConcreteShadowNode::initialStateData( - fragment, family->getSurfaceId(), *this), + std::make_shared( + ConcreteShadowNode::initialStateData( + fragment, family->getSurfaceId(), *this)), family); } virtual State::Shared createState( ShadowNodeFamily::Shared const &family, - const StateData::Shared &data) const override { + StateData::Shared const &data) const override { if (std::is_same::value) { // Default case: Returning `null` for nodes that don't use `State`. return nullptr; @@ -141,8 +142,8 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { assert(data && "Provided `data` is nullptr."); - return std::make_shared( - std::move(*std::static_pointer_cast(data)), family); + return std::make_shared( + std::static_pointer_cast(data), family); } virtual ShadowNodeFamily::Shared createFamily( diff --git a/ReactCommon/fabric/core/shadownode/ConcreteShadowNode.h b/ReactCommon/fabric/core/shadownode/ConcreteShadowNode.h index d503b9b751b..59a606b211b 100644 --- a/ReactCommon/fabric/core/shadownode/ConcreteShadowNode.h +++ b/ReactCommon/fabric/core/shadownode/ConcreteShadowNode.h @@ -106,7 +106,8 @@ class ConcreteShadowNode : public ShadowNode { */ void setStateData(ConcreteStateData &&data) { ensureUnsealed(); - state_ = std::make_shared(std::move(data), *state_); + state_ = std::make_shared( + std::make_shared(std::move(data)), *state_); } /* diff --git a/ReactCommon/fabric/core/state/ConcreteState.h b/ReactCommon/fabric/core/state/ConcreteState.h index 60806235682..7c8b98a289a 100644 --- a/ReactCommon/fabric/core/state/ConcreteState.h +++ b/ReactCommon/fabric/core/state/ConcreteState.h @@ -26,20 +26,30 @@ class ConcreteState : public State { public: using Shared = std::shared_ptr; using Data = DataT; + using SharedData = std::shared_ptr; - explicit ConcreteState(Data &&data, ShadowNodeFamily::Shared const &family) - : State(family), data_(std::move(data)) {} + /* + * Creates an updated `State` object with given previous one and `data`. + */ + explicit ConcreteState(SharedData const &data, State const &state) + : State(data, state) {} - explicit ConcreteState(Data &&data, State const &other) - : State(other), data_(std::move(data)) {} + /* + * Creates a first-of-its-family `State` object with given `family` and + * `data`. + */ + explicit ConcreteState( + SharedData const &data, + ShadowNodeFamily::Shared const &family) + : State(data, family) {} virtual ~ConcreteState() = default; /* * Returns stored data. */ - const Data &getData() const { - return data_; + Data const &getData() const { + return *std::static_pointer_cast(data_); } /* @@ -67,7 +77,7 @@ class ConcreteState : public State { * of conflict. */ void updateState( - std::function callback, + std::function callback, EventPriority priority = EventPriority::AsynchronousBatched) const { family_->dispatchRawState( {[family = family_, callback = std::move(callback)]() @@ -84,16 +94,13 @@ class ConcreteState : public State { #ifdef ANDROID folly::dynamic getDynamic() const override { - return data_.getDynamic(); + return getData().getDynamic(); } void updateState(folly::dynamic data) const override { - updateState(std::move(Data(data_, data))); + updateState(std::move(Data(getData(), data))); } #endif - - private: - DataT data_; }; } // namespace react diff --git a/ReactCommon/fabric/core/state/State.cpp b/ReactCommon/fabric/core/state/State.cpp index e424247d4e6..967f802f93f 100644 --- a/ReactCommon/fabric/core/state/State.cpp +++ b/ReactCommon/fabric/core/state/State.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #ifdef ANDROID @@ -20,11 +21,13 @@ namespace facebook { namespace react { -State::State(State const &state) - : family_(state.family_), revision_(state.revision_ + 1){}; +State::State(StateData::Shared const &data, State const &state) + : family_(state.family_), data_(data), revision_(state.revision_ + 1){}; -State::State(ShadowNodeFamily::Shared const &family) - : family_(family), revision_{1} {}; +State::State( + StateData::Shared const &data, + ShadowNodeFamily::Shared const &family) + : family_(family), data_(data), revision_{1} {}; void State::commit(std::shared_ptr const &shadowNode) const { family_->setTarget(StateTarget{shadowNode}); diff --git a/ReactCommon/fabric/core/state/State.h b/ReactCommon/fabric/core/state/State.h index d76d48603c1..ea71ad7c46e 100644 --- a/ReactCommon/fabric/core/state/State.h +++ b/ReactCommon/fabric/core/state/State.h @@ -24,8 +24,17 @@ class State { public: using Shared = std::shared_ptr; - explicit State(State const &state); - explicit State(ShadowNodeFamily::Shared const &family); + protected: + /* + * Constructors are protected to make calling them directly with + * type-erasured arguments impossible. + */ + explicit State(StateData::Shared const &data, State const &state); + explicit State( + StateData::Shared const &data, + ShadowNodeFamily::Shared const &family); + + public: virtual ~State() = default; /* @@ -53,12 +62,17 @@ class State { void commit(std::shared_ptr const &shadowNode) const; protected: - ShadowNodeFamily::Shared family_; - - private: friend class StateCoordinator; friend class ShadowNodeFamily; + ShadowNodeFamily::Shared family_; + + /* + * Type-erasured pointer to arbitrary component-specific data held by the + * `State`. + */ + StateData::Shared data_; + /* * Indicates that the state was committed once and then was replaced by a * newer one. diff --git a/ReactCommon/fabric/core/state/StateData.h b/ReactCommon/fabric/core/state/StateData.h index 930a8f3b788..b13b5950490 100644 --- a/ReactCommon/fabric/core/state/StateData.h +++ b/ReactCommon/fabric/core/state/StateData.h @@ -21,7 +21,7 @@ namespace react { * don't have a state. */ struct StateData final { - using Shared = std::shared_ptr; + using Shared = std::shared_ptr; #ifdef ANDROID StateData() = default;