Skip to content

Commit f00bf71

Browse files
alxhubAndrewKushnir
authored andcommitted
fix(core): makeEnvironmentProviders should accept EnvironmentProviders (#48720)
`makeEnvironmentProviders` constructs the wrapped `EnvironmentProviders` type, which can only be used in environment injectors (not element injectors). It makes sense that `makeEnvironmentProviders` should be able to accept existing `EnvironmentProviders`-wrapped providers, since it will be providing the same guarantee, but the current types do not allow this. This commit fixes the typings to allow nesting `EnvironmentProviders` and adds a test to verify that it will work. PR Close #48720
1 parent 4ae384f commit f00bf71

File tree

5 files changed

+22
-8
lines changed

5 files changed

+22
-8
lines changed

goldens/public-api/core/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ export class KeyValueDiffers {
884884
export const LOCALE_ID: InjectionToken<string>;
885885

886886
// @public
887-
export function makeEnvironmentProviders(providers: Provider[]): EnvironmentProviders;
887+
export function makeEnvironmentProviders(providers: (Provider | EnvironmentProviders)[]): EnvironmentProviders;
888888

889889
// @public
890890
export enum MissingTranslationStrategy {

packages/core/src/di/interface/provider.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ export type EnvironmentProviders = {
352352
};
353353

354354
export interface InternalEnvironmentProviders extends EnvironmentProviders {
355-
ɵproviders: Provider[];
355+
ɵproviders: (Provider|EnvironmentProviders)[];
356356

357357
/**
358358
* If present, indicates that the `EnvironmentProviders` were derived from NgModule providers.
@@ -362,8 +362,9 @@ export interface InternalEnvironmentProviders extends EnvironmentProviders {
362362
ɵfromNgModule?: true;
363363
}
364364

365-
export function isEnvironmentProviders(value: Provider|InternalEnvironmentProviders):
366-
value is InternalEnvironmentProviders {
365+
export function isEnvironmentProviders(
366+
value: Provider|EnvironmentProviders|
367+
InternalEnvironmentProviders): value is InternalEnvironmentProviders {
367368
return value && !!(value as InternalEnvironmentProviders).ɵproviders;
368369
}
369370

packages/core/src/di/provider_collection.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ import {INJECTOR_DEF_TYPES} from './internal_tokens';
2828
* Wrap an array of `Provider`s into `EnvironmentProviders`, preventing them from being accidentally
2929
* referenced in `@Component in a component injector.
3030
*/
31-
export function makeEnvironmentProviders(providers: Provider[]): EnvironmentProviders {
31+
export function makeEnvironmentProviders(providers: (Provider|EnvironmentProviders)[]):
32+
EnvironmentProviders {
3233
return {
3334
ɵproviders: providers,
3435
} as unknown as EnvironmentProviders;

packages/core/src/di/r3_injector.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -516,8 +516,7 @@ function couldBeInjectableType(value: any): value is ProviderToken<any> {
516516
}
517517

518518
function forEachSingleProvider(
519-
providers: Array<Provider|InternalEnvironmentProviders>,
520-
fn: (provider: SingleProvider) => void): void {
519+
providers: Array<Provider|EnvironmentProviders>, fn: (provider: SingleProvider) => void): void {
521520
for (const provider of providers) {
522521
if (Array.isArray(provider)) {
523522
forEachSingleProvider(provider, fn);

packages/core/test/acceptance/di_spec.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@ const collectEnvironmentInitializerProviders = (providers: Provider[]) =>
2424
getProvidersByToken(providers, ENVIRONMENT_INITIALIZER);
2525

2626
function unwrappedImportProvidersFrom(...sources: ImportProvidersSource[]): Provider[] {
27-
return (importProvidersFrom(...sources) as unknown as InternalEnvironmentProviders).ɵproviders;
27+
const providers =
28+
(importProvidersFrom(...sources) as unknown as InternalEnvironmentProviders).ɵproviders;
29+
if (providers.some(provider => 'ɵproviders' in provider)) {
30+
throw new Error(`Unexpected nested EnvironmentProviders in test`);
31+
}
32+
return providers as Provider[];
2833
}
2934

3035
describe('importProvidersFrom', () => {
@@ -343,6 +348,14 @@ describe('EnvironmentProviders', () => {
343348
expect(inj.get(TOKEN)).toEqual('token!');
344349
});
345350

351+
it('should be accepted as additional input to makeEnvironmentProviders', () => {
352+
const wrappedProviders = makeEnvironmentProviders([environmentProviders]);
353+
TestBed.configureTestingModule({});
354+
355+
const inj = createEnvironmentInjector([wrappedProviders], TestBed.inject(EnvironmentInjector));
356+
expect(inj.get(TOKEN)).toEqual('token!');
357+
});
358+
346359
it('should be overridable by TestBed overrides', () => {
347360
TestBed.configureTestingModule({
348361
providers: [environmentProviders],

0 commit comments

Comments
 (0)