Files
react-native/ReactCommon/fabric/uimanager/UIManager.cpp
Kevin Gozali 65033d7078 Fabric: preserve original props when using fallback component
Summary: This fixes a minor bug where the original props (like for styling) got dropped when the system falls back to UnimplementedView.

Reviewed By: mdvacca

Differential Revision: D14898906

fbshipit-source-id: 4a07952ceac66e491a5c0bc1ffd99f21438cda31
2019-04-11 14:23:13 -07:00

198 lines
6.4 KiB
C++

// Copyright 2004-present Facebook. All Rights Reserved.
#include "UIManager.h"
#include <react/core/ShadowNodeFragment.h>
#include <react/debug/SystraceSection.h>
#include <react/utils/TimeUtils.h>
namespace facebook {
namespace react {
SharedShadowNode UIManager::createNode(
Tag tag,
const ComponentName &name,
SurfaceId surfaceId,
const RawProps &rawProps,
SharedEventTarget eventTarget) const {
SystraceSection s("UIManager::createNode");
auto &componentDescriptor = componentDescriptorRegistry_->at(name);
auto fallbackDescriptor =
componentDescriptorRegistry_->getFallbackComponentDescriptor();
const auto &props = componentDescriptor.cloneProps(nullptr, rawProps);
const auto &state = componentDescriptor.createInitialState(props);
auto shadowNode = componentDescriptor.createShadowNode({
/* .tag = */ tag,
/* .rootTag = */ surfaceId,
/* .props = */
fallbackDescriptor != nullptr &&
fallbackDescriptor->getComponentHandle() ==
componentDescriptor.getComponentHandle()
? componentDescriptor.cloneProps(
props, RawProps(folly::dynamic::object("name", name)))
: props,
/* .eventEmitter = */
componentDescriptor.createEventEmitter(std::move(eventTarget), tag),
/* .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(),
/* .rootTag = */ 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, getTime());
}
}
void UIManager::setNativeProps(
const SharedShadowNode &shadowNode,
const RawProps &rawProps) const {
SystraceSection s("UIManager::setNativeProps");
long startCommitTime = getTime();
auto &componentDescriptor = shadowNode->getComponentDescriptor();
auto props = componentDescriptor.cloneProps(shadowNode->getProps(), rawProps);
auto newShadowNode = shadowNode->clone({
/* .tag = */ ShadowNodeFragment::tagPlaceholder(),
/* .rootTag = */ ShadowNodeFragment::surfaceIdPlaceholder(),
/* .props = */ props,
});
shadowTreeRegistry_->visit(
shadowNode->getSurfaceId(), [&](const ShadowTree &shadowTree) {
shadowTree.tryCommit(
[&](const SharedRootShadowNode &oldRootShadowNode) {
return oldRootShadowNode->clone(shadowNode, newShadowNode);
},
startCommitTime);
});
}
LayoutMetrics UIManager::getRelativeLayoutMetrics(
const ShadowNode &shadowNode,
const ShadowNode *ancestorShadowNode) const {
SystraceSection s("UIManager::getRelativeLayoutMetrics");
long startCommitTime = getTime();
if (!ancestorShadowNode) {
shadowTreeRegistry_->visit(
shadowNode.getSurfaceId(), [&](const ShadowTree &shadowTree) {
shadowTree.tryCommit(
[&](const SharedRootShadowNode &oldRootShadowNode) {
ancestorShadowNode = oldRootShadowNode.get();
return nullptr;
},
startCommitTime);
});
}
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 {
long startCommitTime = getTime();
auto &componentDescriptor = shadowNode->getComponentDescriptor();
auto state =
componentDescriptor.createState(shadowNode->getState(), rawStateData);
auto newShadowNode = shadowNode->clone({
/* .tag = */ ShadowNodeFragment::tagPlaceholder(),
/* .rootTag = */ 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);
},
startCommitTime);
});
}
void UIManager::setShadowTreeRegistry(ShadowTreeRegistry *shadowTreeRegistry) {
shadowTreeRegistry_ = shadowTreeRegistry;
}
void UIManager::setComponentDescriptorRegistry(
const SharedComponentDescriptorRegistry &componentDescriptorRegistry) {
componentDescriptorRegistry_ = componentDescriptorRegistry;
}
void UIManager::setDelegate(UIManagerDelegate *delegate) {
delegate_ = delegate;
}
UIManagerDelegate *UIManager::getDelegate() {
return delegate_;
}
} // namespace react
} // namespace facebook