Introduce SelectorInner and use it for top-level matching.

MozReview-Commit-ID: DxG6USsPIkh
This commit is contained in:
Bobby Holley 2017-04-15 15:03:46 -07:00
parent 11745fb983
commit 9524c5cb57
9 changed files with 138 additions and 109 deletions

View file

@ -86,7 +86,7 @@ use net_traits::request::CorsSettings;
use ref_filter_map::ref_filter_map; use ref_filter_map::ref_filter_map;
use script_layout_interface::message::ReflowQueryType; use script_layout_interface::message::ReflowQueryType;
use script_thread::Runnable; use script_thread::Runnable;
use selectors::matching::{ElementSelectorFlags, StyleRelations, matches}; use selectors::matching::{ElementSelectorFlags, StyleRelations, matches_selector_list};
use selectors::matching::{HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS}; use selectors::matching::{HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS};
use selectors::parser::{AttrSelector, NamespaceConstraint}; use selectors::parser::{AttrSelector, NamespaceConstraint};
use servo_atoms::Atom; use servo_atoms::Atom;
@ -2050,7 +2050,7 @@ impl ElementMethods for Element {
match SelectorParser::parse_author_origin_no_namespace(&selectors) { match SelectorParser::parse_author_origin_no_namespace(&selectors) {
Err(()) => Err(Error::Syntax), Err(()) => Err(Error::Syntax),
Ok(selectors) => { Ok(selectors) => {
Ok(matches(&selectors.0, &Root::from_ref(self), None)) Ok(matches_selector_list(&selectors.0, &Root::from_ref(self), None))
} }
} }
} }
@ -2068,7 +2068,7 @@ impl ElementMethods for Element {
let root = self.upcast::<Node>(); let root = self.upcast::<Node>();
for element in root.inclusive_ancestors() { for element in root.inclusive_ancestors() {
if let Some(element) = Root::downcast::<Element>(element) { if let Some(element) = Root::downcast::<Element>(element) {
if matches(&selectors.0, &element, None) if matches_selector_list(&selectors.0, &element, None)
{ {
return Ok(Some(element)); return Ok(Some(element));
} }

View file

@ -68,7 +68,7 @@ use script_layout_interface::{LayoutElementType, LayoutNodeType, TrustedNodeAddr
use script_layout_interface::message::Msg; use script_layout_interface::message::Msg;
use script_traits::DocumentActivity; use script_traits::DocumentActivity;
use script_traits::UntrustedNodeAddress; use script_traits::UntrustedNodeAddress;
use selectors::matching::matches; use selectors::matching::matches_selector_list;
use selectors::parser::SelectorList; use selectors::parser::SelectorList;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::borrow::ToOwned; use std::borrow::ToOwned;
@ -332,7 +332,7 @@ impl<'a> Iterator for QuerySelectorIterator {
// (instead of passing `None`)? Probably. // (instead of passing `None`)? Probably.
self.iterator.by_ref().filter_map(|node| { self.iterator.by_ref().filter_map(|node| {
if let Some(element) = Root::downcast(node) { if let Some(element) = Root::downcast(node) {
if matches(selectors, &element, None) { if matches_selector_list(selectors, &element, None) {
return Some(Root::upcast(element)); return Some(Root::upcast(element));
} }
} }
@ -695,7 +695,7 @@ impl Node {
// Step 3. // Step 3.
Ok(selectors) => { Ok(selectors) => {
Ok(self.traverse_preorder().filter_map(Root::downcast).find(|element| { Ok(self.traverse_preorder().filter_map(Root::downcast).find(|element| {
matches(&selectors.0, element, None) matches_selector_list(&selectors.0, element, None)
})) }))
} }
} }

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use bloom::BloomFilter; use bloom::BloomFilter;
use parser::{CaseSensitivity, Combinator, ComplexSelector, LocalName}; use parser::{CaseSensitivity, Combinator, ComplexSelector, LocalName};
use parser::{SimpleSelector, Selector}; use parser::{SimpleSelector, Selector, SelectorInner};
use precomputed_hash::PrecomputedHash; use precomputed_hash::PrecomputedHash;
use std::borrow::Borrow; use std::borrow::Borrow;
use tree::Element; use tree::Element;
@ -92,7 +92,7 @@ impl ElementSelectorFlags {
} }
} }
pub fn matches<E>(selector_list: &[Selector<E::Impl>], pub fn matches_selector_list<E>(selector_list: &[Selector<E::Impl>],
element: &E, element: &E,
parent_bf: Option<&BloomFilter>) parent_bf: Option<&BloomFilter>)
-> bool -> bool
@ -100,7 +100,7 @@ pub fn matches<E>(selector_list: &[Selector<E::Impl>],
{ {
selector_list.iter().any(|selector| { selector_list.iter().any(|selector| {
selector.pseudo_element.is_none() && selector.pseudo_element.is_none() &&
matches_complex_selector(&*selector.complex_selector, matches_selector(&selector.inner,
element, element,
parent_bf, parent_bf,
&mut StyleRelations::empty(), &mut StyleRelations::empty(),
@ -108,11 +108,12 @@ pub fn matches<E>(selector_list: &[Selector<E::Impl>],
}) })
} }
fn may_match<E>(mut selector: &ComplexSelector<E::Impl>, fn may_match<E>(sel: &SelectorInner<E::Impl>,
bf: &BloomFilter) bf: &BloomFilter)
-> bool -> bool
where E: Element, where E: Element,
{ {
let mut selector = &*sel.complex;
// See if the bloom filter can exclude any of the descendant selectors, and // See if the bloom filter can exclude any of the descendant selectors, and
// reject if we can. // reject if we can.
loop { loop {
@ -159,7 +160,7 @@ fn may_match<E>(mut selector: &ComplexSelector<E::Impl>,
} }
/// Determines whether the given element matches the given complex selector. /// Determines whether the given element matches the given complex selector.
pub fn matches_complex_selector<E, F>(selector: &ComplexSelector<E::Impl>, pub fn matches_selector<E, F>(selector: &SelectorInner<E::Impl>,
element: &E, element: &E,
parent_bf: Option<&BloomFilter>, parent_bf: Option<&BloomFilter>,
relations: &mut StyleRelations, relations: &mut StyleRelations,
@ -168,19 +169,15 @@ pub fn matches_complex_selector<E, F>(selector: &ComplexSelector<E::Impl>,
where E: Element, where E: Element,
F: FnMut(&E, ElementSelectorFlags), F: FnMut(&E, ElementSelectorFlags),
{ {
// Use the bloom filter to fast-reject.
if let Some(filter) = parent_bf { if let Some(filter) = parent_bf {
if !may_match::<E>(selector, filter) { if !may_match::<E>(selector, filter) {
return false; return false;
} }
} }
match matches_complex_selector_internal(selector, // Match the selector.
element, matches_complex_selector(&selector.complex, element, relations, flags_setter)
relations,
flags_setter) {
SelectorMatchingResult::Matched => true,
_ => false
}
} }
/// A result of selector matching, includes 3 failure types, /// A result of selector matching, includes 3 failure types,
@ -233,6 +230,24 @@ enum SelectorMatchingResult {
NotMatchedGlobally, NotMatchedGlobally,
} }
/// Matches a complex selector.
pub fn matches_complex_selector<E, F>(selector: &ComplexSelector<E::Impl>,
element: &E,
relations: &mut StyleRelations,
flags_setter: &mut F)
-> bool
where E: Element,
F: FnMut(&E, ElementSelectorFlags),
{
match matches_complex_selector_internal(selector,
element,
relations,
flags_setter) {
SelectorMatchingResult::Matched => true,
_ => false
}
}
fn matches_complex_selector_internal<E, F>(selector: &ComplexSelector<E::Impl>, fn matches_complex_selector_internal<E, F>(selector: &ComplexSelector<E::Impl>,
element: &E, element: &E,
relations: &mut StyleRelations, relations: &mut StyleRelations,

View file

@ -121,9 +121,27 @@ impl<Impl: SelectorImpl> SelectorList<Impl> {
} }
} }
/// The cores parts of a selector used for matching. This exists to make that
/// information accessibly separately from the specificity and pseudo-element
/// information that lives on |Selector| proper. We may want to refactor things
/// and move that information elsewhere, at which point we could rename this
/// to |Selector|.
#[derive(PartialEq, Eq, Hash, Clone)]
pub struct SelectorInner<Impl: SelectorImpl> {
pub complex: Arc<ComplexSelector<Impl>>,
}
impl<Impl: SelectorImpl> SelectorInner<Impl> {
pub fn new(c: Arc<ComplexSelector<Impl>>) -> Self {
SelectorInner {
complex: c,
}
}
}
#[derive(PartialEq, Eq, Hash, Clone)] #[derive(PartialEq, Eq, Hash, Clone)]
pub struct Selector<Impl: SelectorImpl> { pub struct Selector<Impl: SelectorImpl> {
pub complex_selector: Arc<ComplexSelector<Impl>>, pub inner: SelectorInner<Impl>,
pub pseudo_element: Option<Impl::PseudoElement>, pub pseudo_element: Option<Impl::PseudoElement>,
pub specificity: u32, pub specificity: u32,
} }
@ -141,7 +159,7 @@ impl<Impl: SelectorImpl> SelectorMethods for Selector<Impl> {
fn visit<V>(&self, visitor: &mut V) -> bool fn visit<V>(&self, visitor: &mut V) -> bool
where V: SelectorVisitor<Impl = Impl>, where V: SelectorVisitor<Impl = Impl>,
{ {
self.complex_selector.visit(visitor) self.inner.complex.visit(visitor)
} }
} }
@ -321,6 +339,9 @@ impl<Impl: SelectorImpl> Debug for Selector<Impl> {
} }
} }
impl<Impl: SelectorImpl> Debug for SelectorInner<Impl> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.complex.to_css(f) }
}
impl<Impl: SelectorImpl> Debug for ComplexSelector<Impl> { impl<Impl: SelectorImpl> Debug for ComplexSelector<Impl> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.to_css(f) } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.to_css(f) }
} }
@ -353,7 +374,7 @@ impl<Impl: SelectorImpl> ToCss for SelectorList<Impl> {
impl<Impl: SelectorImpl> ToCss for Selector<Impl> { impl<Impl: SelectorImpl> ToCss for Selector<Impl> {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
self.complex_selector.to_css(dest)?; self.inner.complex.to_css(dest)?;
if let Some(ref pseudo) = self.pseudo_element { if let Some(ref pseudo) = self.pseudo_element {
pseudo.to_css(dest)?; pseudo.to_css(dest)?;
} }
@ -672,7 +693,7 @@ fn parse_selector<P, Impl>(parser: &P, input: &mut CssParser) -> Result<Selector
parse_complex_selector_and_pseudo_element(parser, input)?; parse_complex_selector_and_pseudo_element(parser, input)?;
Ok(Selector { Ok(Selector {
specificity: specificity(&complex, pseudo_element.as_ref()), specificity: specificity(&complex, pseudo_element.as_ref()),
complex_selector: Arc::new(complex), inner: SelectorInner::new(Arc::new(complex)),
pseudo_element: pseudo_element, pseudo_element: pseudo_element,
}) })
} }
@ -1305,48 +1326,48 @@ pub mod tests {
assert_eq!(parse(":lang(4)"), Err(())) ; assert_eq!(parse(":lang(4)"), Err(())) ;
assert_eq!(parse(":lang(en US)"), Err(())) ; assert_eq!(parse(":lang(en US)"), Err(())) ;
assert_eq!(parse("EeÉ"), Ok(SelectorList(vec!(Selector { assert_eq!(parse("EeÉ"), Ok(SelectorList(vec!(Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec!(SimpleSelector::LocalName(LocalName { compound_selector: vec!(SimpleSelector::LocalName(LocalName {
name: DummyAtom::from("EeÉ"), name: DummyAtom::from("EeÉ"),
lower_name: DummyAtom::from("eeÉ") })), lower_name: DummyAtom::from("eeÉ") })),
next: None, next: None,
}), })),
pseudo_element: None, pseudo_element: None,
specificity: specificity(0, 0, 1), specificity: specificity(0, 0, 1),
})))); }))));
assert_eq!(parse(".foo:lang(en-US)"), Ok(SelectorList(vec!(Selector { assert_eq!(parse(".foo:lang(en-US)"), Ok(SelectorList(vec!(Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec![ compound_selector: vec![
SimpleSelector::Class(DummyAtom::from("foo")), SimpleSelector::Class(DummyAtom::from("foo")),
SimpleSelector::NonTSPseudoClass(PseudoClass::Lang("en-US".to_owned())) SimpleSelector::NonTSPseudoClass(PseudoClass::Lang("en-US".to_owned()))
], ],
next: None, next: None,
}), })),
pseudo_element: None, pseudo_element: None,
specificity: specificity(0, 2, 0), specificity: specificity(0, 2, 0),
})))); }))));
assert_eq!(parse("#bar"), Ok(SelectorList(vec!(Selector { assert_eq!(parse("#bar"), Ok(SelectorList(vec!(Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec!(SimpleSelector::ID(DummyAtom::from("bar"))), compound_selector: vec!(SimpleSelector::ID(DummyAtom::from("bar"))),
next: None, next: None,
}), })),
pseudo_element: None, pseudo_element: None,
specificity: specificity(1, 0, 0), specificity: specificity(1, 0, 0),
})))); }))));
assert_eq!(parse("e.foo#bar"), Ok(SelectorList(vec!(Selector { assert_eq!(parse("e.foo#bar"), Ok(SelectorList(vec!(Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec!(SimpleSelector::LocalName(LocalName { compound_selector: vec!(SimpleSelector::LocalName(LocalName {
name: DummyAtom::from("e"), name: DummyAtom::from("e"),
lower_name: DummyAtom::from("e") }), lower_name: DummyAtom::from("e") }),
SimpleSelector::Class(DummyAtom::from("foo")), SimpleSelector::Class(DummyAtom::from("foo")),
SimpleSelector::ID(DummyAtom::from("bar"))), SimpleSelector::ID(DummyAtom::from("bar"))),
next: None, next: None,
}), })),
pseudo_element: None, pseudo_element: None,
specificity: specificity(1, 1, 1), specificity: specificity(1, 1, 1),
})))); }))));
assert_eq!(parse("e.foo #bar"), Ok(SelectorList(vec!(Selector { assert_eq!(parse("e.foo #bar"), Ok(SelectorList(vec!(Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec!(SimpleSelector::ID(DummyAtom::from("bar"))), compound_selector: vec!(SimpleSelector::ID(DummyAtom::from("bar"))),
next: Some((Arc::new(ComplexSelector { next: Some((Arc::new(ComplexSelector {
compound_selector: vec!(SimpleSelector::LocalName(LocalName { compound_selector: vec!(SimpleSelector::LocalName(LocalName {
@ -1355,7 +1376,7 @@ pub mod tests {
SimpleSelector::Class(DummyAtom::from("foo"))), SimpleSelector::Class(DummyAtom::from("foo"))),
next: None, next: None,
}), Combinator::Descendant)), }), Combinator::Descendant)),
}), })),
pseudo_element: None, pseudo_element: None,
specificity: specificity(1, 1, 1), specificity: specificity(1, 1, 1),
})))); }))));
@ -1363,7 +1384,7 @@ pub mod tests {
// https://github.com/mozilla/servo/pull/1652 // https://github.com/mozilla/servo/pull/1652
let mut parser = DummyParser::default(); let mut parser = DummyParser::default();
assert_eq!(parse_ns("[Foo]", &parser), Ok(SelectorList(vec!(Selector { assert_eq!(parse_ns("[Foo]", &parser), Ok(SelectorList(vec!(Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec!(SimpleSelector::AttrExists(AttrSelector { compound_selector: vec!(SimpleSelector::AttrExists(AttrSelector {
name: DummyAtom::from("Foo"), name: DummyAtom::from("Foo"),
lower_name: DummyAtom::from("foo"), lower_name: DummyAtom::from("foo"),
@ -1373,14 +1394,14 @@ pub mod tests {
}), }),
})), })),
next: None, next: None,
}), })),
pseudo_element: None, pseudo_element: None,
specificity: specificity(0, 1, 0), specificity: specificity(0, 1, 0),
})))); }))));
assert_eq!(parse_ns("svg|circle", &parser), Err(())); assert_eq!(parse_ns("svg|circle", &parser), Err(()));
parser.ns_prefixes.insert(DummyAtom("svg".into()), DummyAtom(SVG.into())); parser.ns_prefixes.insert(DummyAtom("svg".into()), DummyAtom(SVG.into()));
assert_eq!(parse_ns("svg|circle", &parser), Ok(SelectorList(vec![Selector { assert_eq!(parse_ns("svg|circle", &parser), Ok(SelectorList(vec![Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec![ compound_selector: vec![
SimpleSelector::Namespace(Namespace { SimpleSelector::Namespace(Namespace {
prefix: Some(DummyAtom("svg".into())), prefix: Some(DummyAtom("svg".into())),
@ -1392,7 +1413,7 @@ pub mod tests {
}) })
], ],
next: None, next: None,
}), })),
pseudo_element: None, pseudo_element: None,
specificity: specificity(0, 0, 1), specificity: specificity(0, 0, 1),
}]))); }])));
@ -1402,7 +1423,7 @@ pub mod tests {
// https://github.com/servo/rust-selectors/pull/82 // https://github.com/servo/rust-selectors/pull/82
parser.default_ns = Some(MATHML.into()); parser.default_ns = Some(MATHML.into());
assert_eq!(parse_ns("[Foo]", &parser), Ok(SelectorList(vec!(Selector { assert_eq!(parse_ns("[Foo]", &parser), Ok(SelectorList(vec!(Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec![ compound_selector: vec![
SimpleSelector::Namespace(Namespace { SimpleSelector::Namespace(Namespace {
prefix: None, prefix: None,
@ -1418,13 +1439,13 @@ pub mod tests {
}), }),
], ],
next: None, next: None,
}), })),
pseudo_element: None, pseudo_element: None,
specificity: specificity(0, 1, 0), specificity: specificity(0, 1, 0),
})))); }))));
// Default namespace does apply to type selectors // Default namespace does apply to type selectors
assert_eq!(parse_ns("e", &parser), Ok(SelectorList(vec!(Selector { assert_eq!(parse_ns("e", &parser), Ok(SelectorList(vec!(Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec!( compound_selector: vec!(
SimpleSelector::Namespace(Namespace { SimpleSelector::Namespace(Namespace {
prefix: None, prefix: None,
@ -1435,12 +1456,12 @@ pub mod tests {
lower_name: DummyAtom::from("e") }), lower_name: DummyAtom::from("e") }),
), ),
next: None, next: None,
}), })),
pseudo_element: None, pseudo_element: None,
specificity: specificity(0, 0, 1), specificity: specificity(0, 0, 1),
})))); }))));
assert_eq!(parse("[attr |= \"foo\"]"), Ok(SelectorList(vec![Selector { assert_eq!(parse("[attr |= \"foo\"]"), Ok(SelectorList(vec![Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec![ compound_selector: vec![
SimpleSelector::AttrDashMatch(AttrSelector { SimpleSelector::AttrDashMatch(AttrSelector {
name: DummyAtom::from("attr"), name: DummyAtom::from("attr"),
@ -1452,23 +1473,23 @@ pub mod tests {
}, DummyAtom::from("foo")) }, DummyAtom::from("foo"))
], ],
next: None, next: None,
}), })),
pseudo_element: None, pseudo_element: None,
specificity: specificity(0, 1, 0), specificity: specificity(0, 1, 0),
}]))); }])));
// https://github.com/mozilla/servo/issues/1723 // https://github.com/mozilla/servo/issues/1723
assert_eq!(parse("::before"), Ok(SelectorList(vec!(Selector { assert_eq!(parse("::before"), Ok(SelectorList(vec!(Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec!(), compound_selector: vec!(),
next: None, next: None,
}), })),
pseudo_element: Some(PseudoElement::Before), pseudo_element: Some(PseudoElement::Before),
specificity: specificity(0, 0, 1), specificity: specificity(0, 0, 1),
})))); }))));
// https://github.com/servo/servo/issues/15335 // https://github.com/servo/servo/issues/15335
assert_eq!(parse(":: before"), Err(())); assert_eq!(parse(":: before"), Err(()));
assert_eq!(parse("div ::after"), Ok(SelectorList(vec!(Selector { assert_eq!(parse("div ::after"), Ok(SelectorList(vec!(Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec!(), compound_selector: vec!(),
next: Some((Arc::new(ComplexSelector { next: Some((Arc::new(ComplexSelector {
compound_selector: vec!(SimpleSelector::LocalName(LocalName { compound_selector: vec!(SimpleSelector::LocalName(LocalName {
@ -1476,12 +1497,12 @@ pub mod tests {
lower_name: DummyAtom::from("div") })), lower_name: DummyAtom::from("div") })),
next: None, next: None,
}), Combinator::Descendant)), }), Combinator::Descendant)),
}), })),
pseudo_element: Some(PseudoElement::After), pseudo_element: Some(PseudoElement::After),
specificity: specificity(0, 0, 2), specificity: specificity(0, 0, 2),
})))); }))));
assert_eq!(parse("#d1 > .ok"), Ok(SelectorList(vec![Selector { assert_eq!(parse("#d1 > .ok"), Ok(SelectorList(vec![Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec![ compound_selector: vec![
SimpleSelector::Class(DummyAtom::from("ok")), SimpleSelector::Class(DummyAtom::from("ok")),
], ],
@ -1491,12 +1512,12 @@ pub mod tests {
], ],
next: None, next: None,
}), Combinator::Child)), }), Combinator::Child)),
}), })),
pseudo_element: None, pseudo_element: None,
specificity: (1 << 20) + (1 << 10) + (0 << 0), specificity: (1 << 20) + (1 << 10) + (0 << 0),
}]))); }])));
assert_eq!(parse(":not(.babybel, #provel.old)"), Ok(SelectorList(vec!(Selector { assert_eq!(parse(":not(.babybel, #provel.old)"), Ok(SelectorList(vec!(Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec!(SimpleSelector::Negation( compound_selector: vec!(SimpleSelector::Negation(
vec!( vec!(
Arc::new(ComplexSelector { Arc::new(ComplexSelector {
@ -1513,7 +1534,7 @@ pub mod tests {
) )
)), )),
next: None, next: None,
}), })),
pseudo_element: None, pseudo_element: None,
specificity: specificity(1, 1, 0), specificity: specificity(1, 1, 0),
})))); }))));

