perf(regular_expression): advance validated Unicode escapes directly (#28514)

Advance over decoded Unicode escape units in one step while retaining
source offsets from the final unit span.

AI-assisted (Codex).
This commit is contained in:
Boshen authored and GitHub committed 2026-10-30 17:17:35 +08:00
1 parent 82e1982d1a
commit 9b6b7bf98f
3 files changed
+35 -8

No files matched your search

@@ -2168,18 +2168,13 @@ impl<'a> PatternParser<'a> {
let span_start = self.reader.offset();
match decode(self.reader.remaining_code_points(), unicode_mode) {
UnicodeEscape::Value { code_point, length } => {
for _ in 0..length {
self.reader.advance();
}
self.reader.advance_by(length);
Ok(Some(code_point))
}
UnicodeEscape::Overflow { digits } => {
self.reader.advance(); // u
self.reader.advance(); // {
self.reader.advance_by(2); // u{
let digits_start = self.reader.offset();
for _ in 0..digits {
self.reader.advance();
}
self.reader.advance_by(digits);
Err(diagnostics::too_large_number_digits(
self.span_factory.create(digits_start, self.reader.offset()),
"hex",
@@ -96,6 +96,15 @@ impl<'a> Reader<'a> {
}
}
/// Advance over units whose presence the caller has already checked.
pub fn advance_by(&mut self, count: usize) {
if count != 0 {
let index = self.index + count;
self.offset = self.units[index - 1].span.end;
self.index = index;
}
}
fn peek_nth(&self, n: usize) -> Option<u32> {
let nth = self.index + n;
self.units.get(nth).map(|cp| cp.value)
@@ -0,0 +1,23 @@
use oxc_allocator::Allocator;
use oxc_regular_expression::{ConstructorParser, Options, ast::Term};
#[test]
fn decoded_unicode_escapes_keep_source_spans() {
let allocator = Allocator::default();
let source = r#""\\u{\x30\x30\x36\x31}b""#;
let parsed = ConstructorParser::new(&allocator, source, Some(r#""u""#), Options::default())
.parse()
.unwrap();
let terms = &parsed.body.body[0].body;
assert_eq!(terms.len(), 2);
let Term::Character(first) = &terms[0] else {
panic!("expected decoded character");
};
let Term::Character(second) = &terms[1] else {
panic!("expected trailing character");
};
assert_eq!(first.value, u32::from('a'));
assert_eq!(first.span.source_text(source), r"\\u{\x30\x30\x36\x31}");
assert_eq!(second.value, u32::from('b'));
assert_eq!(second.span.source_text(source), "b");
}