Abstract classes for ShadowNode and Props

Summary: Foundation clases for Fabric designed to be "const-first".

Reviewed By: fkgozali

Differential Revision: D7230672

fbshipit-source-id: 433acd35a7958d5d577358b0a306923f970e573f
This commit is contained in:
Valentin Shergin 2018-03-18 19:04:10 -07:00 committed by Facebook Github Bot
parent d16772a31e
commit c623455845
10 changed files with 362 additions and 76 deletions

View File

@ -8,7 +8,6 @@
#include "FabricUIManager.h"
#include "IFabricPlatformUIOperationManager.h"
#include "ShadowNode.h"
namespace facebook {
namespace react {
@ -16,38 +15,38 @@ namespace react {
FabricUIManager::FabricUIManager(const std::shared_ptr<IFabricPlatformUIOperationManager> &platformUIOperationManager) :
platformUIOperationManager_(platformUIOperationManager) {};
ShadowNodeRef FabricUIManager::createNode(int reactTag, std::string viewName, int rootTag, folly::dynamic props, void *instanceHandle) {
SharedShadowNode FabricUIManager::createNode(int reactTag, std::string viewName, int rootTag, folly::dynamic props, void *instanceHandle) {
platformUIOperationManager_->performUIOperation();
return std::make_shared<ShadowNode>(reactTag, viewName, rootTag, props, instanceHandle);
}
ShadowNodeRef FabricUIManager::cloneNode(const ShadowNodeRef &node) {
return nullptr;
}
ShadowNodeRef FabricUIManager::cloneNodeWithNewChildren(const ShadowNodeRef &node) {
SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &node) {
return nullptr;
}
ShadowNodeRef FabricUIManager::cloneNodeWithNewProps(const ShadowNodeRef &node, folly::dynamic props) {
SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNode &node) {
return nullptr;
}
ShadowNodeRef FabricUIManager::cloneNodeWithNewChildrenAndProps(const ShadowNodeRef &node, folly::dynamic newProps) {
SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode &node, folly::dynamic props) {
return nullptr;
}
void FabricUIManager::appendChild(const ShadowNodeRef &parentNode, const ShadowNodeRef &childNode) {
}
ShadowNodeSetRef FabricUIManager::createChildSet(int rootTag) {
SharedShadowNode FabricUIManager::cloneNodeWithNewChildrenAndProps(const SharedShadowNode &node, folly::dynamic newProps) {
return nullptr;
}
void FabricUIManager::appendChildToSet(const ShadowNodeSetRef &childSet, const ShadowNodeRef &childNode) {
void FabricUIManager::appendChild(const SharedShadowNode &parentNode, const SharedShadowNode &childNode) {
}
void FabricUIManager::completeRoot(int rootTag, const ShadowNodeSetRef &childSet) {
SharedShadowNodeUnsharedList FabricUIManager::createChildSet(int rootTag) {
return nullptr;
}
void FabricUIManager::appendChildToSet(const SharedShadowNodeUnsharedList &childSet, const SharedShadowNode &childNode) {
}
void FabricUIManager::completeRoot(int rootTag, const SharedShadowNodeUnsharedList &childSet) {
}
} // namespace react

View File

@ -11,29 +11,26 @@
#include <folly/FBVector.h>
#include <memory>
#include <fabric/core/ShadowNode.h>
namespace facebook {
namespace react {
class ShadowNode;
class IFabricPlatformUIOperationManager;
typedef std::shared_ptr<const ShadowNode> ShadowNodeRef;
typedef folly::fbvector<const ShadowNodeRef> ShadowNodeSet;
typedef std::shared_ptr<const ShadowNodeSet> ShadowNodeSetRef;
class FabricUIManager {
public:
FabricUIManager(const std::shared_ptr<IFabricPlatformUIOperationManager> &platformUIOperationManager);
ShadowNodeRef createNode(int reactTag, std::string viewName, int rootTag, folly::dynamic props, void *instanceHandle);
ShadowNodeRef cloneNode(const ShadowNodeRef &node);
ShadowNodeRef cloneNodeWithNewChildren(const ShadowNodeRef &node);
ShadowNodeRef cloneNodeWithNewProps(const ShadowNodeRef &node, folly::dynamic props);
ShadowNodeRef cloneNodeWithNewChildrenAndProps(const ShadowNodeRef &node, folly::dynamic newProps);
void appendChild(const ShadowNodeRef &parentNode, const ShadowNodeRef &childNode);
ShadowNodeSetRef createChildSet(int rootTag);
void appendChildToSet(const ShadowNodeSetRef &childSet, const ShadowNodeRef &childNode);
void completeRoot(int rootTag, const ShadowNodeSetRef &childSet);
SharedShadowNode createNode(int reactTag, std::string viewName, int rootTag, folly::dynamic props, void *instanceHandle);
SharedShadowNode cloneNode(const SharedShadowNode &node);
SharedShadowNode cloneNodeWithNewChildren(const SharedShadowNode &node);
SharedShadowNode cloneNodeWithNewProps(const SharedShadowNode &node, folly::dynamic props);
SharedShadowNode cloneNodeWithNewChildrenAndProps(const SharedShadowNode &node, folly::dynamic newProps);
void appendChild(const SharedShadowNode &parentNode, const SharedShadowNode &childNode);
SharedShadowNodeUnsharedList createChildSet(int rootTag);
void appendChildToSet(const SharedShadowNodeUnsharedList &childSet, const SharedShadowNode &childNode);
void completeRoot(int rootTag, const SharedShadowNodeUnsharedList &childSet);
private:
std::shared_ptr<IFabricPlatformUIOperationManager> platformUIOperationManager_;

View File

@ -1,20 +0,0 @@
/**
* 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.
*/
#include "ShadowNode.h"
namespace facebook {
namespace react {
ShadowNode::ShadowNode(int reactTag, std::string viewName, int rootTag, folly::dynamic props, void *instanceHandle) :
reactTag_(reactTag),
viewName_(viewName),
rootTag_(rootTag),
props_(props),
instanceHandle_(instanceHandle) {}
}}

View File

@ -1,27 +0,0 @@
/**
* 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 <folly/dynamic.h>
#include <memory>
namespace facebook {
namespace react {
class ShadowNode {
public:
int reactTag_;
std::string viewName_;
int rootTag_;
folly::dynamic props_;
void *instanceHandle_;
ShadowNode(int reactTag, std::string viewName, int rootTag, folly::dynamic props, void *instanceHandle);
};
}}

View File

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

View File

@ -0,0 +1,55 @@
/**
* 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 <string>
#include <folly/dynamic.h>
namespace facebook {
namespace react {
/*
* `Tag` and `InstanceHandle` are used to address React Native components.
*/
using Tag = int32_t;
using InstanceHandle = void *;
/*
* `RawProps` represents untyped map with props comes from JavaScript side.
*/
// TODO(T26954420): Use iterator as underlying type for RawProps.
using RawProps = std::map<std::string, folly::dynamic>;
using SharedRawProps = std::shared_ptr<const RawProps>;
/*
* Components event handlers.
* Something which usually called from JavaScript side.
*/
using BubblingEventHandler = void (*)(void);
using SharedBubblingEventHandler = std::shared_ptr<BubblingEventHandler>;
using DirectEventHandler = void (*)(void);
using SharedDirectEventHandler = std::shared_ptr<DirectEventHandler>;
/*
* Universal component handle which allows to refer to `ComponentDescriptor`s
* in maps efficiently.
* Practically, it's something that concrete ShadowNode and concrete
* ComponentDescriptor have in common.
*/
using ComponentHandle = size_t;
/*
* String identifier for components used for addressing them from
* JavaScript side.
*/
using ComponentName = std::string;
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,29 @@
/**
* 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.
*/
#include "Props.h"
#include <folly/dynamic.h>
namespace facebook {
namespace react {
void Props::apply(const RawProps &rawProps) {
ensureUnsealed();
for (auto const &pair : rawProps) {
auto const &name = pair.first;
auto const &value = pair.second;
if (name == "nativeID") {
nativeId_ = value.asString();
}
}
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,38 @@
/**
* 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 <folly/dynamic.h>
#include <fabric/core/Sealable.h>
#include <fabric/core/ReactPrimitives.h>
#include <fabric/debug/DebugStringConvertible.h>
namespace facebook {
namespace react {
class Props;
using SharedProps = std::shared_ptr<const Props>;
/*
* Represents the most generic props object.
*/
class Props:
public virtual Sealable,
public virtual DebugStringConvertible {
public:
virtual void apply(const RawProps &rawProps);
private:
std::string nativeId_ {""};
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,134 @@
/**
* 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.
*/
#include "ShadowNode.h"
#include <fabric/debug/DebugStringConvertible.h>
#include <fabric/debug/DebugStringConvertibleItem.h>
namespace facebook {
namespace react {
SharedShadowNodeSharedList ShadowNode::emptySharedShadowNodeSharedList() {
static const auto emptySharedShadowNodeSharedList = std::make_shared<SharedShadowNodeList>();
return emptySharedShadowNodeSharedList;
}
#pragma mark - Constructors
ShadowNode::ShadowNode(
Tag tag,
InstanceHandle instanceHandle,
SharedProps props,
SharedShadowNodeSharedList children
):
tag_(tag),
instanceHandle_(instanceHandle),
props_(props),
children_(children) {}
ShadowNode::ShadowNode(
SharedShadowNode shadowNode,
SharedProps props,
SharedShadowNodeSharedList children
):
tag_(shadowNode->tag_),
instanceHandle_(shadowNode->instanceHandle_),
props_(props ? props : shadowNode->props_),
children_(children ? children : shadowNode->children_) {}
#pragma mark - Getters
SharedShadowNodeSharedList ShadowNode::getChildren() const {
return children_;
}
SharedProps ShadowNode::getProps() const {
return props_;
}
Tag ShadowNode::getTag() const {
return tag_;
}
#pragma mark - Mutating Methods
void ShadowNode::sealRecursive() const {
if (getSealed()) {
return;
}
seal();
props_->seal();
for (auto child : *children_) {
child->sealRecursive();
}
}
void ShadowNode::appendChild(const SharedShadowNode &child) {
ensureUnsealed();
// We cannot mutate `children_` in place here because it is a *shared*
// data structure which means other `ShadowNodes` might refer to its old value.
// So, we have to clone this and only then mutate.
auto nonConstChildrenCopy = SharedShadowNodeList(*children_);
nonConstChildrenCopy.push_back(child);
children_ = std::make_shared<const SharedShadowNodeList>(nonConstChildrenCopy);
}
void ShadowNode::replaceChild(const SharedShadowNode &oldChild, const SharedShadowNode &newChild) {
ensureUnsealed();
// We cannot mutate `children_` in place here because it is a *shared*
// data structure which means other `ShadowNodes` might refer to its old value.
// So, we have to clone this and only then mutate.
auto nonConstChildrenCopy = SharedShadowNodeList(*children_);
std::replace(nonConstChildrenCopy.begin(), nonConstChildrenCopy.end(), oldChild, newChild);
children_ = std::make_shared<const SharedShadowNodeList>(nonConstChildrenCopy);
}
#pragma mark - DebugStringConvertible
std::string ShadowNode::getDebugName() const {
return getComponentName();
}
std::string ShadowNode::getDebugValue() const {
return getSealed() ? "sealed" : "";
}
SharedDebugStringConvertibleList ShadowNode::getDebugChildren() const {
SharedDebugStringConvertibleList debugChildren = {};
for (auto child : *children_) {
auto debugChild = std::dynamic_pointer_cast<const DebugStringConvertible>(child);
if (debugChild) {
debugChildren.push_back(debugChild);
}
}
return debugChildren;
}
SharedDebugStringConvertibleList ShadowNode::getDebugProps() const {
SharedDebugStringConvertibleList list = {};
list.push_back(std::make_shared<DebugStringConvertibleItem>("tag", std::to_string(tag_)));
if (instanceHandle_) {
list.push_back(std::make_shared<DebugStringConvertibleItem>("handle", std::to_string((size_t)instanceHandle_)));
}
SharedDebugStringConvertibleList propsList = props_->getDebugProps();
std::move(propsList.begin(), propsList.end(), std::back_inserter(list));
return list;
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,80 @@
/**
* 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 <string>
#include <vector>
#include <fabric/core/Props.h>
#include <fabric/core/Sealable.h>
#include <fabric/core/ReactPrimitives.h>
#include <fabric/debug/DebugStringConvertible.h>
namespace facebook {
namespace react {
class ShadowNode;
using SharedShadowNode = std::shared_ptr<const ShadowNode>;
using SharedShadowNodeList = std::vector<std::shared_ptr<const ShadowNode>>;
using SharedShadowNodeSharedList = std::shared_ptr<const SharedShadowNodeList>;
using SharedShadowNodeUnsharedList = std::shared_ptr<SharedShadowNodeList>;
class ShadowNode:
public virtual Sealable,
public virtual DebugStringConvertible {
public:
static SharedShadowNodeSharedList emptySharedShadowNodeSharedList();
#pragma mark - Constructors
ShadowNode(
Tag tag,
InstanceHandle instanceHandle,
SharedProps props = SharedProps(),
SharedShadowNodeSharedList children = SharedShadowNodeSharedList()
);
ShadowNode(
SharedShadowNode shadowNode,
SharedProps props = nullptr,
SharedShadowNodeSharedList children = nullptr
);
#pragma mark - Getters
virtual ComponentHandle getComponentHandle() const = 0;
virtual ComponentName getComponentName() const = 0;
SharedShadowNodeSharedList getChildren() const;
SharedProps getProps() const;
Tag getTag() const;
#pragma mark - Mutating Methods
void sealRecursive() const;
void appendChild(const SharedShadowNode &child);
void replaceChild(const SharedShadowNode &oldChild, const SharedShadowNode &newChild);
#pragma mark - DebugStringConvertible
std::string getDebugName() const override;
std::string getDebugValue() const override;
SharedDebugStringConvertibleList getDebugChildren() const override;
SharedDebugStringConvertibleList getDebugProps() const override;
protected:
Tag tag_;
InstanceHandle instanceHandle_;
SharedProps props_;
SharedShadowNodeSharedList children_;
};
} // namespace react
} // namespace facebook