Skip to content

Construct the shared animation backend after the UIManager has a delegate (#57817) - #57817

Closed
zeyap wants to merge 1 commit into
react:mainfrom
zeyap:export-D114759538
Closed

Construct the shared animation backend after the UIManager has a delegate (#57817)#57817
zeyap wants to merge 1 commit into
react:mainfrom
zeyap:export-D114759538

Conversation

@zeyap

@zeyap zeyap commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Summary:

Changelog:

[Internal] - Construct the shared animation backend after the UIManager has a delegate

AnimationBackend's constructor calls UIManager::addOnSurfaceStartCallback so that AnimatedPropsRegistry::initializeSurface runs for each surface as it starts. That call is a no-op unless the UIManager already has a delegate:

void UIManager::addOnSurfaceStartCallback(
    UIManagerDelegate::OnSurfaceStartCallback&& callback) {
  if (delegate_ != nullptr) {
    delegate_->uiManagerShouldAddOnSurfaceStartCallback(std::move(callback));
  }
}

Scheduler's constructor was building the backend immediately after constructing the UIManager and roughly seventy lines before uiManager->setDelegate(this), so the callback was dropped every time and Scheduler::onSurfaceStartCallbacks_ never received it. AnimatedPropsRegistry::update skips surfaces missing from surfaceContexts_, so correctness was left resting on getMap() default-constructing the entry via operator[] — that is, on a commit hook happening to run before the first animated update on a freshly started surface. When that ordering does not hold, early animated updates on a new surface are dropped.

Move the backend construction to just after setDelegate, and add a comment recording the ordering constraint. This is still well before any surface can start, so the registry is populated for every surface from the first frame.

The neighbouring getShadowTreeRegistry().enumerate(...) in the same constructor is also dead today — the UIManager is two lines old and its registry is necessarily empty — but it is left in place deliberately. It mirrors the enumerate-then-register pattern in NativeAnimatedNodesManagerProvider and ViewTransitionModule, both of which are constructed lazily and do need it, and it keeps AnimationBackend's constructor correct if it is ever moved to a lazy call site.

Reviewed By: christophpurrer

Differential Revision: D114759538

@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 Aug 4, 2026
@meta-codesync

meta-codesync Bot commented Aug 4, 2026

Copy link
Copy Markdown

@zeyap has exported this pull request. If you are a Meta employee, you can view the originating Diff in D114759538.

…gate (react#57817)

Summary:

## Changelog:

[Internal] - Construct the shared animation backend after the UIManager has a delegate

`AnimationBackend`'s constructor calls `UIManager::addOnSurfaceStartCallback` so that `AnimatedPropsRegistry::initializeSurface` runs for each surface as it starts. That call is a no-op unless the `UIManager` already has a delegate:

```
void UIManager::addOnSurfaceStartCallback(
    UIManagerDelegate::OnSurfaceStartCallback&& callback) {
  if (delegate_ != nullptr) {
    delegate_->uiManagerShouldAddOnSurfaceStartCallback(std::move(callback));
  }
}
```

`Scheduler`'s constructor was building the backend immediately after constructing the `UIManager` and roughly seventy lines before `uiManager->setDelegate(this)`, so the callback was dropped every time and `Scheduler::onSurfaceStartCallbacks_` never received it. `AnimatedPropsRegistry::update` skips surfaces missing from `surfaceContexts_`, so correctness was left resting on `getMap()` default-constructing the entry via `operator[]` — that is, on a commit hook happening to run before the first animated update on a freshly started surface. When that ordering does not hold, early animated updates on a new surface are dropped.

Move the backend construction to just after `setDelegate`, and add a comment recording the ordering constraint. This is still well before any surface can start, so the registry is populated for every surface from the first frame.

The neighbouring `getShadowTreeRegistry().enumerate(...)` in the same constructor is also dead today — the `UIManager` is two lines old and its registry is necessarily empty — but it is left in place deliberately. It mirrors the enumerate-then-register pattern in `NativeAnimatedNodesManagerProvider` and `ViewTransitionModule`, both of which are constructed lazily and do need it, and it keeps `AnimationBackend`'s constructor correct if it is ever moved to a lazy call site.

Reviewed By: christophpurrer

Differential Revision: D114759538
@meta-codesync meta-codesync Bot changed the title Construct the shared animation backend after the UIManager has a delegate Construct the shared animation backend after the UIManager has a delegate (#57817) Aug 5, 2026
@zeyap
zeyap force-pushed the export-D114759538 branch from 9fa3105 to 95ce9ba Compare August 5, 2026 16:08
@meta-codesync meta-codesync Bot closed this in 471c612 Aug 5, 2026
@meta-codesync meta-codesync Bot added the Merged This PR has been merged. label Aug 5, 2026
@meta-codesync

meta-codesync Bot commented Aug 5, 2026

Copy link
Copy Markdown

This pull request has been merged in 471c612.

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. Merged This PR has been merged. meta-exported p: Facebook Partner: Facebook Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant