diff --git a/Cargo.toml b/Cargo.toml index 6fb94f56..d0fe7e29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,12 +34,12 @@ name = "bench" [dependencies] bitflags = "2.0.0" cfg-if = "1.0.0" -cssparser = "0.27.2" +cssparser = "0.28.1" encoding_rs = "0.8.13" lazycell = "1.3.0" lazy_static = "1.3.0" memchr = "2.1.2" -selectors = "0.22.0" +selectors = "0.23.0" thiserror = "1.0.2" hashbrown = "0.13.1" mime = "0.3.16" diff --git a/src/selectors_vm/ast.rs b/src/selectors_vm/ast.rs index 685954b6..60aec1f1 100644 --- a/src/selectors_vm/ast.rs +++ b/src/selectors_vm/ast.rs @@ -123,15 +123,15 @@ impl From<&Component> for Condition { #[inline] fn from(component: &Component) -> Self { match component { - Component::LocalName(n) => Self::OnTagName(OnTagNameExpr::LocalName(n.name.clone())), + Component::LocalName(n) => Self::OnTagName(OnTagNameExpr::LocalName(n.name.0.clone())), Component::ExplicitUniversalType | Component::ExplicitAnyNamespace => { Self::OnTagName(OnTagNameExpr::ExplicitAny) } Component::ExplicitNoNamespace => Self::OnTagName(OnTagNameExpr::Unmatchable), - Component::ID(id) => Self::OnAttributes(OnAttributesExpr::Id(id.to_owned())), - Component::Class(c) => Self::OnAttributes(OnAttributesExpr::Class(c.to_owned())), + Component::ID(id) => Self::OnAttributes(OnAttributesExpr::Id(id.0.to_owned())), + Component::Class(c) => Self::OnAttributes(OnAttributesExpr::Class(c.0.to_owned())), Component::AttributeInNoNamespaceExists { local_name, .. } => { - Self::OnAttributes(OnAttributesExpr::AttributeExists(local_name.to_owned())) + Self::OnAttributes(OnAttributesExpr::AttributeExists(local_name.0.to_owned())) } &Component::AttributeInNoNamespace { ref local_name, @@ -145,8 +145,8 @@ impl From<&Component> for Condition { } else { Self::OnAttributes(OnAttributesExpr::AttributeComparisonExpr( AttributeComparisonExpr::new( - local_name.to_owned(), - value.to_owned(), + local_name.0.to_owned(), + value.0.to_owned(), case_sensitivity, operator, ), @@ -303,8 +303,9 @@ where "Unsupported selector components should be filtered out by the parser." ), }, - Component::Negation(c) => { - c.iter().for_each(|c| predicate.add_component(c, true)); + Component::Negation(ss) => { + ss.iter() + .for_each(|s| s.iter().for_each(|c| predicate.add_component(c, true))); } _ => predicate.add_component(component, false), } @@ -819,10 +820,9 @@ mod tests { r#"div[foo~"bar"]"#, SelectorError::UnexpectedTokenInAttribute, ); - assert_err(":not(:not(p))", SelectorError::NestedNegation); assert_err("svg|img", SelectorError::NamespacedSelector); assert_err(".foo()", SelectorError::InvalidClassName); - assert_err(":not()", SelectorError::EmptyNegation); + assert_err(":not()", SelectorError::EmptySelector); assert_err("div + span", SelectorError::UnsupportedCombinator('+')); assert_err("div ~ span", SelectorError::UnsupportedCombinator('~')); } diff --git a/src/selectors_vm/error.rs b/src/selectors_vm/error.rs index c99b27b1..9e4762b2 100644 --- a/src/selectors_vm/error.rs +++ b/src/selectors_vm/error.rs @@ -45,10 +45,6 @@ pub enum SelectorError { #[error("Invalid or unescaped class name in selector.")] InvalidClassName, - /// An empty negation in the selector. - #[error("Empty negation in selector.")] - EmptyNegation, - /// Unsupported combinator in the selector. #[error("Unsupported combinator `{0}` in selector.")] UnsupportedCombinator(char), @@ -80,7 +76,7 @@ impl From> for SelectorError { SelectorParseErrorKind::EmptySelector => Self::EmptySelector, SelectorParseErrorKind::DanglingCombinator => Self::DanglingCombinator, SelectorParseErrorKind::UnsupportedPseudoClassOrElement(_) - | SelectorParseErrorKind::PseudoElementInComplexSelector + | SelectorParseErrorKind::InvalidPseudoElementInsideWhere | SelectorParseErrorKind::NonPseudoElementAfterSlotted | SelectorParseErrorKind::InvalidPseudoElementAfterSlotted | SelectorParseErrorKind::PseudoElementExpectedColon(_) @@ -88,15 +84,12 @@ impl From> for SelectorError { | SelectorParseErrorKind::NoIdentForPseudo(_) // NOTE: according to the parser code this error occures only during // the parsing of vendor-specific pseudo-classes. - | SelectorParseErrorKind::NonCompoundSelector - // NOTE: according to the parser code this error occures only during - // the parsing of the :slotted() pseudo-class. - | SelectorParseErrorKind::NonSimpleSelectorInNegation => { + | SelectorParseErrorKind::NonCompoundSelector => { Self::UnsupportedPseudoClassOrElement } - // NOTE: this is currently the only case in the parser code - // that triggers this error. - SelectorParseErrorKind::UnexpectedIdent(_) => Self::NestedNegation, + // NOTE: there are currently no cases in the parser code + // that trigger this error. + SelectorParseErrorKind::UnexpectedIdent(_) => unreachable!(), SelectorParseErrorKind::ExpectedNamespace(_) => Self::NamespacedSelector, SelectorParseErrorKind::ExplicitNamespaceUnexpectedToken(_) => { Self::UnexpectedToken @@ -108,7 +101,6 @@ impl From> for SelectorError { Self::UnexpectedTokenInAttribute } SelectorParseErrorKind::ClassNeedsIdent(_) => Self::InvalidClassName, - SelectorParseErrorKind::EmptyNegation => Self::EmptyNegation, SelectorParseErrorKind::InvalidState => panic!("invalid state"), }, } diff --git a/src/selectors_vm/parser.rs b/src/selectors_vm/parser.rs index bba71feb..50f555c0 100644 --- a/src/selectors_vm/parser.rs +++ b/src/selectors_vm/parser.rs @@ -11,16 +11,32 @@ use std::str::FromStr; #[derive(Debug, Clone, Eq, PartialEq)] pub struct SelectorImplDescriptor; +#[derive(Clone, Default, Eq, PartialEq)] +pub struct CssString(pub String); + +impl<'a> From<&'a str> for CssString { + fn from(value: &'a str) -> Self { + Self(value.to_string()) + } +} + +impl ToCss for CssString { + fn to_css(&self, dest: &mut W) -> fmt::Result + where + W: fmt::Write, + { + write!(dest, "{}", self.0) + } +} + impl SelectorImpl for SelectorImplDescriptor { - type AttrValue = String; - type Identifier = String; - type ClassName = String; - type PartName = String; - type LocalName = String; - type NamespacePrefix = String; + type AttrValue = CssString; + type Identifier = CssString; + type LocalName = CssString; + type NamespacePrefix = CssString; type NamespaceUrl = Namespace; type BorrowedNamespaceUrl = Namespace; - type BorrowedLocalName = String; + type BorrowedLocalName = CssString; type NonTSPseudoClass = NonTSPseudoClassStub; type PseudoElement = PseudoElementStub; @@ -57,11 +73,6 @@ impl NonTSPseudoClass for NonTSPseudoClassStub { #[allow(clippy::uninhabited_references)] match *self {} } - - fn has_zero_specificity(&self) -> bool { - #[allow(clippy::uninhabited_references)] - match *self {} - } } impl ToCss for NonTSPseudoClassStub { @@ -110,14 +121,15 @@ impl SelectorsParser { | Component::AttributeInNoNamespaceExists { .. } | Component::AttributeInNoNamespace { .. } => Ok(()), - Component::Negation(components) => { - components.iter().try_for_each(Self::validate_component) - } + Component::Negation(selectors) => selectors + .iter() + .try_for_each(|s| s.iter().try_for_each(Self::validate_component)), // Unsupported Component::Empty | Component::Part(_) | Component::Host(_) + | Component::Is(_) | Component::LastChild | Component::LastOfType | Component::NthLastChild(_, _) @@ -126,6 +138,7 @@ impl SelectorsParser { | Component::OnlyOfType | Component::Root | Component::Scope + | Component::Where(_) | Component::PseudoElement(_) | Component::NonTSPseudoClass(_) | Component::Slotted(_) => Err(SelectorError::UnsupportedPseudoClassOrElement),