mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
Auto merge of #8381 - bholley:attr_restyle_hints, r=pcwalton
Implement attribute restyle hints <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8381) <!-- Reviewable:end -->
This commit is contained in:
commit
13226f8472
18 changed files with 587 additions and 316 deletions
|
@ -2,7 +2,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::RGBA;
|
||||
use devtools_traits::AttrInfo;
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::AttrBinding::{self, AttrMethods};
|
||||
|
@ -12,184 +11,21 @@ use dom::bindings::js::{JS, MutNullableHeap};
|
|||
use dom::bindings::js::{LayoutJS, Root, RootedReference};
|
||||
use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||
use dom::element::{AttributeMutation, Element};
|
||||
use dom::values::UNSIGNED_LONG_MAX;
|
||||
use dom::virtualmethods::vtable_for;
|
||||
use dom::window::Window;
|
||||
use std::borrow::ToOwned;
|
||||
use std::cell::Ref;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use string_cache::{Atom, Namespace};
|
||||
use style::values::specified::Length;
|
||||
use util::str::{DOMString, LengthOrPercentageOrAuto, parse_unsigned_integer, parse_legacy_color, parse_length};
|
||||
use util::str::{split_html_space_chars, str_join};
|
||||
|
||||
#[derive(JSTraceable, PartialEq, Clone, HeapSizeOf)]
|
||||
pub enum AttrValue {
|
||||
String(DOMString),
|
||||
TokenList(DOMString, Vec<Atom>),
|
||||
UInt(DOMString, u32),
|
||||
Atom(Atom),
|
||||
Length(DOMString, Option<Length>),
|
||||
Color(DOMString, Option<RGBA>),
|
||||
Dimension(DOMString, LengthOrPercentageOrAuto),
|
||||
}
|
||||
|
||||
impl AttrValue {
|
||||
pub fn from_serialized_tokenlist(tokens: DOMString) -> AttrValue {
|
||||
let atoms =
|
||||
split_html_space_chars(&tokens)
|
||||
.map(Atom::from_slice)
|
||||
.fold(vec![], |mut acc, atom| {
|
||||
if !acc.contains(&atom) { acc.push(atom) }
|
||||
acc
|
||||
});
|
||||
AttrValue::TokenList(tokens, atoms)
|
||||
}
|
||||
|
||||
pub fn from_atomic_tokens(atoms: Vec<Atom>) -> AttrValue {
|
||||
let tokens = DOMString(str_join(&atoms, "\x20"));
|
||||
AttrValue::TokenList(tokens, atoms)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#reflecting-content-attributes-in-idl-attributes:idl-unsigned-long
|
||||
pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
|
||||
let result = parse_unsigned_integer(string.chars()).unwrap_or(default);
|
||||
let result = if result > UNSIGNED_LONG_MAX {
|
||||
default
|
||||
} else {
|
||||
result
|
||||
};
|
||||
AttrValue::UInt(string, result)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#limited-to-only-non-negative-numbers-greater-than-zero
|
||||
pub fn from_limited_u32(string: DOMString, default: u32) -> AttrValue {
|
||||
let result = parse_unsigned_integer(string.chars()).unwrap_or(default);
|
||||
let result = if result == 0 || result > UNSIGNED_LONG_MAX {
|
||||
default
|
||||
} else {
|
||||
result
|
||||
};
|
||||
AttrValue::UInt(string, result)
|
||||
}
|
||||
|
||||
pub fn from_atomic(string: DOMString) -> AttrValue {
|
||||
let value = Atom::from_slice(&string);
|
||||
AttrValue::Atom(value)
|
||||
}
|
||||
|
||||
pub fn from_legacy_color(string: DOMString) -> AttrValue {
|
||||
let parsed = parse_legacy_color(&string).ok();
|
||||
AttrValue::Color(string, parsed)
|
||||
}
|
||||
|
||||
pub fn from_dimension(string: DOMString) -> AttrValue {
|
||||
let parsed = parse_length(&string);
|
||||
AttrValue::Dimension(string, parsed)
|
||||
}
|
||||
|
||||
/// Assumes the `AttrValue` is a `TokenList` and returns its tokens
|
||||
///
|
||||
/// ## Panics
|
||||
///
|
||||
/// Panics if the `AttrValue` is not a `TokenList`
|
||||
pub fn as_tokens(&self) -> &[Atom] {
|
||||
match *self {
|
||||
AttrValue::TokenList(_, ref tokens) => tokens,
|
||||
_ => panic!("Tokens not found"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Assumes the `AttrValue` is an `Atom` and returns its value
|
||||
///
|
||||
/// ## Panics
|
||||
///
|
||||
/// Panics if the `AttrValue` is not an `Atom`
|
||||
pub fn as_atom(&self) -> &Atom {
|
||||
match *self {
|
||||
AttrValue::Atom(ref value) => value,
|
||||
_ => panic!("Atom not found"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Assumes the `AttrValue` is a `Color` and returns its value
|
||||
///
|
||||
/// ## Panics
|
||||
///
|
||||
/// Panics if the `AttrValue` is not a `Color`
|
||||
pub fn as_color(&self) -> Option<&RGBA> {
|
||||
match *self {
|
||||
AttrValue::Color(_, ref color) => color.as_ref(),
|
||||
_ => panic!("Color not found"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Assumes the `AttrValue` is a `Length` and returns its value
|
||||
///
|
||||
/// ## Panics
|
||||
///
|
||||
/// Panics if the `AttrValue` is not a `Length`
|
||||
pub fn as_length(&self) -> Option<&Length> {
|
||||
match *self {
|
||||
AttrValue::Length(_, ref length) => length.as_ref(),
|
||||
_ => panic!("Length not found"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Assumes the `AttrValue` is a `Dimension` and returns its value
|
||||
///
|
||||
/// ## Panics
|
||||
///
|
||||
/// Panics if the `AttrValue` is not a `Dimension`
|
||||
pub fn as_dimension(&self) -> &LengthOrPercentageOrAuto {
|
||||
match *self {
|
||||
AttrValue::Dimension(_, ref l) => l,
|
||||
_ => panic!("Dimension not found"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the AttrValue as its integer representation, if any.
|
||||
/// This corresponds to attribute values returned as `AttrValue::UInt(_)`
|
||||
/// by `VirtualMethods::parse_plain_attribute()`.
|
||||
///
|
||||
/// ## Panics
|
||||
///
|
||||
/// Panics if the `AttrValue` is not a `UInt`
|
||||
pub fn as_uint(&self) -> u32 {
|
||||
if let AttrValue::UInt(_, value) = *self {
|
||||
value
|
||||
} else {
|
||||
panic!("Uint not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for AttrValue {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &str {
|
||||
match *self {
|
||||
AttrValue::String(ref value) |
|
||||
AttrValue::TokenList(ref value, _) |
|
||||
AttrValue::UInt(ref value, _) |
|
||||
AttrValue::Length(ref value, _) |
|
||||
AttrValue::Color(ref value, _) |
|
||||
AttrValue::Dimension(ref value, _) => &value,
|
||||
AttrValue::Atom(ref value) => &value,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub use style::attr::{AttrIdentifier, AttrValue};
|
||||
use util::str::DOMString;
|
||||
|
||||
// https://dom.spec.whatwg.org/#interface-attr
|
||||
#[dom_struct]
|
||||
pub struct Attr {
|
||||
reflector_: Reflector,
|
||||
local_name: Atom,
|
||||
identifier: AttrIdentifier,
|
||||
value: DOMRefCell<AttrValue>,
|
||||
name: Atom,
|
||||
namespace: Namespace,
|
||||
prefix: Option<Atom>,
|
||||
|
||||
/// the element that owns this attribute.
|
||||
owner: MutNullableHeap<JS<Element>>,
|
||||
|
@ -200,11 +36,13 @@ impl Attr {
|
|||
prefix: Option<Atom>, owner: Option<&Element>) -> Attr {
|
||||
Attr {
|
||||
reflector_: Reflector::new(),
|
||||
local_name: local_name,
|
||||
identifier: AttrIdentifier {
|
||||
local_name: local_name,
|
||||
name: name,
|
||||
namespace: namespace,
|
||||
prefix: prefix,
|
||||
},
|
||||
value: DOMRefCell::new(value),
|
||||
name: name,
|
||||
namespace: namespace,
|
||||
prefix: prefix,
|
||||
owner: MutNullableHeap::new(owner),
|
||||
}
|
||||
}
|
||||
|
@ -220,17 +58,17 @@ impl Attr {
|
|||
|
||||
#[inline]
|
||||
pub fn name(&self) -> &Atom {
|
||||
&self.name
|
||||
&self.identifier.name
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn namespace(&self) -> &Namespace {
|
||||
&self.namespace
|
||||
&self.identifier.namespace
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn prefix(&self) -> &Option<Atom> {
|
||||
&self.prefix
|
||||
&self.identifier.prefix
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,7 +88,7 @@ impl AttrMethods for Attr {
|
|||
match self.owner() {
|
||||
None => *self.value.borrow_mut() = AttrValue::String(value),
|
||||
Some(owner) => {
|
||||
let value = owner.parse_attribute(&self.namespace, self.local_name(), value);
|
||||
let value = owner.parse_attribute(&self.identifier.namespace, self.local_name(), value);
|
||||
self.set_value(value, owner.r());
|
||||
}
|
||||
}
|
||||
|
@ -278,12 +116,12 @@ impl AttrMethods for Attr {
|
|||
|
||||
// https://dom.spec.whatwg.org/#dom-attr-name
|
||||
fn Name(&self) -> DOMString {
|
||||
DOMString((*self.name).to_owned())
|
||||
DOMString((*self.identifier.name).to_owned())
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-attr-namespaceuri
|
||||
fn GetNamespaceURI(&self) -> Option<DOMString> {
|
||||
let Namespace(ref atom) = self.namespace;
|
||||
let Namespace(ref atom) = self.identifier.namespace;
|
||||
match &**atom {
|
||||
"" => None,
|
||||
url => Some(DOMString(url.to_owned())),
|
||||
|
@ -310,33 +148,38 @@ impl AttrMethods for Attr {
|
|||
impl Attr {
|
||||
pub fn set_value(&self, mut value: AttrValue, owner: &Element) {
|
||||
assert!(Some(owner) == self.owner().r());
|
||||
owner.will_mutate_attr();
|
||||
mem::swap(&mut *self.value.borrow_mut(), &mut value);
|
||||
if self.namespace == ns!("") {
|
||||
if self.identifier.namespace == ns!("") {
|
||||
vtable_for(owner.upcast()).attribute_mutated(
|
||||
self, AttributeMutation::Set(Some(&value)));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn identifier(&self) -> &AttrIdentifier {
|
||||
&self.identifier
|
||||
}
|
||||
|
||||
pub fn value(&self) -> Ref<AttrValue> {
|
||||
self.value.borrow()
|
||||
}
|
||||
|
||||
pub fn local_name(&self) -> &Atom {
|
||||
&self.local_name
|
||||
&self.identifier.local_name
|
||||
}
|
||||
|
||||
/// Sets the owner element. Should be called after the attribute is added
|
||||
/// or removed from its older parent.
|
||||
pub fn set_owner(&self, owner: Option<&Element>) {
|
||||
let ref ns = self.namespace;
|
||||
let ref ns = self.identifier.namespace;
|
||||
match (self.owner().r(), owner) {
|
||||
(None, Some(new)) => {
|
||||
// Already in the list of attributes of new owner.
|
||||
assert!(new.get_attribute(&ns, &self.local_name) == Some(Root::from_ref(self)))
|
||||
assert!(new.get_attribute(&ns, &self.identifier.local_name) == Some(Root::from_ref(self)))
|
||||
}
|
||||
(Some(old), None) => {
|
||||
// Already gone from the list of attributes of old owner.
|
||||
assert!(old.get_attribute(&ns, &self.local_name).is_none())
|
||||
assert!(old.get_attribute(&ns, &self.identifier.local_name).is_none())
|
||||
}
|
||||
(old, new) => assert!(old == new)
|
||||
}
|
||||
|
@ -348,7 +191,7 @@ impl Attr {
|
|||
}
|
||||
|
||||
pub fn summarize(&self) -> AttrInfo {
|
||||
let Namespace(ref ns) = self.namespace;
|
||||
let Namespace(ref ns) = self.identifier.namespace;
|
||||
AttrInfo {
|
||||
namespace: (**ns).to_owned(),
|
||||
name: self.Name().0,
|
||||
|
@ -400,7 +243,7 @@ impl AttrHelpersForLayout for LayoutJS<Attr> {
|
|||
|
||||
#[inline]
|
||||
unsafe fn local_name_atom_forever(&self) -> Atom {
|
||||
(*self.unsafe_get()).local_name.clone()
|
||||
(*self.unsafe_get()).identifier.local_name.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -82,7 +82,9 @@ use std::sync::Arc;
|
|||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
use string_cache::{Atom, Namespace, QualName};
|
||||
use style::attr::{AttrIdentifier, AttrValue};
|
||||
use style::properties::PropertyDeclarationBlock;
|
||||
use style::restyle_hints::ElementSnapshot;
|
||||
use style::values::specified::Length;
|
||||
use url::Url;
|
||||
use util::str::{DOMString, LengthOrPercentageOrAuto};
|
||||
|
@ -289,6 +291,9 @@ no_jsmanaged_fields!(Length);
|
|||
no_jsmanaged_fields!(ElementState);
|
||||
no_jsmanaged_fields!(DOMString);
|
||||
no_jsmanaged_fields!(Mime);
|
||||
no_jsmanaged_fields!(AttrIdentifier);
|
||||
no_jsmanaged_fields!(AttrValue);
|
||||
no_jsmanaged_fields!(ElementSnapshot);
|
||||
|
||||
impl JSTraceable for Box<ScriptChan + Send> {
|
||||
#[inline]
|
||||
|
|
|
@ -88,7 +88,6 @@ use net_traits::{AsyncResponseTarget, PendingAsyncLoad};
|
|||
use num::ToPrimitive;
|
||||
use script_task::{MainThreadScriptMsg, Runnable};
|
||||
use script_traits::{MouseButton, TouchEventType, TouchId, UntrustedNodeAddress};
|
||||
use selectors::states::*;
|
||||
use std::ascii::AsciiExt;
|
||||
use std::borrow::ToOwned;
|
||||
use std::boxed::FnBox;
|
||||
|
@ -102,6 +101,7 @@ use std::rc::Rc;
|
|||
use std::sync::Arc;
|
||||
use std::sync::mpsc::channel;
|
||||
use string_cache::{Atom, QualName};
|
||||
use style::restyle_hints::ElementSnapshot;
|
||||
use style::stylesheets::Stylesheet;
|
||||
use time;
|
||||
use url::Url;
|
||||
|
@ -188,8 +188,9 @@ pub struct Document {
|
|||
/// This field is set to the document itself for inert documents.
|
||||
/// https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document
|
||||
appropriate_template_contents_owner_document: MutNullableHeap<JS<Document>>,
|
||||
/// For each element that has had a state change since the last restyle, track the original state.
|
||||
modified_elements: DOMRefCell<HashMap<JS<Element>, ElementState>>,
|
||||
/// For each element that has had a state or attribute change since the last restyle,
|
||||
/// track the original condition of the element.
|
||||
modified_elements: DOMRefCell<HashMap<JS<Element>, ElementSnapshot>>,
|
||||
/// http://w3c.github.io/touch-events/#dfn-active-touch-point
|
||||
active_touch_points: DOMRefCell<Vec<JS<Touch>>>,
|
||||
}
|
||||
|
@ -1275,7 +1276,7 @@ pub enum DocumentSource {
|
|||
#[allow(unsafe_code)]
|
||||
pub trait LayoutDocumentHelpers {
|
||||
unsafe fn is_html_document_for_layout(&self) -> bool;
|
||||
unsafe fn drain_modified_elements(&self) -> Vec<(LayoutJS<Element>, ElementState)>;
|
||||
unsafe fn drain_modified_elements(&self) -> Vec<(LayoutJS<Element>, ElementSnapshot)>;
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
|
@ -1287,7 +1288,7 @@ impl LayoutDocumentHelpers for LayoutJS<Document> {
|
|||
|
||||
#[inline]
|
||||
#[allow(unrooted_must_root)]
|
||||
unsafe fn drain_modified_elements(&self) -> Vec<(LayoutJS<Element>, ElementState)> {
|
||||
unsafe fn drain_modified_elements(&self) -> Vec<(LayoutJS<Element>, ElementSnapshot)> {
|
||||
let mut elements = (*self.unsafe_get()).modified_elements.borrow_mut_for_layout();
|
||||
let drain = elements.drain();
|
||||
let layout_drain = drain.map(|(k, v)| (k.to_layout(), v));
|
||||
|
@ -1457,7 +1458,21 @@ impl Document {
|
|||
|
||||
pub fn element_state_will_change(&self, el: &Element) {
|
||||
let mut map = self.modified_elements.borrow_mut();
|
||||
map.entry(JS::from_ref(el)).or_insert(el.get_state());
|
||||
let snapshot = map.entry(JS::from_ref(el)).or_insert(ElementSnapshot::new());
|
||||
if snapshot.state.is_none() {
|
||||
snapshot.state = Some(el.get_state());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn element_attr_will_change(&self, el: &Element) {
|
||||
let mut map = self.modified_elements.borrow_mut();
|
||||
let mut snapshot = map.entry(JS::from_ref(el)).or_insert(ElementSnapshot::new());
|
||||
if snapshot.attrs.is_none() {
|
||||
let attrs = el.attrs().iter()
|
||||
.map(|attr| (attr.identifier().clone(), attr.value().clone()))
|
||||
.collect();
|
||||
snapshot.attrs = Some(attrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -488,13 +488,7 @@ impl Node {
|
|||
self.dirty_impl(damage, true)
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
// the document's version, but we do have to deal with the case where the node has moved
|
||||
|
@ -505,6 +499,15 @@ impl Node {
|
|||
ancestor.inclusive_descendants_version.set(version);
|
||||
}
|
||||
doc.inclusive_descendants_version.set(version);
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue