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:
Родитель
e0bbdbc040
Коммит
28e89e5081
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче