diff --git a/crates/oxc_ast/src/generated/assert_layouts.rs b/crates/oxc_ast/src/generated/assert_layouts.rs index 520a82908ae44..7969d6dfe8585 100644 --- a/crates/oxc_ast/src/generated/assert_layouts.rs +++ b/crates/oxc_ast/src/generated/assert_layouts.rs @@ -1522,18 +1522,23 @@ const _: () = { assert!(offset_of!(CapturingGroup, name) == 8usize); assert!(offset_of!(CapturingGroup, body) == 24usize); - assert!(size_of::() == 56usize); + assert!(size_of::() == 64usize); assert!(align_of::() == 8usize); assert!(offset_of!(IgnoreGroup, span) == 0usize); - assert!(offset_of!(IgnoreGroup, enabling_modifiers) == 8usize); - assert!(offset_of!(IgnoreGroup, disabling_modifiers) == 11usize); - assert!(offset_of!(IgnoreGroup, body) == 16usize); + assert!(offset_of!(IgnoreGroup, modifiers) == 8usize); + assert!(offset_of!(IgnoreGroup, body) == 24usize); - assert!(size_of::() == 3usize); - assert!(align_of::() == 1usize); - assert!(offset_of!(ModifierFlags, ignore_case) == 0usize); - assert!(offset_of!(ModifierFlags, sticky) == 1usize); - assert!(offset_of!(ModifierFlags, multiline) == 2usize); + assert!(size_of::() == 16usize); + assert!(align_of::() == 4usize); + assert!(offset_of!(Modifiers, span) == 0usize); + assert!(offset_of!(Modifiers, enabling) == 8usize); + assert!(offset_of!(Modifiers, disabling) == 11usize); + + assert!(size_of::() == 3usize); + assert!(align_of::() == 1usize); + assert!(offset_of!(Modifier, ignore_case) == 0usize); + assert!(offset_of!(Modifier, multiline) == 1usize); + assert!(offset_of!(Modifier, sticky) == 2usize); assert!(size_of::() == 12usize); assert!(align_of::() == 4usize); @@ -3059,18 +3064,23 @@ const _: () = { assert!(offset_of!(CapturingGroup, name) == 8usize); assert!(offset_of!(CapturingGroup, body) == 16usize); - assert!(size_of::() == 40usize); + assert!(size_of::() == 48usize); assert!(align_of::() == 4usize); assert!(offset_of!(IgnoreGroup, span) == 0usize); - assert!(offset_of!(IgnoreGroup, enabling_modifiers) == 8usize); - assert!(offset_of!(IgnoreGroup, disabling_modifiers) == 11usize); - assert!(offset_of!(IgnoreGroup, body) == 16usize); - - assert!(size_of::() == 3usize); - assert!(align_of::() == 1usize); - assert!(offset_of!(ModifierFlags, ignore_case) == 0usize); - assert!(offset_of!(ModifierFlags, sticky) == 1usize); - assert!(offset_of!(ModifierFlags, multiline) == 2usize); + assert!(offset_of!(IgnoreGroup, modifiers) == 8usize); + assert!(offset_of!(IgnoreGroup, body) == 24usize); + + assert!(size_of::() == 16usize); + assert!(align_of::() == 4usize); + assert!(offset_of!(Modifiers, span) == 0usize); + assert!(offset_of!(Modifiers, enabling) == 8usize); + assert!(offset_of!(Modifiers, disabling) == 11usize); + + assert!(size_of::() == 3usize); + assert!(align_of::() == 1usize); + assert!(offset_of!(Modifier, ignore_case) == 0usize); + assert!(offset_of!(Modifier, multiline) == 1usize); + assert!(offset_of!(Modifier, sticky) == 2usize); assert!(size_of::() == 12usize); assert!(align_of::() == 4usize); diff --git a/crates/oxc_regular_expression/src/ast.rs b/crates/oxc_regular_expression/src/ast.rs index 5a2dcfee29cfe..b31961d714eff 100644 --- a/crates/oxc_regular_expression/src/ast.rs +++ b/crates/oxc_regular_expression/src/ast.rs @@ -351,21 +351,32 @@ pub struct CapturingGroup<'a> { pub struct IgnoreGroup<'a> { #[serde(flatten)] pub span: Span, - pub enabling_modifiers: Option, - pub disabling_modifiers: Option, + pub modifiers: Option, pub body: Disjunction<'a>, } -/// Pattern modifiers in [`IgnoreGroup`]. -/// e.g. `(?i:...)`, `(?-s:...)` +/// Modifiers in [`IgnoreGroup`]. +/// e.g. `i` in `(?i:...)`, `-s` in `(?-s:...)` #[ast] #[derive(Debug)] #[generate_derive(CloneIn, ContentEq, ContentHash)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] -pub struct ModifierFlags { +pub struct Modifiers { + #[serde(flatten)] + pub span: Span, + pub enabling: Option, + pub disabling: Option, +} + +/// Each part of modifier in [`Modifiers`]. +#[ast] +#[derive(Debug)] +#[generate_derive(CloneIn, ContentEq, ContentHash)] +#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] +pub struct Modifier { pub ignore_case: bool, - pub sticky: bool, pub multiline: bool, + pub sticky: bool, } /// Backreference by index. diff --git a/crates/oxc_regular_expression/src/ast_impl/display.rs b/crates/oxc_regular_expression/src/ast_impl/display.rs index 774edae814840..846ca44be4d16 100644 --- a/crates/oxc_regular_expression/src/ast_impl/display.rs +++ b/crates/oxc_regular_expression/src/ast_impl/display.rs @@ -258,30 +258,29 @@ impl<'a> Display for CapturingGroup<'a> { impl<'a> Display for IgnoreGroup<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fn write_flags( - f: &mut fmt::Formatter<'_>, - prefix: char, - flags: &ModifierFlags, - ) -> fmt::Result { + fn write_flags(f: &mut fmt::Formatter<'_>, flags: &Modifier) -> fmt::Result { if flags.ignore_case { - write!(f, "{prefix}i")?; - } - if flags.sticky { - write!(f, "{prefix}y")?; + write!(f, "i")?; } if flags.multiline { - write!(f, "{prefix}m")?; + write!(f, "m")?; + } + if flags.sticky { + write!(f, "s")?; } Ok(()) } write!(f, "(?")?; - if let Some(enabling) = &self.enabling_modifiers { - write_flags(f, '\0', enabling)?; - } - if let Some(disabling) = &self.disabling_modifiers { - write_flags(f, '-', disabling)?; + if let Some(modifiers) = &self.modifiers { + if let Some(enabling) = &modifiers.enabling { + write_flags(f, enabling)?; + } + if let Some(disabling) = &modifiers.disabling { + write!(f, "-")?; + write_flags(f, disabling)?; + } } write!(f, ":{})", self.body) @@ -541,6 +540,12 @@ mod test { (r"/[\-]/u", None), (r"/[\-]/v", None), (r"/([\-a-z]{0,31})/iu", None), + // ES2025 --- + (r"/(?i:.)/", None), + (r"/(?-s:.)/", None), + (r"/(?im-s:.)/u", None), + (r"/(?m-is:.)/v", None), + (r"/(?smi:.)/v", Some(r"/(?ims:.)/v")), ]; #[test] diff --git a/crates/oxc_regular_expression/src/diagnostics.rs b/crates/oxc_regular_expression/src/diagnostics.rs index 12945812331ab..6550cce7b58cf 100644 --- a/crates/oxc_regular_expression/src/diagnostics.rs +++ b/crates/oxc_regular_expression/src/diagnostics.rs @@ -109,11 +109,6 @@ pub fn character_class_contents_invalid_operands(span: Span) -> OxcDiagnostic { .with_label(span) } -#[cold] -pub fn missing_capturing_group_name(span: Span) -> OxcDiagnostic { - OxcDiagnostic::error(format!("{PREFIX} Missing capturing group name")).with_label(span) -} - #[cold] pub fn too_large_number_in_braced_quantifier(span: Span) -> OxcDiagnostic { OxcDiagnostic::error(format!("{PREFIX} Number is too large in braced quantifier")) @@ -152,3 +147,13 @@ pub fn invalid_unicode_escape_sequence(span: Span) -> OxcDiagnostic { pub fn invalid_surrogate_pair(span: Span) -> OxcDiagnostic { OxcDiagnostic::error(format!("{PREFIX} Invalid surrogate pair")).with_label(span) } + +#[cold] +pub fn invalid_modifiers(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error(format!("{PREFIX} Invalid modifiers")).with_label(span) +} + +#[cold] +pub fn unknown_modifiers(span: Span) -> OxcDiagnostic { + OxcDiagnostic::error(format!("{PREFIX} Unknown modifiers")).with_label(span) +} diff --git a/crates/oxc_regular_expression/src/generated/derive_clone_in.rs b/crates/oxc_regular_expression/src/generated/derive_clone_in.rs index 6f8de2299f1e4..9160d00b409a8 100644 --- a/crates/oxc_regular_expression/src/generated/derive_clone_in.rs +++ b/crates/oxc_regular_expression/src/generated/derive_clone_in.rs @@ -296,20 +296,30 @@ impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for IgnoreGroup<'old_alloc> { fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { IgnoreGroup { span: CloneIn::clone_in(&self.span, allocator), - enabling_modifiers: CloneIn::clone_in(&self.enabling_modifiers, allocator), - disabling_modifiers: CloneIn::clone_in(&self.disabling_modifiers, allocator), + modifiers: CloneIn::clone_in(&self.modifiers, allocator), body: CloneIn::clone_in(&self.body, allocator), } } } -impl<'alloc> CloneIn<'alloc> for ModifierFlags { - type Cloned = ModifierFlags; +impl<'alloc> CloneIn<'alloc> for Modifiers { + type Cloned = Modifiers; fn clone_in(&self, allocator: &'alloc Allocator) -> Self::Cloned { - ModifierFlags { + Modifiers { + span: CloneIn::clone_in(&self.span, allocator), + enabling: CloneIn::clone_in(&self.enabling, allocator), + disabling: CloneIn::clone_in(&self.disabling, allocator), + } + } +} + +impl<'alloc> CloneIn<'alloc> for Modifier { + type Cloned = Modifier; + fn clone_in(&self, allocator: &'alloc Allocator) -> Self::Cloned { + Modifier { ignore_case: CloneIn::clone_in(&self.ignore_case, allocator), - sticky: CloneIn::clone_in(&self.sticky, allocator), multiline: CloneIn::clone_in(&self.multiline, allocator), + sticky: CloneIn::clone_in(&self.sticky, allocator), } } } diff --git a/crates/oxc_regular_expression/src/generated/derive_content_eq.rs b/crates/oxc_regular_expression/src/generated/derive_content_eq.rs index e4c3f8bd27df8..bb8e4861f0b47 100644 --- a/crates/oxc_regular_expression/src/generated/derive_content_eq.rs +++ b/crates/oxc_regular_expression/src/generated/derive_content_eq.rs @@ -230,17 +230,23 @@ impl<'a> ContentEq for CapturingGroup<'a> { impl<'a> ContentEq for IgnoreGroup<'a> { fn content_eq(&self, other: &Self) -> bool { - ContentEq::content_eq(&self.enabling_modifiers, &other.enabling_modifiers) - && ContentEq::content_eq(&self.disabling_modifiers, &other.disabling_modifiers) + ContentEq::content_eq(&self.modifiers, &other.modifiers) && ContentEq::content_eq(&self.body, &other.body) } } -impl ContentEq for ModifierFlags { +impl ContentEq for Modifiers { + fn content_eq(&self, other: &Self) -> bool { + ContentEq::content_eq(&self.enabling, &other.enabling) + && ContentEq::content_eq(&self.disabling, &other.disabling) + } +} + +impl ContentEq for Modifier { fn content_eq(&self, other: &Self) -> bool { ContentEq::content_eq(&self.ignore_case, &other.ignore_case) - && ContentEq::content_eq(&self.sticky, &other.sticky) && ContentEq::content_eq(&self.multiline, &other.multiline) + && ContentEq::content_eq(&self.sticky, &other.sticky) } } diff --git a/crates/oxc_regular_expression/src/generated/derive_content_hash.rs b/crates/oxc_regular_expression/src/generated/derive_content_hash.rs index 0680061472d1e..67219af7653a5 100644 --- a/crates/oxc_regular_expression/src/generated/derive_content_hash.rs +++ b/crates/oxc_regular_expression/src/generated/derive_content_hash.rs @@ -179,17 +179,23 @@ impl<'a> ContentHash for CapturingGroup<'a> { impl<'a> ContentHash for IgnoreGroup<'a> { fn content_hash(&self, state: &mut H) { - ContentHash::content_hash(&self.enabling_modifiers, state); - ContentHash::content_hash(&self.disabling_modifiers, state); + ContentHash::content_hash(&self.modifiers, state); ContentHash::content_hash(&self.body, state); } } -impl ContentHash for ModifierFlags { +impl ContentHash for Modifiers { + fn content_hash(&self, state: &mut H) { + ContentHash::content_hash(&self.enabling, state); + ContentHash::content_hash(&self.disabling, state); + } +} + +impl ContentHash for Modifier { fn content_hash(&self, state: &mut H) { ContentHash::content_hash(&self.ignore_case, state); - ContentHash::content_hash(&self.sticky, state); ContentHash::content_hash(&self.multiline, state); + ContentHash::content_hash(&self.sticky, state); } } diff --git a/crates/oxc_regular_expression/src/parser/mod.rs b/crates/oxc_regular_expression/src/parser/mod.rs index 5bd7ccd6b9574..9791433d74762 100644 --- a/crates/oxc_regular_expression/src/parser/mod.rs +++ b/crates/oxc_regular_expression/src/parser/mod.rs @@ -111,10 +111,21 @@ mod test { (r"\1()", default()), (r"\1()", with_unicode_mode()), (r"(?..)(?..)", default()), - // TODO: ES2025 Duplicate named capturing groups + // ES2025 --- + // TODO: Duplicate named capturing groups // (r"(?..)|(?..)", default()), // (r"(?[0-9]{4})-[0-9]{2}|[0-9]{2}-(?[0-9]{4})", default()), // (r"(?:(?x)|(?y))\k", default()), + // Modifiers + (r"(?:.)", default()), + (r"(?s:.)", default()), + (r"(?ism:.)", default()), + (r"(?-s:.)", default()), + (r"(?-smi:.)", default()), + (r"(?s-im:.)", default()), + (r"(?si-m:.)", default()), + (r"(?im-s:.)", with_unicode_sets_mode()), + (r"(?ims-:.)", default()), ] { let res = Parser::new(&allocator, source_text, *options).parse(); if let Err(err) = res { @@ -161,6 +172,7 @@ mod test { ("a(?:", default()), ("(a", default()), ("(?", default()), + ("(?<", default()), (r"(?.)", default()), (r"(?.)", with_unicode_mode()), (r"(?<\>.)", default()), @@ -184,13 +196,26 @@ mod test { (r"[a--b&&c]", with_unicode_sets_mode()), (r"[\q{]", with_unicode_sets_mode()), (r"[\q{\a}]", with_unicode_sets_mode()), - // TODO: ES2025 Duplicate named capturing groups + // ES2025 --- + // TODO: Duplicate named capturing groups (r"(?..)|(?..)", default()), // This will be valid - // (r"(?|(?))", default()), // Nested, still invalid + // (r"(?|(?))", default()), // Nested, still invalid + // Modifiers + (r"(?a:.)", default()), + (r"(?-S:.)", default()), + (r"(?-:.)", default()), + (r"(?iM:.)", default()), + (r"(?imms:.)", default()), + (r"(?-sI:.)", default()), + (r"(?ii-s:.)", default()), + (r"(?i-msm:.)", default()), + (r"(?i", default()), + (r"(?i-", default()), + (r"(?i-s", default()), ] { assert!( Parser::new(&allocator, source_text, *options).parse().is_err(), - "{source_text} should fail to parse with {options:?}!" + "{source_text} should fail to parse with {options:?}, but passed!" ); } } @@ -234,11 +259,16 @@ mod test { (r"[[z-a]]", with_unicode_sets_mode(), true), (r"[[[[[^[[[[\q{ng}]]]]]]]]]", with_unicode_sets_mode(), true), (r"[^[[[[[[[[[[[[[[[[\q{ng}]]]]]]]]]]]]]]]]]", with_unicode_sets_mode(), true), + // ES2025 --- + // Modifiers + (r"(?ii:.)", default(), true), + (r"(?-ss:.)", default(), true), + (r"(?im-im:.)", default(), true), ] { assert_eq!( Parser::new(&allocator, source_text, *options).parse().is_err(), *is_err, - "{source_text} should early error with {options:?}!" + "{source_text} should fail with early error with {options:?}, but passed!" ); } } diff --git a/crates/oxc_regular_expression/src/parser/parser_impl.rs b/crates/oxc_regular_expression/src/parser/parser_impl.rs index a90559a2844d0..70dc633455d7b 100644 --- a/crates/oxc_regular_expression/src/parser/parser_impl.rs +++ b/crates/oxc_regular_expression/src/parser/parser_impl.rs @@ -304,7 +304,8 @@ impl<'a> Parser<'a> { // \ AtomEscape[?UnicodeMode, ?NamedCaptureGroups] // CharacterClass[?UnicodeMode, ?UnicodeSetsMode] // ( GroupSpecifier[?UnicodeMode][opt] Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) - // (?: Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) + // (? RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) + // (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) // ``` fn parse_atom(&mut self) -> Result>> { let span_start = self.reader.offset(); @@ -345,11 +346,6 @@ impl<'a> Parser<'a> { )))); } - // (?: Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) - if let Some(ignore_group) = self.parse_ignore_group()? { - return Ok(Some(ast::Term::IgnoreGroup(Box::new_in(ignore_group, self.allocator)))); - } - // ( GroupSpecifier[?UnicodeMode][opt] Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) // ( Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) if let Some(capturing_group) = self.parse_capturing_group()? { @@ -359,6 +355,13 @@ impl<'a> Parser<'a> { )))); } + // (?: Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) + // (? RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) + // (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) + if let Some(ignore_group) = self.parse_ignore_group()? { + return Ok(Some(ast::Term::IgnoreGroup(Box::new_in(ignore_group, self.allocator)))); + } + Ok(None) } @@ -369,7 +372,8 @@ impl<'a> Parser<'a> { // \ [lookahead = c] // CharacterClass[~UnicodeMode, ~UnicodeSetsMode] // ( GroupSpecifier[~UnicodeMode][opt] Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) - // (?: Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) + // (? RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) + // (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) // InvalidBracedQuantifier // ExtendedPatternCharacter // ``` @@ -414,13 +418,8 @@ impl<'a> Parser<'a> { )))); } - // (?: Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) - if let Some(ignore_group) = self.parse_ignore_group()? { - return Ok(Some(ast::Term::IgnoreGroup(Box::new_in(ignore_group, self.allocator)))); - } - - // ( GroupSpecifier[~UnicodeMode][opt] Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) - // ( Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) + // ( GroupSpecifier[?UnicodeMode][opt] Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) + // ( Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) if let Some(capturing_group) = self.parse_capturing_group()? { return Ok(Some(ast::Term::CapturingGroup(Box::new_in( capturing_group, @@ -428,6 +427,13 @@ impl<'a> Parser<'a> { )))); } + // (?: Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) + // (? RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) + // (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) + if let Some(ignore_group) = self.parse_ignore_group()? { + return Ok(Some(ast::Term::IgnoreGroup(Box::new_in(ignore_group, self.allocator)))); + } + // InvalidBracedQuantifier let span_start = self.reader.offset(); if self.consume_quantifier()?.is_some() { @@ -1491,6 +1497,7 @@ impl<'a> Parser<'a> { // ``` fn parse_capturing_group(&mut self) -> Result>> { let span_start = self.reader.offset(); + let checkpoint = self.reader.checkpoint(); if self.reader.eat('(') { let mut group_name = None; @@ -1498,10 +1505,11 @@ impl<'a> Parser<'a> { // GroupSpecifier is optional, but if it exists, `?` is also required if self.reader.eat('?') { let Some(name) = self.consume_group_name()? else { - return Err(diagnostics::missing_capturing_group_name( - self.span_factory.create(span_start, self.reader.offset()), - )); + // If GroupSpecifier is not found, fallback to `parse_ignore_group()` branch + self.reader.rewind(checkpoint); + return Ok(None); }; + group_name = Some(name); } @@ -1525,30 +1533,132 @@ impl<'a> Parser<'a> { // ``` // (?: Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) + // (? RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) + // (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) // ``` fn parse_ignore_group(&mut self) -> Result>> { let span_start = self.reader.offset(); - if self.reader.eat3('(', '?', ':') { - let disjunction = self.parse_disjunction()?; + if self.reader.eat2('(', '?') { + let modifiers = if self.reader.peek().filter(|&cp| cp == ':' as u32).is_some() { + None + } else { + self.parse_modifiers()? + }; - if !self.reader.eat(')') { - return Err(diagnostics::unterminated_pattern( + if self.reader.eat(':') { + let disjunction = self.parse_disjunction()?; + + if !self.reader.eat(')') { + return Err(diagnostics::unterminated_pattern( + self.span_factory.create(span_start, self.reader.offset()), + "ignore group", + )); + } + + return Ok(Some(ast::IgnoreGroup { + span: self.span_factory.create(span_start, self.reader.offset()), + modifiers, + body: disjunction, + })); + } + } + + Ok(None) + } + + // ``` + // RegularExpressionModifiers :: + // [empty] + // RegularExpressionModifiers RegularExpressionModifier + // + // RegularExpressionModifier :: one of + // `i` `m` `s` + // ``` + fn parse_modifiers(&mut self) -> Result> { + let span_start = self.reader.offset(); + + // Currently only `[i, m, s]` are supported + let mut enabling_flags = [0, 0, 0]; + let mut disabling_flags = [0, 0, 0]; + + // Enabling + while self.reader.peek().filter(|&cp| cp == ':' as u32 || cp == '-' as u32).is_none() { + if self.reader.eat('i') { + enabling_flags[0] += 1; + continue; + } + if self.reader.eat('m') { + enabling_flags[1] += 1; + continue; + } + if self.reader.eat('s') { + enabling_flags[2] += 1; + continue; + } + + return Err(diagnostics::unknown_modifiers( + self.span_factory.create(span_start, self.reader.offset()), + )); + } + + // Disabling + if self.reader.eat('-') { + while self.reader.peek().filter(|&cp| cp == ':' as u32).is_none() { + if self.reader.eat('i') { + disabling_flags[0] += 1; + continue; + } + if self.reader.eat('m') { + disabling_flags[1] += 1; + continue; + } + if self.reader.eat('s') { + disabling_flags[2] += 1; + continue; + } + + return Err(diagnostics::unknown_modifiers( self.span_factory.create(span_start, self.reader.offset()), - "ignore group", )); } + } - return Ok(Some(ast::IgnoreGroup { - span: self.span_factory.create(span_start, self.reader.offset()), - // TODO: Stage3 ModifierFlags - enabling_modifiers: None, - disabling_modifiers: None, - body: disjunction, - })); + let (enabling_iter, disabling_iter) = (enabling_flags.iter(), disabling_flags.iter()); + + // [SS:EE] Atom :: (? RegularExpressionModifiers : Disjunction ) + // It is a Syntax Error if the source text matched by RegularExpressionModifiers contains the same code point more than once. + // [SS:EE] Atom :: (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction ) + // It is a Syntax Error if the source text matched by the first RegularExpressionModifiers contains the same code point more than once. + // It is a Syntax Error if the source text matched by the second RegularExpressionModifiers contains the same code point more than once. + // It is a Syntax Error if any code point in the source text matched by the first RegularExpressionModifiers is also contained in the source text matched by the second RegularExpressionModifiers. + let flags_iter = enabling_iter.clone().zip(disabling_iter.clone()); + if flags_iter.clone().any(|flags| !matches!(flags, (0 | 1, 0) | (0, 1))) { + return Err(diagnostics::invalid_modifiers( + self.span_factory.create(span_start, self.reader.offset()), + )); + } + // NOTE: Spec is not yet fixed and merged, so these may change: + // https://github.com/tc39/ecma262/pull/3221#pullrequestreview-2341169958 + if flags_iter.clone().all(|flags| matches!(flags, (0, 0))) { + return Err(diagnostics::invalid_modifiers( + self.span_factory.create(span_start, self.reader.offset()), + )); } - Ok(None) + Ok(Some(ast::Modifiers { + span: self.span_factory.create(span_start, self.reader.offset()), + enabling: enabling_iter.clone().any(|f| *f == 1).then(|| ast::Modifier { + ignore_case: enabling_flags[0] == 1, + multiline: enabling_flags[1] == 1, + sticky: enabling_flags[2] == 1, + }), + disabling: disabling_iter.clone().any(|f| *f == 1).then(|| ast::Modifier { + ignore_case: disabling_flags[0] == 1, + multiline: disabling_flags[1] == 1, + sticky: disabling_flags[2] == 1, + }), + })) } // --- diff --git a/tasks/coverage/snapshots/codegen_test262.snap b/tasks/coverage/snapshots/codegen_test262.snap index 5d80288b71b7b..0c37e88ab5264 100644 --- a/tasks/coverage/snapshots/codegen_test262.snap +++ b/tasks/coverage/snapshots/codegen_test262.snap @@ -1,5 +1,5 @@ commit: d62fa93c codegen_test262 Summary: -AST Parsed : 43776/43776 (100.00%) -Positive Passed: 43776/43776 (100.00%) +AST Parsed : 43914/43914 (100.00%) +Positive Passed: 43914/43914 (100.00%) diff --git a/tasks/coverage/snapshots/minifier_test262.snap b/tasks/coverage/snapshots/minifier_test262.snap index a82428638101c..e2070405dd47b 100644 --- a/tasks/coverage/snapshots/minifier_test262.snap +++ b/tasks/coverage/snapshots/minifier_test262.snap @@ -1,5 +1,5 @@ commit: d62fa93c minifier_test262 Summary: -AST Parsed : 43776/43776 (100.00%) -Positive Passed: 43776/43776 (100.00%) +AST Parsed : 43914/43914 (100.00%) +Positive Passed: 43914/43914 (100.00%) diff --git a/tasks/coverage/snapshots/parser_test262.snap b/tasks/coverage/snapshots/parser_test262.snap index 9b2d57a1f1abb..ce5dfb4b7e78a 100644 --- a/tasks/coverage/snapshots/parser_test262.snap +++ b/tasks/coverage/snapshots/parser_test262.snap @@ -1,9 +1,9 @@ commit: d62fa93c parser_test262 Summary: -AST Parsed : 43776/43776 (100.00%) -Positive Passed: 43775/43776 (100.00%) -Negative Passed: 4237/4239 (99.95%) +AST Parsed : 43914/43914 (100.00%) +Positive Passed: 43913/43914 (100.00%) +Negative Passed: 4320/4322 (99.95%) Expect Syntax Error: tasks/coverage/test262/test/language/import/import-attributes/json-invalid.js Expect Syntax Error: tasks/coverage/test262/test/language/import/import-attributes/json-named-bindings.js Expect to Parse: tasks/coverage/test262/test/built-ins/String/prototype/split/separator-regexp.js @@ -20611,6 +20611,412 @@ Expect to Parse: tasks/coverage/test262/test/built-ins/String/prototype/split/se 30 │ / ╰──── + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-add-remove-i.js:20:4] + 19 │ + 20 │ /(?i-i:a)//*{ global-modifiers }*/; + · ─── + ╰──── + + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-add-remove-m.js:20:4] + 19 │ + 20 │ /(?m-m:a)//*{ global-modifiers }*/; + · ─── + ╰──── + + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-add-remove-multi-duplicate.js:20:4] + 19 │ + 20 │ /(?ims-m:a)//*{ global-modifiers }*/; + · ───── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-add-remove-s-escape.js:20:4] + 19 │ + 20 │ /(?\u{0073}-s:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-add-remove-s.js:20:4] + 19 │ + 20 │ /(?s-s:a)//*{ global-modifiers }*/; + · ─── + ╰──── + + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-both-empty.js:20:4] + 19 │ + 20 │ /(?-:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-code-point-repeat-i-1.js:20:4] + 19 │ + 20 │ /(?-ii:a)//*{ global-modifiers }*/; + · ─── + ╰──── + + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-code-point-repeat-i-2.js:20:4] + 19 │ + 20 │ /(?-imsi:a)//*{ global-modifiers }*/; + · ───── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-no-colon-1.js:19:4] + 18 │ + 19 │ /(?ms-i)/; + · ──── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-no-colon-2.js:19:4] + 18 │ + 19 │ /(?-s)/; + · ── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-no-colon-3.js:19:4] + 18 │ + 19 │ /(?i-)/; + · ── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-arbitrary.js:20:4] + 19 │ + 20 │ /(?-1:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-combining-i.js:20:4] + 19 │ + 20 │ /(?-iͥ:a)//*{ global-modifiers }*/; + · ── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-combining-m.js:20:4] + 19 │ + 20 │ /(?-mͫ:a)//*{ global-modifiers }*/; + · ── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-combining-s.js:20:4] + 19 │ + 20 │ /(?-s̀:a)//*{ global-modifiers }*/; + · ── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-d.js:20:4] + 19 │ + 20 │ /(?-d:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-g.js:20:4] + 19 │ + 20 │ /(?-g:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-non-display-1.js:20:4] + 19 │ + 20 │ /(?-s:a)//*{ global-modifiers }*/; + · ── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-non-display-2.js:20:4] + 19 │ + 20 │ /(?-s‎:a)//*{ global-modifiers }*/; + · ── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-non-flag.js:20:4] + 19 │ + 20 │ /(?-Q:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-u.js:20:4] + 19 │ + 20 │ /(?-u:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-uppercase-I.js:20:4] + 19 │ + 20 │ /(?-I:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-y.js:20:4] + 19 │ + 20 │ /(?-y:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-zwj.js:20:4] + 19 │ + 20 │ /(?-s‍:a)//*{ global-modifiers }*/; + · ── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-zwnbsp.js:20:4] + 19 │ + 20 │ /(?-s:a)//*{ global-modifiers }*/; + · ── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-other-code-point-zwnj.js:20:4] + 19 │ + 20 │ /(?-s‌:a)//*{ global-modifiers }*/; + · ── + ╰──── + + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-add-remove-i.js:20:4] + 19 │ + 20 │ /(?i-i:a)//*{ global-modifiers }*/; + · ─── + ╰──── + + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-add-remove-m.js:20:4] + 19 │ + 20 │ /(?m-m:a)//*{ global-modifiers }*/; + · ─── + ╰──── + + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-add-remove-multi-duplicate.js:20:4] + 19 │ + 20 │ /(?m-ims:a)//*{ global-modifiers }*/; + · ───── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-add-remove-s-escape.js:20:4] + 19 │ + 20 │ /(?s-\u{0073}:a)//*{ global-modifiers }*/; + · ── + ╰──── + + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-add-remove-s.js:20:4] + 19 │ + 20 │ /(?s-s:a)//*{ global-modifiers }*/; + · ─── + ╰──── + + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-code-point-repeat-i-1.js:20:4] + 19 │ + 20 │ /(?ii-:a)//*{ global-modifiers }*/; + · ─── + ╰──── + + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-code-point-repeat-i-2.js:20:4] + 19 │ + 20 │ /(?imsi-:a)//*{ global-modifiers }*/; + · ───── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-arbitrary.js:20:4] + 19 │ + 20 │ /(?1-:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-combining-i.js:20:4] + 19 │ + 20 │ /(?iͥ-:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-combining-m.js:20:4] + 19 │ + 20 │ /(?mͫ-:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-combining-s.js:20:4] + 19 │ + 20 │ /(?s̀-:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-d.js:20:4] + 19 │ + 20 │ /(?d-:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-g.js:20:4] + 19 │ + 20 │ /(?g-:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-non-display-1.js:20:4] + 19 │ + 20 │ /(?s-:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-non-display-2.js:20:4] + 19 │ + 20 │ /(?s‎-:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-non-flag.js:20:4] + 19 │ + 20 │ /(?Q-:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-u.js:20:4] + 19 │ + 20 │ /(?u-:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-uppercase-I.js:20:4] + 19 │ + 20 │ /(?I-:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-y.js:20:4] + 19 │ + 20 │ /(?y-:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-zwj.js:20:4] + 19 │ + 20 │ /(?s‍-:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-zwnbsp.js:20:4] + 19 │ + 20 │ /(?s-:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-other-code-point-zwnj.js:20:4] + 19 │ + 20 │ /(?s‌-:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-should-not-case-fold-i.js:20:4] + 19 │ + 20 │ /(?I-:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-should-not-case-fold-m.js:20:4] + 19 │ + 20 │ /(?M-:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-should-not-case-fold-s.js:20:4] + 19 │ + 20 │ /(?S-:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-should-not-unicode-case-fold-i.js:20:4] + 19 │ + 20 │ /(?İ-:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-reverse-should-not-unicode-case-fold-s.js:20:4] + 19 │ + 20 │ /(?ſ-:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-should-not-case-fold-i.js:20:4] + 19 │ + 20 │ /(?-I:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-should-not-case-fold-m.js:20:4] + 19 │ + 20 │ /(?-M:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-should-not-case-fold-s.js:20:4] + 19 │ + 20 │ /(?-S:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-should-not-unicode-case-fold-i.js:20:4] + 19 │ + 20 │ /(?-İ:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-arithmetic-modifiers-should-not-unicode-case-fold-s.js:20:4] + 19 │ + 20 │ /(?-ſ:a)//*{ global-modifiers }*/; + · ─ + ╰──── + × Unexpected flag G in regular expression literal ╭─[test262/test/language/literals/regexp/early-err-bad-flag.js:19:4] 18 │ @@ -20633,6 +21039,181 @@ Expect to Parse: tasks/coverage/test262/test/built-ins/String/prototype/split/se ╰──── help: Try insert a semicolon here + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-code-point-repeat-i-1.js:20:4] + 19 │ + 20 │ /(?ii:a)//*{ global-modifiers }*/; + · ── + ╰──── + + × Invalid regular expression: Invalid modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-code-point-repeat-i-2.js:20:4] + 19 │ + 20 │ /(?imsi:a)//*{ global-modifiers }*/; + · ──── + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-arbitrary.js:20:4] + 19 │ + 20 │ /(?1:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-combining-i.js:20:4] + 19 │ + 20 │ /(?iͥ:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-combining-m.js:20:4] + 19 │ + 20 │ /(?mͫ:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-combining-s.js:20:4] + 19 │ + 20 │ /(?s̀:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-d.js:20:4] + 19 │ + 20 │ /(?d:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-g.js:20:4] + 19 │ + 20 │ /(?g:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-non-display-1.js:20:4] + 19 │ + 20 │ /(?s:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-non-display-2.js:20:4] + 19 │ + 20 │ /(?s‎:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-non-flag.js:20:4] + 19 │ + 20 │ /(?Q:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-u.js:20:4] + 19 │ + 20 │ /(?u:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-uppercase-I.js:20:4] + 19 │ + 20 │ /(?I:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-y.js:20:4] + 19 │ + 20 │ /(?y:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-zwj.js:20:4] + 19 │ + 20 │ /(?s‍:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-zwnbsp.js:20:4] + 19 │ + 20 │ /(?s:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-other-code-point-zwnj.js:20:4] + 19 │ + 20 │ /(?s‌:a)//*{ global-modifiers }*/; + · ─ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-should-not-case-fold-i.js:20:4] + 19 │ + 20 │ /(?I:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-should-not-case-fold-m.js:20:4] + 19 │ + 20 │ /(?M:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-should-not-case-fold-s.js:20:4] + 19 │ + 20 │ /(?S:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-should-not-unicode-case-fold-i.js:20:4] + 19 │ + 20 │ /(?İ:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-should-not-unicode-case-fold-s.js:20:4] + 19 │ + 20 │ /(?ſ:a)//*{ global-modifiers }*/; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-should-not-unicode-escape-i.js:20:4] + 19 │ + 20 │ /(?\u0069:a)/u /* i */; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-should-not-unicode-escape-m.js:20:4] + 19 │ + 20 │ /(?\u006D:a)/u /* m */; + · ▲ + ╰──── + + × Invalid regular expression: Unknown modifiers + ╭─[test262/test/language/literals/regexp/early-err-modifiers-should-not-unicode-escape-s.js:20:4] + 19 │ + 20 │ /(?\u0073:a)/u /* s */; + · ▲ + ╰──── + × Invalid regular expression: Invalid braced quantifier ╭─[test262/test/language/literals/regexp/early-err-pattern.js:18:2] 17 │ diff --git a/tasks/coverage/snapshots/parser_typescript.snap b/tasks/coverage/snapshots/parser_typescript.snap index 7d54ace1ace7c..cd4dbec7cb8c7 100644 --- a/tasks/coverage/snapshots/parser_typescript.snap +++ b/tasks/coverage/snapshots/parser_typescript.snap @@ -10936,11 +10936,11 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private 4 │ // Pattern modifiers ╰──── - × Invalid regular expression: Missing capturing group name - ╭─[typescript/tests/cases/compiler/regularExpressionScanning.ts:5:3] + × Invalid regular expression: Unknown modifiers + ╭─[typescript/tests/cases/compiler/regularExpressionScanning.ts:5:5] 4 │ // Pattern modifiers 5 │ /(?med-ium:bar)/, - · ── + · ─ 6 │ // Capturing groups ╰──── @@ -11167,11 +11167,11 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private · ───── ╰──── - × Invalid regular expression: Missing capturing group name - ╭─[typescript/tests/cases/compiler/regularExpressionWithNonBMPFlags.ts:7:31] + × Invalid regular expression: Unknown modifiers + ╭─[typescript/tests/cases/compiler/regularExpressionWithNonBMPFlags.ts:7:33] 6 │ // See https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols 7 │ const 𝘳𝘦𝘨𝘦𝘹 = /(?𝘴𝘪-𝘮:^𝘧𝘰𝘰.)/𝘨𝘮𝘶; - · ── + · ▲ ╰──── × Expected a semicolon or an implicit semicolon after a statement, but found none diff --git a/tasks/coverage/snapshots/semantic_test262.snap b/tasks/coverage/snapshots/semantic_test262.snap index 39d3e10bb0563..9a4c34053ec69 100644 --- a/tasks/coverage/snapshots/semantic_test262.snap +++ b/tasks/coverage/snapshots/semantic_test262.snap @@ -1,8 +1,8 @@ commit: d62fa93c semantic_test262 Summary: -AST Parsed : 43776/43776 (100.00%) -Positive Passed: 43575/43776 (99.54%) +AST Parsed : 43914/43914 (100.00%) +Positive Passed: 43713/43914 (99.54%) tasks/coverage/test262/test/annexB/language/function-code/if-decl-else-decl-a-func-block-scoping.js semantic error: Symbol scope ID mismatch for "f": after transform: SymbolId(3): ScopeId(4294967294) diff --git a/tasks/coverage/snapshots/transformer_test262.snap b/tasks/coverage/snapshots/transformer_test262.snap index 25b9a34ce76b3..dcb36dcfaf82f 100644 --- a/tasks/coverage/snapshots/transformer_test262.snap +++ b/tasks/coverage/snapshots/transformer_test262.snap @@ -1,5 +1,5 @@ commit: d62fa93c transformer_test262 Summary: -AST Parsed : 43776/43776 (100.00%) -Positive Passed: 43776/43776 (100.00%) +AST Parsed : 43914/43914 (100.00%) +Positive Passed: 43914/43914 (100.00%) diff --git a/tasks/coverage/src/test262/mod.rs b/tasks/coverage/src/test262/mod.rs index d5af7db1f427a..12c1f5d5565a3 100644 --- a/tasks/coverage/src/test262/mod.rs +++ b/tasks/coverage/src/test262/mod.rs @@ -107,8 +107,6 @@ impl Case for Test262Case { [ // ES2025 https://github.com/tc39/proposal-duplicate-named-capturing-groups "regexp-duplicate-named-groups", - // stage 3 https://github.com/tc39/proposal-regexp-modifiers - "regexp-modifiers", // stage 3 https://github.com/tc39/proposal-source-phase-imports "source-phase-imports", ]