Avoid recursion in clear_descendant_data.

MozReview-Commit-ID: LeMhhcKoLr9
This commit is contained in:
Bobby Holley 2017-08-15 16:29:16 -07:00
parent 99b4b7e960
commit 653107d6c4

View file

@ -509,7 +509,7 @@ where
if data.styles.is_display_none() { if data.styles.is_display_none() {
debug!("{:?} style is display:none - clearing data from descendants.", debug!("{:?} style is display:none - clearing data from descendants.",
element); element);
clear_descendant_data(element) unsafe { clear_descendant_data(element); }
} }
// Inform any paint worklets of changed style, to speculatively // Inform any paint worklets of changed style, to speculatively
@ -829,12 +829,18 @@ where
} }
} }
/// Clear style data for all the subtree under `el`. /// Clear style data for all the subtree under `root` (but not for root itself).
pub fn clear_descendant_data<E>(el: E) ///
/// 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 where
E: TElement, E: TElement,
{ {
for kid in el.as_node().traversal_children() { 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() { if let Some(kid) = kid.as_element() {
// We maintain an invariant that, if an element has data, all its // We maintain an invariant that, if an element has data, all its
// ancestors have data as well. // ancestors have data as well.
@ -842,13 +848,11 @@ where
// By consequence, any element without data has no descendants with // By consequence, any element without data has no descendants with
// data. // data.
if kid.get_data().is_some() { if kid.get_data().is_some() {
unsafe { kid.clear_data() }; kid.clear_data();
clear_descendant_data(kid); parents.push(kid);
} }
} }
} }
p.clear_descendants_bits();
unsafe {
el.clear_descendants_bits();
} }
} }