fix(compiler): dedupe NgModule declarations, …

This is important so that we don’t generate things multiple times.
This commit is contained in:
Tobias Bosch 2016-10-28 14:08:54 -07:00 committed by vsavkin
parent 642c1db9ef
commit a178bc6c83
2 changed files with 34 additions and 8 deletions

View File

@ -160,7 +160,7 @@ export class CompileMetadataResolver {
moduleUrl = componentModuleUrl(this._reflector, directiveType, dirMeta);
if (dirMeta.entryComponents) {
entryComponentMetadata =
flattenArray(dirMeta.entryComponents)
flattenAndDedupeArray(dirMeta.entryComponents)
.map((type) => this.getTypeMetadata(type, staticTypeModuleUrl(type)))
.concat(entryComponentMetadata);
}
@ -228,7 +228,7 @@ export class CompileMetadataResolver {
const schemas: SchemaMetadata[] = [];
if (meta.imports) {
flattenArray(meta.imports).forEach((importedType) => {
flattenAndDedupeArray(meta.imports).forEach((importedType) => {
let importedModuleType: Type<any>;
if (isValidType(importedType)) {
importedModuleType = importedType;
@ -257,7 +257,7 @@ export class CompileMetadataResolver {
}
if (meta.exports) {
flattenArray(meta.exports).forEach((exportedType) => {
flattenAndDedupeArray(meta.exports).forEach((exportedType) => {
if (!isValidType(exportedType)) {
throw new Error(
`Unexpected value '${stringify(exportedType)}' exported by the module '${stringify(moduleType)}'`);
@ -283,7 +283,7 @@ export class CompileMetadataResolver {
const transitiveModule =
this._getTransitiveNgModuleMetadata(importedModules, exportedModules);
if (meta.declarations) {
flattenArray(meta.declarations).forEach((declaredType) => {
flattenAndDedupeArray(meta.declarations).forEach((declaredType) => {
if (!isValidType(declaredType)) {
throw new Error(
`Unexpected value '${stringify(declaredType)}' declared by the module '${stringify(moduleType)}'`);
@ -313,12 +313,12 @@ export class CompileMetadataResolver {
if (meta.entryComponents) {
entryComponents.push(
...flattenArray(meta.entryComponents)
...flattenAndDedupeArray(meta.entryComponents)
.map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type))));
}
if (meta.bootstrap) {
const typeMetadata = flattenArray(meta.bootstrap).map(type => {
const typeMetadata = flattenAndDedupeArray(meta.bootstrap).map(type => {
if (!isValidType(type)) {
throw new Error(
`Unexpected value '${stringify(type)}' used in the bootstrap property of module '${stringify(moduleType)}'`);
@ -331,7 +331,7 @@ export class CompileMetadataResolver {
entryComponents.push(...bootstrapComponents);
if (meta.schemas) {
schemas.push(...flattenArray(meta.schemas));
schemas.push(...flattenAndDedupeArray(meta.schemas));
}
transitiveModule.entryComponents.push(...entryComponents);
@ -736,7 +736,6 @@ function getTransitiveModules(
return targetModules;
}
function flattenArray(tree: any[], out: Array<any> = []): Array<any> {
if (tree) {
for (let i = 0; i < tree.length; i++) {
@ -751,6 +750,17 @@ function flattenArray(tree: any[], out: Array<any> = []): Array<any> {
return out;
}
function dedupeArray(array: any[]): Array<any> {
if (array) {
return Array.from(new Set(array));
}
return [];
}
function flattenAndDedupeArray(tree: any[]): Array<any> {
return dedupeArray(flattenArray(tree));
}
function isValidType(value: any): boolean {
return cpl.isStaticSymbol(value) || (value instanceof Type);
}

View File

@ -183,6 +183,22 @@ export function main() {
}));
});
it('should dedupe declarations in NgModule',
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
@Component({template: ''})
class MyComp {
}
@NgModule({declarations: [MyComp, MyComp]})
class MyModule {
}
const modMeta = resolver.getNgModuleMetadata(MyModule);
expect(modMeta.declaredDirectives.length).toBe(1);
expect(modMeta.declaredDirectives[0].type.reference).toBe(MyComp);
}));
});
}