Skip to content

Commit

Permalink
refactor(core): rename internal method to account for standalone comp…
Browse files Browse the repository at this point in the history
…onents (#46407)

Prior to standalone components, the `applyProviderOverridesToModule` method was used exclusively for NgModules. With standalone, its scope was expended to include standalone components as well. This commit renames the method to `applyProviderOverridesInScope` to better reflect this + also renames a field that refers to a set that contains already overridden types.

PR Close #46407
  • Loading branch information
AndrewKushnir committed Jun 21, 2022
1 parent 8ce0b33 commit c79bb14
Showing 1 changed file with 22 additions and 17 deletions.
39 changes: 22 additions & 17 deletions packages/core/testing/src/r3_test_bed_compiler.ts
Expand Up @@ -100,7 +100,7 @@ export class R3TestBedCompiler {
// module's provider list.
private providerOverridesByModule = new Map<InjectorType<any>, Provider[]>();
private providerOverridesByToken = new Map<any, Provider>();
private moduleProvidersOverridden = new Set<Type<any>>();
private scopesWithOverriddenProviders = new Set<Type<any>>();

private testModuleType: NgModuleType<any>;
private testModuleRef: NgModuleRef<any>|null = null;
Expand Down Expand Up @@ -309,7 +309,7 @@ export class R3TestBedCompiler {
this.queueTypesFromModulesArray([moduleType]);
this.compileTypesSync();
this.applyProviderOverrides();
this.applyProviderOverridesToModule(moduleType);
this.applyProviderOverridesInScope(moduleType);
this.applyTransitiveScopes();
}

Expand All @@ -320,7 +320,7 @@ export class R3TestBedCompiler {
this.queueTypesFromModulesArray([moduleType]);
await this.compileComponents();
this.applyProviderOverrides();
this.applyProviderOverridesToModule(moduleType);
this.applyProviderOverridesInScope(moduleType);
this.applyTransitiveScopes();
}

Expand Down Expand Up @@ -435,25 +435,30 @@ export class R3TestBedCompiler {
this.seenDirectives.clear();
}

private applyProviderOverridesToModule(moduleType: Type<any>): void {
if (this.moduleProvidersOverridden.has(moduleType)) {

/**
* Applies provider overrides to a given type (either an NgModule or a standalone component)
* and all imported NgModules and standalone components recursively.
*/
private applyProviderOverridesInScope(type: Type<any>): void {
if (this.scopesWithOverriddenProviders.has(type)) {
return;
}
this.moduleProvidersOverridden.add(moduleType);
this.scopesWithOverriddenProviders.add(type);

// NOTE: the line below triggers JIT compilation of the module injector,
// which also invokes verification of the NgModule semantics, which produces
// detailed error messages. The fact that the code relies on this line being
// present here is suspicious and should be refactored in a way that the line
// below can be moved (for ex. after an early exit check below).
const injectorDef: any = (moduleType as any)[NG_INJ_DEF];
const injectorDef: any = (type as any)[NG_INJ_DEF];

// No provider overrides, exit early.
if (this.providerOverridesByToken.size === 0) return;

if (isStandaloneComponent(moduleType)) {
if (isStandaloneComponent(type)) {
// Visit all component dependencies and override providers there.
const def = getComponentDef(moduleType);
const def = getComponentDef(type);
const dependencies = maybeUnwrapFn(def.dependencies ?? []);
for (const dependency of dependencies) {
// Proceed with examining dependencies recursively
Expand All @@ -462,26 +467,26 @@ export class R3TestBedCompiler {
// Component, Directive and Pipes. Skip them here, they are handled in a
// different location (in the `configureTestingModule` function).
if (isStandaloneComponent(dependency) || hasNgModuleDef(dependency)) {
this.applyProviderOverridesToModule(dependency);
this.applyProviderOverridesInScope(dependency);
}
}
} else {
const providers = [
...injectorDef.providers,
...(this.providerOverridesByModule.get(moduleType as InjectorType<any>) || [])
...(this.providerOverridesByModule.get(type as InjectorType<any>) || [])
];
if (this.hasProviderOverrides(providers)) {
this.maybeStoreNgDef(NG_INJ_DEF, moduleType);
this.maybeStoreNgDef(NG_INJ_DEF, type);

this.storeFieldOfDefOnType(moduleType, NG_INJ_DEF, 'providers');
this.storeFieldOfDefOnType(type, NG_INJ_DEF, 'providers');
injectorDef.providers = this.getOverriddenProviders(providers);
}

// Apply provider overrides to imported modules recursively
const moduleDef = (moduleType as any)[NG_MOD_DEF];
const moduleDef = (type as any)[NG_MOD_DEF];
const imports = maybeUnwrapFn(moduleDef.imports);
for (const importedModule of imports) {
this.applyProviderOverridesToModule(importedModule);
this.applyProviderOverridesInScope(importedModule);
}
// Also override the providers on any ModuleWithProviders imports since those don't appear in
// the moduleDef.
Expand Down Expand Up @@ -729,7 +734,7 @@ export class R3TestBedCompiler {
});
});
this.initialNgDefs.clear();
this.moduleProvidersOverridden.clear();
this.scopesWithOverriddenProviders.clear();
this.restoreComponentResolutionQueue();
// Restore the locale ID to the default value, this shouldn't be necessary but we never know
setLocaleId(DEFAULT_LOCALE_ID);
Expand Down Expand Up @@ -759,7 +764,7 @@ export class R3TestBedCompiler {
}, /* allowDuplicateDeclarationsInRoot */ true);
// clang-format on

this.applyProviderOverridesToModule(this.testModuleType);
this.applyProviderOverridesInScope(this.testModuleType);
}

get injector(): Injector {
Expand Down

0 comments on commit c79bb14

Please sign in to comment.