Fabric: `Element<>` now returns (and accepts) mutable (non const) shared pointers

Summary:
It makes perfect sense because `Builder` builds totally new shadow trees, so those are not sealed or used by anyone yet.
Assigning it to const shared pointer will do logical sealing (and it does not requires const-cast).
Fewer const-casts in the code, fewer bugs.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: sammy-SC

Differential Revision: D19596284

fbshipit-source-id: 75d1c706034958ba7e4bc80a68af75a57c46eb6f
This commit is contained in:
Valentin Shergin 2020-01-30 19:43:33 -08:00 коммит произвёл Facebook Github Bot
Родитель d64bf2c4f8
Коммит b39c75f20e
6 изменённых файлов: 22 добавлений и 21 удалений

Просмотреть файл

@ -36,8 +36,8 @@ TEST(ShadowNodeFamilyTest, sealObjectCorrectly) {
auto builder = ComponentBuilder{componentDescriptorRegistry}; auto builder = ComponentBuilder{componentDescriptorRegistry};
auto shadowNodeAAA = std::shared_ptr<ViewShadowNode const>{}; auto shadowNodeAAA = std::shared_ptr<ViewShadowNode>{};
auto shadowNodeAA = std::shared_ptr<ViewShadowNode const>{}; auto shadowNodeAA = std::shared_ptr<ViewShadowNode>{};
// clang-format off // clang-format off
auto elementA = auto elementA =

Просмотреть файл

@ -14,7 +14,7 @@ ComponentBuilder::ComponentBuilder(
ComponentDescriptorRegistry::Shared const &componentDescriptorRegistry) ComponentDescriptorRegistry::Shared const &componentDescriptorRegistry)
: componentDescriptorRegistry_(componentDescriptorRegistry){}; : componentDescriptorRegistry_(componentDescriptorRegistry){};
ShadowNode::Shared ComponentBuilder::build( ShadowNode::Unshared ComponentBuilder::build(
ElementFragment const &elementFragment) const { ElementFragment const &elementFragment) const {
auto &componentDescriptor = auto &componentDescriptor =
componentDescriptorRegistry_->at(elementFragment.componentHandle); componentDescriptorRegistry_->at(elementFragment.componentHandle);
@ -30,19 +30,21 @@ ShadowNode::Shared ComponentBuilder::build(
elementFragment.tag, elementFragment.surfaceId, nullptr}, elementFragment.tag, elementFragment.surfaceId, nullptr},
nullptr); nullptr);
auto shadowNode = componentDescriptor.createShadowNode( auto constShadowNode = componentDescriptor.createShadowNode(
ShadowNodeFragment{ ShadowNodeFragment{
elementFragment.props, elementFragment.props,
std::make_shared<ShadowNode::ListOfShared const>(children), std::make_shared<ShadowNode::ListOfShared const>(children),
elementFragment.state}, elementFragment.state},
family); family);
auto shadowNode = std::const_pointer_cast<ShadowNode>(constShadowNode);
if (elementFragment.referenceCallback) { if (elementFragment.referenceCallback) {
elementFragment.referenceCallback(shadowNode); elementFragment.referenceCallback(shadowNode);
} }
if (elementFragment.finalizeCallback) { if (elementFragment.finalizeCallback) {
elementFragment.finalizeCallback(const_cast<ShadowNode &>(*shadowNode)); elementFragment.finalizeCallback(*shadowNode);
} }
return shadowNode; return shadowNode;

Просмотреть файл

@ -42,16 +42,15 @@ class ComponentBuilder final {
* `ComponentDescriptorRegistry`. * `ComponentDescriptorRegistry`.
*/ */
template <typename ShadowNodeT> template <typename ShadowNodeT>
std::shared_ptr<ShadowNodeT const> build(Element<ShadowNodeT> element) const { std::shared_ptr<ShadowNodeT> build(Element<ShadowNodeT> element) const {
return std::static_pointer_cast<ShadowNodeT const>( return std::static_pointer_cast<ShadowNodeT>(build(element.fragment_));
build(element.fragment_));
} }
private: private:
/* /*
* Internal, type-erased version of `build`. * Internal, type-erased version of `build`.
*/ */
ShadowNode::Shared build(ElementFragment const &elementFragment) const; ShadowNode::Unshared build(ElementFragment const &elementFragment) const;
ComponentDescriptorRegistry::Shared componentDescriptorRegistry_; ComponentDescriptorRegistry::Shared componentDescriptorRegistry_;
}; };

