aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2014-10-14 16:51:30 -0600
committerbors-servo <metajack+bors@gmail.com>2014-10-14 16:51:30 -0600
commit56989b8dec4aa95a3b484d45f15b23f9b3daaf13 (patch)
tree91c6c430b9a9513be320bc69d79b63f1523f2af5 /components/script
parente2d7777c41135b71293c195d2a9d7a1bc2afd0ca (diff)
parentf552e2f7501337fae76ad66401a1e011d00211df (diff)
downloadservo-56989b8dec4aa95a3b484d45f15b23f9b3daaf13.tar.gz
servo-56989b8dec4aa95a3b484d45f15b23f9b3daaf13.zip
auto merge of #3640 : cgaebel/servo/incremental-flow-construction, r=pcwalton
This also hides the not-yet-working parts of incremental reflow behind a runtime flag. As I get the failing reftests passing, I'll send pull requests for them one by one.
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/node.rs68
1 files changed, 51 insertions, 17 deletions
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index dc6351c9954..5b2e3191ce6 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -135,18 +135,24 @@ bitflags! {
static InDisabledState = 0x04,
#[doc = "Specifies whether this node is in enabled state."]
static InEnabledState = 0x08,
- #[doc = "Specifies whether this node has changed since the last reflow."]
- static IsDirty = 0x10,
+ #[doc = "Specifies whether this node _must_ be reflowed regardless of style differences."]
+ static HasChanged = 0x10,
+ #[doc = "Specifies whether this node needs style recalc on next reflow."]
+ static IsDirty = 0x20,
+ #[doc = "Specifies whether this node has siblings (inclusive of itself) which \
+ changed since the last reflow."]
+ static HasDirtySiblings = 0x40,
#[doc = "Specifies whether this node has descendants (inclusive of itself) which \
have changed since the last reflow."]
- static HasDirtyDescendants = 0x20,
+ static HasDirtyDescendants = 0x80,
}
}
impl NodeFlags {
pub fn new(type_id: NodeTypeId) -> NodeFlags {
+ let dirty = HasChanged | IsDirty | HasDirtySiblings | HasDirtyDescendants;
match type_id {
- DocumentNodeTypeId => IsInDoc | IsDirty,
+ DocumentNodeTypeId => IsInDoc | dirty,
// The following elements are enabled by default.
ElementNodeTypeId(HTMLButtonElementTypeId) |
ElementNodeTypeId(HTMLInputElementTypeId) |
@@ -155,8 +161,8 @@ impl NodeFlags {
ElementNodeTypeId(HTMLOptGroupElementTypeId) |
ElementNodeTypeId(HTMLOptionElementTypeId) |
//ElementNodeTypeId(HTMLMenuItemElementTypeId) |
- ElementNodeTypeId(HTMLFieldSetElementTypeId) => InEnabledState | IsDirty,
- _ => IsDirty,
+ ElementNodeTypeId(HTMLFieldSetElementTypeId) => InEnabledState | dirty,
+ _ => dirty,
}
}
}
@@ -414,9 +420,15 @@ pub trait NodeHelpers<'a> {
fn get_enabled_state(self) -> bool;
fn set_enabled_state(self, state: bool);
+ fn get_has_changed(self) -> bool;
+ fn set_has_changed(self, state: bool);
+
fn get_is_dirty(self) -> bool;
fn set_is_dirty(self, state: bool);
+ fn get_has_dirty_siblings(self) -> bool;
+ fn set_has_dirty_siblings(self, state: bool);
+
fn get_has_dirty_descendants(self) -> bool;
fn set_has_dirty_descendants(self, state: bool);
@@ -574,6 +586,14 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
self.set_flag(InEnabledState, state)
}
+ fn get_has_changed(self) -> bool {
+ self.get_flag(HasChanged)
+ }
+
+ fn set_has_changed(self, state: bool) {
+ self.set_flag(HasChanged, state)
+ }
+
fn get_is_dirty(self) -> bool {
self.get_flag(IsDirty)
}
@@ -582,6 +602,14 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
self.set_flag(IsDirty, state)
}
+ fn get_has_dirty_siblings(self) -> bool {
+ self.get_flag(HasDirtySiblings)
+ }
+
+ fn set_has_dirty_siblings(self, state: bool) {
+ self.set_flag(HasDirtySiblings, state)
+ }
+
fn get_has_dirty_descendants(self) -> bool {
self.get_flag(HasDirtyDescendants)
}
@@ -591,24 +619,24 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
}
fn dirty(self) {
- // 1. Dirty descendants.
+ // 1. Dirty self.
+ self.set_has_changed(true);
+
+ // 2. Dirty descendants.
fn dirty_subtree(node: JSRef<Node>) {
- node.set_is_dirty(true);
+ // Stop if this subtree is already dirty.
+ if node.get_is_dirty() { return }
- let mut has_dirty_descendants = false;
+ node.set_flag(IsDirty | HasDirtySiblings | HasDirtyDescendants, true);
for kid in node.children() {
dirty_subtree(kid);
- has_dirty_descendants = true;
- }
-
- if has_dirty_descendants {
- node.set_has_dirty_descendants(true);
}
}
+
dirty_subtree(self);
- // 2. Dirty siblings.
+ // 3. Dirty siblings.
//
// TODO(cgaebel): This is a very conservative way to account for sibling
// selectors. Maybe we can do something smarter in the future.
@@ -619,10 +647,10 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
};
for sibling in parent.root().children() {
- sibling.set_is_dirty(true);
+ sibling.set_has_dirty_siblings(true);
}
- // 3. Dirty ancestors.
+ // 4. Dirty ancestors.
for ancestor in self.ancestors() {
if ancestor.get_has_dirty_descendants() { break }
ancestor.set_has_dirty_descendants(true);
@@ -2249,9 +2277,15 @@ impl<'a> style::TNode<'a, JSRef<'a, Element>> for JSRef<'a, Node> {
elem.unwrap().html_element_in_html_document()
}
+ fn has_changed(self) -> bool { self.get_has_changed() }
+ unsafe fn set_changed(self, value: bool) { self.set_has_changed(value) }
+
fn is_dirty(self) -> bool { self.get_is_dirty() }
unsafe fn set_dirty(self, value: bool) { self.set_is_dirty(value) }
+ fn has_dirty_siblings(self) -> bool { self.get_has_dirty_siblings() }
+ unsafe fn set_dirty_siblings(self, value: bool) { self.set_has_dirty_siblings(value) }
+
fn has_dirty_descendants(self) -> bool { self.get_has_dirty_descendants() }
unsafe fn set_dirty_descendants(self, value: bool) { self.set_has_dirty_descendants(value) }
}