Fabric/Text/Prep: Refined ComponentDescriptor interface

Summary:
The new interface of ComponentDescriptor makes ShadowNode creation/cloning process a bit more explicit:
Now customers (UIManager) must prepare Props object explicitly before creation or cloning.
Besides general clarity, we need this to prepare for a new virtual `ShadowNode::clone()` method which will serve "virtual constructor" role,
redirecting execution to concrete ComponentDescriptor instance.

Actually, the whole purpose of concrete ComponentDescriptor instance is serve "virtual constructor" role (and all this code should be "templated").

Reviewed By: mdvacca

Differential Revision: D7591714

fbshipit-source-id: 8793b3ef70ed7ae113efb36ad1eee20573360dc8
This commit is contained in:
Valentin Shergin
2018-04-16 07:43:22 -07:00
committed by Facebook Github Bot
parent 2fd7fda05d
commit 3fd2e2da4f
4 changed files with 70 additions and 18 deletions

View File

@@ -48,7 +48,7 @@ public:
const Tag &tag,
const Tag &rootTag,
const InstanceHandle &instanceHandle,
const RawProps &rawProps
const SharedProps &props
) const = 0;
/*
@@ -56,7 +56,7 @@ public:
*/
virtual SharedShadowNode cloneShadowNode(
const SharedShadowNode &shadowNode,
const SharedRawProps &rawProps = nullptr,
const SharedProps &props = nullptr,
const SharedShadowNodeSharedList &children = nullptr
) const = 0;
@@ -67,6 +67,17 @@ public:
const SharedShadowNode &parentShadowNode,
const SharedShadowNode &childShadowNode
) const = 0;
/*
* Creates a new `Props` of a particular type with all values copied from
* `props` and `rawProps` applied on top of this.
* If `props` is `nullptr`, a default `Props` object (with default values)
* will be used.
*/
virtual SharedProps cloneProps(
const SharedProps &props,
const RawProps &rawProps
) const = 0;
};
} // namespace react

View File

@@ -26,6 +26,7 @@ class ConcreteComponentDescriptor: public ComponentDescriptor {
static_assert(std::is_base_of<ShadowNode, ShadowNodeT>::value, "ShadowNodeT must be a descendant of ShadowNode");
using SharedShadowNodeT = std::shared_ptr<const ShadowNodeT>;
using ConcreteProps = typename ShadowNodeT::ConcreteProps;
using SharedConcreteProps = typename ShadowNodeT::SharedConcreteProps;
public:
@@ -37,19 +38,17 @@ public:
const Tag &tag,
const Tag &rootTag,
const InstanceHandle &instanceHandle,
const RawProps &rawProps
const SharedProps &props
) const override {
auto props = ShadowNodeT::Props(rawProps);
return std::make_shared<ShadowNodeT>(tag, rootTag, instanceHandle, props);
return std::make_shared<ShadowNodeT>(tag, rootTag, instanceHandle, std::static_pointer_cast<const ConcreteProps>(props));
}
SharedShadowNode cloneShadowNode(
const SharedShadowNode &shadowNode,
const SharedRawProps &rawProps = nullptr,
const SharedProps &props = nullptr,
const SharedShadowNodeSharedList &children = nullptr
) const override {
const SharedConcreteProps props = rawProps ? ShadowNodeT::Props(*rawProps, shadowNode->getProps()) : nullptr;
return std::make_shared<ShadowNodeT>(std::static_pointer_cast<const ShadowNodeT>(shadowNode), props, children);
return std::make_shared<ShadowNodeT>(std::static_pointer_cast<const ShadowNodeT>(shadowNode), std::static_pointer_cast<const ConcreteProps>(props), children);
}
void appendChild(
@@ -61,6 +60,13 @@ public:
concreteNonConstParentShadowNode->appendChild(childShadowNode);
}
virtual SharedProps cloneProps(
const SharedProps &props,
const RawProps &rawProps
) const override {
return ShadowNodeT::Props(rawProps, props);
};
};
} // namespace react

View File

