Skip to content

Commit bbb39c6

Browse files
authored
cherry-pick(4.3-stable): guard StaticPropsRegistry against cross-thread access (#9495) (#9867)
## Summary Cherry-picking for Reanimated 4.3.2 release - #9495 #9489/#9495 don't apply to 4.3 wholesale, so this ports just the `StaticPropsRegistry` part - it was the only registry still left without a lock. Adds a mutex around its map, matching the per-registry locking 4.3 already uses.
1 parent a722ad6 commit bbb39c6

2 files changed

Lines changed: 22 additions & 4 deletions

File tree

packages/react-native-reanimated/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,26 @@ namespace reanimated::css {
77
void StaticPropsRegistry::set(jsi::Runtime &rt, const Tag viewTag, const jsi::Value &props) {
88
if (props.isNull() || props.isUndefined()) {
99
remove(viewTag);
10-
} else {
11-
const auto newProps = dynamicFromValue(rt, props);
12-
if (has(viewTag)) {
13-
notifyObservers(viewTag, get(viewTag), newProps);
10+
return;
11+
}
12+
13+
const auto newProps = dynamicFromValue(rt, props);
14+
folly::dynamic oldProps;
15+
{
16+
std::lock_guard<std::mutex> lock{mutex_};
17+
const auto it = registry_.find(viewTag);
18+
if (it != registry_.end()) {
19+
oldProps = it->second;
1420
}
1521
registry_[viewTag] = newProps;
1622
}
23+
if (!oldProps.isNull()) {
24+
notifyObservers(viewTag, oldProps, newProps);
25+
}
1726
}
1827

1928
folly::dynamic StaticPropsRegistry::get(const Tag viewTag) const {
29+
std::lock_guard<std::mutex> lock{mutex_};
2030
auto it = registry_.find(viewTag);
2131
if (it == registry_.end()) {
2232
return nullptr;
@@ -25,14 +35,17 @@ folly::dynamic StaticPropsRegistry::get(const Tag viewTag) const {
2535
}
2636

2737
bool StaticPropsRegistry::has(const Tag viewTag) const {
38+
std::lock_guard<std::mutex> lock{mutex_};
2839
return registry_.find(viewTag) != registry_.end();
2940
}
3041

3142
void StaticPropsRegistry::remove(const Tag viewTag) {
43+
std::lock_guard<std::mutex> lock{mutex_};
3244
registry_.erase(viewTag);
3345
}
3446

3547
bool StaticPropsRegistry::isEmpty() const {
48+
std::lock_guard<std::mutex> lock{mutex_};
3649
return registry_.empty() && observers_.empty();
3750
}
3851

packages/react-native-reanimated/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <react/renderer/core/ShadowNode.h>
44

5+
#include <mutex>
56
#include <unordered_map>
67

78
namespace reanimated::css {
@@ -24,6 +25,10 @@ class StaticPropsRegistry {
2425
void removeObserver(Tag viewTag);
2526

2627
private:
28+
/// registry_ is written on the JS thread (setViewStyle) and read on the UI
29+
/// thread during interpolation and on the commit/mount thread during node
30+
/// removals, so it needs its own guard. observers_ is JS-thread-only.
31+
mutable std::mutex mutex_;
2732
std::unordered_map<Tag, folly::dynamic> registry_;
2833
std::unordered_map<Tag, PropsObserver> observers_;
2934

0 commit comments

Comments
 (0)