Skip to content

Keep non-layout animations on the synchronous path while another view animates layout (#58772) - #58772

Open
bartlomiejbloniarz wants to merge 1 commit into
mainfrom
export-D122570616
Open

bartlomiejbloniarz wants to merge 1 commit into
mainfrom
export-D122570616

Conversation

@bartlomiejbloniarz

@bartlomiejbloniarz bartlomiejbloniarz commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

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-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 30, 2026
@facebook-github-tools facebook-github-tools Bot added p: Software Mansion Partner: Software Mansion Partner p: Facebook Partner: Facebook labels Sep 30, 2026
@meta-codesync meta-codesync Bot changed the title Keep non-layout animations on the synchronous path while another view animates layout Keep non-layout animations on the synchronous path while another view animates layout (#58772) Oct 1, 2026
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
meta-codesync Bot force-pushed the export-D122570616 branch from a5b2277 to 708f380 Compare October 1, 2026 11:32
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
meta-codesync Bot force-pushed the export-D122570616 branch from 708f380 to bfcf979 Compare October 2, 2026 12:02
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
meta-codesync Bot force-pushed the export-D122570616 branch 2 times, most recently from a4f1903 to e02d6c9 Compare October 2, 2026 13:54
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

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. meta-exported p: Facebook Partner: Facebook p: Software Mansion Partner: Software Mansion Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant