@aurelia/expression-parser
Version:
[](https://opensource.org/licenses/MIT) [](http://www.typescriptlang.org/) [ • 92 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var kernel = require('@aurelia/kernel');
/* eslint-disable @typescript-eslint/no-unused-vars */
/** @internal */ const ekAccessThis = 'AccessThis';
/** @internal */ const ekAccessBoundary = 'AccessBoundary';
/** @internal */ const ekAccessGlobal = 'AccessGlobal';
/** @internal */ const ekAccessScope = 'AccessScope';
/** @internal */ const ekArrayLiteral = 'ArrayLiteral';
/** @internal */ const ekObjectLiteral = 'ObjectLiteral';
/** @internal */ const ekPrimitiveLiteral = 'PrimitiveLiteral';
/** @internal */ const ekNew = 'New';
/** @internal */ const ekTemplate = 'Template';
/** @internal */ const ekUnary = 'Unary';
/** @internal */ const ekCallScope = 'CallScope';
/** @internal */ const ekCallMember = 'CallMember';
/** @internal */ const ekCallFunction = 'CallFunction';
/** @internal */ const ekCallGlobal = 'CallGlobal';
/** @internal */ const ekAccessMember = 'AccessMember';
/** @internal */ const ekAccessKeyed = 'AccessKeyed';
/** @internal */ const ekTaggedTemplate = 'TaggedTemplate';
/** @internal */ const ekBinary = 'Binary';
/** @internal */ const ekConditional = 'Conditional';
/** @internal */ const ekAssign = 'Assign';
/** @internal */ const ekArrowFunction = 'ArrowFunction';
/** @internal */ const ekValueConverter = 'ValueConverter';
/** @internal */ const ekBindingBehavior = 'BindingBehavior';
/** @internal */ const ekArrayBindingPattern = 'ArrayBindingPattern';
/** @internal */ const ekObjectBindingPattern = 'ObjectBindingPattern';
/** @internal */ const ekBindingIdentifier = 'BindingIdentifier';
/** @internal */ const ekForOfStatement = 'ForOfStatement';
/** @internal */ const ekInterpolation = 'Interpolation';
/** @internal */ const ekArrayDestructuring = 'ArrayDestructuring';
/** @internal */ const ekObjectDestructuring = 'ObjectDestructuring';
/** @internal */ const ekDestructuringAssignmentLeaf = 'DestructuringAssignmentLeaf';
/** @internal */ const ekCustom = 'Custom';
class CustomExpression {
constructor(value) {
this.value = value;
this.$kind = ekCustom;
}
evaluate(...params) {
return this.value;
}
assign(...params) {
return params;
}
bind(...params) {
// empty
}
unbind(...params) {
// empty
}
accept(_visitor) {
return (void 0);
}
}
class BindingBehaviorExpression {
constructor(expression, name, args) {
this.expression = expression;
this.name = name;
this.args = args;
this.$kind = ekBindingBehavior;
this.key = `_bb_${name}`;
}
}
class ValueConverterExpression {
constructor(expression, name, args) {
this.expression = expression;
this.name = name;
this.args = args;
this.$kind = ekValueConverter;
}
}
class AssignExpression {
constructor(target, value, op = '=') {
this.target = target;
this.value = value;
this.op = op;
this.$kind = ekAssign;
}
}
class ConditionalExpression {
constructor(condition, yes, no) {
this.condition = condition;
this.yes = yes;
this.no = no;
this.$kind = ekConditional;
}
}
class AccessGlobalExpression {
constructor(name) {
this.name = name;
this.$kind = ekAccessGlobal;
}
}
class AccessThisExpression {
constructor(ancestor = 0) {
this.ancestor = ancestor;
this.$kind = ekAccessThis;
}
}
class AccessBoundaryExpression {
constructor() {
this.$kind = ekAccessBoundary;
}
}
class AccessScopeExpression {
constructor(name, ancestor = 0) {
this.name = name;
this.ancestor = ancestor;
this.$kind = ekAccessScope;
}
}
const isAccessGlobal = (ast) => (ast.$kind === ekAccessGlobal ||
(ast.$kind === ekAccessMember ||
ast.$kind === ekAccessKeyed) && ast.accessGlobal);
class AccessMemberExpression {
constructor(object, name, optional = false) {
this.object = object;
this.name = name;
this.optional = optional;
this.$kind = ekAccessMember;
this.accessGlobal = isAccessGlobal(object);
}
}
class AccessKeyedExpression {
constructor(object, key, optional = false) {
this.object = object;
this.key = key;
this.optional = optional;
this.$kind = ekAccessKeyed;
this.accessGlobal = isAccessGlobal(object);
}
}
class NewExpression {
constructor(func, args) {
this.func = func;
this.args = args;
this.$kind = ekNew;
}
}
class CallScopeExpression {
constructor(name, args, ancestor = 0, optional = false) {
this.name = name;
this.args = args;
this.ancestor = ancestor;
this.optional = optional;
this.$kind = ekCallScope;
}
}
class CallMemberExpression {
constructor(object, name, args, optionalMember = false, optionalCall = false) {
this.object = object;
this.name = name;
this.args = args;
this.optionalMember = optionalMember;
this.optionalCall = optionalCall;
this.$kind = ekCallMember;
}
}
class CallFunctionExpression {
constructor(func, args, optional = false) {
this.func = func;
this.args = args;
this.optional = optional;
this.$kind = ekCallFunction;
}
}
class CallGlobalExpression {
constructor(name, args) {
this.name = name;
this.args = args;
this.$kind = ekCallGlobal;
}
}
class BinaryExpression {
constructor(operation, left, right) {
this.operation = operation;
this.left = left;
this.right = right;
this.$kind = ekBinary;
}
}
class UnaryExpression {
constructor(operation, expression, pos = 0) {
this.operation = operation;
this.expression = expression;
this.pos = pos;
this.$kind = ekUnary;
}
}
class PrimitiveLiteralExpression {
constructor(value) {
this.value = value;
this.$kind = ekPrimitiveLiteral;
}
}
PrimitiveLiteralExpression.$undefined = new PrimitiveLiteralExpression(void 0);
PrimitiveLiteralExpression.$null = new PrimitiveLiteralExpression(null);
PrimitiveLiteralExpression.$true = new PrimitiveLiteralExpression(true);
PrimitiveLiteralExpression.$false = new PrimitiveLiteralExpression(false);
PrimitiveLiteralExpression.$empty = new PrimitiveLiteralExpression('');
class ArrayLiteralExpression {
constructor(elements) {
this.elements = elements;
this.$kind = ekArrayLiteral;
}
}
ArrayLiteralExpression.$empty = new ArrayLiteralExpression(kernel.emptyArray);
class ObjectLiteralExpression {
constructor(keys, values) {
this.keys = keys;
this.values = values;
this.$kind = ekObjectLiteral;
}
}
ObjectLiteralExpression.$empty = new ObjectLiteralExpression(kernel.emptyArray, kernel.emptyArray);
class TemplateExpression {
constructor(cooked, expressions = kernel.emptyArray) {
this.cooked = cooked;
this.expressions = expressions;
this.$kind = ekTemplate;
}
}
TemplateExpression.$empty = new TemplateExpression(['']);
class TaggedTemplateExpression {
constructor(cooked, raw, func, expressions = kernel.emptyArray) {
this.cooked = cooked;
this.func = func;
this.expressions = expressions;
this.$kind = ekTaggedTemplate;
cooked.raw = raw;
}
}
class ArrayBindingPattern {
// We'll either have elements, or keys+values, but never all 3
constructor(elements) {
this.elements = elements;
this.$kind = ekArrayBindingPattern;
}
}
class ObjectBindingPattern {
// We'll either have elements, or keys+values, but never all 3
constructor(keys, values) {
this.keys = keys;
this.values = values;
this.$kind = ekObjectBindingPattern;
}
}
class BindingIdentifier {
constructor(name) {
this.name = name;
this.$kind = ekBindingIdentifier;
}
}
// https://tc39.github.io/ecma262/#sec-iteration-statements
// https://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements
class ForOfStatement {
constructor(declaration, iterable, semiIdx) {
this.declaration = declaration;
this.iterable = iterable;
this.semiIdx = semiIdx;
this.$kind = ekForOfStatement;
}
}
/*
* Note: this implementation is far simpler than the one in vCurrent and might be missing important stuff (not sure yet)
* so while this implementation is identical to Template and we could reuse that one, we don't want to lock outselves in to potentially the wrong abstraction
* but this class might be a candidate for removal if it turns out it does provide all we need
*/
class Interpolation {
constructor(parts, expressions = kernel.emptyArray) {
this.parts = parts;
this.expressions = expressions;
this.$kind = ekInterpolation;
this.isMulti = expressions.length > 1;
this.firstExpression = expressions[0];
}
}
// spec: https://tc39.es/ecma262/#sec-destructuring-assignment
/** This is an internal API */
class DestructuringAssignmentExpression {
constructor($kind, list, source, initializer) {
this.$kind = $kind;
this.list = list;
this.source = source;
this.initializer = initializer;
}
}
/** This is an internal API */
class DestructuringAssignmentSingleExpression {
constructor(target, source, initializer) {
this.target = target;
this.source = source;
this.initializer = initializer;
this.$kind = ekDestructuringAssignmentLeaf;
}
}
/** This is an internal API */
class DestructuringAssignmentRestExpression {
constructor(target, indexOrProperties) {
this.target = target;
this.indexOrProperties = indexOrProperties;
this.$kind = ekDestructuringAssignmentLeaf;
}
}
class ArrowFunction {
constructor(args, body, rest = false) {
this.args = args;
this.body = body;
this.rest = rest;
this.$kind = ekArrowFunction;
}
}
/** @internal */
const createError = (message) => new Error(message);
/** @internal */
const isString = (v) => typeof v === 'string';
// this is used inside template literal, since TS errs without String(...value)
/** @internal */ const safeString = String;
/** @internal */ const createLookup = () => Object.create(null);
const astVisit = (ast, visitor) => {
switch (ast.$kind) {
case ekAccessKeyed: return visitor.visitAccessKeyed(ast);
case ekAccessMember: return visitor.visitAccessMember(ast);
case ekAccessScope: return visitor.visitAccessScope(ast);
case ekAccessThis: return visitor.visitAccessThis(ast);
case ekAccessBoundary: return visitor.visitAccessBoundary(ast);
case ekArrayBindingPattern: return visitor.visitArrayBindingPattern(ast);
case ekArrayDestructuring: return visitor.visitDestructuringAssignmentExpression(ast);
case ekArrayLiteral: return visitor.visitArrayLiteral(ast);
case ekArrowFunction: return visitor.visitArrowFunction(ast);
case ekAssign: return visitor.visitAssign(ast);
case ekBinary: return visitor.visitBinary(ast);
case ekBindingBehavior: return visitor.visitBindingBehavior(ast);
case ekBindingIdentifier: return visitor.visitBindingIdentifier(ast);
case ekCallFunction: return visitor.visitCallFunction(ast);
case ekCallMember: return visitor.visitCallMember(ast);
case ekCallScope: return visitor.visitCallScope(ast);
case ekConditional: return visitor.visitConditional(ast);
case ekDestructuringAssignmentLeaf: return visitor.visitDestructuringAssignmentSingleExpression(ast);
case ekForOfStatement: return visitor.visitForOfStatement(ast);
case ekInterpolation: return visitor.visitInterpolation(ast);
case ekObjectBindingPattern: return visitor.visitObjectBindingPattern(ast);
case ekObjectDestructuring: return visitor.visitDestructuringAssignmentExpression(ast);
case ekObjectLiteral: return visitor.visitObjectLiteral(ast);
case ekPrimitiveLiteral: return visitor.visitPrimitiveLiteral(ast);
case ekTaggedTemplate: return visitor.visitTaggedTemplate(ast);
case ekTemplate: return visitor.visitTemplate(ast);
case ekUnary: return visitor.visitUnary(ast);
case ekValueConverter: return visitor.visitValueConverter(ast);
case ekCustom: return visitor.visitCustom(ast);
default: {
throw createError(`Trying to visit unknown ast node ${JSON.stringify(ast)}`);
}
}
};
class Unparser {
constructor() {
this.text = '';
}
static unparse(expr) {
const visitor = new Unparser();
astVisit(expr, visitor);
return visitor.text;
}
visitAccessMember(expr) {
astVisit(expr.object, this);
this.text += `${expr.optional ? '?' : ''}.${expr.name}`;
}
visitAccessKeyed(expr) {
astVisit(expr.object, this);
this.text += `${expr.optional ? '?.' : ''}[`;
astVisit(expr.key, this);
this.text += ']';
}
visitAccessThis(expr) {
if (expr.ancestor === 0) {
this.text += '$this';
return;
}
this.text += '$parent';
let i = expr.ancestor - 1;
while (i--) {
this.text += '.$parent';
}
}
visitAccessBoundary(_expr) {
this.text += 'this';
}
visitAccessScope(expr) {
let i = expr.ancestor;
while (i--) {
this.text += '$parent.';
}
this.text += expr.name;
}
visitArrayLiteral(expr) {
const elements = expr.elements;
this.text += '[';
for (let i = 0, length = elements.length; i < length; ++i) {
if (i !== 0) {
this.text += ',';
}
astVisit(elements[i], this);
}
this.text += ']';
}
visitArrowFunction(expr) {
const args = expr.args;
const ii = args.length;
let i = 0;
let text = '(';
let name;
for (; i < ii; ++i) {
name = args[i].name;
if (i > 0) {
text += ', ';
}
if (i < ii - 1) {
text += name;
}
else {
text += expr.rest ? `...${name}` : name;
}
}
this.text += `${text}) => `;
astVisit(expr.body, this);
}
visitObjectLiteral(expr) {
const keys = expr.keys;
const values = expr.values;
this.text += '{';
for (let i = 0, length = keys.length; i < length; ++i) {
if (i !== 0) {
this.text += ',';
}
this.text += `'${keys[i]}':`;
astVisit(values[i], this);
}
this.text += '}';
}
visitPrimitiveLiteral(expr) {
this.text += '(';
if (isString(expr.value)) {
const escaped = expr.value.replace(/'/g, '\\\'');
this.text += `'${escaped}'`;
}
else {
this.text += `${expr.value}`;
}
this.text += ')';
}
visitCallFunction(expr) {
this.text += '(';
astVisit(expr.func, this);
this.text += expr.optional ? '?.' : '';
this.writeArgs(expr.args);
this.text += ')';
}
visitCallMember(expr) {
astVisit(expr.object, this);
this.text += `${expr.optionalMember ? '?.' : ''}.${expr.name}${expr.optionalCall ? '?.' : ''}`;
this.writeArgs(expr.args);
}
visitCallScope(expr) {
let i = expr.ancestor;
while (i--) {
this.text += '$parent.';
}
this.text += `${expr.name}${expr.optional ? '?.' : ''}`;
this.writeArgs(expr.args);
}
visitTemplate(expr) {
const { cooked, expressions } = expr;
const length = expressions.length;
this.text += '`';
this.text += cooked[0];
for (let i = 0; i < length; i++) {
astVisit(expressions[i], this);
this.text += cooked[i + 1];
}
this.text += '`';
}
visitTaggedTemplate(expr) {
const { cooked, expressions } = expr;
const length = expressions.length;
astVisit(expr.func, this);
this.text += '`';
this.text += cooked[0];
for (let i = 0; i < length; i++) {
astVisit(expressions[i], this);
this.text += cooked[i + 1];
}
this.text += '`';
}
visitUnary(expr) {
this.text += `(${expr.operation}`;
if (expr.operation.charCodeAt(0) >= /* a */ 97) {
this.text += ' ';
}
astVisit(expr.expression, this);
this.text += ')';
}
visitBinary(expr) {
this.text += '(';
astVisit(expr.left, this);
if (expr.operation.charCodeAt(0) === /* i */ 105) {
this.text += ` ${expr.operation} `;
}
else {
this.text += expr.operation;
}
astVisit(expr.right, this);
this.text += ')';
}
visitConditional(expr) {
this.text += '(';
astVisit(expr.condition, this);
this.text += '?';
astVisit(expr.yes, this);
this.text += ':';
astVisit(expr.no, this);
this.text += ')';
}
visitAssign(expr) {
this.text += '(';
astVisit(expr.target, this);
this.text += '=';
astVisit(expr.value, this);
this.text += ')';
}
visitValueConverter(expr) {
const args = expr.args;
astVisit(expr.expression, this);
this.text += `|${expr.name}`;
for (let i = 0, length = args.length; i < length; ++i) {
this.text += ':';
astVisit(args[i], this);
}
}
visitBindingBehavior(expr) {
const args = expr.args;
astVisit(expr.expression, this);
this.text += `&${expr.name}`;
for (let i = 0, length = args.length; i < length; ++i) {
this.text += ':';
astVisit(args[i], this);
}
}
visitArrayBindingPattern(expr) {
const elements = expr.elements;
this.text += '[';
for (let i = 0, length = elements.length; i < length; ++i) {
if (i !== 0) {
this.text += ',';
}
astVisit(elements[i], this);
}
this.text += ']';
}
visitObjectBindingPattern(expr) {
const keys = expr.keys;
const values = expr.values;
this.text += '{';
for (let i = 0, length = keys.length; i < length; ++i) {
if (i !== 0) {
this.text += ',';
}
this.text += `'${keys[i]}':`;
astVisit(values[i], this);
}
this.text += '}';
}
visitBindingIdentifier(expr) {
this.text += expr.name;
}
visitForOfStatement(expr) {
astVisit(expr.declaration, this);
this.text += ' of ';
astVisit(expr.iterable, this);
}
visitInterpolation(expr) {
const { parts, expressions } = expr;
const length = expressions.length;
this.text += '${';
this.text += parts[0];
for (let i = 0; i < length; i++) {
astVisit(expressions[i], this);
this.text += parts[i + 1];
}
this.text += '}';
}
visitDestructuringAssignmentExpression(expr) {
const $kind = expr.$kind;
const isObjDes = $kind === ekObjectDestructuring;
this.text += isObjDes ? '{' : '[';
const list = expr.list;
const len = list.length;
let i;
let item;
for (i = 0; i < len; i++) {
item = list[i];
switch (item.$kind) {
case ekDestructuringAssignmentLeaf:
astVisit(item, this);
break;
case ekArrayDestructuring:
case ekObjectDestructuring: {
const source = item.source;
if (source) {
astVisit(source, this);
this.text += ':';
}
astVisit(item, this);
break;
}
}
}
this.text += isObjDes ? '}' : ']';
}
visitDestructuringAssignmentSingleExpression(expr) {
astVisit(expr.source, this);
this.text += ':';
astVisit(expr.target, this);
const initializer = expr.initializer;
if (initializer !== void 0) {
this.text += '=';
astVisit(initializer, this);
}
}
visitDestructuringAssignmentRestExpression(expr) {
this.text += '...';
astVisit(expr.target, this);
}
visitCustom(expr) {
this.text += safeString(expr.value);
}
writeArgs(args) {
this.text += '(';
for (let i = 0, length = args.length; i < length; ++i) {
if (i !== 0) {
this.text += ',';
}
astVisit(args[i], this);
}
this.text += ')';
}
}
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable prefer-template */
/** @internal */
const createMappedError = (code, ...details) => new Error(`AUR${safeString(code).padStart(4, '0')}: ${getMessageByCode(code, ...details)}`)
;
const errorsMap = {
[99 /* ErrorNames.method_not_implemented */]: 'Method {{0}} not implemented',
[101 /* ErrorNames.ast_behavior_not_found */]: `Ast eval error: binding behavior "{{0}}" could not be found. Did you forget to register it as a dependency?`,
[102 /* ErrorNames.ast_behavior_duplicated */]: `Ast eval error: binding behavior "{{0}}" already applied.`,
[103 /* ErrorNames.ast_converter_not_found */]: `Ast eval error: value converter "{{0}}" could not be found. Did you forget to register it as a dependency?`,
[105 /* ErrorNames.ast_$host_not_found */]: `Ast eval error: unable to find $host context. Did you forget [au-slot] attribute?`,
[106 /* ErrorNames.ast_no_assign_$host */]: `Ast eval error: invalid assignment. "$host" is a reserved keyword.`,
[107 /* ErrorNames.ast_not_a_function */]: `Ast eval error: expression is not a function.`,
[109 /* ErrorNames.ast_unknown_unary_operator */]: `Ast eval error: unknown unary operator: "{{0}}"`,
[108 /* ErrorNames.ast_unknown_binary_operator */]: `Ast eval error: unknown binary operator: "{{0}}"`,
[110 /* ErrorNames.ast_tagged_not_a_function */]: `Ast eval error: left-hand side of tagged template expression is not a function.`,
[111 /* ErrorNames.ast_name_is_not_a_function */]: `Ast eval error: expected "{{0}}" to be a function`,
[112 /* ErrorNames.ast_destruct_null */]: `Ast eval error: cannot use non-object value for destructuring assignment.`,
[151 /* ErrorNames.parse_invalid_start */]: `Expression error: invalid start: "{{0}}"`,
[152 /* ErrorNames.parse_no_spread */]: `Expression error: spread operator is not supported: "{{0}}"`,
[153 /* ErrorNames.parse_expected_identifier */]: `Expression error: expected identifier: "{{0}}"`,
[154 /* ErrorNames.parse_invalid_member_expr */]: `Expression error: invalid member expression: "{{0}}"`,
[155 /* ErrorNames.parse_unexpected_end */]: `Expression error: unexpected end of expression: "{{0}}"`,
[156 /* ErrorNames.parse_unconsumed_token */]: `Expression error: unconsumed token: "{{0}}" at position {{1}} of "{{2}}"`,
[157 /* ErrorNames.parse_invalid_empty */]: `Expression error: invalid empty expression. Empty expression is only valid in event bindings (trigger, delegate, capture etc...)`,
[158 /* ErrorNames.parse_left_hand_side_not_assignable */]: `Expression error: left hand side of expression is not assignable: "{{0}}"`,
[159 /* ErrorNames.parse_expected_converter_identifier */]: `Expression error: expected identifier to come after value converter operator: "{{0}}"`,
[160 /* ErrorNames.parse_expected_behavior_identifier */]: `Expression error: expected identifier to come after binding behavior operator: {{0}}`,
[161 /* ErrorNames.parse_unexpected_keyword_of */]: `Expression error: unexpected keyword "of": "{{0}}"`,
[162 /* ErrorNames.parse_unexpected_keyword_import */]: `Expression error: unexpected keyword "import": "{{0}}"`,
[163 /* ErrorNames.parse_invalid_identifier_in_forof */]: `Expression error: invalid BindingIdentifier at left hand side of "of": "{{0}}" | kind: {{1}}`,
[164 /* ErrorNames.parse_invalid_identifier_object_literal_key */]: `Expression error: invalid or unsupported property definition in object literal: "{{0}}"`,
[165 /* ErrorNames.parse_unterminated_string */]: `Expression error: unterminated quote in string literal: "{{0}}"`,
[166 /* ErrorNames.parse_unterminated_template_string */]: `Expression error: unterminated template string: "{{0}}"`,
[167 /* ErrorNames.parse_missing_expected_token */]: `Expression error: missing expected token "{{0}}" in "{{1}}"`,
[168 /* ErrorNames.parse_unexpected_character */]: `Expression error: unexpected character: "{{0}}"`,
[170 /* ErrorNames.parse_unexpected_token_destructuring */]: `Expression error: unexpected "{{0}}" at position "{{1}}" for destructuring assignment in "{{2}}"`,
[171 /* ErrorNames.parse_unexpected_token_optional_chain */]: `Expression error: unexpected {{0}} at position "{{1}}" for optional chain in "{{2}}"`,
[172 /* ErrorNames.parse_invalid_tag_in_optional_chain */]: `Expression error: invalid tagged template on optional chain in "{{1}}"`,
[173 /* ErrorNames.parse_invalid_arrow_params */]: `Expression error: invalid arrow parameter list in "{{0}}"`,
[174 /* ErrorNames.parse_no_arrow_param_default_value */]: `Expression error: arrow function with default parameters is not supported: "{{0}}"`,
[175 /* ErrorNames.parse_no_arrow_param_destructuring */]: `Expression error: arrow function with destructuring parameters is not supported: "{{0}}"`,
[176 /* ErrorNames.parse_rest_must_be_last */]: `Expression error: rest parameter must be last formal parameter in arrow function: "{{0}}"`,
[178 /* ErrorNames.parse_no_arrow_fn_body */]: `Expression error: arrow function with function body is not supported: "{{0}}"`,
[179 /* ErrorNames.parse_unexpected_double_dot */]: `Expression error: unexpected token '.' at position "{{1}}" in "{{0}}"`,
};
const getMessageByCode = (name, ...details) => {
let cooked = errorsMap[name];
for (let i = 0; i < details.length; ++i) {
const regex = new RegExp(`{{${i}(:.*)?}}`, 'g');
let matches = regex.exec(cooked);
while (matches != null) {
const method = matches[1]?.slice(1);
let value = details[i];
if (value != null) {
switch (method) {
case 'toString':
value = Object.prototype.toString.call(value);
break;
case 'join(!=)':
value = value.join('!=');
break;
case 'element':
value = value === '*' ? 'all elements' : `<${value} />`;
break;
default: {
// property access
if (method?.startsWith('.')) {
value = safeString(value[method.slice(1)]);
}
else {
value = safeString(value);
}
}
}
}
cooked = cooked.slice(0, matches.index) + value + cooked.slice(regex.lastIndex);
matches = regex.exec(cooked);
}
}
return cooked;
};
/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
const IExpressionParser = /*@__PURE__*/ kernel.DI.createInterface('IExpressionParser');
/**
* A default implementation of the IExpressionParser interface
*/
class ExpressionParser {
constructor() {
/** @internal */ this._expressionLookup = createLookup();
/** @internal */ this._forOfLookup = createLookup();
/** @internal */ this._interpolationLookup = createLookup();
}
parse(expression, expressionType) {
let found;
switch (expressionType) {
case etIsCustom:
return new CustomExpression(expression);
case etInterpolation:
found = this._interpolationLookup[expression];
if (found === void 0) {
found = this._interpolationLookup[expression] = this.$parse(expression, expressionType);
}
return found;
case etIsIterator:
found = this._forOfLookup[expression];
if (found === void 0) {
found = this._forOfLookup[expression] = this.$parse(expression, expressionType);
}
return found;
default: {
if (expression.length === 0) {
if (expressionType === etIsFunction || expressionType === etIsProperty) {
return PrimitiveLiteralExpression.$empty;
}
throw invalidEmptyExpression();
}
found = this._expressionLookup[expression];
if (found === void 0) {
found = this._expressionLookup[expression] = this.$parse(expression, expressionType);
}
return found;
}
}
}
/** @internal */
$parse(expression, expressionType) {
$input = expression;
$index = 0;
$length = expression.length;
$scopeDepth = 0;
$startIndex = 0;
$currentToken = 6291456 /* Token.EOF */;
$tokenValue = '';
$currentChar = $charCodeAt(0);
$assignable = true;
$optional = false;
$accessGlobal = true;
$semicolonIndex = -1;
return parse(61 /* Precedence.Variadic */, expressionType === void 0 ? etIsProperty : expressionType);
}
}
ExpressionParser.register = kernel.createImplementationRegister(IExpressionParser);
function unescapeCode(code) {
switch (code) {
case 98 /* Char.LowerB */: return 8 /* Char.Backspace */;
case 116 /* Char.LowerT */: return 9 /* Char.Tab */;
case 110 /* Char.LowerN */: return 10 /* Char.LineFeed */;
case 118 /* Char.LowerV */: return 11 /* Char.VerticalTab */;
case 102 /* Char.LowerF */: return 12 /* Char.FormFeed */;
case 114 /* Char.LowerR */: return 13 /* Char.CarriageReturn */;
case 34 /* Char.DoubleQuote */: return 34 /* Char.DoubleQuote */;
case 39 /* Char.SingleQuote */: return 39 /* Char.SingleQuote */;
case 92 /* Char.Backslash */: return 92 /* Char.Backslash */;
default: return code;
}
}
const $false = PrimitiveLiteralExpression.$false;
const $true = PrimitiveLiteralExpression.$true;
const $null = PrimitiveLiteralExpression.$null;
const $undefined = PrimitiveLiteralExpression.$undefined;
const $this = new AccessThisExpression(0);
const $parent = new AccessThisExpression(1);
const boundary = new AccessBoundaryExpression();
const etNone = 'None';
const etInterpolation = 'Interpolation';
const etIsIterator = 'IsIterator';
const etIsChainable = 'IsChainable';
const etIsFunction = 'IsFunction';
const etIsProperty = 'IsProperty';
const etIsCustom = 'IsCustom';
let $input = '';
let $index = 0;
let $length = 0;
let $scopeDepth = 0;
let $startIndex = 0;
let $currentToken = 6291456 /* Token.EOF */;
let $tokenValue = '';
let $currentChar;
let $assignable = true;
let $optional = false;
let $accessGlobal = true;
let $semicolonIndex = -1;
const stringFromCharCode = String.fromCharCode;
const $charCodeAt = (index) => $input.charCodeAt(index);
const $tokenRaw = () => $input.slice($startIndex, $index);
const globalNames = ('Infinity NaN isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent' +
' Array BigInt Boolean Date Map Number Object RegExp Set String JSON Math Intl').split(' ');
function parseExpression(input, expressionType) {
$input = input;
$index = 0;
$length = input.length;
$scopeDepth = 0;
$startIndex = 0;
$currentToken = 6291456 /* Token.EOF */;
$tokenValue = '';
$currentChar = $charCodeAt(0);
$assignable = true;
$optional = false;
$accessGlobal = true;
$semicolonIndex = -1;
return parse(61 /* Precedence.Variadic */, expressionType === void 0 ? etIsProperty : expressionType);
}
// This is performance-critical code which follows a subset of the well-known ES spec.
// Knowing the spec, or parsers in general, will help with understanding this code and it is therefore not the
// single source of information for being able to figure it out.
// It generally does not need to change unless the spec changes or spec violations are found, or optimization
// opportunities are found (which would likely not fix these warnings in any case).
// It's therefore not considered to have any tangible impact on the maintainability of the code base.
// For reference, most of the parsing logic is based on: https://tc39.github.io/ecma262/#sec-ecmascript-language-expressions
// eslint-disable-next-line max-lines-per-function
function parse(minPrecedence, expressionType) {
if (expressionType === etIsCustom) {
return new CustomExpression($input);
}
if ($index === 0) {
if (expressionType === etInterpolation) {
return parseInterpolation();
}
nextToken();
if ($currentToken & 4194304 /* Token.ExpressionTerminal */) {
throw invalidStartOfExpression();
}
}
$assignable = 577 /* Precedence.Binary */ > minPrecedence;
$optional = false;
$accessGlobal = 579 /* Precedence.LeftHandSide */ > minPrecedence;
let optionalThisTail = false;
let result = void 0;
let ancestor = 0;
if ($currentToken & 131072 /* Token.UnaryOp */) {
/**
* parseUnaryExpression
*
* https://tc39.github.io/ecma262/#sec-unary-operators
*
* UnaryExpression :
* 1. LeftHandSideExpression
* 2. void UnaryExpression
* 3. typeof UnaryExpression
* 4. + UnaryExpression
* 5. - UnaryExpression
* 6. ! UnaryExpression
* 7. ++ UnaryExpression
* 8. -- UnaryExpression
*
* IsValidAssignmentTarget
* 2,3,4,5,6,7,8 = false
* 1 = see parseLeftHandSideExpression
*
* Note: technically we should throw on +++ / ---, but there's nothing to gain from that
*/
const op = TokenValues[$currentToken & 63 /* Token.Type */];
nextToken();
result = new UnaryExpression(op, parse(579 /* Precedence.LeftHandSide */, expressionType));
$assignable = false;
}
else {
/**
* parsePrimaryExpression
*
* https://tc39.github.io/ecma262/#sec-primary-expression
*
* PrimaryExpression :
* 1. this
* 2. IdentifierName
* 3. Literal
* 4. ArrayLiteralExpression
* 5. ObjectLiteralExpression
* 6. TemplateLiteral
* 7. ParenthesizedExpression
*
* Literal :
* NullLiteral
* BooleanLiteral
* NumericLiteral
* StringLiteral
*
* ParenthesizedExpression :
* ( AssignmentExpression )
*
* IsValidAssignmentTarget
* 1,3,4,5,6,7 = false
* 2 = true
*/
primary: switch ($currentToken) {
case 12296 /* Token.ParentScope */: // $parent
ancestor = $scopeDepth;
$assignable = false;
$accessGlobal = false;
do {
nextToken();
++ancestor;
switch ($currentToken) {
case 65547 /* Token.Dot */:
nextToken();
if (($currentToken & 12288 /* Token.IdentifierName */) === 0) {
throw expectedIdentifier();
}
break;
case 12 /* Token.DotDot */:
case 13 /* Token.DotDotDot */:
throw expectedIdentifier();
case 2162702 /* Token.QuestionDot */:
$optional = true;
nextToken();
if (($currentToken & 12288 /* Token.IdentifierName */) === 0) {
result = ancestor === 0 ? $this : ancestor === 1 ? $parent : new AccessThisExpression(ancestor);
optionalThisTail = true;
break primary;
}
break;
default:
if ($currentToken & 2097152 /* Token.AccessScopeTerminal */) {
result = ancestor === 0 ? $this : ancestor === 1 ? $parent : new AccessThisExpression(ancestor);
break primary;
}
throw invalidMemberExpression();
}
} while ($currentToken === 12296 /* Token.ParentScope */);
// falls through
case 4096 /* Token.Identifier */: { // identifier
const id = $tokenValue;
if (expressionType === etIsIterator) {
result = new BindingIdentifier(id);
}
else if ($accessGlobal && globalNames.includes(id)) {
result = new AccessGlobalExpression(id);
}
else if ($accessGlobal && id === 'import') {
throw unexpectedImportKeyword();
}
else {
result = new AccessScopeExpression(id, ancestor);
}
$assignable = !$optional;
nextToken();
if (consumeOpt(53 /* Token.Arrow */)) {
if ($currentToken === 524298 /* Token.OpenBrace */) {
throw functionBodyInArrowFn();
}
const _optional = $optional;
const _scopeDepth = $scopeDepth;
++$scopeDepth;
const body = parse(62 /* Precedence.Assign */, etNone);
$optional = _optional;
$scopeDepth = _scopeDepth;
$assignable = false;
result = new ArrowFunction([new BindingIdentifier(id)], body);
}
break;
}
case 12 /* Token.DotDot */:
throw unexpectedDoubleDot();
case 13 /* Token.DotDotDot */:
throw invalidSpreadOp();
case 12293 /* Token.ThisScope */: // $this
$assignable = false;
nextToken();
switch ($scopeDepth) {
case 0:
result = $this;
break;
case 1:
result = $parent;
break;
default:
result = new AccessThisExpression($scopeDepth);
break;
}
break;
case 12294 /* Token.AccessBoundary */: // this
$assignable = false;
nextToken();
result = boundary;
break;
case 2688009 /* Token.OpenParen */:
result = parseCoverParenthesizedExpressionAndArrowParameterList(expressionType);
break;
case 2688020 /* Token.OpenBracket */:
result = $input.search(/\s+of\s+/) > $index ? parseArrayDestructuring() : parseArrayLiteralExpression(expressionType);
break;
case 524298 /* Token.OpenBrace */:
result = parseObjectLiteralExpression(expressionType);
break;
case 2163762 /* Token.TemplateTail */:
result = new TemplateExpression([$tokenValue]);
$assignable = false;
nextToken();
break;
case 2163763 /* Token.TemplateContinuation */:
result = parseTemplate(expressionType, result, false);
break;
case 16384 /* Token.StringLiteral */:
case 32768 /* Token.NumericLiteral */:
result = new PrimitiveLiteralExpression($tokenValue);
$assignable = false;
nextToken();
break;
case 8194 /* Token.NullKeyword */:
case 8195 /* Token.UndefinedKeyword */:
case 8193 /* Token.TrueKeyword */:
case 8192 /* Token.FalseKeyword */:
result = TokenValues[$currentToken & 63 /* Token.Type */];
$assignable = false;
nextToken();
break;
case 8196 /* Token.NewKeyword */: {
nextToken();
const callee = parse(578 /* Precedence.Member */, expressionType);
let args;
if ($currentToken === 2688009 /* Token.OpenParen */) {
args = parseArguments();
}
else {
args = [];
nextToken();
}
result = new NewExpression(callee, args);
$assignable = false;
break;
}
default:
if ($index >= $length) {
throw unexpectedEndOfExpression();
}
else {
throw unconsumedToken();
}
}
if (expressionType === etIsIterator) {
return parseForOfStatement(result);
}
switch ($currentToken) {
case 2228282 /* Token.PlusPlus */:
case 2228283 /* Token.MinusMinus */:
result = new UnaryExpression(TokenValues[$currentToken & 63 /* Token.Type */], result, 1);
nextToken();
$assignable = false;
break;
}
if (579 /* Precedence.LeftHandSide */ < minPrecedence) {
return result;
}
if ($currentToken === 12 /* Token.DotDot */ || $currentToken === 13 /* Token.DotDotDot */) {
throw expectedIdentifier();
}
if (result.$kind === ekAccessThis) {
switch ($currentToken) {
case 2162702 /* Token.QuestionDot */:
$optional = true;
$assignable = false;
nextToken();
if (($currentToken & 13312 /* Token.OptionalSuffix */) === 0) {
throw unexpectedTokenInOptionalChain();
}
if ($currentToken & 12288 /* Token.IdentifierName */) {
result = new AccessScopeExpression($tokenValue, result.ancestor);
nextToken();
}
else if ($currentToken === 2688009 /* Token.OpenParen */) {
result = new CallFunctionExpression(result, parseArguments(), true);
}
else if ($currentToken === 2688020 /* Token.OpenBracket */) {
result = parseKeyedExpression(result, true);
}
else {
throw invalidTaggedTemplateOnOptionalChain();
}
break;
case 65547 /* Token.Dot */:
$assignable = !$optional;
nextToken();
if (($currentToken & 12288 /* Token.IdentifierName */) === 0) {
throw expectedIdentifier();
}
result = new AccessScopeExpression($tokenValue, result.ancestor);
nextToken();
break;
case 12 /* Token.DotDot */:
case 13 /* Token.DotDotDot */:
throw expectedIdentifier();
case 2688009 /* Token.OpenParen */:
result = new CallFunctionExpression(result, parseArguments(), optionalThisTail);
break;
case 2688020 /* Token.OpenBracket */:
result = parseKeyedExpression(result, optionalThisTail);
break;
case 2163762 /* Token.TemplateTail */:
result = createTemplateTail(result);
break;
case 2163763 /* Token.TemplateContinuation */:
result = parseTemplate(expressionType, result, true);
break;
}
}
/**
* parseMemberExpression (Token.Dot, Token.OpenBracket, Token.TemplateContinuation)
*
* MemberExpression :
* 1. PrimaryExpression
* 2. MemberExpression [ AssignmentExpression ]
* 3. MemberExpression . IdentifierName
* 4. MemberExpression TemplateLiteral
*
* IsValidAssignmentTarget
* 1,4 = false
* 2,3 = true
*
*
* parseCallExpression (Token.OpenParen)
* CallExpression :
* 1. MemberExpression Arguments
* 2. CallExpression Arguments
* 3. CallExpression [ AssignmentExpression ]
* 4. CallExpression . IdentifierName
* 5. CallExpression TemplateLiteral
*
* IsValidAssignmentTarget
* 1,2,5 = false
* 3,4 = true
*/
while (($currentToken & 65536 /* Token.LeftHandSide */) > 0) {
switch ($currentToken) {
case 2162702 /* Token.QuestionDot */:
result = parseOptionalChainLHS(result);
break;
case 65547 /* Token.Dot */:
nextToken();
if (($currentToken & 12288 /* Token.IdentifierName */) === 0) {
throw expectedIdentifier();
}
result = parseMemberExpressionLHS(result, false);
break;
case 12 /* Token.DotDot */:
case 13 /* Token.DotDotDot */:
throw expectedIdentifier();
case 2688009 /* Token.OpenParen */:
if (578 /* Precedence.Member */ === minPrecedence) {
return result;
}
if (result.$kind === ekAccessScope) {
result = new CallScopeExpression(result.name, parseArguments(), result.ancestor, false);
}
else if (result.$kind === ekAccessMember) {
result = new CallMemberExpression(result.object, result.name, parseArguments(), result.optional, false);
}
else if (result.$kind === ekAccessGlobal) {
result = new CallGlobalExpression(result.name, parseArguments());
}
else {
result = new CallFunctionExpression(result, parseArguments(), false);
}
break;
case 2688020 /* Token.OpenBracket */:
result = parseKeyedExpression(result, false);
break;
case 2163762 /* Token.TemplateTail */:
if ($optional) {
throw invalidTaggedTemplateOnOptionalChain();
}
result = createTemplateTail(result);
break;
case 2163763 /* Token.TemplateContinuation */:
if ($optional) {
throw invalidTaggedTemplateOnOptionalChain();
}
result = parseTemplate(expressionType, result, true);
break;
}
}
}
if ($currentToken === 12 /* Token.DotDot */ || $currentToken === 13 /* Token.DotDotDot */) {
throw expectedIdentifier();
}
if (577 /* Precedence.Binary */ < minPrecedence) {
return result;
}
/**
* parseBinaryExpression
*
* https://tc39.github.io/ecma262/#sec-multiplicative-operators
*
* MultiplicativeExpression : (local precedence 6)
* UnaryExpression
* MultiplicativeExpression * / % UnaryExpression
*
* AdditiveExpression : (local precedence 5)
* MultiplicativeExpression
* AdditiveExpression + - MultiplicativeExpression
*
* RelationalExpression : (local precedence 4)
* AdditiveExpression
* RelationalExpression < > <= >= instanceof in AdditiveExpression
*
* EqualityExpression : (local precedence 3)
* RelationalExpression
* EqualityExpression == != === !== RelationalExpression
*
* LogicalANDExpression : (local precedence 2)
* EqualityExpression
* LogicalANDExpression && EqualityExpression
*
* LogicalORExpression : (local precedence 1)
* LogicalANDExpression
* LogicalORExpression || LogicalANDExpression
*
* CoalesceExpression :
* CoalesceExpressionHead ?? BitwiseORExpression
*
* CoalesceExpressionHead :
* CoelesceExpression