stylo: Make Servo_TraverseSubtree and Servo_AssertTreeIsClean output more useful info. r?bholley
draft
stylo: Make Servo_TraverseSubtree and Servo_AssertTreeIsClean output more useful info. r?bholley
MozReview-Commit-ID: FqBMdAouFGh
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -201,28 +201,35 @@ impl<N: TNode> Debug for ShowSubtreeData
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "DOM Subtree:")?;
fmt_subtree(f, &|f, n| fmt_with_data_and_primary_values(f, n), self.0, 1)
}
}
fn fmt_with_data<N: TNode>(f: &mut fmt::Formatter, n: N) -> fmt::Result {
if let Some(el) = n.as_element() {
- write!(f, "{:?} dd={} data={:?}", el, el.has_dirty_descendants(), el.borrow_data())
+ write!(
+ f, "{:?} dd={} aodd={} data={:?}",
+ el,
+ el.has_dirty_descendants(),
+ el.has_animation_only_dirty_descendants(),
+ el.borrow_data(),
+ )
} else {
write!(f, "{:?}", n)
}
}
fn fmt_with_data_and_primary_values<N: TNode>(f: &mut fmt::Formatter, n: N) -> fmt::Result {
if let Some(el) = n.as_element() {
let dd = el.has_dirty_descendants();
+ let aodd = el.has_animation_only_dirty_descendants();
let data = el.borrow_data();
let values = data.as_ref().and_then(|d| d.styles.get_primary());
- write!(f, "{:?} dd={} data={:?} values={:?}", el, dd, &data, values)
+ write!(f, "{:?} dd={} aodd={} data={:?} values={:?}", el, dd, aodd, &data, values)
} else {
write!(f, "{:?}", n)
}
}
fn fmt_subtree<F, N: TNode>(f: &mut fmt::Formatter, stringify: &F, n: N, indent: u32)
-> fmt::Result
where F: Fn(&mut fmt::Formatter, N) -> fmt::Result
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -255,27 +255,29 @@ fn traverse_subtree(element: GeckoElemen
}
}
/// Traverses the subtree rooted at `root` for restyling.
///
/// Returns whether a Gecko post-traversal (to perform lazy frame construction,
/// or consume any RestyleData, or drop any ElementData) is required.
#[no_mangle]
-pub extern "C" fn Servo_TraverseSubtree(root: RawGeckoElementBorrowed,
- raw_data: RawServoStyleSetBorrowed,
- snapshots: *const ServoElementSnapshotTable,
- raw_flags: ServoTraversalFlags)
- -> bool {
+pub extern "C" fn Servo_TraverseSubtree(
+ root: RawGeckoElementBorrowed,
+ raw_data: RawServoStyleSetBorrowed,
+ snapshots: *const ServoElementSnapshotTable,
+ raw_flags: ServoTraversalFlags
+) -> bool {
let traversal_flags = TraversalFlags::from_bits_truncate(raw_flags);
debug_assert!(!snapshots.is_null());
let element = GeckoElement(root);
debug!("Servo_TraverseSubtree (flags={:?})", traversal_flags);
+ debug!("{:?}", ShowSubtreeData(element.as_node()));
// It makes no sense to do an animation restyle when we're styling
// newly-inserted content.
if !traversal_flags.contains(traversal_flags::UnstyledOnly) {
let needs_animation_only_restyle =
element.has_animation_only_dirty_descendants() ||
element.has_animation_restyle_hints();
if needs_animation_only_restyle {
@@ -3306,16 +3308,18 @@ pub extern "C" fn Servo_AnimationValue_C
#[no_mangle]
pub extern "C" fn Servo_AssertTreeIsClean(root: RawGeckoElementBorrowed) {
if !cfg!(feature = "gecko_debug") {
panic!("Calling Servo_AssertTreeIsClean in release build");
}
let root = GeckoElement(root);
+ debug!("{:?}", ShowSubtreeData(root.as_node()));
+
fn assert_subtree_is_clean<'le>(el: GeckoElement<'le>) {
debug_assert!(!el.has_dirty_descendants() && !el.has_animation_only_dirty_descendants(),
"{:?} has still dirty bit {:?} or animation-only dirty bit {:?}",
el, el.has_dirty_descendants(), el.has_animation_only_dirty_descendants());
for child in el.as_node().traversal_children() {
if let Some(child) = child.as_element() {
assert_subtree_is_clean(child);
}