Skip to content

Commit ea0bc54

Browse files
zhongwuzwcipolleschi
authored andcommittedFeb 6, 2025
Fabric: Fixes animations strict weak ordering sorted check failed (#46582)
Summary: Fixes #46568 . cc cipolleschi ## Changelog: [IOS] [FIXED] - Fabric: Fixes animations strict weak ordering sorted check failed Pull Request resolved: #46582 Test Plan: See issue in #46568 ## Repro steps - Install Xcode 16.0 - navigate to react-native-github - yarn install - cd packages/rn-tester - bundle install - RCT_NEW_ARCH_ENABLED=1 bundle exec pod install open RNTesterPods.xcworkspace to open Xcode {F1885373361} Testing with Reproducer from OSS | Paper | Fabric (With Fix) | |--------|-----------------| | {F1885395747} | {F1885395870} | Android - LayoutAnimation (Looks like it has been broken and not working way before this changes.) https://pxl.cl/5DGVv Reviewed By: cipolleschi Differential Revision: D63399017 Pulled By: realsoelynn fbshipit-source-id: aaf4ac2884ccca2da7e90a52a8ef10df6ae4fc8a
1 parent dbffbf7 commit ea0bc54

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed
 

‎packages/react-native/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -794,10 +794,7 @@ LayoutAnimationKeyFrameManager::pullTransaction(
794794
finalConflictingMutations.end(),
795795
&shouldFirstComeBeforeSecondMutation);
796796

797-
std::stable_sort(
798-
immediateMutations.begin(),
799-
immediateMutations.end(),
800-
&shouldFirstComeBeforeSecondRemovesOnly);
797+
handleShouldFirstComeBeforeSecondRemovesOnly(immediateMutations);
801798

802799
animation.keyFrames = keyFramesToAnimate;
803800
inflightAnimations_.push_back(std::move(animation));

‎packages/react-native/ReactCommon/react/renderer/animations/utils.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,40 @@ static inline bool shouldFirstComeBeforeSecondRemovesOnly(
2424
(lhs.index > rhs.index);
2525
}
2626

27+
static inline void handleShouldFirstComeBeforeSecondRemovesOnly(
28+
ShadowViewMutation::List& list) noexcept {
29+
std::unordered_map<std::string, std::vector<ShadowViewMutation>>
30+
removeMutationsByTag;
31+
ShadowViewMutation::List finalList;
32+
for (auto& mutation : list) {
33+
if (mutation.type == ShadowViewMutation::Type::Remove) {
34+
auto key = std::to_string(mutation.parentShadowView.tag);
35+
removeMutationsByTag[key].push_back(mutation);
36+
} else {
37+
finalList.push_back(mutation);
38+
}
39+
}
40+
41+
if (removeMutationsByTag.size() == 0) {
42+
return;
43+
}
44+
45+
for (auto& mutationsPair : removeMutationsByTag) {
46+
if (mutationsPair.second.size() > 1) {
47+
std::stable_sort(
48+
mutationsPair.second.begin(),
49+
mutationsPair.second.end(),
50+
&shouldFirstComeBeforeSecondRemovesOnly);
51+
}
52+
finalList.insert(
53+
finalList.begin(),
54+
mutationsPair.second.begin(),
55+
mutationsPair.second.end());
56+
}
57+
58+
list = finalList;
59+
}
60+
2761
static inline bool shouldFirstComeBeforeSecondMutation(
2862
const ShadowViewMutation& lhs,
2963
const ShadowViewMutation& rhs) noexcept {
@@ -55,6 +89,17 @@ static inline bool shouldFirstComeBeforeSecondMutation(
5589
lhs.type == ShadowViewMutation::Type::Insert) {
5690
return false;
5791
}
92+
93+
// Remove comes before Update
94+
if (lhs.type == ShadowViewMutation::Type::Remove &&
95+
rhs.type == ShadowViewMutation::Type::Update) {
96+
return true;
97+
}
98+
if (rhs.type == ShadowViewMutation::Type::Remove &&
99+
lhs.type == ShadowViewMutation::Type::Update) {
100+
return false;
101+
}
102+
58103
} else {
59104
// Make sure that removes on the same level are sorted - highest indices
60105
// must come first.

0 commit comments

Comments
 (0)
Please sign in to comment.