mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Set selector flags when matching elements against revalidation selectors.
This commit is contained in:
parent
1663bf6e5d
commit
d50946933d
2 changed files with 41 additions and 13 deletions
|
@ -108,7 +108,8 @@ fn element_matches_candidate<E: TElement>(element: &E,
|
||||||
candidate_element: &E,
|
candidate_element: &E,
|
||||||
shared: &SharedStyleContext,
|
shared: &SharedStyleContext,
|
||||||
bloom: &BloomFilter,
|
bloom: &BloomFilter,
|
||||||
info: &mut CurrentElementInfo)
|
info: &mut CurrentElementInfo,
|
||||||
|
tasks: &mut Vec<SequentialTask<E>>)
|
||||||
-> Result<ComputedStyle, CacheMiss> {
|
-> Result<ComputedStyle, CacheMiss> {
|
||||||
macro_rules! miss {
|
macro_rules! miss {
|
||||||
($miss: ident) => {
|
($miss: ident) => {
|
||||||
|
@ -156,7 +157,8 @@ fn element_matches_candidate<E: TElement>(element: &E,
|
||||||
miss!(PresHints)
|
miss!(PresHints)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !revalidate(element, candidate, candidate_element, shared, bloom, info) {
|
if !revalidate(element, candidate, candidate_element,
|
||||||
|
shared, bloom, info, tasks) {
|
||||||
miss!(Revalidation)
|
miss!(Revalidation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +205,8 @@ fn revalidate<E: TElement>(element: &E,
|
||||||
candidate_element: &E,
|
candidate_element: &E,
|
||||||
shared: &SharedStyleContext,
|
shared: &SharedStyleContext,
|
||||||
bloom: &BloomFilter,
|
bloom: &BloomFilter,
|
||||||
info: &mut CurrentElementInfo)
|
info: &mut CurrentElementInfo,
|
||||||
|
tasks: &mut Vec<SequentialTask<E>>)
|
||||||
-> bool {
|
-> bool {
|
||||||
// NB: We could avoid matching ancestor selectors entirely (rather than
|
// NB: We could avoid matching ancestor selectors entirely (rather than
|
||||||
// just depending on the bloom filter), at the expense of some complexity.
|
// just depending on the bloom filter), at the expense of some complexity.
|
||||||
|
@ -217,13 +220,33 @@ fn revalidate<E: TElement>(element: &E,
|
||||||
let stylist = &shared.stylist;
|
let stylist = &shared.stylist;
|
||||||
|
|
||||||
if info.revalidation_match_results.is_none() {
|
if info.revalidation_match_results.is_none() {
|
||||||
|
// It's important to set the selector flags. Otherwise, if we succeed in
|
||||||
|
// sharing the style, we may not set the slow selector flags for the
|
||||||
|
// right elements (which may not necessarily be |element|), causing missed
|
||||||
|
// restyles after future DOM mutations.
|
||||||
|
//
|
||||||
|
// Gecko's test_bug534804.html exercises this. A minimal testcase is:
|
||||||
|
// <style> #e:empty + span { ... } </style>
|
||||||
|
// <span id="e">
|
||||||
|
// <span></span>
|
||||||
|
// </span>
|
||||||
|
// <span></span>
|
||||||
|
//
|
||||||
|
// The style sharing cache will get a hit for the second span. When the
|
||||||
|
// child span is subsequently removed from the DOM, missing selector
|
||||||
|
// flags would cause us to miss the restyle on the second span.
|
||||||
|
let mut set_selector_flags = |el: &E, flags: ElementSelectorFlags| {
|
||||||
|
element.apply_selector_flags(tasks, el, flags);
|
||||||
|
};
|
||||||
info.revalidation_match_results =
|
info.revalidation_match_results =
|
||||||
Some(stylist.match_revalidation_selectors(element, bloom));
|
Some(stylist.match_revalidation_selectors(element, bloom,
|
||||||
|
&mut set_selector_flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
if candidate.revalidation_match_results.is_none() {
|
if candidate.revalidation_match_results.is_none() {
|
||||||
candidate.revalidation_match_results =
|
candidate.revalidation_match_results =
|
||||||
Some(stylist.match_revalidation_selectors(candidate_element, bloom));
|
Some(stylist.match_revalidation_selectors(candidate_element, bloom,
|
||||||
|
&mut |_, _| {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let for_element = info.revalidation_match_results.as_ref().unwrap();
|
let for_element = info.revalidation_match_results.as_ref().unwrap();
|
||||||
|
@ -670,11 +693,12 @@ trait PrivateMatchMethods: TElement {
|
||||||
candidate: &mut StyleSharingCandidate<Self>,
|
candidate: &mut StyleSharingCandidate<Self>,
|
||||||
shared: &SharedStyleContext,
|
shared: &SharedStyleContext,
|
||||||
bloom: &BloomFilter,
|
bloom: &BloomFilter,
|
||||||
info: &mut CurrentElementInfo)
|
info: &mut CurrentElementInfo,
|
||||||
|
tasks: &mut Vec<SequentialTask<Self>>)
|
||||||
-> Result<ComputedStyle, CacheMiss> {
|
-> Result<ComputedStyle, CacheMiss> {
|
||||||
let candidate_element = *candidate.element;
|
let candidate_element = *candidate.element;
|
||||||
element_matches_candidate(self, candidate, &candidate_element,
|
element_matches_candidate(self, candidate, &candidate_element,
|
||||||
shared, bloom, info)
|
shared, bloom, info, tasks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1024,13 +1048,15 @@ pub trait MatchMethods : TElement {
|
||||||
let current_element_info =
|
let current_element_info =
|
||||||
&mut context.thread_local.current_element_info.as_mut().unwrap();
|
&mut context.thread_local.current_element_info.as_mut().unwrap();
|
||||||
let bloom = context.thread_local.bloom_filter.filter();
|
let bloom = context.thread_local.bloom_filter.filter();
|
||||||
|
let tasks = &mut context.thread_local.tasks;
|
||||||
let mut should_clear_cache = false;
|
let mut should_clear_cache = false;
|
||||||
for (i, candidate) in cache.iter_mut().enumerate() {
|
for (i, candidate) in cache.iter_mut().enumerate() {
|
||||||
let sharing_result =
|
let sharing_result =
|
||||||
self.share_style_with_candidate_if_possible(candidate,
|
self.share_style_with_candidate_if_possible(candidate,
|
||||||
&context.shared,
|
&context.shared,
|
||||||
bloom,
|
bloom,
|
||||||
current_element_info);
|
current_element_info,
|
||||||
|
tasks);
|
||||||
match sharing_result {
|
match sharing_result {
|
||||||
Ok(shared_style) => {
|
Ok(shared_style) => {
|
||||||
// Yay, cache hit. Share the style.
|
// Yay, cache hit. Share the style.
|
||||||
|
|
|
@ -768,11 +768,13 @@ impl Stylist {
|
||||||
|
|
||||||
/// Computes the match results of a given element against the set of
|
/// Computes the match results of a given element against the set of
|
||||||
/// revalidation selectors.
|
/// revalidation selectors.
|
||||||
pub fn match_revalidation_selectors<E>(&self,
|
pub fn match_revalidation_selectors<E, F>(&self,
|
||||||
element: &E,
|
element: &E,
|
||||||
bloom: &BloomFilter)
|
bloom: &BloomFilter,
|
||||||
|
flags_setter: &mut F)
|
||||||
-> BitVec
|
-> BitVec
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
|
F: FnMut(&E, ElementSelectorFlags)
|
||||||
{
|
{
|
||||||
use selectors::matching::StyleRelations;
|
use selectors::matching::StyleRelations;
|
||||||
use selectors::matching::matches_complex_selector;
|
use selectors::matching::matches_complex_selector;
|
||||||
|
@ -786,7 +788,7 @@ impl Stylist {
|
||||||
element,
|
element,
|
||||||
Some(bloom),
|
Some(bloom),
|
||||||
&mut StyleRelations::empty(),
|
&mut StyleRelations::empty(),
|
||||||
&mut |_, _| {}));
|
flags_setter));
|
||||||
}
|
}
|
||||||
|
|
||||||
results
|
results
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue