Introducing `ComponentDescriptor`

Summary:
Abstract class and default template implementation.
`ComponentDescriptor`s define basic logic of managing (creation, cloning, applying props) ShadowNode of particular type.

Reviewed By: fkgozali

Differential Revision: D7230671

fbshipit-source-id: c32636f4db0716b55a1637f61c4f1872fc52cea7
This commit is contained in:
Valentin Shergin 2018-03-18 19:04:16 -07:00 committed by Facebook Github Bot
parent 608d1fb590
commit 840638c441
5 changed files with 142 additions and 0 deletions

View File

@ -23,6 +23,7 @@ rn_xplat_cxx_library(
exported_headers = subdir_glob(
[
("primitives", "*.h"),
("componentdescriptor", "*.h"),
("shadownode", "*.h"),
],
prefix = "fabric/core",

View File

@ -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 <fabric/core/ShadowNode.h>
#include <fabric/core/Props.h>
namespace facebook {
namespace react {
class ComponentDescriptor;
using SharedComponentDescriptor = std::shared_ptr<ComponentDescriptor>;
/*
* 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

View File

@ -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 <memory>
#include <fabric/core/ShadowNode.h>
#include <fabric/core/Props.h>
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 <typename ShadowNodeT>
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 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<ShadowNodeT>(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<ShadowNodeT>(std::static_pointer_cast<const ShadowNodeT>(shadowNode), props, children);
}
void appendChild(
const SharedShadowNode &parentShadowNode,
const SharedShadowNode &childShadowNode
) const override {
auto concreteParentShadowNode = std::static_pointer_cast<const ShadowNodeT>(parentShadowNode);
auto concreteNonConstParentShadowNode = std::const_pointer_cast<ShadowNodeT>(concreteParentShadowNode);
concreteNonConstParentShadowNode->appendChild(childShadowNode);
}
};
} // namespace react
} // namespace facebook

View File

@ -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) {}

View File

@ -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_;