Update Reanimated patch

This commit is contained in:
Tomek Zawadzki
2026-07-16 14:22:01 +02:00
committed by Oleksii Bulenok
parent 851220b3f9
commit b82d7f5abc
2 changed files with 170 additions and 78 deletions
+30 -26
View File
@@ -1,10 +1,9 @@
# react-native-reanimated@4.3.2.patch
Contains two independent changes:
Backports of two merged upstream PRs:
1. Backport of PR 9901 (`LayoutAnimation.configureNext` compatibility)
2. Backport of PR 9527 plus an eviction guard in `AnimatedPropsRegistry`
(stale `settledProps` applied after app resume)
1. PR 9901 (`LayoutAnimation.configureNext` compatibility)
2. PR 9971 (stale `settledProps` on worklet re-animation / after app resume)
## 1. Backport of PR 9901
@@ -29,33 +28,38 @@ Only the `packages/react-native-reanimated` part of the PR is included (the
include hunk in `LayoutAnimationsProxy_Legacy.cpp` was adjusted to the 4.3.2
release sources.
## 2. Stale `settledProps` after app resume (AnimatedPropsRegistry)
## 2. Backport of PR 9971 (stale `settledProps`)
Backport of https://github.com/software-mansion/react-native-reanimated/pull/9527
("Fix stale settledProps on worklet re-animation") plus an additional eviction
guard on top of it. Fixes the Android DM composer "phantom jump"
Verbatim application of
https://github.com/software-mansion/react-native-reanimated/pull/9971, the
4.3-stable cherry-pick of
https://github.com/software-mansion/react-native-reanimated/pull/9527
("Fix stale settledProps on worklet re-animation"). Fixes the Android DM
composer "phantom jump"
(https://github.com/software-mansion/react-native-reanimated/issues/9574).
Background: with `FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS`, once an
animation settles its final props are handed to JS (polled every 500 ms by
`PropsRegistryGarbageCollector`) and stored in React component state
(`settledProps`). The native registry entry is then evicted ~2 s after the
last worklet write, at which point `ReanimatedCommitHook` no longer covers the
view and the React-side snapshot becomes the sole owner of the value.
(`settledProps`), after which the React-side snapshot becomes the sole owner
of the value.
The PR 9527 part adds `syncedTags_` / `invalidatedTags_` so that when a
previously-synced view re-animates, its now-stale React snapshot is refreshed
on the next GC tick instead of waiting up to ~1.5 s for the new value to
settle.
The PR replaces `getUpdatesOlderThanTimestamp` (which evicted registry
entries on a wall-clock 1 s/2 s window) with `collectSettledUpdates`:
The additional guard fixes the handoff itself. Upstream, eviction relies on a
timing assumption: the settled value is returnable between 1 s and 2 s of age,
and a 500 ms JS timer is assumed to tick inside that window. If no tick lands
there (app backgrounded while a keyboard-driven animation finishes, JS thread
blocked for >1 s), the first tick after resume destroys the entry inside
`getUpdatesOlderThanTimestamp` *before* the collection loop can return it -
the settled value is lost, React state keeps the pre-background value, and the
next React commit snaps the view back (the phantom jump). The guard makes
`removeUpdatesOlderThanTimestamp` only evict tags present in `syncedTags_`,
i.e. values that were actually handed to JS; an unsynced stale entry survives
one more tick, gets returned as settled, and is evicted on the following tick.
- `syncedTags_` / `invalidatedTags_` track which tags React already has a
snapshot for; when a previously-synced view re-animates, its stale snapshot
is refreshed on the next GC tick instead of waiting for the new value to
settle.
- Eviction is no longer time-based. An entry is only evicted on the tick
*after* it was returned to JS (once its `settledProps` commit is
guaranteed), so a missed timer window (app backgrounded, JS thread blocked)
can no longer destroy a settled value before it reaches React. This
replaces the ad-hoc eviction guard an earlier version of this patch added
on top of the pre-merge PR 9527.
- `PropsRegistryGarbageCollector` drops the separate `viewsCount` counter
(which could desync when nested animated components unregister a tag that
was never registered, stopping the GC interval while views remain) in favor
of `viewsMap.size`. Only `src/` is touched, matching the PR; Metro bundles
the app from `src/` via the package's `react-native` field, and the stale
`lib/` copy is unreachable (the feature is native-only).