refactor(compiler): consolidate `R3CompiledExpression` (#41080)

There were a number of almost identical interfaces used in
the same way throughout the Render3 compiler code.
This commit changes the compiler to use the same interface
throughout.

PR Close #41080
This commit is contained in:
Pete Bacon Darwin 2021-03-10 15:24:11 +00:00 committed by Jessica Janiuk
parent 90301f42a9
commit 8a33842cca
17 changed files with 59 additions and 90 deletions

View File

@ -6,11 +6,11 @@
* found in the LICENSE file at https://angular.io/license
*/
import {compileComponentFromMetadata, compileDeclareComponentFromMetadata, ConstantPool, CssSelector, DeclarationListEmitMode, DEFAULT_INTERPOLATION_CONFIG, DomElementSchemaRegistry, Expression, ExternalExpr, Identifiers, InterpolationConfig, LexerRange, makeBindingParser, ParsedTemplate, ParseSourceFile, parseTemplate, R3ComponentDef, R3ComponentMetadata, R3FactoryTarget, R3TargetBinder, R3UsedDirectiveMetadata, SelectorMatcher, Statement, TmplAstNode, WrappedNodeExpr} from '@angular/compiler';
import {compileComponentFromMetadata, compileDeclareComponentFromMetadata, ConstantPool, CssSelector, DeclarationListEmitMode, DEFAULT_INTERPOLATION_CONFIG, DomElementSchemaRegistry, Expression, ExternalExpr, Identifiers, InterpolationConfig, LexerRange, makeBindingParser, ParsedTemplate, ParseSourceFile, parseTemplate, R3CompiledExpression, R3ComponentMetadata, R3FactoryTarget, R3TargetBinder, R3UsedDirectiveMetadata, SelectorMatcher, Statement, TmplAstNode, WrappedNodeExpr} from '@angular/compiler';
import * as ts from 'typescript';
import {Cycle, CycleAnalyzer, CycleHandlingStrategy} from '../../cycles';
import {ErrorCode, FatalDiagnosticError, makeDiagnostic, makeRelatedInformation} from '../../diagnostics';
import {ErrorCode, FatalDiagnosticError, makeRelatedInformation} from '../../diagnostics';
import {absoluteFrom, relative} from '../../file_system';
import {DefaultImportRecorder, ImportedFile, ModuleResolver, Reference, ReferenceEmitter} from '../../imports';
import {DependencyTracker} from '../../incremental/api';
@ -848,7 +848,7 @@ export class ComponentDecoratorHandler implements
private compileComponent(
analysis: Readonly<ComponentAnalysisData>,
{expression: initializer, type}: R3ComponentDef): CompileResult[] {
{expression: initializer, statements, type}: R3CompiledExpression): CompileResult[] {
const factoryRes = compileNgFactoryDefField({
...analysis.meta,
injectFn: Identifiers.directiveInject,
@ -861,7 +861,7 @@ export class ComponentDecoratorHandler implements
factoryRes, {
name: 'ɵcmp',
initializer,
statements: [],
statements,
type,
}
];

View File

@ -6,12 +6,11 @@
* found in the LICENSE file at https://angular.io/license
*/
import {compileDeclareDirectiveFromMetadata, compileDirectiveFromMetadata, ConstantPool, Expression, ExternalExpr, getSafePropertyAccessString, Identifiers, makeBindingParser, ParsedHostBindings, ParseError, parseHostBindings, R3DependencyMetadata, R3DirectiveDef, R3DirectiveMetadata, R3FactoryTarget, R3QueryMetadata, R3ResolvedDependencyType, Statement, verifyHostBindings, WrappedNodeExpr} from '@angular/compiler';
import {compileDeclareDirectiveFromMetadata, compileDirectiveFromMetadata, ConstantPool, Expression, ExternalExpr, getSafePropertyAccessString, Identifiers, makeBindingParser, ParsedHostBindings, ParseError, parseHostBindings, R3CompiledExpression, R3DependencyMetadata, R3DirectiveMetadata, R3FactoryTarget, R3QueryMetadata, R3ResolvedDependencyType, Statement, verifyHostBindings, WrappedNodeExpr} from '@angular/compiler';
import {emitDistinctChangesOnlyDefaultValue} from '@angular/compiler/src/core';
import * as ts from 'typescript';
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
import {absoluteFromSourceFile} from '../../file_system';
import {DefaultImportRecorder, Reference} from '../../imports';
import {areTypeParametersEqual, extractSemanticTypeParameters, isArrayEqual, isSetEqual, isSymbolEqual, SemanticDepGraphUpdater, SemanticSymbol, SemanticTypeParameter} from '../../incremental/semantic_graph';
import {BindingPropertyName, ClassPropertyMapping, ClassPropertyName, DirectiveTypeCheckMeta, InjectableClassRegistry, MetadataReader, MetadataRegistry, TemplateGuardMeta} from '../../metadata';
@ -313,7 +312,7 @@ export class DirectiveDecoratorHandler implements
private compileDirective(
analysis: Readonly<DirectiveHandlerData>,
{expression: initializer, type}: R3DirectiveDef): CompileResult[] {
{expression: initializer, statements, type}: R3CompiledExpression): CompileResult[] {
const factoryRes = compileNgFactoryDefField({
...analysis.meta,
injectFn: Identifiers.directiveInject,
@ -326,7 +325,7 @@ export class DirectiveDecoratorHandler implements
factoryRes, {
name: 'ɵdir',
initializer,
statements: [],
statements,
type,
}
];

View File

@ -12,5 +12,5 @@ import {CompileResult} from '../../transform';
export function compileNgFactoryDefField(metadata: R3FactoryMetadata): CompileResult {
const res = compileFactoryFunction(metadata);
return {name: 'ɵfac', initializer: res.factory, statements: res.statements, type: res.type};
return {name: 'ɵfac', initializer: res.expression, statements: res.statements, type: res.type};
}

View File

@ -457,7 +457,7 @@ export class NgModuleDecoratorHandler implements
const ngInjectorDef =
compileInjector({...inj, imports: [...inj.imports, ...resolution.injectorImports]});
const ngModuleDef = compileNgModule(mod);
const ngModuleStatements = ngModuleDef.additionalStatements;
const ngModuleStatements = ngModuleDef.statements;
if (metadataStmt !== null) {
ngModuleStatements.push(metadataStmt);
}
@ -497,7 +497,7 @@ export class NgModuleDecoratorHandler implements
{
name: 'ɵinj',
initializer: ngInjectorDef.expression,
statements: [],
statements: ngInjectorDef.statements,
type: ngInjectorDef.type,
},
];

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {compileDeclarePipeFromMetadata, compilePipeFromMetadata, Identifiers, R3FactoryTarget, R3PipeDef, R3PipeMetadata, Statement, WrappedNodeExpr} from '@angular/compiler';
import {compileDeclarePipeFromMetadata, compilePipeFromMetadata, Identifiers, R3CompiledExpression, R3FactoryTarget, R3PipeMetadata, Statement, WrappedNodeExpr} from '@angular/compiler';
import * as ts from 'typescript';
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
@ -170,7 +170,7 @@ export class PipeDecoratorHandler implements
return this.compilePipe(analysis, res);
}
private compilePipe(analysis: Readonly<PipeHandlerData>, def: R3PipeDef) {
private compilePipe(analysis: Readonly<PipeHandlerData>, def: R3CompiledExpression) {
const factoryRes = compileNgFactoryDefField({
...analysis.meta,
injectFn: Identifiers.directiveInject,
@ -183,7 +183,7 @@ export class PipeDecoratorHandler implements
factoryRes, {
name: 'ɵpipe',
initializer: def.expression,
statements: [],
statements: def.statements,
type: def.type,
}
];

View File

@ -101,7 +101,7 @@ export {R3DependencyMetadata, R3ResolvedDependencyType, compileFactoryFunction,
export {compileInjector, compileNgModule, R3InjectorMetadata, R3NgModuleMetadata} from './render3/r3_module_compiler';
export {compilePipeFromMetadata, R3PipeMetadata} from './render3/r3_pipe_compiler';
export {makeBindingParser, ParsedTemplate, parseTemplate, ParseTemplateOptions} from './render3/view/template';
export {R3Reference, devOnlyGuardedExpression, getSafePropertyAccessString} from './render3/util';
export {R3CompiledExpression, R3Reference, devOnlyGuardedExpression, getSafePropertyAccessString} from './render3/util';
export {compileComponentFromMetadata, compileDirectiveFromMetadata, parseHostBindings, ParsedHostBindings, verifyHostBindings} from './render3/view/compiler';
export {compileDeclareComponentFromMetadata} from './render3/partial/component';
export {compileDeclareDirectiveFromMetadata} from './render3/partial/directive';

View File

@ -32,7 +32,7 @@ export interface R3InjectableMetadata {
}
export function compileInjectable(meta: R3InjectableMetadata): InjectableDef {
let result: {factory: o.Expression, statements: o.Statement[]}|null = null;
let result: {expression: o.Expression, statements: o.Statement[]}|null = null;
const factoryMeta: R3FactoryMetadata = {
name: meta.name,
@ -83,7 +83,7 @@ export function compileInjectable(meta: R3InjectableMetadata): InjectableDef {
} else {
result = {
statements: [],
factory: o.fn([], [new o.ReturnStatement(meta.useFactory.callFn([]))])
expression: o.fn([], [new o.ReturnStatement(meta.useFactory.callFn([]))])
};
}
} else if (meta.useValue !== undefined) {
@ -110,7 +110,7 @@ export function compileInjectable(meta: R3InjectableMetadata): InjectableDef {
const injectableProps =
new DefinitionMap<{token: o.Expression, factory: o.Expression, providedIn: o.Expression}>();
injectableProps.set('token', token);
injectableProps.set('factory', result.factory);
injectableProps.set('factory', result.expression);
// Only generate providedIn property if it has a non-null value
if ((meta.providedIn as o.LiteralExpr).value !== null) {
@ -135,7 +135,7 @@ function delegateToFactory(type: o.WrappedNodeExpr<any>, internalType: o.Wrapped
// If types are the same, we can generate `factory: type.ɵfac`
// If types are different, we have to generate a wrapper function to ensure
// the internal type has been resolved (`factory: function(t) { return type.ɵfac(t); }`)
factory: type.node === internalType.node ?
expression: type.node === internalType.node ?
internalType.prop('ɵfac') :
o.fn([new o.FnParam('t', o.DYNAMIC_TYPE)], [new o.ReturnStatement(internalType.callMethod(
'ɵfac', [o.variable('t')]))])

View File

@ -196,7 +196,7 @@ export class CompilerFacadeImpl implements CompilerFacade {
target: meta.target,
});
return this.jitExpression(
factoryRes.factory, angularCoreEnv, sourceMapUrl, factoryRes.statements);
factoryRes.expression, angularCoreEnv, sourceMapUrl, factoryRes.statements);
}
createParseSourceSpan(kind: string, typeName: string, sourceUrl: string): ParseSourceSpan {

View File

@ -10,7 +10,8 @@ import {DEFAULT_INTERPOLATION_CONFIG} from '../../ml_parser/interpolation_config
import * as o from '../../output/output_ast';
import {ParseLocation, ParseSourceFile, ParseSourceSpan} from '../../parse_util';
import {Identifiers as R3} from '../r3_identifiers';
import {DeclarationListEmitMode, R3ComponentDef, R3ComponentMetadata, R3UsedDirectiveMetadata} from '../view/api';
import {R3CompiledExpression} from '../util';
import {DeclarationListEmitMode, R3ComponentMetadata, R3UsedDirectiveMetadata} from '../view/api';
import {createComponentType} from '../view/compiler';
import {ParsedTemplate} from '../view/template';
import {DefinitionMap} from '../view/util';
@ -24,13 +25,13 @@ import {toOptionalLiteralArray} from './util';
* Compile a component declaration defined by the `R3ComponentMetadata`.
*/
export function compileDeclareComponentFromMetadata(
meta: R3ComponentMetadata, template: ParsedTemplate): R3ComponentDef {
meta: R3ComponentMetadata, template: ParsedTemplate): R3CompiledExpression {
const definitionMap = createComponentDefinitionMap(meta, template);
const expression = o.importExpr(R3.declareComponent).callFn([definitionMap.toLiteralMap()]);
const type = createComponentType(meta);
return {expression, type};
return {expression, type, statements: []};
}
/**

View File

@ -7,7 +7,8 @@
*/
import * as o from '../../output/output_ast';
import {Identifiers as R3} from '../r3_identifiers';
import {R3DirectiveDef, R3DirectiveMetadata, R3HostMetadata, R3QueryMetadata} from '../view/api';
import {R3CompiledExpression} from '../util';
import {R3DirectiveMetadata, R3HostMetadata, R3QueryMetadata} from '../view/api';
import {createDirectiveType} from '../view/compiler';
import {asLiteral, conditionallyCreateMapObjectLiteral, DefinitionMap} from '../view/util';
import {R3DeclareDirectiveMetadata, R3DeclareQueryMetadata} from './api';
@ -17,13 +18,14 @@ import {toOptionalLiteralMap} from './util';
/**
* Compile a directive declaration defined by the `R3DirectiveMetadata`.
*/
export function compileDeclareDirectiveFromMetadata(meta: R3DirectiveMetadata): R3DirectiveDef {
export function compileDeclareDirectiveFromMetadata(meta: R3DirectiveMetadata):
R3CompiledExpression {
const definitionMap = createDirectiveDefinitionMap(meta);
const expression = o.importExpr(R3.declareDirective).callFn([definitionMap.toLiteralMap()]);
const type = createDirectiveType(meta);
return {expression, type};
return {expression, type, statements: []};
}
/**

View File

@ -8,7 +8,7 @@
import * as o from '../../output/output_ast';
import {Identifiers as R3} from '../r3_identifiers';
import {createPipeType, R3PipeMetadata} from '../r3_pipe_compiler';
import {R3PipeDef} from '../view/api';
import {R3CompiledExpression} from '../util';
import {DefinitionMap} from '../view/util';
import {R3DeclarePipeMetadata} from './api';
@ -16,13 +16,13 @@ import {R3DeclarePipeMetadata} from './api';
/**
* Compile a Pipe declaration defined by the `R3PipeMetadata`.
*/
export function compileDeclarePipeFromMetadata(meta: R3PipeMetadata): R3PipeDef {
export function compileDeclarePipeFromMetadata(meta: R3PipeMetadata): R3CompiledExpression {
const definitionMap = createPipeDefinitionMap(meta);
const expression = o.importExpr(R3.declarePipe).callFn([definitionMap.toLiteralMap()]);
const type = createPipeType(meta);
return {expression, type};
return {expression, type, statements: []};
}
/**

View File

@ -15,7 +15,7 @@ import * as o from '../output/output_ast';
import {Identifiers as R3} from '../render3/r3_identifiers';
import {OutputContext} from '../util';
import {R3Reference, typeWithParameters} from './util';
import {R3CompiledExpression, R3Reference, typeWithParameters} from './util';
import {unsupported} from './view/util';
@ -169,16 +169,10 @@ export interface R3DependencyMetadata {
skipSelf: boolean;
}
export interface R3FactoryFn {
factory: o.Expression;
statements: o.Statement[];
type: o.ExpressionType;
}
/**
* Construct a factory function expression for the given `R3FactoryMetadata`.
*/
export function compileFactoryFunction(meta: R3FactoryMetadata): R3FactoryFn {
export function compileFactoryFunction(meta: R3FactoryMetadata): R3CompiledExpression {
const t = o.variable('t');
const statements: o.Statement[] = [];
let ctorDepsType: o.Type = o.NONE_TYPE;
@ -258,7 +252,7 @@ export function compileFactoryFunction(meta: R3FactoryMetadata): R3FactoryFn {
}
return {
factory: o.fn(
expression: o.fn(
[new o.FnParam('t', o.DYNAMIC_TYPE)], body, o.INFERRED_TYPE, undefined,
`${meta.name}_Factory`),
statements,

View File

@ -9,15 +9,9 @@
import * as o from '../output/output_ast';
import {Identifiers as R3} from './r3_identifiers';
import {jitOnlyGuardedExpression, R3Reference} from './util';
import {jitOnlyGuardedExpression, R3CompiledExpression, R3Reference} from './util';
import {DefinitionMap} from './view/util';
export interface R3NgModuleDef {
expression: o.Expression;
type: o.Type;
additionalStatements: o.Statement[];
}
/**
* Metadata required by the module compiler to generate a module def (`ɵmod`) for a type.
*/
@ -126,7 +120,7 @@ interface R3NgModuleDefMap {
/**
* Construct an `R3NgModuleDef` for the given `R3NgModuleMetadata`.
*/
export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef {
export function compileNgModule(meta: R3NgModuleMetadata): R3CompiledExpression {
const {
internalType,
type: moduleType,
@ -140,7 +134,7 @@ export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef {
id
} = meta;
const additionalStatements: o.Statement[] = [];
const statements: o.Statement[] = [];
const definitionMap = new DefinitionMap<R3NgModuleDefMap>();
definitionMap.set('type', internalType);
@ -170,7 +164,7 @@ export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef {
else {
const setNgModuleScopeCall = generateSetNgModuleScopeCall(meta);
if (setNgModuleScopeCall !== null) {
additionalStatements.push(setNgModuleScopeCall);
statements.push(setNgModuleScopeCall);
}
}
@ -190,7 +184,7 @@ export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef {
]));
return {expression, type, additionalStatements};
return {expression, type, statements};
}
/**
@ -242,11 +236,6 @@ function generateSetNgModuleScopeCall(meta: R3NgModuleMetadata): o.Statement|nul
return iifeCall.toStmt();
}
export interface R3InjectorDef {
expression: o.Expression;
type: o.Type;
}
export interface R3InjectorMetadata {
name: string;
type: R3Reference;
@ -255,7 +244,7 @@ export interface R3InjectorMetadata {
imports: o.Expression[];
}
export function compileInjector(meta: R3InjectorMetadata): R3InjectorDef {
export function compileInjector(meta: R3InjectorMetadata): R3CompiledExpression {
const definitionMap = new DefinitionMap<{providers: o.Expression, imports: o.Expression}>();
if (meta.providers !== null) {
@ -270,7 +259,7 @@ export function compileInjector(meta: R3InjectorMetadata): R3InjectorDef {
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};
return {expression, type, statements: []};
}
function tupleTypeOf(exp: R3Reference[]): o.Type {

View File

@ -9,8 +9,7 @@ import * as o from '../output/output_ast';
import {R3DependencyMetadata} from './r3_factory';
import {Identifiers as R3} from './r3_identifiers';
import {R3Reference, typeWithParameters} from './util';
import {R3PipeDef} from './view/api';
import {R3CompiledExpression, R3Reference, typeWithParameters} from './util';
export interface R3PipeMetadata {
/**
@ -53,7 +52,7 @@ export interface R3PipeMetadata {
pure: boolean;
}
export function compilePipeFromMetadata(metadata: R3PipeMetadata): R3PipeDef {
export function compilePipeFromMetadata(metadata: R3PipeMetadata): R3CompiledExpression {
const definitionMapValues: {key: string, quoted: boolean, value: o.Expression}[] = [];
// e.g. `name: 'myPipe'`
@ -69,7 +68,7 @@ export function compilePipeFromMetadata(metadata: R3PipeMetadata): R3PipeDef {
o.importExpr(R3.definePipe).callFn([o.literalMap(definitionMapValues)], undefined, true);
const type = createPipeType(metadata);
return {expression, type};
return {expression, type, statements: []};
}
export function createPipeType(metadata: R3PipeMetadata): o.Type {

View File

@ -25,6 +25,15 @@ export interface R3Reference {
type: o.Expression;
}
/**
* Result of compilation of a render3 code unit, e.g. component, directive, pipe, etc.
*/
export interface R3CompiledExpression {
expression: o.Expression;
type: o.Type;
statements: o.Statement[];
}
const ANIMATE_SYMBOL_PREFIX = '@';
export function prepareSyntheticPropertyName(name: string) {
return `${ANIMATE_SYMBOL_PREFIX}${name}`;

View File

@ -338,30 +338,6 @@ export interface R3QueryMetadata {
static: boolean;
}
/**
* Output of render3 directive compilation.
*/
export interface R3DirectiveDef {
expression: o.Expression;
type: o.Type;
}
/**
* Output of render3 component compilation.
*/
export interface R3ComponentDef {
expression: o.Expression;
type: o.Type;
}
/**
* Output of render3 pipe compilation.
*/
export interface R3PipeDef {
expression: o.Expression;
type: o.Type;
}
/**
* Mappings indicating how the class interacts with its
* host element (host bindings, listeners, etc).

View File

@ -20,9 +20,9 @@ import {BindingParser} from '../../template_parser/binding_parser';
import {error} from '../../util';
import {BoundEvent} from '../r3_ast';
import {Identifiers as R3} from '../r3_identifiers';
import {prepareSyntheticListenerFunctionName, prepareSyntheticPropertyName, typeWithParameters} from '../util';
import {prepareSyntheticListenerFunctionName, prepareSyntheticPropertyName, R3CompiledExpression, typeWithParameters} from '../util';
import {DeclarationListEmitMode, R3ComponentDef, R3ComponentMetadata, R3DirectiveDef, R3DirectiveMetadata, R3HostMetadata, R3QueryMetadata} from './api';
import {DeclarationListEmitMode, R3ComponentMetadata, R3DirectiveMetadata, R3HostMetadata, R3QueryMetadata} from './api';
import {MIN_STYLING_BINDING_SLOTS_REQUIRED, StylingBuilder, StylingInstructionCall} from './styling_builder';
import {BindingScope, makeBindingParser, prepareEventListenerParameters, renderFlagCheckIfStmt, resolveSanitizationFn, TemplateDefinitionBuilder, ValueConverter} from './template';
import {asLiteral, chainedInstruction, conditionallyCreateMapObjectLiteral, CONTEXT_NAME, DefinitionMap, getQueryPredicate, RENDER_FLAGS, TEMPORARY_NAME, temporaryAllocator} from './util';
@ -113,14 +113,14 @@ function addFeatures(definitionMap: DefinitionMap, meta: R3DirectiveMetadata|R3C
*/
export function compileDirectiveFromMetadata(
meta: R3DirectiveMetadata, constantPool: ConstantPool,
bindingParser: BindingParser): R3DirectiveDef {
bindingParser: BindingParser): R3CompiledExpression {
const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser);
addFeatures(definitionMap, meta);
const expression =
o.importExpr(R3.defineDirective).callFn([definitionMap.toLiteralMap()], undefined, true);
const type = createDirectiveType(meta);
return {expression, type};
return {expression, type, statements: []};
}
/**
@ -128,7 +128,7 @@ export function compileDirectiveFromMetadata(
*/
export function compileComponentFromMetadata(
meta: R3ComponentMetadata, constantPool: ConstantPool,
bindingParser: BindingParser): R3ComponentDef {
bindingParser: BindingParser): R3CompiledExpression {
const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser);
addFeatures(definitionMap, meta);
@ -256,7 +256,7 @@ export function compileComponentFromMetadata(
o.importExpr(R3.defineComponent).callFn([definitionMap.toLiteralMap()], undefined, true);
const type = createComponentType(meta);
return {expression, type};
return {expression, type, statements: []};
}
/**