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)) {
|
if (declaredDirMeta = this.getDirectiveMetadata(declaredType, false)) {
|
||||||
this._addDirectiveToModule(
|
this._addDirectiveToModule(
|
||||||
declaredDirMeta, moduleType, transitiveModule, declaredDirectives, true);
|
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)) {
|
} else if (declaredPipeMeta = this.getPipeMetadata(declaredType, false)) {
|
||||||
this._addPipeToModule(
|
this._addPipeToModule(
|
||||||
declaredPipeMeta, moduleType, transitiveModule, declaredPipes, true);
|
declaredPipeMeta, moduleType, transitiveModule, declaredPipes, true);
|
||||||
|
@ -338,9 +334,6 @@ export class CompileMetadataResolver {
|
||||||
this._addDirectiveToModule(
|
this._addDirectiveToModule(
|
||||||
compMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
|
compMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
|
||||||
moduleMeta.declaredDirectives);
|
moduleMeta.declaredDirectives);
|
||||||
this._getTransitiveViewDirectivesAndPipes(
|
|
||||||
compMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
|
|
||||||
moduleMeta.declaredDirectives, moduleMeta.declaredPipes);
|
|
||||||
|
|
||||||
moduleMeta.transitiveModule.entryComponents.push(compMeta.type);
|
moduleMeta.transitiveModule.entryComponents.push(compMeta.type);
|
||||||
moduleMeta.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!`);
|
`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) => {
|
moduleMeta.entryComponents.forEach((entryComponentType) => {
|
||||||
if (!moduleMeta.transitiveModule.directivesSet.has(entryComponentType.runtime)) {
|
if (!moduleMeta.transitiveModule.directivesSet.has(entryComponentType.runtime)) {
|
||||||
this._addDirectiveToModule(
|
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.`);
|
`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) {
|
private _addTypeToModule(type: Type, moduleType: Type) {
|
||||||
|
@ -394,10 +381,7 @@ export class CompileMetadataResolver {
|
||||||
|
|
||||||
|
|
||||||
private _getTransitiveViewDirectivesAndPipes(
|
private _getTransitiveViewDirectivesAndPipes(
|
||||||
compMeta: cpl.CompileDirectiveMetadata, moduleType: any,
|
compMeta: cpl.CompileDirectiveMetadata, moduleMeta: cpl.CompileNgModuleMetadata) {
|
||||||
transitiveModule: cpl.TransitiveCompileNgModuleMetadata,
|
|
||||||
declaredDirectives: cpl.CompileDirectiveMetadata[],
|
|
||||||
declaredPipes: cpl.CompilePipeMetadata[]) {
|
|
||||||
if (!compMeta.isComponent) {
|
if (!compMeta.isComponent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -407,7 +391,8 @@ export class CompileMetadataResolver {
|
||||||
`Unexpected pipe value '${pipeType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
|
`Unexpected pipe value '${pipeType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
|
||||||
}
|
}
|
||||||
const pipeMeta = this.getPipeMetadata(pipeType);
|
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) => {
|
const addDirective = (dirType: Type) => {
|
||||||
|
@ -416,9 +401,10 @@ export class CompileMetadataResolver {
|
||||||
`Unexpected directive value '${dirType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
|
`Unexpected directive value '${dirType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
|
||||||
}
|
}
|
||||||
const dirMeta = this.getDirectiveMetadata(dirType);
|
const dirMeta = this.getDirectiveMetadata(dirType);
|
||||||
if (this._addDirectiveToModule(dirMeta, moduleType, transitiveModule, declaredDirectives)) {
|
if (this._addDirectiveToModule(
|
||||||
this._getTransitiveViewDirectivesAndPipes(
|
dirMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
|
||||||
dirMeta, moduleType, transitiveModule, declaredDirectives, declaredPipes);
|
moduleMeta.declaredDirectives)) {
|
||||||
|
this._getTransitiveViewDirectivesAndPipes(dirMeta, moduleMeta);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const view = this._viewResolver.resolve(compMeta.type.runtime);
|
const view = this._viewResolver.resolve(compMeta.type.runtime);
|
||||||
|
@ -428,6 +414,13 @@ export class CompileMetadataResolver {
|
||||||
if (view.directives) {
|
if (view.directives) {
|
||||||
flattenArray(view.directives).forEach(addDirective);
|
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(
|
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',
|
it('should warn and auto declare if the component was not declared nor imported by the module',
|
||||||
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
@Component({selector: 'child', template: ''})
|
@Component({selector: 'nestedchild', template: ''})
|
||||||
|
class NestedChildComp {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({selector: 'child', template: '', entryComponents: [NestedChildComp]})
|
||||||
class ChildComp {
|
class ChildComp {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +54,8 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||||
expect(cf.componentType).toBe(ChildComp);
|
expect(cf.componentType).toBe(ChildComp);
|
||||||
|
|
||||||
expect(console.warnings).toEqual([
|
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',
|
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 {
|
class SomeModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ngModule = createModule(SomeModule);
|
const ngModule = createModule(SomeModule);
|
||||||
expect(ngModule.componentFactoryResolver.resolveComponentFactory(SomeComp).componentType)
|
expect(ngModule.componentFactoryResolver
|
||||||
.toBe(SomeComp);
|
.resolveComponentFactory(SomeCompWithEntryComponents)
|
||||||
|
.componentType)
|
||||||
|
.toBe(SomeCompWithEntryComponents);
|
||||||
|
|
||||||
expect(console.warnings).toEqual([
|
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