aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/element.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/element.rs')
-rw-r--r--components/script/dom/element.rs42
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 {