mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
refactor(transformer): RegExp transform do not take ownership of Pattern then reallocate it (#5492)
Previously `try_parse_pattern` took ownership of an existing pattern and then reallocated it back into arena, even if it wasn't changed. Rust's borrow-checker makes it quite hard to avoid this. Only way I could find is to move some of the logic out of `try_parse_pattern`.
This commit is contained in:
parent
64db1b4c40
commit
dd198231dc
1 changed files with 34 additions and 31 deletions
|
|
@ -43,10 +43,8 @@
|
||||||
mod options;
|
mod options;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
pub use options::RegExpOptions;
|
pub use options::RegExpOptions;
|
||||||
use oxc_allocator::Box;
|
|
||||||
use oxc_allocator::Vec;
|
use oxc_allocator::Vec;
|
||||||
use oxc_ast::ast::*;
|
use oxc_ast::ast::*;
|
||||||
use oxc_regular_expression::ast::{
|
use oxc_regular_expression::ast::{
|
||||||
|
|
@ -119,7 +117,8 @@ impl<'a> Traverse<'a> for RegExp<'a> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let has_unsupported_flags = regexp.regex.flags.intersects(self.unsupported_flags);
|
let flags = regexp.regex.flags;
|
||||||
|
let has_unsupported_flags = flags.intersects(self.unsupported_flags);
|
||||||
if !has_unsupported_flags {
|
if !has_unsupported_flags {
|
||||||
if !self.some_unsupported_patterns {
|
if !self.some_unsupported_patterns {
|
||||||
// This RegExp has no unsupported flags, and there are no patterns which may need transforming,
|
// This RegExp has no unsupported flags, and there are no patterns which may need transforming,
|
||||||
|
|
@ -127,18 +126,26 @@ impl<'a> Traverse<'a> for RegExp<'a> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match try_parse_pattern(regexp, ctx) {
|
let span = regexp.span;
|
||||||
Ok(pattern) => {
|
let pattern = match &mut regexp.regex.pattern {
|
||||||
let is_unsupported = self.has_unsupported_regular_expression_pattern(&pattern);
|
RegExpPattern::Raw(raw) => {
|
||||||
regexp.regex.pattern = RegExpPattern::Pattern(pattern);
|
if let Some(pattern) = try_parse_pattern(raw, span, flags, ctx) {
|
||||||
if !is_unsupported {
|
regexp.regex.pattern = RegExpPattern::Pattern(ctx.alloc(pattern));
|
||||||
|
let RegExpPattern::Pattern(pattern) = ®exp.regex.pattern else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
pattern
|
||||||
|
} else {
|
||||||
|
regexp.regex.pattern = RegExpPattern::Invalid(raw);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
RegExpPattern::Invalid(_) => return,
|
||||||
regexp.regex.pattern = RegExpPattern::Invalid(err);
|
RegExpPattern::Pattern(pattern) => &**pattern,
|
||||||
return;
|
};
|
||||||
}
|
|
||||||
|
if !self.has_unsupported_regular_expression_pattern(pattern) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,26 +227,22 @@ fn has_unicode_property_escape_character_class(character_class: &CharacterClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_parse_pattern<'a>(
|
fn try_parse_pattern<'a>(
|
||||||
literal: &mut RegExpLiteral<'a>,
|
raw: &'a str,
|
||||||
|
span: Span,
|
||||||
|
flags: RegExpFlags,
|
||||||
ctx: &mut TraverseCtx<'a>,
|
ctx: &mut TraverseCtx<'a>,
|
||||||
) -> Result<Box<'a, Pattern<'a>>, &'a str> {
|
) -> Option<Pattern<'a>> {
|
||||||
// Take the ownership of the pattern
|
use oxc_regular_expression::{ParserOptions, PatternParser};
|
||||||
let regexp_pattern = mem::replace(&mut literal.regex.pattern, RegExpPattern::Raw(""));
|
|
||||||
|
|
||||||
match regexp_pattern {
|
let options = ParserOptions {
|
||||||
RegExpPattern::Raw(raw) => {
|
span_offset: span.start + 1, // exclude `/`
|
||||||
use oxc_regular_expression::{ParserOptions, PatternParser};
|
unicode_mode: flags.contains(RegExpFlags::U) || flags.contains(RegExpFlags::V),
|
||||||
let options = ParserOptions {
|
unicode_sets_mode: flags.contains(RegExpFlags::V),
|
||||||
span_offset: literal.span.start + 1, // exclude `/`
|
};
|
||||||
unicode_mode: literal.regex.flags.contains(RegExpFlags::U)
|
|
||||||
|| literal.regex.flags.contains(RegExpFlags::V),
|
let ret = PatternParser::new(ctx.ast.allocator, raw, options).parse();
|
||||||
unicode_sets_mode: literal.regex.flags.contains(RegExpFlags::V),
|
match ret {
|
||||||
};
|
Ok(pattern) => Some(pattern),
|
||||||
PatternParser::new(ctx.ast.allocator, raw, options)
|
Err(_) => None,
|
||||||
.parse()
|
|
||||||
.map_or_else(|_| Err(raw), |p| Ok(ctx.alloc(p)))
|
|
||||||
}
|
|
||||||
RegExpPattern::Pattern(pattern) => Ok(pattern),
|
|
||||||
RegExpPattern::Invalid(raw) => Err(raw),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue