Only start a destructuring pattern at the head of an AssignmentExpression - #1652
Open
andreasrosdal wants to merge 4 commits into
Open
Only start a destructuring pattern at the head of an AssignmentExpression#1652andreasrosdal wants to merge 4 commits into
andreasrosdal wants to merge 4 commits into
Conversation
…sion
`[a] = b` and `{a} = b` are AssignmentExpressions whose target happens to
be written like a literal. They are only reachable through
AssignmentExpression : LeftHandSideExpression = AssignmentExpression, so an
array or object literal anywhere else in an expression cannot begin one:
`0 || [a] = b` has no production, because a LogicalORExpression is not a
valid assignment target.
js_parse_postfix_expr() decides purely by peeking past the closing bracket
for a '=', without knowing where in the expression it is, so it accepts
programs with no parse:
0 || [a] = b; // -> 1
0 || {p:a} = b; // -> [object Object]
V8 rejects both with "Invalid left-hand side in assignment".
Add PF_PATTERN, set by js_parse_assign_expr2() when it starts the
ConditionalExpression that may turn out to be an assignment target, and
threaded down the unary/binary chain. Every recursive call that descends
into a non-leftmost operand clears it, so only the leftmost literal is
considered.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014mv33YvfHz7t9mmkituBnn
Covers the positions where an object/array literal must stay a literal (binary, short circuit, unary and private-name-in operands) and the head positions that must keep parsing as a pattern: statement level, both branches of a conditional, comma elements, call arguments, literal elements, initialisers, default parameter values, arrow bodies and the three for loop forms. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K6eRbuuuCujKgQkrHgvMrc
`#field in {} = 0` must be an early SyntaxError. It was not one because the
`{}` was taken for a destructuring pattern on the strength of the `=` that
follows, which is exactly what this change stops; test262's
private-field-invalid-assignment-target now passes in both modes.
Leaving the two entries behind makes the full test262 run exit non-zero for
errors that are fixed rather than new. Also covers the construct in the
local test, next to the array form already there.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6eRbuuuCujKgQkrHgvMrc
The rule is positional, so the test is mostly a list of positions. Added the ones the first round did not name: a NewExpression callee and argument, an update operand, a member access or call on a literal, an optional chain, every compound assignment operator, the head of each statement that takes a full Expression, an argument, array element, property value and spread, the operand of yield and await, a class field initialiser, a default parameter value, a template substitution and the tag of a tagged template.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[a] = band{a} = bare AssignmentExpressions whose target happens to be written like a literal. They are only reachable throughAssignmentExpression : LeftHandSideExpression = AssignmentExpression, so an array or object literal anywhere else in an expression cannot begin one —0 || [a] = bhas no parse, because a LogicalORExpression is not a valid assignment target.js_parse_postfix_expr()decides purely by peeking past the closing bracket for a=, without knowing where in the expression it is, so it accepts programs with no parse:V8 rejects both with Invalid left-hand side in assignment.
Add
PF_PATTERN, set byjs_parse_assign_expr2()when it starts the ConditionalExpression that may turn out to be an assignment target, and threaded down the unary/binary chain. Every recursive call that descends into a non-leftmost operand clears it, so only the leftmost literal is considered.Testing
No change against master in any of:
language/expressions/assignmentlanguage/destructuringlanguage/statements/for-oflanguage/expressions/arrow-functionlanguage/statements/variablelanguage/expressions/conditional🤖 Generated with Claude Code
https://claude.ai/code/session_014mv33YvfHz7t9mmkituBnn
Generated by Claude Code