Skip to content

Commit 1c1ad12

Browse files
JeanMechethePunderWoman
authored andcommitted
refactor(core): Instantiate the ErrorHandler lazily. (#58984)
This change prevents that user code in a custom `ErrorHandler` to run as part of `ApplicationRef`'s creation. fixes #58970 PR Close #58984
1 parent ad5fbd9 commit 1c1ad12

File tree

14 files changed

+201
-158
lines changed

14 files changed

+201
-158
lines changed

packages/core/src/application/create_application.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {ChangeDetectionSchedulerImpl} from '../change_detection/scheduling/zonel
2020
import {bootstrap} from '../platform/bootstrap';
2121
import {profiler} from '../render3/profiler';
2222
import {ProfilerEvent} from '../render3/profiler_types';
23+
import {errorHandlerEnvironmentInitializer} from '../error_handler';
2324

2425
/**
2526
* Internal create application API that implements the core application creation logic and optional
@@ -53,6 +54,7 @@ export function internalCreateApplication(config: {
5354
const allAppProviders = [
5455
internalProvideZoneChangeDetection({}),
5556
{provide: ChangeDetectionScheduler, useExisting: ChangeDetectionSchedulerImpl},
57+
errorHandlerEnvironmentInitializer,
5658
...(appProviders || []),
5759
];
5860
const adapter = new EnvironmentNgModuleRefAdapter({

packages/core/src/change_detection/scheduling/ng_zone_scheduling.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {Subscription} from 'rxjs';
1111
import {ApplicationRef} from '../../application/application_ref';
1212
import {
1313
ENVIRONMENT_INITIALIZER,
14+
EnvironmentInjector,
1415
EnvironmentProviders,
1516
inject,
1617
Injectable,
@@ -134,8 +135,12 @@ export function internalProvideZoneChangeDetection({
134135
provide: INTERNAL_APPLICATION_ERROR_HANDLER,
135136
useFactory: () => {
136137
const zone = inject(NgZone);
137-
const userErrorHandler = inject(ErrorHandler);
138-
return (e: unknown) => zone.runOutsideAngular(() => userErrorHandler.handleError(e));
138+
const injector = inject(EnvironmentInjector);
139+
let userErrorHandler: ErrorHandler;
140+
return (e: unknown) => {
141+
userErrorHandler ??= injector.get(ErrorHandler);
142+
zone.runOutsideAngular(() => userErrorHandler.handleError(e));
143+
};
139144
},
140145
},
141146
];

packages/core/src/error_handler.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import {inject, InjectionToken} from './di';
9+
import {ENVIRONMENT_INITIALIZER, EnvironmentInjector, inject, InjectionToken} from './di';
1010

1111
/**
1212
* Provides a hook for centralized exception handling.
@@ -58,8 +58,20 @@ export const INTERNAL_APPLICATION_ERROR_HANDLER = new InjectionToken<(e: any) =>
5858
{
5959
providedIn: 'root',
6060
factory: () => {
61-
const userErrorHandler = inject(ErrorHandler);
62-
return (e: unknown) => userErrorHandler.handleError(e);
61+
// The user's error handler may depend on things that create a circular dependency
62+
// so we inject it lazily.
63+
const injector = inject(EnvironmentInjector);
64+
let userErrorHandler: ErrorHandler;
65+
return (e: unknown) => {
66+
userErrorHandler ??= injector.get(ErrorHandler);
67+
userErrorHandler.handleError(e);
68+
};
6369
},
6470
},
6571
);
72+
73+
export const errorHandlerEnvironmentInitializer = {
74+
provide: ENVIRONMENT_INITIALIZER,
75+
useValue: () => void inject(ErrorHandler),
76+
multi: true,
77+
};

packages/core/src/platform/platform_ref.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ import {
1515
import {ChangeDetectionScheduler} from '../change_detection/scheduling/zoneless_scheduling';
1616
import {ChangeDetectionSchedulerImpl} from '../change_detection/scheduling/zoneless_scheduling_impl';
1717
import {Injectable, Injector} from '../di';
18+
import {errorHandlerEnvironmentInitializer} from '../error_handler';
1819
import {RuntimeError, RuntimeErrorCode} from '../errors';
1920
import {Type} from '../interface/type';
2021
import {CompilerOptions} from '../linker';
2122
import {NgModuleFactory, NgModuleRef} from '../linker/ng_module_factory';
2223
import {createNgModuleRefWithProviders} from '../render3/ng_module_ref';
23-
import {getNgZone, NgZone} from '../zone/ng_zone';
24+
import {getNgZone} from '../zone/ng_zone';
2425
import {bootstrap} from './bootstrap';
2526
import {PLATFORM_DESTROY_LISTENERS} from './platform_destroy_listeners';
2627

@@ -68,6 +69,7 @@ export class PlatformRef {
6869
ignoreChangesOutsideZone,
6970
}),
7071
{provide: ChangeDetectionScheduler, useExisting: ChangeDetectionSchedulerImpl},
72+
errorHandlerEnvironmentInitializer,
7173
];
7274
const moduleRef = createNgModuleRefWithProviders(
7375
moduleFactory.moduleType,

0 commit comments

Comments
 (0)