Keep non-layout animations on the synchronous path while another view animates layout (#58772) - #58772
Open
bartlomiejbloniarz wants to merge 1 commit into
Open
Keep non-layout animations on the synchronous path while another view animates layout (#58772)#58772bartlomiejbloniarz wants to merge 1 commit into
bartlomiejbloniarz wants to merge 1 commit into
Conversation
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 1, 2026
… animates layout (#58772) Summary: The shared animation backend decided per surface whether a frame's animated props go through a shadow tree commit or straight to the mounted views. As soon as one view animated a layout prop, every animated view on that surface went through the commit path for the whole animation, including views that only animate `transform` or `opacity`. Besides the extra commit work, on Android this moved those views from `updatePropsSynchronously` to regular mounts. There the synchronous mount props cache (`overrideBySynchronousMountPropsAtMountingAndroid`) replaced the incoming transform with its last synchronously written value, so the view froze while the other view's layout animation ran and jumped when it ended. The decision is now made per view. `SurfaceUpdates` holds a surface's mutations keyed by view tag, and `applySurfaceUpdates` splits them into views with layout updates, which go through `commitUpdates`, and the rest, which are applied synchronously. `AnimationMutation` and `AnimationMutations` move to `AnimationMutation.h`, still included by `AnimationBackend.h`. `AnimatedPropsRegistry::update` reads the frame's batches instead of the merged per-surface map. ## Changelog: [General] [Fixed] - A view animating only non-layout props on the shared animation backend no longer freezes while another view on the surface animates a layout prop Differential Revision: D122570616
meta-codesync
Bot
force-pushed
the
export-D122570616
branch
from
October 1, 2026 11:32
a5b2277 to
708f380
Compare
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 2, 2026
… animates layout (#58772) Summary: The shared animation backend decided per surface whether a frame's animated props go through a shadow tree commit or straight to the mounted views. As soon as one view animated a layout prop, every animated view on that surface went through the commit path for the whole animation, including views that only animate `transform` or `opacity`. Besides the extra commit work, on Android this moved those views from `updatePropsSynchronously` to regular mounts. There the synchronous mount props cache (`overrideBySynchronousMountPropsAtMountingAndroid`) replaced the incoming transform with its last synchronously written value, so the view froze while the other view's layout animation ran and jumped when it ended. The decision is now made per view. `SurfaceUpdates` holds a surface's mutations keyed by view tag, and `applySurfaceUpdates` splits them into views with layout updates, which go through `commitUpdates`, and the rest, which are applied synchronously. `AnimationMutation` and `AnimationMutations` move to `AnimationMutation.h`, still included by `AnimationBackend.h`. `AnimatedPropsRegistry::update` reads the frame's batches instead of the merged per-surface map. When the same view receives several mutations in one frame, they are merged, with later values winning, so the mounted view and the registry stay in sync. ## Changelog: [General] [Fixed] - A view animating only non-layout props on the shared animation backend no longer freezes while another view on the surface animates a layout prop Differential Revision: D122570616
meta-codesync
Bot
force-pushed
the
export-D122570616
branch
from
October 2, 2026 12:02
708f380 to
bfcf979
Compare
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 2, 2026
… animates layout (#58772) Summary: Pull Request resolved: #58772 The shared animation backend decided per surface whether a frame's animated props go through a shadow tree commit or straight to the mounted views. As soon as one view animated a layout prop, every animated view on that surface went through the commit path for the whole animation, including views that only animate `transform` or `opacity`. Besides the extra commit work, on Android this moved those views from `updatePropsSynchronously` to regular mounts. There the synchronous mount props cache (`overrideBySynchronousMountPropsAtMountingAndroid`) replaced the incoming transform with its last synchronously written value, so the view froze while the other view's layout animation ran and jumped when it ended. The decision is now made per view. `SurfaceUpdates` holds a surface's mutations keyed by view tag, and `applySurfaceUpdates` splits them into views with layout updates, which go through `commitUpdates`, and the rest, which are applied synchronously. `AnimationMutation` and `AnimationMutations` move to `AnimationMutation.h`, still included by `AnimationBackend.h`. `AnimatedPropsRegistry::update` reads the frame's batches instead of the merged per-surface map. When the same view receives several mutations in one frame, they are merged, with later values winning, so the mounted view and the registry stay in sync. ## Changelog: [General] [Fixed] - A view animating only non-layout props on the shared animation backend no longer freezes while another view on the surface animates a layout prop Differential Revision: D122570616
… animates layout (#58772) Summary: The shared animation backend decided per surface whether a frame's animated props go through a shadow tree commit or straight to the mounted views. As soon as one view animated a layout prop, every animated view on that surface went through the commit path for the whole animation, including views that only animate `transform` or `opacity`. Besides the extra commit work, on Android this moved those views from `updatePropsSynchronously` to regular mounts. There the synchronous mount props cache (`overrideBySynchronousMountPropsAtMountingAndroid`) replaced the incoming transform with its last synchronously written value, so the view froze while the other view's layout animation ran and jumped when it ended. The decision is now made per view. `applySurfaceUpdates` splits a surface's mutations, keyed by view tag, into views with layout updates, which go through `commitUpdates`, and the rest, which are applied synchronously. Views with layout updates are also written synchronously, as the non-shared Animated path already does, so a view that starts animating a layout prop while animating `opacity` doesn't freeze its opacity behind the cache either. `AnimationMutation` and `AnimationMutations` move to `AnimationMutation.h`, still included by `AnimationBackend.h`. `AnimatedPropsRegistry::update` reads the frame's batches instead of the merged per-surface map. When the same view receives several mutations in one frame, they are merged, so the mounted view and the registry stay in sync. Raw animated props are now merged per key, like the animation drivers merge them, instead of with merge-patch, which dropped `null` values meant to reset a prop. `RawProps::getDynamic` exposes a dynamic source without copying it. ## Changelog: [General] [Fixed] - Non-layout props animated on the shared animation backend no longer freeze while the same view or another view on the surface animates a layout prop Differential Revision: D122570616
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 2, 2026
… animates layout (#58772) Summary: The shared animation backend decided per surface whether a frame's animated props go through a shadow tree commit or straight to the mounted views. As soon as one view animated a layout prop, every animated view on that surface went through the commit path for the whole animation, including views that only animate `transform` or `opacity`. Besides the extra commit work, on Android this moved those views from `updatePropsSynchronously` to regular mounts. There the synchronous mount props cache (`overrideBySynchronousMountPropsAtMountingAndroid`) replaced the incoming transform with its last synchronously written value, so the view froze while the other view's layout animation ran and jumped when it ended. The decision is now made per view. `applySurfaceUpdates` splits a surface's mutations, keyed by view tag, into views with layout updates, which go through `commitUpdates`, and the rest, which are applied synchronously. Views with layout updates are also written synchronously, as the non-shared Animated path already does, so a view that starts animating a layout prop while animating `opacity` doesn't freeze its opacity behind the cache either. `AnimationMutation` and `AnimationMutations` move to `AnimationMutation.h`, still included by `AnimationBackend.h`. `AnimatedPropsRegistry::update` reads the frame's batches instead of the merged per-surface map. When the same view receives several mutations in one frame, they are merged, so the mounted view and the registry stay in sync. Raw animated props are now merged per key, like the animation drivers merge them, instead of with merge-patch, which dropped `null` values meant to reset a prop. `RawProps::getDynamic` exposes a dynamic source without copying it. ## Changelog: [General] [Fixed] - Non-layout props animated on the shared animation backend no longer freeze while the same view or another view on the surface animates a layout prop Differential Revision: D122570616
meta-codesync
Bot
force-pushed
the
export-D122570616
branch
2 times, most recently
from
October 2, 2026 13:54
a4f1903 to
e02d6c9
Compare
meta-codesync Bot
pushed a commit
that referenced
this pull request
Oct 2, 2026
… animates layout (#58772) Summary: Pull Request resolved: #58772 The shared animation backend decided per surface whether a frame's animated props go through a shadow tree commit or straight to the mounted views. As soon as one view animated a layout prop, every animated view on that surface went through the commit path for the whole animation, including views that only animate `transform` or `opacity`. Besides the extra commit work, on Android this moved those views from `updatePropsSynchronously` to regular mounts. There the synchronous mount props cache (`overrideBySynchronousMountPropsAtMountingAndroid`) replaced the incoming transform with its last synchronously written value, so the view froze while the other view's layout animation ran and jumped when it ended. The decision is now made per view. `applySurfaceUpdates` splits a surface's mutations, keyed by view tag, into views with layout updates, which go through `commitUpdates`, and the rest, which are applied synchronously. Views with layout updates are also written synchronously, as the non-shared Animated path already does, so a view that starts animating a layout prop while animating `opacity` doesn't freeze its opacity behind the cache either. `AnimationMutation` and `AnimationMutations` move to `AnimationMutation.h`, still included by `AnimationBackend.h`. `AnimatedPropsRegistry::update` reads the frame's batches instead of the merged per-surface map. When the same view receives several mutations in one frame, they are merged, so the mounted view and the registry stay in sync. Raw animated props are now merged per key, like the animation drivers merge them, instead of with merge-patch, which dropped `null` values meant to reset a prop. `RawProps::getDynamic` exposes a dynamic source without copying it. ## Changelog: [General] [Fixed] - Non-layout props animated on the shared animation backend no longer freeze while the same view or another view on the surface animates a layout prop Differential Revision: D122570616
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
The shared animation backend decided per surface whether a frame's animated props go through a shadow tree commit or straight to the mounted views. As soon as one view animated a layout prop, every animated view on that surface went through the commit path for the whole animation, including views that only animate
transformoropacity. Besides the extra commit work, on Android this moved those views fromupdatePropsSynchronouslyto regular mounts. There the synchronous mount props cache (overrideBySynchronousMountPropsAtMountingAndroid) replaced the incoming transform with its last synchronously written value, so the view froze while the other view's layout animation ran and jumped when it ended.The decision is now made per view.
applySurfaceUpdatessplits a surface's mutations, keyed by view tag, into views with layout updates, which go throughcommitUpdates, and the rest, which are applied synchronously. Views with layout updates are also written synchronously, as the non-shared Animated path already does, so a view that starts animating a layout prop while animatingopacitydoesn't freeze its opacity behind the cache either.AnimationMutationandAnimationMutationsmove toAnimationMutation.h, still included byAnimationBackend.h.AnimatedPropsRegistry::updatereads the frame's batches instead of the merged per-surface map. When the same view receives several mutations in one frame, they are merged, so the mounted view and the registry stay in sync. Raw animated props are now merged per key, like the animation drivers merge them, instead of with merge-patch, which droppednullvalues meant to reset a prop.RawProps::getDynamicexposes a dynamic source without copying it.Changelog:
[General] [Fixed] - Non-layout props animated on the shared animation backend no longer freeze while the same view or another view on the surface animates a layout prop
Differential Revision: D122570616