UNPKG

@angular/compiler

Version:

Angular - the compiler library

831 lines • 143 kB
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { rendererTypeName, tokenReference, viewClassName } from '../compile_metadata'; import { BindingForm, convertActionBinding, convertPropertyBinding, convertPropertyBindingBuiltins, EventHandlerVars } from '../compiler_util/expression_converter'; import { ChangeDetectionStrategy } from '../core'; import { Identifiers } from '../identifiers'; import { LifecycleHooks } from '../lifecycle_reflector'; import { isNgContainer } from '../ml_parser/tags'; import * as o from '../output/output_ast'; import { convertValueToOutputAst } from '../output/value_util'; import { ElementAst, EmbeddedTemplateAst, NgContentAst, templateVisitAll } from '../template_parser/template_ast'; import { componentFactoryResolverProviderDef, depDef, lifecycleHookToNodeFlag, providerDef } from './provider_compiler'; const CLASS_ATTR = 'class'; const STYLE_ATTR = 'style'; const IMPLICIT_TEMPLATE_VAR = '$implicit'; export class ViewCompileResult { constructor(viewClassVar, rendererTypeVar) { this.viewClassVar = viewClassVar; this.rendererTypeVar = rendererTypeVar; } } export class ViewCompiler { constructor(_reflector) { this._reflector = _reflector; } compileComponent(outputCtx, component, template, styles, usedPipes) { let embeddedViewCount = 0; let renderComponentVarName = undefined; if (!component.isHost) { const template = component.template; const customRenderData = []; if (template.animations && template.animations.length) { customRenderData.push(new o.LiteralMapEntry('animation', convertValueToOutputAst(outputCtx, template.animations), true)); } const renderComponentVar = o.variable(rendererTypeName(component.type.reference)); renderComponentVarName = renderComponentVar.name; outputCtx.statements.push(renderComponentVar .set(o.importExpr(Identifiers.createRendererType2).callFn([new o.LiteralMapExpr([ new o.LiteralMapEntry('encapsulation', o.literal(template.encapsulation), false), new o.LiteralMapEntry('styles', styles, false), new o.LiteralMapEntry('data', new o.LiteralMapExpr(customRenderData), false) ])])) .toDeclStmt(o.importType(Identifiers.RendererType2), [o.StmtModifier.Final, o.StmtModifier.Exported])); } const viewBuilderFactory = (parent) => { const embeddedViewIndex = embeddedViewCount++; return new ViewBuilder(this._reflector, outputCtx, parent, component, embeddedViewIndex, usedPipes, viewBuilderFactory); }; const visitor = viewBuilderFactory(null); visitor.visitAll([], template); outputCtx.statements.push(...visitor.build()); return new ViewCompileResult(visitor.viewName, renderComponentVarName); } } const LOG_VAR = o.variable('_l'); const VIEW_VAR = o.variable('_v'); const CHECK_VAR = o.variable('_ck'); const COMP_VAR = o.variable('_co'); const EVENT_NAME_VAR = o.variable('en'); const ALLOW_DEFAULT_VAR = o.variable(`ad`); class ViewBuilder { constructor(reflector, outputCtx, parent, component, embeddedViewIndex, usedPipes, viewBuilderFactory) { this.reflector = reflector; this.outputCtx = outputCtx; this.parent = parent; this.component = component; this.embeddedViewIndex = embeddedViewIndex; this.usedPipes = usedPipes; this.viewBuilderFactory = viewBuilderFactory; this.nodes = []; this.purePipeNodeIndices = Object.create(null); // Need Object.create so that we don't have builtin values... this.refNodeIndices = Object.create(null); this.variables = []; this.children = []; // TODO(tbosch): The old view compiler used to use an `any` type // for the context in any embedded view. We keep this behaivor for now // to be able to introduce the new view compiler without too many errors. this.compType = this.embeddedViewIndex > 0 ? o.DYNAMIC_TYPE : o.expressionType(outputCtx.importExpr(this.component.type.reference)); this.viewName = viewClassName(this.component.type.reference, this.embeddedViewIndex); } visitAll(variables, astNodes) { this.variables = variables; // create the pipes for the pure pipes immediately, so that we know their indices. if (!this.parent) { this.usedPipes.forEach((pipe) => { if (pipe.pure) { this.purePipeNodeIndices[pipe.name] = this._createPipe(null, pipe); } }); } if (!this.parent) { 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 ? 0 /* First */ : 1 /* All */; const flags = 134217728 /* TypeViewQuery */ | calcQueryFlags(query); this.nodes.push(() => ({ sourceSpan: null, nodeFlags: flags, nodeDef: o.importExpr(Identifiers.queryDef).callFn([ o.literal(flags), o.literal(queryId), new o.LiteralMapExpr([new o.LiteralMapEntry(query.propertyName, o.literal(bindingType), false)]) ]) })); }); } templateVisitAll(this, astNodes); if (this.parent && (astNodes.length === 0 || needsAdditionalRootNode(astNodes))) { // if the view is an embedded view, then we need to add an additional root node in some cases this.nodes.push(() => ({ sourceSpan: null, nodeFlags: 1 /* TypeElement */, nodeDef: o.importExpr(Identifiers.anchorDef).callFn([ o.literal(0 /* None */), o.NULL_EXPR, o.NULL_EXPR, o.literal(0) ]) })); } } build(targetStatements = []) { this.children.forEach((child) => child.build(targetStatements)); const { updateRendererStmts, updateDirectivesStmts, nodeDefExprs } = this._createNodeExpressions(); const updateRendererFn = this._createUpdateFn(updateRendererStmts); const updateDirectivesFn = this._createUpdateFn(updateDirectivesStmts); let viewFlags = 0 /* None */; if (!this.parent && this.component.changeDetection === ChangeDetectionStrategy.OnPush) { viewFlags |= 2 /* OnPush */; } const viewFactory = new o.DeclareFunctionStmt(this.viewName, [new o.FnParam(LOG_VAR.name)], [new o.ReturnStatement(o.importExpr(Identifiers.viewDef).callFn([ o.literal(viewFlags), o.literalArr(nodeDefExprs), updateDirectivesFn, updateRendererFn, ]))], o.importType(Identifiers.ViewDefinition), this.embeddedViewIndex === 0 ? [o.StmtModifier.Exported] : []); targetStatements.push(viewFactory); return targetStatements; } _createUpdateFn(updateStmts) { let updateFn; if (updateStmts.length > 0) { const preStmts = []; if (!this.component.isHost && o.findReadVarNames(updateStmts).has(COMP_VAR.name)) { preStmts.push(COMP_VAR.set(VIEW_VAR.prop('component')).toDeclStmt(this.compType)); } updateFn = o.fn([ new o.FnParam(CHECK_VAR.name, o.INFERRED_TYPE), new o.FnParam(VIEW_VAR.name, o.INFERRED_TYPE) ], [...preStmts, ...updateStmts], o.INFERRED_TYPE); } else { updateFn = o.NULL_EXPR; } return updateFn; } visitNgContent(ast, context) { // ngContentDef(ngContentIndex: number, index: number): NodeDef; this.nodes.push(() => ({ sourceSpan: ast.sourceSpan, nodeFlags: 8 /* TypeNgContent */, nodeDef: o.importExpr(Identifiers.ngContentDef) .callFn([o.literal(ast.ngContentIndex), o.literal(ast.index)]) })); } visitText(ast, context) { // Static text nodes have no check function const checkIndex = -1; this.nodes.push(() => ({ sourceSpan: ast.sourceSpan, nodeFlags: 2 /* TypeText */, nodeDef: o.importExpr(Identifiers.textDef).callFn([ o.literal(checkIndex), o.literal(ast.ngContentIndex), o.literalArr([o.literal(ast.value)]), ]) })); } visitBoundText(ast, context) { const nodeIndex = this.nodes.length; // reserve the space in the nodeDefs array this.nodes.push(null); const astWithSource = ast.value; const inter = astWithSource.ast; const updateRendererExpressions = inter.expressions.map((expr, bindingIndex) => this._preprocessUpdateExpression({ nodeIndex, bindingIndex, sourceSpan: ast.sourceSpan, context: COMP_VAR, value: expr })); // Check index is the same as the node index during compilation // They might only differ at runtime const checkIndex = nodeIndex; this.nodes[nodeIndex] = () => ({ sourceSpan: ast.sourceSpan, nodeFlags: 2 /* TypeText */, nodeDef: o.importExpr(Identifiers.textDef).callFn([ o.literal(checkIndex), o.literal(ast.ngContentIndex), o.literalArr(inter.strings.map(s => o.literal(s))), ]), updateRenderer: updateRendererExpressions }); } visitEmbeddedTemplate(ast, context) { const nodeIndex = this.nodes.length; // reserve the space in the nodeDefs array this.nodes.push(null); const { flags, queryMatchesExpr, hostEvents } = this._visitElementOrTemplate(nodeIndex, ast); const childVisitor = this.viewBuilderFactory(this); this.children.push(childVisitor); childVisitor.visitAll(ast.variables, ast.children); const childCount = this.nodes.length - nodeIndex - 1; // anchorDef( // flags: NodeFlags, matchedQueries: [string, QueryValueType][], ngContentIndex: number, // childCount: number, handleEventFn?: ElementHandleEventFn, templateFactory?: // ViewDefinitionFactory): NodeDef; this.nodes[nodeIndex] = () => ({ sourceSpan: ast.sourceSpan, nodeFlags: 1 /* TypeElement */ | flags, nodeDef: o.importExpr(Identifiers.anchorDef).callFn([ o.literal(flags), queryMatchesExpr, o.literal(ast.ngContentIndex), o.literal(childCount), this._createElementHandleEventFn(nodeIndex, hostEvents), o.variable(childVisitor.viewName), ]) }); } visitElement(ast, context) { const nodeIndex = this.nodes.length; // reserve the space in the nodeDefs array so we can add children this.nodes.push(null); // Using a null element name creates an anchor. const elName = isNgContainer(ast.name) ? null : ast.name; const { flags, usedEvents, queryMatchesExpr, hostBindings: dirHostBindings, hostEvents } = this._visitElementOrTemplate(nodeIndex, ast); let inputDefs = []; let updateRendererExpressions = []; let outputDefs = []; if (elName) { const hostBindings = ast.inputs .map((inputAst) => ({ context: COMP_VAR, inputAst, dirAst: null, })) .concat(dirHostBindings); if (hostBindings.length) { updateRendererExpressions = hostBindings.map((hostBinding, bindingIndex) => this._preprocessUpdateExpression({ context: hostBinding.context, nodeIndex, bindingIndex, sourceSpan: hostBinding.inputAst.sourceSpan, value: hostBinding.inputAst.value })); inputDefs = hostBindings.map(hostBinding => elementBindingDef(hostBinding.inputAst, hostBinding.dirAst)); } outputDefs = usedEvents.map(([target, eventName]) => o.literalArr([o.literal(target), o.literal(eventName)])); } templateVisitAll(this, ast.children); const childCount = this.nodes.length - nodeIndex - 1; const compAst = ast.directives.find(dirAst => dirAst.directive.isComponent); let compRendererType = o.NULL_EXPR; let compView = o.NULL_EXPR; if (compAst) { compView = this.outputCtx.importExpr(compAst.directive.componentViewType); compRendererType = this.outputCtx.importExpr(compAst.directive.rendererType); } // Check index is the same as the node index during compilation // They might only differ at runtime const checkIndex = nodeIndex; this.nodes[nodeIndex] = () => ({ sourceSpan: ast.sourceSpan, nodeFlags: 1 /* TypeElement */ | flags, nodeDef: o.importExpr(Identifiers.elementDef).callFn([ o.literal(checkIndex), o.literal(flags), queryMatchesExpr, o.literal(ast.ngContentIndex), o.literal(childCount), 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, this._createElementHandleEventFn(nodeIndex, hostEvents), compView, compRendererType, ]), updateRenderer: updateRendererExpressions }); } _visitElementOrTemplate(nodeIndex, ast) { let flags = 0 /* None */; if (ast.hasViewContainer) { flags |= 16777216 /* EmbeddedViews */; } const usedEvents = new Map(); ast.outputs.forEach((event) => { const { name, target } = elementEventNameAndTarget(event, null); usedEvents.set(elementEventFullName(target, name), [target, name]); }); ast.directives.forEach((dirAst) => { dirAst.hostEvents.forEach((event) => { const { name, target } = elementEventNameAndTarget(event, dirAst); usedEvents.set(elementEventFullName(target, name), [target, name]); }); }); const hostBindings = []; const hostEvents = []; this._visitComponentFactoryResolverProvider(ast.directives); ast.providers.forEach(providerAst => { let dirAst = undefined; ast.directives.forEach(localDirAst => { if (localDirAst.directive.type.reference === tokenReference(providerAst.token)) { dirAst = localDirAst; } }); if (dirAst) { const { hostBindings: dirHostBindings, hostEvents: dirHostEvents } = this._visitDirective(providerAst, dirAst, ast.references, ast.queryMatches, usedEvents); hostBindings.push(...dirHostBindings); hostEvents.push(...dirHostEvents); } else { this._visitProvider(providerAst, ast.queryMatches); } }); let queryMatchExprs = []; ast.queryMatches.forEach((match) => { let valueType = undefined; if (tokenReference(match.value) === this.reflector.resolveExternalReference(Identifiers.ElementRef)) { valueType = 0 /* ElementRef */; } else if (tokenReference(match.value) === this.reflector.resolveExternalReference(Identifiers.ViewContainerRef)) { valueType = 3 /* ViewContainerRef */; } else if (tokenReference(match.value) === this.reflector.resolveExternalReference(Identifiers.TemplateRef)) { valueType = 2 /* TemplateRef */; } if (valueType != null) { queryMatchExprs.push(o.literalArr([o.literal(match.queryId), o.literal(valueType)])); } }); ast.references.forEach((ref) => { let valueType = undefined; if (!ref.value) { valueType = 1 /* RenderElement */; } else if (tokenReference(ref.value) === this.reflector.resolveExternalReference(Identifiers.TemplateRef)) { valueType = 2 /* TemplateRef */; } if (valueType != null) { this.refNodeIndices[ref.name] = nodeIndex; queryMatchExprs.push(o.literalArr([o.literal(ref.name), o.literal(valueType)])); } }); ast.outputs.forEach((outputAst) => { hostEvents.push({ context: COMP_VAR, eventAst: outputAst, dirAst: null }); }); return { flags, usedEvents: Array.from(usedEvents.values()), queryMatchesExpr: queryMatchExprs.length ? o.literalArr(queryMatchExprs) : o.NULL_EXPR, hostBindings, hostEvents: hostEvents }; } _visitDirective(providerAst, dirAst, refs, queryMatches, usedEvents) { const nodeIndex = this.nodes.length; // reserve the space in the nodeDefs array so we can add children this.nodes.push(null); dirAst.directive.queries.forEach((query, queryIndex) => { const queryId = dirAst.contentQueryStartId + queryIndex; const flags = 67108864 /* TypeContentQuery */ | calcQueryFlags(query); const bindingType = query.first ? 0 /* First */ : 1 /* All */; this.nodes.push(() => ({ sourceSpan: dirAst.sourceSpan, nodeFlags: flags, nodeDef: o.importExpr(Identifiers.queryDef).callFn([ o.literal(flags), o.literal(queryId), new o.LiteralMapExpr([new o.LiteralMapEntry(query.propertyName, o.literal(bindingType), false)]) ]), })); }); // Note: the operation below might also create new nodeDefs, // but we don't want them to be a child of a directive, // as they might be a provider/pipe on their own. // I.e. we only allow queries as children of directives nodes. const childCount = this.nodes.length - nodeIndex - 1; let { flags, queryMatchExprs, providerExpr, depsExpr } = this._visitProviderOrDirective(providerAst, queryMatches); refs.forEach((ref) => { if (ref.value && tokenReference(ref.value) === tokenReference(providerAst.token)) { this.refNodeIndices[ref.name] = nodeIndex; queryMatchExprs.push(o.literalArr([o.literal(ref.name), o.literal(4 /* Provider */)])); } }); if (dirAst.directive.isComponent) { flags |= 32768 /* Component */; } const inputDefs = dirAst.inputs.map((inputAst, inputIndex) => { const mapValue = o.literalArr([o.literal(inputIndex), o.literal(inputAst.directiveName)]); // Note: it's important to not quote the key so that we can capture renames by minifiers! return new o.LiteralMapEntry(inputAst.directiveName, mapValue, false); }); const outputDefs = []; const dirMeta = dirAst.directive; Object.keys(dirMeta.outputs).forEach((propName) => { const eventName = dirMeta.outputs[propName]; if (usedEvents.has(eventName)) { // Note: it's important to not quote the key so that we can capture renames by minifiers! outputDefs.push(new o.LiteralMapEntry(propName, o.literal(eventName), false)); } }); let updateDirectiveExpressions = []; if (dirAst.inputs.length || (flags & (262144 /* DoCheck */ | 65536 /* OnInit */)) > 0) { updateDirectiveExpressions = dirAst.inputs.map((input, bindingIndex) => this._preprocessUpdateExpression({ nodeIndex, bindingIndex, sourceSpan: input.sourceSpan, context: COMP_VAR, value: input.value })); } const dirContextExpr = o.importExpr(Identifiers.nodeValue).callFn([VIEW_VAR, o.literal(nodeIndex)]); const hostBindings = dirAst.hostProperties.map((inputAst) => ({ context: dirContextExpr, dirAst, inputAst, })); const hostEvents = dirAst.hostEvents.map((hostEventAst) => ({ context: dirContextExpr, eventAst: hostEventAst, dirAst, })); // Check index is the same as the node index during compilation // They might only differ at runtime const checkIndex = nodeIndex; this.nodes[nodeIndex] = () => ({ sourceSpan: dirAst.sourceSpan, nodeFlags: 16384 /* TypeDirective */ | flags, nodeDef: o.importExpr(Identifiers.directiveDef).callFn([ o.literal(checkIndex), o.literal(flags), queryMatchExprs.length ? o.literalArr(queryMatchExprs) : o.NULL_EXPR, o.literal(childCount), providerExpr, depsExpr, inputDefs.length ? new o.LiteralMapExpr(inputDefs) : o.NULL_EXPR, outputDefs.length ? new o.LiteralMapExpr(outputDefs) : o.NULL_EXPR, ]), updateDirectives: updateDirectiveExpressions, directive: dirAst.directive.type, }); return { hostBindings, hostEvents }; } _visitProvider(providerAst, queryMatches) { this._addProviderNode(this._visitProviderOrDirective(providerAst, queryMatches)); } _visitComponentFactoryResolverProvider(directives) { const componentDirMeta = directives.find(dirAst => dirAst.directive.isComponent); if (componentDirMeta && componentDirMeta.directive.entryComponents.length) { const { providerExpr, depsExpr, flags, tokenExpr } = componentFactoryResolverProviderDef(this.reflector, this.outputCtx, 8192 /* PrivateProvider */, componentDirMeta.directive.entryComponents); this._addProviderNode({ providerExpr, depsExpr, flags, tokenExpr, queryMatchExprs: [], sourceSpan: componentDirMeta.sourceSpan }); } } _addProviderNode(data) { // providerDef( // flags: NodeFlags, matchedQueries: [string, QueryValueType][], token:any, // value: any, deps: ([DepFlags, any] | any)[]): NodeDef; this.nodes.push(() => ({ sourceSpan: data.sourceSpan, nodeFlags: data.flags, nodeDef: o.importExpr(Identifiers.providerDef).callFn([ o.literal(data.flags), data.queryMatchExprs.length ? o.literalArr(data.queryMatchExprs) : o.NULL_EXPR, data.tokenExpr, data.providerExpr, data.depsExpr ]) })); } _visitProviderOrDirective(providerAst, queryMatches) { let flags = 0 /* None */; let queryMatchExprs = []; queryMatches.forEach((match) => { if (tokenReference(match.value) === tokenReference(providerAst.token)) { queryMatchExprs.push(o.literalArr([o.literal(match.queryId), o.literal(4 /* Provider */)])); } }); const { providerExpr, depsExpr, flags: providerFlags, tokenExpr } = providerDef(this.outputCtx, providerAst); return { flags: flags | providerFlags, queryMatchExprs, providerExpr, depsExpr, tokenExpr, sourceSpan: providerAst.sourceSpan }; } getLocal(name) { if (name == EventHandlerVars.event.name) { return EventHandlerVars.event; } let currViewExpr = VIEW_VAR; for (let currBuilder = this; currBuilder; currBuilder = currBuilder.parent, currViewExpr = currViewExpr.prop('parent').cast(o.DYNAMIC_TYPE)) { // check references const refNodeIndex = currBuilder.refNodeIndices[name]; if (refNodeIndex != null) { return o.importExpr(Identifiers.nodeValue).callFn([currViewExpr, o.literal(refNodeIndex)]); } // check variables const varAst = currBuilder.variables.find((varAst) => varAst.name === name); if (varAst) { const varValue = varAst.value || IMPLICIT_TEMPLATE_VAR; return currViewExpr.prop('context').prop(varValue); } } return null; } notifyImplicitReceiverUse() { // Not needed in ViewEngine as ViewEngine walks through the generated // expressions to figure out if the implicit receiver is used and needs // to be generated as part of the pre-update statements. } maybeRestoreView() { // Not necessary in ViewEngine, because view restoration is an Ivy concept. } _createLiteralArrayConverter(sourceSpan, argCount) { if (argCount === 0) { const valueExpr = o.importExpr(Identifiers.EMPTY_ARRAY); return () => valueExpr; } const checkIndex = this.nodes.length; this.nodes.push(() => ({ sourceSpan, nodeFlags: 32 /* TypePureArray */, nodeDef: o.importExpr(Identifiers.pureArrayDef).callFn([ o.literal(checkIndex), o.literal(argCount), ]) })); return (args) => callCheckStmt(checkIndex, args); } _createLiteralMapConverter(sourceSpan, keys) { if (keys.length === 0) { const valueExpr = o.importExpr(Identifiers.EMPTY_MAP); return () => valueExpr; } const map = o.literalMap(keys.map((e, i) => ({ ...e, value: o.literal(i) }))); const checkIndex = this.nodes.length; this.nodes.push(() => ({ sourceSpan, nodeFlags: 64 /* TypePureObject */, nodeDef: o.importExpr(Identifiers.pureObjectDef).callFn([ o.literal(checkIndex), map, ]) })); return (args) => callCheckStmt(checkIndex, args); } _createPipeConverter(expression, name, argCount) { const pipe = this.usedPipes.find((pipeSummary) => pipeSummary.name === name); if (pipe.pure) { const checkIndex = this.nodes.length; this.nodes.push(() => ({ sourceSpan: expression.sourceSpan, nodeFlags: 128 /* TypePurePipe */, nodeDef: o.importExpr(Identifiers.purePipeDef).callFn([ o.literal(checkIndex), o.literal(argCount), ]) })); // find underlying pipe in the component view let compViewExpr = VIEW_VAR; let compBuilder = this; while (compBuilder.parent) { compBuilder = compBuilder.parent; compViewExpr = compViewExpr.prop('parent').cast(o.DYNAMIC_TYPE); } const pipeNodeIndex = compBuilder.purePipeNodeIndices[name]; const pipeValueExpr = o.importExpr(Identifiers.nodeValue).callFn([compViewExpr, o.literal(pipeNodeIndex)]); return (args) => callCheckStmt(checkIndex, [pipeValueExpr].concat(args)); } else { const nodeIndex = this._createPipe(expression.sourceSpan, pipe); const nodeValueExpr = o.importExpr(Identifiers.nodeValue).callFn([VIEW_VAR, o.literal(nodeIndex)]); return (args) => nodeValueExpr.prop('transform').callFn(args); } } _createPipe(sourceSpan, pipe) { const nodeIndex = this.nodes.length; let flags = 0 /* None */; pipe.type.lifecycleHooks.forEach((lifecycleHook) => { // for pipes, we only support ngOnDestroy if (lifecycleHook === LifecycleHooks.OnDestroy) { flags |= lifecycleHookToNodeFlag(lifecycleHook); } }); const depExprs = pipe.type.diDeps.map((diDep) => depDef(this.outputCtx, diDep)); // function pipeDef( // flags: NodeFlags, ctor: any, deps: ([DepFlags, any] | any)[]): NodeDef this.nodes.push(() => ({ sourceSpan, nodeFlags: 16 /* TypePipe */, nodeDef: o.importExpr(Identifiers.pipeDef).callFn([ o.literal(flags), this.outputCtx.importExpr(pipe.type.reference), o.literalArr(depExprs) ]) })); return nodeIndex; } /** * For the AST in `UpdateExpression.value`: * - create nodes for pipes, literal arrays and, literal maps, * - update the AST to replace pipes, literal arrays and, literal maps with calls to check fn. * * WARNING: This might create new nodeDefs (for pipes and literal arrays and literal maps)! */ _preprocessUpdateExpression(expression) { return { nodeIndex: expression.nodeIndex, bindingIndex: expression.bindingIndex, sourceSpan: expression.sourceSpan, context: expression.context, value: convertPropertyBindingBuiltins({ createLiteralArrayConverter: (argCount) => this._createLiteralArrayConverter(expression.sourceSpan, argCount), createLiteralMapConverter: (keys) => this._createLiteralMapConverter(expression.sourceSpan, keys), createPipeConverter: (name, argCount) => this._createPipeConverter(expression, name, argCount) }, expression.value) }; } _createNodeExpressions() { const self = this; let updateBindingCount = 0; const updateRendererStmts = []; const updateDirectivesStmts = []; const nodeDefExprs = this.nodes.map((factory, nodeIndex) => { const { nodeDef, nodeFlags, updateDirectives, updateRenderer, sourceSpan } = factory(); if (updateRenderer) { updateRendererStmts.push(...createUpdateStatements(nodeIndex, sourceSpan, updateRenderer, false)); } if (updateDirectives) { updateDirectivesStmts.push(...createUpdateStatements(nodeIndex, sourceSpan, updateDirectives, (nodeFlags & (262144 /* DoCheck */ | 65536 /* OnInit */)) > 0)); } // We use a comma expression to call the log function before // the nodeDef function, but still use the result of the nodeDef function // as the value. // Note: We only add the logger to elements / text nodes, // so we don't generate too much code. const logWithNodeDef = nodeFlags & 3 /* CatRenderNode */ ? new o.CommaExpr([LOG_VAR.callFn([]).callFn([]), nodeDef]) : nodeDef; return o.applySourceSpanToExpressionIfNeeded(logWithNodeDef, sourceSpan); }); return { updateRendererStmts, updateDirectivesStmts, nodeDefExprs }; function createUpdateStatements(nodeIndex, sourceSpan, expressions, allowEmptyExprs) { const updateStmts = []; const exprs = expressions.map(({ sourceSpan, context, value }) => { const bindingId = `${updateBindingCount++}`; const nameResolver = context === COMP_VAR ? self : null; const { stmts, currValExpr } = convertPropertyBinding(nameResolver, context, value, bindingId, BindingForm.General); updateStmts.push(...stmts.map((stmt) => o.applySourceSpanToStatementIfNeeded(stmt, sourceSpan))); return o.applySourceSpanToExpressionIfNeeded(currValExpr, sourceSpan); }); if (expressions.length || allowEmptyExprs) { updateStmts.push(o.applySourceSpanToStatementIfNeeded(callCheckStmt(nodeIndex, exprs).toStmt(), sourceSpan)); } return updateStmts; } } _createElementHandleEventFn(nodeIndex, handlers) { const handleEventStmts = []; let handleEventBindingCount = 0; handlers.forEach(({ context, eventAst, dirAst }) => { const bindingId = `${handleEventBindingCount++}`; const nameResolver = context === COMP_VAR ? this : null; const { stmts, allowDefault } = convertActionBinding(nameResolver, context, eventAst.handler, bindingId); const trueStmts = stmts; if (allowDefault) { trueStmts.push(ALLOW_DEFAULT_VAR.set(allowDefault.and(ALLOW_DEFAULT_VAR)).toStmt()); } const { target: eventTarget, name: eventName } = elementEventNameAndTarget(eventAst, dirAst); const fullEventName = elementEventFullName(eventTarget, eventName); handleEventStmts.push(o.applySourceSpanToStatementIfNeeded(new o.IfStmt(o.literal(fullEventName).identical(EVENT_NAME_VAR), trueStmts), eventAst.sourceSpan)); }); let handleEventFn; if (handleEventStmts.length > 0) { const preStmts = [ALLOW_DEFAULT_VAR.set(o.literal(true)).toDeclStmt(o.BOOL_TYPE)]; if (!this.component.isHost && o.findReadVarNames(handleEventStmts).has(COMP_VAR.name)) { preStmts.push(COMP_VAR.set(VIEW_VAR.prop('component')).toDeclStmt(this.compType)); } handleEventFn = o.fn([ new o.FnParam(VIEW_VAR.name, o.INFERRED_TYPE), new o.FnParam(EVENT_NAME_VAR.name, o.INFERRED_TYPE), new o.FnParam(EventHandlerVars.event.name, o.INFERRED_TYPE) ], [...preStmts, ...handleEventStmts, new o.ReturnStatement(ALLOW_DEFAULT_VAR)], o.INFERRED_TYPE); } else { handleEventFn = o.NULL_EXPR; } return handleEventFn; } visitDirective(ast, context) { } visitDirectiveProperty(ast, context) { } visitReference(ast, context) { } visitVariable(ast, context) { } visitEvent(ast, context) { } visitElementProperty(ast, context) { } visitAttr(ast, context) { } } function needsAdditionalRootNode(astNodes) { const lastAstNode = astNodes[astNodes.length - 1]; if (lastAstNode instanceof EmbeddedTemplateAst) { return lastAstNode.hasViewContainer; } if (lastAstNode instanceof ElementAst) { if (isNgContainer(lastAstNode.name) && lastAstNode.children.length) { return needsAdditionalRootNode(lastAstNode.children); } return lastAstNode.hasViewContainer; } return lastAstNode instanceof NgContentAst; } function elementBindingDef(inputAst, dirAst) { const inputType = inputAst.type; switch (inputType) { case 1 /* Attribute */: return o.literalArr([ o.literal(1 /* TypeElementAttribute */), o.literal(inputAst.name), o.literal(inputAst.securityContext) ]); case 0 /* Property */: return o.literalArr([ o.literal(8 /* TypeProperty */), o.literal(inputAst.name), o.literal(inputAst.securityContext) ]); case 4 /* Animation */: const bindingType = 8 /* TypeProperty */ | (dirAst && dirAst.directive.isComponent ? 32 /* SyntheticHostProperty */ : 16 /* SyntheticProperty */); return o.literalArr([ o.literal(bindingType), o.literal('@' + inputAst.name), o.literal(inputAst.securityContext) ]); case 2 /* Class */: return o.literalArr([o.literal(2 /* TypeElementClass */), o.literal(inputAst.name), o.NULL_EXPR]); case 3 /* Style */: return o.literalArr([ o.literal(4 /* TypeElementStyle */), o.literal(inputAst.name), o.literal(inputAst.unit) ]); default: // This default case is not needed by TypeScript compiler, as the switch is exhaustive. // However Closure Compiler does not understand that and reports an error in typed mode. // The `throw new Error` below works around the problem, and the unexpected: never variable // makes sure tsc still checks this code is unreachable. const unexpected = inputType; throw new Error(`unexpected ${unexpected}`); } } function fixedAttrsDef(elementAst) { const mapResult = Object.create(null); elementAst.attrs.forEach(attrAst => { mapResult[attrAst.name] = attrAst.value; }); elementAst.directives.forEach(dirAst => { Object.keys(dirAst.directive.hostAttributes).forEach(name => { const value = dirAst.directive.hostAttributes[name]; const prevValue = mapResult[name]; mapResult[name] = prevValue != null ? mergeAttributeValue(name, prevValue, value) : value; }); }); // Note: We need to sort to get a defined output order // for tests and for caching generated artifacts... return o.literalArr(Object.keys(mapResult).sort().map((attrName) => o.literalArr([o.literal(attrName), o.literal(mapResult[attrName])]))); } function mergeAttributeValue(attrName, attrValue1, attrValue2) { if (attrName == CLASS_ATTR || attrName == STYLE_ATTR) { return `${attrValue1} ${attrValue2}`; } else { return attrValue2; } } function callCheckStmt(nodeIndex, exprs) { if (exprs.length > 10) { return CHECK_VAR.callFn([VIEW_VAR, o.literal(nodeIndex), o.literal(1 /* Dynamic */), o.literalArr(exprs)]); } else { return CHECK_VAR.callFn([VIEW_VAR, o.literal(nodeIndex), o.literal(0 /* Inline */), ...exprs]); } } function elementEventNameAndTarget(eventAst, dirAst) { if (eventAst.isAnimation) { return { name: `@${eventAst.name}.${eventAst.phase}`, target: dirAst && dirAst.directive.isComponent ? 'component' : null }; } else { return eventAst; } } function calcQueryFlags(query) { let flags = 0 /* None */; // Note: We only make queries static that query for a single item and the user specifically // set the to be static. This is because of backwards compatibility with the old view compiler... if (query.first && query.static) { flags |= 268435456 /* StaticQuery */; } else { flags |= 536870912 /* DynamicQuery */; } if (query.emitDistinctChangesOnly) { flags |= -2147483648 /* EmitDistinctChangesOnly */; } return flags; } export function elementEventFullName(target, name) { return target ? `${target}:${name}` : name; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlld19jb21waWxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy92aWV3X2NvbXBpbGVyL3ZpZXdfY29tcGlsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFxRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFFeEosT0FBTyxFQUFDLFdBQVcsRUFBb0Isb0JBQW9CLEVBQUUsc0JBQXNCLEVBQUUsOEJBQThCLEVBQUUsZ0JBQWdCLEVBQWdCLE1BQU0sdUNBQXVDLENBQUM7QUFFbk0sT0FBTyxFQUE2Qix1QkFBdUIsRUFBeUQsTUFBTSxTQUFTLENBQUM7QUFFcEksT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQzNDLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQztBQUN0RCxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDaEQsT0FBTyxLQUFLLENBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUMxQyxPQUFPLEVBQUMsdUJBQXVCLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUU3RCxPQUFPLEVBQXlHLFVBQVUsRUFBRSxtQkFBbUIsRUFBRSxZQUFZLEVBQStGLGdCQUFnQixFQUF1QixNQUFNLGlDQUFpQyxDQUFDO0FBRTNVLE9BQU8sRUFBQyxtQ0FBbUMsRUFBRSxNQUFNLEVBQUUsdUJBQXVCLEVBQUUsV0FBVyxFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFFdEgsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDO0FBQzNCLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQztBQUMzQixNQUFNLHFCQUFxQixHQUFHLFdBQVcsQ0FBQztBQUUxQyxNQUFNLE9BQU8saUJBQWlCO0lBQzVCLFlBQW1CLFlBQW9CLEVBQVMsZUFBdUI7UUFBcEQsaUJBQVksR0FBWixZQUFZLENBQVE7UUFBUyxvQkFBZSxHQUFmLGVBQWUsQ0FBUTtJQUFHLENBQUM7Q0FDNUU7QUFFRCxNQUFNLE9BQU8sWUFBWTtJQUN2QixZQUFvQixVQUE0QjtRQUE1QixlQUFVLEdBQVYsVUFBVSxDQUFrQjtJQUFHLENBQUM7SUFFcEQsZ0JBQWdCLENBQ1osU0FBd0IsRUFBRSxTQUFtQyxFQUFFLFFBQXVCLEVBQ3RGLE1BQW9CLEVBQUUsU0FBK0I7UUFDdkQsSUFBSSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7UUFFMUIsSUFBSSxzQkFBc0IsR0FBVyxTQUFVLENBQUM7UUFDaEQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUU7WUFDckIsTUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLFFBQVUsQ0FBQztZQUN0QyxNQUFNLGdCQUFnQixHQUF3QixFQUFFLENBQUM7WUFDakQsSUFBSSxRQUFRLENBQUMsVUFBVSxJQUFJLFFBQVEsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFO2dCQUNyRCxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsZUFBZSxDQUN2QyxXQUFXLEVBQUUsdUJBQXVCLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO2FBQ2xGO1lBRUQsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztZQUNsRixzQkFBc0IsR0FBRyxrQkFBa0IsQ0FBQyxJQUFLLENBQUM7WUFDbEQsU0FBUyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQ3JCLGtCQUFrQjtpQkFDYixHQUFHLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxjQUFjLENBQUM7b0JBQzlFLElBQUksQ0FBQyxDQUFDLGVBQWUsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLEVBQUUsS0FBSyxDQUFDO29CQUNoRixJQUFJLENBQUMsQ0FBQyxlQUFlLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUM7b0JBQzlDLElBQUksQ0FBQyxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsY0FBYyxDQUFDLGdCQUFnQixDQUFDLEVBQUUsS0FBSyxDQUFDO2lCQUM3RSxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUNKLFVBQVUsQ0FDUCxDQUFDLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsRUFDdkMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUMvRDtRQUVELE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxNQUF3QixFQUFlLEVBQUU7WUFDbkUsTUFBTSxpQkFBaUIsR0FBRyxpQkFBaUIsRUFBRSxDQUFDO1lBQzlDLE9BQU8sSUFBSSxXQUFXLENBQ2xCLElBQUksQ0FBQyxVQUFVLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxFQUMzRSxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFCLENBQUMsQ0FBQztRQUVGLE1BQU0sT0FBTyxHQUFHLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBRS9CLFNBQVMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFFOUMsT0FBTyxJQUFJLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsc0JBQXNCLENBQUMsQ0FBQztJQUN6RSxDQUFDO0NBQ0Y7QUFjRCxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ2pDLE1BQU0sUUFBUSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDbEMsTUFBTSxTQUFTLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNwQyxNQUFNLFFBQVEsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ25DLE1BQU0sY0FBYyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDeEMsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBRTNDLE1BQU0sV0FBVztJQWlCZixZQUNZLFNBQTJCLEVBQVUsU0FBd0IsRUFDN0QsTUFBd0IsRUFBVSxTQUFtQyxFQUNyRSxpQkFBeUIsRUFBVSxTQUErQixFQUNsRSxrQkFBc0M7UUFIdEMsY0FBUyxHQUFULFNBQVMsQ0FBa0I7UUFBVSxjQUFTLEdBQVQsU0FBUyxDQUFlO1FBQzdELFdBQU0sR0FBTixNQUFNLENBQWtCO1FBQVUsY0FBUyxHQUFULFNBQVMsQ0FBMEI7UUFDckUsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFRO1FBQVUsY0FBUyxHQUFULFNBQVMsQ0FBc0I7UUFDbEUsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUFvQjtRQW5CMUMsVUFBSyxHQU1OLEVBQUUsQ0FBQztRQUNGLHdCQUFtQixHQUFpQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hGLDZEQUE2RDtRQUNyRCxtQkFBYyxHQUFnQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2xFLGNBQVMsR0FBa0IsRUFBRSxDQUFDO1FBQzlCLGFBQVEsR0FBa0IsRUFBRSxDQUFDO1FBU25DLGdFQUFnRTtRQUNoRSxzRUFBc0U7UUFDdEUseUVBQXlFO1FBQ3pFLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3hDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUNoQixDQUFDLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUUsQ0FBQztRQUMzRSxJQUFJLENBQUMsUUFBUSxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDdkYsQ0FBQztJQUVELFFBQVEsQ0FBQyxTQUF3QixFQUFFLFFBQXVCO1FBQ3hELElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBQzNCLGtGQUFrRjtRQUNsRixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNoQixJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO2dCQUM5QixJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUU7b0JBQ2IsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztpQkFDcEU7WUFDSCxDQUFDLENBQUMsQ0FBQztTQUNKO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDaEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLFVBQVUsRUFBRSxFQUFFO2dCQUN2RCw0RUFBNEU7Z0JBQzVFLE1BQU0sT0FBTyxHQUFHLFVBQVUsR0FBRyxDQUFDLENBQUM7Z0JBQy9CLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxlQUF3QixDQUFDLFlBQXFCLENBQUM7Z0JBQ2hGLE1BQU0sS0FBSyxHQUFHLGdDQUEwQixjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQzlELElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7b0JBQ0wsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLFNBQVMsRUFBRSxLQUFLO29CQUNoQixPQUFPLEVBQUUsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDO3dCQUNqRCxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDO3dCQUNwQyxJQUFJLENBQUMsQ0FBQyxjQUFjLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxlQUFlLENBQ3ZDLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO3FCQUN6RCxDQUFDO2lCQUNILENBQUMsQ0FBQyxDQUFDO1lBQ3RCLENBQUMsQ0FBQyxDQUFDO1NBQ0o7UUFDRCxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDakMsSUFBSSxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksdUJBQXVCLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRTtZQUMvRSw2RkFBNkY7WUFDN0YsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztnQkFDTCxVQUFVLEVBQUUsSUFBSTtnQkFDaEIsU0FBUyxxQkFBdUI7Z0JBQ2hDLE9BQU8sRUFBRSxDQUFDLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxNQUFNLENBQUM7b0JBQ2xELENBQUMsQ0FBQyxPQUFPLGNBQWdCLEVBQUUsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO2lCQUNsRSxDQUFDO2FBQ0gsQ0FBQyxDQUFDLENBQUM7U0FDckI7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLG1CQUFrQyxFQUFFO1FBQ3hDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQztRQUVoRSxNQUFNLEVBQUMsbUJBQW1CLEVBQUUscUJBQXFCLEVBQUUsWUFBWSxFQUFDLEdBQzVELElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1FBRWxDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQ25FLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBR3ZFLElBQUksU0FBUyxlQUFpQixDQUFDO1FBQy9CLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsZUFBZSxLQUFLLHVCQUF1QixDQUFDLE1BQU0sRUFBRTtZQUNyRixTQUFTLGtCQUFvQixDQUFDO1NBQy9CO1FBQ0QsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLENBQUMsbUJBQW1CLENBQ3pDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUssQ0FBQyxDQUFDLEVBQzdDLENBQUMsSUFBSSxDQUFDLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQztnQkFDOUQsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUM7Z0JBQ3BCLENBQUMsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDO2dCQUMxQixrQkFBa0I7Z0JBQ2xCLGdCQUFnQjthQUNqQixDQUFDLENBQUMsQ0FBQyxFQUNKLENBQUMsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxFQUN4QyxJQUFJLENBQUMsaUJBQWlCLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRW5FLGdCQUFnQixDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNuQyxPQUFPLGdCQUFnQixDQUFDO0lBQzFCLENBQUM7SUFFTyxlQUFlLENBQUMsV0FBMEI7UUFDaEQsSUFBSSxRQUFzQixDQUFDO1FBQzNCLElBQUksV0FBVyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDMUIsTUFBTSxRQUFRLEdBQWtCLEVBQUUsQ0FBQztZQUNuQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSyxDQUFDLEVBQUU7Z0JBQ2pGLFFBQVEsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO2FBQ25GO1lBQ0QsUUFBUSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQ1g7Z0JBQ0UsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFLLEVBQUUsQ0FBQyxDQUFDLGFBQWEsQ0FBQztnQkFDL0MsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFLLEVBQUUsQ0FBQyxDQUFDLGFBQWEsQ0FBQzthQUMvQyxFQUNELENBQUMsR0FBRyxRQUFRLEVBQUUsR0FBRyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUM7U0FDckQ7YUFBTTtZQUNMLFFBQVEsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDO1NBQ3hCO1FBQ0QsT0FBTyxRQUFRLENBQUM7SUFDbEIsQ0FBQztJQUVELGNBQWMsQ0FBQyxHQUFpQixFQUFFLE9BQVk7UUFDNUMsZ0VBQWdFO1FBQ2hFLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDTCxVQUFVLEVBQUUsR0FBRyxDQUFDLFVBQVU7WUFDMUIsU0FBUyx1QkFBeUI7WUFDbEMsT0FBTyxFQUFFLENBQUMsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQztpQkFDakMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztTQUM1RSxDQUFDLENBQUMsQ0FBQztJQUN0QixDQUFDO0lBRUQsU0FBUyxDQUFDLEdBQVksRUFBRSxPQUFZO1FBQ2xDLDJDQUEyQztRQUMzQyxNQUFNLFVBQVUsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN0QixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQ0wsVUFBVSxFQUFFLEdBQUcsQ0FBQyxVQUFVO1lBQzFCLFNBQVMsa0JBQW9CO1lBQzdCLE9BQU8sRUFBRSxDQUFDLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUM7Z0JBQ2hELENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDO2dCQUNyQixDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUM7Z0JBQzdCLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO2FBQ3JDLENBQUM7U0FDSCxDQUFDLENBQUMsQ0F