mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
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
264 lines
8.3 KiB
C++
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
|