fix(compiler): auto declare `entryComponents` recursively
Closes #10348
This commit is contained in:
parent
fb3608aa5d
commit
a32c4ad2f0
|
@ -280,10 +280,6 @@ export class CompileMetadataResolver {
|
|||
if (declaredDirMeta = this.getDirectiveMetadata(declaredType, false)) {
|
||||
this._addDirectiveToModule(
|
||||
declaredDirMeta, moduleType, transitiveModule, declaredDirectives, true);
|
||||
// Collect @Component.directives/pipes/entryComponents into our declared
|
||||
// directives/pipes.
|
||||
this._getTransitiveViewDirectivesAndPipes(
|
||||
declaredDirMeta, moduleType, transitiveModule, declaredDirectives, declaredPipes);
|
||||
} else if (declaredPipeMeta = this.getPipeMetadata(declaredType, false)) {
|
||||
this._addPipeToModule(
|
||||
declaredPipeMeta, moduleType, transitiveModule, declaredPipes, true);
|
||||
|
@ -338,9 +334,6 @@ export class CompileMetadataResolver {
|
|||
this._addDirectiveToModule(
|
||||
compMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
|
||||
moduleMeta.declaredDirectives);
|
||||
this._getTransitiveViewDirectivesAndPipes(
|
||||
compMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
|
||||
moduleMeta.declaredDirectives, moduleMeta.declaredPipes);
|
||||
|
||||
moduleMeta.transitiveModule.entryComponents.push(compMeta.type);
|
||||
moduleMeta.entryComponents.push(compMeta.type);
|
||||
|
@ -361,17 +354,6 @@ export class CompileMetadataResolver {
|
|||
`Can't export pipe ${stringify(pipeMeta.type.runtime)} from ${stringify(moduleMeta.type.runtime)} as it was neither declared nor imported!`);
|
||||
}
|
||||
});
|
||||
moduleMeta.declaredDirectives.forEach((dirMeta) => {
|
||||
dirMeta.entryComponents.forEach((entryComponentType) => {
|
||||
if (!moduleMeta.transitiveModule.directivesSet.has(entryComponentType.runtime)) {
|
||||
this._addDirectiveToModule(
|
||||
this.getDirectiveMetadata(entryComponentType.runtime), moduleMeta.type.runtime,
|
||||
moduleMeta.transitiveModule, moduleMeta.declaredDirectives);
|
||||
this._console.warn(
|
||||
`Component ${stringify(dirMeta.type.runtime)} in NgModule ${stringify(moduleMeta.type.runtime)} uses ${stringify(entryComponentType.runtime)} via "entryComponents" but it was neither declared nor imported into the module! This warning will become an error after final.`);
|
||||
}
|
||||
});
|
||||
});
|
||||
moduleMeta.entryComponents.forEach((entryComponentType) => {
|
||||
if (!moduleMeta.transitiveModule.directivesSet.has(entryComponentType.runtime)) {
|
||||
this._addDirectiveToModule(
|
||||
|
@ -381,6 +363,11 @@ export class CompileMetadataResolver {
|
|||
`NgModule ${stringify(moduleMeta.type.runtime)} uses ${stringify(entryComponentType.runtime)} via "entryComponents" but it was neither declared nor imported! This warning will become an error after final.`);
|
||||
}
|
||||
});
|
||||
// Collect @Component.directives/pipes/entryComponents into our declared
|
||||
// directives/pipes. Do this last so that directives added by previous steps
|
||||
// are considered as well!
|
||||
moduleMeta.declaredDirectives.forEach(
|
||||
(dirMeta) => { this._getTransitiveViewDirectivesAndPipes(dirMeta, moduleMeta); });
|
||||
}
|
||||
|
||||
private _addTypeToModule(type: Type, moduleType: Type) {
|
||||
|
@ -394,10 +381,7 @@ export class CompileMetadataResolver {
|
|||
|
||||
|
||||
private _getTransitiveViewDirectivesAndPipes(
|
||||
compMeta: cpl.CompileDirectiveMetadata, moduleType: any,
|
||||
transitiveModule: cpl.TransitiveCompileNgModuleMetadata,
|
||||
declaredDirectives: cpl.CompileDirectiveMetadata[],
|
||||
declaredPipes: cpl.CompilePipeMetadata[]) {
|
||||
compMeta: cpl.CompileDirectiveMetadata, moduleMeta: cpl.CompileNgModuleMetadata) {
|
||||
if (!compMeta.isComponent) {
|
||||
return;
|
||||
}
|
||||
|
@ -407,7 +391,8 @@ export class CompileMetadataResolver {
|
|||
`Unexpected pipe value '${pipeType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
|
||||
}
|
||||
const pipeMeta = this.getPipeMetadata(pipeType);
|
||||
this._addPipeToModule(pipeMeta, moduleType, transitiveModule, declaredPipes);
|
||||
this._addPipeToModule(
|
||||
pipeMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule, moduleMeta.declaredPipes);
|
||||
};
|
||||
|
||||
const addDirective = (dirType: Type) => {
|
||||
|
@ -416,9 +401,10 @@ export class CompileMetadataResolver {
|
|||
`Unexpected directive value '${dirType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
|
||||
}
|
||||
const dirMeta = this.getDirectiveMetadata(dirType);
|
||||
if (this._addDirectiveToModule(dirMeta, moduleType, transitiveModule, declaredDirectives)) {
|
||||
this._getTransitiveViewDirectivesAndPipes(
|
||||
dirMeta, moduleType, transitiveModule, declaredDirectives, declaredPipes);
|
||||
if (this._addDirectiveToModule(
|
||||
dirMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
|
||||
moduleMeta.declaredDirectives)) {
|
||||
this._getTransitiveViewDirectivesAndPipes(dirMeta, moduleMeta);
|
||||
}
|
||||
};
|
||||
const view = this._viewResolver.resolve(compMeta.type.runtime);
|
||||
|
@ -428,6 +414,13 @@ export class CompileMetadataResolver {
|
|||
if (view.directives) {
|
||||
flattenArray(view.directives).forEach(addDirective);
|
||||
}
|
||||
compMeta.entryComponents.forEach((entryComponentType) => {
|
||||
if (!moduleMeta.transitiveModule.directivesSet.has(entryComponentType.runtime)) {
|
||||
this._console.warn(
|
||||
`Component ${stringify(compMeta.type.runtime)} in NgModule ${stringify(moduleMeta.type.runtime)} uses ${stringify(entryComponentType.runtime)} via "entryComponents" but it was neither declared nor imported into the module! This warning will become an error after final.`);
|
||||
addDirective(entryComponentType.runtime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _getTransitiveNgModuleMetadata(
|
||||
|
|
|
@ -36,7 +36,11 @@ function declareTests({useJit}: {useJit: boolean}) {
|
|||
it('should warn and auto declare if the component was not declared nor imported by the module',
|
||||
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||
|
||||
@Component({selector: 'child', template: ''})
|
||||
@Component({selector: 'nestedchild', template: ''})
|
||||
class NestedChildComp {
|
||||
}
|
||||
|
||||
@Component({selector: 'child', template: '', entryComponents: [NestedChildComp]})
|
||||
class ChildComp {
|
||||
}
|
||||
|
||||
|
@ -50,7 +54,8 @@ function declareTests({useJit}: {useJit: boolean}) {
|
|||
expect(cf.componentType).toBe(ChildComp);
|
||||
|
||||
expect(console.warnings).toEqual([
|
||||
`Component ${stringify(SomeComp)} in NgModule DynamicTestModule uses ${stringify(ChildComp)} via "entryComponents" but it was neither declared nor imported into the module! This warning will become an error after final.`
|
||||
`Component ${stringify(SomeComp)} in NgModule DynamicTestModule uses ${stringify(ChildComp)} via "entryComponents" but it was neither declared nor imported into the module! This warning will become an error after final.`,
|
||||
`Component ${stringify(ChildComp)} in NgModule DynamicTestModule uses ${stringify(NestedChildComp)} via "entryComponents" but it was neither declared nor imported into the module! This warning will become an error after final.`
|
||||
]);
|
||||
}));
|
||||
|
||||
|
|
|
@ -273,16 +273,23 @@ function declareTests({useJit}: {useJit: boolean}) {
|
|||
|
||||
it('should warn and auto declare when using an entryComponent that was neither declared nor imported',
|
||||
() => {
|
||||
@NgModule({entryComponents: [SomeComp]})
|
||||
@Component({template: '', entryComponents: [SomeComp]})
|
||||
class SomeCompWithEntryComponents {
|
||||
}
|
||||
|
||||
@NgModule({entryComponents: [SomeCompWithEntryComponents]})
|
||||
class SomeModule {
|
||||
}
|
||||
|
||||
const ngModule = createModule(SomeModule);
|
||||
expect(ngModule.componentFactoryResolver.resolveComponentFactory(SomeComp).componentType)
|
||||
.toBe(SomeComp);
|
||||
expect(ngModule.componentFactoryResolver
|
||||
.resolveComponentFactory(SomeCompWithEntryComponents)
|
||||
.componentType)
|
||||
.toBe(SomeCompWithEntryComponents);
|
||||
|
||||
expect(console.warnings).toEqual([
|
||||
`NgModule ${stringify(SomeModule)} uses ${stringify(SomeComp)} via "entryComponents" but it was neither declared nor imported! This warning will become an error after final.`
|
||||
`NgModule ${stringify(SomeModule)} uses ${stringify(SomeCompWithEntryComponents)} via "entryComponents" but it was neither declared nor imported! This warning will become an error after final.`,
|
||||
`Component ${stringify(SomeCompWithEntryComponents)} in NgModule ${stringify(SomeModule)} uses ${stringify(SomeComp)} via "entryComponents" but it was neither declared nor imported into the module! This warning will become an error after final.`
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue