mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Introduce VirtualMethods::attribute_mutated()
This replaces before_remove_attr(), after_remove_attr() and after_set_attr(). The virtual method takes the mutated attribute and an AttributeMutation value to disambiguate between "attribute is changed", "attribute is added" and "attribute is removed". In the case of "attribute is changed", the mutation value contains a reference to the old value of the mutated attribute, which is used to unregister outdated named elements when the "id" attribute is changed on an element. This greatly simplifies the handling of attributes, which in many cases don't have any specific behaviour whether they are removed or changed or added. It also fixes a few bugs where things were put in before_remove_attr() instead of after_remove_attr() (e.g. when removing an href attribute from a base element). A few helper functions in Element were also renamed and made private.
This commit is contained in:
parent
5672142042
commit
58e1bd0e57
27 changed files with 565 additions and 862 deletions
|
@ -9,7 +9,7 @@ use dom::bindings::global::GlobalRef;
|
|||
use dom::bindings::js::{JS, MutNullableHeap};
|
||||
use dom::bindings::js::{Root, RootedReference, LayoutJS};
|
||||
use dom::bindings::utils::{Reflector, reflect_dom_object};
|
||||
use dom::element::Element;
|
||||
use dom::element::{AttributeMutation, Element};
|
||||
use dom::virtualmethods::vtable_for;
|
||||
use dom::window::Window;
|
||||
|
||||
|
@ -23,12 +23,6 @@ use std::cell::Ref;
|
|||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
|
||||
#[derive(HeapSizeOf)]
|
||||
pub enum AttrSettingType {
|
||||
FirstSetAttr,
|
||||
ReplacedAttr,
|
||||
}
|
||||
|
||||
#[derive(JSTraceable, PartialEq, Clone, HeapSizeOf)]
|
||||
pub enum AttrValue {
|
||||
String(DOMString),
|
||||
|
@ -94,6 +88,17 @@ impl AttrValue {
|
|||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the AttrValue as its integer representation, if any.
|
||||
/// This corresponds to attribute values returned as `AttrValue::UInt(_)`
|
||||
/// by `VirtualMethods::parse_plain_attribute()`.
|
||||
pub fn uint(&self) -> Option<u32> {
|
||||
if let AttrValue::UInt(_, value) = *self {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for AttrValue {
|
||||
|
@ -179,7 +184,7 @@ impl AttrMethods for Attr {
|
|||
None => *self.value.borrow_mut() = AttrValue::String(value),
|
||||
Some(owner) => {
|
||||
let value = owner.r().parse_attribute(&self.namespace, self.local_name(), value);
|
||||
self.set_value(AttrSettingType::ReplacedAttr, value, owner.r());
|
||||
self.set_value(value, owner.r());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,22 +241,12 @@ impl AttrMethods for Attr {
|
|||
|
||||
|
||||
impl Attr {
|
||||
pub fn set_value(&self, set_type: AttrSettingType, value: AttrValue, owner: &Element) {
|
||||
pub fn set_value(&self, mut value: AttrValue, owner: &Element) {
|
||||
assert!(Some(owner) == self.owner().r());
|
||||
|
||||
let node = NodeCast::from_ref(owner);
|
||||
let namespace_is_null = self.namespace == ns!("");
|
||||
|
||||
match set_type {
|
||||
AttrSettingType::ReplacedAttr if namespace_is_null =>
|
||||
vtable_for(&node).before_remove_attr(self),
|
||||
_ => ()
|
||||
}
|
||||
|
||||
*self.value.borrow_mut() = value;
|
||||
|
||||
if namespace_is_null {
|
||||
vtable_for(&node).after_set_attr(self)
|
||||
mem::swap(&mut *self.value.borrow_mut(), &mut value);
|
||||
if self.namespace == ns!("") {
|
||||
vtable_for(NodeCast::from_ref(owner)).attribute_mutated(
|
||||
self, AttributeMutation::Set(Some(&value)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue