@angular/compiler
Version:
Angular - the compiler library
873 lines • 154 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
*/
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define("@angular/compiler/src/view_compiler/view_compiler", ["require", "exports", "tslib", "@angular/compiler/src/compile_metadata", "@angular/compiler/src/compiler_util/expression_converter", "@angular/compiler/src/core", "@angular/compiler/src/identifiers", "@angular/compiler/src/lifecycle_reflector", "@angular/compiler/src/ml_parser/tags", "@angular/compiler/src/output/output_ast", "@angular/compiler/src/output/value_util", "@angular/compiler/src/template_parser/template_ast", "@angular/compiler/src/view_compiler/provider_compiler"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.elementEventFullName = exports.ViewCompiler = exports.ViewCompileResult = void 0;
var tslib_1 = require("tslib");
var compile_metadata_1 = require("@angular/compiler/src/compile_metadata");
var expression_converter_1 = require("@angular/compiler/src/compiler_util/expression_converter");
var core_1 = require("@angular/compiler/src/core");
var identifiers_1 = require("@angular/compiler/src/identifiers");
var lifecycle_reflector_1 = require("@angular/compiler/src/lifecycle_reflector");
var tags_1 = require("@angular/compiler/src/ml_parser/tags");
var o = require("@angular/compiler/src/output/output_ast");
var value_util_1 = require("@angular/compiler/src/output/value_util");
var template_ast_1 = require("@angular/compiler/src/template_parser/template_ast");
var provider_compiler_1 = require("@angular/compiler/src/view_compiler/provider_compiler");
var CLASS_ATTR = 'class';
var STYLE_ATTR = 'style';
var IMPLICIT_TEMPLATE_VAR = '\$implicit';
var ViewCompileResult = /** @class */ (function () {
function ViewCompileResult(viewClassVar, rendererTypeVar) {
this.viewClassVar = viewClassVar;
this.rendererTypeVar = rendererTypeVar;
}
return ViewCompileResult;
}());
exports.ViewCompileResult = ViewCompileResult;
var ViewCompiler = /** @class */ (function () {
function ViewCompiler(_reflector) {
this._reflector = _reflector;
}
ViewCompiler.prototype.compileComponent = function (outputCtx, component, template, styles, usedPipes) {
var _a;
var _this = this;
var embeddedViewCount = 0;
var renderComponentVarName = undefined;
if (!component.isHost) {
var template_1 = component.template;
var customRenderData = [];
if (template_1.animations && template_1.animations.length) {
customRenderData.push(new o.LiteralMapEntry('animation', value_util_1.convertValueToOutputAst(outputCtx, template_1.animations), true));
}
var renderComponentVar = o.variable(compile_metadata_1.rendererTypeName(component.type.reference));
renderComponentVarName = renderComponentVar.name;
outputCtx.statements.push(renderComponentVar
.set(o.importExpr(identifiers_1.Identifiers.createRendererType2).callFn([new o.LiteralMapExpr([
new o.LiteralMapEntry('encapsulation', o.literal(template_1.encapsulation), false),
new o.LiteralMapEntry('styles', styles, false),
new o.LiteralMapEntry('data', new o.LiteralMapExpr(customRenderData), false)
])]))
.toDeclStmt(o.importType(identifiers_1.Identifiers.RendererType2), [o.StmtModifier.Final, o.StmtModifier.Exported]));
}
var viewBuilderFactory = function (parent) {
var embeddedViewIndex = embeddedViewCount++;
return new ViewBuilder(_this._reflector, outputCtx, parent, component, embeddedViewIndex, usedPipes, viewBuilderFactory);
};
var visitor = viewBuilderFactory(null);
visitor.visitAll([], template);
(_a = outputCtx.statements).push.apply(_a, tslib_1.__spread(visitor.build()));
return new ViewCompileResult(visitor.viewName, renderComponentVarName);
};
return ViewCompiler;
}());
exports.ViewCompiler = ViewCompiler;
var LOG_VAR = o.variable('_l');
var VIEW_VAR = o.variable('_v');
var CHECK_VAR = o.variable('_ck');
var COMP_VAR = o.variable('_co');
var EVENT_NAME_VAR = o.variable('en');
var ALLOW_DEFAULT_VAR = o.variable("ad");
var ViewBuilder = /** @class */ (function () {
function ViewBuilder(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 = compile_metadata_1.viewClassName(this.component.type.reference, this.embeddedViewIndex);
}
ViewBuilder.prototype.visitAll = function (variables, astNodes) {
var _this = this;
this.variables = variables;
// create the pipes for the pure pipes immediately, so that we know their indices.
if (!this.parent) {
this.usedPipes.forEach(function (pipe) {
if (pipe.pure) {
_this.purePipeNodeIndices[pipe.name] = _this._createPipe(null, pipe);
}
});
}
if (!this.parent) {
this.component.viewQueries.forEach(function (query, queryIndex) {
// Note: queries start with id 1 so we can use the number in a Bloom filter!
var queryId = queryIndex + 1;
var bindingType = query.first ? 0 /* First */ : 1 /* All */;
var flags = 134217728 /* TypeViewQuery */ | calcStaticDynamicQueryFlags(query);
_this.nodes.push(function () { return ({
sourceSpan: null,
nodeFlags: flags,
nodeDef: o.importExpr(identifiers_1.Identifiers.queryDef).callFn([
o.literal(flags), o.literal(queryId),
new o.LiteralMapExpr([new o.LiteralMapEntry(query.propertyName, o.literal(bindingType), false)])
])
}); });
});
}
template_ast_1.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(function () { return ({
sourceSpan: null,
nodeFlags: 1 /* TypeElement */,
nodeDef: o.importExpr(identifiers_1.Identifiers.anchorDef).callFn([
o.literal(0 /* None */), o.NULL_EXPR, o.NULL_EXPR, o.literal(0)
])
}); });
}
};
ViewBuilder.prototype.build = function (targetStatements) {
if (targetStatements === void 0) { targetStatements = []; }
this.children.forEach(function (child) { return child.build(targetStatements); });
var _a = this._createNodeExpressions(), updateRendererStmts = _a.updateRendererStmts, updateDirectivesStmts = _a.updateDirectivesStmts, nodeDefExprs = _a.nodeDefExprs;
var updateRendererFn = this._createUpdateFn(updateRendererStmts);
var updateDirectivesFn = this._createUpdateFn(updateDirectivesStmts);
var viewFlags = 0 /* None */;
if (!this.parent && this.component.changeDetection === core_1.ChangeDetectionStrategy.OnPush) {
viewFlags |= 2 /* OnPush */;
}
var viewFactory = new o.DeclareFunctionStmt(this.viewName, [new o.FnParam(LOG_VAR.name)], [new o.ReturnStatement(o.importExpr(identifiers_1.Identifiers.viewDef).callFn([
o.literal(viewFlags),
o.literalArr(nodeDefExprs),
updateDirectivesFn,
updateRendererFn,
]))], o.importType(identifiers_1.Identifiers.ViewDefinition), this.embeddedViewIndex === 0 ? [o.StmtModifier.Exported] : []);
targetStatements.push(viewFactory);
return targetStatements;
};
ViewBuilder.prototype._createUpdateFn = function (updateStmts) {
var updateFn;
if (updateStmts.length > 0) {
var 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)
], tslib_1.__spread(preStmts, updateStmts), o.INFERRED_TYPE);
}
else {
updateFn = o.NULL_EXPR;
}
return updateFn;
};
ViewBuilder.prototype.visitNgContent = function (ast, context) {
// ngContentDef(ngContentIndex: number, index: number): NodeDef;
this.nodes.push(function () { return ({
sourceSpan: ast.sourceSpan,
nodeFlags: 8 /* TypeNgContent */,
nodeDef: o.importExpr(identifiers_1.Identifiers.ngContentDef)
.callFn([o.literal(ast.ngContentIndex), o.literal(ast.index)])
}); });
};
ViewBuilder.prototype.visitText = function (ast, context) {
// Static text nodes have no check function
var checkIndex = -1;
this.nodes.push(function () { return ({
sourceSpan: ast.sourceSpan,
nodeFlags: 2 /* TypeText */,
nodeDef: o.importExpr(identifiers_1.Identifiers.textDef).callFn([
o.literal(checkIndex),
o.literal(ast.ngContentIndex),
o.literalArr([o.literal(ast.value)]),
])
}); });
};
ViewBuilder.prototype.visitBoundText = function (ast, context) {
var _this = this;
var nodeIndex = this.nodes.length;
// reserve the space in the nodeDefs array
this.nodes.push(null);
var astWithSource = ast.value;
var inter = astWithSource.ast;
var updateRendererExpressions = inter.expressions.map(function (expr, bindingIndex) { return _this._preprocessUpdateExpression({ nodeIndex: nodeIndex, bindingIndex: 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
var checkIndex = nodeIndex;
this.nodes[nodeIndex] = function () { return ({
sourceSpan: ast.sourceSpan,
nodeFlags: 2 /* TypeText */,
nodeDef: o.importExpr(identifiers_1.Identifiers.textDef).callFn([
o.literal(checkIndex),
o.literal(ast.ngContentIndex),
o.literalArr(inter.strings.map(function (s) { return o.literal(s); })),
]),
updateRenderer: updateRendererExpressions
}); };
};
ViewBuilder.prototype.visitEmbeddedTemplate = function (ast, context) {
var _this = this;
var nodeIndex = this.nodes.length;
// reserve the space in the nodeDefs array
this.nodes.push(null);
var _a = this._visitElementOrTemplate(nodeIndex, ast), flags = _a.flags, queryMatchesExpr = _a.queryMatchesExpr, hostEvents = _a.hostEvents;
var childVisitor = this.viewBuilderFactory(this);
this.children.push(childVisitor);
childVisitor.visitAll(ast.variables, ast.children);
var childCount = this.nodes.length - nodeIndex - 1;
// anchorDef(
// flags: NodeFlags, matchedQueries: [string, QueryValueType][], ngContentIndex: number,
// childCount: number, handleEventFn?: ElementHandleEventFn, templateFactory?:
// ViewDefinitionFactory): NodeDef;
this.nodes[nodeIndex] = function () { return ({
sourceSpan: ast.sourceSpan,
nodeFlags: 1 /* TypeElement */ | flags,
nodeDef: o.importExpr(identifiers_1.Identifiers.anchorDef).callFn([
o.literal(flags),
queryMatchesExpr,
o.literal(ast.ngContentIndex),
o.literal(childCount),
_this._createElementHandleEventFn(nodeIndex, hostEvents),
o.variable(childVisitor.viewName),
])
}); };
};
ViewBuilder.prototype.visitElement = function (ast, context) {
var _this = this;
var 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.
var elName = tags_1.isNgContainer(ast.name) ? null : ast.name;
var _a = this._visitElementOrTemplate(nodeIndex, ast), flags = _a.flags, usedEvents = _a.usedEvents, queryMatchesExpr = _a.queryMatchesExpr, dirHostBindings = _a.hostBindings, hostEvents = _a.hostEvents;
var inputDefs = [];
var updateRendererExpressions = [];
var outputDefs = [];
if (elName) {
var hostBindings = ast.inputs
.map(function (inputAst) { return ({
context: COMP_VAR,
inputAst: inputAst,
dirAst: null,
}); })
.concat(dirHostBindings);
if (hostBindings.length) {
updateRendererExpressions =
hostBindings.map(function (hostBinding, bindingIndex) { return _this._preprocessUpdateExpression({
context: hostBinding.context,
nodeIndex: nodeIndex,
bindingIndex: bindingIndex,
sourceSpan: hostBinding.inputAst.sourceSpan,
value: hostBinding.inputAst.value
}); });
inputDefs = hostBindings.map(function (hostBinding) { return elementBindingDef(hostBinding.inputAst, hostBinding.dirAst); });
}
outputDefs = usedEvents.map(function (_a) {
var _b = tslib_1.__read(_a, 2), target = _b[0], eventName = _b[1];
return o.literalArr([o.literal(target), o.literal(eventName)]);
});
}
template_ast_1.templateVisitAll(this, ast.children);
var childCount = this.nodes.length - nodeIndex - 1;
var compAst = ast.directives.find(function (dirAst) { return dirAst.directive.isComponent; });
var compRendererType = o.NULL_EXPR;
var 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
var checkIndex = nodeIndex;
this.nodes[nodeIndex] = function () { return ({
sourceSpan: ast.sourceSpan,
nodeFlags: 1 /* TypeElement */ | flags,
nodeDef: o.importExpr(identifiers_1.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
}); };
};
ViewBuilder.prototype._visitElementOrTemplate = function (nodeIndex, ast) {
var _this = this;
var flags = 0 /* None */;
if (ast.hasViewContainer) {
flags |= 16777216 /* EmbeddedViews */;
}
var usedEvents = new Map();
ast.outputs.forEach(function (event) {
var _a = elementEventNameAndTarget(event, null), name = _a.name, target = _a.target;
usedEvents.set(elementEventFullName(target, name), [target, name]);
});
ast.directives.forEach(function (dirAst) {
dirAst.hostEvents.forEach(function (event) {
var _a = elementEventNameAndTarget(event, dirAst), name = _a.name, target = _a.target;
usedEvents.set(elementEventFullName(target, name), [target, name]);
});
});
var hostBindings = [];
var hostEvents = [];
this._visitComponentFactoryResolverProvider(ast.directives);
ast.providers.forEach(function (providerAst) {
var dirAst = undefined;
ast.directives.forEach(function (localDirAst) {
if (localDirAst.directive.type.reference === compile_metadata_1.tokenReference(providerAst.token)) {
dirAst = localDirAst;
}
});
if (dirAst) {
var _a = _this._visitDirective(providerAst, dirAst, ast.references, ast.queryMatches, usedEvents), dirHostBindings = _a.hostBindings, dirHostEvents = _a.hostEvents;
hostBindings.push.apply(hostBindings, tslib_1.__spread(dirHostBindings));
hostEvents.push.apply(hostEvents, tslib_1.__spread(dirHostEvents));
}
else {
_this._visitProvider(providerAst, ast.queryMatches);
}
});
var queryMatchExprs = [];
ast.queryMatches.forEach(function (match) {
var valueType = undefined;
if (compile_metadata_1.tokenReference(match.value) ===
_this.reflector.resolveExternalReference(identifiers_1.Identifiers.ElementRef)) {
valueType = 0 /* ElementRef */;
}
else if (compile_metadata_1.tokenReference(match.value) ===
_this.reflector.resolveExternalReference(identifiers_1.Identifiers.ViewContainerRef)) {
valueType = 3 /* ViewContainerRef */;
}
else if (compile_metadata_1.tokenReference(match.value) ===
_this.reflector.resolveExternalReference(identifiers_1.Identifiers.TemplateRef)) {
valueType = 2 /* TemplateRef */;
}
if (valueType != null) {
queryMatchExprs.push(o.literalArr([o.literal(match.queryId), o.literal(valueType)]));
}
});
ast.references.forEach(function (ref) {
var valueType = undefined;
if (!ref.value) {
valueType = 1 /* RenderElement */;
}
else if (compile_metadata_1.tokenReference(ref.value) ===
_this.reflector.resolveExternalReference(identifiers_1.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(function (outputAst) {
hostEvents.push({ context: COMP_VAR, eventAst: outputAst, dirAst: null });
});
return {
flags: flags,
usedEvents: Array.from(usedEvents.values()),
queryMatchesExpr: queryMatchExprs.length ? o.literalArr(queryMatchExprs) : o.NULL_EXPR,
hostBindings: hostBindings,
hostEvents: hostEvents
};
};
ViewBuilder.prototype._visitDirective = function (providerAst, dirAst, refs, queryMatches, usedEvents) {
var _this = this;
var nodeIndex = this.nodes.length;
// reserve the space in the nodeDefs array so we can add children
this.nodes.push(null);
dirAst.directive.queries.forEach(function (query, queryIndex) {
var queryId = dirAst.contentQueryStartId + queryIndex;
var flags = 67108864 /* TypeContentQuery */ | calcStaticDynamicQueryFlags(query);
var bindingType = query.first ? 0 /* First */ : 1 /* All */;
_this.nodes.push(function () { return ({
sourceSpan: dirAst.sourceSpan,
nodeFlags: flags,
nodeDef: o.importExpr(identifiers_1.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.
var childCount = this.nodes.length - nodeIndex - 1;
var _a = this._visitProviderOrDirective(providerAst, queryMatches), flags = _a.flags, queryMatchExprs = _a.queryMatchExprs, providerExpr = _a.providerExpr, depsExpr = _a.depsExpr;
refs.forEach(function (ref) {
if (ref.value && compile_metadata_1.tokenReference(ref.value) === compile_metadata_1.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 */;
}
var inputDefs = dirAst.inputs.map(function (inputAst, inputIndex) {
var 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);
});
var outputDefs = [];
var dirMeta = dirAst.directive;
Object.keys(dirMeta.outputs).forEach(function (propName) {
var 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));
}
});
var updateDirectiveExpressions = [];
if (dirAst.inputs.length || (flags & (262144 /* DoCheck */ | 65536 /* OnInit */)) > 0) {
updateDirectiveExpressions =
dirAst.inputs.map(function (input, bindingIndex) { return _this._preprocessUpdateExpression({
nodeIndex: nodeIndex,
bindingIndex: bindingIndex,
sourceSpan: input.sourceSpan,
context: COMP_VAR,
value: input.value
}); });
}
var dirContextExpr = o.importExpr(identifiers_1.Identifiers.nodeValue).callFn([VIEW_VAR, o.literal(nodeIndex)]);
var hostBindings = dirAst.hostProperties.map(function (inputAst) { return ({
context: dirContextExpr,
dirAst: dirAst,
inputAst: inputAst,
}); });
var hostEvents = dirAst.hostEvents.map(function (hostEventAst) { return ({
context: dirContextExpr,
eventAst: hostEventAst,
dirAst: dirAst,
}); });
// Check index is the same as the node index during compilation
// They might only differ at runtime
var checkIndex = nodeIndex;
this.nodes[nodeIndex] = function () { return ({
sourceSpan: dirAst.sourceSpan,
nodeFlags: 16384 /* TypeDirective */ | flags,
nodeDef: o.importExpr(identifiers_1.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: hostBindings, hostEvents: hostEvents };
};
ViewBuilder.prototype._visitProvider = function (providerAst, queryMatches) {
this._addProviderNode(this._visitProviderOrDirective(providerAst, queryMatches));
};
ViewBuilder.prototype._visitComponentFactoryResolverProvider = function (directives) {
var componentDirMeta = directives.find(function (dirAst) { return dirAst.directive.isComponent; });
if (componentDirMeta && componentDirMeta.directive.entryComponents.length) {
var _a = provider_compiler_1.componentFactoryResolverProviderDef(this.reflector, this.outputCtx, 8192 /* PrivateProvider */, componentDirMeta.directive.entryComponents), providerExpr = _a.providerExpr, depsExpr = _a.depsExpr, flags = _a.flags, tokenExpr = _a.tokenExpr;
this._addProviderNode({
providerExpr: providerExpr,
depsExpr: depsExpr,
flags: flags,
tokenExpr: tokenExpr,
queryMatchExprs: [],
sourceSpan: componentDirMeta.sourceSpan
});
}
};
ViewBuilder.prototype._addProviderNode = function (data) {
// providerDef(
// flags: NodeFlags, matchedQueries: [string, QueryValueType][], token:any,
// value: any, deps: ([DepFlags, any] | any)[]): NodeDef;
this.nodes.push(function () { return ({
sourceSpan: data.sourceSpan,
nodeFlags: data.flags,
nodeDef: o.importExpr(identifiers_1.Identifiers.providerDef).callFn([
o.literal(data.flags),
data.queryMatchExprs.length ? o.literalArr(data.queryMatchExprs) : o.NULL_EXPR,
data.tokenExpr, data.providerExpr, data.depsExpr
])
}); });
};
ViewBuilder.prototype._visitProviderOrDirective = function (providerAst, queryMatches) {
var flags = 0 /* None */;
var queryMatchExprs = [];
queryMatches.forEach(function (match) {
if (compile_metadata_1.tokenReference(match.value) === compile_metadata_1.tokenReference(providerAst.token)) {
queryMatchExprs.push(o.literalArr([o.literal(match.queryId), o.literal(4 /* Provider */)]));
}
});
var _a = provider_compiler_1.providerDef(this.outputCtx, providerAst), providerExpr = _a.providerExpr, depsExpr = _a.depsExpr, providerFlags = _a.flags, tokenExpr = _a.tokenExpr;
return {
flags: flags | providerFlags,
queryMatchExprs: queryMatchExprs,
providerExpr: providerExpr,
depsExpr: depsExpr,
tokenExpr: tokenExpr,
sourceSpan: providerAst.sourceSpan
};
};
ViewBuilder.prototype.getLocal = function (name) {
if (name == expression_converter_1.EventHandlerVars.event.name) {
return expression_converter_1.EventHandlerVars.event;
}
var currViewExpr = VIEW_VAR;
for (var currBuilder = this; currBuilder; currBuilder = currBuilder.parent,
currViewExpr = currViewExpr.prop('parent').cast(o.DYNAMIC_TYPE)) {
// check references
var refNodeIndex = currBuilder.refNodeIndices[name];
if (refNodeIndex != null) {
return o.importExpr(identifiers_1.Identifiers.nodeValue).callFn([currViewExpr, o.literal(refNodeIndex)]);
}
// check variables
var varAst = currBuilder.variables.find(function (varAst) { return varAst.name === name; });
if (varAst) {
var varValue = varAst.value || IMPLICIT_TEMPLATE_VAR;
return currViewExpr.prop('context').prop(varValue);
}
}
return null;
};
ViewBuilder.prototype.notifyImplicitReceiverUse = function () {
// Not needed in View Engine as View Engine 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.
};
ViewBuilder.prototype._createLiteralArrayConverter = function (sourceSpan, argCount) {
if (argCount === 0) {
var valueExpr_1 = o.importExpr(identifiers_1.Identifiers.EMPTY_ARRAY);
return function () { return valueExpr_1; };
}
var checkIndex = this.nodes.length;
this.nodes.push(function () { return ({
sourceSpan: sourceSpan,
nodeFlags: 32 /* TypePureArray */,
nodeDef: o.importExpr(identifiers_1.Identifiers.pureArrayDef).callFn([
o.literal(checkIndex),
o.literal(argCount),
])
}); });
return function (args) { return callCheckStmt(checkIndex, args); };
};
ViewBuilder.prototype._createLiteralMapConverter = function (sourceSpan, keys) {
if (keys.length === 0) {
var valueExpr_2 = o.importExpr(identifiers_1.Identifiers.EMPTY_MAP);
return function () { return valueExpr_2; };
}
var map = o.literalMap(keys.map(function (e, i) { return (tslib_1.__assign(tslib_1.__assign({}, e), { value: o.literal(i) })); }));
var checkIndex = this.nodes.length;
this.nodes.push(function () { return ({
sourceSpan: sourceSpan,
nodeFlags: 64 /* TypePureObject */,
nodeDef: o.importExpr(identifiers_1.Identifiers.pureObjectDef).callFn([
o.literal(checkIndex),
map,
])
}); });
return function (args) { return callCheckStmt(checkIndex, args); };
};
ViewBuilder.prototype._createPipeConverter = function (expression, name, argCount) {
var pipe = this.usedPipes.find(function (pipeSummary) { return pipeSummary.name === name; });
if (pipe.pure) {
var checkIndex_1 = this.nodes.length;
this.nodes.push(function () { return ({
sourceSpan: expression.sourceSpan,
nodeFlags: 128 /* TypePurePipe */,
nodeDef: o.importExpr(identifiers_1.Identifiers.purePipeDef).callFn([
o.literal(checkIndex_1),
o.literal(argCount),
])
}); });
// find underlying pipe in the component view
var compViewExpr = VIEW_VAR;
var compBuilder = this;
while (compBuilder.parent) {
compBuilder = compBuilder.parent;
compViewExpr = compViewExpr.prop('parent').cast(o.DYNAMIC_TYPE);
}
var pipeNodeIndex = compBuilder.purePipeNodeIndices[name];
var pipeValueExpr_1 = o.importExpr(identifiers_1.Identifiers.nodeValue).callFn([compViewExpr, o.literal(pipeNodeIndex)]);
return function (args) { return callUnwrapValue(expression.nodeIndex, expression.bindingIndex, callCheckStmt(checkIndex_1, [pipeValueExpr_1].concat(args))); };
}
else {
var nodeIndex = this._createPipe(expression.sourceSpan, pipe);
var nodeValueExpr_1 = o.importExpr(identifiers_1.Identifiers.nodeValue).callFn([VIEW_VAR, o.literal(nodeIndex)]);
return function (args) { return callUnwrapValue(expression.nodeIndex, expression.bindingIndex, nodeValueExpr_1.callMethod('transform', args)); };
}
};
ViewBuilder.prototype._createPipe = function (sourceSpan, pipe) {
var _this = this;
var nodeIndex = this.nodes.length;
var flags = 0 /* None */;
pipe.type.lifecycleHooks.forEach(function (lifecycleHook) {
// for pipes, we only support ngOnDestroy
if (lifecycleHook === lifecycle_reflector_1.LifecycleHooks.OnDestroy) {
flags |= provider_compiler_1.lifecycleHookToNodeFlag(lifecycleHook);
}
});
var depExprs = pipe.type.diDeps.map(function (diDep) { return provider_compiler_1.depDef(_this.outputCtx, diDep); });
// function pipeDef(
// flags: NodeFlags, ctor: any, deps: ([DepFlags, any] | any)[]): NodeDef
this.nodes.push(function () { return ({
sourceSpan: sourceSpan,
nodeFlags: 16 /* TypePipe */,
nodeDef: o.importExpr(identifiers_1.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)!
*/
ViewBuilder.prototype._preprocessUpdateExpression = function (expression) {
var _this = this;
return {
nodeIndex: expression.nodeIndex,
bindingIndex: expression.bindingIndex,
sourceSpan: expression.sourceSpan,
context: expression.context,
value: expression_converter_1.convertPropertyBindingBuiltins({
createLiteralArrayConverter: function (argCount) {
return _this._createLiteralArrayConverter(expression.sourceSpan, argCount);
},
createLiteralMapConverter: function (keys) {
return _this._createLiteralMapConverter(expression.sourceSpan, keys);
},
createPipeConverter: function (name, argCount) {
return _this._createPipeConverter(expression, name, argCount);
}
}, expression.value)
};
};
ViewBuilder.prototype._createNodeExpressions = function () {
var self = this;
var updateBindingCount = 0;
var updateRendererStmts = [];
var updateDirectivesStmts = [];
var nodeDefExprs = this.nodes.map(function (factory, nodeIndex) {
var _a = factory(), nodeDef = _a.nodeDef, nodeFlags = _a.nodeFlags, updateDirectives = _a.updateDirectives, updateRenderer = _a.updateRenderer, sourceSpan = _a.sourceSpan;
if (updateRenderer) {
updateRendererStmts.push.apply(updateRendererStmts, tslib_1.__spread(createUpdateStatements(nodeIndex, sourceSpan, updateRenderer, false)));
}
if (updateDirectives) {
updateDirectivesStmts.push.apply(updateDirectivesStmts, tslib_1.__spread(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.
var logWithNodeDef = nodeFlags & 3 /* CatRenderNode */ ?
new o.CommaExpr([LOG_VAR.callFn([]).callFn([]), nodeDef]) :
nodeDef;
return o.applySourceSpanToExpressionIfNeeded(logWithNodeDef, sourceSpan);
});
return { updateRendererStmts: updateRendererStmts, updateDirectivesStmts: updateDirectivesStmts, nodeDefExprs: nodeDefExprs };
function createUpdateStatements(nodeIndex, sourceSpan, expressions, allowEmptyExprs) {
var updateStmts = [];
var exprs = expressions.map(function (_a) {
var sourceSpan = _a.sourceSpan, context = _a.context, value = _a.value;
var bindingId = "" + updateBindingCount++;
var nameResolver = context === COMP_VAR ? self : null;
var _b = expression_converter_1.convertPropertyBinding(nameResolver, context, value, bindingId, expression_converter_1.BindingForm.General), stmts = _b.stmts, currValExpr = _b.currValExpr;
updateStmts.push.apply(updateStmts, tslib_1.__spread(stmts.map(function (stmt) { return o.applySourceSpanToStatementIfNeeded(stmt, sourceSpan); })));
return o.applySourceSpanToExpressionIfNeeded(currValExpr, sourceSpan);
});
if (expressions.length || allowEmptyExprs) {
updateStmts.push(o.applySourceSpanToStatementIfNeeded(callCheckStmt(nodeIndex, exprs).toStmt(), sourceSpan));
}
return updateStmts;
}
};
ViewBuilder.prototype._createElementHandleEventFn = function (nodeIndex, handlers) {
var _this = this;
var handleEventStmts = [];
var handleEventBindingCount = 0;
handlers.forEach(function (_a) {
var context = _a.context, eventAst = _a.eventAst, dirAst = _a.dirAst;
var bindingId = "" + handleEventBindingCount++;
var nameResolver = context === COMP_VAR ? _this : null;
var _b = expression_converter_1.convertActionBinding(nameResolver, context, eventAst.handler, bindingId), stmts = _b.stmts, allowDefault = _b.allowDefault;
var trueStmts = stmts;
if (allowDefault) {
trueStmts.push(ALLOW_DEFAULT_VAR.set(allowDefault.and(ALLOW_DEFAULT_VAR)).toStmt());
}
var _c = elementEventNameAndTarget(eventAst, dirAst), eventTarget = _c.target, eventName = _c.name;
var fullEventName = elementEventFullName(eventTarget, eventName);
handleEventStmts.push(o.applySourceSpanToStatementIfNeeded(new o.IfStmt(o.literal(fullEventName).identical(EVENT_NAME_VAR), trueStmts), eventAst.sourceSpan));
});
var handleEventFn;
if (handleEventStmts.length > 0) {
var 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(expression_converter_1.EventHandlerVars.event.name, o.INFERRED_TYPE)
], tslib_1.__spread(preStmts, handleEventStmts, [new o.ReturnStatement(ALLOW_DEFAULT_VAR)]), o.INFERRED_TYPE);
}
else {
handleEventFn = o.NULL_EXPR;
}
return handleEventFn;
};
ViewBuilder.prototype.visitDirective = function (ast, context) { };
ViewBuilder.prototype.visitDirectiveProperty = function (ast, context) { };
ViewBuilder.prototype.visitReference = function (ast, context) { };
ViewBuilder.prototype.visitVariable = function (ast, context) { };
ViewBuilder.prototype.visitEvent = function (ast, context) { };
ViewBuilder.prototype.visitElementProperty = function (ast, context) { };
ViewBuilder.prototype.visitAttr = function (ast, context) { };
return ViewBuilder;
}());
function needsAdditionalRootNode(astNodes) {
var lastAstNode = astNodes[astNodes.length - 1];
if (lastAstNode instanceof template_ast_1.EmbeddedTemplateAst) {
return lastAstNode.hasViewContainer;
}
if (lastAstNode instanceof template_ast_1.ElementAst) {
if (tags_1.isNgContainer(lastAstNode.name) && lastAstNode.children.length) {
return needsAdditionalRootNode(lastAstNode.children);
}
return lastAstNode.hasViewContainer;
}
return lastAstNode instanceof template_ast_1.NgContentAst;
}
function elementBindingDef(inputAst, dirAst) {
var 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 */:
var 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.
var unexpected = inputType;
throw new Error("unexpected " + unexpected);
}
}
function fixedAttrsDef(elementAst) {
var mapResult = Object.create(null);
elementAst.attrs.forEach(function (attrAst) {
mapResult[attrAst.name] = attrAst.value;
});
elementAst.directives.forEach(function (dirAst) {
Object.keys(dirAst.directive.hostAttributes).forEach(function (name) {
var value = dirAst.directive.hostAttributes[name];
var 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(function (attrName) { return 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(tslib_1.__spread([VIEW_VAR, o.literal(nodeIndex), o.literal(0 /* Inline */)], exprs));
}
}
function callUnwrapValue(nodeIndex, bindingIdx, expr) {
return o.importExpr(identifiers_1.Identifiers.unwrapValue).callFn([
VIEW_VAR, o.literal(nodeIndex), o.literal(bindingIdx), expr
]);
}
function elementEventNameAndTarget(eventAst, dirAst) {
if (eventAst.isAnimation) {
return {
name: "@" + eventAst.name + "." + eventAst.phase,
target: dirAst && dirAst.directive.isComponent ? 'component' : null
};
}
else {
return eventAst;
}
}
function calcStaticDynamicQueryFlags(query) {
var 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 */;
}
return flags;
}
function elementEventFullName(target, name) {
return target ? target + ":" + name : name;
}
exports.elementEventFullName = elementEventFullName;
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlld19jb21waWxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy92aWV3X2NvbXBpbGVyL3ZpZXdfY29tcGlsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7Ozs7OztJQUVILDJFQUF3SjtJQUV4SixpR0FBbU07SUFDbk0sbURBQW9JO0lBRXBJLGlFQUEyQztJQUMzQyxpRkFBc0Q7SUFDdEQsNkRBQWdEO0lBQ2hELDJEQUEwQztJQUMxQyxzRUFBNkQ7SUFFN0QsbUZBQTJVO0lBRzNVLDJGQUFzSDtJQUV0SCxJQUFNLFVBQVUsR0FBRyxPQUFPLENBQUM7SUFDM0IsSUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDO0lBQzNCLElBQU0scUJBQXFCLEdBQUcsWUFBWSxDQUFDO0lBRTNDO1FBQ0UsMkJBQW1CLFlBQW9CLEVBQVMsZUFBdUI7WUFBcEQsaUJBQVksR0FBWixZQUFZLENBQVE7WUFBUyxvQkFBZSxHQUFmLGVBQWUsQ0FBUTtRQUFHLENBQUM7UUFDN0Usd0JBQUM7SUFBRCxDQUFDLEFBRkQsSUFFQztJQUZZLDhDQUFpQjtJQUk5QjtRQUNFLHNCQUFvQixVQUE0QjtZQUE1QixlQUFVLEdBQVYsVUFBVSxDQUFrQjtRQUFHLENBQUM7UUFFcEQsdUNBQWdCLEdBQWhCLFVBQ0ksU0FBd0IsRUFBRSxTQUFtQyxFQUFFLFFBQXVCLEVBQ3RGLE1BQW9CLEVBQUUsU0FBK0I7O1lBRnpELGlCQXlDQztZQXRDQyxJQUFJLGlCQUFpQixHQUFHLENBQUMsQ0FBQztZQUUxQixJQUFJLHNCQUFzQixHQU