mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
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:
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");
|
||||
}
|
||||
Reference in new issue
Block a user