diff options
-rw-r--r-- | components/style/traversal.rs | 38 |
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(); } } |