Skip to content

Commit 0398d40

Browse files
committed
fix(parser): reject trailing commas after rest elements in object patterns (#15223)
Reject codes like `({...a,} = {});` like we reject `([...a,] = []);`.
1 parent c28807b commit 0398d40

File tree

6 files changed

+44
-14
lines changed

6 files changed

+44
-14
lines changed

crates/oxc_parser/src/js/grammar.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ impl<'a> CoverGrammar<'a, ObjectExpression<'a>> for ObjectAssignmentTarget<'a> {
187187
) {
188188
p.error(diagnostics::invalid_rest_assignment_target(argument.span()));
189189
}
190+
if let Some(span) = p.state.trailing_commas.get(&expr.span.start) {
191+
p.error(diagnostics::rest_element_trailing_comma(*span));
192+
}
190193
let target = AssignmentTarget::cover(argument, p);
191194
rest = Some(p.ast.alloc_assignment_target_rest(span, target));
192195
} else {

crates/oxc_parser/src/js/object.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ impl<'a> ParserImpl<'a> {
1919
pub(crate) fn parse_object_expression(&mut self) -> Box<'a, ObjectExpression<'a>> {
2020
let span = self.start_span();
2121
self.expect(Kind::LCurly);
22-
let (object_expression_properties, _) = self.context_add(Context::In, |p| {
22+
let (object_expression_properties, comma_span) = self.context_add(Context::In, |p| {
2323
p.parse_delimited_list(
2424
Kind::RCurly,
2525
Kind::Comma,
2626
Self::parse_object_expression_property,
2727
)
2828
});
29+
if let Some(comma_span) = comma_span {
30+
self.state.trailing_commas.insert(span, self.end_span(comma_span));
31+
}
2932
self.expect(Kind::RCurly);
3033
self.ast.alloc_object_expression(self.end_span(span), object_expression_properties)
3134
}

crates/oxc_parser/src/state.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ pub struct ParserState<'a> {
1010
/// Keyed by `ObjectProperty`'s span.start.
1111
pub cover_initialized_name: FxHashMap<u32, AssignmentExpression<'a>>,
1212

13-
/// Trailing comma spans for `ArrayExpression`.
13+
/// Trailing comma spans for `ArrayExpression` and `ObjectExpression`.
1414
/// Used for error reporting.
15-
/// Keyed by start span of `ArrayExpression`.
15+
/// Keyed by start span of `ArrayExpression` / `ObjectExpression`.
1616
/// Valued by position of the trailing_comma.
1717
pub trailing_commas: FxHashMap<u32, Span>,
1818
}

tasks/coverage/snapshots/parser_babel.snap

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,7 @@ commit: 4cc3d888
33
parser_babel Summary:
44
AST Parsed : 2422/2440 (99.26%)
55
Positive Passed: 2395/2440 (98.16%)
6-
Negative Passed: 1676/1752 (95.66%)
7-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-rest/input.js
8-
9-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-for-in/input.js
10-
11-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-nested/input.js
12-
6+
Negative Passed: 1679/1752 (95.83%)
137
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/private-in/invalid-private-followed-by-in-2/input.js
148

159
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-in-single-statement-context-async/input.js
@@ -6215,6 +6209,27 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
62156209
· ────
62166210
╰────
62176211

6212+
× A rest parameter or binding pattern may not have a trailing comma.
6213+
╭─[babel/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-rest/input.js:1:7]
6214+
1 │ ({...a,} = {});
6215+
· ─
6216+
╰────
6217+
help: Remove the trailing comma here
6218+
6219+
× A rest parameter or binding pattern may not have a trailing comma.
6220+
╭─[babel/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-for-in/input.js:1:11]
6221+
1 │ for ({...a,} in []);
6222+
· ─
6223+
╰────
6224+
help: Remove the trailing comma here
6225+
6226+
× A rest parameter or binding pattern may not have a trailing comma.
6227+
╭─[babel/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-nested/input.js:1:7]
6228+
1 │ [{...a,}] = [];
6229+
· ─
6230+
╰────
6231+
help: Remove the trailing comma here
6232+
62186233
× Spread must be last element
62196234
╭─[babel/packages/babel-parser/test/fixtures/es2018/object-rest-spread/expression-rest-not-last-invalid/input.js:1:3]
62206235
1 │ ({...rest, b} = {})

tasks/coverage/snapshots/parser_typescript.snap

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20165,6 +20165,15 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc
2016520165
╰────
2016620166
help: Remove the trailing comma here
2016720167

20168+
× A rest parameter or binding pattern may not have a trailing comma.
20169+
╭─[typescript/tests/cases/conformance/es7/trailingCommasInBindingPatterns.ts:5:7]
20170+
4 │ ([...c,] = []);
20171+
5 │ ({...d,} = {});
20172+
· ─
20173+
6 │
20174+
╰────
20175+
help: Remove the trailing comma here
20176+
2016820177
× A rest parameter or binding pattern may not have a trailing comma.
2016920178
╭─[typescript/tests/cases/conformance/es7/trailingCommasInFunctionParametersAndArguments.ts:5:20]
2017020179
4 │
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
File | File size || Sys allocs | Sys reallocs || Arena allocs | Arena reallocs | Arena bytes
22
-------------------------------------------------------------------------------------------------------------------------------------------
3-
checker.ts | 2.92 MB || 10163 | 21 || 268665 | 23341
3+
checker.ts | 2.92 MB || 10165 | 21 || 268665 | 23341
44

5-
cal.com.tsx | 1.06 MB || 2205 | 61 || 138188 | 13712
5+
cal.com.tsx | 1.06 MB || 2209 | 61 || 138188 | 13712
66

77
RadixUIAdoptionSection.jsx | 2.52 kB || 1 | 0 || 365 | 66
88

99
pdf.mjs | 567.30 kB || 701 | 75 || 90678 | 8148
1010

11-
antd.js | 6.69 MB || 6995 | 235 || 528505 | 55357
11+
antd.js | 6.69 MB || 6997 | 235 || 528505 | 55357
1212

13-
binder.ts | 193.08 kB || 537 | 7 || 16807 | 1475
13+
binder.ts | 193.08 kB || 538 | 7 || 16807 | 1475
1414

0 commit comments

Comments
 (0)