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() {
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();
}
}