refactor evaluation logic
This commit is contained in:
parent
5876cf6210
commit
bc1c5a8f23
|
@ -175,6 +175,7 @@
|
|||
"darkgreen",
|
||||
"darkred",
|
||||
"eqeqeq",
|
||||
"boolish",
|
||||
|
||||
"webassemblyjs",
|
||||
"fsevents",
|
||||
|
|
|
@ -24,22 +24,38 @@ class BasicEvaluatedExpression {
|
|||
constructor() {
|
||||
this.type = TypeUnknown;
|
||||
this.range = undefined;
|
||||
/** @type {boolean} */
|
||||
this.falsy = false;
|
||||
/** @type {boolean} */
|
||||
this.truthy = false;
|
||||
/** @type {boolean | undefined} */
|
||||
this.nullish = undefined;
|
||||
/** @type {boolean | undefined} */
|
||||
this.bool = undefined;
|
||||
/** @type {number | undefined} */
|
||||
this.number = undefined;
|
||||
/** @type {bigint | undefined} */
|
||||
this.bigint = undefined;
|
||||
/** @type {RegExp | undefined} */
|
||||
this.regExp = undefined;
|
||||
/** @type {string | undefined} */
|
||||
this.string = undefined;
|
||||
/** @type {BasicEvaluatedExpression[] | undefined} */
|
||||
this.quasis = undefined;
|
||||
/** @type {BasicEvaluatedExpression[] | undefined} */
|
||||
this.parts = undefined;
|
||||
/** @type {any[] | undefined} */
|
||||
this.array = undefined;
|
||||
/** @type {BasicEvaluatedExpression[] | undefined} */
|
||||
this.items = undefined;
|
||||
/** @type {BasicEvaluatedExpression[] | undefined} */
|
||||
this.options = undefined;
|
||||
/** @type {BasicEvaluatedExpression | undefined} */
|
||||
this.prefix = undefined;
|
||||
/** @type {BasicEvaluatedExpression | undefined} */
|
||||
this.postfix = undefined;
|
||||
this.wrappedInnerExpressions = undefined;
|
||||
/** @type {string | undefined} */
|
||||
this.identifier = undefined;
|
||||
this.rootInfo = undefined;
|
||||
this.getMembers = undefined;
|
||||
|
@ -99,34 +115,83 @@ class BasicEvaluatedExpression {
|
|||
}
|
||||
|
||||
/**
|
||||
* check for "simple" types (inlined) only
|
||||
* @returns {boolean} is simple type
|
||||
* Is expression a primitive or an object type value?
|
||||
* @returns {boolean | undefined} true: primitive type, false: object type, undefined: unknown/runtime-defined
|
||||
*/
|
||||
isSimpleType() {
|
||||
isPrimitiveType() {
|
||||
switch (this.type) {
|
||||
case TypeIdentifier:
|
||||
case TypeConditional:
|
||||
case TypeUndefined:
|
||||
case TypeNull:
|
||||
case TypeString:
|
||||
case TypeNumber:
|
||||
case TypeBoolean:
|
||||
case TypeBigInt:
|
||||
case TypeWrapped:
|
||||
case TypeUnknown:
|
||||
case TypeTemplateString:
|
||||
return true;
|
||||
case TypeRegExp:
|
||||
case TypeArray:
|
||||
case TypeConstArray:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BasicEvaluatedExpression} basicEvaluatedExpression basicEvaluatedExpression
|
||||
* @returns {boolean|undefined} is same type
|
||||
* Is expression a runtime or compile-time value?
|
||||
* @returns {boolean} true: compile time value, false: runtime value
|
||||
*/
|
||||
isSameType(basicEvaluatedExpression) {
|
||||
if (
|
||||
this.type === TypeUnknown ||
|
||||
basicEvaluatedExpression.type === TypeUnknown
|
||||
) {
|
||||
return undefined;
|
||||
isCompileTimeValue() {
|
||||
switch (this.type) {
|
||||
case TypeUndefined:
|
||||
case TypeNull:
|
||||
case TypeString:
|
||||
case TypeNumber:
|
||||
case TypeBoolean:
|
||||
case TypeRegExp:
|
||||
case TypeConstArray:
|
||||
case TypeBigInt:
|
||||
return true;
|
||||
case TypeWrapped:
|
||||
case TypeIdentifier:
|
||||
case TypeConditional:
|
||||
case TypeArray:
|
||||
case TypeTemplateString:
|
||||
case TypeUnknown:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return this.type === basicEvaluatedExpression.type;
|
||||
/**
|
||||
* Gets the compile-time value of the expression
|
||||
* @returns {any} the javascript value
|
||||
*/
|
||||
asCompileTimeValue() {
|
||||
switch (this.type) {
|
||||
case TypeUndefined:
|
||||
return undefined;
|
||||
case TypeNull:
|
||||
return null;
|
||||
case TypeString:
|
||||
return this.string;
|
||||
case TypeNumber:
|
||||
return this.number;
|
||||
case TypeBoolean:
|
||||
return this.bool;
|
||||
case TypeRegExp:
|
||||
return this.regExp;
|
||||
case TypeConstArray:
|
||||
return this.array;
|
||||
case TypeBigInt:
|
||||
return this.bigint;
|
||||
default:
|
||||
throw new Error(
|
||||
"asCompileTimeValue must only be called for compile-time values"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
isTruthy() {
|
||||
|
|
|
@ -333,32 +333,27 @@ class JavascriptParser extends Parser {
|
|||
.tap("JavascriptParser", _expr => {
|
||||
const expr = /** @type {LogicalExpressionNode} */ (_expr);
|
||||
|
||||
let left;
|
||||
let leftAsBool;
|
||||
let right;
|
||||
if (expr.operator === "&&") {
|
||||
left = this.evaluateExpression(expr.left);
|
||||
leftAsBool = left && left.asBool();
|
||||
const left = this.evaluateExpression(expr.left);
|
||||
const leftAsBool = left && left.asBool();
|
||||
if (leftAsBool === false) return left.setRange(expr.range);
|
||||
if (leftAsBool !== true) return;
|
||||
right = this.evaluateExpression(expr.right);
|
||||
const right = this.evaluateExpression(expr.right);
|
||||
return right.setRange(expr.range);
|
||||
} else if (expr.operator === "||") {
|
||||
left = this.evaluateExpression(expr.left);
|
||||
leftAsBool = left && left.asBool();
|
||||
const left = this.evaluateExpression(expr.left);
|
||||
const leftAsBool = left && left.asBool();
|
||||
if (leftAsBool === true) return left.setRange(expr.range);
|
||||
if (leftAsBool !== false) return;
|
||||
right = this.evaluateExpression(expr.right);
|
||||
const right = this.evaluateExpression(expr.right);
|
||||
return right.setRange(expr.range);
|
||||
} else if (expr.operator === "??") {
|
||||
left = this.evaluateExpression(expr.left);
|
||||
const left = this.evaluateExpression(expr.left);
|
||||
const leftAsNullish = left && left.asNullish();
|
||||
if (leftAsNullish === false) return left.setRange(expr.range);
|
||||
if (leftAsNullish === true) {
|
||||
right = this.evaluateExpression(expr.right);
|
||||
}
|
||||
|
||||
return right && right.setRange(expr.range);
|
||||
if (leftAsNullish !== true) return;
|
||||
const right = this.evaluateExpression(expr.right);
|
||||
return right.setRange(expr.range);
|
||||
}
|
||||
});
|
||||
this.hooks.evaluate
|
||||
|
@ -366,162 +361,149 @@ class JavascriptParser extends Parser {
|
|||
.tap("JavascriptParser", _expr => {
|
||||
const expr = /** @type {BinaryExpressionNode} */ (_expr);
|
||||
|
||||
const handleNumberOperation = fn => {
|
||||
const handleConstOperation = fn => {
|
||||
const left = this.evaluateExpression(expr.left);
|
||||
if (!left || !left.isCompileTimeValue()) return;
|
||||
|
||||
const right = this.evaluateExpression(expr.right);
|
||||
if (!left || !right) return;
|
||||
if (left.isNumber() && right.isNumber()) {
|
||||
res = new BasicEvaluatedExpression();
|
||||
res.setNumber(fn(left.number, right.number));
|
||||
res.setRange(expr.range);
|
||||
return res;
|
||||
} else if (left.isBigInt() && right.isBigInt()) {
|
||||
res = new BasicEvaluatedExpression();
|
||||
res.setBigInt(fn(left.bigint, right.bigint));
|
||||
res.setRange(expr.range);
|
||||
return res;
|
||||
if (!right || !right.isCompileTimeValue()) return;
|
||||
|
||||
const result = fn(
|
||||
left.asCompileTimeValue(),
|
||||
right.asCompileTimeValue()
|
||||
);
|
||||
switch (typeof result) {
|
||||
case "boolean":
|
||||
return new BasicEvaluatedExpression()
|
||||
.setBoolean(result)
|
||||
.setRange(expr.range);
|
||||
case "number":
|
||||
return new BasicEvaluatedExpression()
|
||||
.setNumber(result)
|
||||
.setRange(expr.range);
|
||||
case "bigint":
|
||||
return new BasicEvaluatedExpression()
|
||||
.setBigInt(result)
|
||||
.setRange(expr.range);
|
||||
case "string":
|
||||
return new BasicEvaluatedExpression()
|
||||
.setString(result)
|
||||
.setRange(expr.range);
|
||||
}
|
||||
};
|
||||
|
||||
const handleStrictCompare = fn => {
|
||||
const left = this.evaluateExpression(expr.left);
|
||||
const right = this.evaluateExpression(expr.right);
|
||||
if (!left || !right) return;
|
||||
const sameType = left.isSameType(right);
|
||||
if (sameType !== true) return;
|
||||
const isAlwaysDifferent = (a, b) =>
|
||||
(a === true && b === false) || (a === false && b === true);
|
||||
|
||||
if (left.isNumber()) {
|
||||
res = new BasicEvaluatedExpression();
|
||||
res.setBoolean(fn(left.number, right.number));
|
||||
res.setRange(expr.range);
|
||||
return res;
|
||||
} else if (left.isString()) {
|
||||
res = new BasicEvaluatedExpression();
|
||||
res.setBoolean(fn(left.string, right.string));
|
||||
res.setRange(expr.range);
|
||||
return res;
|
||||
} else if (left.isBigInt()) {
|
||||
res = new BasicEvaluatedExpression();
|
||||
res.setBoolean(fn(left.bigint, right.bigint));
|
||||
res.setRange(expr.range);
|
||||
return res;
|
||||
const handleTemplateStringCompare = (left, right, res, eql) => {
|
||||
const getPrefix = parts => {
|
||||
let value = "";
|
||||
for (const p of parts) {
|
||||
const v = p.asString();
|
||||
if (v !== undefined) value += v;
|
||||
else break;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
const getSuffix = parts => {
|
||||
let value = "";
|
||||
for (let i = parts.length - 1; i >= 0; i--) {
|
||||
const v = parts[i].asString();
|
||||
if (v !== undefined) value = v + value;
|
||||
else break;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
const leftPrefix = getPrefix(left.parts);
|
||||
const rightPrefix = getPrefix(right.parts);
|
||||
const leftSuffix = getSuffix(left.parts);
|
||||
const rightSuffix = getSuffix(right.parts);
|
||||
const lenPrefix = Math.min(leftPrefix.length, rightPrefix.length);
|
||||
const lenSuffix = Math.min(leftSuffix.length, rightSuffix.length);
|
||||
if (
|
||||
leftPrefix.slice(0, lenPrefix) !==
|
||||
rightPrefix.slice(0, lenPrefix) ||
|
||||
leftSuffix.slice(-lenSuffix) !== rightSuffix.slice(-lenSuffix)
|
||||
) {
|
||||
return res.setBoolean(!eql);
|
||||
}
|
||||
};
|
||||
|
||||
const handleStrictEqualityComparison = eql => {
|
||||
left = this.evaluateExpression(expr.left);
|
||||
right = this.evaluateExpression(expr.right);
|
||||
const left = this.evaluateExpression(expr.left);
|
||||
const right = this.evaluateExpression(expr.right);
|
||||
if (!left || !right) return;
|
||||
const sameType = left.isSameType(right);
|
||||
if (sameType === undefined) return;
|
||||
res = new BasicEvaluatedExpression();
|
||||
const res = new BasicEvaluatedExpression();
|
||||
res.setRange(expr.range);
|
||||
|
||||
if (sameType === true) {
|
||||
// check only for types that could be compared
|
||||
if (left.isString()) {
|
||||
return res.setBoolean(
|
||||
eql
|
||||
? left.string === right.string
|
||||
: left.string !== right.string
|
||||
);
|
||||
} else if (left.isNumber()) {
|
||||
return res.setBoolean(
|
||||
eql
|
||||
? left.number === right.number
|
||||
: left.number !== right.number
|
||||
);
|
||||
} else if (left.isBigInt()) {
|
||||
return res.setBoolean(
|
||||
eql
|
||||
? left.bigint === right.bigint
|
||||
: left.bigint !== right.bigint
|
||||
);
|
||||
} else if (left.isBoolean()) {
|
||||
return res.setBoolean(
|
||||
eql ? left.bool === right.bool : left.bool !== right.bool
|
||||
);
|
||||
} else if (left.isNull() || left.isUndefined()) {
|
||||
return res.setBoolean(eql);
|
||||
}
|
||||
const leftConst = left.isCompileTimeValue();
|
||||
const rightConst = right.isCompileTimeValue();
|
||||
|
||||
if (leftConst && rightConst) {
|
||||
return res.setBoolean(
|
||||
eql === (left.asCompileTimeValue() === right.asCompileTimeValue())
|
||||
);
|
||||
}
|
||||
|
||||
// check for "simple" types, e.g.
|
||||
// if ([] === 1)
|
||||
// if ([] === [])
|
||||
// if (0 === null)
|
||||
// if ("" === /a/i)
|
||||
if (left.isSimpleType() && right.isSimpleType()) {
|
||||
if (left.isArray() && right.isArray()) {
|
||||
return res.setBoolean(!eql);
|
||||
}
|
||||
if (left.isTemplateString() && right.isTemplateString()) {
|
||||
return handleTemplateStringCompare(left, right, res, eql);
|
||||
}
|
||||
|
||||
const leftPrimitive = left.isPrimitiveType();
|
||||
const rightPrimitive = right.isPrimitiveType();
|
||||
|
||||
// Primitive !== Object or
|
||||
// compile-time object types are never equal to something at runtime
|
||||
if (
|
||||
(leftPrimitive === false &&
|
||||
(leftConst || rightPrimitive === true)) ||
|
||||
(rightPrimitive === false && (rightConst || leftPrimitive === true))
|
||||
) {
|
||||
return res.setBoolean(!eql);
|
||||
}
|
||||
|
||||
// Different nullish or boolish status also means not equal
|
||||
if (
|
||||
isAlwaysDifferent(left.asBool(), right.asBool()) ||
|
||||
isAlwaysDifferent(left.asNullish(), right.asNullish())
|
||||
) {
|
||||
return res.setBoolean(!eql);
|
||||
}
|
||||
};
|
||||
|
||||
const handleAbstractEqualityComparison = eql => {
|
||||
left = this.evaluateExpression(expr.left);
|
||||
right = this.evaluateExpression(expr.right);
|
||||
const left = this.evaluateExpression(expr.left);
|
||||
const right = this.evaluateExpression(expr.right);
|
||||
if (!left || !right) return;
|
||||
const sameType = left.isSameType(right);
|
||||
if (sameType === undefined) return;
|
||||
res = new BasicEvaluatedExpression();
|
||||
const res = new BasicEvaluatedExpression();
|
||||
res.setRange(expr.range);
|
||||
|
||||
// use strict equality comparison
|
||||
if (sameType === true) {
|
||||
if (left.isString()) {
|
||||
return res.setBoolean(
|
||||
eql
|
||||
? left.string === right.string
|
||||
: left.string !== right.string
|
||||
);
|
||||
} else if (left.isNumber()) {
|
||||
return res.setBoolean(
|
||||
eql
|
||||
? left.number === right.number
|
||||
: left.number !== right.number
|
||||
);
|
||||
} else if (left.isBigInt()) {
|
||||
return res.setBoolean(
|
||||
eql
|
||||
? left.bigint === right.bigint
|
||||
: left.bigint !== right.bigint
|
||||
);
|
||||
} else if (left.isBoolean()) {
|
||||
return res.setBoolean(
|
||||
eql ? left.bool === right.bool : left.bool !== right.bool
|
||||
);
|
||||
} else if (left.isNull() || left.isUndefined()) {
|
||||
return res.setBoolean(eql);
|
||||
// if ([] == [])
|
||||
// if ("a,s".split(",") == ["a", "s"])
|
||||
// if (/a/ == /a/)
|
||||
} else if (
|
||||
left.isArray() ||
|
||||
left.isConstArray() ||
|
||||
left.isRegExp()
|
||||
) {
|
||||
return res.setBoolean(!eql);
|
||||
}
|
||||
const leftConst = left.isCompileTimeValue();
|
||||
const rightConst = right.isCompileTimeValue();
|
||||
|
||||
if (leftConst && rightConst) {
|
||||
return res.setBoolean(
|
||||
// eslint-disable-next-line eqeqeq
|
||||
eql === (left.asCompileTimeValue() == right.asCompileTimeValue())
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
(left.isFalsy() && right.isTruthy()) ||
|
||||
(left.isTruthy() && right.isFalsy())
|
||||
) {
|
||||
if (left.isArray() && right.isArray()) {
|
||||
return res.setBoolean(!eql);
|
||||
}
|
||||
|
||||
// abstract equality comparison is not fully implemented
|
||||
return undefined;
|
||||
if (left.isTemplateString() && right.isTemplateString()) {
|
||||
return handleTemplateStringCompare(left, right, res, eql);
|
||||
}
|
||||
};
|
||||
|
||||
let left;
|
||||
let right;
|
||||
let res;
|
||||
if (expr.operator === "+") {
|
||||
left = this.evaluateExpression(expr.left);
|
||||
right = this.evaluateExpression(expr.right);
|
||||
const left = this.evaluateExpression(expr.left);
|
||||
const right = this.evaluateExpression(expr.right);
|
||||
if (!left || !right) return;
|
||||
res = new BasicEvaluatedExpression();
|
||||
const res = new BasicEvaluatedExpression();
|
||||
if (left.isString()) {
|
||||
if (right.isString()) {
|
||||
res.setString(left.string + right.string);
|
||||
|
@ -653,13 +635,13 @@ class JavascriptParser extends Parser {
|
|||
res.setRange(expr.range);
|
||||
return res;
|
||||
} else if (expr.operator === "-") {
|
||||
return handleNumberOperation((l, r) => l - r);
|
||||
return handleConstOperation((l, r) => l - r);
|
||||
} else if (expr.operator === "*") {
|
||||
return handleNumberOperation((l, r) => l * r);
|
||||
return handleConstOperation((l, r) => l * r);
|
||||
} else if (expr.operator === "/") {
|
||||
return handleNumberOperation((l, r) => l / r);
|
||||
return handleConstOperation((l, r) => l / r);
|
||||
} else if (expr.operator === "**") {
|
||||
return handleNumberOperation((l, r) => l ** r);
|
||||
return handleConstOperation((l, r) => l ** r);
|
||||
} else if (expr.operator === "===") {
|
||||
return handleStrictEqualityComparison(true);
|
||||
} else if (expr.operator === "==") {
|
||||
|
@ -669,32 +651,25 @@ class JavascriptParser extends Parser {
|
|||
} else if (expr.operator === "!=") {
|
||||
return handleAbstractEqualityComparison(false);
|
||||
} else if (expr.operator === "&") {
|
||||
return handleNumberOperation((l, r) => l & r);
|
||||
return handleConstOperation((l, r) => l & r);
|
||||
} else if (expr.operator === "|") {
|
||||
return handleNumberOperation((l, r) => l | r);
|
||||
return handleConstOperation((l, r) => l | r);
|
||||
} else if (expr.operator === "^") {
|
||||
return handleNumberOperation((l, r) => l ^ r);
|
||||
return handleConstOperation((l, r) => l ^ r);
|
||||
} else if (expr.operator === ">>>") {
|
||||
const left = this.evaluateExpression(expr.left);
|
||||
const right = this.evaluateExpression(expr.right);
|
||||
if (!left || !right) return;
|
||||
if (!left.isNumber() || !right.isNumber()) return;
|
||||
res = new BasicEvaluatedExpression();
|
||||
res.setNumber(left.number >>> right.number);
|
||||
res.setRange(expr.range);
|
||||
return res;
|
||||
return handleConstOperation((l, r) => l >>> r);
|
||||
} else if (expr.operator === ">>") {
|
||||
return handleNumberOperation((l, r) => l >> r);
|
||||
return handleConstOperation((l, r) => l >> r);
|
||||
} else if (expr.operator === "<<") {
|
||||
return handleNumberOperation((l, r) => l << r);
|
||||
return handleConstOperation((l, r) => l << r);
|
||||
} else if (expr.operator === "<") {
|
||||
return handleStrictCompare((l, r) => l < r);
|
||||
return handleConstOperation((l, r) => l < r);
|
||||
} else if (expr.operator === ">") {
|
||||
return handleStrictCompare((l, r) => l > r);
|
||||
return handleConstOperation((l, r) => l > r);
|
||||
} else if (expr.operator === "<=") {
|
||||
return handleStrictCompare((l, r) => l <= r);
|
||||
return handleConstOperation((l, r) => l <= r);
|
||||
} else if (expr.operator === ">=") {
|
||||
return handleStrictCompare((l, r) => l >= r);
|
||||
return handleConstOperation((l, r) => l >= r);
|
||||
}
|
||||
});
|
||||
this.hooks.evaluate
|
||||
|
@ -960,11 +935,11 @@ class JavascriptParser extends Parser {
|
|||
let arg1 = this.evaluateExpression(expr.arguments[0]);
|
||||
let arg2 = this.evaluateExpression(expr.arguments[1]);
|
||||
if (!arg1.isString() && !arg1.isRegExp()) return;
|
||||
arg1 = arg1.regExp || arg1.string;
|
||||
const arg1Value = arg1.regExp || arg1.string;
|
||||
if (!arg2.isString()) return;
|
||||
arg2 = arg2.string;
|
||||
const arg2Value = arg2.string;
|
||||
return new BasicEvaluatedExpression()
|
||||
.setString(param.string.replace(arg1, arg2))
|
||||
.setString(param.string.replace(arg1Value, arg2Value))
|
||||
.setRange(expr.range);
|
||||
});
|
||||
["substr", "substring"].forEach(fn => {
|
||||
|
|
|
@ -17,6 +17,10 @@ it("should evaluate logical expression", function () {
|
|||
const value9 = null === 1 && require("fail");
|
||||
const value91 = [] === [] && require("fail");
|
||||
const value92 = /a/ === /a/ && require("fail");
|
||||
const value93 =
|
||||
`hello${Math.random()}` === `world${Math.random()}` && require("fail");
|
||||
const value94 =
|
||||
`${Math.random()}hello` != `${Math.random()}world` || require("fail");
|
||||
|
||||
expect(value1).toBe("hello");
|
||||
expect(value2).toBe(true);
|
||||
|
@ -29,6 +33,8 @@ it("should evaluate logical expression", function () {
|
|||
expect(value9).toBe(false);
|
||||
expect(value91).toBe(false);
|
||||
expect(value92).toBe(false);
|
||||
expect(value93).toBe(false);
|
||||
expect(value94).toBe(true);
|
||||
});
|
||||
|
||||
it("shouldn't evaluate expression", function () {
|
||||
|
|
|
@ -317,21 +317,21 @@ declare abstract class BasicEvaluatedExpression {
|
|||
range: any;
|
||||
falsy: boolean;
|
||||
truthy: boolean;
|
||||
nullish: any;
|
||||
bool: any;
|
||||
number: any;
|
||||
bigint: any;
|
||||
regExp: any;
|
||||
string: any;
|
||||
quasis: any;
|
||||
parts: any;
|
||||
array: any;
|
||||
items: any;
|
||||
options: any;
|
||||
prefix: any;
|
||||
postfix: any;
|
||||
nullish: boolean;
|
||||
bool: boolean;
|
||||
number: number;
|
||||
bigint: bigint;
|
||||
regExp: RegExp;
|
||||
string: string;
|
||||
quasis: BasicEvaluatedExpression[];
|
||||
parts: BasicEvaluatedExpression[];
|
||||
array: any[];
|
||||
items: BasicEvaluatedExpression[];
|
||||
options: BasicEvaluatedExpression[];
|
||||
prefix: BasicEvaluatedExpression;
|
||||
postfix: BasicEvaluatedExpression;
|
||||
wrappedInnerExpressions: any;
|
||||
identifier: any;
|
||||
identifier: string;
|
||||
rootInfo: any;
|
||||
getMembers: any;
|
||||
expression: any;
|
||||
|
@ -350,13 +350,22 @@ declare abstract class BasicEvaluatedExpression {
|
|||
isTemplateString(): boolean;
|
||||
|
||||
/**
|
||||
* check for "simple" types (inlined) only
|
||||
* Is expression a primitive or an object type value?
|
||||
*/
|
||||
isSimpleType(): boolean;
|
||||
isSameType(basicEvaluatedExpression: BasicEvaluatedExpression): boolean;
|
||||
isPrimitiveType(): boolean;
|
||||
|
||||
/**
|
||||
* Is expression a runtime or compile-time value?
|
||||
*/
|
||||
isCompileTimeValue(): boolean;
|
||||
|
||||
/**
|
||||
* Gets the compile-time value of the expression
|
||||
*/
|
||||
asCompileTimeValue(): any;
|
||||
isTruthy(): boolean;
|
||||
isFalsy(): boolean;
|
||||
isNullish(): any;
|
||||
isNullish(): boolean;
|
||||
asBool(): any;
|
||||
asNullish(): boolean;
|
||||
asString(): any;
|
||||
|
@ -3321,7 +3330,7 @@ declare abstract class JavascriptParser extends Parser {
|
|||
statementStartPos: any;
|
||||
currentTagData: any;
|
||||
initializeEvaluating(): void;
|
||||
getRenameIdentifier(expr?: any): any;
|
||||
getRenameIdentifier(expr?: any): string;
|
||||
walkClass(classy: ClassExpression | ClassDeclaration): void;
|
||||
walkMethodDefinition(methodDefinition?: any): void;
|
||||
preWalkStatements(statements?: any): void;
|
||||
|
|
Loading…
Reference in New Issue