diff --git a/src/quick-lint-js/fe/parse-statement.cpp b/src/quick-lint-js/fe/parse-statement.cpp index a7395fa059..8f80d95d1b 100644 --- a/src/quick-lint-js/fe/parse-statement.cpp +++ b/src/quick-lint-js/fe/parse-statement.cpp @@ -867,6 +867,7 @@ Parser::parse_and_visit_typescript_interface_or_namespace_or_type_statement( default: QLJS_UNREACHABLE(); } + this->lexer_.commit_transaction(std::move(transaction)); return Parse_Possible_Label_Result::parsed_not_as_a_label; // type++; // Expression. diff --git a/test/test-parse-typescript-interface.cpp b/test/test-parse-typescript-interface.cpp index 81d845ac96..568070fae4 100644 --- a/test/test-parse-typescript-interface.cpp +++ b/test/test-parse-typescript-interface.cpp @@ -1494,6 +1494,29 @@ TEST_F(Test_Parse_TypeScript_Interface, u8" \\u{63}onstructor();}"_sv, no_diags, typescript_options); } + +TEST_F(Test_Parse_TypeScript_Interface, + parser_is_left_in_consistent_state_after_parsing_interface) { + { + Test_Parser p( + u8"interface I {}\n" + u8"let a = \"", + typescript_options, capture_diags); + p.parse_and_visit_statement(); + p.parse_and_visit_statement(); + EXPECT_THAT(p.visits, ElementsAreArray({ + "visit_variable_declaration", // I + "visit_enter_interface_scope", // { + "visit_exit_interface_scope", // } + "visit_variable_declaration", // a + })); + assert_diagnostics( + p.code, p.errors, + { + u8" ^^ Diag_Unclosed_String_Literal"_diag, + }); + } +} } }