diff --git a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp index dd734e6905f..d32e65602cc 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp +++ b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp @@ -23,20 +23,25 @@ SharedShadowNodeSharedList ShadowNode::emptySharedShadowNodeSharedList() { return emptySharedShadowNodeSharedList; } +bool ShadowNode::sameFamily(const ShadowNode &first, const ShadowNode &second) { + return first.family_ == second.family_; +} + #pragma mark - Constructors ShadowNode::ShadowNode( const ShadowNodeFragment &fragment, const ComponentDescriptor &componentDescriptor) - : tag_(fragment.tag), - rootTag_(fragment.rootTag), - props_(fragment.props), - eventEmitter_(fragment.eventEmitter), + : props_(fragment.props), children_( fragment.children ? fragment.children : emptySharedShadowNodeSharedList()), state_(fragment.state), - componentDescriptor_(componentDescriptor), + family_(std::make_shared( + fragment.tag, + fragment.rootTag, + fragment.eventEmitter, + componentDescriptor)), childrenAreShared_(true), revision_(1) { assert(props_); @@ -46,10 +51,7 @@ ShadowNode::ShadowNode( ShadowNode::ShadowNode( const ShadowNode &sourceShadowNode, const ShadowNodeFragment &fragment) - : tag_(sourceShadowNode.tag_), - rootTag_(sourceShadowNode.rootTag_), - props_(fragment.props ? fragment.props : sourceShadowNode.props_), - eventEmitter_(fragment.eventEmitter), + : props_(fragment.props ? fragment.props : sourceShadowNode.props_), children_( fragment.children ? fragment.children : sourceShadowNode.children_), localData_( @@ -58,7 +60,7 @@ ShadowNode::ShadowNode( state_( fragment.state ? fragment.state : sourceShadowNode.getCommitedState()), - componentDescriptor_(sourceShadowNode.componentDescriptor_), + family_(sourceShadowNode.family_), childrenAreShared_(true), revision_(sourceShadowNode.revision_ + 1) { // `tag`, `surfaceId`, and `eventEmitter` cannot be changed with cloning. @@ -72,7 +74,7 @@ ShadowNode::ShadowNode( } UnsharedShadowNode ShadowNode::clone(const ShadowNodeFragment &fragment) const { - return componentDescriptor_.cloneShadowNode(*this, fragment); + return family_->componentDescriptor_.cloneShadowNode(*this, fragment); } #pragma mark - Getters @@ -81,24 +83,24 @@ const SharedShadowNodeList &ShadowNode::getChildren() const { return *children_; } -SharedProps ShadowNode::getProps() const { +const SharedProps &ShadowNode::getProps() const { return props_; } -SharedEventEmitter ShadowNode::getEventEmitter() const { - return eventEmitter_; +const SharedEventEmitter &ShadowNode::getEventEmitter() const { + return family_->eventEmitter_; } Tag ShadowNode::getTag() const { - return tag_; + return family_->tag_; } -Tag ShadowNode::getRootTag() const { - return rootTag_; +SurfaceId ShadowNode::getSurfaceId() const { + return family_->surfaceId_; } const ComponentDescriptor &ShadowNode::getComponentDescriptor() const { - return componentDescriptor_; + return family_->componentDescriptor_; } const State::Shared &ShadowNode::getState() const { @@ -175,7 +177,7 @@ void ShadowNode::cloneChildrenIfShared() { } void ShadowNode::setMounted(bool mounted) const { - eventEmitter_->setEnabled(mounted); + family_->eventEmitter_->setEnabled(mounted); if (mounted && state_) { state_->commit(*this); } @@ -229,7 +231,7 @@ SharedDebugStringConvertibleList ShadowNode::getDebugChildren() const { SharedDebugStringConvertibleList ShadowNode::getDebugProps() const { return props_->getDebugProps() + SharedDebugStringConvertibleList{ - debugStringConvertibleItem("tag", folly::to(tag_))}; + debugStringConvertibleItem("tag", folly::to(getTag()))}; } #endif diff --git a/ReactCommon/fabric/core/shadownode/ShadowNode.h b/ReactCommon/fabric/core/shadownode/ShadowNode.h index 3e9d9671039..8e184322cc4 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNode.h +++ b/ReactCommon/fabric/core/shadownode/ShadowNode.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,12 @@ class ShadowNode : public virtual Sealable, static SharedShadowNodeSharedList emptySharedShadowNodeSharedList(); + /* + * Returns `true` if nodes belong to the same family (they were cloned one + * from each other or from the same source node). + */ + static bool sameFamily(const ShadowNode &first, const ShadowNode &second); + #pragma mark - Constructors /* @@ -77,11 +84,11 @@ class ShadowNode : public virtual Sealable, virtual ComponentHandle getComponentHandle() const = 0; virtual ComponentName getComponentName() const = 0; - const SharedShadowNodeList &getChildren() const; - SharedProps getProps() const; - SharedEventEmitter getEventEmitter() const; + SharedProps const &getProps() const; + SharedShadowNodeList const &getChildren() const; + SharedEventEmitter const &getEventEmitter() const; Tag getTag() const; - Tag getRootTag() const; + SurfaceId getSurfaceId() const; /* * Returns a concrete `ComponentDescriptor` that manages nodes of this type. @@ -155,10 +162,7 @@ class ShadowNode : public virtual Sealable, #endif protected: - Tag tag_; - Tag rootTag_; SharedProps props_; - SharedEventEmitter eventEmitter_; SharedShadowNodeSharedList children_; SharedLocalData localData_; State::Shared state_; @@ -171,10 +175,9 @@ class ShadowNode : public virtual Sealable, void cloneChildrenIfShared(); /* - * A reference to a concrete `ComponentDescriptor` that manages nodes of this - * type. + * Pointer to a family object that this shadow node belongs to. */ - const ComponentDescriptor &componentDescriptor_; + ShadowNodeFamily::Shared family_; /* * Indicates that `children` list is shared between nodes and need diff --git a/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.cpp b/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.cpp new file mode 100644 index 00000000000..5cab7803876 --- /dev/null +++ b/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.cpp @@ -0,0 +1,24 @@ +/** + * 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 "ShadowNodeFamily.h" + +namespace facebook { +namespace react { + +ShadowNodeFamily::ShadowNodeFamily( + Tag tag, + SurfaceId surfaceId, + SharedEventEmitter const &eventEmitter, + ComponentDescriptor const &componentDescriptor) + : tag_(tag), + surfaceId_(surfaceId), + eventEmitter_(eventEmitter), + componentDescriptor_(componentDescriptor) {} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.h b/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.h new file mode 100644 index 00000000000..41f8370f750 --- /dev/null +++ b/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.h @@ -0,0 +1,61 @@ +/** + * 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 + +#include +#include + +namespace facebook { +namespace react { + +class ComponentDescriptor; + +/* + * Represents all things that shadow nodes from the same family have in common. + * To be used inside `ShadowNode` class *only*. + */ +class ShadowNodeFamily { + public: + using Shared = std::shared_ptr; + using Weak = std::weak_ptr; + + ShadowNodeFamily( + Tag tag, + SurfaceId surfaceId, + SharedEventEmitter const &eventEmitter, + ComponentDescriptor const &componentDescriptor); + + private: + friend ShadowNode; + + /* + * Deprecated. + */ + Tag const tag_; + + /* + * Identifier of a running Surface instance. + */ + SurfaceId const surfaceId_; + + /* + * `EventEmitter` associated with all nodes of the family. + */ + SharedEventEmitter const eventEmitter_; + + /* + * Reference to a concrete `ComponentDescriptor` that manages nodes of this + * type. + */ + ComponentDescriptor const &componentDescriptor_; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/core/tests/ComponentDescriptorTest.cpp b/ReactCommon/fabric/core/tests/ComponentDescriptorTest.cpp index b19344dc636..405dde03592 100644 --- a/ReactCommon/fabric/core/tests/ComponentDescriptorTest.cpp +++ b/ReactCommon/fabric/core/tests/ComponentDescriptorTest.cpp @@ -34,7 +34,7 @@ TEST(ComponentDescriptorTest, createShadowNode) { node->getComponentName().c_str(), TestShadowNode::Name().c_str()); ASSERT_STREQ(node->getComponentName().c_str(), "Test"); ASSERT_EQ(node->getTag(), 9); - ASSERT_EQ(node->getRootTag(), 1); + ASSERT_EQ(node->getSurfaceId(), 1); ASSERT_STREQ(node->getProps()->nativeId.c_str(), "abc"); } @@ -54,7 +54,7 @@ TEST(ComponentDescriptorTest, cloneShadowNode) { ASSERT_STREQ(cloned->getComponentName().c_str(), "Test"); ASSERT_EQ(cloned->getTag(), 9); - ASSERT_EQ(cloned->getRootTag(), 1); + ASSERT_EQ(cloned->getSurfaceId(), 1); ASSERT_STREQ(cloned->getProps()->nativeId.c_str(), "abc"); } diff --git a/ReactCommon/fabric/core/tests/ShadowNodeTest.cpp b/ReactCommon/fabric/core/tests/ShadowNodeTest.cpp index 4a970ceb099..b332391e4b7 100644 --- a/ReactCommon/fabric/core/tests/ShadowNodeTest.cpp +++ b/ReactCommon/fabric/core/tests/ShadowNodeTest.cpp @@ -41,7 +41,7 @@ TEST(ShadowNodeTest, handleShadowNodeCreation) { ASSERT_FALSE(node->getSealed()); ASSERT_STREQ(node->getComponentName().c_str(), "Test"); ASSERT_EQ(node->getTag(), 9); - ASSERT_EQ(node->getRootTag(), 1); + ASSERT_EQ(node->getSurfaceId(), 1); ASSERT_EQ(node->getEventEmitter(), nullptr); ASSERT_EQ(node->getChildren().size(), 0); @@ -67,7 +67,7 @@ TEST(ShadowNodeTest, handleShadowNodeSimpleCloning) { ASSERT_STREQ(node->getComponentName().c_str(), "Test"); ASSERT_EQ(node->getTag(), 9); - ASSERT_EQ(node->getRootTag(), 1); + ASSERT_EQ(node->getSurfaceId(), 1); ASSERT_EQ(node->getEventEmitter(), nullptr); } @@ -154,7 +154,7 @@ TEST(ShadowNodeTest, handleCloneFunction) { // Both nodes have same content. ASSERT_EQ(firstNode->getTag(), firstNodeClone->getTag()); - ASSERT_EQ(firstNode->getRootTag(), firstNodeClone->getRootTag()); + ASSERT_EQ(firstNode->getSurfaceId(), firstNodeClone->getSurfaceId()); ASSERT_EQ(firstNode->getProps(), firstNodeClone->getProps()); } diff --git a/ReactCommon/fabric/mounting/Differentiator.cpp b/ReactCommon/fabric/mounting/Differentiator.cpp index 62bf19d1229..7c7b7f766a3 100644 --- a/ReactCommon/fabric/mounting/Differentiator.cpp +++ b/ReactCommon/fabric/mounting/Differentiator.cpp @@ -218,8 +218,8 @@ ShadowViewMutationList calculateShadowViewMutations( const ShadowNode &newRootShadowNode) { SystraceSection s("calculateShadowViewMutations"); - // Root shadow nodes must have same tag. - assert(oldRootShadowNode.getTag() == newRootShadowNode.getTag()); + // Root shadow nodes must be belong the same family. + assert(ShadowNode::sameFamily(oldRootShadowNode, newRootShadowNode)); ShadowViewMutationList mutations; diff --git a/ReactCommon/fabric/uimanager/Scheduler.cpp b/ReactCommon/fabric/uimanager/Scheduler.cpp index 096d33d1eda..37f2151cbcb 100644 --- a/ReactCommon/fabric/uimanager/Scheduler.cpp +++ b/ReactCommon/fabric/uimanager/Scheduler.cpp @@ -281,7 +281,7 @@ void Scheduler::uiManagerDidCreateShadowNode( if (delegate_) { auto shadowView = ShadowView(*shadowNode); delegate_->schedulerDidRequestPreliminaryViewAllocation( - shadowNode->getRootTag(), shadowView); + shadowNode->getSurfaceId(), shadowView); } } diff --git a/ReactCommon/fabric/uimanager/UIManager.cpp b/ReactCommon/fabric/uimanager/UIManager.cpp index da06855ea38..6c6c9552dfd 100644 --- a/ReactCommon/fabric/uimanager/UIManager.cpp +++ b/ReactCommon/fabric/uimanager/UIManager.cpp @@ -98,7 +98,7 @@ void UIManager::setNativeProps( }); shadowTreeRegistry_->visit( - shadowNode->getRootTag(), [&](const ShadowTree &shadowTree) { + shadowNode->getSurfaceId(), [&](const ShadowTree &shadowTree) { shadowTree.tryCommit( [&](const SharedRootShadowNode &oldRootShadowNode) { return oldRootShadowNode->clone(shadowNode, newShadowNode); @@ -116,7 +116,7 @@ LayoutMetrics UIManager::getRelativeLayoutMetrics( if (!ancestorShadowNode) { shadowTreeRegistry_->visit( - shadowNode.getRootTag(), [&](const ShadowTree &shadowTree) { + shadowNode.getSurfaceId(), [&](const ShadowTree &shadowTree) { shadowTree.tryCommit( [&](const SharedRootShadowNode &oldRootShadowNode) { ancestorShadowNode = oldRootShadowNode.get(); @@ -158,7 +158,7 @@ void UIManager::updateState( }); shadowTreeRegistry_->visit( - shadowNode->getRootTag(), [&](const ShadowTree &shadowTree) { + shadowNode->getSurfaceId(), [&](const ShadowTree &shadowTree) { shadowTree.tryCommit( [&](const SharedRootShadowNode &oldRootShadowNode) { return oldRootShadowNode->clone(shadowNode, newShadowNode);