mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-01-12 22:50:10 +08:00
Fabric: a new efficient implementation of ShadowNode::getAncestors()
Summary: The algorithm is quite simply: 1. Get family objects of the two nodes (inner and outer). 2. Traverse the list of family objects starting from the inner one and form a reversed list of them. 3. tarting from the inner node, traverse the tree layer-by-layer choosing a next element of the path by comparing the family object of each node on the level and an object from the list. Reviewed By: JoshuaGross Differential Revision: D14416950 fbshipit-source-id: 23c659a9e01690f90174193650a2b0ef09eadb4d
This commit is contained in:
committed by
Facebook Github Bot
parent
978e59aa92
commit
be51d0564b
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "ShadowNode.h"
|
||||
|
||||
#include <better/small_vector.h>
|
||||
#include <string>
|
||||
|
||||
#include <react/core/ComponentDescriptor.h>
|
||||
@@ -17,6 +18,8 @@
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
using AncestorList = ShadowNode::AncestorList;
|
||||
|
||||
SharedShadowNodeSharedList ShadowNode::emptySharedShadowNodeSharedList() {
|
||||
static const auto emptySharedShadowNodeSharedList =
|
||||
std::make_shared<SharedShadowNodeList>();
|
||||
@@ -197,6 +200,48 @@ void ShadowNode::setMounted(bool mounted) const {
|
||||
}
|
||||
}
|
||||
|
||||
AncestorList ShadowNode::getAncestors(
|
||||
ShadowNode const &ancestorShadowNode) const {
|
||||
auto ancestors = AncestorList{};
|
||||
auto families = better::small_vector<ShadowNodeFamily const *, 64>{};
|
||||
auto ancestorFamily = ancestorShadowNode.family_.get();
|
||||
auto descendantFamily = family_.get();
|
||||
|
||||
auto family = descendantFamily;
|
||||
while (family && family != ancestorFamily) {
|
||||
families.push_back(family);
|
||||
family = family->parent_.lock().get();
|
||||
}
|
||||
|
||||
if (family != ancestorFamily) {
|
||||
ancestors.clear();
|
||||
return ancestors;
|
||||
}
|
||||
|
||||
auto parentNode = &ancestorShadowNode;
|
||||
for (auto it = families.rbegin(); it != families.rend(); it++) {
|
||||
auto childFamily = *it;
|
||||
auto found = bool{false};
|
||||
auto childIndex = int{0};
|
||||
for (const auto &childNode : *parentNode->children_) {
|
||||
if (childNode->family_.get() == childFamily) {
|
||||
ancestors.push_back({*parentNode, childIndex});
|
||||
parentNode = childNode.get();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
childIndex++;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
ancestors.clear();
|
||||
return ancestors;
|
||||
}
|
||||
}
|
||||
|
||||
return ancestors;
|
||||
}
|
||||
|
||||
bool ShadowNode::constructAncestorPath(
|
||||
const ShadowNode &ancestorShadowNode,
|
||||
std::vector<std::reference_wrapper<const ShadowNode>> &ancestors) const {
|
||||
|
||||
@@ -45,6 +45,11 @@ class ShadowNode : public virtual Sealable,
|
||||
public:
|
||||
using Shared = std::shared_ptr<const ShadowNode>;
|
||||
using Weak = std::weak_ptr<const ShadowNode>;
|
||||
using AncestorList = better::small_vector<
|
||||
std::pair<
|
||||
std::reference_wrapper<ShadowNode const> /* parentNode */,
|
||||
int /* childIndex */>,
|
||||
64>;
|
||||
|
||||
static SharedShadowNodeSharedList emptySharedShadowNodeSharedList();
|
||||
|
||||
@@ -138,6 +143,7 @@ class ShadowNode : public virtual Sealable,
|
||||
void setMounted(bool mounted) const;
|
||||
|
||||
/*
|
||||
* Deprecated. Use `getAncestors` instead.
|
||||
* Forms a list of all ancestors of the node relative to the given ancestor.
|
||||
* The list starts from the parent node and ends with the given ancestor node.
|
||||
* Returns `true` if successful, `false` otherwise.
|
||||
@@ -149,9 +155,19 @@ class ShadowNode : public virtual Sealable,
|
||||
* `childIndex` and `nodeId` tracking.
|
||||
*/
|
||||
bool constructAncestorPath(
|
||||
const ShadowNode &rootShadowNode,
|
||||
const ShadowNode &ancestorShadowNode,
|
||||
std::vector<std::reference_wrapper<const ShadowNode>> &ancestors) const;
|
||||
|
||||
/*
|
||||
* Returns a list of all ancestors of the node relative to the given ancestor.
|
||||
* The list starts from the given ancestor node and ends with the parent node
|
||||
* of `this` node. The elements of the list have a reference to some parent
|
||||
* node and an index of the child of the parent node.
|
||||
* Can be called from any thread.
|
||||
* The theoretical complexity of the algorithm is `O(ln(n))`. Use it wisely.
|
||||
*/
|
||||
AncestorList getAncestors(ShadowNode const &ancestorShadowNode) const;
|
||||
|
||||
#pragma mark - DebugStringConvertible
|
||||
|
||||
#if RN_DEBUG_STRING_CONVERTIBLE
|
||||
|
||||
Reference in New Issue
Block a user