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 * 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)]));

View File

@ -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<R3NgModuleDefMap>();
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<string, o.Expression> = {};
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};

View File

@ -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`.
*