Skip to content

Commit 0102d21

Browse files
Bartlomiej Bloniarzfacebook-github-bot
authored andcommitted
Sync on js thread after animation finished (#54877)
Summary: This diff adds synchronizing props to react, through a scheduled commit on the js thread. This is used by animated at the end of the animation, and leverages RSNRU to actually push the update to reactjs. Differential Revision: D89042949
1 parent 81044d7 commit 0102d21

File tree

6 files changed

+38
-16
lines changed

6 files changed

+38
-16
lines changed

packages/react-native/Libraries/Animated/__tests__/AnimatedBackend-itest.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,6 @@ test('animated opacity', () => {
7070
_opacityAnimation?.stop();
7171
});
7272

73-
// TODO: T246961305 rendered output should be <rn-view opacity="0" /> at this point
74-
expect(root.getRenderedOutput({props: ['opacity']}).toJSX()).toEqual(
75-
<rn-view />,
76-
);
77-
78-
// Re-render
79-
Fantom.runTask(() => {
80-
root.render(<MyApp />);
81-
});
82-
8373
expect(root.getRenderedOutput({props: ['opacity']}).toJSX()).toEqual(
8474
<rn-view opacity="0" />,
8575
);

packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,9 @@ void NativeAnimatedNodesManager::schedulePropsCommit(
909909
bool layoutStyleUpdated,
910910
bool forceFabricCommit) noexcept {
911911
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
912+
if (forceFabricCommit) {
913+
shouldRequestAsyncFlush_ = true;
914+
}
912915
if (layoutStyleUpdated) {
913916
mergeObjects(updateViewProps_[viewTag], props);
914917
} else {
@@ -962,7 +965,7 @@ AnimationMutations NativeAnimatedNodesManager::pullAnimationMutations() {
962965
task();
963966
}
964967

965-
AnimationMutations mutations;
968+
AnimationMutations mutations{};
966969

967970
// Step through the animation loop
968971
if (isAnimationUpdateNeeded()) {
@@ -1105,6 +1108,8 @@ AnimationMutations NativeAnimatedNodesManager::pullAnimationMutations() {
11051108
// There is no active animation. Stop the render callback.
11061109
stopRenderCallbackIfNeeded(false);
11071110
}
1111+
mutations.shouldRequestAsyncFlush = shouldRequestAsyncFlush_;
1112+
shouldRequestAsyncFlush_ = false;
11081113
return mutations;
11091114
}
11101115
#endif

packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ class NativeAnimatedNodesManager {
260260

261261
std::unordered_map<Tag, folly::dynamic> updateViewProps_{};
262262
std::unordered_map<Tag, folly::dynamic> updateViewPropsDirect_{};
263+
bool shouldRequestAsyncFlush_{false};
263264

264265
mutable std::mutex tagToShadowNodeFamilyMutex_;
265266
std::unordered_map<Tag, std::weak_ptr<const ShadowNodeFamily>> tagToShadowNodeFamily_{};

packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManagerProvider.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ NativeAnimatedNodesManagerProvider::getOrCreate(
9595
std::move(stopOnRenderCallback_),
9696
std::move(directManipulationCallback),
9797
std::move(fabricCommitCallback),
98-
uiManager);
98+
uiManager,
99+
jsInvoker);
99100

100101
nativeAnimatedNodesManager_ =
101102
std::make_shared<NativeAnimatedNodesManager>(animationBackend_);

packages/react-native/ReactCommon/react/renderer/animationbackend/AnimationBackend.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,25 @@ AnimationBackend::AnimationBackend(
5555
StopOnRenderCallback&& stopOnRenderCallback,
5656
DirectManipulationCallback&& directManipulationCallback,
5757
FabricCommitCallback&& fabricCommitCallback,
58-
UIManager* uiManager)
58+
UIManager* uiManager,
59+
std::shared_ptr<CallInvoker> jsInvoker)
5960
: startOnRenderCallback_(std::move(startOnRenderCallback)),
6061
stopOnRenderCallback_(std::move(stopOnRenderCallback)),
6162
directManipulationCallback_(std::move(directManipulationCallback)),
6263
fabricCommitCallback_(std::move(fabricCommitCallback)),
6364
animatedPropsRegistry_(std::make_shared<AnimatedPropsRegistry>()),
6465
uiManager_(uiManager),
66+
jsInvoker_(std::move(jsInvoker)),
6567
commitHook_(uiManager, animatedPropsRegistry_) {}
6668

6769
void AnimationBackend::onAnimationFrame(double timestamp) {
6870
std::unordered_map<SurfaceId, SurfaceUpdates> surfaceUpdates;
71+
bool shouldRequestAsyncFlush = false;
6972

7073
for (auto& callback : callbacks) {
71-
auto muatations = callback(static_cast<float>(timestamp));
72-
for (auto& mutation : muatations.batch) {
74+
auto mutations = callback(static_cast<float>(timestamp));
75+
shouldRequestAsyncFlush |= mutations.shouldRequestAsyncFlush;
76+
for (auto& mutation : mutations.batch) {
7377
const auto family = mutation.family;
7478
react_native_assert(family != nullptr);
7579

@@ -90,6 +94,22 @@ void AnimationBackend::onAnimationFrame(double timestamp) {
9094
synchronouslyUpdateProps(surfaceUpdates.propsMap);
9195
}
9296
}
97+
98+
if (shouldRequestAsyncFlush) {
99+
// for (const auto& [surfaceId, _] : surfaceUpdates) {
100+
jsInvoker_->invokeAsync([this]() {
101+
uiManager_->getShadowTreeRegistry().enumerate(
102+
[](const ShadowTree& shadowTree, bool& stop) {
103+
shadowTree.commit(
104+
[](const RootShadowNode& oldRootShadowNode) {
105+
return std::static_pointer_cast<RootShadowNode>(
106+
oldRootShadowNode.ShadowNode::clone({}));
107+
},
108+
{.source = ShadowTreeCommitSource::React});
109+
});
110+
});
111+
// }
112+
}
93113
}
94114

95115
void AnimationBackend::start(const Callback& callback, bool isAsync) {

packages/react-native/ReactCommon/react/renderer/animationbackend/AnimationBackend.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77

88
#pragma once
99

10+
#include <ReactCommon/CallInvoker.h>
1011
#include <folly/dynamic.h>
1112
#include <react/renderer/core/ReactPrimitives.h>
1213
#include <react/renderer/uimanager/UIManager.h>
1314
#include <react/renderer/uimanager/UIManagerAnimationBackend.h>
1415
#include <functional>
16+
#include <memory>
1517
#include <vector>
1618
#include "AnimatedProps.h"
1719
#include "AnimatedPropsBuilder.h"
@@ -41,6 +43,7 @@ struct AnimationMutation {
4143

4244
struct AnimationMutations {
4345
std::vector<AnimationMutation> batch;
46+
bool shouldRequestAsyncFlush{false};
4447
};
4548

4649
class AnimationBackend : public UIManagerAnimationBackend {
@@ -58,14 +61,16 @@ class AnimationBackend : public UIManagerAnimationBackend {
5861
const FabricCommitCallback fabricCommitCallback_;
5962
std::shared_ptr<AnimatedPropsRegistry> animatedPropsRegistry_;
6063
UIManager *uiManager_;
64+
std::shared_ptr<CallInvoker> jsInvoker_;
6165
AnimationBackendCommitHook commitHook_;
6266

6367
AnimationBackend(
6468
StartOnRenderCallback &&startOnRenderCallback,
6569
StopOnRenderCallback &&stopOnRenderCallback,
6670
DirectManipulationCallback &&directManipulationCallback,
6771
FabricCommitCallback &&fabricCommitCallback,
68-
UIManager *uiManager);
72+
UIManager *uiManager,
73+
std::shared_ptr<CallInvoker> jsInvoker);
6974
void commitUpdates(SurfaceId surfaceId, SurfaceUpdates &surfaceUpdates);
7075
void synchronouslyUpdateProps(const std::unordered_map<Tag, AnimatedProps> &updates);
7176
void clearRegistry(SurfaceId surfaceId) override;

0 commit comments

Comments
 (0)