Skip to content

Commit

Permalink
style: Move the code to parse a list of compound selectors.
Browse files Browse the repository at this point in the history
I'll need this for ::slotted().
  • Loading branch information
emilio committed Dec 9, 2017
1 parent 051a715 commit b1f25a2
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 11 deletions.
28 changes: 28 additions & 0 deletions components/selectors/parser.rs
Expand Up @@ -55,6 +55,7 @@ pub enum SelectorParseErrorKind<'i> {
EmptySelector,
DanglingCombinator,
NonSimpleSelectorInNegation,
NonCompoundSelector,
UnexpectedTokenInAttributeSelector(Token<'i>),
PseudoElementExpectedColon(Token<'i>),
PseudoElementExpectedIdent(Token<'i>),
Expand Down Expand Up @@ -209,6 +210,33 @@ impl<Impl: SelectorImpl> SelectorList<Impl> {
}
}

/// Parse a comma separated list of compound selectors.
pub fn parse_compound_selector_list<'i, 't, P, Impl>(
parser: &P,
input: &mut CssParser<'i, 't>,
) -> Result<Box<[Selector<Impl>]>, ParseError<'i, P::Error>>
where
P: Parser<'i, Impl=Impl>,
Impl: SelectorImpl,
{
let location = input.current_source_location();
let selectors = input.parse_comma_separated(|input| {
Selector::parse(parser, input)
})?;

// Ensure they're actually all compound selectors.
if selectors
.iter()
.flat_map(|x| x.iter_raw_match_order())
.any(|s| s.is_combinator()) {
return Err(location.new_custom_error(
SelectorParseErrorKind::NonCompoundSelector
))
}

Ok(selectors.into_boxed_slice())
}

/// Ancestor hashes for the bloom filter. We precompute these and store them
/// inline with selectors to optimize cache performance during matching.
/// This matters a lot.
Expand Down
18 changes: 7 additions & 11 deletions components/style/gecko/selector_parser.rs
Expand Up @@ -11,7 +11,7 @@ use gecko_bindings::structs::RawServoSelectorList;
use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
use selector_parser::{Direction, SelectorParser, PseudoElementCascadeType};
use selectors::SelectorList;
use selectors::parser::{Selector, SelectorMethods, SelectorParseErrorKind};
use selectors::parser::{self as selector_parser, Selector, SelectorMethods, SelectorParseErrorKind};
use selectors::visitor::SelectorVisitor;
use std::fmt;
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
Expand Down Expand Up @@ -399,16 +399,12 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
NonTSPseudoClass::Dir(Box::new(direction))
},
"-moz-any" => {
let selectors = parser.parse_comma_separated(|input| {
Selector::parse(self, input)
})?;
// Selectors inside `:-moz-any` may not include combinators.
if selectors.iter().flat_map(|x| x.iter_raw_match_order()).any(|s| s.is_combinator()) {
return Err(parser.new_custom_error(
SelectorParseErrorKind::UnexpectedIdent("-moz-any".into())
))
}
NonTSPseudoClass::MozAny(selectors.into_boxed_slice())
NonTSPseudoClass::MozAny(
selector_parser::parse_compound_selector_list(
self,
parser,
)?
)
}
_ => return Err(parser.new_custom_error(
SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name.clone())
Expand Down

0 comments on commit b1f25a2

Please sign in to comment.