react-native-reanimated 4.7.0 → 4.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp +34 -2
- package/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.h +15 -1
- package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +9 -0
- package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +3 -0
- package/Common/cpp/reanimated/Fabric/updates/SynchronousWritesTracker.cpp +103 -0
- package/Common/cpp/reanimated/Fabric/updates/SynchronousWritesTracker.h +74 -0
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.cpp +15 -0
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.h +5 -0
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.cpp +10 -0
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.h +3 -0
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.cpp +97 -54
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.h +5 -1
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.cpp +23 -5
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h +17 -1
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp +9 -9
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h +35 -8
- package/Common/cpp/reanimated/LayoutAnimations/PropsDiffer.h +2 -2
- package/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp +11 -11
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +75 -2
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +11 -1
- package/Common/cpp/reanimated/Tools/PlatformDepMethodsHolder.h +4 -1
- package/android/src/main/cpp/reanimated/android/NativeProxy.cpp +13 -3
- package/android/src/main/cpp/reanimated/android/NativeProxy.h +2 -0
- package/android/src/main/java/com/swmansion/reanimated/NativeProxy.kt +84 -9
- package/android/src/main/java/com/swmansion/reanimated/NodesManager.kt +2 -4
- package/android/src/main/java/com/swmansion/reanimated/nativeProxy/EventHandler.kt +4 -3
- package/android/src/main/java/com/swmansion/reanimated/sensor/ReanimatedSensor.kt +1 -1
- package/android/src/main/java/com/swmansion/reanimated/sensor/ReanimatedSensorListener.kt +44 -33
- package/apple/reanimated/apple/REASynchronousPropsRewriter.h +18 -0
- package/apple/reanimated/apple/REASynchronousPropsRewriter.mm +37 -0
- package/apple/reanimated/apple/ReanimatedModule.mm +7 -0
- package/apple/reanimated/apple/keyboardObserver/REAKeyboardEventObserver.mm +20 -3
- package/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.mm +24 -1
- package/lib/module/animation/timing.js +15 -2
- package/lib/module/animation/timing.js.map +1 -1
- package/lib/module/platform-specific/jsVersion.js +1 -1
- package/lib/typescript/animation/timing.d.ts.map +1 -1
- package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
- package/package.json +3 -1
- package/src/animation/timing.ts +20 -2
- package/src/platform-specific/jsVersion.ts +1 -1
|
@@ -16,11 +16,13 @@ ReanimatedCommitHook::ReanimatedCommitHook(
|
|
|
16
16
|
const std::shared_ptr<UIManager> &uiManager,
|
|
17
17
|
const std::shared_ptr<UpdatesRegistryManager> &updatesRegistryManager,
|
|
18
18
|
const std::shared_ptr<css::ViewStylesRepository> &viewStylesRepository,
|
|
19
|
-
const std::shared_ptr<LayoutAnimationsProxyRegistry> &layoutAnimationsProxyRegistry
|
|
19
|
+
const std::shared_ptr<LayoutAnimationsProxyRegistry> &layoutAnimationsProxyRegistry,
|
|
20
|
+
const std::shared_ptr<SynchronousWritesTracker> &synchronousWritesTracker)
|
|
20
21
|
: uiManager_(uiManager),
|
|
21
22
|
updatesRegistryManager_(updatesRegistryManager),
|
|
22
23
|
viewStylesRepository_(viewStylesRepository),
|
|
23
|
-
layoutAnimationsProxyRegistry_(layoutAnimationsProxyRegistry)
|
|
24
|
+
layoutAnimationsProxyRegistry_(layoutAnimationsProxyRegistry),
|
|
25
|
+
synchronousWritesTracker_(synchronousWritesTracker) {
|
|
24
26
|
uiManager_->registerCommitHook(*this);
|
|
25
27
|
uiManager_->getShadowTreeRegistry().enumerate(
|
|
26
28
|
[this](const ShadowTree &shadowTree, bool & /*stop*/) { registerLayoutAnimations(shadowTree); });
|
|
@@ -57,6 +59,9 @@ RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
|
|
|
57
59
|
// A stopping surface commits an empty root; its mount is not reported on a paused Android host.
|
|
58
60
|
auto lock = updatesRegistryManager_->lock();
|
|
59
61
|
viewStylesRepository_->removeSurface(shadowTree.getSurfaceId());
|
|
62
|
+
if (synchronousWritesTracker_) {
|
|
63
|
+
synchronousWritesTracker_->onSurfaceStop(shadowTree.getSurfaceId());
|
|
64
|
+
}
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
auto reaShadowNode = std::reinterpret_pointer_cast<ReanimatedCommitShadowNode>(newRootShadowNode);
|
|
@@ -66,6 +71,7 @@ RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
|
|
|
66
71
|
// the updates registry manager
|
|
67
72
|
reaShadowNode->unsetReanimatedCommitTrait();
|
|
68
73
|
reaShadowNode->setReanimatedMountTrait();
|
|
74
|
+
trackCommit(newRootShadowNode, false);
|
|
69
75
|
return newRootShadowNode;
|
|
70
76
|
}
|
|
71
77
|
|
|
@@ -74,6 +80,7 @@ RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
|
|
|
74
80
|
// which means that all animation changes are already included.
|
|
75
81
|
// Therefore, there's no need to reapply styles from the props map.
|
|
76
82
|
if (commitOptions.source != ShadowTreeCommitSource::React) {
|
|
83
|
+
trackCommit(newRootShadowNode, false);
|
|
77
84
|
return newRootShadowNode;
|
|
78
85
|
}
|
|
79
86
|
}
|
|
@@ -90,6 +97,8 @@ RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
|
|
|
90
97
|
updatesRegistryManager_->cancelCommitAfterPause();
|
|
91
98
|
|
|
92
99
|
rootNode = cloneShadowTreeWithNewProps(*rootNode, propsMap);
|
|
100
|
+
// Must share the registry lock with `collectProps`, or a write can get the epoch of a snapshot that lacks it.
|
|
101
|
+
trackCommit(rootNode, true);
|
|
93
102
|
// If the commit comes from React Native then pause commits from
|
|
94
103
|
// Reanimated since the ShadowTree to be committed by Reanimated may not
|
|
95
104
|
// include the new changes from React Native yet and all changes of animated
|
|
@@ -104,4 +113,27 @@ RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
|
|
|
104
113
|
return rootNode;
|
|
105
114
|
}
|
|
106
115
|
|
|
116
|
+
#if REACT_NATIVE_VERSION_MINOR >= 88
|
|
117
|
+
void ReanimatedCommitHook::shadowTreeDidCommit(
|
|
118
|
+
const ShadowTree &,
|
|
119
|
+
const RootShadowNode::Shared &rootShadowNode,
|
|
120
|
+
const std::vector<const LayoutableShadowNode *> &) noexcept {
|
|
121
|
+
if (synchronousWritesTracker_) {
|
|
122
|
+
synchronousWritesTracker_->onDidCommit(rootShadowNode);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
#endif
|
|
126
|
+
|
|
127
|
+
void ReanimatedCommitHook::trackCommit(const RootShadowNode::Shared &rootShadowNode, const bool carriesRegistryValues)
|
|
128
|
+
const {
|
|
129
|
+
if (!synchronousWritesTracker_) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
synchronousWritesTracker_->onWillCommit(rootShadowNode, carriesRegistryValues);
|
|
133
|
+
#if REACT_NATIVE_VERSION_MINOR < 88
|
|
134
|
+
// Before 0.88 there is no `shadowTreeDidCommit`. The root that this hook returns is the only one available.
|
|
135
|
+
synchronousWritesTracker_->onDidCommit(rootShadowNode);
|
|
136
|
+
#endif
|
|
137
|
+
}
|
|
138
|
+
|
|
107
139
|
} // namespace reanimated
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
#include <reanimated/CSS/misc/ViewStylesRepository.h>
|
|
4
|
+
#include <reanimated/Compat/ReactNativeVersionCompat.h>
|
|
5
|
+
#include <reanimated/Fabric/updates/SynchronousWritesTracker.h>
|
|
4
6
|
#include <reanimated/Fabric/updates/UpdatesRegistryManager.h>
|
|
5
7
|
#include <reanimated/LayoutAnimations/LayoutAnimationsProxyRegistry.h>
|
|
6
8
|
|
|
7
9
|
#include <react/renderer/uimanager/UIManagerCommitHook.h>
|
|
8
10
|
|
|
9
11
|
#include <memory>
|
|
12
|
+
#include <vector>
|
|
10
13
|
|
|
11
14
|
using namespace facebook::react;
|
|
12
15
|
|
|
@@ -18,7 +21,8 @@ class ReanimatedCommitHook : public UIManagerCommitHook {
|
|
|
18
21
|
const std::shared_ptr<UIManager> &uiManager,
|
|
19
22
|
const std::shared_ptr<UpdatesRegistryManager> &updatesRegistryManager,
|
|
20
23
|
const std::shared_ptr<css::ViewStylesRepository> &viewStylesRepository,
|
|
21
|
-
const std::shared_ptr<LayoutAnimationsProxyRegistry> &layoutAnimationsProxyRegistry
|
|
24
|
+
const std::shared_ptr<LayoutAnimationsProxyRegistry> &layoutAnimationsProxyRegistry,
|
|
25
|
+
const std::shared_ptr<SynchronousWritesTracker> &synchronousWritesTracker);
|
|
22
26
|
|
|
23
27
|
~ReanimatedCommitHook() noexcept override;
|
|
24
28
|
|
|
@@ -34,11 +38,21 @@ class ReanimatedCommitHook : public UIManagerCommitHook {
|
|
|
34
38
|
RootShadowNode::Unshared const &newRootShadowNode,
|
|
35
39
|
const ShadowTreeCommitOptions &commitOptions) noexcept override;
|
|
36
40
|
|
|
41
|
+
#if REACT_NATIVE_VERSION_MINOR >= 88
|
|
42
|
+
void shadowTreeDidCommit(
|
|
43
|
+
const ShadowTree &shadowTree,
|
|
44
|
+
const RootShadowNode::Shared &rootShadowNode,
|
|
45
|
+
const std::vector<const LayoutableShadowNode *> &affectedLayoutableNodes) noexcept override;
|
|
46
|
+
#endif
|
|
47
|
+
|
|
37
48
|
private:
|
|
49
|
+
void trackCommit(const RootShadowNode::Shared &rootShadowNode, bool carriesRegistryValues) const;
|
|
50
|
+
|
|
38
51
|
std::shared_ptr<UIManager> uiManager_;
|
|
39
52
|
std::shared_ptr<UpdatesRegistryManager> updatesRegistryManager_;
|
|
40
53
|
std::shared_ptr<css::ViewStylesRepository> viewStylesRepository_;
|
|
41
54
|
std::shared_ptr<LayoutAnimationsProxyRegistry> layoutAnimationsProxyRegistry_;
|
|
55
|
+
std::shared_ptr<SynchronousWritesTracker> synchronousWritesTracker_;
|
|
42
56
|
};
|
|
43
57
|
|
|
44
58
|
} // namespace reanimated
|
|
@@ -12,11 +12,13 @@ ReanimatedMountHook::ReanimatedMountHook(
|
|
|
12
12
|
const std::shared_ptr<UpdatesRegistryManager> &updatesRegistryManager,
|
|
13
13
|
const std::shared_ptr<css::ViewStylesRepository> &viewStylesRepository,
|
|
14
14
|
const std::shared_ptr<LayoutAnimationsProxyRegistry> &layoutAnimationsProxyRegistry,
|
|
15
|
+
const std::shared_ptr<SynchronousWritesTracker> &synchronousWritesTracker,
|
|
15
16
|
const std::function<void()> &requestFlush)
|
|
16
17
|
: uiManager_(uiManager),
|
|
17
18
|
updatesRegistryManager_(updatesRegistryManager),
|
|
18
19
|
viewStylesRepository_(viewStylesRepository),
|
|
19
20
|
layoutAnimationsProxyRegistry_(layoutAnimationsProxyRegistry),
|
|
21
|
+
synchronousWritesTracker_(synchronousWritesTracker),
|
|
20
22
|
requestFlush_(requestFlush) {
|
|
21
23
|
uiManager_->registerMountHook(*this);
|
|
22
24
|
}
|
|
@@ -35,6 +37,10 @@ void ReanimatedMountHook::shadowTreeDidMount(
|
|
|
35
37
|
return;
|
|
36
38
|
}
|
|
37
39
|
|
|
40
|
+
if (synchronousWritesTracker_) {
|
|
41
|
+
synchronousWritesTracker_->onMountReport(rootShadowNode);
|
|
42
|
+
}
|
|
43
|
+
|
|
38
44
|
auto reaShadowNode = std::reinterpret_pointer_cast<ReanimatedCommitShadowNode>(
|
|
39
45
|
std::const_pointer_cast<RootShadowNode>(rootShadowNode));
|
|
40
46
|
|
|
@@ -73,6 +79,9 @@ void ReanimatedMountHook::shadowTreeDidUnmount(SurfaceId surfaceId, HighResTimeS
|
|
|
73
79
|
if (layoutAnimationsProxyRegistry_) {
|
|
74
80
|
layoutAnimationsProxyRegistry_->remove(surfaceId);
|
|
75
81
|
}
|
|
82
|
+
if (synchronousWritesTracker_) {
|
|
83
|
+
synchronousWritesTracker_->onSurfaceStop(surfaceId);
|
|
84
|
+
}
|
|
76
85
|
|
|
77
86
|
auto lock = updatesRegistryManager_->lock();
|
|
78
87
|
viewStylesRepository_->removeSurface(surfaceId);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
#include <reanimated/CSS/misc/ViewStylesRepository.h>
|
|
4
4
|
#include <reanimated/Fabric/ShadowTreeCloner.h>
|
|
5
|
+
#include <reanimated/Fabric/updates/SynchronousWritesTracker.h>
|
|
5
6
|
#include <reanimated/Fabric/updates/UpdatesRegistryManager.h>
|
|
6
7
|
#include <reanimated/LayoutAnimations/LayoutAnimationsProxyRegistry.h>
|
|
7
8
|
|
|
@@ -20,6 +21,7 @@ class ReanimatedMountHook : public UIManagerMountHook {
|
|
|
20
21
|
const std::shared_ptr<UpdatesRegistryManager> &updatesRegistryManager,
|
|
21
22
|
const std::shared_ptr<css::ViewStylesRepository> &viewStylesRepository,
|
|
22
23
|
const std::shared_ptr<LayoutAnimationsProxyRegistry> &layoutAnimationsProxyRegistry,
|
|
24
|
+
const std::shared_ptr<SynchronousWritesTracker> &synchronousWritesTracker,
|
|
23
25
|
const std::function<void()> &requestFlush);
|
|
24
26
|
~ReanimatedMountHook() noexcept override;
|
|
25
27
|
|
|
@@ -32,6 +34,7 @@ class ReanimatedMountHook : public UIManagerMountHook {
|
|
|
32
34
|
const std::shared_ptr<UpdatesRegistryManager> updatesRegistryManager_;
|
|
33
35
|
const std::shared_ptr<css::ViewStylesRepository> viewStylesRepository_;
|
|
34
36
|
const std::shared_ptr<LayoutAnimationsProxyRegistry> layoutAnimationsProxyRegistry_;
|
|
37
|
+
const std::shared_ptr<SynchronousWritesTracker> synchronousWritesTracker_;
|
|
35
38
|
const std::function<void()> requestFlush_;
|
|
36
39
|
};
|
|
37
40
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#include <reanimated/Fabric/updates/SynchronousWritesTracker.h>
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
|
|
5
|
+
namespace reanimated {
|
|
6
|
+
|
|
7
|
+
void SynchronousWritesTracker::onWillCommit(
|
|
8
|
+
const RootShadowNode::Shared &rootShadowNode,
|
|
9
|
+
const bool carriesRegistryValues) {
|
|
10
|
+
auto lock = std::scoped_lock{mutex_};
|
|
11
|
+
const auto threadId = std::this_thread::get_id();
|
|
12
|
+
pendingCommits_.erase(threadId);
|
|
13
|
+
if (rootShadowNode->getChildren().empty()) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const auto surfaceId = rootShadowNode->getSurfaceId();
|
|
17
|
+
auto &surface = surfaces_[surfaceId];
|
|
18
|
+
if (carriesRegistryValues) {
|
|
19
|
+
surface.epoch++;
|
|
20
|
+
}
|
|
21
|
+
pendingCommits_.emplace(threadId, PendingCommit{surfaceId, surface.epoch});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void SynchronousWritesTracker::onDidCommit(const RootShadowNode::Shared &rootShadowNode) {
|
|
25
|
+
auto lock = std::scoped_lock{mutex_};
|
|
26
|
+
const auto pendingCommit = pendingCommits_.extract(std::this_thread::get_id());
|
|
27
|
+
if (pendingCommit.empty() || pendingCommit.mapped().surfaceId != rootShadowNode->getSurfaceId()) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const auto surfaceIt = surfaces_.find(pendingCommit.mapped().surfaceId);
|
|
31
|
+
if (surfaceIt == surfaces_.end()) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
rememberRoot(surfaceIt->second, rootShadowNode, pendingCommit.mapped().epoch);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
void SynchronousWritesTracker::rememberRoot(
|
|
38
|
+
SurfaceState &surface,
|
|
39
|
+
const RootShadowNode::Shared &rootShadowNode,
|
|
40
|
+
const Epoch epoch) {
|
|
41
|
+
auto &committedRoots = surface.committedRoots;
|
|
42
|
+
while (!committedRoots.empty() && committedRoots.front().rootShadowNode.expired()) {
|
|
43
|
+
committedRoots.pop_front();
|
|
44
|
+
}
|
|
45
|
+
committedRoots.push_back({rootShadowNode, epoch});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
void SynchronousWritesTracker::onSynchronousWrite(const UpdatesBatch &synchronousUpdatesBatch) {
|
|
49
|
+
auto lock = std::scoped_lock{mutex_};
|
|
50
|
+
for (const auto &[shadowNodeFamily, props] : synchronousUpdatesBatch) {
|
|
51
|
+
const auto surfaceIt = surfaces_.find(shadowNodeFamily->getSurfaceId());
|
|
52
|
+
if (surfaceIt == surfaces_.end() || surfaceIt->second.epoch == surfaceIt->second.mountedEpoch) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
auto &surface = surfaceIt->second;
|
|
56
|
+
surface.writes.insert_or_assign(shadowNodeFamily->getTag(), Write{shadowNodeFamily, surface.epoch});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
void SynchronousWritesTracker::onMountReport(const RootShadowNode::Shared &mountedRootShadowNode) {
|
|
61
|
+
auto lock = std::scoped_lock{mutex_};
|
|
62
|
+
const auto surfaceIt = surfaces_.find(mountedRootShadowNode->getSurfaceId());
|
|
63
|
+
if (surfaceIt == surfaces_.end()) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
auto &surface = surfaceIt->second;
|
|
67
|
+
auto &committedRoots = surface.committedRoots;
|
|
68
|
+
const auto it = std::find_if(committedRoots.begin(), committedRoots.end(), [&](const CommittedRoot &root) {
|
|
69
|
+
return root.rootShadowNode.lock() == mountedRootShadowNode;
|
|
70
|
+
});
|
|
71
|
+
if (it == committedRoots.end()) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
surface.reportedEpoch = it->epoch;
|
|
75
|
+
committedRoots.erase(committedRoots.begin(), it + 1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
void SynchronousWritesTracker::onSurfaceStop(const SurfaceId surfaceId) {
|
|
79
|
+
auto lock = std::scoped_lock{mutex_};
|
|
80
|
+
surfaces_.erase(surfaceId);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
std::vector<ShadowNodeFamily::Shared> SynchronousWritesTracker::getFamiliesToRewrite() const {
|
|
84
|
+
auto lock = std::scoped_lock{mutex_};
|
|
85
|
+
std::vector<ShadowNodeFamily::Shared> families;
|
|
86
|
+
for (const auto &[_, surface] : surfaces_) {
|
|
87
|
+
for (const auto &[tag, write] : surface.writes) {
|
|
88
|
+
families.push_back(write.shadowNodeFamily);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return families;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
void SynchronousWritesTracker::onRewrite() {
|
|
95
|
+
auto lock = std::scoped_lock{mutex_};
|
|
96
|
+
for (auto &[_, surface] : surfaces_) {
|
|
97
|
+
const auto mountedEpoch = surface.reportedEpoch;
|
|
98
|
+
surface.mountedEpoch = mountedEpoch;
|
|
99
|
+
std::erase_if(surface.writes, [mountedEpoch](const auto &entry) { return entry.second.epoch <= mountedEpoch; });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
} // namespace reanimated
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <reanimated/Fabric/updates/UpdatesRegistry.h>
|
|
4
|
+
|
|
5
|
+
#include <react/renderer/components/root/RootShadowNode.h>
|
|
6
|
+
#include <react/renderer/core/ShadowNodeFamily.h>
|
|
7
|
+
|
|
8
|
+
#include <cstdint>
|
|
9
|
+
#include <deque>
|
|
10
|
+
#include <memory>
|
|
11
|
+
#include <mutex>
|
|
12
|
+
#include <thread>
|
|
13
|
+
#include <unordered_map>
|
|
14
|
+
#include <vector>
|
|
15
|
+
|
|
16
|
+
using namespace facebook::react;
|
|
17
|
+
|
|
18
|
+
namespace reanimated {
|
|
19
|
+
|
|
20
|
+
// A React commit takes its animated values from the registries in the commit hook, but the platform can mount it
|
|
21
|
+
// after newer synchronous writes. This class keeps the views with such writes until every such commit is mounted, so
|
|
22
|
+
// that the platform can write their current values again after a mount.
|
|
23
|
+
class SynchronousWritesTracker {
|
|
24
|
+
public:
|
|
25
|
+
void onWillCommit(const RootShadowNode::Shared &rootShadowNode, bool carriesRegistryValues);
|
|
26
|
+
void onDidCommit(const RootShadowNode::Shared &rootShadowNode);
|
|
27
|
+
void onSynchronousWrite(const UpdatesBatch &synchronousUpdatesBatch);
|
|
28
|
+
void onMountReport(const RootShadowNode::Shared &mountedRootShadowNode);
|
|
29
|
+
void onSurfaceStop(SurfaceId surfaceId);
|
|
30
|
+
std::vector<ShadowNodeFamily::Shared> getFamiliesToRewrite() const;
|
|
31
|
+
void onRewrite();
|
|
32
|
+
|
|
33
|
+
private:
|
|
34
|
+
using Epoch = uint64_t;
|
|
35
|
+
|
|
36
|
+
struct CommittedRoot {
|
|
37
|
+
std::weak_ptr<const RootShadowNode> rootShadowNode;
|
|
38
|
+
Epoch epoch;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
struct Write {
|
|
42
|
+
ShadowNodeFamily::Shared shadowNodeFamily;
|
|
43
|
+
Epoch epoch;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
struct PendingCommit {
|
|
47
|
+
SurfaceId surfaceId;
|
|
48
|
+
Epoch epoch;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
struct SurfaceState {
|
|
52
|
+
// Number of commits that carried registry values. A write with epoch N is newer than the values in commits 1..N.
|
|
53
|
+
Epoch epoch{0};
|
|
54
|
+
// Android reports a mount at the pull, before the mount items run. The next mount callback writes the props
|
|
55
|
+
// again. That callback also runs for a dispatch that has only view commands. If such a dispatch runs before the
|
|
56
|
+
// mount items, the tracker removes the writes too early. The old value then stays on screen until the next
|
|
57
|
+
// synchronous write.
|
|
58
|
+
Epoch reportedEpoch{0};
|
|
59
|
+
Epoch mountedEpoch{0};
|
|
60
|
+
std::deque<CommittedRoot> committedRoots;
|
|
61
|
+
std::unordered_map<Tag, Write> writes;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
static void rememberRoot(SurfaceState &surface, const RootShadowNode::Shared &rootShadowNode, Epoch epoch);
|
|
65
|
+
|
|
66
|
+
mutable std::mutex mutex_;
|
|
67
|
+
// Carries the epoch from `onWillCommit` (known at the registry read) to `onDidCommit` (final root, after all
|
|
68
|
+
// hooks). Both run on the committing thread, but commits on different threads can overlap on one surface, so
|
|
69
|
+
// the key is the thread. A failed or cancelled commit gets no `onDidCommit`; `onWillCommit` drops its entry.
|
|
70
|
+
std::unordered_map<std::thread::id, PendingCommit> pendingCommits_;
|
|
71
|
+
std::unordered_map<SurfaceId, SurfaceState> surfaces_;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
} // namespace reanimated
|
|
@@ -37,6 +37,21 @@ void UpdatesRegistry::mergeInto(const Tag tag, folly::dynamic &target) const {
|
|
|
37
37
|
target.update(it->second.second);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
#ifdef ANDROID
|
|
41
|
+
void UpdatesRegistry::mergeInto(const Tag tag, folly::dynamic &target, const PropNamePredicate isIncluded) const {
|
|
42
|
+
react_native_assert(UpdatesRegistryManager::isLockedByCurrentThread());
|
|
43
|
+
auto it = updatesRegistry_.find(tag);
|
|
44
|
+
if (it == updatesRegistry_.cend()) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
for (const auto &[name, value] : it->second.second.items()) {
|
|
48
|
+
if (isIncluded(name.getString())) {
|
|
49
|
+
target[name] = value;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
#endif // ANDROID
|
|
54
|
+
|
|
40
55
|
void UpdatesRegistry::remove(const Tag tag) {
|
|
41
56
|
react_native_assert(UpdatesRegistryManager::isLockedByCurrentThread());
|
|
42
57
|
removeTag(tag);
|
|
@@ -29,6 +29,8 @@ struct AnimatedPropsEntry {
|
|
|
29
29
|
};
|
|
30
30
|
using UpdatesBatchAnimatedProps = std::vector<AnimatedPropsEntry>;
|
|
31
31
|
|
|
32
|
+
using PropNamePredicate = bool (*)(const std::string &);
|
|
33
|
+
|
|
32
34
|
using RegistryMap = std::unordered_map<Tag, std::pair<ShadowNodeFamily::Shared, folly::dynamic>>;
|
|
33
35
|
|
|
34
36
|
#ifdef ANDROID
|
|
@@ -48,6 +50,9 @@ class UpdatesRegistry {
|
|
|
48
50
|
virtual bool isEmpty() const;
|
|
49
51
|
folly::dynamic get(Tag tag) const;
|
|
50
52
|
void mergeInto(Tag tag, folly::dynamic &target) const;
|
|
53
|
+
#ifdef ANDROID
|
|
54
|
+
void mergeInto(Tag tag, folly::dynamic &target, PropNamePredicate isIncluded) const;
|
|
55
|
+
#endif
|
|
51
56
|
void remove(Tag tag);
|
|
52
57
|
|
|
53
58
|
#ifdef ANDROID
|
|
@@ -115,6 +115,16 @@ void UpdatesRegistryManager::mergeRegistryProps(const Tag viewTag, folly::dynami
|
|
|
115
115
|
|
|
116
116
|
#ifdef ANDROID
|
|
117
117
|
|
|
118
|
+
void UpdatesRegistryManager::mergeRegistryProps(
|
|
119
|
+
const Tag viewTag,
|
|
120
|
+
folly::dynamic &target,
|
|
121
|
+
const PropNamePredicate isIncluded) {
|
|
122
|
+
react_native_assert(isLockedByCurrentThread());
|
|
123
|
+
for (const auto ®istry : registries_) {
|
|
124
|
+
registry->mergeInto(viewTag, target, isIncluded);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
118
128
|
bool UpdatesRegistryManager::hasPropsToRevert() {
|
|
119
129
|
react_native_assert(isLockedByCurrentThread());
|
|
120
130
|
for (auto ®istry : registries_) {
|
|
@@ -49,6 +49,9 @@ class UpdatesRegistryManager {
|
|
|
49
49
|
void handleNodeRemovals(const RootShadowNode &rootShadowNode);
|
|
50
50
|
PropsMap collectProps();
|
|
51
51
|
void mergeRegistryProps(Tag viewTag, folly::dynamic &target);
|
|
52
|
+
#ifdef ANDROID
|
|
53
|
+
void mergeRegistryProps(Tag viewTag, folly::dynamic &target, PropNamePredicate isIncluded);
|
|
54
|
+
#endif
|
|
52
55
|
|
|
53
56
|
#ifdef ANDROID
|
|
54
57
|
bool hasPropsToRevert();
|