aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/traversal.rs38
1 files changed, 21 insertions, 17 deletions
diff --git a/components/style/traversal.rs b/components/style/traversal.rs
index 37abedfc237..29e36eb29d4 100644
--- a/components/style/traversal.rs
+++ b/components/style/traversal.rs
@@ -509,7 +509,7 @@ where
if data.styles.is_display_none() {
debug!("{:?} style is display:none - clearing data from descendants.",
element);
- clear_descendant_data(element)
+ unsafe { clear_descendant_data(element); }
}
// Inform any paint worklets of changed style, to speculatively
@@ -829,26 +829,30 @@ where
}
}
-/// Clear style data for all the subtree under `el`.
-pub fn clear_descendant_data<E>(el: E)
+/// Clear style data for all the subtree under `root` (but not for root itself).
+///
+/// We use a list to avoid unbounded recursion, which we need to avoid in the
+/// parallel traversal because the rayon stacks are small.
+pub unsafe fn clear_descendant_data<E>(root: E)
where
E: TElement,
{
- for kid in el.as_node().traversal_children() {
- if let Some(kid) = kid.as_element() {
- // We maintain an invariant that, if an element has data, all its
- // ancestors have data as well.
- //
- // By consequence, any element without data has no descendants with
- // data.
- if kid.get_data().is_some() {
- unsafe { kid.clear_data() };
- clear_descendant_data(kid);
+ let mut parents = SmallVec::<[E; 32]>::new();
+ parents.push(root);
+ while let Some(p) = parents.pop() {
+ for kid in p.as_node().traversal_children() {
+ if let Some(kid) = kid.as_element() {
+ // We maintain an invariant that, if an element has data, all its
+ // ancestors have data as well.
+ //
+ // By consequence, any element without data has no descendants with
+ // data.
+ if kid.get_data().is_some() {
+ kid.clear_data();
+ parents.push(kid);
+ }
}
}
- }
-
- unsafe {
- el.clear_descendants_bits();
+ p.clear_descendants_bits();
}
}