diff --git a/CHANGELOG.md b/CHANGELOG.md index e25a3e485866..4a91834c25d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -114,6 +114,13 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b } } ``` +- Fix [#3410](https://github.com/biomejs/biome/issues/3410) by correctly parsing break statements containing keywords. + ```js + out: while (true) { + break out; + } + ``` + Contributed by @ah-yu ## v1.8.3 (2024-06-27) diff --git a/crates/biome_js_parser/src/syntax/stmt.rs b/crates/biome_js_parser/src/syntax/stmt.rs index 6d18214e32e7..ff6393dd6aae 100644 --- a/crates/biome_js_parser/src/syntax/stmt.rs +++ b/crates/biome_js_parser/src/syntax/stmt.rs @@ -582,6 +582,9 @@ fn parse_throw_statement(p: &mut JsParser) -> ParsedSyntax { // break foo; // } // } +// out: while (true) { +// break out; +// } // test_err js break_stmt // function foo() { break; } @@ -598,7 +601,7 @@ fn parse_break_statement(p: &mut JsParser) -> ParsedSyntax { let start = p.cur_range(); p.expect(T![break]); // break keyword - let error = if !p.has_preceding_line_break() && p.at(T![ident]) { + let error = if !p.has_preceding_line_break() && is_at_identifier(p) { let label_name = p.cur_text(); let error = match p.state().get_labelled_item(label_name) { diff --git a/crates/biome_js_parser/test_data/inline/ok/break_stmt.js b/crates/biome_js_parser/test_data/inline/ok/break_stmt.js index 1421378a30d3..eb0b6fb1009e 100644 --- a/crates/biome_js_parser/test_data/inline/ok/break_stmt.js +++ b/crates/biome_js_parser/test_data/inline/ok/break_stmt.js @@ -4,3 +4,6 @@ while (true) { break foo; } } +out: while (true) { + break out; +} diff --git a/crates/biome_js_parser/test_data/inline/ok/break_stmt.rast b/crates/biome_js_parser/test_data/inline/ok/break_stmt.rast index 1c6c5bdd973a..cd20c58bc99f 100644 --- a/crates/biome_js_parser/test_data/inline/ok/break_stmt.rast +++ b/crates/biome_js_parser/test_data/inline/ok/break_stmt.rast @@ -41,15 +41,42 @@ JsModule { r_curly_token: R_CURLY@50..52 "}" [Newline("\n")] [], }, }, + JsLabeledStatement { + label: JsLabel { + value_token: IDENT@52..56 "out" [Newline("\n")] [], + }, + colon_token: COLON@56..58 ":" [] [Whitespace(" ")], + body: JsWhileStatement { + while_token: WHILE_KW@58..64 "while" [] [Whitespace(" ")], + l_paren_token: L_PAREN@64..65 "(" [] [], + test: JsBooleanLiteralExpression { + value_token: TRUE_KW@65..69 "true" [] [], + }, + r_paren_token: R_PAREN@69..71 ")" [] [Whitespace(" ")], + body: JsBlockStatement { + l_curly_token: L_CURLY@71..72 "{" [] [], + statements: JsStatementList [ + JsBreakStatement { + break_token: BREAK_KW@72..81 "break" [Newline("\n"), Whitespace(" ")] [Whitespace(" ")], + label: JsLabel { + value_token: IDENT@81..84 "out" [] [], + }, + semicolon_token: SEMICOLON@84..85 ";" [] [], + }, + ], + r_curly_token: R_CURLY@85..87 "}" [Newline("\n")] [], + }, + }, + }, ], - eof_token: EOF@52..53 "" [Newline("\n")] [], + eof_token: EOF@87..88 "" [Newline("\n")] [], } -0: JS_MODULE@0..53 +0: JS_MODULE@0..88 0: (empty) 1: (empty) 2: JS_DIRECTIVE_LIST@0..0 - 3: JS_MODULE_ITEM_LIST@0..52 + 3: JS_MODULE_ITEM_LIST@0..87 0: JS_WHILE_STATEMENT@0..52 0: WHILE_KW@0..6 "while" [] [Whitespace(" ")] 1: L_PAREN@6..7 "(" [] [] @@ -77,4 +104,23 @@ JsModule { 2: SEMICOLON@45..46 ";" [] [] 2: R_CURLY@46..50 "}" [Newline("\n"), Whitespace(" ")] [] 2: R_CURLY@50..52 "}" [Newline("\n")] [] - 4: EOF@52..53 "" [Newline("\n")] [] + 1: JS_LABELED_STATEMENT@52..87 + 0: JS_LABEL@52..56 + 0: IDENT@52..56 "out" [Newline("\n")] [] + 1: COLON@56..58 ":" [] [Whitespace(" ")] + 2: JS_WHILE_STATEMENT@58..87 + 0: WHILE_KW@58..64 "while" [] [Whitespace(" ")] + 1: L_PAREN@64..65 "(" [] [] + 2: JS_BOOLEAN_LITERAL_EXPRESSION@65..69 + 0: TRUE_KW@65..69 "true" [] [] + 3: R_PAREN@69..71 ")" [] [Whitespace(" ")] + 4: JS_BLOCK_STATEMENT@71..87 + 0: L_CURLY@71..72 "{" [] [] + 1: JS_STATEMENT_LIST@72..85 + 0: JS_BREAK_STATEMENT@72..85 + 0: BREAK_KW@72..81 "break" [Newline("\n"), Whitespace(" ")] [Whitespace(" ")] + 1: JS_LABEL@81..84 + 0: IDENT@81..84 "out" [] [] + 2: SEMICOLON@84..85 ";" [] [] + 2: R_CURLY@85..87 "}" [Newline("\n")] [] + 4: EOF@87..88 "" [Newline("\n")] []