Fabric: Introducing `LocalData` concept
Summary: LocalData might be used to communicate some infomation between `ShadowNode`s and native component views. We will use it soon to store (and transmit to mounting layer) prepared for rendering attributed text in Text component. Reviewed By: mdvacca Differential Revision: D7738582 fbshipit-source-id: 1ead23ffd105cce0b3d9aeb9fc1d0df47673be50
This commit is contained in:
parent
9d08e2afae
commit
368388bfc8
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* 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/Sealable.h>
|
||||
#include <fabric/debug/DebugStringConvertible.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class LocalData;
|
||||
|
||||
using SharedLocalData = std::shared_ptr<const LocalData>;
|
||||
|
||||
/*
|
||||
* Abstract class for any kind of concrete pieces of local data specific for
|
||||
* some kinds of `ShadowNode`s.
|
||||
* LocalData might be used to communicate some infomation between `ShadowNode`s
|
||||
* and native component views.
|
||||
* All `LocalData` objects *must* be immutable (sealed) when they became
|
||||
* a part of the shadow tree.
|
||||
*/
|
||||
class LocalData:
|
||||
public Sealable,
|
||||
public DebugStringConvertible {
|
||||
|
||||
// Nothing.
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -47,6 +47,7 @@ ShadowNode::ShadowNode(
|
|||
props_(props ? props : shadowNode->props_),
|
||||
children_(std::make_shared<SharedShadowNodeList>(*(children ? children : shadowNode->children_))),
|
||||
sourceNode_(shadowNode),
|
||||
localData_(shadowNode->localData_),
|
||||
cloneFunction_(shadowNode->cloneFunction_),
|
||||
revision_(shadowNode->revision_ + 1) {}
|
||||
|
||||
|
@ -84,6 +85,10 @@ SharedShadowNode ShadowNode::getSourceNode() const {
|
|||
return sourceNode_.lock();
|
||||
}
|
||||
|
||||
SharedLocalData ShadowNode::getLocalData() const {
|
||||
return localData_;
|
||||
}
|
||||
|
||||
void ShadowNode::sealRecursive() const {
|
||||
if (getSealed()) {
|
||||
return;
|
||||
|
@ -119,6 +124,11 @@ void ShadowNode::clearSourceNode() {
|
|||
sourceNode_.reset();
|
||||
}
|
||||
|
||||
void ShadowNode::setLocalData(const SharedLocalData &localData) {
|
||||
ensureUnsealed();
|
||||
localData_ = localData;
|
||||
}
|
||||
|
||||
void ShadowNode::shallowSourceNode() {
|
||||
ensureUnsealed();
|
||||
|
||||
|
@ -135,7 +145,8 @@ bool ShadowNode::operator==(const ShadowNode& rhs) const {
|
|||
return
|
||||
tag_ == rhs.tag_ &&
|
||||
rootTag_ == rhs.rootTag_ &&
|
||||
props_ == rhs.props_;
|
||||
props_ == rhs.props_ &&
|
||||
localData_ == rhs.localData_;
|
||||
}
|
||||
|
||||
bool ShadowNode::operator!=(const ShadowNode& rhs) const {
|
||||
|
|
|
@ -11,9 +11,10 @@
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <fabric/core/LocalData.h>
|
||||
#include <fabric/core/Props.h>
|
||||
#include <fabric/core/Sealable.h>
|
||||
#include <fabric/core/ReactPrimitives.h>
|
||||
#include <fabric/core/Sealable.h>
|
||||
#include <fabric/debug/DebugStringConvertible.h>
|
||||
|
||||
namespace facebook {
|
||||
|
@ -80,6 +81,14 @@ public:
|
|||
*/
|
||||
SharedShadowNode getSourceNode() const;
|
||||
|
||||
/*
|
||||
* Returns a local data associated with the node.
|
||||
* `LocalData` object might be used for data exchange between native view and
|
||||
* shadow node instances.
|
||||
* Concrete type of the object depends on concrete type of the `ShadowNode`.
|
||||
*/
|
||||
SharedLocalData getLocalData() const;
|
||||
|
||||
void sealRecursive() const;
|
||||
|
||||
#pragma mark - Mutating Methods
|
||||
|
@ -88,11 +97,18 @@ public:
|
|||
void replaceChild(const SharedShadowNode &oldChild, const SharedShadowNode &newChild);
|
||||
void clearSourceNode();
|
||||
|
||||
/*
|
||||
* Sets local data assosiated with the node.
|
||||
* The node must be unsealed at this point.
|
||||
*/
|
||||
void setLocalData(const SharedLocalData &localData);
|
||||
|
||||
/*
|
||||
* Replaces the current source node with its source node.
|
||||
* This method might be used for illuminating side-effects caused by the last
|
||||
* cloning operation which are not desirable from the diffing algorithm
|
||||
* perspective.
|
||||
* The node must be unsealed at this point.
|
||||
*/
|
||||
void shallowSourceNode();
|
||||
|
||||
|
@ -122,6 +138,7 @@ protected:
|
|||
SharedProps props_;
|
||||
SharedShadowNodeSharedList children_;
|
||||
WeakShadowNode sourceNode_;
|
||||
SharedLocalData localData_;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -150,3 +150,32 @@ TEST(ShadowNodeTest, handleCloneFunction) {
|
|||
ASSERT_EQ(secondNode->getRootTag(), secondNodeClone->getRootTag());
|
||||
ASSERT_EQ(secondNode->getProps(), secondNodeClone->getProps());
|
||||
}
|
||||
|
||||
TEST(ShadowNodeTest, handleLocalData) {
|
||||
auto localData42 = std::make_shared<TestLocalData>();
|
||||
localData42->setNumber(42);
|
||||
|
||||
auto anotherLocalData42 = std::make_shared<TestLocalData>();
|
||||
anotherLocalData42->setNumber(42);
|
||||
|
||||
auto localDataOver9000 = std::make_shared<TestLocalData>();
|
||||
localDataOver9000->setNumber(9001);
|
||||
|
||||
auto firstNode = std::make_shared<TestShadowNode>(9, 1, (void *)NULL);
|
||||
auto secondNode = std::make_shared<TestShadowNode>(9, 1, (void *)NULL);
|
||||
auto thirdNode = std::make_shared<TestShadowNode>(9, 1, (void *)NULL);
|
||||
|
||||
firstNode->setLocalData(localData42);
|
||||
secondNode->setLocalData(localData42);
|
||||
thirdNode->setLocalData(localDataOver9000);
|
||||
|
||||
// LocalData object are compared by pointer, not by value.
|
||||
ASSERT_EQ(*firstNode, *secondNode);
|
||||
ASSERT_NE(*firstNode, *thirdNode);
|
||||
secondNode->setLocalData(anotherLocalData42);
|
||||
ASSERT_NE(*firstNode, *secondNode);
|
||||
|
||||
// LocalData cannot be changed for sealed shadow node.
|
||||
secondNode->sealRecursive();
|
||||
ASSERT_ANY_THROW(secondNode->setLocalData(localDataOver9000));
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <fabric/core/ConcreteComponentDescriptor.h>
|
||||
#include <fabric/core/ConcreteShadowNode.h>
|
||||
#include <fabric/core/LocalData.h>
|
||||
#include <fabric/core/ShadowNode.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
@ -20,6 +21,20 @@ using namespace facebook::react;
|
|||
* To be used for testing purpose.
|
||||
*/
|
||||
|
||||
class TestLocalData: public LocalData {
|
||||
public:
|
||||
void setNumber(const int &number) {
|
||||
number_ = number;
|
||||
}
|
||||
|
||||
int getNumber() const {
|
||||
return number_;
|
||||
}
|
||||
|
||||
private:
|
||||
int number_ {0};
|
||||
};
|
||||
|
||||
class TestProps : public Props {
|
||||
public:
|
||||
TestProps() {
|
||||
|
|
Loading…
Reference in New Issue