diff --git a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts index a88646bd4b..b0b7e793e5 100644 --- a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts +++ b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts @@ -275,7 +275,7 @@ describe('ngtsc behavioral tests', () => { expect(jsContents) .toContain( 'i0.ɵdefineNgModule({ type: TestModule, bootstrap: [TestCmp], ' + - 'declarations: [TestCmp], imports: [], exports: [] })'); + 'declarations: [TestCmp] })'); const dtsContents = env.getContents('test.d.ts'); expect(dtsContents) @@ -373,7 +373,7 @@ describe('ngtsc behavioral tests', () => { env.tsconfig(); env.write('test.ts', ` import {Component, NgModule} from '@angular/core'; - + export class Dep {} export class Token { @@ -1562,11 +1562,11 @@ describe('ngtsc behavioral tests', () => { env.tsconfig(); env.write('node_modules/external/index.d.ts', ` import {ɵDirectiveDefWithMeta, ɵNgModuleDefWithMeta} from '@angular/core'; - + export declare class ExternalDir { static ngDirectiveDef: ɵDirectiveDefWithMeta; } - + export declare class ExternalModule { static ngModuleDef: ɵNgModuleDefWithMeta; } @@ -1574,12 +1574,12 @@ describe('ngtsc behavioral tests', () => { env.write('test.ts', ` import {Component, Directive, NgModule} from '@angular/core'; import {ExternalModule} from 'external'; - + @Component({ template: '
', }) class Cmp {} - + @NgModule({ declarations: [Cmp], // Multiple imports of the same module used to result in duplicate directive references diff --git a/packages/compiler/src/render3/r3_module_compiler.ts b/packages/compiler/src/render3/r3_module_compiler.ts index fa6020a411..aab985b25b 100644 --- a/packages/compiler/src/render3/r3_module_compiler.ts +++ b/packages/compiler/src/render3/r3_module_compiler.ts @@ -64,14 +64,34 @@ export interface R3NgModuleMetadata { */ export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef { const {type: moduleType, bootstrap, declarations, imports, exports} = meta; - const expression = o.importExpr(R3.defineNgModule).callFn([mapToMapExpression({ - type: moduleType, - bootstrap: o.literalArr(bootstrap.map(ref => ref.value)), - declarations: o.literalArr(declarations.map(ref => ref.value)), - imports: o.literalArr(imports.map(ref => ref.value)), - exports: o.literalArr(exports.map(ref => ref.value)), - })]); + const definitionMap = { + type: moduleType + } as{ + type: o.Expression, + bootstrap: o.LiteralArrayExpr, + declarations: o.LiteralArrayExpr, + imports: o.LiteralArrayExpr, + exports: o.LiteralArrayExpr + }; + // Only generate the keys in the metadata if the arrays have values. + if (bootstrap.length) { + definitionMap.bootstrap = o.literalArr(bootstrap.map(ref => ref.value)); + } + + if (declarations.length) { + definitionMap.declarations = o.literalArr(declarations.map(ref => ref.value)); + } + + if (imports.length) { + definitionMap.imports = o.literalArr(imports.map(ref => ref.value)); + } + + if (exports.length) { + definitionMap.exports = o.literalArr(exports.map(ref => ref.value)); + } + + const expression = o.importExpr(R3.defineNgModule).callFn([mapToMapExpression(definitionMap)]); const type = new o.ExpressionType(o.importExpr(R3.NgModuleDefWithMeta, [ new o.ExpressionType(moduleType), tupleTypeOf(declarations), tupleTypeOf(imports), tupleTypeOf(exports)