diff --git a/ReactCommon/fabric/view/ConcreteViewShadowNode.h b/ReactCommon/fabric/view/ConcreteViewShadowNode.h new file mode 100644 index 000000000..320fbb0d4 --- /dev/null +++ b/ReactCommon/fabric/view/ConcreteViewShadowNode.h @@ -0,0 +1,167 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * 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 +#include +#include +#include +#include + +namespace facebook { +namespace react { + +/* + * Template for all -like classes (classes which have all same props + * as and similar basic behaviour). + * For example: , , but not , . + */ +template +class ConcreteViewShadowNode: + public ConcreteShadowNode, + public AccessibleShadowNode, + public YogaLayoutableShadowNode { + + static_assert(std::is_base_of::value, "ViewPropsT must be a descendant of ViewProps"); + static_assert(std::is_base_of::value, "ViewPropsT must be a descendant of YogaStylableProps"); + static_assert(std::is_base_of::value, "ViewPropsT must be a descendant of AccessibilityProps"); + +public: + + using ConcreteViewProps = ViewPropsT; + using SharedConcreteViewProps = std::shared_ptr; + using SharedConcreteViewShadowNode = std::shared_ptr; + + ConcreteViewShadowNode( + const Tag &tag, + const Tag &rootTag, + const InstanceHandle &instanceHandle, + const SharedViewProps &props = ConcreteViewShadowNode::defaultSharedProps(), + const SharedShadowNodeSharedList &children = ShadowNode::emptySharedShadowNodeSharedList(), + const ShadowNodeCloneFunction &cloneFunction = nullptr + ): + ConcreteShadowNode( + tag, + rootTag, + instanceHandle, + props, + children, + cloneFunction + ), + AccessibleShadowNode( + props + ), + YogaLayoutableShadowNode( + props, + children + ) {}; + + ConcreteViewShadowNode( + const SharedConcreteViewShadowNode &shadowNode, + const SharedViewProps &props = nullptr, + const SharedShadowNodeSharedList &children = nullptr + ): + ConcreteShadowNode( + shadowNode, + props, + children + ), + AccessibleShadowNode( + shadowNode, + props + ), + YogaLayoutableShadowNode( + shadowNode, + props, + children + ) {}; + + void appendChild(const SharedShadowNode &child) { + ensureUnsealed(); + + ShadowNode::appendChild(child); + + auto yogaLayoutableChild = std::dynamic_pointer_cast(child); + if (yogaLayoutableChild) { + YogaLayoutableShadowNode::appendChild(yogaLayoutableChild); + } + } + + SharedLayoutableShadowNode cloneAndReplaceChild(const SharedLayoutableShadowNode &child) override { + ensureUnsealed(); + + auto childShadowNode = std::dynamic_pointer_cast(child); + assert(childShadowNode); + auto childShadowNodeClone = childShadowNode->clone(); + + // This is overloading of `SharedLayoutableShadowNode::cloneAndReplaceChild`, + // the method is used to clone some node as a preparation for future mutation + // caused by relayout. + // Because those changes are not requested by UIManager, they add a layer + // of node generation (between the committed stage and new proposed stage). + // That additional layer confuses the Diffing algorithm which uses + // `sourceNode` for referencing the previous (aka committed) stage + // of the tree to produce mutation instructions. + // In other words, if we don't compensate this change here, + // the Diffing algorithm will compare wrong trees + // ("new-but-not-laid-out-yet vs. new" instead of "committed vs. new"). + auto nonConstChildShadowNodeClone = std::const_pointer_cast(childShadowNodeClone); + nonConstChildShadowNodeClone->shallowSourceNode(); + + ShadowNode::replaceChild(childShadowNode, childShadowNodeClone); + return std::dynamic_pointer_cast(childShadowNodeClone); + } + +#pragma mark - Equality + + bool operator==(const ShadowNode& rhs) const override { + if (!ShadowNode::operator==(rhs)) { + return false; + } + + auto &&other = static_cast(rhs); + return getLayoutMetrics() == other.getLayoutMetrics(); + } + +#pragma mark - DebugStringConvertible + + SharedDebugStringConvertibleList getDebugProps() const override { + SharedDebugStringConvertibleList list = {}; + + auto basePropsList = ShadowNode::getDebugProps(); + std::move(basePropsList.begin(), basePropsList.end(), std::back_inserter(list)); + + list.push_back(std::make_shared("layout", "", YogaLayoutableShadowNode::getDebugProps())); + + return list; + } + +private: + +#pragma mark - LayoutableShadowNode + + SharedLayoutableShadowNodeList getLayoutableChildNodes() const override { + SharedLayoutableShadowNodeList sharedLayoutableShadowNodeList = {}; + for (auto child : *ShadowNode::children_) { + const SharedLayoutableShadowNode layoutableShadowNode = std::dynamic_pointer_cast(child); + if (!layoutableShadowNode) { + continue; + } + + sharedLayoutableShadowNodeList.push_back(layoutableShadowNode); + } + + return sharedLayoutableShadowNodeList; + } + +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/view/ViewShadowNode.cpp b/ReactCommon/fabric/view/ViewShadowNode.cpp index 51d4be23b..2bf7f30d7 100644 --- a/ReactCommon/fabric/view/ViewShadowNode.cpp +++ b/ReactCommon/fabric/view/ViewShadowNode.cpp @@ -7,138 +7,12 @@ #include "ViewShadowNode.h" -#include - -#include - namespace facebook { namespace react { -#pragma mark - Constructors - -ViewShadowNode::ViewShadowNode( - const Tag &tag, - const Tag &rootTag, - const InstanceHandle &instanceHandle, - const SharedViewProps &props, - const SharedShadowNodeSharedList &children, - const ShadowNodeCloneFunction &cloneFunction -): - ConcreteShadowNode( - tag, - rootTag, - instanceHandle, - props, - children, - cloneFunction - ), - AccessibleShadowNode( - props - ), - YogaLayoutableShadowNode( - props, - children - ) {}; - -ViewShadowNode::ViewShadowNode( - const SharedViewShadowNode &shadowNode, - const SharedViewProps &props, - const SharedShadowNodeSharedList &children -): - ConcreteShadowNode( - shadowNode, - props, - children - ), - AccessibleShadowNode( - shadowNode, - props - ), - YogaLayoutableShadowNode( - shadowNode, - props, - children - ) {}; - ComponentName ViewShadowNode::getComponentName() const { return ComponentName("View"); } -void ViewShadowNode::appendChild(const SharedShadowNode &child) { - ensureUnsealed(); - - ShadowNode::appendChild(child); - - auto yogaLayoutableChild = std::dynamic_pointer_cast(child); - if (yogaLayoutableChild) { - YogaLayoutableShadowNode::appendChild(yogaLayoutableChild); - } -} - -#pragma mark - YogaLayoutableShadowNode - -SharedLayoutableShadowNodeList ViewShadowNode::getLayoutableChildNodes() const { - SharedLayoutableShadowNodeList sharedLayoutableShadowNodeList = {}; - for (auto child : *children_) { - const SharedLayoutableShadowNode layoutableShadowNode = std::dynamic_pointer_cast(child); - if (!layoutableShadowNode) { - continue; - } - - sharedLayoutableShadowNodeList.push_back(layoutableShadowNode); - } - - return sharedLayoutableShadowNodeList; -} - -SharedLayoutableShadowNode ViewShadowNode::cloneAndReplaceChild(const SharedLayoutableShadowNode &child) { - ensureUnsealed(); - - auto childShadowNode = std::dynamic_pointer_cast(child); - assert(childShadowNode); - auto childShadowNodeClone = childShadowNode->clone(); - - // This is overloading of `SharedLayoutableShadowNode::cloneAndReplaceChild`, - // the method is used to clone some node as a preparation for future mutation - // caused by relayout. - // Because those changes are not requested by UIManager, they add a layer - // of node generation (between the committed stage and new proposed stage). - // That additional layer confuses the Diffing algorithm which uses - // `sourceNode` for referencing the previous (aka committed) stage - // of the tree to produce mutation instructions. - // In other words, if we don't compensate this change here, - // the Diffing algorithm will compare wrong trees - // ("new-but-not-laid-out-yet vs. new" instead of "committed vs. new"). - auto nonConstChildShadowNodeClone = std::const_pointer_cast(childShadowNodeClone); - nonConstChildShadowNodeClone->shallowSourceNode(); - - ShadowNode::replaceChild(childShadowNode, childShadowNodeClone); - return std::dynamic_pointer_cast(childShadowNodeClone); -} - -#pragma mark - Equality - -bool ViewShadowNode::operator==(const ShadowNode& rhs) const { - if (!ShadowNode::operator==(rhs)) { - return false; - } - - auto &&other = static_cast(rhs); - return getLayoutMetrics() == other.getLayoutMetrics(); -} - -#pragma mark - DebugStringConvertible - -SharedDebugStringConvertibleList ViewShadowNode::getDebugProps() const { - SharedDebugStringConvertibleList list = {}; - - auto basePropsList = ShadowNode::getDebugProps(); - std::move(basePropsList.begin(), basePropsList.end(), std::back_inserter(list)); - - list.push_back(std::make_shared("layout", "", YogaLayoutableShadowNode::getDebugProps())); - - return list; -} - } // namespace react } // namespace facebook diff --git a/ReactCommon/fabric/view/ViewShadowNode.h b/ReactCommon/fabric/view/ViewShadowNode.h index 5809430df..d063b0196 100644 --- a/ReactCommon/fabric/view/ViewShadowNode.h +++ b/ReactCommon/fabric/view/ViewShadowNode.h @@ -7,12 +7,10 @@ #pragma once -#include -#include -#include -#include +#include + #include -#include +#include namespace facebook { namespace react { @@ -21,48 +19,14 @@ class ViewShadowNode; using SharedViewShadowNode = std::shared_ptr; -class ViewShadowNode: - public ConcreteShadowNode, - public AccessibleShadowNode, - public YogaLayoutableShadowNode { - - static_assert(std::is_base_of::value, "ViewProps must be a descendant of YogaStylableProps"); - static_assert(std::is_base_of::value, "ViewProps must be a descendant of AccessibilityProps"); +class ViewShadowNode final: + public ConcreteViewShadowNode { public: - ViewShadowNode( - const Tag &tag, - const Tag &rootTag, - const InstanceHandle &instanceHandle, - const SharedViewProps &props = ViewShadowNode::defaultSharedProps(), - const SharedShadowNodeSharedList &children = ShadowNode::emptySharedShadowNodeSharedList(), - const ShadowNodeCloneFunction &cloneFunction = nullptr - ); - ViewShadowNode( - const SharedViewShadowNode &shadowNode, - const SharedViewProps &props = nullptr, - const SharedShadowNodeSharedList &children = nullptr - ); + using ConcreteViewShadowNode::ConcreteViewShadowNode; ComponentName getComponentName() const override; - - void appendChild(const SharedShadowNode &child); - -#pragma mark - Equality - - bool operator==(const ShadowNode& rhs) const override; - -#pragma mark - DebugStringConvertible - - SharedDebugStringConvertibleList getDebugProps() const override; - -private: - -#pragma mark - LayoutableShadowNode - - SharedLayoutableShadowNodeList getLayoutableChildNodes() const override; - SharedLayoutableShadowNode cloneAndReplaceChild(const SharedLayoutableShadowNode &child) override; }; } // namespace react