diff options
author | Bobby Holley <bobbyholley@gmail.com> | 2015-11-05 09:58:06 -0800 |
---|---|---|
committer | Bobby Holley <bobbyholley@gmail.com> | 2015-11-10 11:57:24 -0800 |
commit | 7fa79366576751fa6d032091ea54698263783d5d (patch) | |
tree | 1eacd1b76fe400d33613afa5ff55e1d8cd0ae3ae /components/script/dom/element.rs | |
parent | 47744d95add56352ab5d0631d3dd5e054aad3849 (diff) | |
download | servo-7fa79366576751fa6d032091ea54698263783d5d.tar.gz servo-7fa79366576751fa6d032091ea54698263783d5d.zip |
Implement attribute restyle hints.
Fixes #6942.
Diffstat (limited to 'components/script/dom/element.rs')
-rw-r--r-- | components/script/dom/element.rs | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 829383a4a62..4d0cf6fea54 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -65,6 +65,7 @@ use html5ever::serialize::TraversalScope; use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode}; use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks}; use selectors::matching::{DeclarationBlock, matches}; +use selectors::matching::{common_style_affecting_attributes, rare_style_affecting_attributes}; use selectors::parser::{AttrSelector, NamespaceConstraint, parse_author_origin_selector_list_from_str}; use selectors::states::*; use smallvec::VecLike; @@ -851,6 +852,7 @@ impl Element { name: Atom, namespace: Namespace, prefix: Option<Atom>) { + self.will_mutate_attr(); let window = window_from_node(self); let in_empty_ns = namespace == ns!(""); let attr = Attr::new(&window, local_name, value, name, namespace, prefix, Some(self)); @@ -963,6 +965,7 @@ impl Element { let idx = self.attrs.borrow().iter().position(|attr| find(&attr)); idx.map(|idx| { + self.will_mutate_attr(); let attr = Root::from_ref(&*(*self.attrs.borrow())[idx]); self.attrs.borrow_mut().remove(idx); attr.set_owner(None); @@ -1075,6 +1078,11 @@ impl Element { assert!(&**local_name == local_name.to_ascii_lowercase()); self.set_attribute(local_name, AttrValue::UInt(DOMString(value.to_string()), value)); } + + pub fn will_mutate_attr(&self) { + let node = self.upcast::<Node>(); + node.owner_doc().element_attr_will_change(self); + } } impl ElementMethods for Element { @@ -1459,6 +1467,10 @@ impl ElementMethods for Element { } } +pub fn fragment_affecting_attributes() -> [Atom; 3] { + [atom!("width"), atom!("height"), atom!("src")] +} + impl VirtualMethods for Element { fn super_type(&self) -> Option<&VirtualMethods> { Some(self.upcast::<Node>() as &VirtualMethods) @@ -1468,18 +1480,16 @@ impl VirtualMethods for Element { self.super_type().unwrap().attribute_mutated(attr, mutation); let node = self.upcast::<Node>(); let doc = node.owner_doc(); - let damage = match attr.local_name() { + match attr.local_name() { &atom!(style) => { // Modifying the `style` attribute might change style. *self.style_attribute.borrow_mut() = mutation.new_value(attr).map(|value| { parse_style_attribute(&value, &doc.base_url()) }); - NodeDamage::NodeStyleDamaged - }, - &atom!(class) => { - // Modifying a class can change style. - NodeDamage::NodeStyleDamaged + if node.is_in_doc() { + doc.content_changed(node, NodeDamage::NodeStyleDamaged); + } }, &atom!(id) => { *self.id_attribute.borrow_mut() = @@ -1510,16 +1520,22 @@ impl VirtualMethods for Element { } } } - NodeDamage::NodeStyleDamaged }, - _ => { - // Modifying any other attribute might change arbitrary things. - NodeDamage::OtherNodeDamage + _ if attr.namespace() == &ns!("") => { + if fragment_affecting_attributes().iter().any(|a| a == attr.local_name()) || + common_style_affecting_attributes().iter().any(|a| &a.atom == attr.local_name()) || + rare_style_affecting_attributes().iter().any(|a| a == attr.local_name()) + { + doc.content_changed(node, NodeDamage::OtherNodeDamage); + } }, + _ => {}, }; - if node.is_in_doc() { - doc.content_changed(node, damage); - } + + // Make sure we rev the version even if we didn't dirty the node. If we + // don't do this, various attribute-dependent htmlcollections (like those + // generated by getElementsByClassName) might become stale. + node.rev_version(); } fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue { |