Skip to content

Commit 0180563

Browse files
sammy-SCfacebook-github-bot
authored andcommitted
Move ShadowNode::getAncestors to ShadowNodeFamily
Summary: Changelog: [internal] 1. Moves `ShadowNode::getAncestors` to `ShadowNodeFamily`. 2. Exposes shadowNode's family through `ShadowNode::getFamily()`. # Why? This is a first step in order to merge `StateCoordinator` into `ShadowNodeFamily` and use it as target for state updates. Reviewed By: shergin Differential Revision: D19465188 fbshipit-source-id: b5a3625aa21c040301259de02beedbf97e11f20e
1 parent 8259a9d commit 0180563

File tree

12 files changed

+176
-73
lines changed

12 files changed

+176
-73
lines changed

ReactCommon/fabric/components/root/RootShadowNode.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ RootShadowNode::Unshared RootShadowNode::clone(
4747
}
4848

4949
RootShadowNode::Unshared RootShadowNode::clone(
50-
ShadowNode const &shadowNode,
50+
ShadowNodeFamily const &shadowNodeFamily,
5151
std::function<ShadowNode::Unshared(ShadowNode const &oldShadowNode)>
5252
callback) const {
53-
auto ancestors = shadowNode.getAncestors(*this);
53+
auto ancestors = shadowNodeFamily.getAncestors(*this);
5454

5555
if (ancestors.size() == 0) {
5656
return RootShadowNode::Unshared{nullptr};
@@ -59,7 +59,6 @@ RootShadowNode::Unshared RootShadowNode::clone(
5959
auto &parent = ancestors.back();
6060
auto &oldShadowNode = parent.first.get().getChildren().at(parent.second);
6161

62-
assert(ShadowNode::sameFamily(shadowNode, *oldShadowNode));
6362
auto newShadowNode = callback(*oldShadowNode);
6463

6564
auto childNode = newShadowNode;

ReactCommon/fabric/components/root/RootShadowNode.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class RootShadowNode final
5555
* Returns `nullptr` if the operation cannot be performed successfully.
5656
*/
5757
RootShadowNode::Unshared clone(
58-
ShadowNode const &shadowNode,
58+
ShadowNodeFamily const &shadowNodeFamily,
5959
std::function<ShadowNode::Unshared(ShadowNode const &oldShadowNode)>
6060
callback) const;
6161

ReactCommon/fabric/core/componentdescriptor/ConcreteComponentDescriptor.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include <react/core/ShadowNodeFragment.h>
1818
#include <react/core/State.h>
1919
#include <react/core/StateCoordinator.h>
20-
#include <react/core/StateUpdate.h>
2120

2221
namespace facebook {
2322
namespace react {

ReactCommon/fabric/core/layout/LayoutableShadowNode.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ LayoutMetrics LayoutableShadowNode::getRelativeLayoutMetrics(
9999
return layoutMetrics;
100100
}
101101

102-
auto ancestors = shadowNode.getAncestors(ancestorShadowNode);
102+
auto ancestors = shadowNode.getFamily().getAncestors(ancestorShadowNode);
103103

104104
if (ancestors.size() == 0) {
105105
return EmptyLayoutMetrics;

ReactCommon/fabric/core/shadownode/ShadowNode.cpp

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
namespace facebook {
1818
namespace react {
1919

20-
using AncestorList = ShadowNode::AncestorList;
21-
2220
SharedShadowNodeSharedList ShadowNode::emptySharedShadowNodeSharedList() {
2321
static const auto emptySharedShadowNodeSharedList =
2422
std::make_shared<SharedShadowNodeList>();
@@ -215,44 +213,8 @@ void ShadowNode::setMounted(bool mounted) const {
215213
family_->eventEmitter_->setEnabled(mounted);
216214
}
217215

218-
AncestorList ShadowNode::getAncestors(
219-
ShadowNode const &ancestorShadowNode) const {
220-
auto families = better::small_vector<ShadowNodeFamily const *, 64>{};
221-
auto ancestorFamily = ancestorShadowNode.family_.get();
222-
223-
auto family = family_.get();
224-
while (family && family != ancestorFamily) {
225-
families.push_back(family);
226-
family = family->parent_.lock().get();
227-
}
228-
229-
if (family != ancestorFamily) {
230-
return {};
231-
}
232-
233-
auto ancestors = AncestorList{};
234-
auto parentNode = &ancestorShadowNode;
235-
for (auto it = families.rbegin(); it != families.rend(); it++) {
236-
auto childFamily = *it;
237-
auto found = false;
238-
auto childIndex = 0;
239-
for (const auto &childNode : *parentNode->children_) {
240-
if (childNode->family_.get() == childFamily) {
241-
ancestors.push_back({*parentNode, childIndex});
242-
parentNode = childNode.get();
243-
found = true;
244-
break;
245-
}
246-
childIndex++;
247-
}
248-
249-
if (!found) {
250-
ancestors.clear();
251-
return ancestors;
252-
}
253-
}
254-
255-
return ancestors;
216+
ShadowNodeFamily const &ShadowNode::getFamily() const {
217+
return *family_;
256218
}
257219

258220
#pragma mark - DebugStringConvertible

ReactCommon/fabric/core/shadownode/ShadowNode.h

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ static constexpr const int kShadowNodeChildrenSmallVectorSize = 8;
2828

2929
class ComponentDescriptor;
3030
struct ShadowNodeFragment;
31-
3231
class ShadowNode;
3332

3433
using SharedShadowNode = std::shared_ptr<const ShadowNode>;
@@ -127,6 +126,8 @@ class ShadowNode : public virtual Sealable,
127126

128127
void sealRecursive() const;
129128

129+
ShadowNodeFamily const &getFamily() const;
130+
130131
#pragma mark - Mutating Methods
131132

132133
void appendChild(ShadowNode::Shared const &child);
@@ -142,17 +143,6 @@ class ShadowNode : public virtual Sealable,
142143
*/
143144
void setMounted(bool mounted) const;
144145

145-
/*
146-
* Returns a list of all ancestors of the node relative to the given ancestor.
147-
* The list starts from the given ancestor node and ends with the parent node
148-
* of `this` node. The elements of the list have a reference to some parent
149-
* node and an index of the child of the parent node.
150-
* Returns an empty array if there is no ancestor-descendant relationship.
151-
* Can be called from any thread.
152-
* The theoretical complexity of the algorithm is `O(ln(n))`. Use it wisely.
153-
*/
154-
AncestorList getAncestors(ShadowNode const &ancestorShadowNode) const;
155-
156146
#pragma mark - DebugStringConvertible
157147

158148
#if RN_DEBUG_STRING_CONVERTIBLE
@@ -175,6 +165,7 @@ class ShadowNode : public virtual Sealable,
175165
State::Shared state_;
176166

177167
private:
168+
friend ShadowNodeFamily;
178169
/*
179170
* Clones the list of children (and creates a new `shared_ptr` to it) if
180171
* `childrenAreShared_` flag is `true`.

ReactCommon/fabric/core/shadownode/ShadowNodeFamily.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66
*/
77

88
#include "ShadowNodeFamily.h"
9+
#include "ShadowNode.h"
910

1011
#include <react/core/ComponentDescriptor.h>
1112

1213
namespace facebook {
1314
namespace react {
1415

16+
using AncestorList = ShadowNode::AncestorList;
17+
1518
ShadowNodeFamily::ShadowNodeFamily(
1619
ShadowNodeFamilyFragment const &fragment,
1720
ComponentDescriptor const &componentDescriptor)
@@ -40,5 +43,45 @@ ComponentName ShadowNodeFamily::getComponentName() const {
4043
return componentName_;
4144
}
4245

46+
AncestorList ShadowNodeFamily::getAncestors(
47+
ShadowNode const &ancestorShadowNode) const {
48+
auto families = better::small_vector<ShadowNodeFamily const *, 64>{};
49+
auto ancestorFamily = ancestorShadowNode.family_.get();
50+
51+
auto family = this;
52+
while (family && family != ancestorFamily) {
53+
families.push_back(family);
54+
family = family->parent_.lock().get();
55+
}
56+
57+
if (family != ancestorFamily) {
58+
return {};
59+
}
60+
61+
auto ancestors = AncestorList{};
62+
auto parentNode = &ancestorShadowNode;
63+
for (auto it = families.rbegin(); it != families.rend(); it++) {
64+
auto childFamily = *it;
65+
auto found = false;
66+
auto childIndex = 0;
67+
for (const auto &childNode : *parentNode->children_) {
68+
if (childNode->family_.get() == childFamily) {
69+
ancestors.push_back({*parentNode, childIndex});
70+
parentNode = childNode.get();
71+
found = true;
72+
break;
73+
}
74+
childIndex++;
75+
}
76+
77+
if (!found) {
78+
ancestors.clear();
79+
return ancestors;
80+
}
81+
}
82+
83+
return ancestors;
84+
}
85+
4386
} // namespace react
4487
} // namespace facebook

ReactCommon/fabric/core/shadownode/ShadowNodeFamily.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ namespace facebook {
1717
namespace react {
1818

1919
class ComponentDescriptor;
20+
class ShadowNode;
2021

2122
/*
2223
* Represents all things that shadow nodes from the same family have in common.
@@ -27,6 +28,12 @@ class ShadowNodeFamily {
2728
using Shared = std::shared_ptr<ShadowNodeFamily const>;
2829
using Weak = std::weak_ptr<ShadowNodeFamily const>;
2930

31+
using AncestorList = better::small_vector<
32+
std::pair<
33+
std::reference_wrapper<ShadowNode const> /* parentNode */,
34+
int /* childIndex */>,
35+
64>;
36+
3037
ShadowNodeFamily(
3138
ShadowNodeFamilyFragment const &fragment,
3239
ComponentDescriptor const &componentDescriptor);
@@ -44,6 +51,17 @@ class ShadowNodeFamily {
4451
ComponentHandle getComponentHandle() const;
4552
ComponentName getComponentName() const;
4653

54+
/*
55+
* Returns a list of all ancestors of the node relative to the given ancestor.
56+
* The list starts from the given ancestor node and ends with the parent node
57+
* of `this` node. The elements of the list have a reference to some parent
58+
* node and an index of the child of the parent node.
59+
* Returns an empty array if there is no ancestor-descendant relationship.
60+
* Can be called from any thread.
61+
* The theoretical complexity of the algorithm is `O(ln(n))`. Use it wisely.
62+
*/
63+
AncestorList getAncestors(ShadowNode const &ancestorShadowNode) const;
64+
4765
private:
4866
friend ShadowNode;
4967

ReactCommon/fabric/core/state/State.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include <react/core/ShadowNodeFragment.h>
1313
#include <react/core/State.h>
1414
#include <react/core/StateTarget.h>
15-
#include <react/core/StateUpdate.h>
1615

1716
#ifdef ANDROID
1817
#include <folly/dynamic.h>
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include <exception>
9+
10+
#include <gtest/gtest.h>
11+
#include "TestComponent.h"
12+
13+
using namespace facebook::react;
14+
15+
TEST(ShadowNodeFamilyTest, sealObjectCorrectly) {
16+
/*
17+
* The structure:
18+
* <A>
19+
* <AA>
20+
* <AAA/>
21+
* </AA>
22+
* </A>
23+
*/
24+
SurfaceId surfaceId = 1;
25+
auto eventDispatcher = std::shared_ptr<EventDispatcher const>();
26+
auto componentDescriptor = TestComponentDescriptor({eventDispatcher});
27+
auto props = std::make_shared<const TestProps>();
28+
29+
auto familyAAA = std::make_shared<ShadowNodeFamily>(
30+
ShadowNodeFamilyFragment{
31+
/* .tag = */ 12,
32+
/* .surfaceId = */ surfaceId,
33+
/* .eventEmitter = */ nullptr,
34+
},
35+
componentDescriptor);
36+
37+
auto nodeAAA = std::make_shared<TestShadowNode>(
38+
ShadowNodeFragment{
39+
/* .props = */ props,
40+
/* .children = */ ShadowNode::emptySharedShadowNodeSharedList(),
41+
},
42+
familyAAA,
43+
ShadowNodeTraits{});
44+
45+
auto nodeAAChildren =
46+
std::make_shared<SharedShadowNodeList>(SharedShadowNodeList{nodeAAA});
47+
auto familyAA = std::make_shared<ShadowNodeFamily>(
48+
ShadowNodeFamilyFragment{
49+
/* .tag = */ 11,
50+
/* .surfaceId = */ surfaceId,
51+
/* .eventEmitter = */ nullptr,
52+
},
53+
componentDescriptor);
54+
auto nodeAA = std::make_shared<TestShadowNode>(
55+
ShadowNodeFragment{
56+
/* .props = */ props,
57+
/* .children = */ nodeAAChildren,
58+
},
59+
familyAA,
60+
ShadowNodeTraits{});
61+
62+
auto nodeAChildren =
63+
std::make_shared<SharedShadowNodeList>(SharedShadowNodeList{nodeAA});
64+
65+
auto familyA = std::make_shared<ShadowNodeFamily>(
66+
ShadowNodeFamilyFragment{
67+
/* .tag = */ 17,
68+
/* .surfaceId = */ surfaceId,
69+
/* .eventEmitter = */ nullptr,
70+
},
71+
componentDescriptor);
72+
auto nodeA = std::make_shared<TestShadowNode>(
73+
ShadowNodeFragment{
74+
/* .props = */ props,
75+
/* .children = */ nodeAChildren,
76+
},
77+
familyA,
78+
ShadowNodeTraits{});
79+
80+
auto familyZ = std::make_shared<ShadowNodeFamily>(
81+
ShadowNodeFamilyFragment{
82+
/* .tag = */ 18,
83+
/* .surfaceId = */ surfaceId,
84+
/* .eventEmitter = */ nullptr,
85+
},
86+
componentDescriptor);
87+
auto nodeZ = std::make_shared<TestShadowNode>(
88+
ShadowNodeFragment{
89+
/* .props = */ props,
90+
/* .children = */ ShadowNode::emptySharedShadowNodeSharedList(),
91+
},
92+
familyZ,
93+
ShadowNodeTraits{});
94+
95+
// Negative case:
96+
auto ancestors1 = nodeZ->getFamily().getAncestors(*nodeA);
97+
EXPECT_EQ(ancestors1.size(), 0);
98+
99+
// Positive case:
100+
auto ancestors2 = nodeAAA->getFamily().getAncestors(*nodeA);
101+
EXPECT_EQ(ancestors2.size(), 2);
102+
EXPECT_EQ(&ancestors2[0].first.get(), nodeA.get());
103+
EXPECT_EQ(&ancestors2[1].first.get(), nodeAA.get());
104+
}

0 commit comments

Comments
 (0)