Fabric: Simplified way to specialize ComponentName in ConcreteShadowNode class template

Summary:
@public
Previously, all ConcreteShadowNode subclasses had to override `getComponentName()` function to specialize a name of the component. And often it was all that those subclasses do. Now, it's a template argument; and many ShadowNode classes can be created as oneliners via *just* specializing  ConcreteShadowNode template.

Unfortunately, C++ does not allow to use `std::string`s or string literals as template arguments, but it allows to use pointers. Moreover, those pointers must point to some linked data, hence, those values must be declared in .cpp (not .h) files. For simplicity, we put those constants in Props classes, (but this is not a strong requirement).

Reviewed By: mdvacca

Differential Revision: D8942826

fbshipit-source-id: 4fd517e2485eb8f8c20a51df9b3496941856d8a5
This commit is contained in:
Valentin Shergin 2018-08-04 09:30:13 -07:00 committed by Facebook Github Bot
parent 88293d391a
commit 67a79010ca
32 changed files with 118 additions and 166 deletions

View File

@ -5,14 +5,12 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#include <fabric/components/activityindicator/ActivityIndicatorViewShadowNode.h> #include "ActivityIndicatorViewShadowNode.h"
namespace facebook { namespace facebook {
namespace react { namespace react {
ComponentName ActivityIndicatorViewShadowNode::getComponentName() const { const char ActivityIndicatorViewComponentName[] = "ActivityIndicatorView";
return ComponentName("ActivityIndicatorView");
}
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -13,18 +13,16 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
extern const char ActivityIndicatorViewComponentName[];
/* /*
* `ShadowNode` for <ActivityIndicatorView> component. * `ShadowNode` for <ActivityIndicatorView> component.
*/ */
class ActivityIndicatorViewShadowNode final: using ActivityIndicatorViewShadowNode =
public ConcreteViewShadowNode<ActivityIndicatorViewProps> { ConcreteViewShadowNode<
ActivityIndicatorViewComponentName,
public: ActivityIndicatorViewProps
>;
using ConcreteViewShadowNode::ConcreteViewShadowNode;
ComponentName getComponentName() const override;
};
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -14,9 +14,7 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
ComponentName ImageShadowNode::getComponentName() const { const char ImageComponentName[] = "Image";
return ComponentName("Image");
}
void ImageShadowNode::setImageManager(const SharedImageManager &imageManager) { void ImageShadowNode::setImageManager(const SharedImageManager &imageManager) {
ensureUnsealed(); ensureUnsealed();

View File

@ -16,18 +16,22 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
extern const char ImageComponentName[];
/* /*
* `ShadowNode` for <Image> component. * `ShadowNode` for <Image> component.
*/ */
class ImageShadowNode final: class ImageShadowNode final:
public ConcreteViewShadowNode<ImageProps, ImageEventEmitter> { public ConcreteViewShadowNode<
ImageComponentName,
ImageProps,
ImageEventEmitter
> {
public: public:
using ConcreteViewShadowNode::ConcreteViewShadowNode; using ConcreteViewShadowNode::ConcreteViewShadowNode;
ComponentName getComponentName() const override;
/* /*
* Associates a shared `ImageManager` with the node. * Associates a shared `ImageManager` with the node.
*/ */

View File

@ -24,7 +24,6 @@ class RootProps final:
public ViewProps { public ViewProps {
public: public:
RootProps() = default; RootProps() = default;
RootProps( RootProps(
const RootProps &sourceProps, const RootProps &sourceProps,

View File

@ -12,9 +12,7 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
ComponentName RootShadowNode::getComponentName() const { const char RootComponentName[] = "RootView";
return ComponentName("RootView");
}
void RootShadowNode::layout() { void RootShadowNode::layout() {
ensureUnsealed(); ensureUnsealed();

View File

@ -21,6 +21,8 @@ class RootShadowNode;
using SharedRootShadowNode = std::shared_ptr<const RootShadowNode>; using SharedRootShadowNode = std::shared_ptr<const RootShadowNode>;
using UnsharedRootShadowNode = std::shared_ptr<RootShadowNode>; using UnsharedRootShadowNode = std::shared_ptr<RootShadowNode>;
extern const char RootComponentName[];
/* /*
* `ShadowNode` for the root component. * `ShadowNode` for the root component.
* Besides all functionality of the `View` component, `RootShadowNode` contains * Besides all functionality of the `View` component, `RootShadowNode` contains
@ -28,14 +30,15 @@ using UnsharedRootShadowNode = std::shared_ptr<RootShadowNode>;
* shadow tree. * shadow tree.
*/ */
class RootShadowNode final: class RootShadowNode final:
public ConcreteViewShadowNode<RootProps> { public ConcreteViewShadowNode<
RootComponentName,
RootProps
> {
public: public:
using ConcreteViewShadowNode::ConcreteViewShadowNode; using ConcreteViewShadowNode::ConcreteViewShadowNode;
ComponentName getComponentName() const override;
/* /*
* Layouts the shadow tree. * Layouts the shadow tree.
*/ */

View File

@ -14,9 +14,7 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
ComponentName ScrollViewShadowNode::getComponentName() const { const char ScrollViewComponentName[] = "ScrollView";
return ComponentName("ScrollView");
}
void ScrollViewShadowNode::updateLocalData() { void ScrollViewShadowNode::updateLocalData() {
ensureUnsealed(); ensureUnsealed();

View File

@ -7,8 +7,6 @@
#pragma once #pragma once
#include <memory>
#include <fabric/components/scrollview/ScrollViewEventEmitter.h> #include <fabric/components/scrollview/ScrollViewEventEmitter.h>
#include <fabric/components/scrollview/ScrollViewProps.h> #include <fabric/components/scrollview/ScrollViewProps.h>
#include <fabric/components/view/ConcreteViewShadowNode.h> #include <fabric/components/view/ConcreteViewShadowNode.h>
@ -17,22 +15,22 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
class ScrollViewShadowNode; extern const char ScrollViewComponentName[];
using SharedScrollViewShadowNode = std::shared_ptr<const ScrollViewShadowNode>;
/* /*
* `ShadowNode` for <ScrollView> component. * `ShadowNode` for <ScrollView> component.
*/ */
class ScrollViewShadowNode final: class ScrollViewShadowNode final:
public ConcreteViewShadowNode<ScrollViewProps, ScrollViewEventEmitter> { public ConcreteViewShadowNode<
ScrollViewComponentName,
ScrollViewProps,
ScrollViewEventEmitter
> {
public: public:
using ConcreteViewShadowNode::ConcreteViewShadowNode; using ConcreteViewShadowNode::ConcreteViewShadowNode;
ComponentName getComponentName() const override;
#pragma mark - LayoutableShadowNode #pragma mark - LayoutableShadowNode
void layout(LayoutContext layoutContext) override; void layout(LayoutContext layoutContext) override;

View File

@ -5,14 +5,12 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#include <fabric/components/switch/SwitchShadowNode.h> #include "SwitchShadowNode.h"
namespace facebook { namespace facebook {
namespace react { namespace react {
ComponentName SwitchShadowNode::getComponentName() const { extern const char SwitchComponentName[] = "Switch";
return ComponentName("Switch");
}
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -14,18 +14,17 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
extern const char SwitchComponentName[];
/* /*
* `ShadowNode` for <Switch> component. * `ShadowNode` for <Switch> component.
*/ */
class SwitchShadowNode final: using SwitchShadowNode =
public ConcreteViewShadowNode<SwitchProps, SwitchEventEmitter> { ConcreteViewShadowNode<
SwitchComponentName,
public: SwitchProps,
SwitchEventEmitter
using ConcreteViewShadowNode::ConcreteViewShadowNode; >;
ComponentName getComponentName() const override;
};
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -24,7 +24,7 @@ AttributedString BaseTextShadowNode::getAttributedString(
for (const auto &childNode : *childNodes) { for (const auto &childNode : *childNodes) {
// RawShadowNode // RawShadowNode
SharedRawTextShadowNode rawTextShadowNode = std::dynamic_pointer_cast<const RawTextShadowNode>(childNode); auto rawTextShadowNode = std::dynamic_pointer_cast<const RawTextShadowNode>(childNode);
if (rawTextShadowNode) { if (rawTextShadowNode) {
AttributedString::Fragment fragment; AttributedString::Fragment fragment;
fragment.string = rawTextShadowNode->getProps()->text; fragment.string = rawTextShadowNode->getProps()->text;
@ -34,7 +34,7 @@ AttributedString BaseTextShadowNode::getAttributedString(
} }
// TextShadowNode // TextShadowNode
SharedTextShadowNode textShadowNode = std::dynamic_pointer_cast<const TextShadowNode>(childNode); auto textShadowNode = std::dynamic_pointer_cast<const TextShadowNode>(childNode);
if (textShadowNode) { if (textShadowNode) {
TextAttributes localTextAttributes = textAttributes; TextAttributes localTextAttributes = textAttributes;
localTextAttributes.apply(textShadowNode->getProps()->textAttributes); localTextAttributes.apply(textShadowNode->getProps()->textAttributes);

View File

@ -30,7 +30,7 @@ public:
} }
void adopt(UnsharedShadowNode shadowNode) const override { void adopt(UnsharedShadowNode shadowNode) const override {
ConcreteComponentDescriptor<ParagraphShadowNode>::adopt(shadowNode); ConcreteComponentDescriptor::adopt(shadowNode);
assert(std::dynamic_pointer_cast<ParagraphShadowNode>(shadowNode)); assert(std::dynamic_pointer_cast<ParagraphShadowNode>(shadowNode));
auto paragraphShadowNode = std::static_pointer_cast<ParagraphShadowNode>(shadowNode); auto paragraphShadowNode = std::static_pointer_cast<ParagraphShadowNode>(shadowNode);

View File

@ -18,10 +18,6 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
class ParagraphProps;
using SharedParagraphProps = std::shared_ptr<const ParagraphProps>;
/* /*
* Props of <Paragraph> component. * Props of <Paragraph> component.
* Most of the props are directly stored in composed `ParagraphAttributes` * Most of the props are directly stored in composed `ParagraphAttributes`

View File

@ -7,16 +7,12 @@
#include "ParagraphShadowNode.h" #include "ParagraphShadowNode.h"
#include <fabric/debug/DebugStringConvertibleItem.h> #include "ParagraphLocalData.h"
#import "ParagraphLocalData.h"
namespace facebook { namespace facebook {
namespace react { namespace react {
ComponentName ParagraphShadowNode::getComponentName() const { const char ParagraphComponentName[] = "Paragraph";
return ComponentName("Paragraph");
}
AttributedString ParagraphShadowNode::getAttributedString() const { AttributedString ParagraphShadowNode::getAttributedString() const {
if (!cachedAttributedString_.has_value()) { if (!cachedAttributedString_.has_value()) {
@ -53,7 +49,7 @@ Size ParagraphShadowNode::measure(LayoutConstraints layoutConstraints) const {
void ParagraphShadowNode::layout(LayoutContext layoutContext) { void ParagraphShadowNode::layout(LayoutContext layoutContext) {
updateLocalData(); updateLocalData();
ConcreteViewShadowNode<ParagraphProps>::layout(layoutContext); ConcreteViewShadowNode::layout(layoutContext);
} }
} // namespace react } // namespace react

View File

@ -19,9 +19,7 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
class ParagraphShadowNode; extern const char ParagraphComponentName[];
using SharedParagraphShadowNode = std::shared_ptr<const ParagraphShadowNode>;
/* /*
* `ShadowNode` for <Paragraph> component, represents <View>-like component * `ShadowNode` for <Paragraph> component, represents <View>-like component
@ -29,15 +27,16 @@ using SharedParagraphShadowNode = std::shared_ptr<const ParagraphShadowNode>;
* and <RawText> components. * and <RawText> components.
*/ */
class ParagraphShadowNode: class ParagraphShadowNode:
public ConcreteViewShadowNode<ParagraphProps>, public ConcreteViewShadowNode<
ParagraphComponentName,
ParagraphProps
>,
public BaseTextShadowNode { public BaseTextShadowNode {
public: public:
using ConcreteViewShadowNode::ConcreteViewShadowNode; using ConcreteViewShadowNode::ConcreteViewShadowNode;
ComponentName getComponentName() const override;
/* /*
* Returns a `AttributedString` which represents text content of the node. * Returns a `AttributedString` which represents text content of the node.
*/ */

View File

@ -23,7 +23,6 @@ class RawTextProps:
public Props { public Props {
public: public:
RawTextProps() = default; RawTextProps() = default;
RawTextProps(const RawTextProps &sourceProps, const RawProps &rawProps); RawTextProps(const RawTextProps &sourceProps, const RawProps &rawProps);

View File

@ -7,14 +7,10 @@
#include "RawTextShadowNode.h" #include "RawTextShadowNode.h"
#include <fabric/debug/DebugStringConvertibleItem.h>
namespace facebook { namespace facebook {
namespace react { namespace react {
ComponentName RawTextShadowNode::getComponentName() const { extern const char RawTextComponentName[] = "RawText";
return ComponentName("RawText");
}
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -7,18 +7,13 @@
#pragma once #pragma once
#include <memory>
#include <fabric/components/text/RawTextProps.h> #include <fabric/components/text/RawTextProps.h>
#include <fabric/core/ConcreteShadowNode.h> #include <fabric/core/ConcreteShadowNode.h>
#include <fabric/core/ShadowNode.h>
namespace facebook { namespace facebook {
namespace react { namespace react {
class RawTextShadowNode; extern const char RawTextComponentName[];
using SharedRawTextShadowNode = std::shared_ptr<const RawTextShadowNode>;
/* /*
* `ShadowNode` for <RawText> component, represents a purely regular string * `ShadowNode` for <RawText> component, represents a purely regular string
@ -26,14 +21,11 @@ using SharedRawTextShadowNode = std::shared_ptr<const RawTextShadowNode>;
* is represented as `<RawText text="Hello!"/>`. * is represented as `<RawText text="Hello!"/>`.
* <RawText> component must not have any children. * <RawText> component must not have any children.
*/ */
class RawTextShadowNode: using RawTextShadowNode =
public ConcreteShadowNode<RawTextProps> { ConcreteShadowNode<
RawTextComponentName,
public: RawTextProps
using ConcreteShadowNode::ConcreteShadowNode; >;
ComponentName getComponentName() const override;
};
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -16,16 +16,11 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
class TextProps;
using SharedTextProps = std::shared_ptr<const TextProps>;
class TextProps: class TextProps:
public Props, public Props,
public BaseTextProps { public BaseTextProps {
public: public:
TextProps() = default; TextProps() = default;
TextProps(const TextProps &sourceProps, const RawProps &rawProps); TextProps(const TextProps &sourceProps, const RawProps &rawProps);

View File

@ -7,14 +7,10 @@
#include "TextShadowNode.h" #include "TextShadowNode.h"
#include <fabric/debug/DebugStringConvertibleItem.h>
namespace facebook { namespace facebook {
namespace react { namespace react {
ComponentName TextShadowNode::getComponentName() const { extern const char TextComponentName[] = "Text";
return ComponentName("Text");
}
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -7,30 +7,25 @@
#pragma once #pragma once
#include <fabric/attributedstring/AttributedString.h>
#include <fabric/attributedstring/TextAttributes.h>
#include <fabric/components/text/BaseTextShadowNode.h> #include <fabric/components/text/BaseTextShadowNode.h>
#include <fabric/components/text/TextProps.h> #include <fabric/components/text/TextProps.h>
#include <fabric/components/text/TextShadowNode.h>
#include <fabric/core/ConcreteShadowNode.h> #include <fabric/core/ConcreteShadowNode.h>
#include <fabric/core/ShadowNode.h>
namespace facebook { namespace facebook {
namespace react { namespace react {
class TextShadowNode; extern const char TextComponentName[];
using SharedTextShadowNode = std::shared_ptr<const TextShadowNode>;
class TextShadowNode: class TextShadowNode:
public ConcreteShadowNode<TextProps>, public ConcreteShadowNode<
TextComponentName,
TextProps
>,
public BaseTextShadowNode { public BaseTextShadowNode {
public: public:
using ConcreteShadowNode::ConcreteShadowNode; using ConcreteShadowNode::ConcreteShadowNode;
ComponentName getComponentName() const override;
}; };
} // namespace react } // namespace react

View File

@ -24,9 +24,17 @@ namespace react {
* as <View> and similar basic behaviour). * as <View> and similar basic behaviour).
* For example: <Paragraph>, <Image>, but not <Text>, <RawText>. * For example: <Paragraph>, <Image>, but not <Text>, <RawText>.
*/ */
template <typename ViewPropsT = ViewProps, typename ViewEventEmitterT = ViewEventEmitter> template <
const char *concreteComponentName,
typename ViewPropsT = ViewProps,
typename ViewEventEmitterT = ViewEventEmitter
>
class ConcreteViewShadowNode: class ConcreteViewShadowNode:
public ConcreteShadowNode<ViewPropsT, ViewEventEmitterT>, public ConcreteShadowNode<
concreteComponentName,
ViewPropsT,
ViewEventEmitterT
>,
public AccessibleShadowNode, public AccessibleShadowNode,
public YogaLayoutableShadowNode { public YogaLayoutableShadowNode {
@ -50,7 +58,7 @@ public:
const SharedShadowNodeSharedList &children, const SharedShadowNodeSharedList &children,
const ShadowNodeCloneFunction &cloneFunction const ShadowNodeCloneFunction &cloneFunction
): ):
ConcreteShadowNode<ViewPropsT, ViewEventEmitterT>( ConcreteShadowNode<concreteComponentName, ViewPropsT, ViewEventEmitterT>(
tag, tag,
rootTag, rootTag,
props, props,
@ -64,7 +72,7 @@ public:
YogaLayoutableShadowNode() { YogaLayoutableShadowNode() {
YogaLayoutableShadowNode::setProps(*props); YogaLayoutableShadowNode::setProps(*props);
YogaLayoutableShadowNode::setChildren(ConcreteShadowNode<ViewPropsT, ViewEventEmitterT>::template getChildrenSlice<YogaLayoutableShadowNode>()); YogaLayoutableShadowNode::setChildren(ConcreteShadowNode<concreteComponentName, ViewPropsT, ViewEventEmitterT>::template getChildrenSlice<YogaLayoutableShadowNode>());
}; };
ConcreteViewShadowNode( ConcreteViewShadowNode(
@ -73,7 +81,7 @@ public:
const SharedConcreteViewEventEmitter &eventEmitter, const SharedConcreteViewEventEmitter &eventEmitter,
const SharedShadowNodeSharedList &children const SharedShadowNodeSharedList &children
): ):
ConcreteShadowNode<ViewPropsT, ViewEventEmitterT>( ConcreteShadowNode<concreteComponentName, ViewPropsT, ViewEventEmitterT>(
shadowNode, shadowNode,
props, props,
eventEmitter, eventEmitter,
@ -92,7 +100,7 @@ public:
} }
if (children) { if (children) {
YogaLayoutableShadowNode::setChildren(ConcreteShadowNode<ViewPropsT, ViewEventEmitterT>::template getChildrenSlice<YogaLayoutableShadowNode>()); YogaLayoutableShadowNode::setChildren(ConcreteShadowNode<concreteComponentName, ViewPropsT, ViewEventEmitterT>::template getChildrenSlice<YogaLayoutableShadowNode>());
} }
}; };

View File

@ -27,7 +27,6 @@ class ViewProps:
public AccessibilityProps { public AccessibilityProps {
public: public:
ViewProps() = default; ViewProps() = default;
ViewProps(const YGStyle &yogaStyle); ViewProps(const YGStyle &yogaStyle);
ViewProps(const ViewProps &sourceProps, const RawProps &rawProps); ViewProps(const ViewProps &sourceProps, const RawProps &rawProps);

View File

@ -10,9 +10,7 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
ComponentName ViewShadowNode::getComponentName() const { const char ViewComponentName[] = "View";
return ComponentName("View");
}
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -7,27 +7,20 @@
#pragma once #pragma once
#include <memory>
#include <fabric/components/view/ViewProps.h> #include <fabric/components/view/ViewProps.h>
#include <fabric/components/view/ConcreteViewShadowNode.h> #include <fabric/components/view/ConcreteViewShadowNode.h>
namespace facebook { namespace facebook {
namespace react { namespace react {
class ViewShadowNode; extern const char ViewComponentName[];
using SharedViewShadowNode = std::shared_ptr<const ViewShadowNode>; using ViewShadowNode =
ConcreteViewShadowNode<
class ViewShadowNode final: ViewComponentName,
public ConcreteViewShadowNode<ViewProps, ViewEventEmitter> { ViewProps,
ViewEventEmitter
public: >;
using ConcreteViewShadowNode::ConcreteViewShadowNode;
ComponentName getComponentName() const override;
};
} // namespace react } // namespace react
} // namespace facebook } // namespace facebook

View File

@ -37,22 +37,11 @@ public:
eventDispatcher_(eventDispatcher) {} eventDispatcher_(eventDispatcher) {}
ComponentHandle getComponentHandle() const override { ComponentHandle getComponentHandle() const override {
return typeid(ShadowNodeT).hash_code(); return ShadowNodeT::Handle();
} }
ComponentName getComponentName() const override { ComponentName getComponentName() const override {
// Even if this looks suboptimal, it is the only way to call return ShadowNodeT::Name();
// a virtual non-static method of `ShadowNodeT`.
// Because it is not a hot path (it is executed once per an app run),
// it's fine.
return std::make_shared<ShadowNodeT>(
0,
0,
std::make_shared<const ConcreteProps>(),
nullptr,
ShadowNode::emptySharedShadowNodeSharedList(),
nullptr
)->ShadowNodeT::getComponentName();
} }
SharedShadowNode createShadowNode( SharedShadowNode createShadowNode(
@ -74,6 +63,7 @@ public:
); );
adopt(shadowNode); adopt(shadowNode);
return shadowNode; return shadowNode;
} }
@ -123,6 +113,7 @@ protected:
virtual void adopt(UnsharedShadowNode shadowNode) const { virtual void adopt(UnsharedShadowNode shadowNode) const {
// Default implementation does nothing. // Default implementation does nothing.
assert(shadowNode->getComponentHandle() == getComponentHandle());
} }
private: private:

View File

@ -35,7 +35,7 @@ using SharedRawProps = std::shared_ptr<const RawProps>;
* Practically, it's something that concrete ShadowNode and concrete * Practically, it's something that concrete ShadowNode and concrete
* ComponentDescriptor have in common. * ComponentDescriptor have in common.
*/ */
using ComponentHandle = size_t; using ComponentHandle = int64_t;
/* /*
* String identifier for components used for addressing them from * String identifier for components used for addressing them from

View File

@ -19,7 +19,11 @@ namespace react {
* `ConcreteShadowNode` is a default implementation of `ShadowNode` interface * `ConcreteShadowNode` is a default implementation of `ShadowNode` interface
* with many handy features. * with many handy features.
*/ */
template <typename PropsT, typename EventEmitterT = EventEmitter> template <
const char *concreteComponentName,
typename PropsT,
typename EventEmitterT = EventEmitter
>
class ConcreteShadowNode: public ShadowNode { class ConcreteShadowNode: public ShadowNode {
static_assert(std::is_base_of<Props, PropsT>::value, "PropsT must be a descendant of Props"); static_assert(std::is_base_of<Props, PropsT>::value, "PropsT must be a descendant of Props");
@ -30,6 +34,14 @@ public:
using SharedConcreteEventEmitter = std::shared_ptr<const EventEmitterT>; using SharedConcreteEventEmitter = std::shared_ptr<const EventEmitterT>;
using SharedConcreteShadowNode = std::shared_ptr<const ConcreteShadowNode>; using SharedConcreteShadowNode = std::shared_ptr<const ConcreteShadowNode>;
static ComponentName Name() {
return ComponentName(concreteComponentName);
}
static ComponentHandle Handle() {
return ComponentHandle(concreteComponentName);
}
static SharedConcreteProps Props(const RawProps &rawProps, const SharedProps &baseProps = nullptr) { static SharedConcreteProps Props(const RawProps &rawProps, const SharedProps &baseProps = nullptr) {
return std::make_shared<const PropsT>(baseProps ? *std::static_pointer_cast<const PropsT>(baseProps) : PropsT(), rawProps); return std::make_shared<const PropsT>(baseProps ? *std::static_pointer_cast<const PropsT>(baseProps) : PropsT(), rawProps);
} }
@ -69,8 +81,12 @@ public:
children children
) {} ) {}
virtual ComponentHandle getComponentHandle() const { ComponentName getComponentName() const override {
return typeid(*this).hash_code(); return ComponentName(concreteComponentName);
}
ComponentHandle getComponentHandle() const override {
return reinterpret_cast<ComponentHandle>(concreteComponentName);
} }
const SharedConcreteProps getProps() const { const SharedConcreteProps getProps() const {

View File

@ -14,7 +14,8 @@ using namespace facebook::react;
TEST(ComponentDescriptorTest, createShadowNode) { TEST(ComponentDescriptorTest, createShadowNode) {
SharedComponentDescriptor descriptor = std::make_shared<TestComponentDescriptor>(nullptr); SharedComponentDescriptor descriptor = std::make_shared<TestComponentDescriptor>(nullptr);
ASSERT_EQ(descriptor->getComponentHandle(), typeid(TestShadowNode).hash_code()); ASSERT_EQ(descriptor->getComponentHandle(), TestShadowNode::Handle());
ASSERT_STREQ(descriptor->getComponentName().c_str(), TestShadowNode::Name().c_str());
ASSERT_STREQ(descriptor->getComponentName().c_str(), "Test"); ASSERT_STREQ(descriptor->getComponentName().c_str(), "Test");
RawProps raw; RawProps raw;
@ -22,7 +23,8 @@ TEST(ComponentDescriptorTest, createShadowNode) {
SharedProps props = descriptor->cloneProps(nullptr, raw); SharedProps props = descriptor->cloneProps(nullptr, raw);
SharedShadowNode node = descriptor->createShadowNode(9, 1, descriptor->createEventEmitter(0, 9), props); SharedShadowNode node = descriptor->createShadowNode(9, 1, descriptor->createEventEmitter(0, 9), props);
ASSERT_EQ(node->getComponentHandle(), typeid(TestShadowNode).hash_code()); ASSERT_EQ(node->getComponentHandle(), TestShadowNode::Handle());
ASSERT_STREQ(node->getComponentName().c_str(), TestShadowNode::Name().c_str());
ASSERT_STREQ(node->getComponentName().c_str(), "Test"); ASSERT_STREQ(node->getComponentName().c_str(), "Test");
ASSERT_EQ(node->getTag(), 9); ASSERT_EQ(node->getTag(), 9);
ASSERT_EQ(node->getRootTag(), 1); ASSERT_EQ(node->getRootTag(), 1);
@ -38,7 +40,6 @@ TEST(ComponentDescriptorTest, cloneShadowNode) {
SharedShadowNode node = descriptor->createShadowNode(9, 1, descriptor->createEventEmitter(0, 9), props); SharedShadowNode node = descriptor->createShadowNode(9, 1, descriptor->createEventEmitter(0, 9), props);
SharedShadowNode cloned = descriptor->cloneShadowNode(node); SharedShadowNode cloned = descriptor->cloneShadowNode(node);
ASSERT_EQ(cloned->getComponentHandle(), typeid(TestShadowNode).hash_code());
ASSERT_STREQ(cloned->getComponentName().c_str(), "Test"); ASSERT_STREQ(cloned->getComponentName().c_str(), "Test");
ASSERT_EQ(cloned->getTag(), 9); ASSERT_EQ(cloned->getTag(), 9);
ASSERT_EQ(cloned->getRootTag(), 1); ASSERT_EQ(cloned->getRootTag(), 1);

View File

@ -35,8 +35,6 @@ TEST(ShadowNodeTest, handleShadowNodeCreation) {
ASSERT_EQ(node->getTag(), 9); ASSERT_EQ(node->getTag(), 9);
ASSERT_EQ(node->getRootTag(), 1); ASSERT_EQ(node->getRootTag(), 1);
ASSERT_EQ(node->getEventEmitter(), nullptr); ASSERT_EQ(node->getEventEmitter(), nullptr);
TestShadowNode *nodePtr = node.get();
ASSERT_EQ(node->getComponentHandle(), typeid(*nodePtr).hash_code());
ASSERT_EQ(node->getChildren()->size(), 0); ASSERT_EQ(node->getChildren()->size(), 0);
ASSERT_STREQ(node->getProps()->nativeId.c_str(), "testNativeID"); ASSERT_STREQ(node->getProps()->nativeId.c_str(), "testNativeID");

View File

@ -36,6 +36,8 @@ private:
int number_ {0}; int number_ {0};
}; };
static const char TestComponentName[] = "Test";
class TestProps : public Props { class TestProps : public Props {
public: public:
using Props::Props; using Props::Props;
@ -46,21 +48,12 @@ using SharedTestProps = std::shared_ptr<const TestProps>;
class TestShadowNode; class TestShadowNode;
using SharedTestShadowNode = std::shared_ptr<const TestShadowNode>; using SharedTestShadowNode = std::shared_ptr<const TestShadowNode>;
class TestShadowNode : public ConcreteShadowNode<TestProps> { class TestShadowNode : public ConcreteShadowNode<TestComponentName, TestProps> {
public: public:
using ConcreteShadowNode::ConcreteShadowNode; using ConcreteShadowNode::ConcreteShadowNode;
ComponentName getComponentName() const override {
return ComponentName("Test");
}
}; };
class TestComponentDescriptor: public ConcreteComponentDescriptor<TestShadowNode> { class TestComponentDescriptor: public ConcreteComponentDescriptor<TestShadowNode> {
public: public:
using ConcreteComponentDescriptor::ConcreteComponentDescriptor; using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
// TODO (shergin): Why does this gets repeated here and the shadow node class?
ComponentName getComponentName() const override {
return "Test";
}
}; };