From 28a7fba29a6b224562bf0acd373dd6307f429c1d Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Wed, 10 Mar 2021 13:28:04 +0000 Subject: [PATCH] refactor(compiler): use `DefinitionMap` and remove `mapToMapExpression()` (#41080) By consistently using the `DefinitionMap` class there is no longer any need for the `mapToMapExpression()` function. PR Close #41080 --- .../compiler/src/injectable_compiler_2.ts | 12 ++- .../src/render3/r3_module_compiler.ts | 91 ++++++++++++------- packages/compiler/src/render3/util.ts | 15 --- 3 files changed, 67 insertions(+), 51 deletions(-) diff --git a/packages/compiler/src/injectable_compiler_2.ts b/packages/compiler/src/injectable_compiler_2.ts index 0386ba782a..2ba1b243b3 100644 --- a/packages/compiler/src/injectable_compiler_2.ts +++ b/packages/compiler/src/injectable_compiler_2.ts @@ -9,7 +9,8 @@ import {Identifiers} from './identifiers'; import * as o from './output/output_ast'; import {compileFactoryFunction, R3DependencyMetadata, R3FactoryDelegateType, R3FactoryMetadata, R3FactoryTarget} from './render3/r3_factory'; -import {mapToMapExpression, R3Reference, typeWithParameters} from './render3/util'; +import {R3Reference, typeWithParameters} from './render3/util'; +import {DefinitionMap} from './render3/view/util'; export interface InjectableDef { expression: o.Expression; @@ -106,15 +107,18 @@ export function compileInjectable(meta: R3InjectableMetadata): InjectableDef { const token = meta.internalType; - const injectableProps: {[key: string]: o.Expression} = {token, factory: result.factory}; + const injectableProps = + new DefinitionMap<{token: o.Expression, factory: o.Expression, providedIn: o.Expression}>(); + injectableProps.set('token', token); + injectableProps.set('factory', result.factory); // Only generate providedIn property if it has a non-null value if ((meta.providedIn as o.LiteralExpr).value !== null) { - injectableProps.providedIn = meta.providedIn; + injectableProps.set('providedIn', meta.providedIn); } const expression = o.importExpr(Identifiers.ɵɵdefineInjectable) - .callFn([mapToMapExpression(injectableProps)], undefined, true); + .callFn([injectableProps.toLiteralMap()], undefined, true); const type = new o.ExpressionType(o.importExpr( Identifiers.InjectableDef, [typeWithParameters(meta.type.type, meta.typeArgumentCount)])); diff --git a/packages/compiler/src/render3/r3_module_compiler.ts b/packages/compiler/src/render3/r3_module_compiler.ts index bd7fee31f5..3ffbb554ea 100644 --- a/packages/compiler/src/render3/r3_module_compiler.ts +++ b/packages/compiler/src/render3/r3_module_compiler.ts @@ -8,9 +8,9 @@ import * as o from '../output/output_ast'; -import {R3DependencyMetadata, R3FactoryFn} from './r3_factory'; import {Identifiers as R3} from './r3_identifiers'; -import {jitOnlyGuardedExpression, mapToMapExpression, R3Reference} from './util'; +import {jitOnlyGuardedExpression, R3Reference} from './util'; +import {DefinitionMap} from './view/util'; export interface R3NgModuleDef { expression: o.Expression; @@ -86,6 +86,43 @@ export interface R3NgModuleMetadata { id: o.Expression|null; } +/** + * The shape of the object literal that is passed to the `ɵɵdefineNgModule()` call. + */ +interface R3NgModuleDefMap { + /** + * An expression representing the module type being compiled. + */ + type: o.Expression; + /** + * An expression evaluating to an array of expressions representing the bootstrap components + * specified by the module. + */ + bootstrap?: o.Expression; + /** + * An expression evaluating to an array of expressions representing the directives and pipes + * declared by the module. + */ + declarations?: o.Expression; + /** + * An expression evaluating to an array of expressions representing the imports of the module. + */ + imports?: o.Expression; + /** + * An expression evaluating to an array of expressions representing the exports of the module. + */ + exports?: o.Expression; + /** + * A literal array expression containing the schemas that declare elements to be allowed in the + * NgModule. + */ + schemas?: o.LiteralArrayExpr; + /** + * An expression evaluating to the unique ID of an NgModule. + * */ + id?: o.Expression; +} + /** * Construct an `R3NgModuleDef` for the given `R3NgModuleMetadata`. */ @@ -104,34 +141,27 @@ export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef { } = meta; const additionalStatements: o.Statement[] = []; - const definitionMap = {type: internalType} as { - type: o.Expression, - bootstrap: o.Expression, - declarations: o.Expression, - imports: o.Expression, - exports: o.Expression, - schemas: o.LiteralArrayExpr, - id: o.Expression - }; + const definitionMap = new DefinitionMap(); + definitionMap.set('type', internalType); // Only generate the keys in the metadata if the arrays have values. if (bootstrap.length) { - definitionMap.bootstrap = refsToArray(bootstrap, containsForwardDecls); + definitionMap.set('bootstrap', refsToArray(bootstrap, containsForwardDecls)); } // If requested to emit scope information inline, pass the declarations, imports and exports to // the `ɵɵdefineNgModule` call. The JIT compilation uses this. if (emitInline) { if (declarations.length) { - definitionMap.declarations = refsToArray(declarations, containsForwardDecls); + definitionMap.set('declarations', refsToArray(declarations, containsForwardDecls)); } if (imports.length) { - definitionMap.imports = refsToArray(imports, containsForwardDecls); + definitionMap.set('imports', refsToArray(imports, containsForwardDecls)); } if (exports.length) { - definitionMap.exports = refsToArray(exports, containsForwardDecls); + definitionMap.set('exports', refsToArray(exports, containsForwardDecls)); } } @@ -145,15 +175,15 @@ export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef { } if (schemas && schemas.length) { - definitionMap.schemas = o.literalArr(schemas.map(ref => ref.value)); + definitionMap.set('schemas', o.literalArr(schemas.map(ref => ref.value))); } if (id) { - definitionMap.id = id; + definitionMap.set('id', id); } const expression = - o.importExpr(R3.defineNgModule).callFn([mapToMapExpression(definitionMap)], undefined, true); + o.importExpr(R3.defineNgModule).callFn([definitionMap.toLiteralMap()], undefined, true); const type = new o.ExpressionType(o.importExpr(R3.NgModuleDefWithMeta, [ new o.ExpressionType(moduleType.type), tupleTypeOf(declarations), tupleTypeOf(imports), tupleTypeOf(exports) @@ -172,32 +202,29 @@ export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef { function generateSetNgModuleScopeCall(meta: R3NgModuleMetadata): o.Statement|null { const {adjacentType: moduleType, declarations, imports, exports, containsForwardDecls} = meta; - const scopeMap = {} as { - declarations: o.Expression, - imports: o.Expression, - exports: o.Expression, - }; + const scopeMap = new DefinitionMap< + {declarations: o.Expression, imports: o.Expression, exports: o.Expression}>(); if (declarations.length) { - scopeMap.declarations = refsToArray(declarations, containsForwardDecls); + scopeMap.set('declarations', refsToArray(declarations, containsForwardDecls)); } if (imports.length) { - scopeMap.imports = refsToArray(imports, containsForwardDecls); + scopeMap.set('imports', refsToArray(imports, containsForwardDecls)); } if (exports.length) { - scopeMap.exports = refsToArray(exports, containsForwardDecls); + scopeMap.set('exports', refsToArray(exports, containsForwardDecls)); } - if (Object.keys(scopeMap).length === 0) { + if (Object.keys(scopeMap.values).length === 0) { return null; } // setNgModuleScope(...) const fnCall = new o.InvokeFunctionExpr( /* fn */ o.importExpr(R3.setNgModuleScope), - /* args */[moduleType, mapToMapExpression(scopeMap)]); + /* args */[moduleType, scopeMap.toLiteralMap()]); // (ngJitMode guard) && setNgModuleScope(...) const guardedCall = jitOnlyGuardedExpression(fnCall); @@ -229,18 +256,18 @@ export interface R3InjectorMetadata { } export function compileInjector(meta: R3InjectorMetadata): R3InjectorDef { - const definitionMap: Record = {}; + const definitionMap = new DefinitionMap<{providers: o.Expression, imports: o.Expression}>(); if (meta.providers !== null) { - definitionMap.providers = meta.providers; + definitionMap.set('providers', meta.providers); } if (meta.imports.length > 0) { - definitionMap.imports = o.literalArr(meta.imports); + definitionMap.set('imports', o.literalArr(meta.imports)); } const expression = - o.importExpr(R3.defineInjector).callFn([mapToMapExpression(definitionMap)], undefined, true); + o.importExpr(R3.defineInjector).callFn([definitionMap.toLiteralMap()], undefined, true); const type = new o.ExpressionType(o.importExpr(R3.InjectorDef, [new o.ExpressionType(meta.type.type)])); return {expression, type}; diff --git a/packages/compiler/src/render3/util.ts b/packages/compiler/src/render3/util.ts index 04083d07c5..89b1b47d7a 100644 --- a/packages/compiler/src/render3/util.ts +++ b/packages/compiler/src/render3/util.ts @@ -11,21 +11,6 @@ import {escapeIdentifier} from '../output/abstract_emitter'; import * as o from '../output/output_ast'; import {OutputContext} from '../util'; -/** - * Convert an object map with `Expression` values into a `LiteralMapExpr`. - */ -export function mapToMapExpression(map: {[key: string]: o.Expression|undefined}): o.LiteralMapExpr { - const result = Object.keys(map).map( - key => ({ - key, - // The assertion here is because really TypeScript doesn't allow us to express that if the - // key is present, it will have a value, but this is true in reality. - value: map[key]!, - quoted: false, - })); - return o.literalMap(result); -} - /** * Convert metadata into an `Expression` in the given `OutputContext`. *