Skip to content

Commit

Permalink
fix(js_parser): don't crash on malformed for statement
Browse files Browse the repository at this point in the history
  • Loading branch information
arendjr committed Jan 13, 2025
1 parent 7f0e969 commit 7220702
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 10 deletions.
10 changes: 5 additions & 5 deletions crates/biome_js_parser/src/syntax/assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,17 @@ pub(crate) fn expression_to_assignment_pattern(
p: &mut JsParser,
target: CompletedMarker,
checkpoint: JsParserCheckpoint,
) -> CompletedMarker {
) -> ParsedSyntax {
match target.kind(p) {
JS_OBJECT_EXPRESSION => {
p.rewind(checkpoint);
ObjectAssignmentPattern.parse_object_pattern(p).unwrap()
ObjectAssignmentPattern.parse_object_pattern(p)
}
JS_ARRAY_EXPRESSION => {
p.rewind(checkpoint);
ArrayAssignmentPattern.parse_array_pattern(p).unwrap()
ArrayAssignmentPattern.parse_array_pattern(p)
}
_ => expression_to_assignment(p, target, checkpoint),
_ => ParsedSyntax::Present(expression_to_assignment(p, target, checkpoint)),
}
}

Expand All @@ -119,7 +119,7 @@ pub(crate) fn parse_assignment_pattern(p: &mut JsParser) -> ParsedSyntax {
let assignment_expression = parse_conditional_expr(p, ExpressionContext::default());

assignment_expression
.map(|expression| expression_to_assignment_pattern(p, expression, checkpoint))
.and_then(|expression| expression_to_assignment_pattern(p, expression, checkpoint))
}

/// Re-parses an expression as an assignment.
Expand Down
5 changes: 4 additions & 1 deletion crates/biome_js_parser/src/syntax/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,10 @@ fn parse_assign_expr_recursive(
target.change_kind(p, JS_BOGUS_ASSIGNMENT);
target
} else {
expression_to_assignment_pattern(p, target, checkpoint)
match expression_to_assignment_pattern(p, target, checkpoint) {
Present(target) => target,
Absent => return Absent,
}
};

let m = target.precede(p);
Expand Down
7 changes: 3 additions & 4 deletions crates/biome_js_parser/src/syntax/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1646,10 +1646,9 @@ fn parse_for_head(p: &mut JsParser, has_l_paren: bool, is_for_await: bool) -> Js

if p.at(T![in]) || p.at(T![of]) {
// for (assignment_pattern in ...
if let Present(assignment_expr) = init_expr {
let mut assignment =
expression_to_assignment_pattern(p, assignment_expr, checkpoint);

if let Present(mut assignment) = init_expr.and_then(|assignment_expr| {
expression_to_assignment_pattern(p, assignment_expr, checkpoint)
}) {
if TypeScript.is_supported(p)
&& p.at(T![in])
&& matches!(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
for@s[]of
108 changes: 108 additions & 0 deletions crates/biome_js_parser/tests/js_test_suite/error/issue4617.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
source: crates/biome_js_parser/tests/spec_test.rs
expression: snapshot
---
## Input

```js
for@s[]of
```


## AST

```
JsModule {
bom_token: missing (optional),
interpreter_token: missing (optional),
directives: JsDirectiveList [],
items: JsModuleItemList [
JsBogusStatement {
items: [
FOR_KW@0..3 "for" [] [],
JsBogusExpression {
items: [
JsDecorator {
at_token: AT@3..4 "@" [] [],
expression: JsIdentifierExpression {
name: JsReferenceIdentifier {
value_token: IDENT@4..5 "s" [] [],
},
},
},
],
},
JsArrayExpression {
l_brack_token: L_BRACK@5..6 "[" [] [],
elements: JsArrayElementList [],
r_brack_token: R_BRACK@6..7 "]" [] [],
},
JsExpressionStatement {
expression: JsIdentifierExpression {
name: JsReferenceIdentifier {
value_token: IDENT@7..9 "of" [] [],
},
},
semicolon_token: missing (optional),
},
],
},
],
eof_token: EOF@9..10 "" [Newline("\n")] [],
}
```

## CST

```
0: [email protected]
0: (empty)
1: (empty)
2: [email protected]
3: [email protected]
0: [email protected]
0: [email protected] "for" [] []
1: [email protected]
0: [email protected]
0: [email protected] "@" [] []
1: [email protected]
0: [email protected]
0: [email protected] "s" [] []
2: [email protected]
0: [email protected] "[" [] []
1: [email protected]
2: [email protected] "]" [] []
3: [email protected]
0: [email protected]
0: [email protected]
0: [email protected] "of" [] []
1: (empty)
4: [email protected] "" [Newline("\n")] []
```

## Diagnostics

```
issue4617.js:1:4 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× expected `(` but instead found `@`
> 1 │ for@s[]of
│ ^
2 │
i Remove @
issue4617.js:1:8 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× expected `)` but instead found `of`
> 1 │ for@s[]of
│ ^^
2 │
i Remove of
```

0 comments on commit 7220702

Please sign in to comment.