From ae388ec6c0915d733f5d4d34f086b180918c9881 Mon Sep 17 00:00:00 2001 From: branchseer Date: Mon, 28 Oct 2024 23:16:44 +0800 Subject: [PATCH] fix(parser): do not double-parse modifiers of ts index signature in class --- crates/oxc_parser/src/js/class.rs | 6 +++--- crates/oxc_parser/src/lib.rs | 17 +++++++++++++++++ crates/oxc_parser/src/ts/statement.rs | 2 +- crates/oxc_parser/src/ts/types.rs | 20 ++++++++++++++++---- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/crates/oxc_parser/src/js/class.rs b/crates/oxc_parser/src/js/class.rs index 1134d31403fa0a..dfad7e00410352 100644 --- a/crates/oxc_parser/src/js/class.rs +++ b/crates/oxc_parser/src/js/class.rs @@ -229,9 +229,9 @@ impl<'a> ParserImpl<'a> { } if self.is_at_ts_index_signature_member() { - if let TSSignature::TSIndexSignature(sig) = self.parse_ts_index_signature_member()? { - return Ok(Some(ClassElement::TSIndexSignature(sig))); - } + return Ok(Some(self.ast.class_element_from_ts_index_signature( + self.parse_ts_index_signature_member(span, modifiers)?, + ))); } // * ... diff --git a/crates/oxc_parser/src/lib.rs b/crates/oxc_parser/src/lib.rs index 8a8b705681d9ac..6bb5cbe85c7a0b 100644 --- a/crates/oxc_parser/src/lib.rs +++ b/crates/oxc_parser/src/lib.rs @@ -696,6 +696,23 @@ mod test { assert_eq!(ret.errors.first().unwrap().to_string(), "Source length exceeds 4 GiB limit"); } + #[test] + fn class_index_signature_modifiers() { + use oxc_ast::ast::*; + let allocator = Allocator::default(); + let source_type = SourceType::ts(); + let source = "class Foo { readonly [a: string]: string }"; + let ret = Parser::new(&allocator, source, source_type).parse(); + let Statement::ClassDeclaration(class_decl) = &ret.program.body[0] else { + panic!("expected Statement::ClassDeclaration"); + }; + let ClassElement::TSIndexSignature(index_sig) = &class_decl.body.body[0] else { + panic!("expected ClassElement::TSIndexSignature"); + }; + assert!(index_sig.readonly); + assert_eq!(index_sig.span.start, source.find("readonly").unwrap() as u32); + } + // Source with length MAX_LEN parses OK. // This test takes over 1 minute on an M1 Macbook Pro unless compiled in release mode. // `not(debug_assertions)` is a proxy for detecting release mode. diff --git a/crates/oxc_parser/src/ts/statement.rs b/crates/oxc_parser/src/ts/statement.rs index 4123f05b859efe..a9b013846bcccc 100644 --- a/crates/oxc_parser/src/ts/statement.rs +++ b/crates/oxc_parser/src/ts/statement.rs @@ -206,7 +206,7 @@ impl<'a> ParserImpl<'a> { pub(crate) fn parse_ts_type_signature(&mut self) -> Result>> { if self.is_at_ts_index_signature_member() { - return self.parse_ts_index_signature_member().map(Some); + return self.parse_ts_index_signature_member_with_modifiers().map(Some); } match self.cur_kind() { diff --git a/crates/oxc_parser/src/ts/types.rs b/crates/oxc_parser/src/ts/types.rs index 49374dd6c0fee9..b5a8699ff89e9a 100644 --- a/crates/oxc_parser/src/ts/types.rs +++ b/crates/oxc_parser/src/ts/types.rs @@ -1267,10 +1267,22 @@ impl<'a> ParserImpl<'a> { )) } - pub(crate) fn parse_ts_index_signature_member(&mut self) -> Result> { - let span = self.start_span(); + pub(crate) fn parse_ts_index_signature_member_with_modifiers( + &mut self, + ) -> Result> { + let start_span = self.start_span(); let modifiers = self.parse_class_element_modifiers(false); + Ok(self.ast.ts_signature_from_ts_index_signature( + self.parse_ts_index_signature_member(start_span, modifiers)?, + )) + } + + pub(crate) fn parse_ts_index_signature_member( + &mut self, + start_span: Span, + modifiers: Modifiers<'a>, + ) -> Result> { self.verify_modifiers( &modifiers, ModifierFlags::READONLY, @@ -1288,8 +1300,8 @@ impl<'a> ParserImpl<'a> { if let Some(type_annotation) = type_annotation { self.bump(Kind::Comma); self.bump(Kind::Semicolon); - Ok(self.ast.ts_signature_index_signature( - self.end_span(span), + Ok(self.ast.ts_index_signature( + self.end_span(start_span), parameters, type_annotation, readonly,