@angular/compiler
Version:
Angular - the compiler library
684 lines • 123 kB
JavaScript
/**
* @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 { identifierName, sanitizeIdentifier } from '../../compile_metadata';
import { BindingForm, convertPropertyBinding } from '../../compiler_util/expression_converter';
import * as core from '../../core';
import { DEFAULT_INTERPOLATION_CONFIG } from '../../ml_parser/interpolation_config';
import * as o from '../../output/output_ast';
import { CssSelector, SelectorMatcher } from '../../selector';
import { ShadowCss } from '../../shadow_css';
import { CONTENT_ATTR, HOST_ATTR } from '../../style_compiler';
import { error } from '../../util';
import { BoundEvent } from '../r3_ast';
import { compileFactoryFunction, R3FactoryTarget } from '../r3_factory';
import { Identifiers as R3 } from '../r3_identifiers';
import { prepareSyntheticListenerFunctionName, prepareSyntheticPropertyName, typeWithParameters } from '../util';
import { MIN_STYLING_BINDING_SLOTS_REQUIRED, StylingBuilder } 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';
const EMPTY_ARRAY = [];
// This regex matches any binding names that contain the "attr." prefix, e.g. "attr.required"
// If there is a match, the first matching group will contain the attribute name to bind.
const ATTR_REGEX = /attr\.([^\]]+)/;
function baseDirectiveFields(meta, constantPool, bindingParser) {
const definitionMap = new DefinitionMap();
const selectors = core.parseSelectorToR3Selector(meta.selector);
// e.g. `type: MyDirective`
definitionMap.set('type', meta.internalType);
// e.g. `selectors: [['', 'someDir', '']]`
if (selectors.length > 0) {
definitionMap.set('selectors', asLiteral(selectors));
}
if (meta.queries.length > 0) {
// e.g. `contentQueries: (rf, ctx, dirIndex) => { ... }
definitionMap.set('contentQueries', createContentQueriesFunction(meta.queries, constantPool, meta.name));
}
if (meta.viewQueries.length) {
definitionMap.set('viewQuery', createViewQueriesFunction(meta.viewQueries, constantPool, meta.name));
}
// e.g. `hostBindings: (rf, ctx) => { ... }
definitionMap.set('hostBindings', createHostBindingsFunction(meta.host, meta.typeSourceSpan, bindingParser, constantPool, meta.selector || '', meta.name, definitionMap));
// e.g 'inputs: {a: 'a'}`
definitionMap.set('inputs', conditionallyCreateMapObjectLiteral(meta.inputs, true));
// e.g 'outputs: {a: 'a'}`
definitionMap.set('outputs', conditionallyCreateMapObjectLiteral(meta.outputs));
if (meta.exportAs !== null) {
definitionMap.set('exportAs', o.literalArr(meta.exportAs.map(e => o.literal(e))));
}
return definitionMap;
}
/**
* Add features to the definition map.
*/
function addFeatures(definitionMap, meta) {
// e.g. `features: [NgOnChangesFeature]`
const features = [];
const providers = meta.providers;
const viewProviders = meta.viewProviders;
if (providers || viewProviders) {
const args = [providers || new o.LiteralArrayExpr([])];
if (viewProviders) {
args.push(viewProviders);
}
features.push(o.importExpr(R3.ProvidersFeature).callFn(args));
}
if (meta.usesInheritance) {
features.push(o.importExpr(R3.InheritDefinitionFeature));
}
if (meta.fullInheritance) {
features.push(o.importExpr(R3.CopyDefinitionFeature));
}
if (meta.lifecycle.usesOnChanges) {
features.push(o.importExpr(R3.NgOnChangesFeature));
}
if (features.length) {
definitionMap.set('features', o.literalArr(features));
}
}
/**
* Compile a directive for the render3 runtime as defined by the `R3DirectiveMetadata`.
*/
export function compileDirectiveFromMetadata(meta, constantPool, bindingParser) {
const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser);
addFeatures(definitionMap, meta);
const expression = o.importExpr(R3.defineDirective).callFn([definitionMap.toLiteralMap()]);
const typeParams = createDirectiveTypeParams(meta);
const type = o.expressionType(o.importExpr(R3.DirectiveDefWithMeta, typeParams));
return { expression, type };
}
/**
* Compile a component for the render3 runtime as defined by the `R3ComponentMetadata`.
*/
export function compileComponentFromMetadata(meta, constantPool, bindingParser) {
const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser);
addFeatures(definitionMap, meta);
const selector = meta.selector && CssSelector.parse(meta.selector);
const firstSelector = selector && selector[0];
// e.g. `attr: ["class", ".my.app"]`
// This is optional an only included if the first selector of a component specifies attributes.
if (firstSelector) {
const selectorAttributes = firstSelector.getAttrs();
if (selectorAttributes.length) {
definitionMap.set('attrs', constantPool.getConstLiteral(o.literalArr(selectorAttributes.map(value => value != null ? o.literal(value) : o.literal(undefined))),
/* forceShared */ true));
}
}
// Generate the CSS matcher that recognize directive
let directiveMatcher = null;
if (meta.directives.length > 0) {
const matcher = new SelectorMatcher();
for (const { selector, expression } of meta.directives) {
matcher.addSelectables(CssSelector.parse(selector), expression);
}
directiveMatcher = matcher;
}
// e.g. `template: function MyComponent_Template(_ctx, _cm) {...}`
const templateTypeName = meta.name;
const templateName = templateTypeName ? `${templateTypeName}_Template` : null;
const directivesUsed = new Set();
const pipesUsed = new Set();
const changeDetection = meta.changeDetection;
const template = meta.template;
const templateBuilder = new TemplateDefinitionBuilder(constantPool, BindingScope.createRootScope(), 0, templateTypeName, null, null, templateName, directiveMatcher, directivesUsed, meta.pipes, pipesUsed, R3.namespaceHTML, meta.relativeContextFilePath, meta.i18nUseExternalIds);
const templateFunctionExpression = templateBuilder.buildTemplateFunction(template.nodes, []);
// We need to provide this so that dynamically generated components know what
// projected content blocks to pass through to the component when it is instantiated.
const ngContentSelectors = templateBuilder.getNgContentSelectors();
if (ngContentSelectors) {
definitionMap.set('ngContentSelectors', ngContentSelectors);
}
// e.g. `decls: 2`
definitionMap.set('decls', o.literal(templateBuilder.getConstCount()));
// e.g. `vars: 2`
definitionMap.set('vars', o.literal(templateBuilder.getVarCount()));
// Generate `consts` section of ComponentDef:
// - either as an array:
// `consts: [['one', 'two'], ['three', 'four']]`
// - or as a factory function in case additional statements are present (to support i18n):
// `consts: function() { var i18n_0; if (ngI18nClosureMode) {...} else {...} return [i18n_0]; }`
const { constExpressions, prepareStatements } = templateBuilder.getConsts();
if (constExpressions.length > 0) {
let constsExpr = o.literalArr(constExpressions);
// Prepare statements are present - turn `consts` into a function.
if (prepareStatements.length > 0) {
constsExpr = o.fn([], [...prepareStatements, new o.ReturnStatement(constsExpr)]);
}
definitionMap.set('consts', constsExpr);
}
definitionMap.set('template', templateFunctionExpression);
// e.g. `directives: [MyDirective]`
if (directivesUsed.size) {
let directivesExpr = o.literalArr(Array.from(directivesUsed));
if (meta.wrapDirectivesAndPipesInClosure) {
directivesExpr = o.fn([], [new o.ReturnStatement(directivesExpr)]);
}
definitionMap.set('directives', directivesExpr);
}
// e.g. `pipes: [MyPipe]`
if (pipesUsed.size) {
let pipesExpr = o.literalArr(Array.from(pipesUsed));
if (meta.wrapDirectivesAndPipesInClosure) {
pipesExpr = o.fn([], [new o.ReturnStatement(pipesExpr)]);
}
definitionMap.set('pipes', pipesExpr);
}
if (meta.encapsulation === null) {
meta.encapsulation = core.ViewEncapsulation.Emulated;
}
// e.g. `styles: [str1, str2]`
if (meta.styles && meta.styles.length) {
const styleValues = meta.encapsulation == core.ViewEncapsulation.Emulated ?
compileStyles(meta.styles, CONTENT_ATTR, HOST_ATTR) :
meta.styles;
const strings = styleValues.map(str => constantPool.getConstLiteral(o.literal(str)));
definitionMap.set('styles', o.literalArr(strings));
}
else if (meta.encapsulation === core.ViewEncapsulation.Emulated) {
// If there is no style, don't generate css selectors on elements
meta.encapsulation = core.ViewEncapsulation.None;
}
// Only set view encapsulation if it's not the default value
if (meta.encapsulation !== core.ViewEncapsulation.Emulated) {
definitionMap.set('encapsulation', o.literal(meta.encapsulation));
}
// e.g. `animation: [trigger('123', [])]`
if (meta.animations !== null) {
definitionMap.set('data', o.literalMap([{ key: 'animation', value: meta.animations, quoted: false }]));
}
// Only set the change detection flag if it's defined and it's not the default.
if (changeDetection != null && changeDetection !== core.ChangeDetectionStrategy.Default) {
definitionMap.set('changeDetection', o.literal(changeDetection));
}
const expression = o.importExpr(R3.defineComponent).callFn([definitionMap.toLiteralMap()]);
const typeParams = createDirectiveTypeParams(meta);
typeParams.push(stringArrayAsType(meta.template.ngContentSelectors));
const type = o.expressionType(o.importExpr(R3.ComponentDefWithMeta, typeParams));
return { expression, type };
}
/**
* A wrapper around `compileDirective` which depends on render2 global analysis data as its input
* instead of the `R3DirectiveMetadata`.
*
* `R3DirectiveMetadata` is computed from `CompileDirectiveMetadata` and other statically reflected
* information.
*/
export function compileDirectiveFromRender2(outputCtx, directive, reflector, bindingParser) {
const name = identifierName(directive.type);
name || error(`Cannot resolver the name of ${directive.type}`);
const definitionField = outputCtx.constantPool.propertyNameOf(1 /* Directive */);
const meta = directiveMetadataFromGlobalMetadata(directive, outputCtx, reflector);
const res = compileDirectiveFromMetadata(meta, outputCtx.constantPool, bindingParser);
const factoryRes = compileFactoryFunction(Object.assign(Object.assign({}, meta), { injectFn: R3.directiveInject, target: R3FactoryTarget.Directive }));
const ngFactoryDefStatement = new o.ClassStmt(name, null, [new o.ClassField('ɵfac', o.INFERRED_TYPE, [o.StmtModifier.Static], factoryRes.factory)], [], new o.ClassMethod(null, [], []), []);
const directiveDefStatement = new o.ClassStmt(name, null, [new o.ClassField(definitionField, o.INFERRED_TYPE, [o.StmtModifier.Static], res.expression)], [], new o.ClassMethod(null, [], []), []);
// Create the partial class to be merged with the actual class.
outputCtx.statements.push(ngFactoryDefStatement, directiveDefStatement);
}
/**
* A wrapper around `compileComponent` which depends on render2 global analysis data as its input
* instead of the `R3DirectiveMetadata`.
*
* `R3ComponentMetadata` is computed from `CompileDirectiveMetadata` and other statically reflected
* information.
*/
export function compileComponentFromRender2(outputCtx, component, render3Ast, reflector, bindingParser, directiveTypeBySel, pipeTypeByName) {
const name = identifierName(component.type);
name || error(`Cannot resolver the name of ${component.type}`);
const definitionField = outputCtx.constantPool.propertyNameOf(2 /* Component */);
const summary = component.toSummary();
// Compute the R3ComponentMetadata from the CompileDirectiveMetadata
const meta = Object.assign(Object.assign({}, directiveMetadataFromGlobalMetadata(component, outputCtx, reflector)), { selector: component.selector, template: { nodes: render3Ast.nodes, ngContentSelectors: render3Ast.ngContentSelectors }, directives: [], pipes: typeMapToExpressionMap(pipeTypeByName, outputCtx), viewQueries: queriesFromGlobalMetadata(component.viewQueries, outputCtx), wrapDirectivesAndPipesInClosure: false, styles: (summary.template && summary.template.styles) || EMPTY_ARRAY, encapsulation: (summary.template && summary.template.encapsulation) || core.ViewEncapsulation.Emulated, interpolation: DEFAULT_INTERPOLATION_CONFIG, animations: null, viewProviders: component.viewProviders.length > 0 ? new o.WrappedNodeExpr(component.viewProviders) : null, relativeContextFilePath: '', i18nUseExternalIds: true });
const res = compileComponentFromMetadata(meta, outputCtx.constantPool, bindingParser);
const factoryRes = compileFactoryFunction(Object.assign(Object.assign({}, meta), { injectFn: R3.directiveInject, target: R3FactoryTarget.Directive }));
const ngFactoryDefStatement = new o.ClassStmt(name, null, [new o.ClassField('ɵfac', o.INFERRED_TYPE, [o.StmtModifier.Static], factoryRes.factory)], [], new o.ClassMethod(null, [], []), []);
const componentDefStatement = new o.ClassStmt(name, null, [new o.ClassField(definitionField, o.INFERRED_TYPE, [o.StmtModifier.Static], res.expression)], [], new o.ClassMethod(null, [], []), []);
// Create the partial class to be merged with the actual class.
outputCtx.statements.push(ngFactoryDefStatement, componentDefStatement);
}
/**
* Compute `R3DirectiveMetadata` given `CompileDirectiveMetadata` and a `CompileReflector`.
*/
function directiveMetadataFromGlobalMetadata(directive, outputCtx, reflector) {
// The global-analysis based Ivy mode in ngc is no longer utilized/supported.
throw new Error('unsupported');
}
/**
* Convert `CompileQueryMetadata` into `R3QueryMetadata`.
*/
function queriesFromGlobalMetadata(queries, outputCtx) {
return queries.map(query => {
let read = null;
if (query.read && query.read.identifier) {
read = outputCtx.importExpr(query.read.identifier.reference);
}
return {
propertyName: query.propertyName,
first: query.first,
predicate: selectorsFromGlobalMetadata(query.selectors, outputCtx),
descendants: query.descendants,
read,
static: !!query.static
};
});
}
/**
* Convert `CompileTokenMetadata` for query selectors into either an expression for a predicate
* type, or a list of string predicates.
*/
function selectorsFromGlobalMetadata(selectors, outputCtx) {
if (selectors.length > 1 || (selectors.length == 1 && selectors[0].value)) {
const selectorStrings = selectors.map(value => value.value);
selectorStrings.some(value => !value) &&
error('Found a type among the string selectors expected');
return outputCtx.constantPool.getConstLiteral(o.literalArr(selectorStrings.map(value => o.literal(value))));
}
if (selectors.length == 1) {
const first = selectors[0];
if (first.identifier) {
return outputCtx.importExpr(first.identifier.reference);
}
}
error('Unexpected query form');
return o.NULL_EXPR;
}
function prepareQueryParams(query, constantPool) {
const parameters = [getQueryPredicate(query, constantPool), o.literal(query.descendants)];
if (query.read) {
parameters.push(query.read);
}
return parameters;
}
function convertAttributesToExpressions(attributes) {
const values = [];
for (let key of Object.getOwnPropertyNames(attributes)) {
const value = attributes[key];
values.push(o.literal(key), value);
}
return values;
}
// Define and update any content queries
function createContentQueriesFunction(queries, constantPool, name) {
const createStatements = [];
const updateStatements = [];
const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME);
for (const query of queries) {
const queryInstruction = query.static ? R3.staticContentQuery : R3.contentQuery;
// creation, e.g. r3.contentQuery(dirIndex, somePredicate, true, null);
createStatements.push(o.importExpr(queryInstruction)
.callFn([o.variable('dirIndex'), ...prepareQueryParams(query, constantPool)])
.toStmt());
// update, e.g. (r3.queryRefresh(tmp = r3.loadQuery()) && (ctx.someDir = tmp));
const temporary = tempAllocator();
const getQueryList = o.importExpr(R3.loadQuery).callFn([]);
const refresh = o.importExpr(R3.queryRefresh).callFn([temporary.set(getQueryList)]);
const updateDirective = o.variable(CONTEXT_NAME)
.prop(query.propertyName)
.set(query.first ? temporary.prop('first') : temporary);
updateStatements.push(refresh.and(updateDirective).toStmt());
}
const contentQueriesFnName = name ? `${name}_ContentQueries` : null;
return o.fn([
new o.FnParam(RENDER_FLAGS, o.NUMBER_TYPE), new o.FnParam(CONTEXT_NAME, null),
new o.FnParam('dirIndex', null)
], [
renderFlagCheckIfStmt(1 /* Create */, createStatements),
renderFlagCheckIfStmt(2 /* Update */, updateStatements)
], o.INFERRED_TYPE, null, contentQueriesFnName);
}
function stringAsType(str) {
return o.expressionType(o.literal(str));
}
function stringMapAsType(map) {
const mapValues = Object.keys(map).map(key => {
const value = Array.isArray(map[key]) ? map[key][0] : map[key];
return {
key,
value: o.literal(value),
quoted: true,
};
});
return o.expressionType(o.literalMap(mapValues));
}
function stringArrayAsType(arr) {
return arr.length > 0 ? o.expressionType(o.literalArr(arr.map(value => o.literal(value)))) :
o.NONE_TYPE;
}
function createDirectiveTypeParams(meta) {
// On the type side, remove newlines from the selector as it will need to fit into a TypeScript
// string literal, which must be on one line.
const selectorForType = meta.selector !== null ? meta.selector.replace(/\n/g, '') : null;
return [
typeWithParameters(meta.type.type, meta.typeArgumentCount),
selectorForType !== null ? stringAsType(selectorForType) : o.NONE_TYPE,
meta.exportAs !== null ? stringArrayAsType(meta.exportAs) : o.NONE_TYPE,
stringMapAsType(meta.inputs),
stringMapAsType(meta.outputs),
stringArrayAsType(meta.queries.map(q => q.propertyName)),
];
}
// Define and update any view queries
function createViewQueriesFunction(viewQueries, constantPool, name) {
const createStatements = [];
const updateStatements = [];
const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME);
viewQueries.forEach((query) => {
const queryInstruction = query.static ? R3.staticViewQuery : R3.viewQuery;
// creation, e.g. r3.viewQuery(somePredicate, true);
const queryDefinition = o.importExpr(queryInstruction).callFn(prepareQueryParams(query, constantPool));
createStatements.push(queryDefinition.toStmt());
// update, e.g. (r3.queryRefresh(tmp = r3.loadQuery()) && (ctx.someDir = tmp));
const temporary = tempAllocator();
const getQueryList = o.importExpr(R3.loadQuery).callFn([]);
const refresh = o.importExpr(R3.queryRefresh).callFn([temporary.set(getQueryList)]);
const updateDirective = o.variable(CONTEXT_NAME)
.prop(query.propertyName)
.set(query.first ? temporary.prop('first') : temporary);
updateStatements.push(refresh.and(updateDirective).toStmt());
});
const viewQueryFnName = name ? `${name}_Query` : null;
return o.fn([new o.FnParam(RENDER_FLAGS, o.NUMBER_TYPE), new o.FnParam(CONTEXT_NAME, null)], [
renderFlagCheckIfStmt(1 /* Create */, createStatements),
renderFlagCheckIfStmt(2 /* Update */, updateStatements)
], o.INFERRED_TYPE, null, viewQueryFnName);
}
// Return a host binding function or null if one is not necessary.
function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindingParser, constantPool, selector, name, definitionMap) {
const bindingContext = o.variable(CONTEXT_NAME);
const styleBuilder = new StylingBuilder(bindingContext);
const { styleAttr, classAttr } = hostBindingsMetadata.specialAttributes;
if (styleAttr !== undefined) {
styleBuilder.registerStyleAttr(styleAttr);
}
if (classAttr !== undefined) {
styleBuilder.registerClassAttr(classAttr);
}
const createStatements = [];
const updateStatements = [];
const hostBindingSourceSpan = typeSourceSpan;
const directiveSummary = metadataAsSummary(hostBindingsMetadata);
// Calculate host event bindings
const eventBindings = bindingParser.createDirectiveHostEventAsts(directiveSummary, hostBindingSourceSpan);
if (eventBindings && eventBindings.length) {
const listeners = createHostListeners(eventBindings, name);
createStatements.push(...listeners);
}
// Calculate the host property bindings
const bindings = bindingParser.createBoundHostProperties(directiveSummary, hostBindingSourceSpan);
const allOtherBindings = [];
// We need to calculate the total amount of binding slots required by
// all the instructions together before any value conversions happen.
// Value conversions may require additional slots for interpolation and
// bindings with pipes. These calculates happen after this block.
let totalHostVarsCount = 0;
bindings && bindings.forEach((binding) => {
const stylingInputWasSet = styleBuilder.registerInputBasedOnName(binding.name, binding.expression, hostBindingSourceSpan);
if (stylingInputWasSet) {
totalHostVarsCount += MIN_STYLING_BINDING_SLOTS_REQUIRED;
}
else {
allOtherBindings.push(binding);
totalHostVarsCount++;
}
});
let valueConverter;
const getValueConverter = () => {
if (!valueConverter) {
const hostVarsCountFn = (numSlots) => {
const originalVarsCount = totalHostVarsCount;
totalHostVarsCount += numSlots;
return originalVarsCount;
};
valueConverter = new ValueConverter(constantPool, () => error('Unexpected node'), // new nodes are illegal here
hostVarsCountFn, () => error('Unexpected pipe')); // pipes are illegal here
}
return valueConverter;
};
const propertyBindings = [];
const attributeBindings = [];
const syntheticHostBindings = [];
allOtherBindings.forEach((binding) => {
// resolve literal arrays and literal objects
const value = binding.expression.visit(getValueConverter());
const bindingExpr = bindingFn(bindingContext, value);
const { bindingName, instruction, isAttribute } = getBindingNameAndInstruction(binding);
const securityContexts = bindingParser.calcPossibleSecurityContexts(selector, bindingName, isAttribute)
.filter(context => context !== core.SecurityContext.NONE);
let sanitizerFn = null;
if (securityContexts.length) {
if (securityContexts.length === 2 &&
securityContexts.indexOf(core.SecurityContext.URL) > -1 &&
securityContexts.indexOf(core.SecurityContext.RESOURCE_URL) > -1) {
// Special case for some URL attributes (such as "src" and "href") that may be a part
// of different security contexts. In this case we use special santitization function and
// select the actual sanitizer at runtime based on a tag name that is provided while
// invoking sanitization function.
sanitizerFn = o.importExpr(R3.sanitizeUrlOrResourceUrl);
}
else {
sanitizerFn = resolveSanitizationFn(securityContexts[0], isAttribute);
}
}
const instructionParams = [o.literal(bindingName), bindingExpr.currValExpr];
if (sanitizerFn) {
instructionParams.push(sanitizerFn);
}
updateStatements.push(...bindingExpr.stmts);
if (instruction === R3.hostProperty) {
propertyBindings.push(instructionParams);
}
else if (instruction === R3.attribute) {
attributeBindings.push(instructionParams);
}
else if (instruction === R3.syntheticHostProperty) {
syntheticHostBindings.push(instructionParams);
}
else {
updateStatements.push(o.importExpr(instruction).callFn(instructionParams).toStmt());
}
});
if (propertyBindings.length > 0) {
updateStatements.push(chainedInstruction(R3.hostProperty, propertyBindings).toStmt());
}
if (attributeBindings.length > 0) {
updateStatements.push(chainedInstruction(R3.attribute, attributeBindings).toStmt());
}
if (syntheticHostBindings.length > 0) {
updateStatements.push(chainedInstruction(R3.syntheticHostProperty, syntheticHostBindings).toStmt());
}
// since we're dealing with directives/components and both have hostBinding
// functions, we need to generate a special hostAttrs instruction that deals
// with both the assignment of styling as well as static attributes to the host
// element. The instruction below will instruct all initial styling (styling
// that is inside of a host binding within a directive/component) to be attached
// to the host element alongside any of the provided host attributes that were
// collected earlier.
const hostAttrs = convertAttributesToExpressions(hostBindingsMetadata.attributes);
styleBuilder.assignHostAttrs(hostAttrs, definitionMap);
if (styleBuilder.hasBindings) {
// finally each binding that was registered in the statement above will need to be added to
// the update block of a component/directive templateFn/hostBindingsFn so that the bindings
// are evaluated and updated for the element.
styleBuilder.buildUpdateLevelInstructions(getValueConverter()).forEach(instruction => {
if (instruction.calls.length > 0) {
const calls = [];
instruction.calls.forEach(call => {
// we subtract a value of `1` here because the binding slot was already allocated
// at the top of this method when all the input bindings were counted.
totalHostVarsCount +=
Math.max(call.allocateBindingSlots - MIN_STYLING_BINDING_SLOTS_REQUIRED, 0);
calls.push(convertStylingCall(call, bindingContext, bindingFn));
});
updateStatements.push(chainedInstruction(instruction.reference, calls).toStmt());
}
});
}
if (totalHostVarsCount) {
definitionMap.set('hostVars', o.literal(totalHostVarsCount));
}
if (createStatements.length > 0 || updateStatements.length > 0) {
const hostBindingsFnName = name ? `${name}_HostBindings` : null;
const statements = [];
if (createStatements.length > 0) {
statements.push(renderFlagCheckIfStmt(1 /* Create */, createStatements));
}
if (updateStatements.length > 0) {
statements.push(renderFlagCheckIfStmt(2 /* Update */, updateStatements));
}
return o.fn([new o.FnParam(RENDER_FLAGS, o.NUMBER_TYPE), new o.FnParam(CONTEXT_NAME, null)], statements, o.INFERRED_TYPE, null, hostBindingsFnName);
}
return null;
}
function bindingFn(implicit, value) {
return convertPropertyBinding(null, implicit, value, 'b', BindingForm.Expression, () => error('Unexpected interpolation'));
}
function convertStylingCall(call, bindingContext, bindingFn) {
return call.params(value => bindingFn(bindingContext, value).currValExpr);
}
function getBindingNameAndInstruction(binding) {
let bindingName = binding.name;
let instruction;
// Check to see if this is an attr binding or a property binding
const attrMatches = bindingName.match(ATTR_REGEX);
if (attrMatches) {
bindingName = attrMatches[1];
instruction = R3.attribute;
}
else {
if (binding.isAnimation) {
bindingName = prepareSyntheticPropertyName(bindingName);
// host bindings that have a synthetic property (e.g. @foo) should always be rendered
// in the context of the component and not the parent. Therefore there is a special
// compatibility instruction available for this purpose.
instruction = R3.syntheticHostProperty;
}
else {
instruction = R3.hostProperty;
}
}
return { bindingName, instruction, isAttribute: !!attrMatches };
}
function createHostListeners(eventBindings, name) {
const listeners = [];
const syntheticListeners = [];
const instructions = [];
eventBindings.forEach(binding => {
let bindingName = binding.name && sanitizeIdentifier(binding.name);
const bindingFnName = binding.type === 1 /* Animation */ ?
prepareSyntheticListenerFunctionName(bindingName, binding.targetOrPhase) :
bindingName;
const handlerName = name && bindingName ? `${name}_${bindingFnName}_HostBindingHandler` : null;
const params = prepareEventListenerParameters(BoundEvent.fromParsedEvent(binding), handlerName);
if (binding.type == 1 /* Animation */) {
syntheticListeners.push(params);
}
else {
listeners.push(params);
}
});
if (syntheticListeners.length > 0) {
instructions.push(chainedInstruction(R3.syntheticHostListener, syntheticListeners).toStmt());
}
if (listeners.length > 0) {
instructions.push(chainedInstruction(R3.listener, listeners).toStmt());
}
return instructions;
}
function metadataAsSummary(meta) {
// clang-format off
return {
// This is used by the BindingParser, which only deals with listeners and properties. There's no
// need to pass attributes to it.
hostAttributes: {},
hostListeners: meta.listeners,
hostProperties: meta.properties,
};
// clang-format on
}
function typeMapToExpressionMap(map, outputCtx) {
// Convert each map entry into another entry where the value is an expression importing the type.
const entries = Array.from(map).map(([key, type]) => [key, outputCtx.importExpr(type)]);
return new Map(entries);
}
const HOST_REG_EXP = /^(?:\[([^\]]+)\])|(?:\(([^\)]+)\))$/;
export function parseHostBindings(host) {
const attributes = {};
const listeners = {};
const properties = {};
const specialAttributes = {};
for (const key of Object.keys(host)) {
const value = host[key];
const matches = key.match(HOST_REG_EXP);
if (matches === null) {
switch (key) {
case 'class':
if (typeof value !== 'string') {
// TODO(alxhub): make this a diagnostic.
throw new Error(`Class binding must be string`);
}
specialAttributes.classAttr = value;
break;
case 'style':
if (typeof value !== 'string') {
// TODO(alxhub): make this a diagnostic.
throw new Error(`Style binding must be string`);
}
specialAttributes.styleAttr = value;
break;
default:
if (typeof value === 'string') {
attributes[key] = o.literal(value);
}
else {
attributes[key] = value;
}
}
}
else if (matches[1 /* Binding */] != null) {
if (typeof value !== 'string') {
// TODO(alxhub): make this a diagnostic.
throw new Error(`Property binding must be string`);
}
// synthetic properties (the ones that have a `@` as a prefix)
// are still treated the same as regular properties. Therefore
// there is no point in storing them in a separate map.
properties[matches[1 /* Binding */]] = value;
}
else if (matches[2 /* Event */] != null) {
if (typeof value !== 'string') {
// TODO(alxhub): make this a diagnostic.
throw new Error(`Event binding must be string`);
}
listeners[matches[2 /* Event */]] = value;
}
}
return { attributes, listeners, properties, specialAttributes };
}
/**
* Verifies host bindings and returns the list of errors (if any). Empty array indicates that a
* given set of host bindings has no errors.
*
* @param bindings set of host bindings to verify.
* @param sourceSpan source span where host bindings were defined.
* @returns array of errors associated with a given set of host bindings.
*/
export function verifyHostBindings(bindings, sourceSpan) {
const summary = metadataAsSummary(bindings);
// TODO: abstract out host bindings verification logic and use it instead of
// creating events and properties ASTs to detect errors (FW-996)
const bindingParser = makeBindingParser();
bindingParser.createDirectiveHostEventAsts(summary, sourceSpan);
bindingParser.createBoundHostProperties(summary, sourceSpan);
return bindingParser.errors;
}
function compileStyles(styles, selector, hostSelector) {
const shadowCss = new ShadowCss();
return styles.map(style => {
return shadowCss.shimCssText(style, selector, hostSelector);
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcGlsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvcmVuZGVyMy92aWV3L2NvbXBpbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUdILE9BQU8sRUFBZ0csY0FBYyxFQUFFLGtCQUFrQixFQUFDLE1BQU0sd0JBQXdCLENBQUM7QUFFekssT0FBTyxFQUFDLFdBQVcsRUFBRSxzQkFBc0IsRUFBQyxNQUFNLDBDQUEwQyxDQUFDO0FBRTdGLE9BQU8sS0FBSyxJQUFJLE1BQU0sWUFBWSxDQUFDO0FBRW5DLE9BQU8sRUFBQyw0QkFBNEIsRUFBQyxNQUFNLHNDQUFzQyxDQUFDO0FBQ2xGLE9BQU8sS0FBSyxDQUFDLE1BQU0seUJBQXlCLENBQUM7QUFFN0MsT0FBTyxFQUFDLFdBQVcsRUFBRSxlQUFlLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUM1RCxPQUFPLEVBQUMsU0FBUyxFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFDM0MsT0FBTyxFQUFDLFlBQVksRUFBRSxTQUFTLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUU3RCxPQUFPLEVBQUMsS0FBSyxFQUFnQixNQUFNLFlBQVksQ0FBQztBQUNoRCxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sV0FBVyxDQUFDO0FBQ3JDLE9BQU8sRUFBQyxzQkFBc0IsRUFBd0IsZUFBZSxFQUEyQixNQUFNLGVBQWUsQ0FBQztBQUN0SCxPQUFPLEVBQUMsV0FBVyxJQUFJLEVBQUUsRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBRXBELE9BQU8sRUFBQyxvQ0FBb0MsRUFBRSw0QkFBNEIsRUFBRSxrQkFBa0IsRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUcvRyxPQUFPLEVBQUMsa0NBQWtDLEVBQUUsY0FBYyxFQUF5QixNQUFNLG1CQUFtQixDQUFDO0FBQzdHLE9BQU8sRUFBQyxZQUFZLEVBQUUsaUJBQWlCLEVBQUUsOEJBQThCLEVBQUUscUJBQXFCLEVBQUUscUJBQXFCLEVBQUUseUJBQXlCLEVBQUUsY0FBYyxFQUFDLE1BQU0sWUFBWSxDQUFDO0FBQ3BMLE9BQU8sRUFBQyxTQUFTLEVBQUUsa0JBQWtCLEVBQUUsbUNBQW1DLEVBQUUsWUFBWSxFQUFFLGFBQWEsRUFBRSxpQkFBaUIsRUFBRSxZQUFZLEVBQUUsY0FBYyxFQUFFLGtCQUFrQixFQUFDLE1BQU0sUUFBUSxDQUFDO0FBRTVMLE1BQU0sV0FBVyxHQUFVLEVBQUUsQ0FBQztBQUU5Qiw2RkFBNkY7QUFDN0YseUZBQXlGO0FBQ3pGLE1BQU0sVUFBVSxHQUFHLGdCQUFnQixDQUFDO0FBRXBDLFNBQVMsbUJBQW1CLENBQ3hCLElBQXlCLEVBQUUsWUFBMEIsRUFDckQsYUFBNEI7SUFDOUIsTUFBTSxhQUFhLEdBQUcsSUFBSSxhQUFhLEVBQUUsQ0FBQztJQUMxQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMseUJBQXlCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRWhFLDJCQUEyQjtJQUMzQixhQUFhLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7SUFFN0MsMENBQTBDO0lBQzFDLElBQUksU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7UUFDeEIsYUFBYSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7S0FDdEQ7SUFFRCxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtRQUMzQix1REFBdUQ7UUFDdkQsYUFBYSxDQUFDLEdBQUcsQ0FDYixnQkFBZ0IsRUFBRSw0QkFBNEIsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztLQUM1RjtJQUVELElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUU7UUFDM0IsYUFBYSxDQUFDLEdBQUcsQ0FDYixXQUFXLEVBQUUseUJBQXlCLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxZQUFZLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7S0FDeEY7SUFFRCwyQ0FBMkM7SUFDM0MsYUFBYSxDQUFDLEdBQUcsQ0FDYixjQUFjLEVBQ2QsMEJBQTBCLENBQ3RCLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLGNBQWMsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLElBQUksQ0FBQyxRQUFRLElBQUksRUFBRSxFQUNoRixJQUFJLENBQUMsSUFBSSxFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFFbkMseUJBQXlCO0lBQ3pCLGFBQWEsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLG1DQUFtQyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUVwRiwwQkFBMEI7SUFDMUIsYUFBYSxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQUUsbUNBQW1DLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFFaEYsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLElBQUksRUFBRTtRQUMxQixhQUFhLENBQUMsR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUNuRjtJQUVELE9BQU8sYUFBYSxDQUFDO0FBQ3ZCLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsV0FBVyxDQUFDLGFBQTRCLEVBQUUsSUFBNkM7SUFDOUYsd0NBQXdDO0lBQ3hDLE1BQU0sUUFBUSxHQUFtQixFQUFFLENBQUM7SUFFcEMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUNqQyxNQUFNLGFBQWEsR0FBSSxJQUE0QixDQUFDLGFBQWEsQ0FBQztJQUNsRSxJQUFJLFNBQVMsSUFBSSxhQUFhLEVBQUU7UUFDOUIsTUFBTSxJQUFJLEdBQUcsQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUN2RCxJQUFJLGFBQWEsRUFBRTtZQUNqQixJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1NBQzFCO1FBQ0QsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0tBQy9EO0lBRUQsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFO1FBQ3hCLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxDQUFDO0tBQzFEO0lBQ0QsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFO1FBQ3hCLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDO0tBQ3ZEO0lBQ0QsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsRUFBRTtRQUNoQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQztLQUNwRDtJQUNELElBQUksUUFBUSxDQUFDLE1BQU0sRUFBRTtRQUNuQixhQUFhLENBQUMsR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7S0FDdkQ7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFVBQVUsNEJBQTRCLENBQ3hDLElBQXlCLEVBQUUsWUFBMEIsRUFDckQsYUFBNEI7SUFDOUIsTUFBTSxhQUFhLEdBQUcsbUJBQW1CLENBQUMsSUFBSSxFQUFFLFlBQVksRUFBRSxhQUFhLENBQUMsQ0FBQztJQUM3RSxXQUFXLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2pDLE1BQU0sVUFBVSxHQUFHLENBQUMsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLGVBQWUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLGFBQWEsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFM0YsTUFBTSxVQUFVLEdBQUcseUJBQXlCLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkQsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxvQkFBb0IsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBRWpGLE9BQU8sRUFBQyxVQUFVLEVBQUUsSUFBSSxFQUFDLENBQUM7QUFDNUIsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLDRCQUE0QixDQUN4QyxJQUF5QixFQUFFLFlBQTBCLEVBQ3JELGFBQTRCO0lBQzlCLE1BQU0sYUFBYSxHQUFHLG1CQUFtQixDQUFDLElBQUksRUFBRSxZQUFZLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDN0UsV0FBVyxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUVqQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxJQUFJLFdBQVcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ25FLE1BQU0sYUFBYSxHQUFHLFFBQVEsSUFBSSxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFOUMsb0NBQW9DO0lBQ3BDLCtGQUErRjtJQUMvRixJQUFJLGFBQWEsRUFBRTtRQUNqQixNQUFNLGtCQUFrQixHQUFHLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNwRCxJQUFJLGtCQUFrQixDQUFDLE1BQU0sRUFBRTtZQUM3QixhQUFhLENBQUMsR0FBRyxDQUNiLE9BQU8sRUFDUCxZQUFZLENBQUMsZUFBZSxDQUN4QixDQUFDLENBQUMsVUFBVSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FDL0IsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7WUFDdEUsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztTQUNsQztLQUNGO0lBRUQsb0RBQW9EO0lBQ3BELElBQUksZ0JBQWdCLEdBQXlCLElBQUksQ0FBQztJQUVsRCxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtRQUM5QixNQUFNLE9BQU8sR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO1FBQ3RDLEtBQUssTUFBTSxFQUFDLFFBQVEsRUFBRSxVQUFVLEVBQUMsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ3BELE9BQU8sQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQztTQUNqRTtRQUNELGdCQUFnQixHQUFHLE9BQU8sQ0FBQztLQUM1QjtJQUVELGtFQUFrRTtJQUNsRSxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDbkMsTUFBTSxZQUFZLEdBQUcsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLEdBQUcsZ0JBQWdCLFdBQVcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBRTlFLE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxFQUFnQixDQUFDO0lBQy9DLE1BQU0sU0FBUyxHQUFHLElBQUksR0FBRyxFQUFnQixDQUFDO0lBQzFDLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUM7SUFFN0MsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUMvQixNQUFNLGVBQWUsR0FBRyxJQUFJLHlCQUF5QixDQUNqRCxZQUFZLEVBQUUsWUFBWSxDQUFDLGVBQWUsRUFBRSxFQUFFLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFDM0YsZ0JBQWdCLEVBQUUsY0FBYyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsQ0FBQyxhQUFhLEVBQ3pFLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUUzRCxNQUFNLDBCQUEwQixHQUFHLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRTdGLDZFQUE2RTtJQUM3RSxxRkFBcUY7SUFDckYsTUFBTSxrQkFBa0IsR0FBRyxlQUFlLENBQUMscUJBQXFCLEVBQUUsQ0FBQztJQUNuRSxJQUFJLGtCQUFrQixFQUFFO1FBQ3RCLGFBQWEsQ0FBQyxHQUFHLENBQUMsb0JBQW9CLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztLQUM3RDtJQUVELGtCQUFrQjtJQUNsQixhQUFhLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFdkUsaUJBQWlCO0lBQ2pCLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUVwRSw2Q0FBNkM7SUFDN0Msd0JBQXdCO0lBQ3hCLGtEQUFrRDtJQUNsRCwwRkFBMEY7SUFDMUYsa0dBQWtHO0lBQ2xHLE1BQU0sRUFBQyxnQkFBZ0IsRUFBRSxpQkFBaUIsRUFBQyxHQUFHLGVBQWUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUMxRSxJQUFJLGdCQUFnQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7UUFDL0IsSUFBSSxVQUFVLEdBQXNDLENBQUMsQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUNuRixrRUFBa0U7UUFDbEUsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQ2hDLFVBQVUsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNsRjtRQUNELGFBQWEsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0tBQ3pDO0lBRUQsYUFBYSxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsMEJBQTBCLENBQUMsQ0FBQztJQUUxRCxtQ0FBbUM7SUFDbkMsSUFBSSxjQUFjLENBQUMsSUFBSSxFQUFFO1FBQ3ZCLElBQUksY0FBYyxHQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztRQUM1RSxJQUFJLElBQUksQ0FBQywrQkFBK0IsRUFBRTtZQUN4QyxjQUFjLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxlQUFlLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ3BFO1FBQ0QsYUFBYSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsY0FBYyxDQUFDLENBQUM7S0FDakQ7SUFFRCx5QkFBeUI7SUFDekIsSUFBSSxTQUFTLENBQUMsSUFBSSxFQUFFO1FBQ2xCLElBQUksU0FBUyxHQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUNsRSxJQUFJLElBQUksQ0FBQywrQkFBK0IsRUFBRTtZQUN4QyxTQUFTLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQzFEO1FBQ0QsYUFBYSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLENBQUM7S0FDdkM7SUFFRCxJQUFJLElBQUksQ0FBQyxhQUFhLEtBQUssSUFBSSxFQUFFO1FBQy9CLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQztLQUN0RDtJQUVELDhCQUE4QjtJQUM5QixJQUFJLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUU7UUFDckMsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDdkUsYUFBYSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsWUFBWSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUM7WUFDckQsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUNoQixNQUFNLE9BQU8sR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNyRixhQUFhLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7S0FDcEQ7U0FBTSxJQUFJLElBQUksQ0FBQyxhQUFhLEtBQUssSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsRUFBRTtRQUNqRSxpRUFBaUU7UUFDakUsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDO0tBQ2xEO0lBRUQsNERBQTREO0lBQzVELElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxFQUFFO1FBQzFELGFBQWEsQ0FBQyxHQUFHLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7S0FDbkU7SUFFRCx5Q0FBeUM7SUFDekMsSUFBSSxJQUFJLENBQUMsVUFBVSxLQUFLLElBQUksRUFBRTtRQUM1QixhQUFhLENBQUMsR0FBRyxDQUNiLE1BQU0sRUFBRSxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsRUFBQyxHQUFHLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUN4RjtJQUVELCtFQUErRTtJQUMvRSxJQUFJLGVBQWUsSUFBSSxJQUFJLElBQUksZUFBZSxLQUFLLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxPQUFPLEVBQUU7UUFDdkYsYUFBYSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUM7S0FDbEU7SUFFRCxNQUFNLFVBQVUsR0FBRyxDQUFDLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxhQUFhLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRzNGLE1BQU0sVUFBVSxHQUFHLHlCQUF5QixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ25ELFVBQVUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7SUFDckUsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxvQkFBb0IsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBRWpGLE9BQU8sRUFBQyxVQUFVLEVBQUUsSUFBSSxFQUFDLENBQUM7QUFDNUIsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSwyQkFBMkIsQ0FDdkMsU0FBd0IsRUFBRSxTQUFtQyxFQUFFLFNBQTJCLEVBQzFGLGFBQTRCO0lBQzlCLE1BQU0sSUFBSSxHQUFHLGNBQWMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFFLENBQUM7SUFDN0MsSUFBSSxJQUFJLEtBQUssQ0FBQywrQkFBK0IsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFFL0QsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDLFlBQVksQ0FBQyxjQUFjLG1CQUEwQixDQUFDO0lBRXhGLE1BQU0sSUFBSSxHQUFHLG1DQUFtQyxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDbEYsTUFBTSxHQUFHLEdBQUcsNEJBQTRCLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxZQUFZLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDdEYsTUFBTSxVQUFVLEdBQUcsc0JBQXNCLGlDQUNqQyxJQUFJLEtBQUUsUUFBUSxFQUFFLEVBQUUsQ0FBQyxlQUFlLEVBQUUsTUFBTSxFQUFFLGVBQWUsQ0FBQyxTQUFTLElBQUUsQ0FBQztJQUNoRixNQUFNLHFCQUFxQixHQUFHLElBQUksQ0FBQyxDQUFDLFNBQVMsQ0FDekMsSUFBSSxFQUFFLElBQUksRUFDVixDQUFDLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUM1RixJQUFJLENBQUMsQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN6QyxNQUFNLHFCQUFxQixHQUFHLElBQUksQ0FBQyxDQUFDLFNBQVMsQ0FDekMsSUFBSSxFQUFFLElBQUksRUFDVixDQUFDLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQzdGLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUU3QywrREFBK0Q7SUFDL0QsU0FBUyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMscUJBQXFCLEVBQUUscUJBQXFCLENBQUMsQ0FBQztBQUMxRSxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLDJCQUEyQixDQUN2QyxTQUF3QixFQUFFLFNBQW1DLEVBQUUsVUFBOEIsRUFDN0YsU0FBMkIsRUFBRSxhQUE0QixFQUFFLGtCQUFvQyxFQUMvRixjQUFnQztJQUNsQyxNQUFNLElBQUksR0FBRyxjQUFjLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBRSxDQUFDO0lBQzdDLElBQUksSUFBSSxLQUFLLENBQUMsK0JBQStCLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBRS9ELE1BQU0sZUFBZSxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsY0FBYyxtQkFBMEIsQ0FBQztJQUV4RixNQUFNLE9BQU8sR0FBRyxTQUFTLENBQUMsU0FBUyxFQUFFLENBQUM7SUFFdEMsb0VBQW9FO0lBQ3BFLE1BQU0sSUFBSSxtQ0FDTCxtQ0FBbUMsQ0FBQyxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQyxLQUN2RSxRQUFRLEVBQUUsU0FBUyxDQUFDLFFBQVEsRUFDNUIsUUFBUSxFQUFFLEVBQUMsS0FBSyxFQUFFLFVBQVUsQ0FBQyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsVUFBVSxDQUFDLGtCQUFrQixFQUFDLEVBQ3RGLFVBQVUsRUFBRSxFQUFFLEVBQ2QsS0FBSyxFQUFFLHNCQUFzQixDQUFDLGNBQWMsRUFBRSxTQUFTLENBQUMsRUFDeEQsV0FBVyxFQUFFLHlCQUF5QixDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsU0FBUyxDQUFDLEVBQ3hFLCtCQUErQixFQUFFLEtBQUssRUFDdEMsTUFBTSxFQUFFLENBQUMsT0FBTyxDQUFDLFFBQVEsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLFdBQVcsRUFDcEUsYUFBYSxFQUNULENBQUMsT0FBTyxDQUFDLFFBQVEsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxJQUFJLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLEVBQzNGLGFBQWEsRUFBRSw0QkFBNEIsRUFDM0MsVUFBVSxFQUFFLElBQUksRUFDaEIsYUFBYSxFQUNULFNBQVMsQ0FBQyxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUM5Rix1QkFBdUIsRUFBRSxFQUFFLEVBQzNCLGtCQUFrQixFQUFFLElBQUksR0FDekIsQ0FBQztJQUNGLE1BQU0sR0FBRyxHQUFHLDRCQUE0QixDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsWUFBWSxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBQ3RGLE1BQU0sVUFBVSxHQUFHLHNCQUFzQixpQ0FDakMsSUFBSSxLQUFFLFFBQVEsRUFBRSxFQUFFLENBQUMsZUFBZSxFQUFFLE1BQU0sRUFBRSxlQUFlLENBQUMsU0FBUyxJQUFFLENBQUM7SUFDaEYsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQ3pDLElBQUksRUFBRSxJQUFJLEVBQ1YsQ0FBQyxJQUFJLENBQUMsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLEVB