Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52081
changelog: [internal]
# The problem in Java and Obj-C Native Animated
--------------------
Event based animations in Native Animated have one big problem: detecting when the gesture is completed. This has led to number of bugs over the years that manifest as Pressable's onPress not triggering. The root cause of the problem is disconnect between where a piece of UI is on the screen and where Fabric thinks it is. Fabric is used for hit testing, and other things like intersection observing, and if Fabric does not have up to date values, weird things start happening.
This diff implements completion detection for event based animations. Unlike previous solutions, it does not depend on sequence of events nor it uses React setState to update shadow tree.
# Completion Detection
--------------------
The key mechanism for marking event animations as completed is in the `onRender` method:
- After processing animations, if `onAnimationFrame` returns false - indicating no UI changes, the system assumes all event-driven animations have completed.
- it then:
* Collects all animated value nodes connected to event drivers.
* Updates all nodes connected to these "finished" animations.
* isEventAnimationInProgress_ to false.
* Commits final property values to the UI.
The benefits over the previous solution:
- It works across all platforms without the need to emit "completion events".
- It uses a UI frame that wouldn't animate anything to do syncing work. Using main thread IDLE time towards bookkeeping.
- No need to call into JavaScript for synchronisation.
Reviewed By: zeyap
Differential Revision: D76743467
fbshipit-source-id: b21ab5ef9c71ff93fd0250e6af6b22ded395be8d
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52062
changelog: [internal]
- update comments to be more descriptive.
- use `#pragma mark -` to better group methods in `NativeAnimatedNodesManager`. It is nicely formatted in VSCode.
{F1979345410}
Reviewed By: mdvacca
Differential Revision: D76737257
fbshipit-source-id: c4b22ca45cd5dec2c72e7931bfec4466cda3070c
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52012
changelog: [internal]
On iOS, once a prop on a view is controlled by animated, the control is never released to Fabric or React. That's why it is important to use direct manipulation to commit even final value.
Reviewed By: lenaic
Differential Revision: D76601913
fbshipit-source-id: ea02219e158f28977018b34ac7152b899723b35a
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51922
changelog: [internal]
fix existing C++ Animated tests and align with Android on how to go from current time to applied frame.
On iOS [floor](https://fburl.com/code/7zy5e5ul) is used to decide which frame to apply. On Android, [round](https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/FrameBasedAnimationDriver.kt#L65) is used.
In D75813200 I chose to use `std::ceil` as I wanted to have a predictable behaviour in tests. This is not wrong but it is better to align at least with one of the existing implementations. Let's go with Android as it strikes the balance of what we want to see in tests (an animation that is running for 1000ms should finish after 1000ms, not 1000ms + one frame) and C++ Animated is closer to at least one of the existing implementations.
Reviewed By: christophpurrer
Differential Revision: D76337384
fbshipit-source-id: 444c94d88c2fa60bb4f0649f57e0e42f5cd27626
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51802
changelog: [internal]
avoid conversions when dealing with time in C++ Animated. This makes tests more predictable.
Reviewed By: christophpurrer
Differential Revision: D75813200
fbshipit-source-id: b8934848237e5ea7c350d9a5f0175ac0f9202ffd
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51750
changelog: [internal]
inline call `onRender()` instead of calling it from `startRenderCallbackIfNeeded`. This has identical functionality but allows to use Fantom to test C++ Animated. In Fantom, there is only one thread the existing mechanism in C++ Animated uses thread locals to capture which thread in the UI thread. Therefore, some assumptions are broken. This is just an easy workaround around the problem.
Reviewed By: javache, zeyap
Differential Revision: D75787084
fbshipit-source-id: 8d70ef2d13e4ab14807deb7ca4cb0844980f5901
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51749
changelog: [internal]
Make it possible to inject time via `now` argument to C++ Animated. This will be used in testing.
Reviewed By: javache
Differential Revision: D75710463
fbshipit-source-id: 2d6da875c7379c4b229f8b7af0fa665cebc2ca8b
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51743
Noticed some of these were missing, which may lose us useful test signal, or prevent tests from being ran at all.
Changelog: [Internal]
Reviewed By: sammy-SC
Differential Revision: D75789456
fbshipit-source-id: 75645866c672c77d3dac34383105955ef6d25e60
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51705
changelog: [internal]
use if/else instead of unordered_map to map types of nodes/drivers from string to a class. This is faster and improves binary size.
Reviewed By: javache
Differential Revision: D75676701
fbshipit-source-id: be9b8b646ebd9472382e6f692768b8fe9703d88f
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51697
changelog: [internal]
as a general rule of thumb, do not call outside of your class when holding a mutex. It is easy to cause a deadlock because the outside code may end up trying to acquire the mutex down the stack, leading to deadlock.
Here, it happens because `startRenderCallbackIfNeeded` may end up calling onRender and in onRender, we try to acquire the mutex again
Reviewed By: javache
Differential Revision: D75675465
fbshipit-source-id: 46168ee154a54ae5cccaa74728b41f027519db59
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51674
changelog: [internal]
just a clean up of code in AnimationDriverUtils and removal of unused headers.
Reviewed By: mdvacca
Differential Revision: D75549612
fbshipit-source-id: a8ad63622478d06318b6304b886554478b43d19b
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51616
changelog: [internal]
doesn't seem to be used by anything. let's delete it.
Reviewed By: javache
Differential Revision: D75218695
fbshipit-source-id: eeb3a826f06456be8de6941fa95d6ffc7917dcf8
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51615
changelog: [internal]
rename methods to reflect that they are getters and mark them as noexcept const
Reviewed By: rshest
Differential Revision: D75217535
fbshipit-source-id: c7d77060d0f54f8043a7552eec7e2b231cb5b7bf
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51611
changelog: [internal]
AnimationDriver does not use enable_shared_from_this, let's remove it. Also mark a few methods as noexcept and const.
This helps with C++ binary size.
Reviewed By: rshest
Differential Revision: D75172851
fbshipit-source-id: d6552cd577371a51c3fa3b394b451d7ed2b61e44
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51610
changelog: [internal]
No need to store uiManagerBinding in a shared_ptr. Let's just get it, pass it to classes that need it and not store it.
This helps with C++ binary size a little bit.
Reviewed By: rshest
Differential Revision: D75174567
fbshipit-source-id: 1d4e5a9f89ba2f2d2eb733eac9d103ee97550d0f
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51609
changelog: [internal]
NativeAnimatedNodesManagerProvider is not subclassed. Let's remove virtual methods and make it a final class.
Reviewed By: lenaic
Differential Revision: D75169108
fbshipit-source-id: 32121cf372ba94c8a7b86c61fd96efd75560f789
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51605
changelog: [internal]
folly::dynamic can be constructed with nullptr and it creates a null folly::dynamic. Let's use that to indicate missing value instead of std::optional to lower C++ binary size.
Reviewed By: rshest
Differential Revision: D75174590
fbshipit-source-id: f2dfef00975686f6ac4c14b42539e700e967075b
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51606
changelog: [internal]
When native module is destroyed, ui queue is also torn down.
this helps with C++ binary size a little bit
Reviewed By: rshest
Differential Revision: D75149437
fbshipit-source-id: 1df061db26b4fb5026114e00bbc6846bf38d83a9
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51589
changelog: [internal]
With D75140890, there is a guarantee that `startOnRenderCallback_` won't be called after the owning class is destroyed.
There shouldn't be any events flowing through Fabric when the RN instance is torn down. Passing this to eventEmitterListener_ should be safe.
This helps with C++ binary size a little bit.
Reviewed By: rshest
Differential Revision: D75148616
fbshipit-source-id: 5110736c2ddcff738fce395bd0b9844d44e8dcb2
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51588
changelog: [internal]
AnimatedNode never outlive NativeAnimatedNodesManager. We can safely use raw pointer here instead of shared_ptr.
This improves a C++ binary size a little bit.
Reviewed By: rshest
Differential Revision: D75148487
fbshipit-source-id: 4c2f6dc6e4de670be37dd3b65dc3a8d63d546150
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51587
changelog: [internal]
use unique_ptr instead of shared_ptr to manage memory of activeAnimations_.
Active animations are only owned by NativeAnimatedNodesManager and their ownership isn't shared with any other class.
This saves a little bit of C++ binary size.
Reviewed By: rshest
Differential Revision: D75142643
fbshipit-source-id: c09753b68e70e95fedcb7b2b8fb19a0fd7010059
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51586
changelog: [internal]
using shared_ptr here is not necessary because AnimatedNodes are not shared between multiple entities, they are only owned by NativeAnimatedNodesManager.
This saves a little bit C++ binary size.
Reviewed By: rshest
Differential Revision: D75148952
fbshipit-source-id: 18b8231061cda970ad96842ee6ca3135c2ec5d68
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51563
changelog: [internal]
Throwing errors in C++ is expensive and slow. Let's replace it with logging.
This is to reduce binary size of C++ Animated.
Reviewed By: mdvacca
Differential Revision: D75140875
fbshipit-source-id: 32909572141d8e1b51b60f317716f783aa760265
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51558
changelog: [internal]
we must call stopRenderCallbackIfNeeded to prevent UI tick from being called when
`NativeAnimatedNodesManager` is deallocated.
Reviewed By: mdvacca
Differential Revision: D75140890
fbshipit-source-id: 9ad32956a877f9ee8256790ba32cb5982a5b0c2f
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50936
D63141469 introduced an option to use HSR Core's trace macros for profiling react. I believe this was to enable Tracy support. However, the consequence of this is that hsr core is statically linked twice into Worlds, once in libclient_server_android.so and once into libxplat_js_react-native-github_packages_react-native_ReactCxxPlatform_react_profiling_profiling.so.
It isn't obvious that this causes any problems, but it does result in some weirdness with regard to symbol interposition between the two shared libraries. Some tracing categories are registered twice in hz_tracing, for example.
Since the HSR Core macros call directly through to hz_tracing, this change simply replaces the HSR Core dependency with an equivalent hz_tracing dependency.
Reviewed By: javache
Differential Revision: D73532803
fbshipit-source-id: 56d4b62873aabcbf0a92cebd7a0f720fed616158