mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Stop slicing selectors when noting dependencies, and match with an offset instead.
MozReview-Commit-ID: KLqmdRKygO0
This commit is contained in:
parent
5ddabef636
commit
1281fd9353
6 changed files with 76 additions and 55 deletions
|
@ -160,6 +160,7 @@ pub fn matches_selector_list<E>(selector_list: &SelectorList<E::Impl>,
|
||||||
{
|
{
|
||||||
selector_list.0.iter().any(|selector_and_hashes| {
|
selector_list.0.iter().any(|selector_and_hashes| {
|
||||||
matches_selector(&selector_and_hashes.selector,
|
matches_selector(&selector_and_hashes.selector,
|
||||||
|
0,
|
||||||
&selector_and_hashes.hashes,
|
&selector_and_hashes.hashes,
|
||||||
element,
|
element,
|
||||||
context,
|
context,
|
||||||
|
@ -333,8 +334,16 @@ enum SelectorMatchingResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Matches a selector, fast-rejecting against a bloom filter.
|
/// Matches a selector, fast-rejecting against a bloom filter.
|
||||||
|
///
|
||||||
|
/// We accept an offset to allow consumers to represent and match against partial
|
||||||
|
/// selectors (indexed from the right). We use this API design, rather than
|
||||||
|
/// having the callers pass a SelectorIter, because creating a SelectorIter
|
||||||
|
/// requires dereferencing the selector to get the length, which adds an
|
||||||
|
/// unncessary cache miss for cases when we can fast-reject with AncestorHashes
|
||||||
|
/// (which the caller can store inline with the selector pointer).
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn matches_selector<E, F>(selector: &Selector<E::Impl>,
|
pub fn matches_selector<E, F>(selector: &Selector<E::Impl>,
|
||||||
|
offset: usize,
|
||||||
hashes: &AncestorHashes,
|
hashes: &AncestorHashes,
|
||||||
element: &E,
|
element: &E,
|
||||||
context: &mut MatchingContext,
|
context: &mut MatchingContext,
|
||||||
|
@ -350,11 +359,12 @@ pub fn matches_selector<E, F>(selector: &Selector<E::Impl>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
matches_complex_selector(selector, element, context, flags_setter)
|
matches_complex_selector(selector, offset, element, context, flags_setter)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Matches a complex selector.
|
/// Matches a complex selector.
|
||||||
pub fn matches_complex_selector<E, F>(complex_selector: &Selector<E::Impl>,
|
pub fn matches_complex_selector<E, F>(complex_selector: &Selector<E::Impl>,
|
||||||
|
offset: usize,
|
||||||
element: &E,
|
element: &E,
|
||||||
context: &mut MatchingContext,
|
context: &mut MatchingContext,
|
||||||
flags_setter: &mut F)
|
flags_setter: &mut F)
|
||||||
|
@ -362,11 +372,15 @@ pub fn matches_complex_selector<E, F>(complex_selector: &Selector<E::Impl>,
|
||||||
where E: Element,
|
where E: Element,
|
||||||
F: FnMut(&E, ElementSelectorFlags),
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
{
|
{
|
||||||
let mut iter = complex_selector.iter();
|
let mut iter = if offset == 0 {
|
||||||
|
complex_selector.iter()
|
||||||
|
} else {
|
||||||
|
complex_selector.iter_from(offset)
|
||||||
|
};
|
||||||
|
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
if context.matching_mode == MatchingMode::ForStatelessPseudoElement {
|
if context.matching_mode == MatchingMode::ForStatelessPseudoElement {
|
||||||
assert!(complex_selector.iter().any(|c| {
|
assert!(iter.clone().any(|c| {
|
||||||
matches!(*c, Component::PseudoElement(..))
|
matches!(*c, Component::PseudoElement(..))
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,9 +177,13 @@ pub struct AncestorHashes(pub [u32; NUM_ANCESTOR_HASHES]);
|
||||||
|
|
||||||
impl AncestorHashes {
|
impl AncestorHashes {
|
||||||
pub fn new<Impl: SelectorImpl>(s: &Selector<Impl>) -> Self {
|
pub fn new<Impl: SelectorImpl>(s: &Selector<Impl>) -> Self {
|
||||||
|
Self::from_iter(s.iter())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_iter<Impl: SelectorImpl>(iter: SelectorIter<Impl>) -> Self {
|
||||||
let mut hashes = [0; NUM_ANCESTOR_HASHES];
|
let mut hashes = [0; NUM_ANCESTOR_HASHES];
|
||||||
// Compute ancestor hashes for the bloom filter.
|
// Compute ancestor hashes for the bloom filter.
|
||||||
let mut hash_iter = s.iter_ancestors()
|
let mut hash_iter = AncestorIter::new(iter)
|
||||||
.map(|x| x.ancestor_hash())
|
.map(|x| x.ancestor_hash())
|
||||||
.filter(|x| x.is_some())
|
.filter(|x| x.is_some())
|
||||||
.map(|x| x.unwrap());
|
.map(|x| x.unwrap());
|
||||||
|
@ -356,6 +360,16 @@ impl<Impl: SelectorImpl> Selector<Impl> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn iter_from(&self, offset: usize) -> SelectorIter<Impl> {
|
||||||
|
// Note: selectors are stored left-to-right but logical order is right-to-left.
|
||||||
|
let slice = self.0.as_ref();
|
||||||
|
let iter = slice[..(slice.len() - offset)].iter().rev();
|
||||||
|
SelectorIter {
|
||||||
|
iter: iter,
|
||||||
|
next_combinator: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an iterator over the entire sequence of simple selectors and combinators,
|
/// Returns an iterator over the entire sequence of simple selectors and combinators,
|
||||||
/// from right to left.
|
/// from right to left.
|
||||||
pub fn iter_raw(&self) -> Rev<slice::Iter<Component<Impl>>> {
|
pub fn iter_raw(&self) -> Rev<slice::Iter<Component<Impl>>> {
|
||||||
|
@ -368,28 +382,6 @@ impl<Impl: SelectorImpl> Selector<Impl> {
|
||||||
self.0.iter()
|
self.0.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator over ancestor simple selectors. All combinators and
|
|
||||||
/// non-ancestor simple selectors will be skipped.
|
|
||||||
pub fn iter_ancestors(&self) -> AncestorIter<Impl> {
|
|
||||||
AncestorIter::new(self.iter())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a Selector identical to |self| but with the rightmost |index| entries
|
|
||||||
/// removed.
|
|
||||||
pub fn slice_from(&self, index: usize) -> Self {
|
|
||||||
// Note that we convert the slice_from to slice_to because selectors are
|
|
||||||
// stored left-to-right but logical order is right-to-left.
|
|
||||||
Selector(self.0.clone().slice_to(self.0.len() - index), self.1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a Selector identical to |self| but with the leftmost |len() - index|
|
|
||||||
/// entries removed.
|
|
||||||
pub fn slice_to(&self, index: usize) -> Self {
|
|
||||||
// Note that we convert the slice_to to slice_from because selectors are
|
|
||||||
// stored left-to-right but logical order is right-to-left.
|
|
||||||
Selector(self.0.clone().slice_from(self.0.len() - index), self.1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a Selector from a vec of Components. Used in tests.
|
/// Creates a Selector from a vec of Components. Used in tests.
|
||||||
pub fn from_vec(vec: Vec<Component<Impl>>, specificity_and_flags: u32) -> Self {
|
pub fn from_vec(vec: Vec<Component<Impl>>, specificity_and_flags: u32) -> Self {
|
||||||
Selector(ArcSlice::new(vec.into_boxed_slice()), specificity_and_flags)
|
Selector(ArcSlice::new(vec.into_boxed_slice()), specificity_and_flags)
|
||||||
|
|
|
@ -1405,7 +1405,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||||
NonTSPseudoClass::MozPlaceholder => false,
|
NonTSPseudoClass::MozPlaceholder => false,
|
||||||
NonTSPseudoClass::MozAny(ref sels) => {
|
NonTSPseudoClass::MozAny(ref sels) => {
|
||||||
sels.iter().any(|s| {
|
sels.iter().any(|s| {
|
||||||
matches_complex_selector(s, self, context, flags_setter)
|
matches_complex_selector(s, 0, self, context, flags_setter)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
NonTSPseudoClass::MozSystemMetric(ref s) |
|
NonTSPseudoClass::MozSystemMetric(ref s) |
|
||||||
|
|
|
@ -23,7 +23,7 @@ use selectors::attr::{AttrSelectorOperation, NamespaceConstraint};
|
||||||
use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode};
|
use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode};
|
||||||
use selectors::matching::{RelevantLinkStatus, VisitedHandlingMode, matches_selector};
|
use selectors::matching::{RelevantLinkStatus, VisitedHandlingMode, matches_selector};
|
||||||
use selectors::parser::{AncestorHashes, Combinator, Component};
|
use selectors::parser::{AncestorHashes, Combinator, Component};
|
||||||
use selectors::parser::{Selector, SelectorAndHashes, SelectorMethods};
|
use selectors::parser::{Selector, SelectorAndHashes, SelectorIter, SelectorMethods};
|
||||||
use selectors::visitor::SelectorVisitor;
|
use selectors::visitor::SelectorVisitor;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -643,7 +643,7 @@ impl<'a, E> Element for ElementWrapper<'a, E>
|
||||||
use selectors::matching::matches_complex_selector;
|
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, self, context, _setter)
|
matches_complex_selector(s, 0, self, context, _setter)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -867,8 +867,13 @@ impl Sensitivities {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct Dependency {
|
pub struct Dependency {
|
||||||
|
/// The dependency selector.
|
||||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||||
selector: Selector<SelectorImpl>,
|
selector: Selector<SelectorImpl>,
|
||||||
|
/// The offset into the selector that we should match on.
|
||||||
|
selector_offset: usize,
|
||||||
|
/// The ancestor hashes associated with the above selector at the given
|
||||||
|
/// offset.
|
||||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "No heap data")]
|
#[cfg_attr(feature = "servo", ignore_heap_size_of = "No heap data")]
|
||||||
hashes: AncestorHashes,
|
hashes: AncestorHashes,
|
||||||
/// The hint associated with this dependency.
|
/// The hint associated with this dependency.
|
||||||
|
@ -878,8 +883,8 @@ pub struct Dependency {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SelectorMapEntry for Dependency {
|
impl SelectorMapEntry for Dependency {
|
||||||
fn selector(&self) -> &Selector<SelectorImpl> {
|
fn selector(&self) -> SelectorIter<SelectorImpl> {
|
||||||
&self.selector
|
self.selector.iter_from(self.selector_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hashes(&self) -> &AncestorHashes {
|
fn hashes(&self) -> &AncestorHashes {
|
||||||
|
@ -999,19 +1004,20 @@ impl DependencySet {
|
||||||
None => RestyleHint::for_self(),
|
None => RestyleHint::for_self(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (dep_selector, hashes) = if sequence_start == 0 {
|
// Reuse the bloom hashes if this is the base selector. Otherwise,
|
||||||
// Reuse the bloom hashes if this is the base selector.
|
// rebuild them.
|
||||||
(selector_and_hashes.selector.clone(), selector_and_hashes.hashes.clone())
|
let hashes = if sequence_start == 0 {
|
||||||
|
selector_and_hashes.hashes.clone()
|
||||||
} else {
|
} else {
|
||||||
let selector = selector_and_hashes.selector.slice_from(sequence_start);
|
let seq_iter = selector_and_hashes.selector.iter_from(sequence_start);
|
||||||
let hashes = AncestorHashes::new(&selector);
|
AncestorHashes::from_iter(seq_iter)
|
||||||
(selector, hashes)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.dependencies.insert(Dependency {
|
self.dependencies.insert(Dependency {
|
||||||
sensitivities: visitor.sensitivities,
|
sensitivities: visitor.sensitivities,
|
||||||
hint: hint,
|
hint: hint,
|
||||||
selector: dep_selector,
|
selector: selector_and_hashes.selector.clone(),
|
||||||
|
selector_offset: sequence_start,
|
||||||
hashes: hashes,
|
hashes: hashes,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1141,6 +1147,7 @@ impl DependencySet {
|
||||||
VisitedHandlingMode::AllLinksUnvisited);
|
VisitedHandlingMode::AllLinksUnvisited);
|
||||||
let matched_then =
|
let matched_then =
|
||||||
matches_selector(&dep.selector,
|
matches_selector(&dep.selector,
|
||||||
|
dep.selector_offset,
|
||||||
&dep.hashes,
|
&dep.hashes,
|
||||||
&snapshot_el,
|
&snapshot_el,
|
||||||
&mut then_context,
|
&mut then_context,
|
||||||
|
@ -1150,6 +1157,7 @@ impl DependencySet {
|
||||||
VisitedHandlingMode::AllLinksUnvisited);
|
VisitedHandlingMode::AllLinksUnvisited);
|
||||||
let matches_now =
|
let matches_now =
|
||||||
matches_selector(&dep.selector,
|
matches_selector(&dep.selector,
|
||||||
|
dep.selector_offset,
|
||||||
&dep.hashes,
|
&dep.hashes,
|
||||||
el,
|
el,
|
||||||
&mut now_context,
|
&mut now_context,
|
||||||
|
@ -1177,6 +1185,7 @@ impl DependencySet {
|
||||||
then_context.visited_handling = VisitedHandlingMode::RelevantLinkVisited;
|
then_context.visited_handling = VisitedHandlingMode::RelevantLinkVisited;
|
||||||
let matched_then =
|
let matched_then =
|
||||||
matches_selector(&dep.selector,
|
matches_selector(&dep.selector,
|
||||||
|
dep.selector_offset,
|
||||||
&dep.hashes,
|
&dep.hashes,
|
||||||
&snapshot_el,
|
&snapshot_el,
|
||||||
&mut then_context,
|
&mut then_context,
|
||||||
|
@ -1184,6 +1193,7 @@ impl DependencySet {
|
||||||
now_context.visited_handling = VisitedHandlingMode::RelevantLinkVisited;
|
now_context.visited_handling = VisitedHandlingMode::RelevantLinkVisited;
|
||||||
let matches_now =
|
let matches_now =
|
||||||
matches_selector(&dep.selector,
|
matches_selector(&dep.selector,
|
||||||
|
dep.selector_offset,
|
||||||
&dep.hashes,
|
&dep.hashes,
|
||||||
el,
|
el,
|
||||||
&mut now_context,
|
&mut now_context,
|
||||||
|
|
|
@ -12,7 +12,7 @@ use pdqsort::sort_by;
|
||||||
use rule_tree::CascadeLevel;
|
use rule_tree::CascadeLevel;
|
||||||
use selector_parser::SelectorImpl;
|
use selector_parser::SelectorImpl;
|
||||||
use selectors::matching::{matches_selector, MatchingContext, ElementSelectorFlags};
|
use selectors::matching::{matches_selector, MatchingContext, ElementSelectorFlags};
|
||||||
use selectors::parser::{AncestorHashes, Component, Combinator, Selector, SelectorAndHashes};
|
use selectors::parser::{AncestorHashes, Component, Combinator, SelectorAndHashes, SelectorIter};
|
||||||
use selectors::parser::LocalName as LocalNameSelector;
|
use selectors::parser::LocalName as LocalNameSelector;
|
||||||
use smallvec::VecLike;
|
use smallvec::VecLike;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
@ -23,15 +23,15 @@ use stylist::{ApplicableDeclarationBlock, Rule};
|
||||||
/// A trait to abstract over a given selector map entry.
|
/// A trait to abstract over a given selector map entry.
|
||||||
pub trait SelectorMapEntry : Sized + Clone {
|
pub trait SelectorMapEntry : Sized + Clone {
|
||||||
/// Gets the selector we should use to index in the selector map.
|
/// Gets the selector we should use to index in the selector map.
|
||||||
fn selector(&self) -> &Selector<SelectorImpl>;
|
fn selector(&self) -> SelectorIter<SelectorImpl>;
|
||||||
|
|
||||||
/// Gets the ancestor hashes associated with the selector.
|
/// Gets the ancestor hashes associated with the selector.
|
||||||
fn hashes(&self) -> &AncestorHashes;
|
fn hashes(&self) -> &AncestorHashes;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SelectorMapEntry for SelectorAndHashes<SelectorImpl> {
|
impl SelectorMapEntry for SelectorAndHashes<SelectorImpl> {
|
||||||
fn selector(&self) -> &Selector<SelectorImpl> {
|
fn selector(&self) -> SelectorIter<SelectorImpl> {
|
||||||
&self.selector
|
self.selector.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hashes(&self) -> &AncestorHashes {
|
fn hashes(&self) -> &AncestorHashes {
|
||||||
|
@ -232,6 +232,7 @@ impl SelectorMap<Rule> {
|
||||||
{
|
{
|
||||||
for rule in rules {
|
for rule in rules {
|
||||||
if matches_selector(&rule.selector,
|
if matches_selector(&rule.selector,
|
||||||
|
0,
|
||||||
&rule.hashes,
|
&rule.hashes,
|
||||||
element,
|
element,
|
||||||
context,
|
context,
|
||||||
|
@ -398,12 +399,12 @@ impl<T: SelectorMapEntry> SelectorMap<T> {
|
||||||
///
|
///
|
||||||
/// Effectively, pseudo-elements are ignored, given only state pseudo-classes
|
/// Effectively, pseudo-elements are ignored, given only state pseudo-classes
|
||||||
/// may appear before them.
|
/// may appear before them.
|
||||||
fn find_from_right<F, R>(selector: &Selector<SelectorImpl>,
|
#[inline(always)]
|
||||||
|
fn find_from_right<F, R>(mut iter: SelectorIter<SelectorImpl>,
|
||||||
mut f: F)
|
mut f: F)
|
||||||
-> Option<R>
|
-> Option<R>
|
||||||
where F: FnMut(&Component<SelectorImpl>) -> Option<R>,
|
where F: FnMut(&Component<SelectorImpl>) -> Option<R>,
|
||||||
{
|
{
|
||||||
let mut iter = selector.iter();
|
|
||||||
for ss in &mut iter {
|
for ss in &mut iter {
|
||||||
if let Some(r) = f(ss) {
|
if let Some(r) = f(ss) {
|
||||||
return Some(r)
|
return Some(r)
|
||||||
|
@ -422,9 +423,10 @@ fn find_from_right<F, R>(selector: &Selector<SelectorImpl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the first ID name in the selector, or None otherwise.
|
/// Retrieve the first ID name in the selector, or None otherwise.
|
||||||
pub fn get_id_name(selector: &Selector<SelectorImpl>)
|
#[inline(always)]
|
||||||
|
pub fn get_id_name(iter: SelectorIter<SelectorImpl>)
|
||||||
-> Option<Atom> {
|
-> Option<Atom> {
|
||||||
find_from_right(selector, |ss| {
|
find_from_right(iter, |ss| {
|
||||||
// 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 Component::ID(ref id) = *ss {
|
if let Component::ID(ref id) = *ss {
|
||||||
|
@ -435,9 +437,10 @@ pub fn get_id_name(selector: &Selector<SelectorImpl>)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the FIRST class name in the selector, or None otherwise.
|
/// Retrieve the FIRST class name in the selector, or None otherwise.
|
||||||
pub fn get_class_name(selector: &Selector<SelectorImpl>)
|
#[inline(always)]
|
||||||
|
pub fn get_class_name(iter: SelectorIter<SelectorImpl>)
|
||||||
-> Option<Atom> {
|
-> Option<Atom> {
|
||||||
find_from_right(selector, |ss| {
|
find_from_right(iter, |ss| {
|
||||||
// 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 Component::Class(ref class) = *ss {
|
if let Component::Class(ref class) = *ss {
|
||||||
|
@ -448,9 +451,10 @@ pub fn get_class_name(selector: &Selector<SelectorImpl>)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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(selector: &Selector<SelectorImpl>)
|
#[inline(always)]
|
||||||
|
pub fn get_local_name(iter: SelectorIter<SelectorImpl>)
|
||||||
-> Option<LocalNameSelector<SelectorImpl>> {
|
-> Option<LocalNameSelector<SelectorImpl>> {
|
||||||
find_from_right(selector, |ss| {
|
find_from_right(iter, |ss| {
|
||||||
if let Component::LocalName(ref n) = *ss {
|
if let Component::LocalName(ref n) = *ss {
|
||||||
return Some(LocalNameSelector {
|
return Some(LocalNameSelector {
|
||||||
name: n.name.clone(),
|
name: n.name.clone(),
|
||||||
|
|
|
@ -1134,6 +1134,7 @@ impl Stylist {
|
||||||
let mut results = BitVec::new();
|
let mut results = BitVec::new();
|
||||||
self.selectors_for_cache_revalidation.lookup(*element, &mut |selector_and_hashes| {
|
self.selectors_for_cache_revalidation.lookup(*element, &mut |selector_and_hashes| {
|
||||||
results.push(matches_selector(&selector_and_hashes.selector,
|
results.push(matches_selector(&selector_and_hashes.selector,
|
||||||
|
0,
|
||||||
&selector_and_hashes.hashes,
|
&selector_and_hashes.hashes,
|
||||||
element,
|
element,
|
||||||
&mut matching_context,
|
&mut matching_context,
|
||||||
|
@ -1424,8 +1425,8 @@ pub struct Rule {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SelectorMapEntry for Rule {
|
impl SelectorMapEntry for Rule {
|
||||||
fn selector(&self) -> &Selector<SelectorImpl> {
|
fn selector(&self) -> SelectorIter<SelectorImpl> {
|
||||||
&self.selector
|
self.selector.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hashes(&self) -> &AncestorHashes {
|
fn hashes(&self) -> &AncestorHashes {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue