Initialise ShadowNodeFamily before ShadowNode is created

Summary:
Changelog: [internal]

1. Use `ShadowNode::Shared` instead of `SharedShadowNode`.
2. Initialise `ShadowNodeFamily` before `ShadowNode`.

Why?
This is a step in order to merge `StateCoordinator` into `ShadowNodeFamily` and use it as target for state updates.

Reviewed By: shergin

Differential Revision: D19471399

fbshipit-source-id: 2f67901c901349d238c711f9eeaadb19fe7c1110
This commit is contained in:
Samuel Susla
2020-01-28 09:32:53 -08:00
committed by Facebook Github Bot
parent 01805636b9
commit 7f79b46bad
11 changed files with 100 additions and 113 deletions
+1
View File
@@ -84,6 +84,7 @@ fb_xplat_cxx_test(
platforms = (ANDROID, APPLE, CXX),
deps = [
"fbsource//xplat/folly:molly",
"fbsource//xplat/js/react-native-github/ReactCommon/fabric/element:element",
"fbsource//xplat/third-party/gmock:gtest",
react_native_xplat_target("fabric/components/view:view"),
":core",
@@ -75,9 +75,9 @@ class ComponentDescriptor {
/*
* Creates a new `ShadowNode` of a particular component type.
*/
virtual SharedShadowNode createShadowNode(
virtual ShadowNode::Shared createShadowNode(
const ShadowNodeFragment &fragment,
ShadowNodeFamilyFragment const &familyFragment) const = 0;
ShadowNodeFamily::Shared const &family) const = 0;
/*
* Clones a `ShadowNode` with optionally new `props` and/or `children`.
@@ -61,14 +61,10 @@ class ConcreteComponentDescriptor : public ComponentDescriptor {
return ShadowNodeT::BaseTraits();
}
SharedShadowNode createShadowNode(
ShadowNode::Shared createShadowNode(
const ShadowNodeFragment &fragment,
ShadowNodeFamilyFragment const &familyFragment) const override {
ShadowNodeFamily::Shared const &family) const override {
assert(std::dynamic_pointer_cast<const ConcreteProps>(fragment.props));
assert(std::dynamic_pointer_cast<const ConcreteEventEmitter>(
familyFragment.eventEmitter));
auto family = std::make_shared<ShadowNodeFamily>(familyFragment, *this);
auto shadowNode =
std::make_shared<ShadowNodeT>(fragment, family, getTraits());
@@ -39,6 +39,10 @@ ComponentHandle ShadowNodeFamily::getComponentHandle() const {
return componentHandle_;
}
SurfaceId ShadowNodeFamily::getSurfaceId() const {
return surfaceId_;
}
ComponentName ShadowNodeFamily::getComponentName() const {
return componentName_;
}
@@ -62,6 +62,8 @@ class ShadowNodeFamily {
*/
AncestorList getAncestors(ShadowNode const &ancestorShadowNode) const;
SurfaceId getSurfaceId() const;
private:
friend ShadowNode;
@@ -23,16 +23,15 @@ TEST(ComponentDescriptorTest, createShadowNode) {
const auto &raw = RawProps(folly::dynamic::object("nativeID", "abc"));
SharedProps props = descriptor->cloneProps(nullptr, raw);
auto family = std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{9, 1, descriptor->createEventEmitter(0, 9)},
*descriptor);
SharedShadowNode node = descriptor->createShadowNode(
ShadowNodeFragment{
/* .props = */ props,
},
ShadowNodeFamilyFragment{
/* .tag = */ 9,
/* .surfaceId = */ 1,
/* .eventEmitter = */ descriptor->createEventEmitter(0, 9),
});
family);
EXPECT_EQ(node->getComponentHandle(), TestShadowNode::Handle());
EXPECT_STREQ(node->getComponentName(), TestShadowNode::Name());
@@ -50,15 +49,14 @@ TEST(ComponentDescriptorTest, cloneShadowNode) {
const auto &raw = RawProps(folly::dynamic::object("nativeID", "abc"));
SharedProps props = descriptor->cloneProps(nullptr, raw);
auto family = std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{9, 1, descriptor->createEventEmitter(0, 9)},
*descriptor);
SharedShadowNode node = descriptor->createShadowNode(
ShadowNodeFragment{
/* .props = */ props,
},
ShadowNodeFamilyFragment{
/* .tag = */ 9,
/* .surfaceId = */ 1,
/* .eventEmitter = */ descriptor->createEventEmitter(0, 9),
});
family);
SharedShadowNode cloned = descriptor->cloneShadowNode(*node, {});
EXPECT_STREQ(cloned->getComponentName(), "Test");
@@ -75,34 +73,30 @@ TEST(ComponentDescriptorTest, appendChild) {
const auto &raw = RawProps(folly::dynamic::object("nativeID", "abc"));
SharedProps props = descriptor->cloneProps(nullptr, raw);
auto family1 = std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{1, 1, descriptor->createEventEmitter(0, 9)},
*descriptor);
SharedShadowNode node1 = descriptor->createShadowNode(
ShadowNodeFragment{
/* .props = */ props,
},
ShadowNodeFamilyFragment{
/* .tag = */ 1,
/* .surfaceId = */ 1,
/* .eventEmitter = */ descriptor->createEventEmitter(0, 9),
});
family1);
auto family2 = std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{2, 1, descriptor->createEventEmitter(0, 2)},
*descriptor);
SharedShadowNode node2 = descriptor->createShadowNode(
ShadowNodeFragment{
/* .props = */ props,
},
ShadowNodeFamilyFragment{
/* .tag = */ 2,
/* .surfaceId = */ 1,
/* .eventEmitter = */ descriptor->createEventEmitter(0, 9),
});
family2);
auto family3 = std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{3, 1, descriptor->createEventEmitter(0, 3)},
*descriptor);
SharedShadowNode node3 = descriptor->createShadowNode(
ShadowNodeFragment{
/* .props = */ props,
},
ShadowNodeFamilyFragment{
/* .tag = */ 3,
/* .surfaceId = */ 1,
/* .eventEmitter = */ descriptor->createEventEmitter(0, 9),
});
family3);
descriptor->appendChild(node1, node2);
descriptor->appendChild(node1, node3);
@@ -8,7 +8,11 @@
#include <exception>
#include <gtest/gtest.h>
#include "TestComponent.h"
#include <react/components/view/ViewComponentDescriptor.h>
#include <react/element/ComponentBuilder.h>
#include <react/element/Element.h>
#include <react/uimanager/ComponentDescriptorProviderRegistry.h>
using namespace facebook::react;
@@ -21,84 +25,55 @@ TEST(ShadowNodeFamilyTest, sealObjectCorrectly) {
* </AA>
* </A>
*/
SurfaceId surfaceId = 1;
auto eventDispatcher = std::shared_ptr<EventDispatcher const>();
auto componentDescriptor = TestComponentDescriptor({eventDispatcher});
auto props = std::make_shared<const TestProps>();
ComponentDescriptorProviderRegistry componentDescriptorProviderRegistry{};
auto eventDispatcher = EventDispatcher::Shared{};
auto componentDescriptorRegistry =
componentDescriptorProviderRegistry.createComponentDescriptorRegistry(
ComponentDescriptorParameters{eventDispatcher, nullptr, nullptr});
auto familyAAA = std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{
/* .tag = */ 12,
/* .surfaceId = */ surfaceId,
/* .eventEmitter = */ nullptr,
},
componentDescriptor);
componentDescriptorProviderRegistry.add(
concreteComponentDescriptorProvider<ViewComponentDescriptor>());
auto nodeAAA = std::make_shared<TestShadowNode>(
ShadowNodeFragment{
/* .props = */ props,
/* .children = */ ShadowNode::emptySharedShadowNodeSharedList(),
},
familyAAA,
ShadowNodeTraits{});
auto builder = ComponentBuilder{componentDescriptorRegistry};
auto nodeAAChildren =
std::make_shared<SharedShadowNodeList>(SharedShadowNodeList{nodeAAA});
auto familyAA = std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{
/* .tag = */ 11,
/* .surfaceId = */ surfaceId,
/* .eventEmitter = */ nullptr,
},
componentDescriptor);
auto nodeAA = std::make_shared<TestShadowNode>(
ShadowNodeFragment{
/* .props = */ props,
/* .children = */ nodeAAChildren,
},
familyAA,
ShadowNodeTraits{});
auto shadowNodeAAA = std::shared_ptr<ViewShadowNode const>{};
auto shadowNodeAA = std::shared_ptr<ViewShadowNode const>{};
auto nodeAChildren =
std::make_shared<SharedShadowNodeList>(SharedShadowNodeList{nodeAA});
// clang-format off
auto elementA =
Element<ViewShadowNode>()
.tag(1)
.finalize([](ViewShadowNode &shadowNode){
shadowNode.sealRecursive();
})
.children({
Element<ViewShadowNode>()
.tag(2)
.reference(shadowNodeAA)
.children({
Element<ViewShadowNode>()
.reference(shadowNodeAAA)
.tag(3)
})
});
auto elementB =
Element<ViewShadowNode>()
.tag(1)
.finalize([](ViewShadowNode &shadowNode){
shadowNode.sealRecursive();
});
// clang-format on
auto familyA = std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{
/* .tag = */ 17,
/* .surfaceId = */ surfaceId,
/* .eventEmitter = */ nullptr,
},
componentDescriptor);
auto nodeA = std::make_shared<TestShadowNode>(
ShadowNodeFragment{
/* .props = */ props,
/* .children = */ nodeAChildren,
},
familyA,
ShadowNodeTraits{});
auto familyZ = std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{
/* .tag = */ 18,
/* .surfaceId = */ surfaceId,
/* .eventEmitter = */ nullptr,
},
componentDescriptor);
auto nodeZ = std::make_shared<TestShadowNode>(
ShadowNodeFragment{
/* .props = */ props,
/* .children = */ ShadowNode::emptySharedShadowNodeSharedList(),
},
familyZ,
ShadowNodeTraits{});
auto shadowNodeA = builder.build(elementA);
auto shadowNodeB = builder.build(elementB);
// Negative case:
auto ancestors1 = nodeZ->getFamily().getAncestors(*nodeA);
auto ancestors1 = shadowNodeB->getFamily().getAncestors(*shadowNodeA);
EXPECT_EQ(ancestors1.size(), 0);
// Positive case:
auto ancestors2 = nodeAAA->getFamily().getAncestors(*nodeA);
auto ancestors2 = shadowNodeAAA->getFamily().getAncestors(*shadowNodeA);
EXPECT_EQ(ancestors2.size(), 2);
EXPECT_EQ(&ancestors2[0].first.get(), nodeA.get());
EXPECT_EQ(&ancestors2[1].first.get(), nodeAA.get());
EXPECT_EQ(&ancestors2[0].first.get(), shadowNodeA.get());
EXPECT_EQ(&ancestors2[1].first.get(), shadowNodeAA.get());
}
@@ -28,13 +28,17 @@ ShadowNode::Shared ComponentBuilder::build(
auto eventEmitter =
componentDescriptor.createEventEmitter(nullptr, elementFragment.tag);
auto family = std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{
elementFragment.tag, elementFragment.surfaceId, eventEmitter},
componentDescriptor);
auto shadowNode = componentDescriptor.createShadowNode(
ShadowNodeFragment{
elementFragment.props,
std::make_shared<ShadowNode::ListOfShared const>(children),
elementFragment.state},
ShadowNodeFamilyFragment{
elementFragment.tag, elementFragment.surfaceId, eventEmitter});
family);
if (elementFragment.referenceCallback) {
elementFragment.referenceCallback(shadowNode);
+4 -1
View File
@@ -102,12 +102,15 @@ ShadowTree::ShadowTree(
const auto props = std::make_shared<const RootProps>(
*RootShadowNode::defaultSharedProps(), layoutConstraints, layoutContext);
auto family = std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{surfaceId, surfaceId, noopEventEmitter},
rootComponentDescriptor);
rootShadowNode_ = std::static_pointer_cast<const RootShadowNode>(
rootComponentDescriptor.createShadowNode(
ShadowNodeFragment{
/* .props = */ props,
},
{surfaceId, surfaceId, noopEventEmitter}));
family));
mountingCoordinator_ = std::make_shared<MountingCoordinator const>(
ShadowTreeRevision{rootShadowNode_, 0, {}});
@@ -172,8 +172,12 @@ SharedShadowNode ComponentDescriptorRegistry::createNode(
auto unifiedComponentName = componentNameByReactViewName(viewName);
auto const &componentDescriptor = this->at(unifiedComponentName);
auto const eventEmitter =
componentDescriptor.createEventEmitter(std::move(eventTarget), tag);
auto family = std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{
tag,
surfaceId,
componentDescriptor.createEventEmitter(std::move(eventTarget), tag)},
componentDescriptor);
auto const props =
componentDescriptor.cloneProps(nullptr, RawProps(propsDynamic));
auto const state = componentDescriptor.createInitialState(
@@ -185,7 +189,7 @@ SharedShadowNode ComponentDescriptorRegistry::createNode(
/* .children = */ ShadowNodeFragment::childrenPlaceholder(),
/* .state = */ state,
},
{tag, surfaceId, eventEmitter});
family);
}
void ComponentDescriptorRegistry::setFallbackComponentDescriptor(
+7 -3
View File
@@ -33,8 +33,12 @@ SharedShadowNode UIManager::createNode(
auto fallbackDescriptor =
componentDescriptorRegistry_->getFallbackComponentDescriptor();
auto const eventEmitter =
componentDescriptor.createEventEmitter(std::move(eventTarget), tag);
auto family = std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{
tag,
surfaceId,
componentDescriptor.createEventEmitter(std::move(eventTarget), tag)},
componentDescriptor);
auto const props = componentDescriptor.cloneProps(nullptr, rawProps);
auto const state = componentDescriptor.createInitialState(
ShadowNodeFragment{props}, surfaceId);
@@ -51,7 +55,7 @@ SharedShadowNode UIManager::createNode(
/* .children = */ ShadowNodeFragment::childrenPlaceholder(),
/* .state = */ state,
},
ShadowNodeFamilyFragment{tag, surfaceId, eventEmitter});
family);
// state->commit(x) associates a ShadowNode with the State object.
// state->commit(x) must be called before calling updateState; updateState