Bug 1368240: Record whether an snapshot is recording a class attribute change or id change. r?heycam
I'll use this information in order to get fewer dependencies out of the
dependency set.
MozReview-Commit-ID: 5HlmKmSNO8p
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -795,17 +795,17 @@ ServoRestyleManager::AttributeWillChange
{
MOZ_ASSERT(!mInStyleRefresh);
if (!aElement->HasServoData()) {
return;
}
ServoElementSnapshot& snapshot = SnapshotFor(aElement);
- snapshot.AddAttrs(aElement);
+ snapshot.AddAttrs(aElement, aNameSpaceID, aAttribute);
if (AttributeInfluencesOtherPseudoClassState(aElement, aAttribute)) {
snapshot.AddOtherPseudoClassState(aElement);
}
if (Element* parent = aElement->GetFlattenedTreeParentElementForStyle()) {
parent->NoteDirtyDescendantsForServo();
}
--- a/layout/style/ServoElementSnapshot.cpp
+++ b/layout/style/ServoElementSnapshot.cpp
@@ -11,34 +11,51 @@
namespace mozilla {
ServoElementSnapshot::ServoElementSnapshot(const Element* aElement)
: mState(0)
, mContains(Flags(0))
, mIsTableBorderNonzero(false)
, mIsMozBrowserFrame(false)
+ , mClassAttributeChanged(false)
+ , mIdAttributeChanged(false)
+ , mOtherAttributeChanged(false)
{
MOZ_COUNT_CTOR(ServoElementSnapshot);
mIsHTMLElementInHTMLDocument =
aElement->IsHTMLElement() && aElement->IsInHTMLDocument();
mIsInChromeDocument = nsContentUtils::IsChromeDoc(aElement->OwnerDoc());
mSupportsLangAttr = aElement->SupportsLangAttr();
}
ServoElementSnapshot::~ServoElementSnapshot()
{
MOZ_COUNT_DTOR(ServoElementSnapshot);
}
void
-ServoElementSnapshot::AddAttrs(Element* aElement)
+ServoElementSnapshot::AddAttrs(Element* aElement,
+ int32_t aNameSpaceID,
+ nsIAtom* aAttribute)
{
MOZ_ASSERT(aElement);
+ if (aNameSpaceID == kNameSpaceID_None) {
+ if (aAttribute == nsGkAtoms::_class) {
+ mClassAttributeChanged = true;
+ } else if (aAttribute == nsGkAtoms::id) {
+ mIdAttributeChanged = true;
+ } else {
+ mOtherAttributeChanged = true;
+ }
+ } else {
+ mOtherAttributeChanged = true;
+ }
+
if (HasAttrs()) {
return;
}
uint32_t attrCount = aElement->GetAttrCount();
const nsAttrName* attrName;
for (uint32_t i = 0; i < attrCount; ++i) {
attrName = aElement->GetAttrNameAt(i);
--- a/layout/style/ServoElementSnapshot.h
+++ b/layout/style/ServoElementSnapshot.h
@@ -89,18 +89,23 @@ public:
if (!HasAny(Flags::State)) {
mState = aState.ServoValue();
mContains |= Flags::State;
}
}
/**
* Captures the given element attributes (if not previously captured).
+ *
+ * The attribute name and namespace are used to note which kind of attribute
+ * has changed.
*/
- void AddAttrs(Element* aElement);
+ void AddAttrs(Element* aElement,
+ int32_t aNameSpaceID,
+ nsIAtom* aChangedAttribute);
/**
* Captures some other pseudo-class matching state not included in
* EventStates.
*/
void AddOtherPseudoClassState(Element* aElement);
/**
@@ -170,13 +175,16 @@ private:
nsTArray<ServoAttrSnapshot> mAttrs;
ServoStateType mState;
Flags mContains;
bool mIsHTMLElementInHTMLDocument : 1;
bool mIsInChromeDocument : 1;
bool mSupportsLangAttr : 1;
bool mIsTableBorderNonzero : 1;
bool mIsMozBrowserFrame : 1;
+ bool mClassAttributeChanged : 1;
+ bool mIdAttributeChanged : 1;
+ bool mOtherAttributeChanged : 1;
};
} // namespace mozilla
#endif
--- a/servo/components/script/dom/document.rs
+++ b/servo/components/script/dom/document.rs
@@ -2382,16 +2382,23 @@ impl Document {
// FIXME(emilio): This should become something like
// element.is_attribute_mapped(attr.local_name()).
if attr.local_name() == &local_name!("width") ||
attr.local_name() == &local_name!("height") {
entry.hint.insert(RestyleHint::for_self());
}
let mut snapshot = entry.snapshot.as_mut().unwrap();
+ if attr.local_name() == &local_name!("id") {
+ snapshot.id_changed = true;
+ } else if attr.local_name() == &local_name!("class") {
+ snapshot.class_changed = true;
+ } else {
+ snapshot.other_attributes_changed = true;
+ }
if snapshot.attrs.is_none() {
let attrs = el.attrs()
.iter()
.map(|attr| (attr.identifier().clone(), attr.value().clone()))
.collect();
snapshot.attrs = Some(attrs);
}
}
--- a/servo/components/style/gecko/snapshot.rs
+++ b/servo/components/style/gecko/snapshot.rs
@@ -57,16 +57,35 @@ impl GeckoElementSnapshot {
/// Returns true if the snapshot has stored state for pseudo-classes
/// that depend on things other than `ElementState`.
#[inline]
pub fn has_other_pseudo_class_state(&self) -> bool {
self.has_any(Flags::OtherPseudoClassState)
}
+ /// Returns true if the snapshot recorded an id change.
+ #[inline]
+ pub fn id_changed(&self) -> bool {
+ self.mIdAttributeChanged()
+ }
+
+ /// Returns true if the snapshot recorded a class attribute change.
+ #[inline]
+ pub fn class_changed(&self) -> bool {
+ self.mClassAttributeChanged()
+ }
+
+ /// Returns true if the snapshot recorded an attribute change which isn't a
+ /// class or id change.
+ #[inline]
+ pub fn other_attr_changed(&self) -> bool {
+ self.mOtherAttributeChanged()
+ }
+
/// selectors::Element::attr_matches
pub fn attr_matches(&self,
ns: &NamespaceConstraint<&Namespace>,
local_name: &Atom,
operation: &AttrSelectorOperation<&Atom>)
-> bool {
unsafe {
match *operation {
--- a/servo/components/style/servo/selector_parser.rs
+++ b/servo/components/style/servo/selector_parser.rs
@@ -540,28 +540,52 @@ impl DerefMut for SnapshotMap {
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct ServoElementSnapshot {
/// The stored state of the element.
pub state: Option<ElementState>,
/// The set of stored attributes and its values.
pub attrs: Option<Vec<(AttrIdentifier, AttrValue)>>,
/// Whether this element is an HTML element in an HTML document.
pub is_html_element_in_html_document: bool,
+ /// Whether the class attribute changed or not.
+ pub class_changed: bool,
+ /// Whether the id attribute changed or not.
+ pub id_changed: bool,
+ /// Whether other attributes other than id or class changed or not.
+ pub other_attributes_changed: bool,
}
impl ServoElementSnapshot {
/// Create an empty element snapshot.
pub fn new(is_html_element_in_html_document: bool) -> Self {
ServoElementSnapshot {
state: None,
attrs: None,
is_html_element_in_html_document: is_html_element_in_html_document,
+ class_changed: false,
+ id_changed: false,
+ other_attributes_changed: false,
}
}
+ /// Returns whether the id attribute changed or not.
+ pub fn id_changed(&self) -> bool {
+ self.id_changed
+ }
+
+ /// Returns whether the class attribute changed or not.
+ pub fn class_changed(&self) -> bool {
+ self.class_changed
+ }
+
+ /// Returns whether other attributes other than id or class changed or not.
+ pub fn other_attr_changed(&self) -> bool {
+ self.other_attributes_changed
+ }
+
fn get_attr(&self, namespace: &Namespace, name: &LocalName) -> Option<&AttrValue> {
self.attrs.as_ref().unwrap().iter()
.find(|&&(ref ident, _)| ident.local_name == *name &&
ident.namespace == *namespace)
.map(|&(_, ref v)| v)
}
fn any_attr_ignore_ns<F>(&self, name: &LocalName, mut f: F) -> bool