From 182ab91570f0e4cc9fecaf6e91b3c1e6538f3c45 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Thu, 5 Sep 2024 12:47:34 +0000 Subject: [PATCH] perf(transformer): pre-calculate unsupported flags in RegExp transform (#5482) Calculate unsupported RegExp flags at start, to make checking flags on each RegExp during traversal cheaper (a single OR operation). i.e. do work once at the start, rather than over and over each time you find a `RegExp`. --- crates/oxc_transformer/src/regexp/mod.rs | 38 ++++++++++++++---------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/crates/oxc_transformer/src/regexp/mod.rs b/crates/oxc_transformer/src/regexp/mod.rs index 04ae98cfaef64..5078504411563 100644 --- a/crates/oxc_transformer/src/regexp/mod.rs +++ b/crates/oxc_transformer/src/regexp/mod.rs @@ -60,12 +60,31 @@ use crate::context::Ctx; pub struct RegExp<'a> { _ctx: Ctx<'a>, + unsupported_flags: RegExpFlags, options: RegExpOptions, } impl<'a> RegExp<'a> { pub fn new(options: RegExpOptions, ctx: Ctx<'a>) -> Self { - Self { _ctx: ctx, options } + // Get unsupported flags + let mut unsupported_flags = RegExpFlags::empty(); + if options.dot_all_flag { + unsupported_flags |= RegExpFlags::S; + } + if options.sticky_flag { + unsupported_flags |= RegExpFlags::Y; + } + if options.unicode_flag { + unsupported_flags |= RegExpFlags::U; + } + if options.match_indices { + unsupported_flags |= RegExpFlags::D; + } + if options.set_notation { + unsupported_flags |= RegExpFlags::V; + } + + Self { _ctx: ctx, unsupported_flags, options } } } @@ -79,9 +98,8 @@ impl<'a> Traverse<'a> for RegExp<'a> { return; }; - if !self.has_unsupported_regular_expression_flags(regexp.regex.flags) - && self.requires_pattern_analysis() - { + let has_unsupported_flags = regexp.regex.flags.intersects(self.unsupported_flags); + if !has_unsupported_flags && self.requires_pattern_analysis() { match try_parse_pattern(regexp, ctx) { Ok(pattern) => { let is_unsupported = self.has_unsupported_regular_expression_pattern(&pattern); @@ -141,18 +159,6 @@ impl<'a> RegExp<'a> { || self.options.look_behind_assertions } - /// Check if the regular expression contains any unsupported flags. - fn has_unsupported_regular_expression_flags(&self, flags: RegExpFlags) -> bool { - flags.iter().any(|f| match f { - RegExpFlags::S if self.options.dot_all_flag => true, - RegExpFlags::Y if self.options.sticky_flag => true, - RegExpFlags::U if self.options.unicode_flag => true, - RegExpFlags::D if self.options.match_indices => true, - RegExpFlags::V if self.options.set_notation => true, - _ => false, - }) - } - /// Check if the regular expression contains any unsupported syntax. /// /// Based on parsed regular expression pattern.