diff --git a/src/component.rs b/src/component.rs index f43e38c..4c6a4b8 100644 --- a/src/component.rs +++ b/src/component.rs @@ -7,6 +7,7 @@ use crate::parser::Options; use crate::parser::Part; use crate::parser::PartModifier; use crate::parser::PartType; +use crate::parser::RegexSyntax; use crate::parser::FULL_WILDCARD_REGEXP_VALUE; use crate::regexp::RegExp; use crate::tokenizer::is_valid_name_codepoint; @@ -42,7 +43,15 @@ impl Component { let (regexp_string, name_list) = generate_regular_expression_and_name_list(&part_list, &options); let flags = if options.ignore_case { "ui" } else { "u" }; - let regexp = R::parse(®exp_string, flags).map_err(Error::RegExp); + let mut regexp = + R::parse(®exp_string, flags, false).map_err(Error::RegExp); + if regexp.is_ok() && R::syntax() == RegexSyntax::EcmaScript { + for part in part_list.iter() { + if part.kind == PartType::Regexp { + regexp = R::parse(®exp_string, flags, true).map_err(Error::RegExp); + } + } + } let pattern_string = generate_pattern_string(&part_list, &options); let matcher = generate_matcher::(&part_list, &options, flags); Ok(Component { @@ -350,7 +359,8 @@ fn generate_matcher( part_list => { let (regexp_string, _) = generate_regular_expression_and_name_list(part_list, options); - let regexp = R::parse(®exp_string, flags).map_err(Error::RegExp); + let regexp = + R::parse(®exp_string, flags, false).map_err(Error::RegExp); InnerMatcher::RegExp { regexp } } }; diff --git a/src/quirks.rs b/src/quirks.rs index a08a02f..cb166ef 100644 --- a/src/quirks.rs +++ b/src/quirks.rs @@ -175,12 +175,20 @@ impl RegExp for EcmaRegexp { RegexSyntax::EcmaScript } - fn parse(pattern: &str, flags: &str) -> Result { - Ok(EcmaRegexp(pattern.to_string(), flags.to_string())) + fn parse(pattern: &str, flags: &str, force_eval: bool) -> Result { + if force_eval { + let regexp = regex::Regex::parse(pattern, flags, false); + match regexp { + Ok(r) => Ok(EcmaRegexp(r.to_string(), flags.to_string())), + _ => Err(()), + } + } else { + Ok(EcmaRegexp(pattern.to_string(), flags.to_string())) + } } fn matches<'a>(&self, text: &'a str) -> Option>> { - let regexp = regex::Regex::parse(&self.0, &self.1).ok()?; + let regexp = regex::Regex::parse(&self.0, &self.1, false).ok()?; regexp.matches(text) } } @@ -191,7 +199,8 @@ pub fn parse_pattern( options: UrlPatternOptions, ) -> Result { let pattern = - crate::UrlPattern::::parse_internal(init, false, options)?; + crate::UrlPattern::::parse_internal(init, true, options)?; + let urlpattern = UrlPattern { has_regexp_groups: pattern.has_regexp_groups(), protocol: pattern.protocol.into(), diff --git a/src/regexp.rs b/src/regexp.rs index 78bba14..9c3f1dc 100644 --- a/src/regexp.rs +++ b/src/regexp.rs @@ -5,7 +5,7 @@ pub trait RegExp: Sized { /// Generates a regexp pattern for the given string. If the pattern is /// invalid, the parse function should return an error. - fn parse(pattern: &str, flags: &str) -> Result; + fn parse(pattern: &str, flags: &str, force_eval: bool) -> Result; /// Matches the given text against the regular expression and returns the list /// of captures. The matches are returned in the order they appear in the @@ -22,7 +22,7 @@ impl RegExp for regex::Regex { RegexSyntax::Rust } - fn parse(pattern: &str, flags: &str) -> Result { + fn parse(pattern: &str, flags: &str, _force_eval: bool) -> Result { regex::Regex::new(&format!("(?{flags}){pattern}")).map_err(|_| ()) }