aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/node.rs
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2014-12-08 12:28:14 -0700
committerbors-servo <metajack+bors@gmail.com>2014-12-08 12:28:14 -0700
commit5c506f7a98368020c7936517f1d8e243c9556937 (patch)
tree315cf319f15a8ca92bc6807ee962443ad247ac8a /components/script/dom/node.rs
parentf18c18371d2bb5edde9d64e46b74bf01411afab3 (diff)
parentd3e4d293687d51504f68323228bfbab972aa0f2f (diff)
downloadservo-5c506f7a98368020c7936517f1d8e243c9556937.tar.gz
servo-5c506f7a98368020c7936517f1d8e243c9556937.zip
auto merge of #4194 : cgaebel/servo/incremental-reflow-fix, r=pcwalton
When inserting a node that was already dirtied, the dirtying logic would short circuit: "This node is already dirty? Great! Then its parents must be HAS_DIRTY_DESCENDANTS, too! Let's skip that step." This isn't appropriate when nodes move around the tree. In that case, the node may be marked HAS_CHANGED, but ancestors may not yet have the HAS_DIRTY_DESCENDANTS flag set. This patch adds a `content_and_heritage_changed` hook in the document, to deal with these cases appropriately.
Diffstat (limited to 'components/script/dom/node.rs')
-rw-r--r--components/script/dom/node.rs25
1 files changed, 21 insertions, 4 deletions
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index ef655cc1bc3..eb9b263dc73 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -288,7 +288,7 @@ impl<'a> PrivateNodeHelpers for JSRef<'a, Node> {
let parent = self.parent_node().root();
parent.map(|parent| vtable_for(&*parent).child_inserted(self));
- document.content_changed(self);
+ document.content_and_heritage_changed(self);
}
// http://dom.spec.whatwg.org/#node-is-removed
@@ -465,6 +465,16 @@ pub trait NodeHelpers<'a> {
/// descendants as `IS_DIRTY`.
fn dirty(self);
+ /// Similar to `dirty`, but will always walk the ancestors to mark them dirty,
+ /// too. This is useful when a node is reparented. The node will frequently
+ /// already be marked as `changed` to skip double-dirties, but the ancestors
+ /// still need to be marked as `HAS_DIRTY_DESCENDANTS`.
+ ///
+ /// See #4170
+ fn force_dirty_ancestors(self);
+
+ fn dirty_impl(self, force_ancestors: bool);
+
fn dump(self);
fn dump_indent(self, indent: uint);
fn debug_str(self) -> String;
@@ -646,11 +656,19 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
self.set_flag(HAS_DIRTY_DESCENDANTS, state)
}
+ fn force_dirty_ancestors(self) {
+ self.dirty_impl(true)
+ }
+
fn dirty(self) {
+ self.dirty_impl(false)
+ }
+
+ fn dirty_impl(self, force_ancestors: bool) {
// 1. Dirty self.
self.set_has_changed(true);
- if self.get_is_dirty() {
+ if self.get_is_dirty() && !force_ancestors {
return
}
@@ -684,7 +702,7 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
// 4. Dirty ancestors.
for ancestor in self.ancestors() {
- if ancestor.get_has_dirty_descendants() { break }
+ if !force_ancestors && ancestor.get_has_dirty_descendants() { break }
ancestor.set_has_dirty_descendants(true);
}
}
@@ -1424,7 +1442,6 @@ impl Node {
// http://dom.spec.whatwg.org/#concept-node-replace-all
fn replace_all(node: Option<JSRef<Node>>, parent: JSRef<Node>) {
-
// Step 1.
match node {
Some(node) => {