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
This commit is contained in:
Pete Bacon Darwin 2021-03-10 13:28:04 +00:00 committed by Jessica Janiuk
parent cc75e1d17b
commit 28a7fba29a
3 changed files with 67 additions and 51 deletions

View File

@ -9,7 +9,8 @@
import {Identifiers} from './identifiers'; import {Identifiers} from './identifiers';
import * as o from './output/output_ast'; import * as o from './output/output_ast';
import {compileFactoryFunction, R3DependencyMetadata, R3FactoryDelegateType, R3FactoryMetadata, R3FactoryTarget} from './render3/r3_factory'; 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 { export interface InjectableDef {
expression: o.Expression; expression: o.Expression;
@ -106,15 +107,18 @@ export function compileInjectable(meta: R3InjectableMetadata): InjectableDef {
const token = meta.internalType; 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 // Only generate providedIn property if it has a non-null value
if ((meta.providedIn as o.LiteralExpr).value !== null) { if ((meta.providedIn as o.LiteralExpr).value !== null) {
injectableProps.providedIn = meta.providedIn; injectableProps.set('providedIn', meta.providedIn);
} }
const expression = o.importExpr(Identifiers.ɵɵdefineInjectable) const expression = o.importExpr(Identifiers.ɵɵdefineInjectable)
.callFn([mapToMapExpression(injectableProps)], undefined, true); .callFn([injectableProps.toLiteralMap()], undefined, true);
const type = new o.ExpressionType(o.importExpr( const type = new o.ExpressionType(o.importExpr(
Identifiers.InjectableDef, [typeWithParameters(meta.type.type, meta.typeArgumentCount)])); Identifiers.InjectableDef, [typeWithParameters(meta.type.type, meta.typeArgumentCount)]));

View File

@ -8,9 +8,9 @@
import * as o from '../output/output_ast'; import * as o from '../output/output_ast';
import {R3DependencyMetadata, R3FactoryFn} from './r3_factory';
import {Identifiers as R3} from './r3_identifiers'; 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 { export interface R3NgModuleDef {
expression: o.Expression; expression: o.Expression;
@ -86,6 +86,43 @@ export interface R3NgModuleMetadata {
id: o.Expression|null; 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`. * Construct an `R3NgModuleDef` for the given `R3NgModuleMetadata`.
*/ */
@ -104,34 +141,27 @@ export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef {
} = meta; } = meta;
const additionalStatements: o.Statement[] = []; const additionalStatements: o.Statement[] = [];
const definitionMap = {type: internalType} as { const definitionMap = new DefinitionMap<R3NgModuleDefMap>();
type: o.Expression, definitionMap.set('type', internalType);
bootstrap: o.Expression,
declarations: o.Expression,
imports: o.Expression,
exports: o.Expression,
schemas: o.LiteralArrayExpr,
id: o.Expression
};
// Only generate the keys in the metadata if the arrays have values. // Only generate the keys in the metadata if the arrays have values.
if (bootstrap.length) { 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 // If requested to emit scope information inline, pass the declarations, imports and exports to
// the `ɵɵdefineNgModule` call. The JIT compilation uses this. // the `ɵɵdefineNgModule` call. The JIT compilation uses this.
if (emitInline) { if (emitInline) {
if (declarations.length) { if (declarations.length) {
definitionMap.declarations = refsToArray(declarations, containsForwardDecls); definitionMap.set('declarations', refsToArray(declarations, containsForwardDecls));
} }
if (imports.length) { if (imports.length) {
definitionMap.imports = refsToArray(imports, containsForwardDecls); definitionMap.set('imports', refsToArray(imports, containsForwardDecls));
} }
if (exports.length) { 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) { 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) { if (id) {
definitionMap.id = id; definitionMap.set('id', id);
} }
const expression = 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, [ const type = new o.ExpressionType(o.importExpr(R3.NgModuleDefWithMeta, [
new o.ExpressionType(moduleType.type), tupleTypeOf(declarations), tupleTypeOf(imports), new o.ExpressionType(moduleType.type), tupleTypeOf(declarations), tupleTypeOf(imports),
tupleTypeOf(exports) tupleTypeOf(exports)
@ -172,32 +202,29 @@ export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef {
function generateSetNgModuleScopeCall(meta: R3NgModuleMetadata): o.Statement|null { function generateSetNgModuleScopeCall(meta: R3NgModuleMetadata): o.Statement|null {
const {adjacentType: moduleType, declarations, imports, exports, containsForwardDecls} = meta; const {adjacentType: moduleType, declarations, imports, exports, containsForwardDecls} = meta;
const scopeMap = {} as { const scopeMap = new DefinitionMap<
declarations: o.Expression, {declarations: o.Expression, imports: o.Expression, exports: o.Expression}>();
imports: o.Expression,
exports: o.Expression,
};
if (declarations.length) { if (declarations.length) {
scopeMap.declarations = refsToArray(declarations, containsForwardDecls); scopeMap.set('declarations', refsToArray(declarations, containsForwardDecls));
} }
if (imports.length) { if (imports.length) {
scopeMap.imports = refsToArray(imports, containsForwardDecls); scopeMap.set('imports', refsToArray(imports, containsForwardDecls));
} }
if (exports.length) { 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; return null;
} }
// setNgModuleScope(...) // setNgModuleScope(...)
const fnCall = new o.InvokeFunctionExpr( const fnCall = new o.InvokeFunctionExpr(
/* fn */ o.importExpr(R3.setNgModuleScope), /* fn */ o.importExpr(R3.setNgModuleScope),
/* args */[moduleType, mapToMapExpression(scopeMap)]); /* args */[moduleType, scopeMap.toLiteralMap()]);
// (ngJitMode guard) && setNgModuleScope(...) // (ngJitMode guard) && setNgModuleScope(...)
const guardedCall = jitOnlyGuardedExpression(fnCall); const guardedCall = jitOnlyGuardedExpression(fnCall);
@ -229,18 +256,18 @@ export interface R3InjectorMetadata {
} }
export function compileInjector(meta: R3InjectorMetadata): R3InjectorDef { export function compileInjector(meta: R3InjectorMetadata): R3InjectorDef {
const definitionMap: Record<string, o.Expression> = {}; const definitionMap = new DefinitionMap<{providers: o.Expression, imports: o.Expression}>();
if (meta.providers !== null) { if (meta.providers !== null) {
definitionMap.providers = meta.providers; definitionMap.set('providers', meta.providers);
} }
if (meta.imports.length > 0) { if (meta.imports.length > 0) {
definitionMap.imports = o.literalArr(meta.imports); definitionMap.set('imports', o.literalArr(meta.imports));
} }
const expression = const expression =
o.importExpr(R3.defineInjector).callFn([mapToMapExpression(definitionMap)], undefined, true); o.importExpr(R3.defineInjector).callFn([definitionMap.toLiteralMap()], undefined, true);
const type = const type =
new o.ExpressionType(o.importExpr(R3.InjectorDef, [new o.ExpressionType(meta.type.type)])); new o.ExpressionType(o.importExpr(R3.InjectorDef, [new o.ExpressionType(meta.type.type)]));
return {expression, type}; return {expression, type};

View File

@ -11,21 +11,6 @@ import {escapeIdentifier} from '../output/abstract_emitter';
import * as o from '../output/output_ast'; import * as o from '../output/output_ast';
import {OutputContext} from '../util'; 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`. * Convert metadata into an `Expression` in the given `OutputContext`.
* *