#include #include #include #include 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 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>>( 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( cloneShadowTreeWithNewPropsRecursive(oldRootNode, childrenMap, propsMap)); } } // namespace reanimated