Fabric: ShadowNodeFamily, the first steps

Summary:
ShadowNodeFamily is a new concept that allows us to implement an efficient way to solve the problem of finding a path to some ancestor node (practically reimplement ShadowNode::constructAncestorPath() in some efficient way).

This diff is the first one in the series. It introduces a new class and moves some data into it.

Reviewed By: JoshuaGross

Differential Revision: D14416947

fbshipit-source-id: c93865a8929a2128498e34d3589487696aac6283
This commit is contained in:
Valentin Shergin 2019-03-18 23:38:11 -07:00 коммит произвёл Facebook Github Bot
Родитель e0bbdbc040
Коммит 28e89e5081
9 изменённых файлов: 131 добавлений и 41 удалений

Просмотреть файл

@ -23,20 +23,25 @@ SharedShadowNodeSharedList ShadowNode::emptySharedShadowNodeSharedList() {
return emptySharedShadowNodeSharedList;
}
bool ShadowNode::sameFamily(const ShadowNode &first, const ShadowNode &second) {
return first.family_ == second.family_;
}
#pragma mark - Constructors
ShadowNode::ShadowNode(
const ShadowNodeFragment &fragment,
const ComponentDescriptor &componentDescriptor)
: tag_(fragment.tag),
rootTag_(fragment.rootTag),
props_(fragment.props),
eventEmitter_(fragment.eventEmitter),
: props_(fragment.props),
children_(
fragment.children ? fragment.children
: emptySharedShadowNodeSharedList()),
state_(fragment.state),
componentDescriptor_(componentDescriptor),
family_(std::make_shared<ShadowNodeFamily const>(
fragment.tag,
fragment.rootTag,
fragment.eventEmitter,
componentDescriptor)),
childrenAreShared_(true),
revision_(1) {
assert(props_);
@ -46,10 +51,7 @@ ShadowNode::ShadowNode(
ShadowNode::ShadowNode(
const ShadowNode &sourceShadowNode,
const ShadowNodeFragment &fragment)
: tag_(sourceShadowNode.tag_),
rootTag_(sourceShadowNode.rootTag_),
props_(fragment.props ? fragment.props : sourceShadowNode.props_),
eventEmitter_(fragment.eventEmitter),
: props_(fragment.props ? fragment.props : sourceShadowNode.props_),
children_(
fragment.children ? fragment.children : sourceShadowNode.children_),
localData_(
@ -58,7 +60,7 @@ ShadowNode::ShadowNode(
state_(
fragment.state ? fragment.state
: sourceShadowNode.getCommitedState()),
componentDescriptor_(sourceShadowNode.componentDescriptor_),
family_(sourceShadowNode.family_),
childrenAreShared_(true),
revision_(sourceShadowNode.revision_ + 1) {
// `tag`, `surfaceId`, and `eventEmitter` cannot be changed with cloning.
@ -72,7 +74,7 @@ ShadowNode::ShadowNode(
}
UnsharedShadowNode ShadowNode::clone(const ShadowNodeFragment &fragment) const {
return componentDescriptor_.cloneShadowNode(*this, fragment);
return family_->componentDescriptor_.cloneShadowNode(*this, fragment);
}
#pragma mark - Getters
@ -81,24 +83,24 @@ const SharedShadowNodeList &ShadowNode::getChildren() const {
return *children_;
}
SharedProps ShadowNode::getProps() const {
const SharedProps &ShadowNode::getProps() const {
return props_;
}
SharedEventEmitter ShadowNode::getEventEmitter() const {
return eventEmitter_;
const SharedEventEmitter &ShadowNode::getEventEmitter() const {
return family_->eventEmitter_;
}
Tag ShadowNode::getTag() const {
return tag_;
return family_->tag_;
}
Tag ShadowNode::getRootTag() const {
return rootTag_;
SurfaceId ShadowNode::getSurfaceId() const {
return family_->surfaceId_;
}
const ComponentDescriptor &ShadowNode::getComponentDescriptor() const {
return componentDescriptor_;
return family_->componentDescriptor_;
}
const State::Shared &ShadowNode::getState() const {
@ -175,7 +177,7 @@ void ShadowNode::cloneChildrenIfShared() {
}
void ShadowNode::setMounted(bool mounted) const {
eventEmitter_->setEnabled(mounted);
family_->eventEmitter_->setEnabled(mounted);
if (mounted && state_) {
state_->commit(*this);
}
@ -229,7 +231,7 @@ SharedDebugStringConvertibleList ShadowNode::getDebugChildren() const {
SharedDebugStringConvertibleList ShadowNode::getDebugProps() const {
return props_->getDebugProps() +
SharedDebugStringConvertibleList{
debugStringConvertibleItem("tag", folly::to<std::string>(tag_))};
debugStringConvertibleItem("tag", folly::to<std::string>(getTag()))};
}
#endif

Просмотреть файл

@ -17,6 +17,7 @@
#include <react/core/Props.h>
#include <react/core/ReactPrimitives.h>
#include <react/core/Sealable.h>
#include <react/core/ShadowNodeFamily.h>
#include <react/core/State.h>
#include <react/debug/DebugStringConvertible.h>
@ -47,6 +48,12 @@ class ShadowNode : public virtual Sealable,
static SharedShadowNodeSharedList emptySharedShadowNodeSharedList();
/*
* Returns `true` if nodes belong to the same family (they were cloned one
* from each other or from the same source node).
*/
static bool sameFamily(const ShadowNode &first, const ShadowNode &second);
#pragma mark - Constructors
/*
@ -77,11 +84,11 @@ class ShadowNode : public virtual Sealable,
virtual ComponentHandle getComponentHandle() const = 0;
virtual ComponentName getComponentName() const = 0;
const SharedShadowNodeList &getChildren() const;
SharedProps getProps() const;
SharedEventEmitter getEventEmitter() const;
SharedProps const &getProps() const;
SharedShadowNodeList const &getChildren() const;
SharedEventEmitter const &getEventEmitter() const;
Tag getTag() const;
Tag getRootTag() const;
SurfaceId getSurfaceId() const;
/*
* Returns a concrete `ComponentDescriptor` that manages nodes of this type.
@ -155,10 +162,7 @@ class ShadowNode : public virtual Sealable,
#endif
protected:
Tag tag_;
Tag rootTag_;
SharedProps props_;
SharedEventEmitter eventEmitter_;
SharedShadowNodeSharedList children_;
SharedLocalData localData_;
State::Shared state_;
@ -171,10 +175,9 @@ class ShadowNode : public virtual Sealable,
void cloneChildrenIfShared();
/*
* A reference to a concrete `ComponentDescriptor` that manages nodes of this
* type.
* Pointer to a family object that this shadow node belongs to.
*/
const ComponentDescriptor &componentDescriptor_;
ShadowNodeFamily::Shared family_;
/*
* Indicates that `children` list is shared between nodes and need

Просмотреть файл

@ -0,0 +1,24 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "ShadowNodeFamily.h"
namespace facebook {
namespace react {
ShadowNodeFamily::ShadowNodeFamily(
Tag tag,
SurfaceId surfaceId,
SharedEventEmitter const &eventEmitter,
ComponentDescriptor const &componentDescriptor)
: tag_(tag),
surfaceId_(surfaceId),
eventEmitter_(eventEmitter),
componentDescriptor_(componentDescriptor) {}
} // namespace react
} // namespace facebook

Просмотреть файл

@ -0,0 +1,61 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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 <react/core/EventEmitter.h>
#include <react/core/ReactPrimitives.h>
namespace facebook {
namespace react {
class ComponentDescriptor;
/*
* Represents all things that shadow nodes from the same family have in common.
* To be used inside `ShadowNode` class *only*.
*/
class ShadowNodeFamily {
public:
using Shared = std::shared_ptr<ShadowNodeFamily const>;
using Weak = std::weak_ptr<ShadowNodeFamily const>;
ShadowNodeFamily(
Tag tag,
SurfaceId surfaceId,
SharedEventEmitter const &eventEmitter,
ComponentDescriptor const &componentDescriptor);
private:
friend ShadowNode;
/*
* Deprecated.
*/
Tag const tag_;
/*
* Identifier of a running Surface instance.
*/
SurfaceId const surfaceId_;
/*
* `EventEmitter` associated with all nodes of the family.
*/
SharedEventEmitter const eventEmitter_;
/*
* Reference to a concrete `ComponentDescriptor` that manages nodes of this
* type.
*/
ComponentDescriptor const &componentDescriptor_;
};
} // namespace react
} // namespace facebook

Просмотреть файл

@ -34,7 +34,7 @@ TEST(ComponentDescriptorTest, createShadowNode) {
node->getComponentName().c_str(), TestShadowNode::Name().c_str());
ASSERT_STREQ(node->getComponentName().c_str(), "Test");
ASSERT_EQ(node->getTag(), 9);
ASSERT_EQ(node->getRootTag(), 1);
ASSERT_EQ(node->getSurfaceId(), 1);
ASSERT_STREQ(node->getProps()->nativeId.c_str(), "abc");
}
@ -54,7 +54,7 @@ TEST(ComponentDescriptorTest, cloneShadowNode) {
ASSERT_STREQ(cloned->getComponentName().c_str(), "Test");
ASSERT_EQ(cloned->getTag(), 9);
ASSERT_EQ(cloned->getRootTag(), 1);
ASSERT_EQ(cloned->getSurfaceId(), 1);
ASSERT_STREQ(cloned->getProps()->nativeId.c_str(), "abc");
}

Просмотреть файл

@ -41,7 +41,7 @@ TEST(ShadowNodeTest, handleShadowNodeCreation) {
ASSERT_FALSE(node->getSealed());
ASSERT_STREQ(node->getComponentName().c_str(), "Test");
ASSERT_EQ(node->getTag(), 9);
ASSERT_EQ(node->getRootTag(), 1);
ASSERT_EQ(node->getSurfaceId(), 1);
ASSERT_EQ(node->getEventEmitter(), nullptr);
ASSERT_EQ(node->getChildren().size(), 0);
@ -67,7 +67,7 @@ TEST(ShadowNodeTest, handleShadowNodeSimpleCloning) {
ASSERT_STREQ(node->getComponentName().c_str(), "Test");
ASSERT_EQ(node->getTag(), 9);
ASSERT_EQ(node->getRootTag(), 1);
ASSERT_EQ(node->getSurfaceId(), 1);
ASSERT_EQ(node->getEventEmitter(), nullptr);
}
@ -154,7 +154,7 @@ TEST(ShadowNodeTest, handleCloneFunction) {
// Both nodes have same content.
ASSERT_EQ(firstNode->getTag(), firstNodeClone->getTag());
ASSERT_EQ(firstNode->getRootTag(), firstNodeClone->getRootTag());
ASSERT_EQ(firstNode->getSurfaceId(), firstNodeClone->getSurfaceId());
ASSERT_EQ(firstNode->getProps(), firstNodeClone->getProps());
}

Просмотреть файл

@ -218,8 +218,8 @@ ShadowViewMutationList calculateShadowViewMutations(
const ShadowNode &newRootShadowNode) {
SystraceSection s("calculateShadowViewMutations");
// Root shadow nodes must have same tag.
assert(oldRootShadowNode.getTag() == newRootShadowNode.getTag());
// Root shadow nodes must be belong the same family.
assert(ShadowNode::sameFamily(oldRootShadowNode, newRootShadowNode));
ShadowViewMutationList mutations;

Просмотреть файл

@ -281,7 +281,7 @@ void Scheduler::uiManagerDidCreateShadowNode(
if (delegate_) {
auto shadowView = ShadowView(*shadowNode);
delegate_->schedulerDidRequestPreliminaryViewAllocation(
shadowNode->getRootTag(), shadowView);
shadowNode->getSurfaceId(), shadowView);
}
}

Просмотреть файл

@ -98,7 +98,7 @@ void UIManager::setNativeProps(
});
shadowTreeRegistry_->visit(
shadowNode->getRootTag(), [&](const ShadowTree &shadowTree) {
shadowNode->getSurfaceId(), [&](const ShadowTree &shadowTree) {
shadowTree.tryCommit(
[&](const SharedRootShadowNode &oldRootShadowNode) {
return oldRootShadowNode->clone(shadowNode, newShadowNode);
@ -116,7 +116,7 @@ LayoutMetrics UIManager::getRelativeLayoutMetrics(
if (!ancestorShadowNode) {
shadowTreeRegistry_->visit(
shadowNode.getRootTag(), [&](const ShadowTree &shadowTree) {
shadowNode.getSurfaceId(), [&](const ShadowTree &shadowTree) {
shadowTree.tryCommit(
[&](const SharedRootShadowNode &oldRootShadowNode) {
ancestorShadowNode = oldRootShadowNode.get();
@ -158,7 +158,7 @@ void UIManager::updateState(
});
shadowTreeRegistry_->visit(
shadowNode->getRootTag(), [&](const ShadowTree &shadowTree) {
shadowNode->getSurfaceId(), [&](const ShadowTree &shadowTree) {
shadowTree.tryCommit(
[&](const SharedRootShadowNode &oldRootShadowNode) {
return oldRootShadowNode->clone(shadowNode, newShadowNode);