@@ -19,7 +19,8 @@ TEST(ComponentDescriptorTest, createShadowNode) {
RawProps raw;
raw["nativeID"] = "abc";
SharedShadowNode node = descriptor->createShadowNode(9, 1, (void *)NULL, raw);
SharedProps props = descriptor->cloneProps(nullptr, raw);
SharedShadowNode node = descriptor->createShadowNode(9, 1, (void *)NULL, props);
ASSERT_EQ(node->getComponentHandle(), typeid(TestShadowNode).hash_code());
ASSERT_STREQ(node->getComponentName().c_str(), "Test");
@@ -35,7 +36,8 @@ TEST(ComponentDescriptorTest, cloneShadowNode) {
RawProps raw;
raw["nativeID"] = "abc";
SharedShadowNode node = descriptor->createShadowNode(9, 1, (void *)NULL, raw);
SharedProps props = descriptor->cloneProps(nullptr, raw);
SharedShadowNode node = descriptor->createShadowNode(9, 1, (void *)NULL, props);
SharedShadowNode cloned = descriptor->cloneShadowNode(node);
ASSERT_EQ(cloned->getComponentHandle(), typeid(TestShadowNode).hash_code());
@@ -52,9 +54,10 @@ TEST(ComponentDescriptorTest, appendChild) {
RawProps raw;
raw["nativeID"] = "abc";
SharedShadowNode node1 = descriptor->createShadowNode(1, 1, (void *)NULL, raw);
SharedShadowNode node2 = descriptor->createShadowNode(2, 1, (void *)NULL, raw);
SharedShadowNode node3 = descriptor->createShadowNode(3, 1, (void *)NULL, raw);
SharedProps props = descriptor->cloneProps(nullptr, raw);
SharedShadowNode node1 = descriptor->createShadowNode(1, 1, (void *)NULL, props);
SharedShadowNode node2 = descriptor->createShadowNode(2, 1, (void *)NULL, props);
SharedShadowNode node3 = descriptor->createShadowNode(3, 1, (void *)NULL, props);
descriptor->appendChild(node1, node2);
descriptor->appendChild(node1, node3);

View File

@@ -54,7 +54,15 @@ SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int
LOG(INFO) << "FabricUIManager::createNode(tag: " << tag << ", name: " << viewName << ", rootTag" << rootTag << ", props: " << props << ")";
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)["View"];
RawProps rawProps = rawPropsFromDynamic(props);
SharedShadowNode shadowNode = componentDescriptor->createShadowNode(tag, rootTag, instanceHandle, rawProps);
SharedShadowNode shadowNode =
componentDescriptor->createShadowNode(
tag,
rootTag,
instanceHandle,
componentDescriptor->cloneProps(nullptr, rawProps)
);
LOG(INFO) << "FabricUIManager::createNode() -> " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
if (delegate_) {
@@ -67,7 +75,10 @@ SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int
SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode) {
LOG(INFO) << "FabricUIManager::cloneNode(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode];
SharedShadowNode clonedShadowNode = componentDescriptor->cloneShadowNode(shadowNode);
SharedShadowNode clonedShadowNode =
componentDescriptor->cloneShadowNode(shadowNode);
LOG(INFO) << "FabricUIManager::cloneNode() -> " << clonedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
return clonedShadowNode;
}
@@ -76,7 +87,14 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNod
LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildren(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
// Assuming semantic: Cloning with same props but empty children.
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode];
SharedShadowNode clonedShadowNode = componentDescriptor->cloneShadowNode(shadowNode, nullptr, ShadowNode::emptySharedShadowNodeSharedList());
SharedShadowNode clonedShadowNode =
componentDescriptor->cloneShadowNode(
shadowNode,
nullptr,
ShadowNode::emptySharedShadowNodeSharedList()
);
LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildren() -> " << clonedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
return clonedShadowNode;
}
@@ -86,7 +104,14 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode &
// Assuming semantic: Cloning with same children and specified props.
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode];
RawProps rawProps = rawPropsFromDynamic(props);
SharedShadowNode clonedShadowNode = componentDescriptor->cloneShadowNode(shadowNode, std::make_shared<const RawProps>(rawProps), nullptr);
SharedShadowNode clonedShadowNode =
componentDescriptor->cloneShadowNode(
shadowNode,
componentDescriptor->cloneProps(shadowNode->getProps(), rawProps),
nullptr
);
LOG(INFO) << "FabricUIManager::cloneNodeWithNewProps() -> " << clonedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
return clonedShadowNode;
}
@@ -96,7 +121,14 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewChildrenAndProps(const SharedS
// Assuming semantic: Cloning with empty children and specified props.
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode];
RawProps rawProps = rawPropsFromDynamic(props);
SharedShadowNode clonedShadowNode = componentDescriptor->cloneShadowNode(shadowNode, std::make_shared<const RawProps>(rawProps), ShadowNode::emptySharedShadowNodeSharedList());
SharedShadowNode clonedShadowNode =
componentDescriptor->cloneShadowNode(
shadowNode,
componentDescriptor->cloneProps(shadowNode->getProps(), rawProps),
ShadowNode::emptySharedShadowNodeSharedList()
);
LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildrenAndProps() -> " << clonedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
return clonedShadowNode;
}