#include namespace reanimated { std::lock_guard UpdatesRegistry::lock() const { return std::lock_guard{mutex_}; } bool UpdatesRegistry::isEmpty() const { return updatesRegistry_.empty(); } folly::dynamic UpdatesRegistry::get(const Tag tag) const { std::lock_guard lock{mutex_}; auto it = updatesRegistry_.find(tag); if (it == updatesRegistry_.cend()) { return nullptr; } return it->second.second; } void UpdatesRegistry::flushUpdates(UpdatesBatch &updatesBatch) { auto copiedUpdatesBatch = std::move(updatesBatch_); updatesBatch_.clear(); // Store all updates in the registry for later use in the commit hook flushUpdatesToRegistry(copiedUpdatesBatch); // Flush the updates to the updatesBatch used to apply current changes for (auto &[shadowNode, props] : copiedUpdatesBatch) { updatesBatch.emplace_back(shadowNode, std::move(props)); } } UpdatesBatch UpdatesRegistry::getPendingUpdates() { auto lock = std::lock_guard{mutex_}; flushUpdatesToRegistry(updatesBatch_); UpdatesBatch updatesBatch; for (const auto &[tag, pair] : updatesRegistry_) { const auto &[shadowNode, props] = pair; updatesBatch.emplace_back(shadowNode, props); } return updatesBatch; } void UpdatesRegistry::collectProps(PropsMap &propsMap) { std::lock_guard lock{mutex_}; auto copiedRegistry = updatesRegistry_; for (const auto &[tag, pair] : copiedRegistry) { const auto &[shadowNode, props] = pair; auto &family = shadowNode->getFamily(); auto it = propsMap.find(&family); if (it == propsMap.cend()) { auto propsVector = std::vector{}; propsVector.emplace_back(RawProps(props)); propsMap.emplace(&family, propsVector); } else { it->second.push_back(RawProps(props)); } } } void UpdatesRegistry::addUpdatesToBatch( const std::shared_ptr &shadowNode, const folly::dynamic &props) { updatesBatch_.emplace_back(shadowNode, props); } void UpdatesRegistry::setInUpdatesRegistry( const std::shared_ptr &shadowNode, const folly::dynamic &props) { const auto tag = shadowNode->getTag(); #ifdef ANDROID updatePropsToRevert(tag, &props); #endif updatesRegistry_[tag] = std::make_pair(shadowNode, props); } folly::dynamic UpdatesRegistry::getUpdatesFromRegistry(const Tag tag) const { auto it = updatesRegistry_.find(tag); if (it == updatesRegistry_.cend()) { return folly::dynamic(); } return it->second.second; } void UpdatesRegistry::removeFromUpdatesRegistry(const Tag tag) { #ifdef ANDROID updatePropsToRevert(tag); #endif updatesRegistry_.erase(tag); } void UpdatesRegistry::flushUpdatesToRegistry(const UpdatesBatch &updatesBatch) { for (auto &[shadowNode, props] : updatesBatch) { const auto tag = shadowNode->getTag(); auto it = updatesRegistry_.find(tag); if (it == updatesRegistry_.cend()) { updatesRegistry_[tag] = std::make_pair(shadowNode, props); } else { it->second.second.update(props); } } } #ifdef ANDROID bool UpdatesRegistry::hasPropsToRevert() const { return !propsToRevertMap_.empty(); } void UpdatesRegistry::collectPropsToRevert(PropsToRevertMap &propsToRevertMap) { std::lock_guard lock{mutex_}; for (const auto &[tag, pair] : propsToRevertMap_) { const auto &[shadowNode, props] = pair; const auto it = propsToRevertMap.find(tag); if (it == propsToRevertMap.end()) { propsToRevertMap[tag] = {shadowNode, props}; } else { it->second.props.insert(props.begin(), props.end()); } } propsToRevertMap_.clear(); } void UpdatesRegistry::updatePropsToRevert( const Tag tag, const folly::dynamic *newProps) { auto it = updatesRegistry_.find(tag); if (it == updatesRegistry_.end()) { return; } const auto &shadowNode = it->second.first; const auto ®istryProps = it->second.second; if (propsToRevertMap_.find(tag) == propsToRevertMap_.end()) { propsToRevertMap_[tag] = {shadowNode, std::unordered_set()}; } if (newProps == nullptr) { // If newProps is not provided, revert all props from registry for (const auto &propName : registryProps.keys()) { propsToRevertMap_[tag].props.emplace(propName.asString()); } } else { // If newProps is provided, revert only props that are in registry but not // in newProps for (const auto &propName : registryProps.keys()) { if (newProps->find(propName) == newProps->items().end()) { propsToRevertMap_[tag].props.emplace(propName.asString()); } } } if (propsToRevertMap_[tag].props.empty()) { propsToRevertMap_.erase(tag); } } #endif } // namespace reanimated