UNPKG

@angular/compiler

Version:

Angular - the compiler library

873 lines • 154 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 */ (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