Track all node damage with PendingRestyles.

This commit is contained in:
Bobby Holley 2016-11-14 14:46:59 -08:00
parent 0547a6b313
commit f1043f6305
5 changed files with 68 additions and 44 deletions

View file

@ -477,7 +477,7 @@ impl Document {
}
pub fn content_and_heritage_changed(&self, node: &Node, damage: NodeDamage) {
node.force_dirty_ancestors(damage);
node.dirty(damage);
}
/// Reflows and disarms the timer if the reflow timer has expired.
@ -1990,12 +1990,12 @@ impl Document {
self.id_map.borrow().get(&id).map(|ref elements| Root::from_ref(&*(*elements)[0]))
}
fn ensure_pending_restyle(&self, el: &Element) -> RefMut<PendingRestyle> {
pub fn ensure_pending_restyle(&self, el: &Element) -> RefMut<PendingRestyle> {
let map = self.pending_restyles.borrow_mut();
RefMut::map(map, |m| m.entry(JS::from_ref(el)).or_insert_with(PendingRestyle::new))
}
fn ensure_snapshot(&self, el: &Element) -> RefMut<Snapshot> {
pub fn ensure_snapshot(&self, el: &Element) -> RefMut<Snapshot> {
let mut entry = self.ensure_pending_restyle(el);
if entry.snapshot.is_none() {
entry.snapshot = Some(Snapshot::new(el.html_element_in_html_document()));

View file

@ -84,13 +84,15 @@ use std::fmt;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
use style::dom::TRestyleDamage;
use style::element_state::*;
use style::matching::{common_style_affecting_attributes, rare_style_affecting_attributes};
use style::parser::ParserContextExtraData;
use style::properties::{DeclaredValue, Importance};
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
use style::properties::longhands::{background_image, border_spacing, font_family, font_size, overflow_x};
use style::selector_impl::{NonTSPseudoClass, ServoSelectorImpl};
use style::restyle_hints::RESTYLE_SELF;
use style::selector_impl::{NonTSPseudoClass, RestyleDamage, ServoSelectorImpl};
use style::selector_matching::ApplicableDeclarationBlock;
use style::sink::Push;
use style::values::CSSFloat;
@ -201,6 +203,19 @@ impl Element {
ElementBinding::Wrap)
}
pub fn restyle(&self, damage: NodeDamage) {
let doc = self.node.owner_doc();
let mut restyle = doc.ensure_pending_restyle(self);
// FIXME(bholley): I think we should probably only do this for
// NodeStyleDamaged, but I'm preserving existing behavior.
restyle.hint |= RESTYLE_SELF;
if damage == NodeDamage::OtherNodeDamage {
restyle.damage = RestyleDamage::rebuild_and_reflow();
}
}
// https://drafts.csswg.org/cssom-view/#css-layout-box
// Elements that have a computed value of the display property
// that is table-column or table-column-group

View file

@ -446,10 +446,6 @@ impl Node {
self.set_flag(HAS_DIRTY_DESCENDANTS, state)
}
pub fn force_dirty_ancestors(&self, damage: NodeDamage) {
self.dirty_impl(damage, true)
}
pub fn rev_version(&self) {
// The new version counter is 1 plus the max of the node's current version counter,
// its descendants version, and the document's version. Normally, this will just be
@ -464,30 +460,18 @@ impl Node {
}
pub fn dirty(&self, damage: NodeDamage) {
self.dirty_impl(damage, false)
}
pub fn dirty_impl(&self, damage: NodeDamage, force_ancestors: bool) {
// 0. Set version counter
self.rev_version();
// 1. Dirty self.
match damage {
NodeDamage::NodeStyleDamaged => {}
NodeDamage::OtherNodeDamage => self.set_has_changed(true),
if !self.is_in_doc() {
return;
}
if self.is_dirty() && !force_ancestors {
return
}
self.set_flag(IS_DIRTY, true);
// 4. Dirty ancestors.
for ancestor in self.ancestors() {
if !force_ancestors && ancestor.has_dirty_descendants() { break }
ancestor.set_has_dirty_descendants(true);
}
match self.type_id() {
NodeTypeId::CharacterData(CharacterDataTypeId::Text) =>
self.parent_node.get().unwrap().downcast::<Element>().unwrap().restyle(damage),
NodeTypeId::Element(_) =>
self.downcast::<Element>().unwrap().restyle(damage),
_ => {},
};
}
/// The maximum version number of this node's descendants, including itself