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