From 1adf40b7f84a1d15b6823e8973dab1b4dc9ea0fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Wi=C5=9Bniewski?= Date: Mon, 16 Mar 2026 15:19:29 +0100 Subject: [PATCH 1/9] Change the script --- packages/react-native-reanimated/package.json | 2 +- packages/react-native-worklets/package.json | 2 +- scripts/clang-tidy-lint.sh | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/react-native-reanimated/package.json b/packages/react-native-reanimated/package.json index b79414173ce7..aad6a6cccdec 100644 --- a/packages/react-native-reanimated/package.json +++ b/packages/react-native-reanimated/package.json @@ -14,7 +14,7 @@ "lint:js": "eslint src __tests__ __typetests__ && yarn prettier --check src __tests__ __typetests__", "lint:android": "../../scripts/validate-android.sh && ./android/gradlew -p android spotlessCheck -q && ../../scripts/cpplint.sh android/src && yarn format:android:cpp --dry-run -Werror && yarn lint:cmake", "lint:common": "../../scripts/validate-common.sh && ../../scripts/cpplint.sh Common && yarn format:common --dry-run -Werror", - "lint:clang-tidy": "find Common -iname \"*.h\" -o -iname \"*.cpp\" | xargs ../../scripts/clang-tidy-lint.sh", + "lint:clang-tidy": "../../scripts/clang-tidy-lint.sh \"Common\"", "lint:apple": "../../scripts/validate-apple.sh && yarn format:apple --dry-run -Werror", "lint:cmake": "find ./android -type d \\( -name build -o -name .cxx \\) -prune -o -type f -name 'CMakeLists.txt' -print | xargs ../../scripts/lint-cmake.sh", "format": "yarn format:js && yarn format:apple && yarn format:android && yarn format:common", diff --git a/packages/react-native-worklets/package.json b/packages/react-native-worklets/package.json index 7c3099cb3c84..c010a0125eb1 100644 --- a/packages/react-native-worklets/package.json +++ b/packages/react-native-worklets/package.json @@ -27,7 +27,7 @@ "lint:apple": "../../scripts/validate-apple.sh && yarn format:apple --dry-run -Werror", "lint:common": "../../scripts/validate-common.sh && ../../scripts/cpplint.sh Common && yarn format:common --dry-run -Werror", "lint:cmake": "find ./android -type d \\( -name build -o -name .cxx \\) -prune -o -type f -name 'CMakeLists.txt' -print | xargs ../../scripts/lint-cmake.sh", - "lint:clang-tidy": "find Common -iname \"*.h\" -o -iname \"*.cpp\" | xargs ../../scripts/clang-tidy-lint.sh", + "lint:clang-tidy": "../../scripts/clang-tidy-lint.sh \"Common\"", "lint:js": "eslint src && yarn prettier --check src", "lint:plugin": "yarn workspace babel-plugin-worklets lint", "test": "jest", diff --git a/scripts/clang-tidy-lint.sh b/scripts/clang-tidy-lint.sh index de37686f7ae9..0653258d0d09 100755 --- a/scripts/clang-tidy-lint.sh +++ b/scripts/clang-tidy-lint.sh @@ -1,7 +1,7 @@ #!/bin/bash -if ! which clang-tidy >/dev/null; then - echo "error: clang-tidy not installed, download \ +if ! which run-clang-tidy >/dev/null; then + echo "error: run-clang-tidy not installed, download \ from https://clang.llvm.org/extra/clang-tidy/" 1>&2 exit 1 fi @@ -15,4 +15,4 @@ if [ ! -f "../../compile_commands.json" ]; then ) fi -clang-tidy --quiet "$@" +run-clang-tidy -quiet -p . -header-filter="^.*/$1/.*\.h$" "$1" From b2e1ae8326a0532c30dc90e4f5a8d689987e3a0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Wi=C5=9Bniewski?= Date: Mon, 16 Mar 2026 15:50:12 +0100 Subject: [PATCH 2/9] Lint worklets with clang-tidy --- .../Common/cpp/worklets/SharedItems/Serializable.h | 4 ++-- .../Common/cpp/worklets/Tools/WorkletsJSIUtils.h | 6 +++--- .../cpp/worklets/WorkletRuntime/UIRuntimeDecorator.cpp | 5 +++-- .../Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.h | 3 ++- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/react-native-worklets/Common/cpp/worklets/SharedItems/Serializable.h b/packages/react-native-worklets/Common/cpp/worklets/SharedItems/Serializable.h index 1c20158074ff..a67df49654e4 100644 --- a/packages/react-native-worklets/Common/cpp/worklets/SharedItems/Serializable.h +++ b/packages/react-native-worklets/Common/cpp/worklets/SharedItems/Serializable.h @@ -52,7 +52,7 @@ class RetainingSerializable : virtual public BaseClass { explicit RetainingSerializable(jsi::Runtime &rt, Args &&...args) : BaseClass(rt, std::forward(args)...), primaryRuntime_(&rt) {} - jsi::Value toJSValue(jsi::Runtime &rt) { + jsi::Value toJSValue(jsi::Runtime &rt) override { if (&rt == primaryRuntime_) { // TODO: it is suboptimal to generate new object every time getJS is // called on host runtime – the objects we are generating already exists @@ -74,7 +74,7 @@ class RetainingSerializable : virtual public BaseClass { return BaseClass::toJSValue(rt); } - ~RetainingSerializable() { + ~RetainingSerializable() override { cleanupIfRuntimeExists(secondaryRuntime_, secondaryValue_); } }; diff --git a/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletsJSIUtils.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletsJSIUtils.h index 975819a7e13d..c713bb7a72c3 100644 --- a/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletsJSIUtils.h +++ b/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletsJSIUtils.h @@ -84,7 +84,7 @@ getArgsForFunction(std::function, jsi::Runtime &rt, const jsi::Val // passing `rt` as the first argument template std::tuple getArgsForFunction( - std::function, + const std::function &, jsi::Runtime &rt, const jsi::Value *args, const size_t count) { @@ -116,7 +116,7 @@ inline jsi::Value apply(std::function function, std::tuple -jsi::HostFunctionType createHostFunction(Fun function) { +jsi::HostFunctionType createHostFunction(const Fun &function) { return [function](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args, const size_t count) { auto argz = getArgsForFunction(function, rt, args, count); return apply(function, std::move(argz)); @@ -150,7 +150,7 @@ struct takes_runtime { // and installs it as a global function named `name` // in the `rt` JS runtime template -void installJsiFunction(jsi::Runtime &rt, std::string_view name, std::function function) { +void installJsiFunction(jsi::Runtime &rt, std::string_view name, const std::function &function) { auto clb = createHostFunction(function); auto argsCount = sizeof...(Args) - takes_runtime::value; jsi::Value jsiFunction = diff --git a/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.cpp b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.cpp index 2337198d7de2..f47905bc98e6 100644 --- a/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.cpp +++ b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.cpp @@ -8,12 +8,13 @@ namespace worklets { void UIRuntimeDecorator::decorate( facebook::jsi::Runtime &uiRuntime, - std::function &&requestAnimationFrame) { + const std::function + &requestAnimationFrame) { uiRuntime.global().setProperty(uiRuntime, runtimeKindBindingName, static_cast(RuntimeKind::UI)); uiRuntime.global().setProperty(uiRuntime, "_UI", true); - jsi_utils::installJsiFunction(uiRuntime, "requestAnimationFrame", std::move(requestAnimationFrame)); + jsi_utils::installJsiFunction(uiRuntime, "requestAnimationFrame", requestAnimationFrame); } } // namespace worklets diff --git a/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.h b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.h index 717d6c9af892..55064b5f8c43 100644 --- a/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.h +++ b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.h @@ -8,7 +8,8 @@ class UIRuntimeDecorator { public: static void decorate( facebook::jsi::Runtime &uiRuntime, - std::function &&requestAnimationFrame); + const std::function + &requestAnimationFrame); }; } // namespace worklets From 3a8cf583e3a7688ded85eea28fd1d50477765b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Wi=C5=9Bniewski?= Date: Mon, 16 Mar 2026 16:21:01 +0100 Subject: [PATCH 3/9] Lint reanimated with clang-tidy --- .../CSS/utils/DelayedItemsManager.cpp | 4 +- .../CSS/utils/DelayedItemsManager.h | 4 +- .../LayoutAnimationsProxy_Experimental.cpp | 10 +-- .../LayoutAnimationsProxy_Experimental.h | 2 +- .../LayoutAnimationsProxy_Legacy.cpp | 34 ++++----- .../LayoutAnimationsProxy_Legacy.h | 4 +- .../LayoutAnimations/LayoutAnimationsUtils.h | 6 +- .../LayoutAnimations/SharedTransitions.cpp | 76 ++++++++++--------- .../RuntimeDecorators/UIRuntimeDecorator.cpp | 44 +++++------ .../RuntimeDecorators/UIRuntimeDecorator.h | 20 ++--- .../Common/cpp/reanimated/Tools/ReaJSIUtils.h | 10 +-- 11 files changed, 109 insertions(+), 105 deletions(-) diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.cpp index e989c2b23306..fd65b26bff19 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.cpp @@ -18,7 +18,7 @@ bool DelayedItemComparator::operator()(const DelayedItem &lhs, c } template -void DelayedItemsManager::add(const double timestamp, const TValue value) { +void DelayedItemsManager::add(const double timestamp, const TValue &value) { auto result = itemsSet_.emplace(timestamp, value); if (result.second) { itemsMap_[result.first->value] = result.first; @@ -38,7 +38,7 @@ typename DelayedItemsManager::Item DelayedItemsManager::pop() { } template -bool DelayedItemsManager::remove(const TValue value) { +bool DelayedItemsManager::remove(const TValue &value) { auto it = itemsMap_.find(value); if (it == itemsMap_.end()) { diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.h b/packages/react-native-reanimated/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.h index 54fb72840156..ff84a60c0458 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.h @@ -34,9 +34,9 @@ class DelayedItemsManager { ItemMap itemsMap_; public: - void add(double timestamp, TValue value); + void add(double timestamp, const TValue &value); Item pop(); - bool remove(TValue value); + bool remove(const TValue &value); const Item &top() const; bool empty() const; size_t size() const; diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp index ba22e753391e..0952b23b1b58 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp @@ -32,7 +32,7 @@ std::optional LayoutAnimationsProxy_Experimental::pullTrans ShadowViewMutationList filteredMutations; auto rootChildCount = static_cast(lightNodes_[surfaceId]->children.size()); const std::vector> roots; - const bool isInTransition = transitionState_; + const bool isInTransition = static_cast(transitionState_); if (isInTransition) { updateLightTree(propsParserContext, mutations, filteredMutations); @@ -50,7 +50,7 @@ std::optional LayoutAnimationsProxy_Experimental::pullTrans auto beforeTopScreen = topScreen[surfaceId]; if (beforeTopScreen) { ReanimatedSystraceSection s("find before elements"); - findSharedElementsOnScreen(beforeTopScreen, BEFORE, propsParserContext); + findSharedElementsOnScreen(beforeTopScreen, BeforeOrAfter::BEFORE, propsParserContext); } updateLightTree(propsParserContext, mutations, filteredMutations); @@ -59,7 +59,7 @@ std::optional LayoutAnimationsProxy_Experimental::pullTrans topScreen[surfaceId] = afterTopScreen; if (afterTopScreen) { ReanimatedSystraceSection s("find after elements"); - findSharedElementsOnScreen(afterTopScreen, AFTER, propsParserContext); + findSharedElementsOnScreen(afterTopScreen, BeforeOrAfter::AFTER, propsParserContext); #ifdef __APPLE__ forceScreenSnapshot_(afterTopScreen->current.tag); #endif @@ -71,9 +71,9 @@ std::optional LayoutAnimationsProxy_Experimental::pullTrans // To keep things simple, we put mutations related to source views before all muatations // and mutations to hide target views after all mutations. std::vector mergedMutations; - hideTransitioningViews(BEFORE, mergedMutations, propsParserContext); + hideTransitioningViews(BeforeOrAfter::BEFORE, mergedMutations, propsParserContext); mergedMutations.insert(mergedMutations.end(), filteredMutations.begin(), filteredMutations.end()); - hideTransitioningViews(AFTER, mergedMutations, propsParserContext); + hideTransitioningViews(BeforeOrAfter::AFTER, mergedMutations, propsParserContext); std::swap(filteredMutations, mergedMutations); } diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h index 12420865bf40..a6fe9fa69ef7 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h @@ -44,7 +44,7 @@ struct LayoutAnimationsProxy_Experimental : public LayoutAnimationsProxyCommon, mutable Tag transitionTag_; mutable double transitionProgress_; mutable bool transitionUpdated_; - mutable TransitionState transitionState_ = NONE; + mutable TransitionState transitionState_ = TransitionState::NONE; mutable SurfaceId transitioningSurfaceId_ = -1; mutable std::unordered_map> topScreen; mutable int containerTag_ = 10000002; diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp index f39ba96f8770..3ee855c43269 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp @@ -124,7 +124,7 @@ std::optional LayoutAnimationsProxy_Legacy::endLayoutAnimation(int ta auto node = nodeForTag_[tag]; auto mutationNode = std::static_pointer_cast(node); - mutationNode->state = DEAD; + mutationNode->state = ExitingState_Legacy::DEAD; auto &[deadNodes] = surfaceContext_[surfaceId]; deadNodes.insert(mutationNode); @@ -172,7 +172,7 @@ void LayoutAnimationsProxy_Legacy::parseRemoveMutations( } } if (!deletedViews.contains(mutation.oldChildShadowView.tag)) { - mutationNode->state = MOVED; + mutationNode->state = ExitingState_Legacy::MOVED; movedViews.insert_or_assign(mutation.oldChildShadowView.tag, -1); } nodeForTag_[tag] = mutationNode; @@ -245,11 +245,11 @@ void LayoutAnimationsProxy_Legacy::handleRemovals( if (!startAnimationsRecursively(node, true, shouldAnimate, false, filteredMutations)) { filteredMutations.push_back(node->mutation); node->unflattenedParent->removeChildFromUnflattenedTree(node); //??? - if (node->state != MOVED) { + if (node->state != ExitingState_Legacy::MOVED) { maybeCancelAnimation(node->tag); filteredMutations.push_back(ShadowViewMutation::DeleteMutation(node->mutation.oldChildShadowView)); nodeForTag_.erase(node->tag); - node->state = DELETED; + node->state = ExitingState_Legacy::DELETED; #ifdef LAYOUT_ANIMATIONS_LOGS LOG(INFO) << "delete " << node->tag << std::endl; #endif @@ -258,7 +258,7 @@ void LayoutAnimationsProxy_Legacy::handleRemovals( } for (const auto &node : deadNodes) { - if (node->state != DELETED) { + if (node->state != ExitingState_Legacy::DELETED) { endAnimationsRecursively(node, filteredMutations); maybeDropAncestors(node->unflattenedParent, node, filteredMutations); } @@ -429,12 +429,12 @@ void LayoutAnimationsProxy_Legacy::endAnimationsRecursively( const std::shared_ptr &node, ShadowViewMutationList &mutations) const { maybeCancelAnimation(node->tag); - node->state = DELETED; + node->state = ExitingState_Legacy::DELETED; // iterate from the end, so that children // with higher indices appear first in the mutations list for (auto it = node->unflattenedChildren.rbegin(); it != node->unflattenedChildren.rend(); it++) { auto &subNode = *it; - if (subNode->state != DELETED) { + if (subNode->state != ExitingState_Legacy::DELETED) { endAnimationsRecursively(subNode, mutations); } } @@ -457,11 +457,11 @@ void LayoutAnimationsProxy_Legacy::maybeDropAncestors( auto node = std::static_pointer_cast(parent); - if (node->children.size() == 0 && node->state != ANIMATING) { + if (node->children.size() == 0 && node->state != ExitingState_Legacy::ANIMATING) { nodeForTag_.erase(node->tag); cleanupMutations.push_back(node->mutation); maybeCancelAnimation(node->tag); - node->state = DELETED; + node->state = ExitingState_Legacy::DELETED; #ifdef LAYOUT_ANIMATIONS_LOGS LOG(INFO) << "delete " << node->tag << std::endl; #endif @@ -492,7 +492,7 @@ bool LayoutAnimationsProxy_Legacy::startAnimationsRecursively( bool hasAnimatedChildren = false; shouldRemoveSubviewsWithoutAnimations = - shouldRemoveSubviewsWithoutAnimations && (!hasExitAnimation || node->state == MOVED); + shouldRemoveSubviewsWithoutAnimations && (!hasExitAnimation || node->state == ExitingState_Legacy::MOVED); std::vector> toBeRemoved; // iterate from the end, so that children @@ -503,8 +503,8 @@ bool LayoutAnimationsProxy_Legacy::startAnimationsRecursively( LOG(INFO) << "child " << subNode->tag << " " << " " << shouldAnimate << " " << shouldRemoveSubviewsWithoutAnimations << std::endl; #endif - if (subNode->state != UNDEFINED && subNode->state != MOVED) { - if (shouldAnimate && subNode->state != DEAD) { + if (subNode->state != ExitingState_Legacy::UNDEFINED && subNode->state != ExitingState_Legacy::MOVED) { + if (shouldAnimate && subNode->state != ExitingState_Legacy::DEAD) { hasAnimatedChildren = true; } else { endAnimationsRecursively(subNode, mutations); @@ -516,21 +516,21 @@ bool LayoutAnimationsProxy_Legacy::startAnimationsRecursively( LOG(INFO) << "child " << subNode->tag << " start animations returned true " << std::endl; #endif hasAnimatedChildren = true; - } else if (subNode->state == MOVED) { + } else if (subNode->state == ExitingState_Legacy::MOVED) { mutations.push_back(subNode->mutation); toBeRemoved.push_back(subNode); } else if (shouldRemoveSubviewsWithoutAnimations) { maybeCancelAnimation(subNode->tag); mutations.push_back(subNode->mutation); toBeRemoved.push_back(subNode); - subNode->state = DELETED; + subNode->state = ExitingState_Legacy::DELETED; nodeForTag_.erase(subNode->tag); #ifdef LAYOUT_ANIMATIONS_LOGS LOG(INFO) << "delete " << subNode->tag << std::endl; #endif mutations.push_back(ShadowViewMutation::DeleteMutation(subNode->mutation.oldChildShadowView)); } else { - subNode->state = WAITING; + subNode->state = ExitingState_Legacy::WAITING; } } @@ -538,7 +538,7 @@ bool LayoutAnimationsProxy_Legacy::startAnimationsRecursively( node->removeChildFromUnflattenedTree(subNode); } - if (node->state == MOVED) { + if (node->state == ExitingState_Legacy::MOVED) { auto replacement = std::make_shared(*node); for (const auto &subNode : node->children) { subNode->parent = replacement; @@ -553,7 +553,7 @@ bool LayoutAnimationsProxy_Legacy::startAnimationsRecursively( bool wantAnimateExit = hasExitAnimation || hasAnimatedChildren; if (hasExitAnimation) { - node->state = ANIMATING; + node->state = ExitingState_Legacy::ANIMATING; startExitingAnimation(node->tag, node->mutation); } else { layoutAnimationsManager_->clearLayoutAnimationConfig(node->tag); diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.h b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.h index bcd0b801fd19..b4221d84ee75 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.h @@ -24,7 +24,7 @@ class ReanimatedModuleProxy; using namespace facebook; -typedef enum ExitingState_Legacy : std::uint8_t { +typedef enum class ExitingState_Legacy : std::uint8_t { UNDEFINED = 1, WAITING = 2, ANIMATING = 4, @@ -60,7 +60,7 @@ struct Node { */ struct MutationNode : public Node { ShadowViewMutation mutation; - ExitingState_Legacy state = UNDEFINED; + ExitingState_Legacy state = ExitingState_Legacy::UNDEFINED; explicit MutationNode(ShadowViewMutation &mutation) : Node(mutation.oldChildShadowView.tag), mutation(mutation) {} MutationNode(ShadowViewMutation &mutation, Node &&node) : Node(std::move(node)), mutation(mutation) {} bool isMutationNode() override; diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h index f8cdaaa397f2..4f53e693c51c 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h @@ -13,7 +13,7 @@ namespace reanimated { -enum BeforeOrAfter : std::uint8_t { BEFORE = 0, AFTER = 1 }; +enum class BeforeOrAfter : std::uint8_t { BEFORE = 0, AFTER = 1 }; struct Rect { double width, height; @@ -66,7 +66,7 @@ typedef enum class ExitingState : std::uint8_t { struct MutationNode; -enum TransitionState : std::uint8_t { +enum class TransitionState : std::uint8_t { NONE = 0, START = 1, ACTIVE = 2, @@ -74,7 +74,7 @@ enum TransitionState : std::uint8_t { CANCELLED = 4, }; -enum Intent : std::uint8_t { +enum class Intent : std::uint8_t { NO_INTENT = 0, TO_MOVE = 1, TO_DELETE = 2, diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp index a8e08d255a75..861b08cbbb3c 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #ifndef ANDROID #if __has_include() @@ -62,15 +63,17 @@ void LayoutAnimationsProxy_Experimental::findSharedElementsOnScreen( auto newTransform = parseParentTransforms(node, absolutePositions); const auto &parent = node->parent.lock(); react_native_assert(parent && "Parent node is nullptr"); - transform[index] = std::move(newTransform); - snapshot[index] = copy; - parentTag[index] = parent->current.tag; - if (parentTag[BEFORE] && parentTag[AFTER]) { + int indexNum = static_cast(index); + transform[indexNum] = std::move(newTransform); + snapshot[indexNum] = copy; + parentTag[indexNum] = parent->current.tag; + + if (parentTag[static_cast(BeforeOrAfter::BEFORE)] && parentTag[static_cast(BeforeOrAfter::AFTER)]) { transitions_.emplace_back(sharedTag, transition); - } else if (parentTag[AFTER]) { + } else if (parentTag[static_cast(BeforeOrAfter::AFTER)]) { // TODO (future): this is adding unnecessary views to the list - tagsToRestore_.push_back(snapshot[AFTER].tag); + tagsToRestore_.push_back(snapshot[static_cast(BeforeOrAfter::AFTER)].tag); } } for (auto &child : node->children) { @@ -88,30 +91,30 @@ void LayoutAnimationsProxy_Experimental::handleProgressTransition( } transitionUpdated_ = false; - if (!mutations.empty() || !transitionState_) { + if (!mutations.empty() || !static_cast(transitionState_)) { return; } - if (transitionState_ == START) { + if (transitionState_ == TransitionState::START) { auto root = lightNodes_[surfaceId]; auto beforeTopScreen = topScreen[surfaceId]; auto afterTopScreen = lightNodes_[transitionTag_]; if (beforeTopScreen && afterTopScreen && beforeTopScreen != afterTopScreen) { - findSharedElementsOnScreen(beforeTopScreen, BEFORE, propsParserContext); - findSharedElementsOnScreen(afterTopScreen, AFTER, propsParserContext); - hideTransitioningViews(BEFORE, filteredMutations, propsParserContext); - hideTransitioningViews(AFTER, filteredMutations, propsParserContext); + findSharedElementsOnScreen(beforeTopScreen, BeforeOrAfter::BEFORE, propsParserContext); + findSharedElementsOnScreen(afterTopScreen, BeforeOrAfter::AFTER, propsParserContext); + hideTransitioningViews(BeforeOrAfter::BEFORE, filteredMutations, propsParserContext); + hideTransitioningViews(BeforeOrAfter::AFTER, filteredMutations, propsParserContext); for (auto &[sharedTag, transition] : transitions_) { auto &[before, after] = transition.snapshot; const auto &transform = transition.transform; - overrideTransform(before, transform[BEFORE], propsParserContext); - overrideTransform(after, transform[AFTER], propsParserContext); + overrideTransform(before, transform[static_cast(BeforeOrAfter::BEFORE)], propsParserContext); + overrideTransform(after, transform[static_cast(BeforeOrAfter::AFTER)], propsParserContext); auto containerTag = getOrCreateContainer(before, sharedTag, filteredMutations, surfaceId); transferConfigToContainer(containerTag, before.tag); - restoreMap_[containerTag][BEFORE] = before.tag; - restoreMap_[containerTag][AFTER] = after.tag; + restoreMap_[containerTag][static_cast(BeforeOrAfter::BEFORE)] = before.tag; + restoreMap_[containerTag][static_cast(BeforeOrAfter::AFTER)] = after.tag; before.tag = containerTag; after.tag = containerTag; activeTransitions_.insert(containerTag); @@ -119,7 +122,7 @@ void LayoutAnimationsProxy_Experimental::handleProgressTransition( startProgressTransition(containerTag, before, after, surfaceId); } } - } else if (transitionState_ == ACTIVE) { + } else if (transitionState_ == TransitionState::ACTIVE) { for (auto tag : activeTransitions_) { auto layoutAnimation = layoutAnimations_[tag]; auto &updateMap = surfaceManager.getUpdateMap(layoutAnimation.finalView.surfaceId); @@ -153,23 +156,23 @@ void LayoutAnimationsProxy_Experimental::handleProgressTransition( } } - if (transitionState_ == START) { - transitionState_ = ACTIVE; - } else if (transitionState_ == END || transitionState_ == CANCELLED) { + if (transitionState_ == TransitionState::START) { + transitionState_ = TransitionState::ACTIVE; + } else if (transitionState_ == TransitionState::END || transitionState_ == TransitionState::CANCELLED) { for (auto tag : activeTransitions_) { sharedContainersToRemove_.push_back(tag); - tagsToRestore_.push_back(restoreMap_[tag][AFTER]); - if (transitionState_ == CANCELLED) { - tagsToRestore_.push_back(restoreMap_[tag][BEFORE]); + tagsToRestore_.push_back(restoreMap_[tag][static_cast(BeforeOrAfter::AFTER)]); + if (transitionState_ == TransitionState::CANCELLED) { + tagsToRestore_.push_back(restoreMap_[tag][static_cast(BeforeOrAfter::BEFORE)]); } } - if (transitionState_ == END) { + if (transitionState_ == TransitionState::END) { topScreen[surfaceId] = lightNodes_[transitionTag_]; synchronized_ = false; } sharedTransitionManager_->containerTags_.clear(); activeTransitions_.clear(); - transitionState_ = NONE; + transitionState_ = TransitionState::NONE; } } @@ -244,8 +247,8 @@ void LayoutAnimationsProxy_Experimental::handleSharedTransitionsStart( for (auto &[sharedTag, transition] : transitions_) { auto &[before, after] = transition.snapshot; const auto &transform = transition.transform; - overrideTransform(before, transform[BEFORE], propsParserContext); - overrideTransform(after, transform[AFTER], propsParserContext); + overrideTransform(before, transform[static_cast(BeforeOrAfter::BEFORE)], propsParserContext); + overrideTransform(after, transform[static_cast(BeforeOrAfter::AFTER)], propsParserContext); auto containerTag = getOrCreateContainer(before, sharedTag, filteredMutations, surfaceId); transferConfigToContainer(containerTag, before.tag); @@ -266,7 +269,7 @@ void LayoutAnimationsProxy_Experimental::handleSharedTransitionsStart( after.tag = containerTag; const auto &la = layoutAnimations_[containerTag]; if (la.finalView.layoutMetrics != after.layoutMetrics) { - overrideTransform(after, transition.transform[AFTER], propsParserContext); + overrideTransform(after, transition.transform[static_cast(BeforeOrAfter::AFTER)], propsParserContext); startSharedTransition(containerTag, la.currentView, after, surfaceId); } } @@ -278,8 +281,9 @@ void LayoutAnimationsProxy_Experimental::hideTransitioningViews( ShadowViewMutationList &filteredMutations, const PropsParserContext &propsParserContext) const { for (auto &[sharedTag, transition] : transitions_) { - const auto &shadowView = transition.snapshot[index]; - const auto &parentTag = transition.parentTag[index]; + int indexNum = static_cast(index); + const auto &shadowView = transition.snapshot[indexNum]; + const auto &parentTag = transition.parentTag[indexNum]; auto m = ShadowViewMutation::UpdateMutation( shadowView, cloneViewWithoutOpacity(shadowView, propsParserContext), parentTag); filteredMutations.push_back(m); @@ -303,11 +307,11 @@ std::optional LayoutAnimationsProxy_Experimental::onTransitionProgres // transitions (maybe that's ok?) if (!isClosing && !isGoingForward && !isAndroid) { transitionProgress_ = progress; - if (transitionState_ == NONE && progress < 1) { - transitionState_ = START; + if (transitionState_ == TransitionState::NONE && progress < 1) { + transitionState_ = TransitionState::START; transitionTag_ = tag; - } else if (transitionState_ == ACTIVE && progress == 1) { - transitionState_ = END; + } else if (transitionState_ == TransitionState::ACTIVE && progress == 1) { + transitionState_ = TransitionState::END; } const auto &node = lightNodes_[tag]; react_native_assert(node && "LightNode is nullptr"); @@ -320,8 +324,8 @@ std::optional LayoutAnimationsProxy_Experimental::onTransitionProgres std::optional LayoutAnimationsProxy_Experimental::onGestureCancel() { auto lock = std::unique_lock(mutex); - if (transitionState_) { - transitionState_ = CANCELLED; + if (static_cast(transitionState_)) { + transitionState_ = TransitionState::CANCELLED; transitionUpdated_ = true; react_native_assert(transitioningSurfaceId_ != -1 && "Cancelling non-observed transition"); diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.cpp index 2fb3e0f3f466..0d4efb14beb8 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.cpp @@ -7,31 +7,31 @@ namespace reanimated { void UIRuntimeDecorator::decorate( jsi::Runtime &uiRuntime, - ObtainPropFunction obtainPropFunction, - UpdatePropsFunction updateProps, - MeasureFunction measure, - DispatchCommandFunction dispatchCommand, - GetAnimationTimestampFunction getAnimationTimestamp, - SetGestureStateFunction setGestureState, - ProgressLayoutAnimationFunction progressLayoutAnimation, - EndLayoutAnimationFunction endLayoutAnimation, - MaybeFlushUIUpdatesQueueFunction maybeFlushUIUpdatesQueue) { - - jsi_utils::installJsiFunction(uiRuntime, "_updateProps", std::move(updateProps)); - jsi_utils::installJsiFunction(uiRuntime, "_dispatchCommand", std::move(dispatchCommand)); - jsi_utils::installJsiFunction(uiRuntime, "_measure", std::move(measure)); - jsi_utils::installJsiFunction(uiRuntime, "_getAnimationTimestamp", std::move(getAnimationTimestamp)); - jsi_utils::installJsiFunction(uiRuntime, "_notifyAboutProgress", std::move(progressLayoutAnimation)); - jsi_utils::installJsiFunction(uiRuntime, "_notifyAboutEnd", std::move(endLayoutAnimation)); - jsi_utils::installJsiFunction(uiRuntime, "_setGestureState", std::move(setGestureState)); - jsi_utils::installJsiFunction(uiRuntime, "_obtainProp", std::move(obtainPropFunction)); - - subscribeForMicrotasksFinalization(uiRuntime, std::move(maybeFlushUIUpdatesQueue)); + const ObtainPropFunction &obtainPropFunction, + const UpdatePropsFunction &updateProps, + const MeasureFunction &measure, + const DispatchCommandFunction &dispatchCommand, + const GetAnimationTimestampFunction &getAnimationTimestamp, + const SetGestureStateFunction &setGestureState, + const ProgressLayoutAnimationFunction &progressLayoutAnimation, + const EndLayoutAnimationFunction &endLayoutAnimation, + const MaybeFlushUIUpdatesQueueFunction &maybeFlushUIUpdatesQueue) { + + jsi_utils::installJsiFunction(uiRuntime, "_updateProps", updateProps); + jsi_utils::installJsiFunction(uiRuntime, "_dispatchCommand", dispatchCommand); + jsi_utils::installJsiFunction(uiRuntime, "_measure", measure); + jsi_utils::installJsiFunction(uiRuntime, "_getAnimationTimestamp", getAnimationTimestamp); + jsi_utils::installJsiFunction(uiRuntime, "_notifyAboutProgress", progressLayoutAnimation); + jsi_utils::installJsiFunction(uiRuntime, "_notifyAboutEnd", endLayoutAnimation); + jsi_utils::installJsiFunction(uiRuntime, "_setGestureState", setGestureState); + jsi_utils::installJsiFunction(uiRuntime, "_obtainProp", obtainPropFunction); + + subscribeForMicrotasksFinalization(uiRuntime, maybeFlushUIUpdatesQueue); } void UIRuntimeDecorator::subscribeForMicrotasksFinalization( jsi::Runtime &uiRuntime, - MaybeFlushUIUpdatesQueueFunction maybeFlushUIUpdatesQueue) { + const MaybeFlushUIUpdatesQueueFunction &maybeFlushUIUpdatesQueue) { auto maybeMicrotaskQueueFinalizers = uiRuntime.global().getProperty(uiRuntime, "_microtaskQueueFinalizers"); if (maybeMicrotaskQueueFinalizers.isUndefined()) { @@ -50,7 +50,7 @@ void UIRuntimeDecorator::subscribeForMicrotasksFinalization( uiRuntime, jsi::PropNameID::forAscii(uiRuntime, "_maybeFlushUIUpdatesQueue"), 0, - jsi_utils::createHostFunction(std::move(maybeFlushUIUpdatesQueue)))); + jsi_utils::createHostFunction(maybeFlushUIUpdatesQueue))); } } // namespace reanimated diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.h b/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.h index b86ac41f84c2..35ffacafb2dc 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.h @@ -12,20 +12,20 @@ class UIRuntimeDecorator { public: static void decorate( jsi::Runtime &uiRuntime, - const ObtainPropFunction obtainPropFunction, - const UpdatePropsFunction updateProps, - const MeasureFunction measure, - const DispatchCommandFunction dispatchCommand, - const GetAnimationTimestampFunction getAnimationTimestamp, - const SetGestureStateFunction setGestureState, - const ProgressLayoutAnimationFunction progressLayoutAnimation, - const EndLayoutAnimationFunction endLayoutAnimation, - const MaybeFlushUIUpdatesQueueFunction maybeFlushUIUpdatesQueue); + const ObtainPropFunction &obtainPropFunction, + const UpdatePropsFunction &updateProps, + const MeasureFunction &measure, + const DispatchCommandFunction &dispatchCommand, + const GetAnimationTimestampFunction &getAnimationTimestamp, + const SetGestureStateFunction &setGestureState, + const ProgressLayoutAnimationFunction &progressLayoutAnimation, + const EndLayoutAnimationFunction &endLayoutAnimation, + const MaybeFlushUIUpdatesQueueFunction &maybeFlushUIUpdatesQueue); private: static void subscribeForMicrotasksFinalization( jsi::Runtime &uiRuntime, - MaybeFlushUIUpdatesQueueFunction maybeFlushUIUpdatesQueue); + const MaybeFlushUIUpdatesQueueFunction &maybeFlushUIUpdatesQueue); }; } // namespace reanimated diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/Tools/ReaJSIUtils.h b/packages/react-native-reanimated/Common/cpp/reanimated/Tools/ReaJSIUtils.h index d1556c33dcd7..c87b872bb5ba 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/Tools/ReaJSIUtils.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/Tools/ReaJSIUtils.h @@ -75,7 +75,7 @@ inline std::tuple convertArgs(jsi::Runtime &rt, const jsi::Value *ar // native C++ types needed to call `function` template std::tuple -getArgsForFunction(std::function, jsi::Runtime &rt, const jsi::Value *args, const size_t count) { +getArgsForFunction(const std::function &, jsi::Runtime &rt, const jsi::Value *args, const size_t count) { react_native_assert(sizeof...(Args) == count && "Argument list has different length than expected"); return convertArgs(rt, args); } @@ -85,7 +85,7 @@ getArgsForFunction(std::function, jsi::Runtime &rt, const jsi::Val // passing `rt` as the first argument template std::tuple getArgsForFunction( - std::function, + const std::function &, jsi::Runtime &rt, const jsi::Value *args, const size_t count) { @@ -117,7 +117,7 @@ inline jsi::Value apply(std::function function, std::tuple -jsi::HostFunctionType createHostFunction(Fun function) { +jsi::HostFunctionType createHostFunction(const Fun &function) { return [function](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args, const size_t count) { auto argz = getArgsForFunction(function, rt, args, count); return apply(function, std::move(argz)); @@ -127,7 +127,7 @@ jsi::HostFunctionType createHostFunction(Fun function) { // returns a function with JSI calling convention // from a native function `function` returning a string template -jsi::HostFunctionType createHostFunction(std::function function) { +jsi::HostFunctionType createHostFunction(const std::function &function) { return [function](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args, const size_t count) { auto argz = getArgsForFunction(function, rt, args, count); return apply(rt, function, std::move(argz)); @@ -151,7 +151,7 @@ struct takes_runtime { // and installs it as a global function named `name` // in the `rt` JS runtime template -void installJsiFunction(jsi::Runtime &rt, std::string_view name, std::function function) { +void installJsiFunction(jsi::Runtime &rt, std::string_view name, const std::function &function) { auto clb = createHostFunction(function); auto argsCount = sizeof...(Args) - takes_runtime::value; jsi::Value jsiFunction = From c02dec5770ea70030164ba8f99c7797abfa8d697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Wi=C5=9Bniewski?= Date: Mon, 16 Mar 2026 16:58:51 +0100 Subject: [PATCH 4/9] Push podfile --- apps/fabric-example/ios/Podfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/fabric-example/ios/Podfile.lock b/apps/fabric-example/ios/Podfile.lock index fd0aaaee9934..0f651593b0ad 100644 --- a/apps/fabric-example/ios/Podfile.lock +++ b/apps/fabric-example/ios/Podfile.lock @@ -2456,7 +2456,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: FBLazyVector: 4815a9b6c97de1f17c88b3cf7047fc0aa0018fb8 - hermes-engine: 9f864e304a78a35e15543a8fcd93c2850e11cfe6 + hermes-engine: 3086d2d1b345833ccabb2cd7a9b5901dce9ee889 MMKVCore: f2dd4c9befea04277a55e84e7812f930537993df NitroMmkv: ca0b67493c62d3f2b29457569ee48d24a1f7afd5 NitroModules: 42fb1740701d25672d7531652987eca15bbb181e @@ -2468,7 +2468,7 @@ SPEC CHECKSUMS: React: ce3b89b04d579b21ba990ff07a1d4cf0a68588dd React-callinvoker: 30be38ed761abcb8ae7edaa39e34cb9aade4b33b React-Core: 59c718ce09b1b83d4f07c0112b9c5f99ea39ee94 - React-Core-prebuilt: 8b3b621447332c61506e40260403fc71d783c4e0 + React-Core-prebuilt: cabdf97514cfa97669e3e2f056c26e62a0b06998 React-CoreModules: bcb9314b39eaa9134487be0cb8c8ee4a6d2e5cd9 React-cxxreact: fee24034f430cfbcbedced4157eacd2be7ced010 React-debug: 5138aa953fe4a9db1690681de71577dd3b4f05b1 @@ -2530,7 +2530,7 @@ SPEC CHECKSUMS: ReactAppDependencyProvider: dd8001caba9cb3fbe49a61d234262eaaa3d67aee ReactCodegen: 3e81858c6242de4bbde48ee222523fe45c41a21a ReactCommon: 2f76f91c78f14d4a2c3bc841842a6145d3e99038 - ReactNativeDependencies: e8ba825d80e7c478c81d6075a56ff068ca9da99e + ReactNativeDependencies: ed078b635b88b05e1a88544a348d420115ff49b9 RNCAsyncStorage: 2ad919e88b8bc2cd80e8697ce66d04d006743283 RNCClipboard: 715fa7c6c8366f17d00f05a439ee7488f390fa5f RNCMaskedView: eb2b2e538afa907f05a5848a1a1ac26092e6fec9 From 0685361a4f9a5b09cc9ded4bfc6ea0068980ae24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Wi=C5=9Bniewski?= Date: Mon, 16 Mar 2026 17:18:54 +0100 Subject: [PATCH 5/9] [TMP]: This should fail miserably --- .../cpp/worklets/Tools/WorkletsJSIUtils.h | 19 ++++++++++++++++++- scripts/clang-tidy-lint.sh | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletsJSIUtils.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletsJSIUtils.h index c713bb7a72c3..65ee2f5d386f 100644 --- a/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletsJSIUtils.h +++ b/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletsJSIUtils.h @@ -9,6 +9,23 @@ using namespace facebook; +inline std::string triggerClangTidyFailures(const std::string text) { + // 1. performance-unnecessary-value-param: + // 'text' is passed by value (triggering a copy) instead of const std::string& + + // 2. performance-move-const-arg: + // Trying to move a 'const' variable does nothing but block optimizations + std::string firstCopy = std::move(text); + + // 3. bugprone-use-after-move: + // Accessing 'firstCopy' right after we moved its contents to 'secondCopy' + std::string secondCopy = std::move(firstCopy); + if (firstCopy.length() > 0) + return "Failed"; // 4. readability-braces-around-statements: Missing braces + + return secondCopy; +} + namespace worklets::jsi_utils { // `get` functions take a pointer to `jsi::Value` and @@ -102,7 +119,7 @@ inline jsi::Value apply(std::function function, std::tuple inline jsi::Value apply(jsi::Runtime &rt, std::function function, std::tuple args) { - return jsi::String::createFromUtf8(rt, std::apply(function, std::move(args))); + return jsi::String::createFromUtf8(rt, std::apply(function, args)); } // calls void-returning `function` with `args`, diff --git a/scripts/clang-tidy-lint.sh b/scripts/clang-tidy-lint.sh index 0653258d0d09..b4ba818ef03a 100755 --- a/scripts/clang-tidy-lint.sh +++ b/scripts/clang-tidy-lint.sh @@ -15,4 +15,4 @@ if [ ! -f "../../compile_commands.json" ]; then ) fi -run-clang-tidy -quiet -p . -header-filter="^.*/$1/.*\.h$" "$1" +run-clang-tidy -quiet -p="." -header-filter="^.*/$1/.*\.h$" "$1" From 90a6ee8dc057131621820db8ad21d39ffa81e143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Wi=C5=9Bniewski?= Date: Mon, 16 Mar 2026 17:53:47 +0100 Subject: [PATCH 6/9] Revert "[TMP]: This should fail miserably" This reverts commit 0685361a4f9a5b09cc9ded4bfc6ea0068980ae24. --- .../cpp/worklets/Tools/WorkletsJSIUtils.h | 19 +------------------ scripts/clang-tidy-lint.sh | 2 +- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletsJSIUtils.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletsJSIUtils.h index 65ee2f5d386f..c713bb7a72c3 100644 --- a/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletsJSIUtils.h +++ b/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletsJSIUtils.h @@ -9,23 +9,6 @@ using namespace facebook; -inline std::string triggerClangTidyFailures(const std::string text) { - // 1. performance-unnecessary-value-param: - // 'text' is passed by value (triggering a copy) instead of const std::string& - - // 2. performance-move-const-arg: - // Trying to move a 'const' variable does nothing but block optimizations - std::string firstCopy = std::move(text); - - // 3. bugprone-use-after-move: - // Accessing 'firstCopy' right after we moved its contents to 'secondCopy' - std::string secondCopy = std::move(firstCopy); - if (firstCopy.length() > 0) - return "Failed"; // 4. readability-braces-around-statements: Missing braces - - return secondCopy; -} - namespace worklets::jsi_utils { // `get` functions take a pointer to `jsi::Value` and @@ -119,7 +102,7 @@ inline jsi::Value apply(std::function function, std::tuple inline jsi::Value apply(jsi::Runtime &rt, std::function function, std::tuple args) { - return jsi::String::createFromUtf8(rt, std::apply(function, args)); + return jsi::String::createFromUtf8(rt, std::apply(function, std::move(args))); } // calls void-returning `function` with `args`, diff --git a/scripts/clang-tidy-lint.sh b/scripts/clang-tidy-lint.sh index b4ba818ef03a..0653258d0d09 100755 --- a/scripts/clang-tidy-lint.sh +++ b/scripts/clang-tidy-lint.sh @@ -15,4 +15,4 @@ if [ ! -f "../../compile_commands.json" ]; then ) fi -run-clang-tidy -quiet -p="." -header-filter="^.*/$1/.*\.h$" "$1" +run-clang-tidy -quiet -p . -header-filter="^.*/$1/.*\.h$" "$1" From 101587fcca22597b05b3b62ebeaec19e3cf98ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Wi=C5=9Bniewski?= Date: Wed, 18 Mar 2026 11:12:08 +0100 Subject: [PATCH 7/9] Check for compile_commands locally --- scripts/clang-tidy-lint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/clang-tidy-lint.sh b/scripts/clang-tidy-lint.sh index 0653258d0d09..5449aaf4f3f6 100755 --- a/scripts/clang-tidy-lint.sh +++ b/scripts/clang-tidy-lint.sh @@ -6,7 +6,7 @@ if ! which run-clang-tidy >/dev/null; then exit 1 fi -if [ ! -f "../../compile_commands.json" ]; then +if [ ! -f "compile_commands.json" ]; then echo "info: missing compile_commands.json, generating one" ( cd ../../apps/fabric-example || exit 1 From f01f18485306987306cb7af61bc412c61e5c4cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Wi=C5=9Bniewski?= Date: Wed, 18 Mar 2026 11:16:15 +0100 Subject: [PATCH 8/9] NOLINT for beforeOrAfter --- .../LayoutAnimationsProxy_Experimental.cpp | 8 ++--- .../LayoutAnimations/LayoutAnimationsUtils.h | 2 +- .../LayoutAnimations/SharedTransitions.cpp | 32 +++++++++---------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp index 0952b23b1b58..d904bf59a9e8 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp @@ -50,7 +50,7 @@ std::optional LayoutAnimationsProxy_Experimental::pullTrans auto beforeTopScreen = topScreen[surfaceId]; if (beforeTopScreen) { ReanimatedSystraceSection s("find before elements"); - findSharedElementsOnScreen(beforeTopScreen, BeforeOrAfter::BEFORE, propsParserContext); + findSharedElementsOnScreen(beforeTopScreen, BEFORE, propsParserContext); } updateLightTree(propsParserContext, mutations, filteredMutations); @@ -59,7 +59,7 @@ std::optional LayoutAnimationsProxy_Experimental::pullTrans topScreen[surfaceId] = afterTopScreen; if (afterTopScreen) { ReanimatedSystraceSection s("find after elements"); - findSharedElementsOnScreen(afterTopScreen, BeforeOrAfter::AFTER, propsParserContext); + findSharedElementsOnScreen(afterTopScreen, AFTER, propsParserContext); #ifdef __APPLE__ forceScreenSnapshot_(afterTopScreen->current.tag); #endif @@ -71,9 +71,9 @@ std::optional LayoutAnimationsProxy_Experimental::pullTrans // To keep things simple, we put mutations related to source views before all muatations // and mutations to hide target views after all mutations. std::vector mergedMutations; - hideTransitioningViews(BeforeOrAfter::BEFORE, mergedMutations, propsParserContext); + hideTransitioningViews(BEFORE, mergedMutations, propsParserContext); mergedMutations.insert(mergedMutations.end(), filteredMutations.begin(), filteredMutations.end()); - hideTransitioningViews(BeforeOrAfter::AFTER, mergedMutations, propsParserContext); + hideTransitioningViews(AFTER, mergedMutations, propsParserContext); std::swap(filteredMutations, mergedMutations); } diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h index 4f53e693c51c..a5c860f72689 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h @@ -13,7 +13,7 @@ namespace reanimated { -enum class BeforeOrAfter : std::uint8_t { BEFORE = 0, AFTER = 1 }; +enum BeforeOrAfter : std::uint8_t { BEFORE = 0, AFTER = 1 }; // NOLINT struct Rect { double width, height; diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp index 861b08cbbb3c..c94f9bd69ee2 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp @@ -69,11 +69,11 @@ void LayoutAnimationsProxy_Experimental::findSharedElementsOnScreen( snapshot[indexNum] = copy; parentTag[indexNum] = parent->current.tag; - if (parentTag[static_cast(BeforeOrAfter::BEFORE)] && parentTag[static_cast(BeforeOrAfter::AFTER)]) { + if (parentTag[BEFORE] && parentTag[AFTER]) { transitions_.emplace_back(sharedTag, transition); - } else if (parentTag[static_cast(BeforeOrAfter::AFTER)]) { + } else if (parentTag[AFTER]) { // TODO (future): this is adding unnecessary views to the list - tagsToRestore_.push_back(snapshot[static_cast(BeforeOrAfter::AFTER)].tag); + tagsToRestore_.push_back(snapshot[AFTER].tag); } } for (auto &child : node->children) { @@ -100,21 +100,21 @@ void LayoutAnimationsProxy_Experimental::handleProgressTransition( auto beforeTopScreen = topScreen[surfaceId]; auto afterTopScreen = lightNodes_[transitionTag_]; if (beforeTopScreen && afterTopScreen && beforeTopScreen != afterTopScreen) { - findSharedElementsOnScreen(beforeTopScreen, BeforeOrAfter::BEFORE, propsParserContext); - findSharedElementsOnScreen(afterTopScreen, BeforeOrAfter::AFTER, propsParserContext); - hideTransitioningViews(BeforeOrAfter::BEFORE, filteredMutations, propsParserContext); - hideTransitioningViews(BeforeOrAfter::AFTER, filteredMutations, propsParserContext); + findSharedElementsOnScreen(beforeTopScreen, BEFORE, propsParserContext); + findSharedElementsOnScreen(afterTopScreen, AFTER, propsParserContext); + hideTransitioningViews(BEFORE, filteredMutations, propsParserContext); + hideTransitioningViews(AFTER, filteredMutations, propsParserContext); for (auto &[sharedTag, transition] : transitions_) { auto &[before, after] = transition.snapshot; const auto &transform = transition.transform; - overrideTransform(before, transform[static_cast(BeforeOrAfter::BEFORE)], propsParserContext); - overrideTransform(after, transform[static_cast(BeforeOrAfter::AFTER)], propsParserContext); + overrideTransform(before, transform[BEFORE], propsParserContext); + overrideTransform(after, transform[AFTER], propsParserContext); auto containerTag = getOrCreateContainer(before, sharedTag, filteredMutations, surfaceId); transferConfigToContainer(containerTag, before.tag); - restoreMap_[containerTag][static_cast(BeforeOrAfter::BEFORE)] = before.tag; - restoreMap_[containerTag][static_cast(BeforeOrAfter::AFTER)] = after.tag; + restoreMap_[containerTag][BEFORE] = before.tag; + restoreMap_[containerTag][AFTER] = after.tag; before.tag = containerTag; after.tag = containerTag; activeTransitions_.insert(containerTag); @@ -161,9 +161,9 @@ void LayoutAnimationsProxy_Experimental::handleProgressTransition( } else if (transitionState_ == TransitionState::END || transitionState_ == TransitionState::CANCELLED) { for (auto tag : activeTransitions_) { sharedContainersToRemove_.push_back(tag); - tagsToRestore_.push_back(restoreMap_[tag][static_cast(BeforeOrAfter::AFTER)]); + tagsToRestore_.push_back(restoreMap_[tag][AFTER]); if (transitionState_ == TransitionState::CANCELLED) { - tagsToRestore_.push_back(restoreMap_[tag][static_cast(BeforeOrAfter::BEFORE)]); + tagsToRestore_.push_back(restoreMap_[tag][BEFORE]); } } if (transitionState_ == TransitionState::END) { @@ -247,8 +247,8 @@ void LayoutAnimationsProxy_Experimental::handleSharedTransitionsStart( for (auto &[sharedTag, transition] : transitions_) { auto &[before, after] = transition.snapshot; const auto &transform = transition.transform; - overrideTransform(before, transform[static_cast(BeforeOrAfter::BEFORE)], propsParserContext); - overrideTransform(after, transform[static_cast(BeforeOrAfter::AFTER)], propsParserContext); + overrideTransform(before, transform[BEFORE], propsParserContext); + overrideTransform(after, transform[AFTER], propsParserContext); auto containerTag = getOrCreateContainer(before, sharedTag, filteredMutations, surfaceId); transferConfigToContainer(containerTag, before.tag); @@ -269,7 +269,7 @@ void LayoutAnimationsProxy_Experimental::handleSharedTransitionsStart( after.tag = containerTag; const auto &la = layoutAnimations_[containerTag]; if (la.finalView.layoutMetrics != after.layoutMetrics) { - overrideTransform(after, transition.transform[static_cast(BeforeOrAfter::AFTER)], propsParserContext); + overrideTransform(after, transition.transform[AFTER], propsParserContext); startSharedTransition(containerTag, la.currentView, after, surfaceId); } } From 2a88a879e444754859b01afbaa6e730740970f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= Date: Thu, 19 Mar 2026 17:35:25 +0100 Subject: [PATCH 9/9] chore: amend clang-tidy CI --- .github/workflows/lint-clang-tidy.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/lint-clang-tidy.yml b/.github/workflows/lint-clang-tidy.yml index c022d6e7c0b5..3c305a0df82d 100644 --- a/.github/workflows/lint-clang-tidy.yml +++ b/.github/workflows/lint-clang-tidy.yml @@ -7,6 +7,7 @@ on: - main paths: - '.github/workflows/lint-clang-tidy.yml' + - 'scripts/clang-tidy-lint.sh' merge_group: branches: @@ -15,6 +16,7 @@ on: pull_request: paths: - '.github/workflows/lint-clang-tidy.yml' + - 'scripts/clang-tidy-lint.sh' workflow_call: workflow_dispatch: @@ -30,12 +32,9 @@ jobs: - name: Install monorepo node dependencies run: yarn install --immutable - - name: Build Worklets package - run: yarn workspace react-native-worklets build - - name: Build Reanimated package - run: yarn workspace react-native-reanimated build - name: Clang-tidy lint Worklets run: yarn workspace react-native-worklets lint:clang-tidy + - name: Clang-tidy lint Reanimated run: yarn workspace react-native-reanimated lint:clang-tidy