Skip to content

Commit

Permalink
fix(parser): do not double-parse modifiers of ts index signature in c…
Browse files Browse the repository at this point in the history
…lass
  • Loading branch information
branchseer committed Oct 28, 2024
1 parent 46e5360 commit ae388ec
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 8 deletions.
6 changes: 3 additions & 3 deletions crates/oxc_parser/src/js/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?,
)));
}

// * ...
Expand Down
17 changes: 17 additions & 0 deletions crates/oxc_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_parser/src/ts/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ impl<'a> ParserImpl<'a> {

pub(crate) fn parse_ts_type_signature(&mut self) -> Result<Option<TSSignature<'a>>> {
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() {
Expand Down
20 changes: 16 additions & 4 deletions crates/oxc_parser/src/ts/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1267,10 +1267,22 @@ impl<'a> ParserImpl<'a> {
))
}

pub(crate) fn parse_ts_index_signature_member(&mut self) -> Result<TSSignature<'a>> {
let span = self.start_span();
pub(crate) fn parse_ts_index_signature_member_with_modifiers(
&mut self,
) -> Result<TSSignature<'a>> {
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<TSIndexSignature<'a>> {
self.verify_modifiers(
&modifiers,
ModifierFlags::READONLY,
Expand All @@ -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,
Expand Down

0 comments on commit ae388ec

Please sign in to comment.