Revert as many changes to selectors from upstream as possible (#31365)

This is part of the preparation for splitting stylo into a separate
crate. We have made various changes to selectors includings:

 1. Bumping the rust edition
 2. Fixing typos and updating links

In addition to reverting those changes, this PR pulls in some changes to
selectors we seem to have missed in the process of updates.
This commit is contained in:
Martin Robinson 2024-02-20 07:57:10 +01:00 committed by GitHub
parent b993518892
commit 2fa76916d3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 58 additions and 69 deletions

View file

@ -9,7 +9,6 @@ readme = "README.md"
keywords = ["css", "selectors"] keywords = ["css", "selectors"]
license = "MPL-2.0" license = "MPL-2.0"
build = "build.rs" build = "build.rs"
edition = "2018"
[lib] [lib]
name = "selectors" name = "selectors"

View file

@ -1,11 +1,13 @@
rust-selectors rust-selectors
============== ==============
* [Documentation](https://docs.rs/selectors) * [![Build Status](https://travis-ci.com/servo/rust-selectors.svg?branch=master)](
https://travis-ci.com/servo/rust-selectors)
* [Documentation](https://docs.rs/selectors/)
* [crates.io](https://crates.io/crates/selectors) * [crates.io](https://crates.io/crates/selectors)
CSS Selectors library for Rust. CSS Selectors library for Rust.
Includes parsing and serialization of selectors, Includes parsing and serilization of selectors,
as well as matching against a generic tree of elements. as well as matching against a generic tree of elements.
Pseudo-elements and most pseudo-classes are generic as well. Pseudo-elements and most pseudo-classes are generic as well.

View file

@ -5,19 +5,16 @@
use crate::parser::SelectorImpl; use crate::parser::SelectorImpl;
use cssparser::ToCss; use cssparser::ToCss;
use std::fmt; use std::fmt;
#[cfg(feature = "shmem")]
use to_shmem_derive::ToShmem;
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq, ToShmem)]
#[cfg_attr(feature = "shmem", derive(ToShmem))] #[shmem(no_bounds)]
#[cfg_attr(feature = "shmem", shmem(no_bounds))]
pub struct AttrSelectorWithOptionalNamespace<Impl: SelectorImpl> { pub struct AttrSelectorWithOptionalNamespace<Impl: SelectorImpl> {
#[cfg_attr(feature = "shmem", shmem(field_bound))] #[shmem(field_bound)]
pub namespace: Option<NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>>, pub namespace: Option<NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>>,
#[cfg_attr(feature = "shmem", shmem(field_bound))] #[shmem(field_bound)]
pub local_name: Impl::LocalName, pub local_name: Impl::LocalName,
pub local_name_lower: Impl::LocalName, pub local_name_lower: Impl::LocalName,
#[cfg_attr(feature = "shmem", shmem(field_bound))] #[shmem(field_bound)]
pub operation: ParsedAttrSelectorOperation<Impl::AttrValue>, pub operation: ParsedAttrSelectorOperation<Impl::AttrValue>,
} }
@ -30,8 +27,7 @@ impl<Impl: SelectorImpl> AttrSelectorWithOptionalNamespace<Impl> {
} }
} }
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq, ToShmem)]
#[cfg_attr(feature = "shmem", derive(ToShmem))]
pub enum NamespaceConstraint<NamespaceUrl> { pub enum NamespaceConstraint<NamespaceUrl> {
Any, Any,
@ -39,8 +35,7 @@ pub enum NamespaceConstraint<NamespaceUrl> {
Specific(NamespaceUrl), Specific(NamespaceUrl),
} }
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq, ToShmem)]
#[cfg_attr(feature = "shmem", derive(ToShmem))]
pub enum ParsedAttrSelectorOperation<AttrValue> { pub enum ParsedAttrSelectorOperation<AttrValue> {
Exists, Exists,
WithValue { WithValue {
@ -80,8 +75,7 @@ impl<AttrValue> AttrSelectorOperation<AttrValue> {
} }
} }
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy, Eq, PartialEq, ToShmem)]
#[cfg_attr(feature = "shmem", derive(ToShmem))]
pub enum AttrSelectorOperator { pub enum AttrSelectorOperator {
Equal, Equal,
Includes, Includes,
@ -146,8 +140,7 @@ impl AttrSelectorOperator {
/// The definition of whitespace per CSS Selectors Level 3 § 4. /// The definition of whitespace per CSS Selectors Level 3 § 4.
pub static SELECTOR_WHITESPACE: &[char] = &[' ', '\t', '\n', '\r', '\x0C']; pub static SELECTOR_WHITESPACE: &[char] = &[' ', '\t', '\n', '\r', '\x0C'];
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
#[cfg_attr(feature = "shmem", derive(ToShmem))]
pub enum ParsedCaseSensitivity { pub enum ParsedCaseSensitivity {
/// 's' was specified. /// 's' was specified.
ExplicitCaseSensitive, ExplicitCaseSensitive,

View file

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
extern crate phf_codegen;
use std::env; use std::env;
use std::fs::File; use std::fs::File;
use std::io::{BufWriter, Write}; use std::io::{BufWriter, Write};

View file

@ -19,16 +19,12 @@
use crate::parser::{Combinator, Component, RelativeSelector, Selector, SelectorImpl}; use crate::parser::{Combinator, Component, RelativeSelector, Selector, SelectorImpl};
use crate::sink::Push; use crate::sink::Push;
use bitflags::bitflags;
use derive_more::{Add, AddAssign};
use servo_arc::{Arc, HeaderWithLength, ThinArc}; use servo_arc::{Arc, HeaderWithLength, ThinArc};
use smallvec::{self, SmallVec}; use smallvec::{self, SmallVec};
use std::cmp; use std::cmp;
use std::iter; use std::iter;
use std::ptr; use std::ptr;
use std::slice; use std::slice;
#[cfg(feature = "shmem")]
use to_shmem_derive::ToShmem;
/// Top-level SelectorBuilder struct. This should be stack-allocated by the /// Top-level SelectorBuilder struct. This should be stack-allocated by the
/// consumer and never moved (because it contains a lot of inline data that /// consumer and never moved (because it contains a lot of inline data that
@ -182,8 +178,7 @@ fn split_from_end<T>(s: &[T], at: usize) -> (&[T], &[T]) {
bitflags! { bitflags! {
/// Flags that indicate at which point of parsing a selector are we. /// Flags that indicate at which point of parsing a selector are we.
#[derive(Default)] #[derive(Default, ToShmem)]
#[cfg_attr(feature = "shmem", derive(ToShmem))]
pub (crate) struct SelectorFlags : u8 { pub (crate) struct SelectorFlags : u8 {
const HAS_PSEUDO = 1 << 0; const HAS_PSEUDO = 1 << 0;
const HAS_SLOTTED = 1 << 1; const HAS_SLOTTED = 1 << 1;
@ -192,8 +187,7 @@ bitflags! {
} }
} }
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
#[cfg_attr(feature = "shmem", derive(ToShmem))]
pub struct SpecificityAndFlags { pub struct SpecificityAndFlags {
/// There are two free bits here, since we use ten bits for each specificity /// There are two free bits here, since we use ten bits for each specificity
/// kind (id, class, element). /// kind (id, class, element).

View file

@ -5,6 +5,25 @@
// Make |cargo bench| work. // Make |cargo bench| work.
#![cfg_attr(feature = "bench", feature(test))] #![cfg_attr(feature = "bench", feature(test))]
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate cssparser;
#[macro_use]
extern crate debug_unreachable;
#[macro_use]
extern crate derive_more;
extern crate fxhash;
#[macro_use]
extern crate log;
extern crate phf;
extern crate precomputed_hash;
extern crate servo_arc;
extern crate smallvec;
extern crate to_shmem;
#[macro_use]
extern crate to_shmem_derive;
pub mod attr; pub mod attr;
pub mod bloom; pub mod bloom;
mod builder; mod builder;

View file

@ -15,8 +15,6 @@ use crate::parser::{
}; };
use crate::tree::Element; use crate::tree::Element;
use bitflags::bitflags; use bitflags::bitflags;
use debug_unreachable::debug_unreachable;
use log::debug;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::iter; use std::iter;

View file

@ -14,21 +14,17 @@ use crate::sink::Push;
use crate::visitor::SelectorListKind; use crate::visitor::SelectorListKind;
pub use crate::visitor::SelectorVisitor; pub use crate::visitor::SelectorVisitor;
use bitflags::bitflags; use bitflags::bitflags;
use cssparser::{match_ignore_ascii_case, parse_nth}; use cssparser::parse_nth;
use cssparser::{BasicParseError, BasicParseErrorKind, ParseError, ParseErrorKind}; use cssparser::{BasicParseError, BasicParseErrorKind, ParseError, ParseErrorKind};
use cssparser::{CowRcStr, Delimiter, SourceLocation}; use cssparser::{CowRcStr, Delimiter, SourceLocation};
use cssparser::{Parser as CssParser, ToCss, Token}; use cssparser::{Parser as CssParser, ToCss, Token};
use debug_unreachable::debug_unreachable;
use precomputed_hash::PrecomputedHash; use precomputed_hash::PrecomputedHash;
use servo_arc::{HeaderWithLength, ThinArc, UniqueArc}; use servo_arc::{HeaderWithLength, ThinArc, UniqueArc};
use size_of_test::size_of_test;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::borrow::{Borrow, Cow}; use std::borrow::{Borrow, Cow};
use std::fmt::{self, Debug}; use std::fmt::{self, Debug};
use std::iter::Rev; use std::iter::Rev;
use std::slice; use std::slice;
#[cfg(feature = "shmem")]
use to_shmem_derive::ToShmem;
/// A trait that represents a pseudo-element. /// A trait that represents a pseudo-element.
pub trait PseudoElement: Sized + ToCss { pub trait PseudoElement: Sized + ToCss {
@ -168,8 +164,6 @@ impl SelectorParsingState {
pub type SelectorParseError<'i> = ParseError<'i, SelectorParseErrorKind<'i>>; pub type SelectorParseError<'i> = ParseError<'i, SelectorParseErrorKind<'i>>;
size_of_test!(SelectorParseError, 48);
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum SelectorParseErrorKind<'i> { pub enum SelectorParseErrorKind<'i> {
NoQualifiedNameInAttributeSelector(Token<'i>), NoQualifiedNameInAttributeSelector(Token<'i>),
@ -194,8 +188,6 @@ pub enum SelectorParseErrorKind<'i> {
ClassNeedsIdent(Token<'i>), ClassNeedsIdent(Token<'i>),
} }
size_of_test!(SelectorParseErrorKind, 40);
macro_rules! with_all_bounds { macro_rules! with_all_bounds {
( (
[ $( $InSelector: tt )* ] [ $( $InSelector: tt )* ]
@ -298,9 +290,6 @@ pub trait Parser<'i> {
true true
} }
/// Parses non-tree-structural pseudo-classes. Tree structural pseudo-classes,
/// like `:first-child`, are built into this library.
///
/// This function can return an "Err" pseudo-element in order to support CSS2.1 /// This function can return an "Err" pseudo-element in order to support CSS2.1
/// pseudo-elements. /// pseudo-elements.
fn parse_non_ts_pseudo_class( fn parse_non_ts_pseudo_class(
@ -363,11 +352,10 @@ pub trait Parser<'i> {
} }
} }
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq, ToShmem)]
#[cfg_attr(feature = "shmem", derive(ToShmem))] #[shmem(no_bounds)]
#[cfg_attr(feature = "shmem", shmem(no_bounds))]
pub struct SelectorList<Impl: SelectorImpl>( pub struct SelectorList<Impl: SelectorImpl>(
#[cfg_attr(feature = "shmem", shmem(field_bound))] pub SmallVec<[Selector<Impl>; 1]>, #[shmem(field_bound)] pub SmallVec<[Selector<Impl>; 1]>,
); );
/// Whether or not we're using forgiving parsing mode /// Whether or not we're using forgiving parsing mode
@ -643,12 +631,10 @@ pub fn namespace_empty_string<Impl: SelectorImpl>() -> Impl::NamespaceUrl {
/// ///
/// This reordering doesn't change the semantics of selector matching, and we /// This reordering doesn't change the semantics of selector matching, and we
/// handle it in to_css to make it invisible to serialization. /// handle it in to_css to make it invisible to serialization.
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq, ToShmem)]
#[cfg_attr(feature = "shmem", derive(ToShmem))] #[shmem(no_bounds)]
#[cfg_attr(feature = "shmem", shmem(no_bounds))]
pub struct Selector<Impl: SelectorImpl>( pub struct Selector<Impl: SelectorImpl>(
#[cfg_attr(feature = "shmem", shmem(field_bound))] #[shmem(field_bound)] ThinArc<SpecificityAndFlags, Component<Impl>>,
ThinArc<SpecificityAndFlags, Component<Impl>>,
); );
impl<Impl: SelectorImpl> Selector<Impl> { impl<Impl: SelectorImpl> Selector<Impl> {
@ -1299,8 +1285,7 @@ impl<'a, Impl: SelectorImpl> Iterator for AncestorIter<'a, Impl> {
} }
} }
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
#[cfg_attr(feature = "shmem", derive(ToShmem))]
pub enum Combinator { pub enum Combinator {
Child, // > Child, // >
Descendant, // space Descendant, // space
@ -1541,10 +1526,10 @@ impl CombinatorComposition {
for combinator in CombinatorIter::new(inner_selector.iter_skip_relative_selector_anchor()) { for combinator in CombinatorIter::new(inner_selector.iter_skip_relative_selector_anchor()) {
match combinator { match combinator {
Combinator::Descendant | Combinator::Child => { Combinator::Descendant | Combinator::Child => {
result.insert(CombinatorComposition::DESCENDANTS); result.insert(Self::DESCENDANTS);
}, },
Combinator::NextSibling | Combinator::LaterSibling => { Combinator::NextSibling | Combinator::LaterSibling => {
result.insert(CombinatorComposition::SIBLINGS); result.insert(Self::SIBLINGS);
}, },
Combinator::Part | Combinator::PseudoElement | Combinator::SlotAssignment => { Combinator::Part | Combinator::PseudoElement | Combinator::SlotAssignment => {
continue continue
@ -1637,17 +1622,16 @@ impl<Impl: SelectorImpl> RelativeSelector<Impl> {
/// optimal packing and cache performance, see [1]. /// optimal packing and cache performance, see [1].
/// ///
/// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1357973 /// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1357973
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq, ToShmem)]
#[cfg_attr(feature = "shmem", derive(ToShmem))] #[shmem(no_bounds)]
#[cfg_attr(feature = "shmem", shmem(no_bounds))]
pub enum Component<Impl: SelectorImpl> { pub enum Component<Impl: SelectorImpl> {
LocalName(LocalName<Impl>), LocalName(LocalName<Impl>),
ID(#[cfg_attr(feature = "shmem", shmem(field_bound))] Impl::Identifier), ID(#[shmem(field_bound)] Impl::Identifier),
Class(#[cfg_attr(feature = "shmem", shmem(field_bound))] Impl::Identifier), Class(#[shmem(field_bound)] Impl::Identifier),
AttributeInNoNamespaceExists { AttributeInNoNamespaceExists {
#[cfg_attr(feature = "shmem", shmem(field_bound))] #[shmem(field_bound)]
local_name: Impl::LocalName, local_name: Impl::LocalName,
local_name_lower: Impl::LocalName, local_name_lower: Impl::LocalName,
}, },
@ -1655,7 +1639,7 @@ pub enum Component<Impl: SelectorImpl> {
AttributeInNoNamespace { AttributeInNoNamespace {
local_name: Impl::LocalName, local_name: Impl::LocalName,
operator: AttrSelectorOperator, operator: AttrSelectorOperator,
#[cfg_attr(feature = "shmem", shmem(field_bound))] #[shmem(field_bound)]
value: Impl::AttrValue, value: Impl::AttrValue,
case_sensitivity: ParsedCaseSensitivity, case_sensitivity: ParsedCaseSensitivity,
}, },
@ -1680,7 +1664,7 @@ pub enum Component<Impl: SelectorImpl> {
ParentSelector, ParentSelector,
Nth(NthSelectorData), Nth(NthSelectorData),
NthOf(NthOfSelectorData<Impl>), NthOf(NthOfSelectorData<Impl>),
NonTSPseudoClass(#[cfg_attr(feature = "shmem", shmem(field_bound))] Impl::NonTSPseudoClass), NonTSPseudoClass(#[shmem(field_bound)] Impl::NonTSPseudoClass),
/// The ::slotted() pseudo-element: /// The ::slotted() pseudo-element:
/// ///
/// https://drafts.csswg.org/css-scoping/#slotted-pseudo /// https://drafts.csswg.org/css-scoping/#slotted-pseudo
@ -1695,7 +1679,7 @@ pub enum Component<Impl: SelectorImpl> {
Slotted(Selector<Impl>), Slotted(Selector<Impl>),
/// The `::part` pseudo-element. /// The `::part` pseudo-element.
/// https://drafts.csswg.org/css-shadow-parts/#part /// https://drafts.csswg.org/css-shadow-parts/#part
Part(#[cfg_attr(feature = "shmem", shmem(field_bound))] Box<[Impl::Identifier]>), Part(#[shmem(field_bound)] Box<[Impl::Identifier]>),
/// The `:host` pseudo-class: /// The `:host` pseudo-class:
/// ///
/// https://drafts.csswg.org/css-scoping/#host-selector /// https://drafts.csswg.org/css-scoping/#host-selector
@ -1726,7 +1710,7 @@ pub enum Component<Impl: SelectorImpl> {
/// Same comment as above re. the argument. /// Same comment as above re. the argument.
Has(Box<[RelativeSelector<Impl>]>), Has(Box<[RelativeSelector<Impl>]>),
/// An implementation-dependent pseudo-element selector. /// An implementation-dependent pseudo-element selector.
PseudoElement(#[cfg_attr(feature = "shmem", shmem(field_bound))] Impl::PseudoElement), PseudoElement(#[shmem(field_bound)] Impl::PseudoElement),
Combinator(Combinator), Combinator(Combinator),
@ -1886,11 +1870,10 @@ impl<Impl: SelectorImpl> Component<Impl> {
} }
} }
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq, ToShmem)]
#[cfg_attr(feature = "shmem", derive(ToShmem))] #[shmem(no_bounds)]
#[cfg_attr(feature = "shmem", shmem(no_bounds))]
pub struct LocalName<Impl: SelectorImpl> { pub struct LocalName<Impl: SelectorImpl> {
#[cfg_attr(feature = "shmem", shmem(field_bound))] #[shmem(field_bound)]
pub name: Impl::LocalName, pub name: Impl::LocalName,
pub lower_name: Impl::LocalName, pub lower_name: Impl::LocalName,
} }

View file

@ -8,7 +8,6 @@
use crate::attr::NamespaceConstraint; use crate::attr::NamespaceConstraint;
use crate::parser::{Combinator, Component, Selector, SelectorImpl}; use crate::parser::{Combinator, Component, Selector, SelectorImpl};
use bitflags::bitflags;
/// A trait to visit selector properties. /// A trait to visit selector properties.
/// ///