зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #17707 - stylo: Waste less memory in invalidation stuff and style rules (from emilio:invalidation-less-memory); r=heycam
This should help a lot with https://bugzilla.mozilla.org/show_bug.cgi?id=1380488. Source-Repo: https://github.com/servo/servo Source-Revision: 9515abbca396c176e6a5c603a193573ac0cb9e33 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : a4601778f9a782387203cceb70efe733848cee16
This commit is contained in:
Родитель
95d7656f60
Коммит
be09f143b8
|
@ -164,10 +164,10 @@ pub fn matches_selector_list<E>(selector_list: &SelectorList<E::Impl>,
|
||||||
-> bool
|
-> bool
|
||||||
where E: Element
|
where E: Element
|
||||||
{
|
{
|
||||||
selector_list.0.iter().any(|selector_and_hashes| {
|
selector_list.0.iter().any(|selector| {
|
||||||
matches_selector(&selector_and_hashes.selector,
|
matches_selector(selector,
|
||||||
0,
|
0,
|
||||||
&selector_and_hashes.hashes,
|
None,
|
||||||
element,
|
element,
|
||||||
context,
|
context,
|
||||||
&mut |_, _| {})
|
&mut |_, _| {})
|
||||||
|
@ -371,7 +371,7 @@ enum SelectorMatchingResult {
|
||||||
#[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,
|
offset: usize,
|
||||||
hashes: &AncestorHashes,
|
hashes: Option<&AncestorHashes>,
|
||||||
element: &E,
|
element: &E,
|
||||||
context: &mut MatchingContext,
|
context: &mut MatchingContext,
|
||||||
flags_setter: &mut F)
|
flags_setter: &mut F)
|
||||||
|
@ -380,9 +380,11 @@ pub fn matches_selector<E, F>(selector: &Selector<E::Impl>,
|
||||||
F: FnMut(&E, ElementSelectorFlags),
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
{
|
{
|
||||||
// Use the bloom filter to fast-reject.
|
// Use the bloom filter to fast-reject.
|
||||||
if let Some(filter) = context.bloom_filter {
|
if let Some(hashes) = hashes {
|
||||||
if !may_match::<E>(hashes, filter) {
|
if let Some(filter) = context.bloom_filter {
|
||||||
return false;
|
if !may_match::<E>(hashes, filter) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,27 +177,7 @@ pub trait Parser<'i> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
pub struct SelectorAndHashes<Impl: SelectorImpl> {
|
pub struct SelectorList<Impl: SelectorImpl>(pub Vec<Selector<Impl>>);
|
||||||
pub selector: Selector<Impl>,
|
|
||||||
pub hashes: AncestorHashes,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Impl: SelectorImpl> SelectorAndHashes<Impl> {
|
|
||||||
pub fn new(selector: Selector<Impl>) -> Self {
|
|
||||||
let hashes = AncestorHashes::new(&selector);
|
|
||||||
Self::new_with_hashes(selector, hashes)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_with_hashes(selector: Selector<Impl>, hashes: AncestorHashes) -> Self {
|
|
||||||
SelectorAndHashes {
|
|
||||||
selector: selector,
|
|
||||||
hashes: hashes,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
|
||||||
pub struct SelectorList<Impl: SelectorImpl>(pub Vec<SelectorAndHashes<Impl>>);
|
|
||||||
|
|
||||||
impl<Impl: SelectorImpl> SelectorList<Impl> {
|
impl<Impl: SelectorImpl> SelectorList<Impl> {
|
||||||
/// Parse a comma-separated list of Selectors.
|
/// Parse a comma-separated list of Selectors.
|
||||||
|
@ -207,13 +187,13 @@ impl<Impl: SelectorImpl> SelectorList<Impl> {
|
||||||
pub fn parse<'i, 't, P, E>(parser: &P, input: &mut CssParser<'i, 't>)
|
pub fn parse<'i, 't, P, E>(parser: &P, input: &mut CssParser<'i, 't>)
|
||||||
-> Result<Self, ParseError<'i, SelectorParseError<'i, E>>>
|
-> Result<Self, ParseError<'i, SelectorParseError<'i, E>>>
|
||||||
where P: Parser<'i, Impl=Impl, Error=E> {
|
where P: Parser<'i, Impl=Impl, Error=E> {
|
||||||
input.parse_comma_separated(|input| parse_selector(parser, input).map(SelectorAndHashes::new))
|
input.parse_comma_separated(|input| parse_selector(parser, input))
|
||||||
.map(SelectorList)
|
.map(SelectorList)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a SelectorList from a Vec of selectors. Used in tests.
|
/// Creates a SelectorList from a Vec of selectors. Used in tests.
|
||||||
pub fn from_vec(v: Vec<Selector<Impl>>) -> Self {
|
pub fn from_vec(v: Vec<Selector<Impl>>) -> Self {
|
||||||
SelectorList(v.into_iter().map(SelectorAndHashes::new).collect())
|
SelectorList(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,10 +741,10 @@ impl<Impl: SelectorImpl> ToCss for SelectorList<Impl> {
|
||||||
let mut iter = self.0.iter();
|
let mut iter = self.0.iter();
|
||||||
let first = iter.next()
|
let first = iter.next()
|
||||||
.expect("Empty SelectorList, should contain at least one selector");
|
.expect("Empty SelectorList, should contain at least one selector");
|
||||||
first.selector.to_css(dest)?;
|
first.to_css(dest)?;
|
||||||
for selector_and_hashes in iter {
|
for selector in iter {
|
||||||
dest.write_str(", ")?;
|
dest.write_str(", ")?;
|
||||||
selector_and_hashes.selector.to_css(dest)?;
|
selector.to_css(dest)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1761,7 +1741,7 @@ pub mod tests {
|
||||||
let result = SelectorList::parse(parser, &mut CssParser::new(&mut parser_input));
|
let result = SelectorList::parse(parser, &mut CssParser::new(&mut parser_input));
|
||||||
if let Ok(ref selectors) = result {
|
if let Ok(ref selectors) = result {
|
||||||
assert_eq!(selectors.0.len(), 1);
|
assert_eq!(selectors.0.len(), 1);
|
||||||
assert_eq!(selectors.0[0].selector.to_css_string(), input);
|
assert_eq!(selectors.0[0].to_css_string(), input);
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -2066,7 +2046,7 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pseudo_iter() {
|
fn test_pseudo_iter() {
|
||||||
let selector = &parse("q::before").unwrap().0[0].selector;
|
let selector = &parse("q::before").unwrap().0[0];
|
||||||
assert!(!selector.is_universal());
|
assert!(!selector.is_universal());
|
||||||
let mut iter = selector.iter();
|
let mut iter = selector.iter();
|
||||||
assert_eq!(iter.next(), Some(&Component::PseudoElement(PseudoElement::Before)));
|
assert_eq!(iter.next(), Some(&Component::PseudoElement(PseudoElement::Before)));
|
||||||
|
@ -2080,13 +2060,13 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_universal() {
|
fn test_universal() {
|
||||||
let selector = &parse("*|*::before").unwrap().0[0].selector;
|
let selector = &parse("*|*::before").unwrap().0[0];
|
||||||
assert!(selector.is_universal());
|
assert!(selector.is_universal());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_empty_pseudo_iter() {
|
fn test_empty_pseudo_iter() {
|
||||||
let selector = &parse("::before").unwrap().0[0].selector;
|
let selector = &parse("::before").unwrap().0[0];
|
||||||
assert!(selector.is_universal());
|
assert!(selector.is_universal());
|
||||||
let mut iter = selector.iter();
|
let mut iter = selector.iter();
|
||||||
assert_eq!(iter.next(), Some(&Component::PseudoElement(PseudoElement::Before)));
|
assert_eq!(iter.next(), Some(&Component::PseudoElement(PseudoElement::Before)));
|
||||||
|
@ -2112,11 +2092,11 @@ pub mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn visitor() {
|
fn visitor() {
|
||||||
let mut test_visitor = TestVisitor { seen: vec![], };
|
let mut test_visitor = TestVisitor { seen: vec![], };
|
||||||
parse(":not(:hover) ~ label").unwrap().0[0].selector.visit(&mut test_visitor);
|
parse(":not(:hover) ~ label").unwrap().0[0].visit(&mut test_visitor);
|
||||||
assert!(test_visitor.seen.contains(&":hover".into()));
|
assert!(test_visitor.seen.contains(&":hover".into()));
|
||||||
|
|
||||||
let mut test_visitor = TestVisitor { seen: vec![], };
|
let mut test_visitor = TestVisitor { seen: vec![], };
|
||||||
parse("::before:hover").unwrap().0[0].selector.visit(&mut test_visitor);
|
parse("::before:hover").unwrap().0[0].visit(&mut test_visitor);
|
||||||
assert!(test_visitor.seen.contains(&":hover".into()));
|
assert!(test_visitor.seen.contains(&":hover".into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,8 @@ use element_state::ElementState;
|
||||||
use selector_map::{MaybeCaseInsensitiveHashMap, SelectorMap, SelectorMapEntry};
|
use selector_map::{MaybeCaseInsensitiveHashMap, SelectorMap, SelectorMapEntry};
|
||||||
use selector_parser::SelectorImpl;
|
use selector_parser::SelectorImpl;
|
||||||
use selectors::attr::NamespaceConstraint;
|
use selectors::attr::NamespaceConstraint;
|
||||||
use selectors::parser::{AncestorHashes, Combinator, Component};
|
use selectors::parser::{Combinator, Component};
|
||||||
use selectors::parser::{Selector, SelectorAndHashes, SelectorIter, SelectorMethods};
|
use selectors::parser::{Selector, SelectorIter, SelectorMethods};
|
||||||
use selectors::visitor::SelectorVisitor;
|
use selectors::visitor::SelectorVisitor;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
|
@ -59,10 +59,6 @@ pub struct Dependency {
|
||||||
/// The dependency selector.
|
/// The dependency selector.
|
||||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||||
pub selector: Selector<SelectorImpl>,
|
pub selector: Selector<SelectorImpl>,
|
||||||
/// The ancestor hashes associated with the above selector at the given
|
|
||||||
/// offset.
|
|
||||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "No heap data")]
|
|
||||||
pub hashes: AncestorHashes,
|
|
||||||
/// The offset into the selector that we should match on.
|
/// The offset into the selector that we should match on.
|
||||||
pub selector_offset: usize,
|
pub selector_offset: usize,
|
||||||
}
|
}
|
||||||
|
@ -109,10 +105,6 @@ impl SelectorMapEntry for Dependency {
|
||||||
fn selector(&self) -> SelectorIter<SelectorImpl> {
|
fn selector(&self) -> SelectorIter<SelectorImpl> {
|
||||||
self.selector.iter_from(self.selector_offset)
|
self.selector.iter_from(self.selector_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hashes(&self) -> &AncestorHashes {
|
|
||||||
&self.hashes
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The same, but for state selectors, which can track more exactly what state
|
/// The same, but for state selectors, which can track more exactly what state
|
||||||
|
@ -128,11 +120,7 @@ pub struct StateDependency {
|
||||||
|
|
||||||
impl SelectorMapEntry for StateDependency {
|
impl SelectorMapEntry for StateDependency {
|
||||||
fn selector(&self) -> SelectorIter<SelectorImpl> {
|
fn selector(&self) -> SelectorIter<SelectorImpl> {
|
||||||
self.dep.selector.iter_from(self.dep.selector_offset)
|
self.dep.selector()
|
||||||
}
|
|
||||||
|
|
||||||
fn hashes(&self) -> &AncestorHashes {
|
|
||||||
&self.dep.hashes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,10 +184,10 @@ impl InvalidationMap {
|
||||||
/// Adds a selector to this `InvalidationMap`.
|
/// Adds a selector to this `InvalidationMap`.
|
||||||
pub fn note_selector(
|
pub fn note_selector(
|
||||||
&mut self,
|
&mut self,
|
||||||
selector_and_hashes: &SelectorAndHashes<SelectorImpl>,
|
selector: &Selector<SelectorImpl>,
|
||||||
quirks_mode: QuirksMode)
|
quirks_mode: QuirksMode)
|
||||||
{
|
{
|
||||||
self.collect_invalidations_for(selector_and_hashes, quirks_mode)
|
self.collect_invalidations_for(selector, quirks_mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clears this map, leaving it empty.
|
/// Clears this map, leaving it empty.
|
||||||
|
@ -214,13 +202,12 @@ impl InvalidationMap {
|
||||||
|
|
||||||
fn collect_invalidations_for(
|
fn collect_invalidations_for(
|
||||||
&mut self,
|
&mut self,
|
||||||
selector_and_hashes: &SelectorAndHashes<SelectorImpl>,
|
selector: &Selector<SelectorImpl>,
|
||||||
quirks_mode: QuirksMode)
|
quirks_mode: QuirksMode)
|
||||||
{
|
{
|
||||||
debug!("InvalidationMap::collect_invalidations_for({:?})",
|
debug!("InvalidationMap::collect_invalidations_for({:?})", selector);
|
||||||
selector_and_hashes.selector);
|
|
||||||
|
|
||||||
let mut iter = selector_and_hashes.selector.iter();
|
let mut iter = selector.iter();
|
||||||
let mut combinator;
|
let mut combinator;
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
|
|
||||||
|
@ -249,22 +236,6 @@ impl InvalidationMap {
|
||||||
index += 1; // Account for the simple selector.
|
index += 1; // Account for the simple selector.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reuse the bloom hashes if this is the base selector. Otherwise,
|
|
||||||
// rebuild them.
|
|
||||||
let mut hashes = None;
|
|
||||||
|
|
||||||
let mut get_hashes = || -> AncestorHashes {
|
|
||||||
if hashes.is_none() {
|
|
||||||
hashes = Some(if sequence_start == 0 {
|
|
||||||
selector_and_hashes.hashes.clone()
|
|
||||||
} else {
|
|
||||||
let seq_iter = selector_and_hashes.selector.iter_from(sequence_start);
|
|
||||||
AncestorHashes::from_iter(seq_iter)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
hashes.clone().unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
self.has_id_attribute_selectors |= compound_visitor.has_id_attribute_selectors;
|
self.has_id_attribute_selectors |= compound_visitor.has_id_attribute_selectors;
|
||||||
self.has_class_attribute_selectors |= compound_visitor.has_class_attribute_selectors;
|
self.has_class_attribute_selectors |= compound_visitor.has_class_attribute_selectors;
|
||||||
|
|
||||||
|
@ -273,9 +244,8 @@ impl InvalidationMap {
|
||||||
.entry(class, quirks_mode)
|
.entry(class, quirks_mode)
|
||||||
.or_insert_with(SelectorMap::new)
|
.or_insert_with(SelectorMap::new)
|
||||||
.insert(Dependency {
|
.insert(Dependency {
|
||||||
selector: selector_and_hashes.selector.clone(),
|
selector: selector.clone(),
|
||||||
selector_offset: sequence_start,
|
selector_offset: sequence_start,
|
||||||
hashes: get_hashes(),
|
|
||||||
}, quirks_mode);
|
}, quirks_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,9 +254,8 @@ impl InvalidationMap {
|
||||||
.entry(id, quirks_mode)
|
.entry(id, quirks_mode)
|
||||||
.or_insert_with(SelectorMap::new)
|
.or_insert_with(SelectorMap::new)
|
||||||
.insert(Dependency {
|
.insert(Dependency {
|
||||||
selector: selector_and_hashes.selector.clone(),
|
selector: selector.clone(),
|
||||||
selector_offset: sequence_start,
|
selector_offset: sequence_start,
|
||||||
hashes: get_hashes(),
|
|
||||||
}, quirks_mode);
|
}, quirks_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,9 +263,8 @@ impl InvalidationMap {
|
||||||
self.state_affecting_selectors
|
self.state_affecting_selectors
|
||||||
.insert(StateDependency {
|
.insert(StateDependency {
|
||||||
dep: Dependency {
|
dep: Dependency {
|
||||||
selector: selector_and_hashes.selector.clone(),
|
selector: selector.clone(),
|
||||||
selector_offset: sequence_start,
|
selector_offset: sequence_start,
|
||||||
hashes: get_hashes(),
|
|
||||||
},
|
},
|
||||||
state: compound_visitor.state,
|
state: compound_visitor.state,
|
||||||
}, quirks_mode);
|
}, quirks_mode);
|
||||||
|
@ -305,9 +273,8 @@ impl InvalidationMap {
|
||||||
if compound_visitor.other_attributes {
|
if compound_visitor.other_attributes {
|
||||||
self.other_attribute_affecting_selectors
|
self.other_attribute_affecting_selectors
|
||||||
.insert(Dependency {
|
.insert(Dependency {
|
||||||
selector: selector_and_hashes.selector.clone(),
|
selector: selector.clone(),
|
||||||
selector_offset: sequence_start,
|
selector_offset: sequence_start,
|
||||||
hashes: get_hashes(),
|
|
||||||
}, quirks_mode);
|
}, quirks_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -762,14 +762,14 @@ impl<'a, 'b: 'a, E> InvalidationCollector<'a, 'b, E>
|
||||||
let matched_then =
|
let matched_then =
|
||||||
matches_selector(&dependency.selector,
|
matches_selector(&dependency.selector,
|
||||||
dependency.selector_offset,
|
dependency.selector_offset,
|
||||||
&dependency.hashes,
|
None,
|
||||||
&self.wrapper,
|
&self.wrapper,
|
||||||
&mut then_context,
|
&mut then_context,
|
||||||
&mut |_, _| {});
|
&mut |_, _| {});
|
||||||
let matches_now =
|
let matches_now =
|
||||||
matches_selector(&dependency.selector,
|
matches_selector(&dependency.selector,
|
||||||
dependency.selector_offset,
|
dependency.selector_offset,
|
||||||
&dependency.hashes,
|
None,
|
||||||
&self.element,
|
&self.element,
|
||||||
&mut now_context,
|
&mut now_context,
|
||||||
&mut |_, _| {});
|
&mut |_, _| {});
|
||||||
|
@ -802,7 +802,7 @@ impl<'a, 'b: 'a, E> InvalidationCollector<'a, 'b, E>
|
||||||
let matched_then =
|
let matched_then =
|
||||||
matches_selector(&dependency.selector,
|
matches_selector(&dependency.selector,
|
||||||
dependency.selector_offset,
|
dependency.selector_offset,
|
||||||
&dependency.hashes,
|
None,
|
||||||
&self.wrapper,
|
&self.wrapper,
|
||||||
&mut then_context,
|
&mut then_context,
|
||||||
&mut |_, _| {});
|
&mut |_, _| {});
|
||||||
|
@ -811,7 +811,7 @@ impl<'a, 'b: 'a, E> InvalidationCollector<'a, 'b, E>
|
||||||
let matches_now =
|
let matches_now =
|
||||||
matches_selector(&dependency.selector,
|
matches_selector(&dependency.selector,
|
||||||
dependency.selector_offset,
|
dependency.selector_offset,
|
||||||
&dependency.hashes,
|
None,
|
||||||
&self.element,
|
&self.element,
|
||||||
&mut now_context,
|
&mut now_context,
|
||||||
&mut |_, _| {});
|
&mut |_, _| {});
|
||||||
|
|
|
@ -282,8 +282,8 @@ impl StylesheetInvalidationSet {
|
||||||
match *rule {
|
match *rule {
|
||||||
Style(ref lock) => {
|
Style(ref lock) => {
|
||||||
let style_rule = lock.read_with(guard);
|
let style_rule = lock.read_with(guard);
|
||||||
for selector_and_hashes in &style_rule.selectors.0 {
|
for selector in &style_rule.selectors.0 {
|
||||||
self.collect_scopes(&selector_and_hashes.selector);
|
self.collect_scopes(selector);
|
||||||
if self.fully_invalid {
|
if self.fully_invalid {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,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, SelectorAndHashes, SelectorIter};
|
use selectors::parser::{Component, Combinator, SelectorIter};
|
||||||
use selectors::parser::LocalName as LocalNameSelector;
|
use selectors::parser::LocalName as LocalNameSelector;
|
||||||
use smallvec::VecLike;
|
use smallvec::VecLike;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -26,19 +26,6 @@ use stylist::Rule;
|
||||||
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) -> SelectorIter<SelectorImpl>;
|
fn selector(&self) -> SelectorIter<SelectorImpl>;
|
||||||
|
|
||||||
/// Gets the ancestor hashes associated with the selector.
|
|
||||||
fn hashes(&self) -> &AncestorHashes;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SelectorMapEntry for SelectorAndHashes<SelectorImpl> {
|
|
||||||
fn selector(&self) -> SelectorIter<SelectorImpl> {
|
|
||||||
self.selector.iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hashes(&self) -> &AncestorHashes {
|
|
||||||
&self.hashes
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Map element data to selector-providing objects for which the last simple
|
/// Map element data to selector-providing objects for which the last simple
|
||||||
|
@ -65,7 +52,7 @@ impl SelectorMapEntry for SelectorAndHashes<SelectorImpl> {
|
||||||
/// TODO: Tune the initial capacity of the HashMap
|
/// TODO: Tune the initial capacity of the HashMap
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct SelectorMap<T: SelectorMapEntry> {
|
pub struct SelectorMap<T> {
|
||||||
/// A hash from an ID to rules which contain that ID selector.
|
/// A hash from an ID to rules which contain that ID selector.
|
||||||
pub id_hash: MaybeCaseInsensitiveHashMap<Atom, Vec<T>>,
|
pub id_hash: MaybeCaseInsensitiveHashMap<Atom, Vec<T>>,
|
||||||
/// A hash from a class name to rules which contain that class selector.
|
/// A hash from a class name to rules which contain that class selector.
|
||||||
|
@ -83,7 +70,7 @@ fn sort_by_key<T, F: Fn(&T) -> K, K: Ord>(v: &mut [T], f: F) {
|
||||||
sort_by(v, |a, b| f(a).cmp(&f(b)))
|
sort_by(v, |a, b| f(a).cmp(&f(b)))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: SelectorMapEntry> SelectorMap<T> {
|
impl<T> SelectorMap<T> {
|
||||||
/// Trivially constructs an empty `SelectorMap`.
|
/// Trivially constructs an empty `SelectorMap`.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
SelectorMap {
|
SelectorMap {
|
||||||
|
@ -209,7 +196,7 @@ impl SelectorMap<Rule> {
|
||||||
for rule in rules {
|
for rule in rules {
|
||||||
if matches_selector(&rule.selector,
|
if matches_selector(&rule.selector,
|
||||||
0,
|
0,
|
||||||
&rule.hashes,
|
Some(&rule.hashes),
|
||||||
element,
|
element,
|
||||||
context,
|
context,
|
||||||
flags_setter) {
|
flags_setter) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ use selectors::attr::NamespaceConstraint;
|
||||||
use selectors::bloom::BloomFilter;
|
use selectors::bloom::BloomFilter;
|
||||||
use selectors::matching::{ElementSelectorFlags, matches_selector, MatchingContext, MatchingMode};
|
use selectors::matching::{ElementSelectorFlags, matches_selector, MatchingContext, MatchingMode};
|
||||||
use selectors::matching::VisitedHandlingMode;
|
use selectors::matching::VisitedHandlingMode;
|
||||||
use selectors::parser::{AncestorHashes, Combinator, Component, Selector, SelectorAndHashes};
|
use selectors::parser::{AncestorHashes, Combinator, Component, Selector};
|
||||||
use selectors::parser::{SelectorIter, SelectorMethods};
|
use selectors::parser::{SelectorIter, SelectorMethods};
|
||||||
use selectors::sink::Push;
|
use selectors::sink::Push;
|
||||||
use selectors::visitor::SelectorVisitor;
|
use selectors::visitor::SelectorVisitor;
|
||||||
|
@ -478,10 +478,10 @@ impl Stylist {
|
||||||
CssRule::Style(ref locked) => {
|
CssRule::Style(ref locked) => {
|
||||||
let style_rule = locked.read_with(&guard);
|
let style_rule = locked.read_with(&guard);
|
||||||
self.num_declarations += style_rule.block.read_with(&guard).len();
|
self.num_declarations += style_rule.block.read_with(&guard).len();
|
||||||
for selector_and_hashes in &style_rule.selectors.0 {
|
for selector in &style_rule.selectors.0 {
|
||||||
self.num_selectors += 1;
|
self.num_selectors += 1;
|
||||||
|
|
||||||
let map = if let Some(pseudo) = selector_and_hashes.selector.pseudo_element() {
|
let map = if let Some(pseudo) = selector.pseudo_element() {
|
||||||
self.pseudos_map
|
self.pseudos_map
|
||||||
.entry(pseudo.canonical())
|
.entry(pseudo.canonical())
|
||||||
.or_insert_with(PerPseudoElementSelectorMap::new)
|
.or_insert_with(PerPseudoElementSelectorMap::new)
|
||||||
|
@ -490,25 +490,26 @@ impl Stylist {
|
||||||
self.element_map.borrow_for_origin(&origin)
|
self.element_map.borrow_for_origin(&origin)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let hashes = AncestorHashes::new(&selector);
|
||||||
map.insert(
|
map.insert(
|
||||||
Rule::new(selector_and_hashes.selector.clone(),
|
Rule::new(selector.clone(),
|
||||||
selector_and_hashes.hashes.clone(),
|
hashes.clone(),
|
||||||
locked.clone(),
|
locked.clone(),
|
||||||
self.rules_source_order),
|
self.rules_source_order),
|
||||||
self.quirks_mode);
|
self.quirks_mode);
|
||||||
|
|
||||||
self.invalidation_map.note_selector(selector_and_hashes, self.quirks_mode);
|
self.invalidation_map.note_selector(selector, self.quirks_mode);
|
||||||
if needs_revalidation(&selector_and_hashes.selector) {
|
if needs_revalidation(&selector) {
|
||||||
self.selectors_for_cache_revalidation.insert(
|
self.selectors_for_cache_revalidation.insert(
|
||||||
RevalidationSelectorAndHashes::new(&selector_and_hashes),
|
RevalidationSelectorAndHashes::new(&selector, &hashes),
|
||||||
self.quirks_mode);
|
self.quirks_mode);
|
||||||
}
|
}
|
||||||
selector_and_hashes.selector.visit(&mut AttributeAndStateDependencyVisitor {
|
selector.visit(&mut AttributeAndStateDependencyVisitor {
|
||||||
attribute_dependencies: &mut self.attribute_dependencies,
|
attribute_dependencies: &mut self.attribute_dependencies,
|
||||||
style_attribute_dependency: &mut self.style_attribute_dependency,
|
style_attribute_dependency: &mut self.style_attribute_dependency,
|
||||||
state_dependencies: &mut self.state_dependencies,
|
state_dependencies: &mut self.state_dependencies,
|
||||||
});
|
});
|
||||||
selector_and_hashes.selector.visit(&mut MappedIdVisitor {
|
selector.visit(&mut MappedIdVisitor {
|
||||||
mapped_ids: &mut self.mapped_ids,
|
mapped_ids: &mut self.mapped_ids,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1302,7 +1303,7 @@ impl Stylist {
|
||||||
*element, self.quirks_mode, &mut |selector_and_hashes| {
|
*element, self.quirks_mode, &mut |selector_and_hashes| {
|
||||||
results.push(matches_selector(&selector_and_hashes.selector,
|
results.push(matches_selector(&selector_and_hashes.selector,
|
||||||
selector_and_hashes.selector_offset,
|
selector_and_hashes.selector_offset,
|
||||||
&selector_and_hashes.hashes,
|
Some(&selector_and_hashes.hashes),
|
||||||
element,
|
element,
|
||||||
&mut matching_context,
|
&mut matching_context,
|
||||||
flags_setter));
|
flags_setter));
|
||||||
|
@ -1431,12 +1432,12 @@ struct RevalidationSelectorAndHashes {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RevalidationSelectorAndHashes {
|
impl RevalidationSelectorAndHashes {
|
||||||
fn new(selector_and_hashes: &SelectorAndHashes<SelectorImpl>) -> Self {
|
fn new(selector: &Selector<SelectorImpl>, hashes: &AncestorHashes) -> Self {
|
||||||
// We basically want to check whether the first combinator is a
|
// We basically want to check whether the first combinator is a
|
||||||
// pseudo-element combinator. If it is, we want to use the offset one
|
// pseudo-element combinator. If it is, we want to use the offset one
|
||||||
// past it. Otherwise, our offset is 0.
|
// past it. Otherwise, our offset is 0.
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
let mut iter = selector_and_hashes.selector.iter();
|
let mut iter = selector.iter();
|
||||||
|
|
||||||
// First skip over the first ComplexSelector. We can't check what sort
|
// First skip over the first ComplexSelector. We can't check what sort
|
||||||
// of combinator we have until we do that.
|
// of combinator we have until we do that.
|
||||||
|
@ -1450,9 +1451,9 @@ impl RevalidationSelectorAndHashes {
|
||||||
};
|
};
|
||||||
|
|
||||||
RevalidationSelectorAndHashes {
|
RevalidationSelectorAndHashes {
|
||||||
selector: selector_and_hashes.selector.clone(),
|
selector: selector.clone(),
|
||||||
selector_offset: offset,
|
selector_offset: offset,
|
||||||
hashes: selector_and_hashes.hashes.clone(),
|
hashes: hashes.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1461,10 +1462,6 @@ impl SelectorMapEntry for RevalidationSelectorAndHashes {
|
||||||
fn selector(&self) -> SelectorIter<SelectorImpl> {
|
fn selector(&self) -> SelectorIter<SelectorImpl> {
|
||||||
self.selector.iter_from(self.selector_offset)
|
self.selector.iter_from(self.selector_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hashes(&self) -> &AncestorHashes {
|
|
||||||
&self.hashes
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visitor to determine whether a selector requires cache revalidation.
|
/// Visitor to determine whether a selector requires cache revalidation.
|
||||||
|
@ -1609,10 +1606,6 @@ impl SelectorMapEntry for Rule {
|
||||||
fn selector(&self) -> SelectorIter<SelectorImpl> {
|
fn selector(&self) -> SelectorIter<SelectorImpl> {
|
||||||
self.selector.iter()
|
self.selector.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hashes(&self) -> &AncestorHashes {
|
|
||||||
&self.hashes
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rule {
|
impl Rule {
|
||||||
|
|
|
@ -1263,7 +1263,7 @@ pub extern "C" fn Servo_StyleRule_GetSelectorTextAtIndex(rule: RawServoStyleRule
|
||||||
if index >= rule.selectors.0.len() {
|
if index >= rule.selectors.0.len() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rule.selectors.0[index].selector.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
rule.selectors.0[index].to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1287,7 +1287,7 @@ pub extern "C" fn Servo_StyleRule_GetSpecificityAtIndex(
|
||||||
*specificity = 0;
|
*specificity = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*specificity = rule.selectors.0[index].selector.specificity() as u64;
|
*specificity = rule.selectors.0[index].specificity() as u64;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1302,14 +1302,14 @@ pub extern "C" fn Servo_StyleRule_SelectorMatchesElement(rule: RawServoStyleRule
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let selector_and_hashes = &rule.selectors.0[index];
|
let selector = &rule.selectors.0[index];
|
||||||
let mut matching_mode = MatchingMode::Normal;
|
let mut matching_mode = MatchingMode::Normal;
|
||||||
|
|
||||||
match PseudoElement::from_pseudo_type(pseudo_type) {
|
match PseudoElement::from_pseudo_type(pseudo_type) {
|
||||||
Some(pseudo) => {
|
Some(pseudo) => {
|
||||||
// We need to make sure that the requested pseudo element type
|
// We need to make sure that the requested pseudo element type
|
||||||
// matches the selector pseudo element type before proceeding.
|
// matches the selector pseudo element type before proceeding.
|
||||||
match selector_and_hashes.selector.pseudo_element() {
|
match selector.pseudo_element() {
|
||||||
Some(selector_pseudo) if *selector_pseudo == pseudo => {
|
Some(selector_pseudo) if *selector_pseudo == pseudo => {
|
||||||
matching_mode = MatchingMode::ForStatelessPseudoElement
|
matching_mode = MatchingMode::ForStatelessPseudoElement
|
||||||
},
|
},
|
||||||
|
@ -1319,7 +1319,7 @@ pub extern "C" fn Servo_StyleRule_SelectorMatchesElement(rule: RawServoStyleRule
|
||||||
None => {
|
None => {
|
||||||
// Do not attempt to match if a pseudo element is requested and
|
// Do not attempt to match if a pseudo element is requested and
|
||||||
// this is not a pseudo element selector, or vice versa.
|
// this is not a pseudo element selector, or vice versa.
|
||||||
if selector_and_hashes.selector.has_pseudo_element() {
|
if selector.has_pseudo_element() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1327,8 +1327,7 @@ pub extern "C" fn Servo_StyleRule_SelectorMatchesElement(rule: RawServoStyleRule
|
||||||
|
|
||||||
let element = GeckoElement(element);
|
let element = GeckoElement(element);
|
||||||
let mut ctx = MatchingContext::new(matching_mode, None, element.owner_document_quirks_mode());
|
let mut ctx = MatchingContext::new(matching_mode, None, element.owner_document_quirks_mode());
|
||||||
matches_selector(&selector_and_hashes.selector, 0, &selector_and_hashes.hashes,
|
matches_selector(selector, 0, None, &element, &mut ctx, &mut |_, _| {})
|
||||||
&element, &mut ctx, &mut |_, _| {})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,11 @@
|
||||||
* 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 http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use style::invalidation::element::invalidation_map::Dependency;
|
||||||
use style::properties;
|
use style::properties;
|
||||||
|
|
||||||
|
size_of_test!(test_size_of_dependency, Dependency, 16);
|
||||||
|
|
||||||
size_of_test!(test_size_of_property_declaration, properties::PropertyDeclaration, 32);
|
size_of_test!(test_size_of_property_declaration, properties::PropertyDeclaration, 32);
|
||||||
|
|
||||||
// This is huge, but we allocate it on the stack and then never move it,
|
// This is huge, but we allocate it on the stack and then never move it,
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
use cssparser::SourceLocation;
|
use cssparser::SourceLocation;
|
||||||
use euclid::TypedSize2D;
|
use euclid::TypedSize2D;
|
||||||
use html5ever::LocalName;
|
use html5ever::LocalName;
|
||||||
|
use selectors::parser::{AncestorHashes, Selector};
|
||||||
use selectors::parser::LocalName as LocalNameSelector;
|
use selectors::parser::LocalName as LocalNameSelector;
|
||||||
use selectors::parser::Selector;
|
|
||||||
use servo_atoms::Atom;
|
use servo_atoms::Atom;
|
||||||
use style::context::QuirksMode;
|
use style::context::QuirksMode;
|
||||||
use style::media_queries::{Device, MediaType};
|
use style::media_queries::{Device, MediaType};
|
||||||
|
@ -45,7 +45,7 @@ fn get_mock_rules(css_selectors: &[&str]) -> (Vec<Vec<Rule>>, SharedRwLock) {
|
||||||
let guard = shared_lock.read();
|
let guard = shared_lock.read();
|
||||||
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::new(s.selector.clone(), s.hashes.clone(), locked.clone(), i as u32)
|
Rule::new(s.clone(), AncestorHashes::new(s), locked.clone(), i as u32)
|
||||||
}).collect()
|
}).collect()
|
||||||
}).collect(), shared_lock)
|
}).collect(), shared_lock)
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ fn parse_selectors(selectors: &[&str]) -> Vec<Selector<SelectorImpl>> {
|
||||||
.map(|x| SelectorParser::parse_author_origin_no_namespace(x).unwrap().0
|
.map(|x| SelectorParser::parse_author_origin_no_namespace(x).unwrap().0
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.nth(0)
|
.nth(0)
|
||||||
.unwrap().selector)
|
.unwrap())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче