This document specifies the extensions to the core ESTree AST types to support the ES2020 grammar.
extend interface Literal <: Expression {
type: "Literal";
value: string | boolean | null | number | RegExp | bigint;
}
value
property can be aBigInt
value to representBigInt
literals such as100n
.
interface BigIntLiteral <: Literal {
bigint: string;
}
bigint
property is the string representation of theBigInt
value. It doesn't include the suffixn
.- In environments that don't support
BigInt
values,value
property will benull
as theBigInt
value can't be represented natively.
interface ImportExpression <: Expression {
type: "ImportExpression";
source: Expression;
}
ImportExpression
node represents Dynamic Imports such asimport(source)
. Thesource
property is the importing source as similar to ImportDeclaration node, but it can be an arbitrary expression node.
extend enum LogicalOperator {
"||" | "&&" | "??"
}
- The
operator
property of theLogicalExpression
node can be"??"
to represent Nullish Coalescing syntax.
interface OptionalChainLink {
optional: boolean;
shortCircuited: boolean;
}
extend interface MemberExpression <: OptionalChainLink {}
extend interface CallExpression <: OptionalChainLink {}
- The
OptionalChainLink
interface represents Optional Chaining syntax. This is just an interface rather than aNode
.- The
optional
property represents if it's optional by?.
. - The
shortCircuited
property represents if it's short-circuited by preceded optional member|call expressions.
- The
- The existing MemberExpression and CallExpression nodes inherit the
OptionalChainLink
interface to represent that those are the links of optional chaining.
For examples:
// obj?.aaa?.bbb
{
"type": "MemberExpression",
"optional": true, // If `obj.aaa` was nullish, this node is evaluated to undefined.
"shortCircuited": true, // If `obj` was nullish, this node is short-circuited.
"object": {
"type": "MemberExpression",
"optional": true, // If `obj` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"object": { "type": "Identifier", "name": "obj" },
"property": { "type": "Identifier", "name": "aaa" },
},
"property": { "type": "Identifier", "name": "bbb" },
}
// obj?.aaa.bbb
{
"type": "MemberExpression",
"optional": false, // If `obj.aaa` was nullish, this node is evaluated to throwing TypeError.
"shortCircuited": true, // If `obj` was nullish, this node is short-circuited.
"object": {
"type": "MemberExpression",
"optional": true, // If `obj` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"object": { "type": "Identifier", "name": "obj" },
"property": { "type": "Identifier", "name": "aaa" },
},
"property": { "type": "Identifier", "name": "bbb" },
}
// (obj?.aaa)?.bbb
{
"type": "MemberExpression",
"optional": true, // If `obj.aaa` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"object": {
"type": "MemberExpression",
"optional": true, // If `obj` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"object": { "type": "Identifier", "name": "obj" },
"property": { "type": "Identifier", "name": "aaa" },
},
"property": { "type": "Identifier", "name": "bbb" },
}
// (obj?.aaa).bbb
{
"type": "MemberExpression",
"optional": false, // If `obj.aaa` was nullish, this node is evaluated to throwing TypeError.
"shortCircuited": false, // This node isn't short-circuited.
"object": {
"type": "MemberExpression",
"optional": true, // If `obj` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"object": { "type": "Identifier", "name": "obj" },
"property": { "type": "Identifier", "name": "aaa" },
},
"property": { "type": "Identifier", "name": "bbb" },
}
// func?.()?.bbb
{
"type": "MemberExpression",
"optional": true, // If the result of `func()` was nullish, this node is evaluated to undefined.
"shortCircuited": true, // If `func` was nullish, this node is short-circuited.
"object": {
"type": "CallExpression",
"optional": true, // If `func` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"callee": { "type": "Identifier", "name": "func" },
"arguments": [],
},
"property": { "type": "Identifier", "name": "bbb" },
}
// func?.().bbb
{
"type": "MemberExpression",
"optional": false, // If the result of `func()` was nullish, this node is evaluated to throwing TypeError.
"shortCircuited": true, // If `func` was nullish, this node is short-circuited.
"object": {
"type": "CallExpression",
"optional": true, // If `func` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"callee": { "type": "Identifier", "name": "func" },
"arguments": [],
},
"property": { "type": "Identifier", "name": "bbb" },
}
// (func?.())?.bbb
{
"type": "MemberExpression",
"optional": true, // If the result of `func()` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"object": {
"type": "CallExpression",
"optional": true, // If `func` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"callee": { "type": "Identifier", "name": "func" },
"arguments": [],
},
"property": { "type": "Identifier", "name": "bbb" },
}
// (func?.()).bbb
{
"type": "MemberExpression",
"optional": false, // If the result of `func()` was nullish, this node is evaluated to throwing TypeError.
"shortCircuited": false, // This node isn't short-circuited.
"object": {
"type": "CallExpression",
"optional": true, // If `func` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"callee": { "type": "Identifier", "name": "func" },
"arguments": [],
},
"property": { "type": "Identifier", "name": "bbb" },
}
// obj?.aaa?.()
{
"type": "CallExpression",
"optional": true, // If `obj.aaa` was nullish, this node is evaluated to undefined.
"shortCircuited": true, // If `obj` was nullish, this node is short-circuited.
"callee": {
"type": "MemberExpression",
"optional": true, // If `obj` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"object": { "type": "Identifier", "name": "obj" },
"property": { "type": "Identifier", "name": "aaa" },
},
"arguments": [],
}
// obj?.aaa()
{
"type": "CallExpression",
"optional": false, // If `obj.aaa` was nullish, this node is evaluated to throwing TypeError.
"shortCircuited": true, // If `obj` was nullish, this node is short-circuited.
"callee": {
"type": "MemberExpression",
"optional": true, // If `obj` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"object": { "type": "Identifier", "name": "obj" },
"property": { "type": "Identifier", "name": "aaa" },
},
"arguments": [],
}
// (obj?.aaa)?.()
{
"type": "CallExpression",
"optional": true, // If `obj.aaa` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"callee": {
"type": "MemberExpression",
"optional": true, // If `obj` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"object": { "type": "Identifier", "name": "obj" },
"property": { "type": "Identifier", "name": "aaa" },
},
"arguments": [],
}
// (obj?.aaa)()
{
"type": "CallExpression",
"optional": false, // If `obj.aaa` was nullish, this node is evaluated to throwing TypeError.
"shortCircuited": false, // This node isn't short-circuited.
"callee": {
"type": "MemberExpression",
"optional": true, // If `obj` was nullish, this node is evaluated to undefined.
"shortCircuited": false, // This node isn't short-circuited.
"object": { "type": "Identifier", "name": "obj" },
"property": { "type": "Identifier", "name": "aaa" },
},
"arguments": [],
}