From ebac5dba38d66e9d86e9889a11c85198bfe773db Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Sat, 26 Jan 2019 12:29:38 +0100 Subject: [PATCH] fix(ivy): don't generate code for blank NgModule fields (#28387) Currently `compileNgModule` generates an empty array for optional fields that are omitted from an `NgModule` declaration (e.g. `bootstrap`, `exports`). This isn't necessary, because `defineNgModule` has some code to default these fields to empty arrays at runtime if they aren't defined. The following changes will only output code if there are values for the particular field. PR Close #28387 --- .../compiler-cli/test/ngtsc/ngtsc_spec.ts | 12 +++---- .../src/render3/r3_module_compiler.ts | 34 +++++++++++++++---- 2 files changed, 33 insertions(+), 13 deletions(-) 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)