@angular/compiler
Version:
Angular - the compiler library
834 lines • 118 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 * as cdAst from '../expression_parser/ast';
import { Identifiers } from '../identifiers';
import * as o from '../output/output_ast';
import { ParseSourceSpan } from '../parse_util';
export class EventHandlerVars {
}
EventHandlerVars.event = o.variable('$event');
export class ConvertActionBindingResult {
constructor(
/**
* Render2 compatible statements,
*/
stmts,
/**
* Variable name used with render2 compatible statements.
*/
allowDefault) {
this.stmts = stmts;
this.allowDefault = allowDefault;
/**
* This is bit of a hack. It converts statements which render2 expects to statements which are
* expected by render3.
*
* Example: `<div click="doSomething($event)">` will generate:
*
* Render3:
* ```
* const pd_b:any = ((<any>ctx.doSomething($event)) !== false);
* return pd_b;
* ```
*
* but render2 expects:
* ```
* return ctx.doSomething($event);
* ```
*/
// TODO(misko): remove this hack once we no longer support ViewEngine.
this.render3Stmts = stmts.map((statement) => {
if (statement instanceof o.DeclareVarStmt && statement.name == allowDefault.name &&
statement.value instanceof o.BinaryOperatorExpr) {
const lhs = statement.value.lhs;
return new o.ReturnStatement(lhs.value);
}
return statement;
});
}
}
/**
* Converts the given expression AST into an executable output AST, assuming the expression is
* used in an action binding (e.g. an event handler).
*/
export function convertActionBinding(localResolver, implicitReceiver, action, bindingId, interpolationFunction, baseSourceSpan, implicitReceiverAccesses, globals) {
if (!localResolver) {
localResolver = new DefaultLocalResolver(globals);
}
const actionWithoutBuiltins = convertPropertyBindingBuiltins({
createLiteralArrayConverter: (argCount) => {
// Note: no caching for literal arrays in actions.
return (args) => o.literalArr(args);
},
createLiteralMapConverter: (keys) => {
// Note: no caching for literal maps in actions.
return (values) => {
const entries = keys.map((k, i) => ({
key: k.key,
value: values[i],
quoted: k.quoted,
}));
return o.literalMap(entries);
};
},
createPipeConverter: (name) => {
throw new Error(`Illegal State: Actions are not allowed to contain pipes. Pipe: ${name}`);
}
}, action);
const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId, interpolationFunction, baseSourceSpan, implicitReceiverAccesses);
const actionStmts = [];
flattenStatements(actionWithoutBuiltins.visit(visitor, _Mode.Statement), actionStmts);
prependTemporaryDecls(visitor.temporaryCount, bindingId, actionStmts);
if (visitor.usesImplicitReceiver) {
localResolver.notifyImplicitReceiverUse();
}
const lastIndex = actionStmts.length - 1;
let preventDefaultVar = null;
if (lastIndex >= 0) {
const lastStatement = actionStmts[lastIndex];
const returnExpr = convertStmtIntoExpression(lastStatement);
if (returnExpr) {
// Note: We need to cast the result of the method call to dynamic,
// as it might be a void method!
preventDefaultVar = createPreventDefaultVar(bindingId);
actionStmts[lastIndex] =
preventDefaultVar.set(returnExpr.cast(o.DYNAMIC_TYPE).notIdentical(o.literal(false)))
.toDeclStmt(null, [o.StmtModifier.Final]);
}
}
return new ConvertActionBindingResult(actionStmts, preventDefaultVar);
}
export function convertPropertyBindingBuiltins(converterFactory, ast) {
return convertBuiltins(converterFactory, ast);
}
export class ConvertPropertyBindingResult {
constructor(stmts, currValExpr) {
this.stmts = stmts;
this.currValExpr = currValExpr;
}
}
export var BindingForm;
(function (BindingForm) {
// The general form of binding expression, supports all expressions.
BindingForm[BindingForm["General"] = 0] = "General";
// Try to generate a simple binding (no temporaries or statements)
// otherwise generate a general binding
BindingForm[BindingForm["TrySimple"] = 1] = "TrySimple";
// Inlines assignment of temporaries into the generated expression. The result may still
// have statements attached for declarations of temporary variables.
// This is the only relevant form for Ivy, the other forms are only used in ViewEngine.
BindingForm[BindingForm["Expression"] = 2] = "Expression";
})(BindingForm || (BindingForm = {}));
/**
* Converts the given expression AST into an executable output AST, assuming the expression
* is used in property binding. The expression has to be preprocessed via
* `convertPropertyBindingBuiltins`.
*/
export function convertPropertyBinding(localResolver, implicitReceiver, expressionWithoutBuiltins, bindingId, form, interpolationFunction) {
if (!localResolver) {
localResolver = new DefaultLocalResolver();
}
const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId, interpolationFunction);
const outputExpr = expressionWithoutBuiltins.visit(visitor, _Mode.Expression);
const stmts = getStatementsFromVisitor(visitor, bindingId);
if (visitor.usesImplicitReceiver) {
localResolver.notifyImplicitReceiverUse();
}
if (visitor.temporaryCount === 0 && form == BindingForm.TrySimple) {
return new ConvertPropertyBindingResult([], outputExpr);
}
else if (form === BindingForm.Expression) {
return new ConvertPropertyBindingResult(stmts, outputExpr);
}
const currValExpr = createCurrValueExpr(bindingId);
stmts.push(currValExpr.set(outputExpr).toDeclStmt(o.DYNAMIC_TYPE, [o.StmtModifier.Final]));
return new ConvertPropertyBindingResult(stmts, currValExpr);
}
/**
* Given some expression, such as a binding or interpolation expression, and a context expression to
* look values up on, visit each facet of the given expression resolving values from the context
* expression such that a list of arguments can be derived from the found values that can be used as
* arguments to an external update instruction.
*
* @param localResolver The resolver to use to look up expressions by name appropriately
* @param contextVariableExpression The expression representing the context variable used to create
* the final argument expressions
* @param expressionWithArgumentsToExtract The expression to visit to figure out what values need to
* be resolved and what arguments list to build.
* @param bindingId A name prefix used to create temporary variable names if they're needed for the
* arguments generated
* @returns An array of expressions that can be passed as arguments to instruction expressions like
* `o.importExpr(R3.propertyInterpolate).callFn(result)`
*/
export function convertUpdateArguments(localResolver, contextVariableExpression, expressionWithArgumentsToExtract, bindingId) {
const visitor = new _AstToIrVisitor(localResolver, contextVariableExpression, bindingId, undefined);
const outputExpr = expressionWithArgumentsToExtract.visit(visitor, _Mode.Expression);
if (visitor.usesImplicitReceiver) {
localResolver.notifyImplicitReceiverUse();
}
const stmts = getStatementsFromVisitor(visitor, bindingId);
// Removing the first argument, because it was a length for ViewEngine, not Ivy.
let args = outputExpr.args.slice(1);
if (expressionWithArgumentsToExtract instanceof cdAst.Interpolation) {
// If we're dealing with an interpolation of 1 value with an empty prefix and suffix, reduce the
// args returned to just the value, because we're going to pass it to a special instruction.
const strings = expressionWithArgumentsToExtract.strings;
if (args.length === 3 && strings[0] === '' && strings[1] === '') {
// Single argument interpolate instructions.
args = [args[1]];
}
else if (args.length >= 19) {
// 19 or more arguments must be passed to the `interpolateV`-style instructions, which accept
// an array of arguments
args = [o.literalArr(args)];
}
}
return { stmts, args };
}
function getStatementsFromVisitor(visitor, bindingId) {
const stmts = [];
for (let i = 0; i < visitor.temporaryCount; i++) {
stmts.push(temporaryDeclaration(bindingId, i));
}
return stmts;
}
function convertBuiltins(converterFactory, ast) {
const visitor = new _BuiltinAstConverter(converterFactory);
return ast.visit(visitor);
}
function temporaryName(bindingId, temporaryNumber) {
return `tmp_${bindingId}_${temporaryNumber}`;
}
function temporaryDeclaration(bindingId, temporaryNumber) {
return new o.DeclareVarStmt(temporaryName(bindingId, temporaryNumber));
}
function prependTemporaryDecls(temporaryCount, bindingId, statements) {
for (let i = temporaryCount - 1; i >= 0; i--) {
statements.unshift(temporaryDeclaration(bindingId, i));
}
}
var _Mode;
(function (_Mode) {
_Mode[_Mode["Statement"] = 0] = "Statement";
_Mode[_Mode["Expression"] = 1] = "Expression";
})(_Mode || (_Mode = {}));
function ensureStatementMode(mode, ast) {
if (mode !== _Mode.Statement) {
throw new Error(`Expected a statement, but saw ${ast}`);
}
}
function ensureExpressionMode(mode, ast) {
if (mode !== _Mode.Expression) {
throw new Error(`Expected an expression, but saw ${ast}`);
}
}
function convertToStatementIfNeeded(mode, expr) {
if (mode === _Mode.Statement) {
return expr.toStmt();
}
else {
return expr;
}
}
class _BuiltinAstConverter extends cdAst.AstTransformer {
constructor(_converterFactory) {
super();
this._converterFactory = _converterFactory;
}
visitPipe(ast, context) {
const args = [ast.exp, ...ast.args].map(ast => ast.visit(this, context));
return new BuiltinFunctionCall(ast.span, ast.sourceSpan, args, this._converterFactory.createPipeConverter(ast.name, args.length));
}
visitLiteralArray(ast, context) {
const args = ast.expressions.map(ast => ast.visit(this, context));
return new BuiltinFunctionCall(ast.span, ast.sourceSpan, args, this._converterFactory.createLiteralArrayConverter(ast.expressions.length));
}
visitLiteralMap(ast, context) {
const args = ast.values.map(ast => ast.visit(this, context));
return new BuiltinFunctionCall(ast.span, ast.sourceSpan, args, this._converterFactory.createLiteralMapConverter(ast.keys));
}
}
class _AstToIrVisitor {
constructor(_localResolver, _implicitReceiver, bindingId, interpolationFunction, baseSourceSpan, implicitReceiverAccesses) {
this._localResolver = _localResolver;
this._implicitReceiver = _implicitReceiver;
this.bindingId = bindingId;
this.interpolationFunction = interpolationFunction;
this.baseSourceSpan = baseSourceSpan;
this.implicitReceiverAccesses = implicitReceiverAccesses;
this._nodeMap = new Map();
this._resultMap = new Map();
this._currentTemporary = 0;
this.temporaryCount = 0;
this.usesImplicitReceiver = false;
}
visitUnary(ast, mode) {
let op;
switch (ast.operator) {
case '+':
op = o.UnaryOperator.Plus;
break;
case '-':
op = o.UnaryOperator.Minus;
break;
default:
throw new Error(`Unsupported operator ${ast.operator}`);
}
return convertToStatementIfNeeded(mode, new o.UnaryOperatorExpr(op, this._visit(ast.expr, _Mode.Expression), undefined, this.convertSourceSpan(ast.span)));
}
visitBinary(ast, mode) {
let op;
switch (ast.operation) {
case '+':
op = o.BinaryOperator.Plus;
break;
case '-':
op = o.BinaryOperator.Minus;
break;
case '*':
op = o.BinaryOperator.Multiply;
break;
case '/':
op = o.BinaryOperator.Divide;
break;
case '%':
op = o.BinaryOperator.Modulo;
break;
case '&&':
op = o.BinaryOperator.And;
break;
case '||':
op = o.BinaryOperator.Or;
break;
case '==':
op = o.BinaryOperator.Equals;
break;
case '!=':
op = o.BinaryOperator.NotEquals;
break;
case '===':
op = o.BinaryOperator.Identical;
break;
case '!==':
op = o.BinaryOperator.NotIdentical;
break;
case '<':
op = o.BinaryOperator.Lower;
break;
case '>':
op = o.BinaryOperator.Bigger;
break;
case '<=':
op = o.BinaryOperator.LowerEquals;
break;
case '>=':
op = o.BinaryOperator.BiggerEquals;
break;
case '??':
return this.convertNullishCoalesce(ast, mode);
default:
throw new Error(`Unsupported operation ${ast.operation}`);
}
return convertToStatementIfNeeded(mode, new o.BinaryOperatorExpr(op, this._visit(ast.left, _Mode.Expression), this._visit(ast.right, _Mode.Expression), undefined, this.convertSourceSpan(ast.span)));
}
visitChain(ast, mode) {
ensureStatementMode(mode, ast);
return this.visitAll(ast.expressions, mode);
}
visitConditional(ast, mode) {
const value = this._visit(ast.condition, _Mode.Expression);
return convertToStatementIfNeeded(mode, value.conditional(this._visit(ast.trueExp, _Mode.Expression), this._visit(ast.falseExp, _Mode.Expression), this.convertSourceSpan(ast.span)));
}
visitPipe(ast, mode) {
throw new Error(`Illegal state: Pipes should have been converted into functions. Pipe: ${ast.name}`);
}
visitImplicitReceiver(ast, mode) {
ensureExpressionMode(mode, ast);
this.usesImplicitReceiver = true;
return this._implicitReceiver;
}
visitThisReceiver(ast, mode) {
return this.visitImplicitReceiver(ast, mode);
}
visitInterpolation(ast, mode) {
ensureExpressionMode(mode, ast);
const args = [o.literal(ast.expressions.length)];
for (let i = 0; i < ast.strings.length - 1; i++) {
args.push(o.literal(ast.strings[i]));
args.push(this._visit(ast.expressions[i], _Mode.Expression));
}
args.push(o.literal(ast.strings[ast.strings.length - 1]));
if (this.interpolationFunction) {
return this.interpolationFunction(args);
}
return ast.expressions.length <= 9 ?
o.importExpr(Identifiers.inlineInterpolate).callFn(args) :
o.importExpr(Identifiers.interpolate).callFn([
args[0], o.literalArr(args.slice(1), undefined, this.convertSourceSpan(ast.span))
]);
}
visitKeyedRead(ast, mode) {
const leftMostSafe = this.leftMostSafeNode(ast);
if (leftMostSafe) {
return this.convertSafeAccess(ast, leftMostSafe, mode);
}
else {
return convertToStatementIfNeeded(mode, this._visit(ast.receiver, _Mode.Expression).key(this._visit(ast.key, _Mode.Expression)));
}
}
visitKeyedWrite(ast, mode) {
const obj = this._visit(ast.receiver, _Mode.Expression);
const key = this._visit(ast.key, _Mode.Expression);
const value = this._visit(ast.value, _Mode.Expression);
if (obj === this._implicitReceiver) {
this._localResolver.maybeRestoreView();
}
return convertToStatementIfNeeded(mode, obj.key(key).set(value));
}
visitLiteralArray(ast, mode) {
throw new Error(`Illegal State: literal arrays should have been converted into functions`);
}
visitLiteralMap(ast, mode) {
throw new Error(`Illegal State: literal maps should have been converted into functions`);
}
visitLiteralPrimitive(ast, mode) {
// For literal values of null, undefined, true, or false allow type interference
// to infer the type.
const type = ast.value === null || ast.value === undefined || ast.value === true || ast.value === true ?
o.INFERRED_TYPE :
undefined;
return convertToStatementIfNeeded(mode, o.literal(ast.value, type, this.convertSourceSpan(ast.span)));
}
_getLocal(name, receiver) {
if (this._localResolver.globals?.has(name) && receiver instanceof cdAst.ThisReceiver) {
return null;
}
return this._localResolver.getLocal(name);
}
visitPrefixNot(ast, mode) {
return convertToStatementIfNeeded(mode, o.not(this._visit(ast.expression, _Mode.Expression)));
}
visitNonNullAssert(ast, mode) {
return convertToStatementIfNeeded(mode, o.assertNotNull(this._visit(ast.expression, _Mode.Expression)));
}
visitPropertyRead(ast, mode) {
const leftMostSafe = this.leftMostSafeNode(ast);
if (leftMostSafe) {
return this.convertSafeAccess(ast, leftMostSafe, mode);
}
else {
let result = null;
const prevUsesImplicitReceiver = this.usesImplicitReceiver;
const receiver = this._visit(ast.receiver, _Mode.Expression);
if (receiver === this._implicitReceiver) {
result = this._getLocal(ast.name, ast.receiver);
if (result) {
// Restore the previous "usesImplicitReceiver" state since the implicit
// receiver has been replaced with a resolved local expression.
this.usesImplicitReceiver = prevUsesImplicitReceiver;
this.addImplicitReceiverAccess(ast.name);
}
}
if (result == null) {
result = receiver.prop(ast.name, this.convertSourceSpan(ast.span));
}
return convertToStatementIfNeeded(mode, result);
}
}
visitPropertyWrite(ast, mode) {
const receiver = this._visit(ast.receiver, _Mode.Expression);
const prevUsesImplicitReceiver = this.usesImplicitReceiver;
let varExpr = null;
if (receiver === this._implicitReceiver) {
const localExpr = this._getLocal(ast.name, ast.receiver);
if (localExpr) {
if (localExpr instanceof o.ReadPropExpr) {
// If the local variable is a property read expression, it's a reference
// to a 'context.property' value and will be used as the target of the
// write expression.
varExpr = localExpr;
// Restore the previous "usesImplicitReceiver" state since the implicit
// receiver has been replaced with a resolved local expression.
this.usesImplicitReceiver = prevUsesImplicitReceiver;
this.addImplicitReceiverAccess(ast.name);
}
else {
// Otherwise it's an error.
const receiver = ast.name;
const value = (ast.value instanceof cdAst.PropertyRead) ? ast.value.name : undefined;
throw new Error(`Cannot assign value "${value}" to template variable "${receiver}". Template variables are read-only.`);
}
}
}
// If no local expression could be produced, use the original receiver's
// property as the target.
if (varExpr === null) {
varExpr = receiver.prop(ast.name, this.convertSourceSpan(ast.span));
}
return convertToStatementIfNeeded(mode, varExpr.set(this._visit(ast.value, _Mode.Expression)));
}
visitSafePropertyRead(ast, mode) {
return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);
}
visitSafeKeyedRead(ast, mode) {
return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);
}
visitAll(asts, mode) {
return asts.map(ast => this._visit(ast, mode));
}
visitQuote(ast, mode) {
throw new Error(`Quotes are not supported for evaluation!
Statement: ${ast.uninterpretedExpression} located at ${ast.location}`);
}
visitCall(ast, mode) {
const convertedArgs = this.visitAll(ast.args, _Mode.Expression);
if (ast instanceof BuiltinFunctionCall) {
return convertToStatementIfNeeded(mode, ast.converter(convertedArgs));
}
const receiver = ast.receiver;
if (receiver instanceof cdAst.PropertyRead &&
receiver.receiver instanceof cdAst.ImplicitReceiver &&
!(receiver.receiver instanceof cdAst.ThisReceiver) && receiver.name === '$any') {
if (convertedArgs.length !== 1) {
throw new Error(`Invalid call to $any, expected 1 argument but received ${convertedArgs.length || 'none'}`);
}
return convertedArgs[0]
.cast(o.DYNAMIC_TYPE, this.convertSourceSpan(ast.span));
}
const leftMostSafe = this.leftMostSafeNode(ast);
if (leftMostSafe) {
return this.convertSafeAccess(ast, leftMostSafe, mode);
}
const call = this._visit(receiver, _Mode.Expression)
.callFn(convertedArgs, this.convertSourceSpan(ast.span));
return convertToStatementIfNeeded(mode, call);
}
_visit(ast, mode) {
const result = this._resultMap.get(ast);
if (result)
return result;
return (this._nodeMap.get(ast) || ast).visit(this, mode);
}
convertSafeAccess(ast, leftMostSafe, mode) {
// If the expression contains a safe access node on the left it needs to be converted to
// an expression that guards the access to the member by checking the receiver for blank. As
// execution proceeds from left to right, the left most part of the expression must be guarded
// first but, because member access is left associative, the right side of the expression is at
// the top of the AST. The desired result requires lifting a copy of the left part of the
// expression up to test it for blank before generating the unguarded version.
// Consider, for example the following expression: a?.b.c?.d.e
// This results in the ast:
// .
// / \
// ?. e
// / \
// . d
// / \
// ?. c
// / \
// a b
// The following tree should be generated:
//
// /---- ? ----\
// / | \
// a /--- ? ---\ null
// / | \
// . . null
// / \ / \
// . c . e
// / \ / \
// a b . d
// / \
// . c
// / \
// a b
//
// Notice that the first guard condition is the left hand of the left most safe access node
// which comes in as leftMostSafe to this routine.
let guardedExpression = this._visit(leftMostSafe.receiver, _Mode.Expression);
let temporary = undefined;
if (this.needsTemporaryInSafeAccess(leftMostSafe.receiver)) {
// If the expression has method calls or pipes then we need to save the result into a
// temporary variable to avoid calling stateful or impure code more than once.
temporary = this.allocateTemporary();
// Preserve the result in the temporary variable
guardedExpression = temporary.set(guardedExpression);
// Ensure all further references to the guarded expression refer to the temporary instead.
this._resultMap.set(leftMostSafe.receiver, temporary);
}
const condition = guardedExpression.isBlank();
// Convert the ast to an unguarded access to the receiver's member. The map will substitute
// leftMostNode with its unguarded version in the call to `this.visit()`.
if (leftMostSafe instanceof cdAst.SafeKeyedRead) {
this._nodeMap.set(leftMostSafe, new cdAst.KeyedRead(leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.receiver, leftMostSafe.key));
}
else {
this._nodeMap.set(leftMostSafe, new cdAst.PropertyRead(leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.nameSpan, leftMostSafe.receiver, leftMostSafe.name));
}
// Recursively convert the node now without the guarded member access.
const access = this._visit(ast, _Mode.Expression);
// Remove the mapping. This is not strictly required as the converter only traverses each node
// once but is safer if the conversion is changed to traverse the nodes more than once.
this._nodeMap.delete(leftMostSafe);
// If we allocated a temporary, release it.
if (temporary) {
this.releaseTemporary(temporary);
}
// Produce the conditional
return convertToStatementIfNeeded(mode, condition.conditional(o.NULL_EXPR, access));
}
convertNullishCoalesce(ast, mode) {
const left = this._visit(ast.left, _Mode.Expression);
const right = this._visit(ast.right, _Mode.Expression);
const temporary = this.allocateTemporary();
this.releaseTemporary(temporary);
// Generate the following expression. It is identical to how TS
// transpiles binary expressions with a nullish coalescing operator.
// let temp;
// (temp = a) !== null && temp !== undefined ? temp : b;
return convertToStatementIfNeeded(mode, temporary.set(left)
.notIdentical(o.NULL_EXPR)
.and(temporary.notIdentical(o.literal(undefined)))
.conditional(temporary, right));
}
// Given an expression of the form a?.b.c?.d.e then the left most safe node is
// the (a?.b). The . and ?. are left associative thus can be rewritten as:
// ((((a?.c).b).c)?.d).e. This returns the most deeply nested safe read or
// safe method call as this needs to be transformed initially to:
// a == null ? null : a.c.b.c?.d.e
// then to:
// a == null ? null : a.b.c == null ? null : a.b.c.d.e
leftMostSafeNode(ast) {
const visit = (visitor, ast) => {
return (this._nodeMap.get(ast) || ast).visit(visitor);
};
return ast.visit({
visitUnary(ast) {
return null;
},
visitBinary(ast) {
return null;
},
visitChain(ast) {
return null;
},
visitConditional(ast) {
return null;
},
visitCall(ast) {
return visit(this, ast.receiver);
},
visitImplicitReceiver(ast) {
return null;
},
visitThisReceiver(ast) {
return null;
},
visitInterpolation(ast) {
return null;
},
visitKeyedRead(ast) {
return visit(this, ast.receiver);
},
visitKeyedWrite(ast) {
return null;
},
visitLiteralArray(ast) {
return null;
},
visitLiteralMap(ast) {
return null;
},
visitLiteralPrimitive(ast) {
return null;
},
visitPipe(ast) {
return null;
},
visitPrefixNot(ast) {
return null;
},
visitNonNullAssert(ast) {
return null;
},
visitPropertyRead(ast) {
return visit(this, ast.receiver);
},
visitPropertyWrite(ast) {
return null;
},
visitQuote(ast) {
return null;
},
visitSafePropertyRead(ast) {
return visit(this, ast.receiver) || ast;
},
visitSafeKeyedRead(ast) {
return visit(this, ast.receiver) || ast;
}
});
}
// Returns true of the AST includes a method or a pipe indicating that, if the
// expression is used as the target of a safe property or method access then
// the expression should be stored into a temporary variable.
needsTemporaryInSafeAccess(ast) {
const visit = (visitor, ast) => {
return ast && (this._nodeMap.get(ast) || ast).visit(visitor);
};
const visitSome = (visitor, ast) => {
return ast.some(ast => visit(visitor, ast));
};
return ast.visit({
visitUnary(ast) {
return visit(this, ast.expr);
},
visitBinary(ast) {
return visit(this, ast.left) || visit(this, ast.right);
},
visitChain(ast) {
return false;
},
visitConditional(ast) {
return visit(this, ast.condition) || visit(this, ast.trueExp) || visit(this, ast.falseExp);
},
visitCall(ast) {
return true;
},
visitImplicitReceiver(ast) {
return false;
},
visitThisReceiver(ast) {
return false;
},
visitInterpolation(ast) {
return visitSome(this, ast.expressions);
},
visitKeyedRead(ast) {
return false;
},
visitKeyedWrite(ast) {
return false;
},
visitLiteralArray(ast) {
return true;
},
visitLiteralMap(ast) {
return true;
},
visitLiteralPrimitive(ast) {
return false;
},
visitPipe(ast) {
return true;
},
visitPrefixNot(ast) {
return visit(this, ast.expression);
},
visitNonNullAssert(ast) {
return visit(this, ast.expression);
},
visitPropertyRead(ast) {
return false;
},
visitPropertyWrite(ast) {
return false;
},
visitQuote(ast) {
return false;
},
visitSafePropertyRead(ast) {
return false;
},
visitSafeKeyedRead(ast) {
return false;
}
});
}
allocateTemporary() {
const tempNumber = this._currentTemporary++;
this.temporaryCount = Math.max(this._currentTemporary, this.temporaryCount);
return new o.ReadVarExpr(temporaryName(this.bindingId, tempNumber));
}
releaseTemporary(temporary) {
this._currentTemporary--;
if (temporary.name != temporaryName(this.bindingId, this._currentTemporary)) {
throw new Error(`Temporary ${temporary.name} released out of order`);
}
}
/**
* Creates an absolute `ParseSourceSpan` from the relative `ParseSpan`.
*
* `ParseSpan` objects are relative to the start of the expression.
* This method converts these to full `ParseSourceSpan` objects that
* show where the span is within the overall source file.
*
* @param span the relative span to convert.
* @returns a `ParseSourceSpan` for the given span or null if no
* `baseSourceSpan` was provided to this class.
*/
convertSourceSpan(span) {
if (this.baseSourceSpan) {
const start = this.baseSourceSpan.start.moveBy(span.start);
const end = this.baseSourceSpan.start.moveBy(span.end);
const fullStart = this.baseSourceSpan.fullStart.moveBy(span.start);
return new ParseSourceSpan(start, end, fullStart);
}
else {
return null;
}
}
/** Adds the name of an AST to the list of implicit receiver accesses. */
addImplicitReceiverAccess(name) {
if (this.implicitReceiverAccesses) {
this.implicitReceiverAccesses.add(name);
}
}
}
function flattenStatements(arg, output) {
if (Array.isArray(arg)) {
arg.forEach((entry) => flattenStatements(entry, output));
}
else {
output.push(arg);
}
}
class DefaultLocalResolver {
constructor(globals) {
this.globals = globals;
}
notifyImplicitReceiverUse() { }
maybeRestoreView() { }
getLocal(name) {
if (name === EventHandlerVars.event.name) {
return EventHandlerVars.event;
}
return null;
}
}
function createCurrValueExpr(bindingId) {
return o.variable(`currVal_${bindingId}`); // fix syntax highlighting: `
}
function createPreventDefaultVar(bindingId) {
return o.variable(`pd_${bindingId}`);
}
function convertStmtIntoExpression(stmt) {
if (stmt instanceof o.ExpressionStatement) {
return stmt.expr;
}
else if (stmt instanceof o.ReturnStatement) {
return stmt.value;
}
return null;
}
export class BuiltinFunctionCall extends cdAst.Call {
constructor(span, sourceSpan, args, converter) {
super(span, sourceSpan, new cdAst.EmptyExpr(span, sourceSpan), args, null);
this.converter = converter;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwcmVzc2lvbl9jb252ZXJ0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvY29tcGlsZXJfdXRpbC9leHByZXNzaW9uX2NvbnZlcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEtBQUssS0FBSyxNQUFNLDBCQUEwQixDQUFDO0FBQ2xELE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzQyxPQUFPLEtBQUssQ0FBQyxNQUFNLHNCQUFzQixDQUFDO0FBQzFDLE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFFOUMsTUFBTSxPQUFPLGdCQUFnQjs7QUFDcEIsc0JBQUssR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBVXRDLE1BQU0sT0FBTywwQkFBMEI7SUFLckM7SUFDSTs7T0FFRztJQUNJLEtBQW9CO0lBQzNCOztPQUVHO0lBQ0ksWUFBMkI7UUFKM0IsVUFBSyxHQUFMLEtBQUssQ0FBZTtRQUlwQixpQkFBWSxHQUFaLFlBQVksQ0FBZTtRQUNwQzs7Ozs7Ozs7Ozs7Ozs7OztXQWdCRztRQUNILHNFQUFzRTtRQUN0RSxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFzQixFQUFFLEVBQUU7WUFDdkQsSUFBSSxTQUFTLFlBQVksQ0FBQyxDQUFDLGNBQWMsSUFBSSxTQUFTLENBQUMsSUFBSSxJQUFJLFlBQVksQ0FBQyxJQUFJO2dCQUM1RSxTQUFTLENBQUMsS0FBSyxZQUFZLENBQUMsQ0FBQyxrQkFBa0IsRUFBRTtnQkFDbkQsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFpQixDQUFDO2dCQUM5QyxPQUFPLElBQUksQ0FBQyxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENB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