Skip to content

Add support for ??=, ||=,&&= in JavaScript#72

Open
CyanM0un wants to merge 1 commit into
antgroup:mainfrom
CyanM0un:main
Open

Add support for ??=, ||=,&&= in JavaScript#72
CyanM0un wants to merge 1 commit into
antgroup:mainfrom
CyanM0un:main

Conversation

@CyanM0un

Copy link
Copy Markdown
Contributor

Convert a ??= b to a = a ?? b for parsing, similar for others

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements desugaring for logical assignment operators (??=, ||=, &&=) in the JavaScript parser. The review feedback highlights critical issues regarding semantic correctness, specifically the double evaluation of the left-hand side and the lack of proper short-circuiting behavior compared to standard JavaScript. There is also a concern regarding the reuse of UAST node instances, which could lead to corrupted tree structures.

Comment on lines +345 to +353
if (node.operator === '??=') {
return UAST.assignmentExpression(left, UAST.binaryExpression('??', left, right), '=', false);
}
if (node.operator === '||=') {
return UAST.assignmentExpression(left, UAST.binaryExpression('||', left, right), '=', false);
}
if (node.operator === '&&=') {
return UAST.assignmentExpression(left, UAST.binaryExpression('&&', left, right), '=', false);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation of logical assignment operators (??=, ||=, &&=) has two significant issues:

  1. Semantic Correctness (Side Effects & Short-circuiting): Desugaring a ??= b to a = a ?? b is not equivalent in JavaScript. It causes the left-hand side to be evaluated twice (e.g., func().prop ??= 1 calls func() twice), which is incorrect if the expression has side effects. Furthermore, logical assignment operators in JS are short-circuiting; a ||= b only performs an assignment if a is falsy. The desugared a = a || b always performs an assignment, which can trigger setters or proxy traps unnecessarily.
  2. UAST Node Reuse: The left node object is reused as both the assignment target and an operand in the binary expression. In most AST/UAST implementations, node objects must be unique instances within the tree. Reusing the same object instance can lead to broken parent pointers and issues during tree traversal or serialization.

If the UAST specification supports these operators, it is highly recommended to pass them directly to UAST.assignmentExpression. If not, consider updating the UAST spec to support them, as correct desugaring is complex and typically requires temporary variables to ensure single evaluation of the LHS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant