/
githubmr
/
facebook-react-native
Обзор
Документация
Войти
/
githubmr
/
facebook-react-native
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
main
packages/react-native/ReactCommon/react/renderer/observers/mutation/MutationObserver.cpp
186 строк
6 KB
generatedunixname89002005287564
Fix CQS signal modernize-use-designated-initializers in xplat/js/react-native-github/packages [A] (#54002)
01 окт 2025, 14:10
01 окт 2025, 14:10
33bc271
Код
Авторство
О чём код?
/* * 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 = mutationObserverId_, .targetShadowNode = oldNode, .addedShadowNodes = std::move(addedNodes), .removedShadowNodes = std::move(removedNodes)}); } } } // namespace facebook::react