diff --git a/ReactCommon/fabric/uimanager/UIManager.cpp b/ReactCommon/fabric/uimanager/UIManager.cpp index ee0e812eb5a..d0ed76dbd73 100644 --- a/ReactCommon/fabric/uimanager/UIManager.cpp +++ b/ReactCommon/fabric/uimanager/UIManager.cpp @@ -191,6 +191,47 @@ void UIManager::dispatchCommand( } } +static ShadowNode::Shared findShadowNodeByTagRecursively( + ShadowNode::Shared const &parentShadowNode, + Tag tag) { + if (parentShadowNode->getTag() == tag) { + return parentShadowNode; + } + + for (ShadowNode::Shared const &shadowNode : parentShadowNode->getChildren()) { + auto result = findShadowNodeByTagRecursively(shadowNode, tag); + if (result) { + return result; + } + } + + return nullptr; +} + +ShadowNode::Shared UIManager::findShadowNodeByTag_DEPRECATED(Tag tag) const { + auto shadowNode = ShadowNode::Shared{}; + + shadowTreeRegistry_.enumerate([&](ShadowTree const &shadowTree, bool &stop) { + auto rootShadowNode = ShadowNode::Shared{}; + // This is tricky. + // The public interface of `ShadowTree` discourages accessing a stored + // pointer to a root node because of the possible data race. + // To work around this, we ask for a commit and immediately cancel it + // returning `nullptr` instead of a new shadow tree. + shadowTree.tryCommit([&](SharedRootShadowNode const &oldRootShadowNode) { + rootShadowNode = oldRootShadowNode; + return nullptr; + }); + + shadowNode = findShadowNodeByTagRecursively(rootShadowNode, tag); + if (shadowNode) { + stop = true; + } + }); + + return shadowNode; +} + void UIManager::setComponentDescriptorRegistry( const SharedComponentDescriptorRegistry &componentDescriptorRegistry) { componentDescriptorRegistry_ = componentDescriptorRegistry; diff --git a/ReactCommon/fabric/uimanager/UIManager.h b/ReactCommon/fabric/uimanager/UIManager.h index 5ba848f87ce..781ac4bd1a3 100644 --- a/ReactCommon/fabric/uimanager/UIManager.h +++ b/ReactCommon/fabric/uimanager/UIManager.h @@ -97,6 +97,14 @@ class UIManager { std::string const &commandName, folly::dynamic const args) const; + /* + * Iterates over all shadow nodes which are parts of all registered surfaces + * and find the one that has given `tag`. Returns `nullptr` if the node wasn't + * found. This is a temporary workaround that should not be used in any core + * functionality. + */ + ShadowNode::Shared findShadowNodeByTag_DEPRECATED(Tag tag) const; + ShadowTreeRegistry const &getShadowTreeRegistry() const; SharedComponentDescriptorRegistry componentDescriptorRegistry_;