Skip to content

Commit

Permalink
Introduce FabricUIManager.findShadowNodeByTag_DEPRECATED
Browse files Browse the repository at this point in the history
Summary:
changelog: [internal]

Add findShadowNodeByTag_DEPRECATED` to Fabric's UIManager.
This API makes it possible to get ShadowNode reference for given native tag.
We will leverage this API to make UIManager.measure* calls backwards compatible in the new architecture.

Reviewed By: yungsters

Differential Revision: D41550734

fbshipit-source-id: a45b6a76634d034eac70603bad8ac60f9135ff24
  • Loading branch information
sammy-SC authored and facebook-github-bot committed Dec 6, 2022
1 parent 913ebd2 commit 86786f1
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 5 deletions.
9 changes: 7 additions & 2 deletions ReactCommon/react/renderer/mounting/ShadowTreeRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,15 @@ bool ShadowTreeRegistry::visit(
}

void ShadowTreeRegistry::enumerate(
std::function<void(const ShadowTree &shadowTree)> const &callback) const {
std::function<void(const ShadowTree &shadowTree, bool &stop)> const
&callback) const {
std::shared_lock<butter::shared_mutex> lock(mutex_);
auto stop = false;
for (auto const &pair : registry_) {
callback(*pair.second);
callback(*pair.second, stop);
if (stop) {
return;
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion ReactCommon/react/renderer/mounting/ShadowTreeRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,12 @@ class ShadowTreeRegistry final {

/*
* Enumerates all stored shadow trees.
* Set `stop` to `true` to interrupt the enumeration.
* Can be called from any thread.
*/
void enumerate(
std::function<void(const ShadowTree &shadowTree)> const &callback) const;
std::function<void(const ShadowTree &shadowTree, bool &stop)> const
&callback) const;

private:
mutable butter::shared_mutex mutex_;
Expand Down
2 changes: 1 addition & 1 deletion ReactCommon/react/renderer/scheduler/Scheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ Scheduler::~Scheduler() {
// Then, let's verify that the requirement was satisfied.
auto surfaceIds = std::vector<SurfaceId>{};
uiManager_->getShadowTreeRegistry().enumerate(
[&surfaceIds](ShadowTree const &shadowTree) {
[&surfaceIds](ShadowTree const &shadowTree, bool &) {
surfaceIds.push_back(shadowTree.getSurfaceId());
});

Expand Down
51 changes: 50 additions & 1 deletion ReactCommon/react/renderer/uimanager/UIManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,55 @@ void UIManager::configureNextLayoutAnimation(
}
}

static ShadowNode::Shared findShadowNodeByTagRecursively(
ShadowNode::Shared 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) {
RootShadowNode const *rootShadowNode;
// 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.
// We don't want to add a way to access a stored pointer to a root node
// because this `findShadowNodeByTag` is deprecated. It is only added
// to make migration to the new architecture easier.
shadowTree.tryCommit([&](RootShadowNode const &oldRootShadowNode) {
rootShadowNode = &oldRootShadowNode;
return nullptr;
});

if (rootShadowNode != nullptr) {
auto const &children = rootShadowNode->getChildren();
if (!children.empty()) {
auto const &child = children.front();
shadowNode = findShadowNodeByTagRecursively(child, tag);
if (shadowNode) {
stop = true;
}
}
}
});

return shadowNode;
}

void UIManager::setComponentDescriptorRegistry(
const SharedComponentDescriptorRegistry &componentDescriptorRegistry) {
componentDescriptorRegistry_ = componentDescriptorRegistry;
Expand Down Expand Up @@ -440,7 +489,7 @@ void UIManager::stopSurfaceForAnimationDelegate(SurfaceId surfaceId) const {
void UIManager::animationTick() const {
if (animationDelegate_ != nullptr &&
animationDelegate_->shouldAnimateFrame()) {
shadowTreeRegistry_.enumerate([](ShadowTree const &shadowTree) {
shadowTreeRegistry_.enumerate([](ShadowTree const &shadowTree, bool &) {
shadowTree.notifyDelegatesOfUpdates();
});
}
Expand Down
8 changes: 8 additions & 0 deletions ReactCommon/react/renderer/uimanager/UIManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,14 @@ class UIManager final : public ShadowTreeDelegate {
const ShadowNode::Shared &shadowNode,
std::string const &eventType);

/*
* 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;

private:
Expand Down
21 changes: 21 additions & 0 deletions ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,27 @@ jsi::Value UIManagerBinding::get(
return {serialize(ReactEventPriority::Discrete)};
}

if (methodName == "findShadowNodeByTag_DEPRECATED") {
return jsi::Function::createFromHostFunction(
runtime,
name,
1,
[uiManager](
jsi::Runtime &runtime,
jsi::Value const &,
jsi::Value const *arguments,
size_t) -> jsi::Value {
auto shadowNode = uiManager->findShadowNodeByTag_DEPRECATED(
tagFromValue(arguments[0]));

if (!shadowNode) {
return jsi::Value::null();
}

return valueFromShadowNode(runtime, shadowNode);
});
}

return jsi::Value::undefined();
}

Expand Down

0 comments on commit 86786f1

Please sign in to comment.