diff --git a/Cargo.toml b/Cargo.toml index 78d23242..d1c6820d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,8 @@ encoding_rs = "0.8.13" memchr = "2.1.2" hashbrown = "0.15.0" mime = "0.3.16" -selectors = "0.24" +# HACK: Using commit between 0.24 and 0.25, allows us to get rid of phf 0.8. +selectors = {git = "https://github.com/servo/stylo.git", rev = "767bc8bc11424d107cd58c7c2d3a1695e387e4ea"} thiserror = "2.0" [dev-dependencies] diff --git a/src/selectors_vm/attribute_matcher.rs b/src/selectors_vm/attribute_matcher.rs index b759c3e1..6ed0adfc 100644 --- a/src/selectors_vm/attribute_matcher.rs +++ b/src/selectors_vm/attribute_matcher.rs @@ -3,7 +3,7 @@ use crate::base::Bytes; use crate::html::Namespace; use crate::parser::{AttributeBuffer, AttributeOutline}; use memchr::{memchr, memchr2}; -use selectors::attr::CaseSensitivity; +use selectors::attr::{CaseSensitivity, ParsedCaseSensitivity}; use std::cell::OnceCell; static ID_ATTR: Bytes<'static> = Bytes::from_static("id"); @@ -14,6 +14,27 @@ const fn is_attr_whitespace(b: u8) -> bool { b == b' ' || b == b'\n' || b == b'\r' || b == b'\t' || b == b'\x0c' } +#[inline] +pub fn to_unconditional( + parsed: ParsedCaseSensitivity, + is_html_element_in_html_document: bool, +) -> CaseSensitivity { + match parsed { + ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument + if is_html_element_in_html_document => + { + CaseSensitivity::AsciiCaseInsensitive + } + ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => { + CaseSensitivity::CaseSensitive + } + ParsedCaseSensitivity::CaseSensitive | ParsedCaseSensitivity::ExplicitCaseSensitive => { + CaseSensitivity::CaseSensitive + } + ParsedCaseSensitivity::AsciiCaseInsensitive => CaseSensitivity::AsciiCaseInsensitive, + } +} + type MemoizedAttrValue<'i> = OnceCell>>; pub(crate) struct AttributeMatcher<'i> { @@ -99,9 +120,7 @@ impl<'i> AttributeMatcher<'i> { #[inline] pub fn attr_eq(&self, operand: &AttrExprOperands) -> bool { self.value_matches(&operand.name, |actual_value| { - operand - .case_sensitivity - .to_unconditional(self.is_html_element) + to_unconditional(operand.case_sensitivity, self.is_html_element) .eq(&actual_value, &operand.value) }) } @@ -109,9 +128,7 @@ impl<'i> AttributeMatcher<'i> { #[inline] pub fn matches_splitted_by_whitespace(&self, operand: &AttrExprOperands) -> bool { self.value_matches(&operand.name, |actual_value| { - let case_sensitivity = operand - .case_sensitivity - .to_unconditional(self.is_html_element); + let case_sensitivity = to_unconditional(operand.case_sensitivity, self.is_html_element); actual_value .split(|&b| is_attr_whitespace(b)) @@ -122,9 +139,7 @@ impl<'i> AttributeMatcher<'i> { #[inline] pub fn has_attr_with_prefix(&self, operand: &AttrExprOperands) -> bool { self.value_matches(&operand.name, |actual_value| { - let case_sensitivity = operand - .case_sensitivity - .to_unconditional(self.is_html_element); + let case_sensitivity = to_unconditional(operand.case_sensitivity, self.is_html_element); let prefix_len = operand.value.len(); @@ -136,9 +151,7 @@ impl<'i> AttributeMatcher<'i> { #[inline] pub fn has_dash_matching_attr(&self, operand: &AttrExprOperands) -> bool { self.value_matches(&operand.name, |actual_value| { - let case_sensitivity = operand - .case_sensitivity - .to_unconditional(self.is_html_element); + let case_sensitivity = to_unconditional(operand.case_sensitivity, self.is_html_element); if case_sensitivity.eq(&actual_value, &operand.value) { return true; @@ -154,9 +167,7 @@ impl<'i> AttributeMatcher<'i> { #[inline] pub fn has_attr_with_suffix(&self, operand: &AttrExprOperands) -> bool { self.value_matches(&operand.name, |actual_value| { - let case_sensitivity = operand - .case_sensitivity - .to_unconditional(self.is_html_element); + let case_sensitivity = to_unconditional(operand.case_sensitivity, self.is_html_element); let suffix_len = operand.value.len(); let value_len = actual_value.len(); @@ -169,9 +180,7 @@ impl<'i> AttributeMatcher<'i> { #[inline] pub fn has_attr_with_substring(&self, operand: &AttrExprOperands) -> bool { self.value_matches(&operand.name, |actual_value| { - let case_sensitivity = operand - .case_sensitivity - .to_unconditional(self.is_html_element); + let case_sensitivity = to_unconditional(operand.case_sensitivity, self.is_html_element); let Some((&first_byte, rest)) = operand.value.split_first() else { return false; diff --git a/src/selectors_vm/parser.rs b/src/selectors_vm/parser.rs index 3b2421df..c6b25bb1 100644 --- a/src/selectors_vm/parser.rs +++ b/src/selectors_vm/parser.rs @@ -38,7 +38,7 @@ impl SelectorImpl for SelectorImplDescriptor { type NonTSPseudoClass = NonTSPseudoClassStub; type PseudoElement = PseudoElementStub; - type ExtraMatchingData = (); + type ExtraMatchingData<'a> = std::marker::PhantomData<&'a ()>; } #[derive(PartialEq, Eq, Clone, Debug, Hash)] @@ -127,6 +127,7 @@ impl SelectorsParser { | Component::Part(_) | Component::Host(_) | Component::Is(_) + | Component::Has(_) | Component::LastChild | Component::LastOfType | Component::NthLastChild(_, _)