mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
fix(platform-browser): avoid circular DI error in async renderer (#59271)
In https://github.com/angular/components/pull/30179 the CDK overlay started depending on the `Renderer2Factory`. Since the overlay is used in the `MatSnackbar` which is commonly used in error handlers, `Overlay` can end up being injected as a part of the app initialization. Because `AsyncAnimationRendererFactory` depends on the `ChangeDetectionScheduler`, it may cause a circular dependency. These changes inject the `ChangeDetectionScheduler` lazily to avoid the error. Note: this will also be resolved by #58984, but I decided to send it out, because: 1. #58984 seems to be stuck on some internal cleanup. 2. The `AsyncAnimationRendererFactory` doesn't need the `scheduler` eagerly anyway so the change is fairly safe. Fixes #59255. PR Close #59271
This commit is contained in:
parent
c73aee21f3
commit
dbb8980d03
2 changed files with 24 additions and 1 deletions
|
|
@ -34,7 +34,8 @@ const ANIMATION_PREFIX = '@';
|
|||
@Injectable()
|
||||
export class AsyncAnimationRendererFactory implements OnDestroy, RendererFactory2 {
|
||||
private _rendererFactoryPromise: Promise<AnimationRendererFactory> | null = null;
|
||||
private readonly scheduler = inject(ChangeDetectionScheduler, {optional: true});
|
||||
private scheduler: ChangeDetectionScheduler | null = null;
|
||||
private readonly injector = inject(Injector);
|
||||
private readonly loadingSchedulerFn = inject(ɵASYNC_ANIMATION_LOADING_SCHEDULER_FN, {
|
||||
optional: true,
|
||||
});
|
||||
|
|
@ -143,6 +144,7 @@ export class AsyncAnimationRendererFactory implements OnDestroy, RendererFactory
|
|||
rendererType,
|
||||
);
|
||||
dynamicRenderer.use(animationRenderer);
|
||||
this.scheduler ??= this.injector.get(ChangeDetectionScheduler, null, {optional: true});
|
||||
this.scheduler?.notify(NotificationSource.AsyncAnimationsLoaded);
|
||||
})
|
||||
.catch((e) => {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import {
|
|||
afterNextRender,
|
||||
ANIMATION_MODULE_TYPE,
|
||||
Component,
|
||||
ErrorHandler,
|
||||
inject,
|
||||
Injectable,
|
||||
Injector,
|
||||
|
|
@ -447,6 +448,26 @@ type AnimationBrowserModule = typeof import('@angular/animations/browser');
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to inject the renderer factory in an ErrorHandler', async () => {
|
||||
@Injectable({providedIn: 'root'})
|
||||
class CustomErrorHandler {
|
||||
renderer = inject(RendererFactory2).createRenderer(null, null);
|
||||
}
|
||||
|
||||
@Component({template: ''})
|
||||
class App {}
|
||||
|
||||
TestBed.resetTestingModule();
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
provideAnimationsAsync(),
|
||||
{provide: ErrorHandler, useClass: CustomErrorHandler},
|
||||
],
|
||||
});
|
||||
|
||||
expect(() => TestBed.createComponent(App)).not.toThrow();
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue