fix: make all tests green with new view engine and JIT
Note that this does not yet include enabling the view engine by default. Included refactoring: - view engine: split namespace of elements / attributes already when creating the `NodeDef` - view engine: when injecting the old `Renderer`, use an implementation that is based on `RendererV2` - view engine: store view queries in the component view, not on the host element
This commit is contained in:
@ -68,9 +68,9 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom
|
||||
const expressionParser = new Parser(new Lexer());
|
||||
const elementSchemaRegistry = new DomElementSchemaRegistry();
|
||||
const tmplParser =
|
||||
new TemplateParser(expressionParser, elementSchemaRegistry, htmlParser, console, []);
|
||||
new TemplateParser(config, expressionParser, elementSchemaRegistry, htmlParser, console, []);
|
||||
const resolver = new CompileMetadataResolver(
|
||||
new NgModuleResolver(staticReflector), new DirectiveResolver(staticReflector),
|
||||
config, new NgModuleResolver(staticReflector), new DirectiveResolver(staticReflector),
|
||||
new PipeResolver(staticReflector), summaryResolver, elementSchemaRegistry, normalizer,
|
||||
symbolCache, staticReflector);
|
||||
// TODO(vicb): do not pass options.i18nFormat here
|
||||
|
@ -26,17 +26,19 @@ export class CompilerConfig {
|
||||
private _genDebugInfo: boolean;
|
||||
private _logBindingUpdate: boolean;
|
||||
public useJit: boolean;
|
||||
public useViewEngine: boolean;
|
||||
public missingTranslation: MissingTranslationStrategy;
|
||||
|
||||
constructor(
|
||||
{renderTypes = new DefaultRenderTypes(), defaultEncapsulation = ViewEncapsulation.Emulated,
|
||||
genDebugInfo, logBindingUpdate, useJit = true, missingTranslation}: {
|
||||
genDebugInfo, logBindingUpdate, useJit = true, missingTranslation, useViewEngine}: {
|
||||
renderTypes?: RenderTypes,
|
||||
defaultEncapsulation?: ViewEncapsulation,
|
||||
genDebugInfo?: boolean,
|
||||
logBindingUpdate?: boolean,
|
||||
useJit?: boolean,
|
||||
missingTranslation?: MissingTranslationStrategy,
|
||||
useViewEngine?: boolean
|
||||
} = {}) {
|
||||
this.renderTypes = renderTypes;
|
||||
this.defaultEncapsulation = defaultEncapsulation;
|
||||
@ -44,6 +46,7 @@ export class CompilerConfig {
|
||||
this._logBindingUpdate = logBindingUpdate;
|
||||
this.useJit = useJit;
|
||||
this.missingTranslation = missingTranslation;
|
||||
this.useViewEngine = useViewEngine;
|
||||
}
|
||||
|
||||
get genDebugInfo(): boolean {
|
||||
|
@ -357,7 +357,8 @@ function parseHostBindings(
|
||||
const sourceSpan = new ParseSourceSpan(
|
||||
new ParseLocation(sourceFile, null, null, null),
|
||||
new ParseLocation(sourceFile, null, null, null));
|
||||
const parsedHostProps = parser.createDirectiveHostPropertyAsts(dirMeta.toSummary(), sourceSpan);
|
||||
const parsedHostProps =
|
||||
parser.createDirectiveHostPropertyAsts(dirMeta.toSummary(), dirMeta.selector, sourceSpan);
|
||||
const parsedHostListeners = parser.createDirectiveHostEventAsts(dirMeta.toSummary(), sourceSpan);
|
||||
|
||||
return new ParseResult(parsedHostProps, parsedHostListeners, errors);
|
||||
|
@ -107,7 +107,7 @@ export class Extractor {
|
||||
{get: (url: string) => host.loadResource(url)}, urlResolver, htmlParser, config);
|
||||
const elementSchemaRegistry = new DomElementSchemaRegistry();
|
||||
const resolver = new CompileMetadataResolver(
|
||||
new NgModuleResolver(staticReflector), new DirectiveResolver(staticReflector),
|
||||
config, new NgModuleResolver(staticReflector), new DirectiveResolver(staticReflector),
|
||||
new PipeResolver(staticReflector), summaryResolver, elementSchemaRegistry, normalizer,
|
||||
symbolCache, staticReflector);
|
||||
|
||||
|
@ -11,7 +11,7 @@ import {Compiler, ComponentFactory, ComponentRenderTypeV2, Inject, Injector, Mod
|
||||
import {AnimationCompiler} from '../animation/animation_compiler';
|
||||
import {AnimationParser} from '../animation/animation_parser';
|
||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, ProviderMeta, ProxyClass, createHostComponentMeta, identifierName} from '../compile_metadata';
|
||||
import {CompilerConfig, USE_VIEW_ENGINE} from '../config';
|
||||
import {CompilerConfig} from '../config';
|
||||
import {DirectiveWrapperCompiler} from '../directive_wrapper_compiler';
|
||||
import {stringify} from '../facade/lang';
|
||||
import {CompilerInjectable} from '../injectable';
|
||||
@ -50,8 +50,7 @@ export class JitCompiler implements Compiler {
|
||||
private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler,
|
||||
private _viewCompiler: ViewCompiler, private _ngModuleCompiler: NgModuleCompiler,
|
||||
private _directiveWrapperCompiler: DirectiveWrapperCompiler,
|
||||
private _compilerConfig: CompilerConfig, private _animationParser: AnimationParser,
|
||||
@Inject(USE_VIEW_ENGINE) private _useViewEngine: boolean) {}
|
||||
private _compilerConfig: CompilerConfig, private _animationParser: AnimationParser) {}
|
||||
|
||||
get injector(): Injector { return this._injector; }
|
||||
|
||||
@ -245,7 +244,7 @@ export class JitCompiler implements Compiler {
|
||||
|
||||
private _compileDirectiveWrapper(
|
||||
dirMeta: CompileDirectiveMetadata, moduleMeta: CompileNgModuleMetadata): void {
|
||||
if (this._useViewEngine) {
|
||||
if (this._compilerConfig.useViewEngine) {
|
||||
return;
|
||||
}
|
||||
const compileResult = this._directiveWrapperCompiler.compile(dirMeta);
|
||||
|
@ -43,9 +43,8 @@ const _NO_RESOURCE_LOADER: ResourceLoader = {
|
||||
|
||||
const baseHtmlParser = new InjectionToken('HtmlParser');
|
||||
|
||||
function viewCompilerFactory(
|
||||
useViewEngine: boolean, cc: CompilerConfig, sr: ElementSchemaRegistry) {
|
||||
return useViewEngine ? new ViewCompilerNext(cc, sr) : new ViewCompiler(cc, sr);
|
||||
function viewCompilerFactory(cc: CompilerConfig, sr: ElementSchemaRegistry) {
|
||||
return cc.useViewEngine ? new ViewCompilerNext(cc, sr) : new ViewCompiler(cc, sr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,7 +90,7 @@ export const COMPILER_PROVIDERS: Array<any|Type<any>|{[k: string]: any}|any[]> =
|
||||
{
|
||||
provide: ViewCompiler,
|
||||
useFactory: viewCompilerFactory,
|
||||
deps: [USE_VIEW_ENGINE, CompilerConfig, ElementSchemaRegistry]
|
||||
deps: [CompilerConfig, ElementSchemaRegistry]
|
||||
},
|
||||
NgModuleCompiler,
|
||||
DirectiveWrapperCompiler,
|
||||
@ -124,7 +123,7 @@ export class JitCompilerFactory implements CompilerFactory {
|
||||
const injector = ReflectiveInjector.resolveAndCreate([
|
||||
COMPILER_PROVIDERS, {
|
||||
provide: CompilerConfig,
|
||||
useFactory: () => {
|
||||
useFactory: (useViewEngine: boolean) => {
|
||||
return new CompilerConfig({
|
||||
// let explicit values from the compiler options overwrite options
|
||||
// from the app providers. E.g. important for the testing platform.
|
||||
@ -136,10 +135,10 @@ export class JitCompilerFactory implements CompilerFactory {
|
||||
// from the app providers
|
||||
defaultEncapsulation: opts.defaultEncapsulation,
|
||||
logBindingUpdate: opts.useDebug,
|
||||
missingTranslation: opts.missingTranslation,
|
||||
missingTranslation: opts.missingTranslation, useViewEngine
|
||||
});
|
||||
},
|
||||
deps: []
|
||||
deps: [USE_VIEW_ENGINE]
|
||||
},
|
||||
opts.providers
|
||||
]);
|
||||
|
@ -12,7 +12,7 @@ import {StaticSymbol, StaticSymbolCache} from './aot/static_symbol';
|
||||
import {ngfactoryFilePath} from './aot/util';
|
||||
import {assertArrayOfStrings, assertInterpolationSymbols} from './assertions';
|
||||
import * as cpl from './compile_metadata';
|
||||
import {USE_VIEW_ENGINE} from './config';
|
||||
import {CompilerConfig} from './config';
|
||||
import {DirectiveNormalizer} from './directive_normalizer';
|
||||
import {DirectiveResolver} from './directive_resolver';
|
||||
import {stringify} from './facade/lang';
|
||||
@ -48,14 +48,14 @@ export class CompileMetadataResolver {
|
||||
private _ngModuleOfTypes = new Map<Type<any>, Type<any>>();
|
||||
|
||||
constructor(
|
||||
private _ngModuleResolver: NgModuleResolver, private _directiveResolver: DirectiveResolver,
|
||||
private _pipeResolver: PipeResolver, private _summaryResolver: SummaryResolver<any>,
|
||||
private _config: CompilerConfig, private _ngModuleResolver: NgModuleResolver,
|
||||
private _directiveResolver: DirectiveResolver, private _pipeResolver: PipeResolver,
|
||||
private _summaryResolver: SummaryResolver<any>,
|
||||
private _schemaRegistry: ElementSchemaRegistry,
|
||||
private _directiveNormalizer: DirectiveNormalizer,
|
||||
@Optional() private _staticSymbolCache: StaticSymbolCache,
|
||||
private _reflector: ReflectorReader = reflector,
|
||||
@Optional() @Inject(ERROR_COLLECTOR_TOKEN) private _errorCollector?: ErrorCollector,
|
||||
@Optional() @Inject(USE_VIEW_ENGINE) private _useViewEngine?: boolean) {}
|
||||
@Optional() @Inject(ERROR_COLLECTOR_TOKEN) private _errorCollector?: ErrorCollector) {}
|
||||
|
||||
clearCacheFor(type: Type<any>) {
|
||||
const dirMeta = this._directiveCache.get(type);
|
||||
@ -148,7 +148,7 @@ export class CompileMetadataResolver {
|
||||
ngfactoryFilePath(dirType.filePath), cpl.componentFactoryName(dirType));
|
||||
} else {
|
||||
const hostView = this.getHostComponentViewClass(dirType);
|
||||
if (this._useViewEngine) {
|
||||
if (this._config.useViewEngine) {
|
||||
return viewEngine.createComponentFactory(selector, dirType, <any>hostView);
|
||||
} else {
|
||||
return new ComponentFactory(selector, <any>hostView, dirType);
|
||||
|
@ -62,8 +62,9 @@ export class BindingParser {
|
||||
|
||||
getUsedPipes(): CompilePipeSummary[] { return Array.from(this._usedPipes.values()); }
|
||||
|
||||
createDirectiveHostPropertyAsts(dirMeta: CompileDirectiveSummary, sourceSpan: ParseSourceSpan):
|
||||
BoundElementPropertyAst[] {
|
||||
createDirectiveHostPropertyAsts(
|
||||
dirMeta: CompileDirectiveSummary, elementSelector: string,
|
||||
sourceSpan: ParseSourceSpan): BoundElementPropertyAst[] {
|
||||
if (dirMeta.hostProperties) {
|
||||
const boundProps: BoundProperty[] = [];
|
||||
Object.keys(dirMeta.hostProperties).forEach(propName => {
|
||||
@ -76,7 +77,7 @@ export class BindingParser {
|
||||
sourceSpan);
|
||||
}
|
||||
});
|
||||
return boundProps.map((prop) => this.createElementPropertyAst(dirMeta.selector, prop));
|
||||
return boundProps.map((prop) => this.createElementPropertyAst(elementSelector, prop));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
import {Inject, InjectionToken, Optional, SchemaMetadata} from '@angular/core';
|
||||
|
||||
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeSummary, CompileTemplateSummary, CompileTokenMetadata, CompileTypeMetadata, identifierName} from '../compile_metadata';
|
||||
import {CompilerConfig} from '../config';
|
||||
import {AST, ASTWithSource, EmptyExpr} from '../expression_parser/ast';
|
||||
import {Parser} from '../expression_parser/parser';
|
||||
import {isPresent} from '../facade/lang';
|
||||
@ -33,6 +34,7 @@ import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventA
|
||||
import {PreparsedElementType, preparseElement} from './template_preparser';
|
||||
|
||||
|
||||
|
||||
// Group 1 = "bind-"
|
||||
// Group 2 = "let-"
|
||||
// Group 3 = "ref-/#"
|
||||
@ -88,8 +90,9 @@ export class TemplateParseResult {
|
||||
@CompilerInjectable()
|
||||
export class TemplateParser {
|
||||
constructor(
|
||||
private _exprParser: Parser, private _schemaRegistry: ElementSchemaRegistry,
|
||||
private _htmlParser: I18NHtmlParser, private _console: Console,
|
||||
private _config: CompilerConfig, private _exprParser: Parser,
|
||||
private _schemaRegistry: ElementSchemaRegistry, private _htmlParser: I18NHtmlParser,
|
||||
private _console: Console,
|
||||
@Optional() @Inject(TEMPLATE_TRANSFORMS) public transforms: TemplateAstVisitor[]) {}
|
||||
|
||||
parse(
|
||||
@ -144,8 +147,8 @@ export class TemplateParser {
|
||||
const bindingParser = new BindingParser(
|
||||
this._exprParser, interpolationConfig, this._schemaRegistry, uniqPipes, errors);
|
||||
const parseVisitor = new TemplateParseVisitor(
|
||||
providerViewContext, uniqDirectives, bindingParser, this._schemaRegistry, schemas,
|
||||
errors);
|
||||
this._config, providerViewContext, uniqDirectives, bindingParser, this._schemaRegistry,
|
||||
schemas, errors);
|
||||
result = html.visitAll(parseVisitor, htmlAstWithErrors.rootNodes, EMPTY_ELEMENT_CONTEXT);
|
||||
errors.push(...providerViewContext.errors);
|
||||
usedPipes.push(...bindingParser.getUsedPipes());
|
||||
@ -211,9 +214,10 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
contentQueryStartId: number;
|
||||
|
||||
constructor(
|
||||
public providerViewContext: ProviderViewContext, directives: CompileDirectiveSummary[],
|
||||
private _bindingParser: BindingParser, private _schemaRegistry: ElementSchemaRegistry,
|
||||
private _schemas: SchemaMetadata[], private _targetErrors: TemplateParseError[]) {
|
||||
private config: CompilerConfig, public providerViewContext: ProviderViewContext,
|
||||
directives: CompileDirectiveSummary[], private _bindingParser: BindingParser,
|
||||
private _schemaRegistry: ElementSchemaRegistry, private _schemas: SchemaMetadata[],
|
||||
private _targetErrors: TemplateParseError[]) {
|
||||
// Note: queries start with id 1 so we can use the number in a Bloom filter!
|
||||
this.contentQueryStartId = providerViewContext.component.viewQueries.length + 1;
|
||||
directives.forEach((directive, index) => {
|
||||
@ -574,8 +578,8 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
component = directive;
|
||||
}
|
||||
const directiveProperties: BoundDirectivePropertyAst[] = [];
|
||||
let hostProperties =
|
||||
this._bindingParser.createDirectiveHostPropertyAsts(directive, sourceSpan);
|
||||
let hostProperties = this._bindingParser.createDirectiveHostPropertyAsts(
|
||||
directive, this.config.useViewEngine ? elementName : directive.selector, sourceSpan);
|
||||
// Note: We need to check the host properties here as well,
|
||||
// as we don't know the element name in the DirectiveWrapperCompiler yet.
|
||||
hostProperties = this._checkPropertiesInSchema(elementName, hostProperties);
|
||||
|
@ -61,13 +61,14 @@ export class ViewCompilerNext extends ViewCompiler {
|
||||
const viewBuilderFactory = (parent: ViewBuilder): ViewBuilder => {
|
||||
const embeddedViewIndex = embeddedViewCount++;
|
||||
const viewName = viewClassName(component.type.reference, embeddedViewIndex);
|
||||
return new ViewBuilder(parent, viewName, usedPipes, staticQueryIds, viewBuilderFactory);
|
||||
return new ViewBuilder(
|
||||
parent, component, viewName, usedPipes, staticQueryIds, viewBuilderFactory);
|
||||
};
|
||||
|
||||
const visitor = viewBuilderFactory(null);
|
||||
visitor.visitAll([], template);
|
||||
|
||||
statements.push(...visitor.build(component));
|
||||
statements.push(...visitor.build());
|
||||
|
||||
return new ViewCompileResult(statements, visitor.viewName, renderComponentVar.name, []);
|
||||
}
|
||||
@ -107,7 +108,8 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
|
||||
private handleEventExpressions: HandleEventExpression[] = [];
|
||||
|
||||
constructor(
|
||||
private parent: ViewBuilder, public viewName: string, private usedPipes: CompilePipeSummary[],
|
||||
private parent: ViewBuilder, private component: CompileDirectiveMetadata,
|
||||
public viewName: string, private usedPipes: CompilePipeSummary[],
|
||||
private staticQueryIds: Map<TemplateAst, StaticAndDynamicQueryIds>,
|
||||
private viewBuilderFactory: ViewBuilderFactory) {}
|
||||
|
||||
@ -122,6 +124,25 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.parent) {
|
||||
const queryIds = staticViewQueryIds(this.staticQueryIds);
|
||||
this.component.viewQueries.forEach((query, queryIndex) => {
|
||||
// Note: queries start with id 1 so we can use the number in a Bloom filter!
|
||||
const queryId = queryIndex + 1;
|
||||
const bindingType =
|
||||
query.first ? viewEngine.QueryBindingType.First : viewEngine.QueryBindingType.All;
|
||||
let flags = viewEngine.NodeFlags.HasViewQuery;
|
||||
if (queryIds.staticQueryIds.has(queryId)) {
|
||||
flags |= viewEngine.NodeFlags.HasStaticQuery;
|
||||
} else {
|
||||
flags |= viewEngine.NodeFlags.HasDynamicQuery;
|
||||
}
|
||||
this.nodeDefs.push(o.importExpr(createIdentifier(Identifiers.queryDef)).callFn([
|
||||
o.literal(flags), o.literal(queryId),
|
||||
new o.LiteralMapExpr([new o.LiteralMapEntry(query.propertyName, o.literal(bindingType))])
|
||||
]));
|
||||
});
|
||||
}
|
||||
templateVisitAll(this, astNodes);
|
||||
if (astNodes.length === 0 ||
|
||||
(this.parent && needsAdditionalRootNode(astNodes[astNodes.length - 1]))) {
|
||||
@ -133,9 +154,9 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
|
||||
}
|
||||
}
|
||||
|
||||
build(component: CompileDirectiveMetadata, targetStatements: o.Statement[] = []): o.Statement[] {
|
||||
const compType = o.importType(component.type);
|
||||
this.children.forEach((child) => { child.build(component, targetStatements); });
|
||||
build(targetStatements: o.Statement[] = []): o.Statement[] {
|
||||
const compType = o.importType(this.component.type);
|
||||
this.children.forEach((child) => child.build(targetStatements));
|
||||
|
||||
const updateDirectivesFn = this._createUpdateFn(this.updateDirectivesExpressions, compType);
|
||||
const updateRendererFn = this._createUpdateFn(this.updateRendererExpressions, compType);
|
||||
@ -174,7 +195,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
|
||||
}
|
||||
|
||||
let viewFlags = viewEngine.ViewFlags.None;
|
||||
if (!this.parent && component.changeDetection === ChangeDetectionStrategy.OnPush) {
|
||||
if (!this.parent && this.component.changeDetection === ChangeDetectionStrategy.OnPush) {
|
||||
viewFlags |= viewEngine.ViewFlags.OnPush;
|
||||
}
|
||||
const viewFactory = new o.DeclareFunctionStmt(
|
||||
@ -272,31 +293,36 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
|
||||
// reserve the space in the nodeDefs array so we can add children
|
||||
this.nodeDefs.push(null);
|
||||
|
||||
let {flags, usedEvents, queryMatchesExpr, hostBindings} =
|
||||
this._visitElementOrTemplate(nodeIndex, ast);
|
||||
|
||||
templateVisitAll(this, ast.children);
|
||||
|
||||
ast.inputs.forEach(
|
||||
(inputAst) => { hostBindings.push({context: COMP_VAR, value: inputAst.value}); });
|
||||
this._addUpdateExpressions(nodeIndex, hostBindings, this.updateRendererExpressions);
|
||||
|
||||
const inputDefs = elementBindingDefs(ast.inputs);
|
||||
ast.directives.forEach(
|
||||
(dirAst, dirIndex) => { inputDefs.push(...elementBindingDefs(dirAst.hostProperties)); });
|
||||
const outputDefs = usedEvents.map(([target, eventName]) => {
|
||||
return target ? o.literalArr([o.literal(target), o.literal(eventName)]) :
|
||||
o.literal(eventName);
|
||||
});
|
||||
|
||||
const childCount = this.nodeDefs.length - nodeIndex - 1;
|
||||
|
||||
let elName = ast.name;
|
||||
if (ast.name === NG_CONTAINER_TAG) {
|
||||
// Using a null element name creates an anchor.
|
||||
elName = null;
|
||||
}
|
||||
|
||||
let {flags, usedEvents, queryMatchesExpr, hostBindings} =
|
||||
this._visitElementOrTemplate(nodeIndex, ast);
|
||||
|
||||
let inputDefs: o.Expression[] = [];
|
||||
let outputDefs: o.Expression[] = [];
|
||||
if (elName) {
|
||||
ast.inputs.forEach(
|
||||
(inputAst) => { hostBindings.push({context: COMP_VAR, value: inputAst.value}); });
|
||||
if (hostBindings.length) {
|
||||
this._addUpdateExpressions(nodeIndex, hostBindings, this.updateRendererExpressions);
|
||||
}
|
||||
inputDefs = elementBindingDefs(ast.inputs);
|
||||
ast.directives.forEach(
|
||||
(dirAst, dirIndex) => inputDefs.push(...elementBindingDefs(dirAst.hostProperties)));
|
||||
outputDefs = usedEvents.map(([target, eventName]) => {
|
||||
return target ? o.literalArr([o.literal(target), o.literal(eventName)]) :
|
||||
o.literal(eventName);
|
||||
});
|
||||
}
|
||||
|
||||
templateVisitAll(this, ast.children);
|
||||
|
||||
const childCount = this.nodeDefs.length - nodeIndex - 1;
|
||||
|
||||
// elementDef(
|
||||
// flags: NodeFlags, matchedQueries: [string, QueryValueType][], ngContentIndex: number,
|
||||
// childCount: number, name: string, fixedAttrs: {[name: string]: string} = {},
|
||||
@ -307,7 +333,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
|
||||
// outputs?: (string | [string, string])[]): NodeDef;
|
||||
this.nodeDefs[nodeIndex] = o.importExpr(createIdentifier(Identifiers.elementDef)).callFn([
|
||||
o.literal(flags), queryMatchesExpr, o.literal(ast.ngContentIndex), o.literal(childCount),
|
||||
o.literal(elName), fixedAttrsDef(ast),
|
||||
o.literal(elName), elName ? fixedAttrsDef(ast) : o.NULL_EXPR,
|
||||
inputDefs.length ? o.literalArr(inputDefs) : o.NULL_EXPR,
|
||||
outputDefs.length ? o.literalArr(outputDefs) : o.NULL_EXPR
|
||||
]);
|
||||
@ -422,22 +448,6 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
|
||||
// reserve the space in the nodeDefs array so we can add children
|
||||
this.nodeDefs.push(null);
|
||||
|
||||
directiveAst.directive.viewQueries.forEach((query, queryIndex) => {
|
||||
// Note: queries start with id 1 so we can use the number in a Bloom filter!
|
||||
const queryId = queryIndex + 1;
|
||||
const bindingType =
|
||||
query.first ? viewEngine.QueryBindingType.First : viewEngine.QueryBindingType.All;
|
||||
let flags = viewEngine.NodeFlags.HasViewQuery;
|
||||
if (queryIds.staticQueryIds.has(queryId)) {
|
||||
flags |= viewEngine.NodeFlags.HasStaticQuery;
|
||||
} else {
|
||||
flags |= viewEngine.NodeFlags.HasDynamicQuery;
|
||||
}
|
||||
this.nodeDefs.push(o.importExpr(createIdentifier(Identifiers.queryDef)).callFn([
|
||||
o.literal(flags), o.literal(queryId),
|
||||
new o.LiteralMapExpr([new o.LiteralMapEntry(query.propertyName, o.literal(bindingType))])
|
||||
]));
|
||||
});
|
||||
directiveAst.directive.queries.forEach((query, queryIndex) => {
|
||||
let flags = viewEngine.NodeFlags.HasContentQuery;
|
||||
const queryId = directiveAst.contentQueryStartId + queryIndex;
|
||||
@ -493,7 +503,8 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
|
||||
outputDefs.push(new o.LiteralMapEntry(propName, o.literal(eventName), false));
|
||||
}
|
||||
});
|
||||
if (directiveAst.inputs.length) {
|
||||
if (directiveAst.inputs.length ||
|
||||
(flags & (viewEngine.NodeFlags.DoCheck | viewEngine.NodeFlags.OnInit)) > 0) {
|
||||
this._addUpdateExpressions(
|
||||
nodeIndex,
|
||||
directiveAst.inputs.map((input) => { return {context: COMP_VAR, value: input.value}; }),
|
||||
@ -697,9 +708,6 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
|
||||
private _addUpdateExpressions(
|
||||
nodeIndex: number, expressions: {context: o.Expression, value: AST}[],
|
||||
target: UpdateExpression[]) {
|
||||
if (expressions.length === 0) {
|
||||
return;
|
||||
}
|
||||
const transformedExpressions = expressions.map(({context, value}) => {
|
||||
if (value instanceof ASTWithSource) {
|
||||
value = value.ast;
|
||||
@ -885,7 +893,7 @@ function elementBindingDefs(inputAsts: BoundElementPropertyAst[]): o.Expression[
|
||||
}
|
||||
|
||||
|
||||
function fixedAttrsDef(elementAst: ElementAst): o.LiteralMapExpr {
|
||||
function fixedAttrsDef(elementAst: ElementAst): o.Expression {
|
||||
const mapResult: {[key: string]: string} = {};
|
||||
elementAst.attrs.forEach(attrAst => { mapResult[attrAst.name] = attrAst.value; });
|
||||
elementAst.directives.forEach(dirAst => {
|
||||
@ -898,10 +906,8 @@ function fixedAttrsDef(elementAst: ElementAst): o.LiteralMapExpr {
|
||||
const mapEntries: o.LiteralMapEntry[] = [];
|
||||
// Note: We need to sort to get a defined output order
|
||||
// for tests and for caching generated artifacts...
|
||||
Object.keys(mapResult).sort().forEach((attrName) => {
|
||||
mapEntries.push(new o.LiteralMapEntry(attrName, o.literal(mapResult[attrName]), true));
|
||||
});
|
||||
return new o.LiteralMapExpr(mapEntries);
|
||||
return o.literalArr(Object.keys(mapResult).sort().map(
|
||||
(attrName) => o.literalArr([o.literal(attrName), o.literal(mapResult[attrName])])));
|
||||
}
|
||||
|
||||
function mergeAttributeValue(attrName: string, attrValue1: string, attrValue2: string): string {
|
||||
@ -967,9 +973,21 @@ function findStaticQueryIds(
|
||||
return result;
|
||||
}
|
||||
|
||||
function staticViewQueryIds(nodeStaticQueryIds: Map<TemplateAst, StaticAndDynamicQueryIds>):
|
||||
StaticAndDynamicQueryIds {
|
||||
const staticQueryIds = new Set<number>();
|
||||
const dynamicQueryIds = new Set<number>();
|
||||
Array.from(nodeStaticQueryIds.values()).forEach((entry) => {
|
||||
entry.staticQueryIds.forEach(queryId => staticQueryIds.add(queryId));
|
||||
entry.dynamicQueryIds.forEach(queryId => dynamicQueryIds.add(queryId));
|
||||
});
|
||||
dynamicQueryIds.forEach(queryId => staticQueryIds.delete(queryId));
|
||||
return {staticQueryIds, dynamicQueryIds};
|
||||
}
|
||||
|
||||
function createComponentFactoryResolver(directives: DirectiveAst[]): ProviderAst {
|
||||
const componentDirMeta = directives.find(dirAst => dirAst.directive.isComponent);
|
||||
if (componentDirMeta) {
|
||||
if (componentDirMeta && componentDirMeta.directive.entryComponents.length) {
|
||||
const entryComponentFactories = componentDirMeta.directive.entryComponents.map(
|
||||
(entryComponent) => o.importExpr({reference: entryComponent.componentFactory}));
|
||||
const cfrExpr = o.importExpr(createIdentifier(Identifiers.CodegenComponentFactoryResolver))
|
||||
@ -988,4 +1006,4 @@ function createComponentFactoryResolver(directives: DirectiveAst[]): ProviderAst
|
||||
ProviderAstType.PrivateService, [], componentDirMeta.sourceSpan);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user