103 lines
3.0 KiB
C++
103 lines
3.0 KiB
C++
#include <reanimated/Fabric/ShadowTreeCloner.h>
|
|
#include <reanimated/Tools/ReanimatedSystraceSection.h>
|
|
|
|
#include <ranges>
|
|
#include <utility>
|
|
|
|
namespace reanimated {
|
|
|
|
Props::Shared mergeProps(
|
|
const ShadowNode &shadowNode,
|
|
const PropsMap &propsMap,
|
|
const ShadowNodeFamily &family) {
|
|
ReanimatedSystraceSection s("ShadowTreeCloner::mergeProps");
|
|
|
|
const auto it = propsMap.find(&family);
|
|
|
|
if (it == propsMap.end()) {
|
|
return ShadowNodeFragment::propsPlaceholder();
|
|
}
|
|
|
|
PropsParserContext propsParserContext{
|
|
shadowNode.getSurfaceId(), *shadowNode.getContextContainer()};
|
|
const auto &propsVector = it->second;
|
|
auto newProps = shadowNode.getProps();
|
|
|
|
#ifdef ANDROID
|
|
if (propsVector.size() > 1) {
|
|
folly::dynamic newPropsDynamic = folly::dynamic::object;
|
|
for (const auto &props : propsVector) {
|
|
newPropsDynamic = folly::dynamic::merge(
|
|
props.operator folly::dynamic(), newPropsDynamic);
|
|
}
|
|
return shadowNode.getComponentDescriptor().cloneProps(
|
|
propsParserContext, newProps, RawProps(newPropsDynamic));
|
|
}
|
|
#endif
|
|
|
|
for (const auto &props : propsVector) {
|
|
newProps = shadowNode.getComponentDescriptor().cloneProps(
|
|
propsParserContext, newProps, RawProps(props));
|
|
}
|
|
|
|
return newProps;
|
|
}
|
|
|
|
std::shared_ptr<ShadowNode> cloneShadowTreeWithNewPropsRecursive(
|
|
const ShadowNode &shadowNode,
|
|
const ChildrenMap &childrenMap,
|
|
const PropsMap &propsMap) {
|
|
const auto family = &shadowNode.getFamily();
|
|
const auto affectedChildrenIt = childrenMap.find(family);
|
|
auto children = shadowNode.getChildren();
|
|
|
|
if (affectedChildrenIt != childrenMap.end()) {
|
|
for (const auto index : affectedChildrenIt->second) {
|
|
children[index] = cloneShadowTreeWithNewPropsRecursive(
|
|
*children[index], childrenMap, propsMap);
|
|
}
|
|
}
|
|
|
|
return shadowNode.clone(
|
|
{mergeProps(shadowNode, propsMap, *family),
|
|
std::make_shared<std::vector<std::shared_ptr<const ShadowNode>>>(
|
|
children),
|
|
shadowNode.getState(),
|
|
false});
|
|
}
|
|
|
|
RootShadowNode::Unshared cloneShadowTreeWithNewProps(
|
|
const RootShadowNode &oldRootNode,
|
|
const PropsMap &propsMap) {
|
|
ReanimatedSystraceSection s("ShadowTreeCloner::cloneShadowTreeWithNewProps");
|
|
|
|
ChildrenMap childrenMap;
|
|
|
|
{
|
|
ReanimatedSystraceSection s("ShadowTreeCloner::prepareChildrenMap");
|
|
|
|
for (auto &[family, _] : propsMap) {
|
|
const auto ancestors = family->getAncestors(oldRootNode);
|
|
|
|
for (const auto &[parentNode, index] :
|
|
std::ranges::reverse_view(ancestors)) {
|
|
const auto parentFamily = &parentNode.get().getFamily();
|
|
auto &affectedChildren = childrenMap[parentFamily];
|
|
|
|
if (affectedChildren.contains(index)) {
|
|
continue;
|
|
}
|
|
|
|
affectedChildren.insert(index);
|
|
}
|
|
}
|
|
}
|
|
|
|
// This cast is safe, because this function returns a clone
|
|
// of the oldRootNode, which is an instance of RootShadowNode
|
|
return std::static_pointer_cast<RootShadowNode>(
|
|
cloneShadowTreeWithNewPropsRecursive(oldRootNode, childrenMap, propsMap));
|
|
}
|
|
|
|
} // namespace reanimated
|