-
Notifications
You must be signed in to change notification settings - Fork 358
Open
Description
Summary
When printing a TSESTree AST that contains both a LogicalExpression (||) and a Nullish Coalescing (??) operator, recast omits required parentheses, resulting in invalid JavaScript output.
Environment
- Node.js: 21.7.3
- recast: 0.23.11
- @typescript-eslint/typescript-estree: 8.36.0
- @typescript-eslint/parser: 8.36.0
- astring: 1.9.0 (for reference)
Minimal Repro Example
import recast from "recast";
const ast = {
type: "Program",
body: [
{
type: "VariableDeclaration",
declarations: [
{
type: "VariableDeclarator",
id: { type: "Identifier", name: "_0x176f73" },
init: {
type: "LogicalExpression",
operator: "??",
left: {
type: "LogicalExpression",
operator: "||",
left: {
type: "MemberExpression",
computed: true,
object: { type: "Identifier", name: "_0x2778c4" },
property: { type: "Literal", value: "loading", raw: '"loading"' }
},
right: {
type: "MemberExpression",
computed: true,
object: { type: "Identifier", name: "_0x2778c4" },
property: { type: "Literal", value: "disabled", raw: '"disabled"' }
}
},
right: {
type: "LogicalExpression",
operator: "||",
left: {
type: "LogicalExpression",
operator: "||",
left: {
type: "MemberExpression",
computed: true,
object: { type: "Identifier", name: "_0x23798f" },
property: { type: "Literal", value: "disabled", raw: '"disabled"' }
},
right: { type: "Identifier", name: "_0x3df9d4" }
},
right: { type: "Identifier", name: "_0x7c2427" }
}
}
}
],
kind: "const"
}
],
sourceType: "script"
};
console.log(recast.print(ast).code);Expected Output:
const _0x176f73 = (_0x2778c4["loading"] || _0x2778c4["disabled"]) ??
(_0x23798f["disabled"] || _0x3df9d4 || _0x7c2427);Actual Output (bug):
const _0x176f73 = _0x2778c4["loading"] || _0x2778c4["disabled"] ?? _0x23798f["disabled"] || _0x3df9d4 || _0x7c2427;Notes
- The output is not valid JavaScript or changes semantics.
- TSESTree does not emit ParenthesizedExpression nodes here.
- Other code generators such as astring produce the correct output with the same AST.
Expected behavior
Recast should emit the necessary parentheses in these situations, preserving correct operator precedence even in the absence of explicit parenthesis nodes.
Thank you!
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels