diff options
author | bors-servo <metajack+bors@gmail.com> | 2014-12-08 12:28:14 -0700 |
---|---|---|
committer | bors-servo <metajack+bors@gmail.com> | 2014-12-08 12:28:14 -0700 |
commit | 5c506f7a98368020c7936517f1d8e243c9556937 (patch) | |
tree | 315cf319f15a8ca92bc6807ee962443ad247ac8a /components/script/dom/node.rs | |
parent | f18c18371d2bb5edde9d64e46b74bf01411afab3 (diff) | |
parent | d3e4d293687d51504f68323228bfbab972aa0f2f (diff) | |
download | servo-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.rs | 25 |
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) => { |