perf(parser): optimize trailing comma tracking (#25376)

## Summary

- Track trailing-comma spans only for array and object literals ending in a spread.
- Consume the stored span while covering a rest assignment target.

## Rationale

Avoids parser-state map work for ordinary trailing commas while retaining constant-time diagnostics for invalid rest-target trailing commas.
This commit is contained in:
camc314 committed 2026-08-07 21:30:28 +00:00
1 parent fe111eb112
commit e4208164e1
5 files changed
+30 -24

No files matched your search

+3 -1
View File
@@ -522,7 +522,9 @@ impl<'a, C: Config> ParserImpl<'a, C> {
Self::parse_array_expression_element,
)
});
if let Some(comma_start) = comma_start {
if let Some(comma_start) = comma_start
&& matches!(elements.last(), Some(ArrayExpressionElement::SpreadElement(_)))
{
self.state.trailing_commas.insert(start, self.end_span(comma_start));
}
self.expect(Kind::RBrack);
+4 -4
View File
@@ -125,8 +125,8 @@ impl<'a, C: Config> CoverGrammar<'a, ArrayExpression<'a>, C> for ArrayAssignment
}
let target = AssignmentTarget::cover(argument, p);
rest = Some(AssignmentTargetRest::boxed(span, target, p));
if let Some(span) = p.state.trailing_commas.get(&expr.span.start) {
p.error(diagnostics::rest_element_trailing_comma(*span));
if let Some(span) = p.state.trailing_commas.remove(&expr.span.start) {
p.error(diagnostics::rest_element_trailing_comma(span));
}
} else {
let error = diagnostics::spread_last_element(elem.span);
@@ -197,8 +197,8 @@ impl<'a, C: Config> CoverGrammar<'a, ObjectExpression<'a>, C> for ObjectAssignme
) {
p.error(diagnostics::invalid_rest_assignment_target(argument.span()));
}
if let Some(span) = p.state.trailing_commas.get(&expr.span.start) {
p.error(diagnostics::rest_element_trailing_comma(*span));
if let Some(span) = p.state.trailing_commas.remove(&expr.span.start) {
p.error(diagnostics::rest_element_trailing_comma(span));
}
let target = AssignmentTarget::cover(argument, p);
rest = Some(AssignmentTargetRest::boxed(span, target, p));
+6 -1
View File
@@ -28,7 +28,12 @@ impl<'a, C: Config> ParserImpl<'a, C> {
Self::parse_object_expression_property,
)
});
if let Some(comma_start) = comma_start {
if let Some(comma_start) = comma_start
&& matches!(
object_expression_properties.last(),
Some(ObjectPropertyKind::SpreadProperty(_))
)
{
self.state.trailing_commas.insert(start, self.end_span(comma_start));
}
self.expect(Kind::RCurly);
+3 -4
View File
@@ -12,10 +12,9 @@ pub struct ParserState<'a> {
/// Keyed by `ObjectProperty`'s span.start.
pub cover_initialized_name: FxHashMap<u32, AssignmentExpression<'a>>,
/// Trailing comma spans for `ArrayExpression` and `ObjectExpression`.
/// Used for error reporting.
/// Keyed by start span of `ArrayExpression` / `ObjectExpression`.
/// Valued by position of the trailing_comma.
/// Trailing comma spans for `ArrayExpression` and `ObjectExpression` ending in a spread.
/// Used for error reporting when covering a rest assignment target.
/// Keyed by the expression start and consumed when checked.
pub trailing_commas: FxHashMap<u32, Span>,
/// Statements that may need reparsing when `sourceType` is `unambiguous`.
@@ -1,8 +1,8 @@
checker.ts:
file size: 2922154 # 2.92 MB
sys allocs: 23
sys allocs: 19
sys reallocs: 10
sys deallocs: 23
sys deallocs: 19
sys alloc bytes: 4820 # 4.82 kB
sys peak growth: 2432 # 2.43 kB
arena allocs: 262590
@@ -11,11 +11,11 @@ checker.ts:
App.tsx:
file size: 415342 # 415.34 kB
sys allocs: 23
sys allocs: 18
sys reallocs: 13
sys deallocs: 23
sys alloc bytes: 38116 # 38.12 kB
sys peak growth: 26404 # 26.40 kB
sys deallocs: 18
sys alloc bytes: 4348 # 4.35 kB
sys peak growth: 1868 # 1.87 kB
arena allocs: 44037
arena reallocs: 3537
arena size: 2230856 # 2.23 MB
@@ -44,9 +44,9 @@ pdf.mjs:
antd.js:
file size: 6686316 # 6.69 MB
sys allocs: 190
sys allocs: 185
sys reallocs: 221
sys deallocs: 190
sys deallocs: 185
sys alloc bytes: 109952 # 109.95 kB
sys peak growth: 48264 # 48.26 kB
arena allocs: 528577
@@ -55,9 +55,9 @@ antd.js:
binder.ts:
file size: 193077 # 193.08 kB
sys allocs: 1
sys allocs: 0
sys reallocs: 0
sys deallocs: 1
sys deallocs: 0
sys alloc bytes: 3016 # 3.02 kB
sys peak growth: 251 # 251 B
arena allocs: 16587
@@ -66,11 +66,11 @@ binder.ts:
kitchen-sink.tsx:
file size: 732898 # 732.90 kB
sys allocs: 190
sys allocs: 183
sys reallocs: 160
sys deallocs: 190
sys alloc bytes: 51381 # 51.38 kB
sys peak growth: 14644 # 14.64 kB
sys deallocs: 183
sys alloc bytes: 34053 # 34.05 kB
sys peak growth: 3892 # 3.89 kB
arena allocs: 136453
arena reallocs: 11898
arena size: 6440104 # 6.44 MB