Просмотреть файл

@ -31,10 +31,10 @@ template <typename ShadowNodeT>
class Element final { class Element final {
public: public:
using ConcreteProps = typename ShadowNodeT::ConcreteProps; using ConcreteProps = typename ShadowNodeT::ConcreteProps;
using SharedConcreteProps = typename ShadowNodeT::SharedConcreteProps; using SharedConcreteProps = std::shared_ptr<ConcreteProps const>;
using ConcreteEventEmitter = typename ShadowNodeT::ConcreteEventEmitter; using UnsharedConcreteProps = std::shared_ptr<ConcreteProps>;
using ConcreteShadowNode = ShadowNodeT; using ConcreteShadowNode = ShadowNodeT;
using ConcreteSharedShadowNode = std::shared_ptr<ConcreteShadowNode const>; using ConcreteUnsharedShadowNode = std::shared_ptr<ConcreteShadowNode>;
using ConcreteReferenceCallback = using ConcreteReferenceCallback =
std::function<void(std::shared_ptr<ShadowNodeT const> const &shadowNode)>; std::function<void(std::shared_ptr<ShadowNodeT const> const &shadowNode)>;
@ -105,7 +105,7 @@ class Element final {
* component which is being constructed. * component which is being constructed.
*/ */
Element &reference( Element &reference(
std::function<void(ConcreteSharedShadowNode const &shadowNode)> std::function<void(ConcreteUnsharedShadowNode const &shadowNode)>
callback) { callback) {
fragment_.referenceCallback = callback; fragment_.referenceCallback = callback;
return *this; return *this;
@ -115,10 +115,10 @@ class Element final {
* During component construction, assigns a given pointer to a component * During component construction, assigns a given pointer to a component
* that is being constructed. * that is being constructed.
*/ */
Element &reference(ConcreteSharedShadowNode &inShadowNode) { Element &reference(ConcreteUnsharedShadowNode &outShadowNode) {
fragment_.referenceCallback = [&](ShadowNode::Shared const &shadowNode) { fragment_.referenceCallback = [&](ShadowNode::Shared const &shadowNode) {
inShadowNode = outShadowNode = std::const_pointer_cast<ConcreteShadowNode>(
std::static_pointer_cast<ConcreteShadowNode const>(shadowNode); std::static_pointer_cast<ConcreteShadowNode const>(shadowNode));
}; };
return *this; return *this;
} }

Просмотреть файл

@ -28,7 +28,7 @@ class ElementFragment final {
using List = std::vector<ElementFragment>; using List = std::vector<ElementFragment>;
using ListOfShared = std::vector<Shared>; using ListOfShared = std::vector<Shared>;
using ReferenceCallback = using ReferenceCallback =
std::function<void(ShadowNode::Shared const &shadowNode)>; std::function<void(ShadowNode::Unshared const &shadowNode)>;
using FinalizeCallback = std::function<void(ShadowNode &shadowNode)>; using FinalizeCallback = std::function<void(ShadowNode &shadowNode)>;
/* /*

Просмотреть файл

@ -21,10 +21,10 @@ using namespace facebook::react;
TEST(ElementTest, testNormalCases) { TEST(ElementTest, testNormalCases) {
auto builder = simpleComponentBuilder(); auto builder = simpleComponentBuilder();
auto shadowNodeA = std::shared_ptr<RootShadowNode const>{}; auto shadowNodeA = std::shared_ptr<RootShadowNode>{};
auto shadowNodeAA = std::shared_ptr<ViewShadowNode const>{}; auto shadowNodeAA = std::shared_ptr<ViewShadowNode>{};
auto shadowNodeAB = std::shared_ptr<ViewShadowNode const>{}; auto shadowNodeAB = std::shared_ptr<ViewShadowNode>{};
auto shadowNodeABA = std::shared_ptr<ViewShadowNode const>{}; auto shadowNodeABA = std::shared_ptr<ViewShadowNode>{};
auto propsAA = std::make_shared<ViewProps>(); auto propsAA = std::make_shared<ViewProps>();
propsAA->nativeId = "node AA"; propsAA->nativeId = "node AA";