PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/react-native/ReactCommon/react/renderer/observers/mutation
Просмотр файла: MutationObserver.cpp
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "MutationObserver.h"
#include <react/renderer/core/ShadowNodeTraits.h>
#include <react/renderer/uimanager/primitives.h>
namespace facebook::react {
MutationObserver::MutationObserver(MutationObserverId mutationObserverId)
: mutationObserverId_(mutationObserverId) {}
void MutationObserver::observe(
std::shared_ptr<const ShadowNodeFamily> targetShadowNodeFamily,
bool observeSubtree) {
auto& list = observeSubtree ? deeplyObservedShadowNodeFamilies_
: shallowlyObservedShadowNodeFamilies_;
auto& otherList = observeSubtree ? shallowlyObservedShadowNodeFamilies_
: deeplyObservedShadowNodeFamilies_;
if (std::find(list.begin(), list.end(), targetShadowNodeFamily) !=
list.end()) {
// It is already being observed correctly.
return;
}
auto it =
std::find(otherList.begin(), otherList.end(), targetShadowNodeFamily);
if (it != otherList.end()) {
// It is being observed incorrectly.
otherList.erase(it);
}
list.push_back(targetShadowNodeFamily);
}
static std::shared_ptr<const ShadowNode> getShadowNodeInTree(
const ShadowNodeFamily& shadowNodeFamily,
const ShadowNode& newTree) {
auto ancestors = shadowNodeFamily.getAncestors(newTree);
if (ancestors.empty()) {
return nullptr;
}
auto pair = ancestors.rbegin();
return pair->first.get().getChildren().at(pair->second);
}
static std::shared_ptr<const ShadowNode> findNodeOfSameFamily(
const std::vector<std::shared_ptr<const ShadowNode>>& list,
const ShadowNode& node) {
for (auto& current : list) {
if (ShadowNode::sameFamily(node, *current)) {
return current;
}
}
return nullptr;
}
void MutationObserver::recordMutations(
const RootShadowNode& oldRootShadowNode,
const RootShadowNode& newRootShadowNode,
std::vector<MutationRecord>& recordedMutations) const {
// This tracks the nodes that have already been processed by this observer,
// so we avoid unnecessary work and duplicated entries.
SetOfShadowNodePointers processedNodes;
// We go over the deeply observed nodes first to avoid skipping nodes that
// have only been checked shallowly.
for (const auto& targetShadowNodeFamily : deeplyObservedShadowNodeFamilies_) {
recordMutationsInTarget(
*targetShadowNodeFamily,
oldRootShadowNode,
newRootShadowNode,
true,
recordedMutations,
processedNodes);
}
for (const auto& targetShadowNodeFamily :
shallowlyObservedShadowNodeFamilies_) {
recordMutationsInTarget(
*targetShadowNodeFamily,
oldRootShadowNode,
newRootShadowNode,
false,
recordedMutations,
processedNodes);
}
}
void MutationObserver::recordMutationsInTarget(
const ShadowNodeFamily& targetShadowNodeFamily,
const RootShadowNode& oldRootShadowNode,
const RootShadowNode& newRootShadowNode,
bool observeSubtree,
std::vector<MutationRecord>& recordedMutations,
SetOfShadowNodePointers& processedNodes) const {
// If the node isnt't present in the old tree, it's either:
// - A new node. In that case, the mutation happened in its parent, not in the
// node itself.
// - A non-existent node. In that case, there are no new mutations.
auto oldTargetShadowNode =
getShadowNodeInTree(targetShadowNodeFamily, oldRootShadowNode);
if (!oldTargetShadowNode) {
return;
}
// If the node isn't present in the new tree (and we didn't return in the
// previous check), it means the whole node was removed. In that case we don't
// record any mutations in the node itself (maybe in its parent if there are
// other observers set up).
auto newTargetShadowNode =
getShadowNodeInTree(targetShadowNodeFamily, newRootShadowNode);
if (!newTargetShadowNode) {
return;
}
recordMutationsInSubtrees(
oldTargetShadowNode,
newTargetShadowNode,
observeSubtree,
recordedMutations,
processedNodes);
}
void MutationObserver::recordMutationsInSubtrees(
const std::shared_ptr<const ShadowNode>& oldNode,
const std::shared_ptr<const ShadowNode>& newNode,
bool observeSubtree,
std::vector<MutationRecord>& recordedMutations,
SetOfShadowNodePointers& processedNodes) const {
bool isSameNode = oldNode.get() == newNode.get();
// If the nodes are referentially equal, their children are also the same.
if (isSameNode ||
processedNodes.find(oldNode.get()) != processedNodes.end()) {
return;
}
processedNodes.insert(oldNode.get());
auto oldChildren = oldNode->getChildren();
auto newChildren = newNode->getChildren();
std::vector<std::shared_ptr<const ShadowNode>> addedNodes;
std::vector<std::shared_ptr<const ShadowNode>> removedNodes;
// Check for removed nodes (and equal nodes for further inspection)
for (auto& oldChild : oldChildren) {
auto newChild = findNodeOfSameFamily(newChildren, *oldChild);
if (!newChild) {
removedNodes.push_back(oldChild);
} else if (observeSubtree) {
// Nodes are present in both tress. If `subtree` is set to true,
// we continue checking their children.
recordMutationsInSubtrees(
oldChild,
newChild,
observeSubtree,
recordedMutations,
processedNodes);
}
}
// Check for added nodes
for (auto& newChild : newChildren) {
auto oldChild = findNodeOfSameFamily(oldChildren, *newChild);
if (!oldChild) {
addedNodes.push_back(newChild);
}
}
if (!addedNodes.empty() || !removedNodes.empty()) {
recordedMutations.emplace_back(MutationRecord{
mutationObserverId_,
oldNode,
std::move(addedNodes),
std::move(removedNodes)});
}
}
} // namespace facebook::react
Выполнить команду
Для локальной разработки. Не используйте в интернете!