diff --git a/ReactCommon/fabric/core/BUCK b/ReactCommon/fabric/core/BUCK index 977460fc5..4e062a8bc 100644 --- a/ReactCommon/fabric/core/BUCK +++ b/ReactCommon/fabric/core/BUCK @@ -23,6 +23,7 @@ rn_xplat_cxx_library( exported_headers = subdir_glob( [ ("primitives", "*.h"), + ("componentdescriptor", "*.h"), ("shadownode", "*.h"), ], prefix = "fabric/core", diff --git a/ReactCommon/fabric/core/componentdescriptor/ComponentDescriptor.h b/ReactCommon/fabric/core/componentdescriptor/ComponentDescriptor.h new file mode 100644 index 000000000..975900c91 --- /dev/null +++ b/ReactCommon/fabric/core/componentdescriptor/ComponentDescriptor.h @@ -0,0 +1,71 @@ +/** + * 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 + +namespace facebook { +namespace react { + +class ComponentDescriptor; + +using SharedComponentDescriptor = std::shared_ptr; + +/* + * Abstract class defining an interface of `ComponentDescriptor`. + * `ComponentDescriptor` represents particular `ShadowNode` type and + * defines (customizes) basic operations with particular kind of + * `ShadowNode`s (such as creating, cloning, props and children managing). + */ +class ComponentDescriptor { +public: + + /* + * Returns `componentHandle` associated with particular kind of components. + * All `ShadowNode`s of this type must return same `componentHandle`. + */ + virtual ComponentHandle getComponentHandle() const = 0; + + /* + * Returns component's name. + * React uses a `name` to refer to particular kind of components in + * `create` requests. + */ + virtual ComponentName getComponentName() const = 0; + + /* + * Creates a new `ShadowNode` of a particular type. + */ + virtual SharedShadowNode createShadowNode( + const Tag &tag, + const Tag &rootTag, + const InstanceHandle &instanceHandle, + const RawProps &rawProps + ) const = 0; + + /* + * Clones a `ShadowNode` with optionally new `props` and/or `children`. + */ + virtual SharedShadowNode cloneShadowNode( + const SharedShadowNode &shadowNode, + const SharedRawProps &rawProps = nullptr, + const SharedShadowNodeSharedList &children = nullptr + ) const = 0; + + /* + * Appends (by mutating) a given `childShadowNode` to `parentShadowNode`. + */ + virtual void appendChild( + const SharedShadowNode &parentShadowNode, + const SharedShadowNode &childShadowNode + ) const = 0; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h b/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h new file mode 100644 index 000000000..0a521bd49 --- /dev/null +++ b/ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h @@ -0,0 +1,66 @@ +/** + * 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 + +namespace facebook { +namespace react { + +/* + * Default template-based implementation of ComponentDescriptor. + * Use your `ShadowNode` type as a template argument and override any methods + * if necessary. + */ +template +class ConcreteComponentDescriptor: public ComponentDescriptor { + static_assert(std::is_base_of::value, "ShadowNodeT must be a descendant of ShadowNode"); + + using SharedShadowNodeT = std::shared_ptr; + using SharedConcreteProps = typename ShadowNodeT::SharedConcreteProps; + +public: + ComponentHandle getComponentHandle() const override { + return typeid(ShadowNodeT).hash_code(); + } + + SharedShadowNode createShadowNode( + const Tag &tag, + const Tag &rootTag, + const InstanceHandle &instanceHandle, + const RawProps &rawProps + ) const override { + auto props = ShadowNodeT::Props(rawProps); + return std::make_shared(tag, rootTag, instanceHandle, props); + } + + SharedShadowNode cloneShadowNode( + const SharedShadowNode &shadowNode, + const SharedRawProps &rawProps = nullptr, + const SharedShadowNodeSharedList &children = nullptr + ) const override { + const SharedConcreteProps props = rawProps ? ShadowNodeT::Props(*rawProps, shadowNode->getProps()) : nullptr; + return std::make_shared(std::static_pointer_cast(shadowNode), props, children); + } + + void appendChild( + const SharedShadowNode &parentShadowNode, + const SharedShadowNode &childShadowNode + ) const override { + auto concreteParentShadowNode = std::static_pointer_cast(parentShadowNode); + auto concreteNonConstParentShadowNode = std::const_pointer_cast(concreteParentShadowNode); + concreteNonConstParentShadowNode->appendChild(childShadowNode); + } + +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp index 1f2777429..d095a8821 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp +++ b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp @@ -22,11 +22,13 @@ SharedShadowNodeSharedList ShadowNode::emptySharedShadowNodeSharedList() { ShadowNode::ShadowNode( Tag tag, + Tag rootTag, InstanceHandle instanceHandle, SharedProps props, SharedShadowNodeSharedList children ): tag_(tag), + rootTag_(rootTag), instanceHandle_(instanceHandle), props_(props), children_(children) {} diff --git a/ReactCommon/fabric/core/shadownode/ShadowNode.h b/ReactCommon/fabric/core/shadownode/ShadowNode.h index f341d6f12..0f2fab928 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNode.h +++ b/ReactCommon/fabric/core/shadownode/ShadowNode.h @@ -35,6 +35,7 @@ public: ShadowNode( Tag tag, + Tag rootTag, InstanceHandle instanceHandle, SharedProps props = SharedProps(), SharedShadowNodeSharedList children = SharedShadowNodeSharedList() @@ -71,6 +72,7 @@ public: protected: Tag tag_; + Tag rootTag_; InstanceHandle instanceHandle_; SharedProps props_; SharedShadowNodeSharedList children_;