Files
react-native/ReactCommon/fabric/uimanager/UIManager.cpp
T
Valentin Shergin 79ef5f9b0f Fabric: UIManager::findShadowNodeByTag_DEPRECATED
Summary: The mehtod implements the core functionality of finding a shadow node by given tag.

Reviewed By: zackargyle, JoshuaGross, mdvacca

Differential Revision: D17175955

fbshipit-source-id: 5cfbb80b2d4e54a33ca9c20a21988df4de54c800
2019-09-04 23:16:56 -07:00

264 lines
8.3 KiB
C++

// Copyright 2004-present Facebook. All Rights Reserved.
#include "UIManager.h"
#include <react/core/ShadowNodeFragment.h>
#include <react/debug/SystraceSection.h>
namespace facebook {
namespace react {
SharedShadowNode UIManager::createNode(
Tag tag,
std::string const &name,
SurfaceId surfaceId,
const RawProps &rawProps,
SharedEventTarget eventTarget) const {
SystraceSection s("UIManager::createNode");
auto &componentDescriptor = componentDescriptorRegistry_->at(name);
auto fallbackDescriptor =
componentDescriptorRegistry_->getFallbackComponentDescriptor();
auto const eventEmitter =
componentDescriptor.createEventEmitter(std::move(eventTarget), tag);
auto const props = componentDescriptor.cloneProps(nullptr, rawProps);
auto const state = componentDescriptor.createInitialState(
ShadowNodeFragment{tag, surfaceId, props, eventEmitter});
auto shadowNode = componentDescriptor.createShadowNode({
/* .tag = */ tag,
/* .surfaceId = */ surfaceId,
/* .props = */
fallbackDescriptor != nullptr &&
fallbackDescriptor->getComponentHandle() ==
componentDescriptor.getComponentHandle()
? componentDescriptor.cloneProps(
props, RawProps(folly::dynamic::object("name", name)))
: props,
/* .eventEmitter = */ eventEmitter,
/* .children = */ ShadowNodeFragment::childrenPlaceholder(),
/* .localData = */ ShadowNodeFragment::localDataPlaceholder(),
/* .state = */ state,
});
if (delegate_) {
delegate_->uiManagerDidCreateShadowNode(shadowNode);
}
return shadowNode;
}
SharedShadowNode UIManager::cloneNode(
const SharedShadowNode &shadowNode,
const SharedShadowNodeSharedList &children,
const RawProps *rawProps) const {
SystraceSection s("UIManager::cloneNode");
auto &componentDescriptor = shadowNode->getComponentDescriptor();
auto clonedShadowNode = componentDescriptor.cloneShadowNode(
*shadowNode,
{
/* .tag = */ ShadowNodeFragment::tagPlaceholder(),
/* .surfaceId = */ ShadowNodeFragment::surfaceIdPlaceholder(),
/* .props = */
rawProps ? componentDescriptor.cloneProps(
shadowNode->getProps(), *rawProps)
: ShadowNodeFragment::propsPlaceholder(),
/* .eventEmitter = */ ShadowNodeFragment::eventEmitterPlaceholder(),
/* .children = */ children,
});
return clonedShadowNode;
}
void UIManager::appendChild(
const SharedShadowNode &parentShadowNode,
const SharedShadowNode &childShadowNode) const {
SystraceSection s("UIManager::appendChild");
auto &componentDescriptor = parentShadowNode->getComponentDescriptor();
componentDescriptor.appendChild(parentShadowNode, childShadowNode);
}
void UIManager::completeSurface(
SurfaceId surfaceId,
const SharedShadowNodeUnsharedList &rootChildren) const {
SystraceSection s("UIManager::completeSurface");
if (delegate_) {
delegate_->uiManagerDidFinishTransaction(surfaceId, rootChildren);
}
}
void UIManager::setJSResponder(
const SharedShadowNode &shadowNode,
const bool blockNativeResponder) const {
if (delegate_) {
delegate_->uiManagerDidSetJSResponder(
shadowNode->getSurfaceId(), shadowNode, blockNativeResponder);
}
}
void UIManager::clearJSResponder() const {
if (delegate_) {
delegate_->uiManagerDidClearJSResponder();
}
}
void UIManager::setNativeProps(
const SharedShadowNode &shadowNode,
const RawProps &rawProps) const {
SystraceSection s("UIManager::setNativeProps");
auto &componentDescriptor = shadowNode->getComponentDescriptor();
auto props = componentDescriptor.cloneProps(shadowNode->getProps(), rawProps);
auto newShadowNode = shadowNode->clone({
/* .tag = */ ShadowNodeFragment::tagPlaceholder(),
/* .surfaceId = */ ShadowNodeFragment::surfaceIdPlaceholder(),
/* .props = */ props,
});
shadowTreeRegistry_.visit(
shadowNode->getSurfaceId(), [&](const ShadowTree &shadowTree) {
shadowTree.tryCommit(
[&](const SharedRootShadowNode &oldRootShadowNode) {
return oldRootShadowNode->clone(shadowNode, newShadowNode);
});
});
}
LayoutMetrics UIManager::getRelativeLayoutMetrics(
const ShadowNode &shadowNode,
const ShadowNode *ancestorShadowNode) const {
SystraceSection s("UIManager::getRelativeLayoutMetrics");
if (!ancestorShadowNode) {
shadowTreeRegistry_.visit(
shadowNode.getSurfaceId(), [&](const ShadowTree &shadowTree) {
shadowTree.tryCommit(
[&](const SharedRootShadowNode &oldRootShadowNode) {
ancestorShadowNode = oldRootShadowNode.get();
return nullptr;
});
});
}
auto layoutableShadowNode =
dynamic_cast<const LayoutableShadowNode *>(&shadowNode);
auto layoutableAncestorShadowNode =
dynamic_cast<const LayoutableShadowNode *>(ancestorShadowNode);
if (!layoutableShadowNode || !layoutableAncestorShadowNode) {
return EmptyLayoutMetrics;
}
return layoutableShadowNode->getRelativeLayoutMetrics(
*layoutableAncestorShadowNode);
}
void UIManager::updateState(
const SharedShadowNode &shadowNode,
const StateData::Shared &rawStateData) const {
auto &componentDescriptor = shadowNode->getComponentDescriptor();
auto state =
componentDescriptor.createState(shadowNode->getState(), rawStateData);
auto newShadowNode = shadowNode->clone({
/* .tag = */ ShadowNodeFragment::tagPlaceholder(),
/* .surfaceId = */ ShadowNodeFragment::surfaceIdPlaceholder(),
/* .props = */ ShadowNodeFragment::propsPlaceholder(),
/* .eventEmitter = */ ShadowNodeFragment::eventEmitterPlaceholder(),
/* .children = */ ShadowNodeFragment::childrenPlaceholder(),
/* .localData = */ ShadowNodeFragment::localDataPlaceholder(),
/* .state = */ state,
});
shadowTreeRegistry_.visit(
shadowNode->getSurfaceId(), [&](const ShadowTree &shadowTree) {
shadowTree.tryCommit(
[&](const SharedRootShadowNode &oldRootShadowNode) {
return oldRootShadowNode->clone(shadowNode, newShadowNode);
});
});
}
void UIManager::dispatchCommand(
const SharedShadowNode &shadowNode,
std::string const &commandName,
folly::dynamic const args) const {
if (delegate_) {
delegate_->uiManagerDidDispatchCommand(shadowNode, commandName, args);
}
}
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;
}
void UIManager::setDelegate(UIManagerDelegate *delegate) {
delegate_ = delegate;
}
UIManagerDelegate *UIManager::getDelegate() {
return delegate_;
}
void UIManager::visitBinding(
std::function<void(UIManagerBinding const &uiManagerBinding)> callback)
const {
if (!uiManagerBinding_) {
return;
}
callback(*uiManagerBinding_);
}
ShadowTreeRegistry const &UIManager::getShadowTreeRegistry() const {
return shadowTreeRegistry_;
}
} // namespace react
} // namespace facebook