View file

@ -1150,11 +1150,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
}, },
NonTSPseudoClass::MozAny(ref sels) => { NonTSPseudoClass::MozAny(ref sels) => {
sels.iter().any(|s| { sels.iter().any(|s| {
matches_complex_selector(s, matches_complex_selector(s, self, relations, flags_setter)
self,
None,
relations,
flags_setter)
}) })
} }
NonTSPseudoClass::MozSystemMetric(ref s) | NonTSPseudoClass::MozSystemMetric(ref s) |

View file

@ -16,8 +16,8 @@ use heapsize::HeapSizeOf;
use selector_parser::{AttrValue, NonTSPseudoClass, Snapshot, SelectorImpl}; use selector_parser::{AttrValue, NonTSPseudoClass, Snapshot, SelectorImpl};
use selectors::{Element, MatchAttr}; use selectors::{Element, MatchAttr};
use selectors::matching::{ElementSelectorFlags, StyleRelations}; use selectors::matching::{ElementSelectorFlags, StyleRelations};
use selectors::matching::matches_complex_selector; use selectors::matching::matches_selector;
use selectors::parser::{AttrSelector, Combinator, ComplexSelector, SelectorMethods, SimpleSelector}; use selectors::parser::{AttrSelector, Combinator, ComplexSelector, SelectorInner, SelectorMethods, SimpleSelector};
use selectors::visitor::SelectorVisitor; use selectors::visitor::SelectorVisitor;
use std::clone::Clone; use std::clone::Clone;
use std::sync::Arc; use std::sync::Arc;
@ -298,13 +298,10 @@ impl<'a, E> Element for ElementWrapper<'a, E>
// snapshot. // snapshot.
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
{ {
use selectors::matching::matches_complex_selector;
if let NonTSPseudoClass::MozAny(ref selectors) = *pseudo_class { if let NonTSPseudoClass::MozAny(ref selectors) = *pseudo_class {
return selectors.iter().any(|s| { return selectors.iter().any(|s| {
matches_complex_selector(s, matches_complex_selector(s, self, relations, _setter)
self,
None,
relations,
_setter)
}) })
} }
} }
@ -493,7 +490,7 @@ impl Sensitivities {
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
struct Dependency { struct Dependency {
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")] #[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
selector: Arc<ComplexSelector<SelectorImpl>>, selector: SelectorInner<SelectorImpl>,
hint: RestyleHint, hint: RestyleHint,
sensitivities: Sensitivities, sensitivities: Sensitivities,
} }
@ -603,7 +600,7 @@ impl DependencySet {
self.add_dependency(Dependency { self.add_dependency(Dependency {
sensitivities: sensitivities, sensitivities: sensitivities,
hint: hint, hint: hint,
selector: current.clone(), selector: SelectorInner::new(current.clone()),
}) })
} }
@ -699,11 +696,11 @@ impl DependencySet {
// We can ignore the selector flags, since they would have already been set during // We can ignore the selector flags, since they would have already been set during
// original matching for any element that might change its matching behavior here. // original matching for any element that might change its matching behavior here.
let matched_then = let matched_then =
matches_complex_selector(&dep.selector, snapshot, None, matches_selector(&dep.selector, snapshot, None,
&mut StyleRelations::empty(), &mut StyleRelations::empty(),
&mut |_, _| {}); &mut |_, _| {});
let matches_now = let matches_now =
matches_complex_selector(&dep.selector, element, None, matches_selector(&dep.selector, element, None,
&mut StyleRelations::empty(), &mut StyleRelations::empty(),
&mut |_, _| {}); &mut |_, _| {});
if matched_then != matches_now { if matched_then != matches_now {

View file

@ -26,8 +26,8 @@ use selectors::Element;
use selectors::bloom::BloomFilter; use selectors::bloom::BloomFilter;
use selectors::matching::{AFFECTED_BY_ANIMATIONS, AFFECTED_BY_TRANSITIONS}; use selectors::matching::{AFFECTED_BY_ANIMATIONS, AFFECTED_BY_TRANSITIONS};
use selectors::matching::{AFFECTED_BY_STYLE_ATTRIBUTE, AFFECTED_BY_PRESENTATIONAL_HINTS}; use selectors::matching::{AFFECTED_BY_STYLE_ATTRIBUTE, AFFECTED_BY_PRESENTATIONAL_HINTS};
use selectors::matching::{ElementSelectorFlags, StyleRelations, matches_complex_selector}; use selectors::matching::{ElementSelectorFlags, StyleRelations, matches_selector};
use selectors::parser::{Selector, SimpleSelector, LocalName as LocalNameSelector, ComplexSelector}; use selectors::parser::{Selector, SelectorInner, SimpleSelector, LocalName as LocalNameSelector};
use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards}; use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
use sink::Push; use sink::Push;
use smallvec::VecLike; use smallvec::VecLike;
@ -336,7 +336,7 @@ impl Stylist {
}; };
map.insert(Rule { map.insert(Rule {
selector: selector.complex_selector.clone(), selector: selector.inner.clone(),
style_rule: locked.clone(), style_rule: locked.clone(),
specificity: selector.specificity, specificity: selector.specificity,
source_order: self.rules_source_order, source_order: self.rules_source_order,
@ -346,7 +346,7 @@ impl Stylist {
for selector in &style_rule.selectors.0 { for selector in &style_rule.selectors.0 {
let needs_cache_revalidation = let needs_cache_revalidation =
self.dependencies.note_selector(&selector.complex_selector); self.dependencies.note_selector(&selector.inner.complex);
if needs_cache_revalidation { if needs_cache_revalidation {
self.selectors_for_cache_revalidation.push(selector.clone()); self.selectors_for_cache_revalidation.push(selector.clone());
} }
@ -826,14 +826,14 @@ impl Stylist {
F: FnMut(&E, ElementSelectorFlags) F: FnMut(&E, ElementSelectorFlags)
{ {
use selectors::matching::StyleRelations; use selectors::matching::StyleRelations;
use selectors::matching::matches_complex_selector; use selectors::matching::matches_selector;
let len = self.selectors_for_cache_revalidation.len(); let len = self.selectors_for_cache_revalidation.len();
let mut results = BitVec::from_elem(len, false); let mut results = BitVec::from_elem(len, false);
for (i, ref selector) in self.selectors_for_cache_revalidation for (i, ref selector) in self.selectors_for_cache_revalidation
.iter().enumerate() { .iter().enumerate() {
results.set(i, matches_complex_selector(&selector.complex_selector, results.set(i, matches_selector(&selector.inner,
element, element,
Some(bloom), Some(bloom),
&mut StyleRelations::empty(), &mut StyleRelations::empty(),
@ -1081,8 +1081,8 @@ impl SelectorMap {
// correct, and also to not trigger rule tree assertions. // correct, and also to not trigger rule tree assertions.
let mut important = vec![]; let mut important = vec![];
for rule in self.other_rules.iter() { for rule in self.other_rules.iter() {
if rule.selector.compound_selector.is_empty() && if rule.selector.complex.compound_selector.is_empty() &&
rule.selector.next.is_none() { rule.selector.complex.next.is_none() {
let style_rule = rule.style_rule.read_with(guard); let style_rule = rule.style_rule.read_with(guard);
let block = style_rule.block.read_with(guard); let block = style_rule.block.read_with(guard);
if block.any_normal() { if block.any_normal() {
@ -1157,7 +1157,7 @@ impl SelectorMap {
block.any_normal() block.any_normal()
}; };
if any_declaration_for_importance && if any_declaration_for_importance &&
matches_complex_selector(&*rule.selector, element, parent_bf, matches_selector(&rule.selector, element, parent_bf,
relations, flags_setter) { relations, flags_setter) {
matching_rules.push( matching_rules.push(
rule.to_applicable_declaration_block(cascade_level)); rule.to_applicable_declaration_block(cascade_level));
@ -1191,7 +1191,7 @@ impl SelectorMap {
/// Retrieve the first ID name in Rule, or None otherwise. /// Retrieve the first ID name in Rule, or None otherwise.
pub fn get_id_name(rule: &Rule) -> Option<Atom> { pub fn get_id_name(rule: &Rule) -> Option<Atom> {
for ss in &rule.selector.compound_selector { for ss in &rule.selector.complex.compound_selector {
// TODO(pradeep): Implement case-sensitivity based on the // TODO(pradeep): Implement case-sensitivity based on the
// document type and quirks mode. // document type and quirks mode.
if let SimpleSelector::ID(ref id) = *ss { if let SimpleSelector::ID(ref id) = *ss {
@ -1204,7 +1204,7 @@ impl SelectorMap {
/// Retrieve the FIRST class name in Rule, or None otherwise. /// Retrieve the FIRST class name in Rule, or None otherwise.
pub fn get_class_name(rule: &Rule) -> Option<Atom> { pub fn get_class_name(rule: &Rule) -> Option<Atom> {
for ss in &rule.selector.compound_selector { for ss in &rule.selector.complex.compound_selector {
// TODO(pradeep): Implement case-sensitivity based on the // TODO(pradeep): Implement case-sensitivity based on the
// document type and quirks mode. // document type and quirks mode.
if let SimpleSelector::Class(ref class) = *ss { if let SimpleSelector::Class(ref class) = *ss {
@ -1217,7 +1217,7 @@ impl SelectorMap {
/// Retrieve the name if it is a type selector, or None otherwise. /// Retrieve the name if it is a type selector, or None otherwise.
pub fn get_local_name(rule: &Rule) -> Option<LocalNameSelector<SelectorImpl>> { pub fn get_local_name(rule: &Rule) -> Option<LocalNameSelector<SelectorImpl>> {
for ss in &rule.selector.compound_selector { for ss in &rule.selector.complex.compound_selector {
if let SimpleSelector::LocalName(ref n) = *ss { if let SimpleSelector::LocalName(ref n) = *ss {
return Some(LocalNameSelector { return Some(LocalNameSelector {
name: n.name.clone(), name: n.name.clone(),
@ -1245,7 +1245,7 @@ pub struct Rule {
/// style rule was a generic parameter to it. It's not trivial though, due /// style rule was a generic parameter to it. It's not trivial though, due
/// to the specificity. /// to the specificity.
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")] #[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
pub selector: Arc<ComplexSelector<SelectorImpl>>, pub selector: SelectorInner<SelectorImpl>,
/// The actual style rule. /// The actual style rule.
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")] #[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
pub style_rule: Arc<Locked<StyleRule>>, pub style_rule: Arc<Locked<StyleRule>>,

View file

@ -84,7 +84,7 @@ fn test_parse_stylesheet() {
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule { CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
selectors: SelectorList(vec![ selectors: SelectorList(vec![
Selector { Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec![ compound_selector: vec![
SimpleSelector::Namespace(Namespace { SimpleSelector::Namespace(Namespace {
prefix: None, prefix: None,
@ -104,7 +104,7 @@ fn test_parse_stylesheet() {
}, "hidden".to_owned(), CaseSensitivity::CaseInsensitive) }, "hidden".to_owned(), CaseSensitivity::CaseInsensitive)
], ],
next: None, next: None,
}), })),
pseudo_element: None, pseudo_element: None,
specificity: (0 << 20) + (1 << 10) + (1 << 0), specificity: (0 << 20) + (1 << 10) + (1 << 0),
}, },
@ -120,7 +120,7 @@ fn test_parse_stylesheet() {
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule { CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
selectors: SelectorList(vec![ selectors: SelectorList(vec![
Selector { Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec![ compound_selector: vec![
SimpleSelector::Namespace(Namespace { SimpleSelector::Namespace(Namespace {
prefix: None, prefix: None,
@ -132,12 +132,12 @@ fn test_parse_stylesheet() {
}), }),
], ],
next: None, next: None,
}), })),
pseudo_element: None, pseudo_element: None,
specificity: (0 << 20) + (0 << 10) + (1 << 0), specificity: (0 << 20) + (0 << 10) + (1 << 0),
}, },
Selector { Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec![ compound_selector: vec![
SimpleSelector::Namespace(Namespace { SimpleSelector::Namespace(Namespace {
prefix: None, prefix: None,
@ -149,7 +149,7 @@ fn test_parse_stylesheet() {
}), }),
], ],
next: None, next: None,
}), })),
pseudo_element: None, pseudo_element: None,
specificity: (0 << 20) + (0 << 10) + (1 << 0), specificity: (0 << 20) + (0 << 10) + (1 << 0),
}, },
@ -162,7 +162,7 @@ fn test_parse_stylesheet() {
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule { CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
selectors: SelectorList(vec![ selectors: SelectorList(vec![
Selector { Selector {
complex_selector: Arc::new(ComplexSelector { inner: SelectorInner::new(Arc::new(ComplexSelector {
compound_selector: vec![ compound_selector: vec![
SimpleSelector::Namespace(Namespace { SimpleSelector::Namespace(Namespace {
prefix: None, prefix: None,
@ -180,7 +180,7 @@ fn test_parse_stylesheet() {
], ],
next: None, next: None,
}), Combinator::Child)), }), Combinator::Child)),
}), })),
pseudo_element: None, pseudo_element: None,
specificity: (1 << 20) + (1 << 10) + (0 << 0), specificity: (1 << 20) + (1 << 10) + (0 << 0),
}, },

View file

@ -35,7 +35,7 @@ fn get_mock_rules(css_selectors: &[&str]) -> (Vec<Vec<Rule>>, SharedRwLock) {
let rule = locked.read_with(&guard); let rule = locked.read_with(&guard);
rule.selectors.0.iter().map(|s| { rule.selectors.0.iter().map(|s| {
Rule { Rule {
selector: s.complex_selector.clone(), selector: s.inner.clone(),
style_rule: locked.clone(), style_rule: locked.clone(),
specificity: s.specificity, specificity: s.specificity,
source_order: i, source_order: i,