Bug 1365159 - Part 1: Record :-moz-browser-frame and :-moz-table-border-nonzero state on snapshots. r=emilio
MozReview-Commit-ID: BEglHnXhpYJ
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -746,31 +746,46 @@ ServoRestyleManager::ContentStateChanged
snapshot.AddState(previousState);
if (Element* parent = aElement->GetFlattenedTreeParentElementForStyle()) {
parent->NoteDirtyDescendantsForServo();
}
PostRestyleEvent(aElement, restyleHint, changeHint);
}
+static inline bool
+AttributeInfluencesOtherPseudoClassState(Element* aElement, nsIAtom* aAttribute)
+{
+ // We must record some state for :-moz-browser-frame and
+ // :-moz-table-border-nonzero.
+ return (aAttribute == nsGkAtoms::mozbrowser &&
+ aElement->IsAnyOfHTMLElements(nsGkAtoms::iframe, nsGkAtoms::frame)) ||
+ (aAttribute == nsGkAtoms::border &&
+ aElement->IsHTMLElement(nsGkAtoms::table));
+}
+
void
ServoRestyleManager::AttributeWillChange(Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute, int32_t aModType,
const nsAttrValue* aNewValue)
{
MOZ_ASSERT(!mInStyleRefresh);
if (!aElement->HasServoData()) {
return;
}
ServoElementSnapshot& snapshot = SnapshotFor(aElement);
snapshot.AddAttrs(aElement);
+ if (AttributeInfluencesOtherPseudoClassState(aElement, aAttribute)) {
+ snapshot.AddOtherPseudoClassState(aElement);
+ }
+
if (Element* parent = aElement->GetFlattenedTreeParentElementForStyle()) {
parent->NoteDirtyDescendantsForServo();
}
}
void
ServoRestyleManager::AttributeChanged(Element* aElement, int32_t aNameSpaceID,
nsIAtom* aAttribute, int32_t aModType,
--- a/layout/style/ServoElementSnapshot.cpp
+++ b/layout/style/ServoElementSnapshot.cpp
@@ -9,16 +9,18 @@
#include "nsIContentInlines.h"
#include "nsContentUtils.h"
namespace mozilla {
ServoElementSnapshot::ServoElementSnapshot(const Element* aElement)
: mState(0)
, mContains(Flags(0))
+ , mIsTableBorderNonzero(false)
+ , mIsMozBrowserFrame(false)
{
MOZ_COUNT_CTOR(ServoElementSnapshot);
mIsHTMLElementInHTMLDocument =
aElement->IsHTMLElement() && aElement->IsInHTMLDocument();
mIsInChromeDocument =
nsContentUtils::IsChromeDoc(aElement->OwnerDoc());
}
@@ -48,9 +50,28 @@ ServoElementSnapshot::AddAttrs(Element*
if (aElement->HasID()) {
mContains |= Flags::Id;
}
if (aElement->MayHaveClass()) {
mContains |= Flags::MaybeClass;
}
}
+void
+ServoElementSnapshot::AddOtherPseudoClassState(Element* aElement)
+{
+ MOZ_ASSERT(aElement);
+
+ if (HasOtherPseudoClassState()) {
+ return;
+ }
+
+ mIsTableBorderNonzero =
+ *nsCSSPseudoClasses::MatchesElement(CSSPseudoClassType::mozTableBorderNonzero,
+ aElement);
+ mIsMozBrowserFrame =
+ *nsCSSPseudoClasses::MatchesElement(CSSPseudoClassType::mozBrowserFrame,
+ aElement);
+
+ mContains |= Flags::OtherPseudoClassState;
+}
+
} // namespace mozilla
--- a/layout/style/ServoElementSnapshot.h
+++ b/layout/style/ServoElementSnapshot.h
@@ -43,16 +43,17 @@ struct ServoAttrSnapshot
* contains.
*/
enum class ServoElementSnapshotFlags : uint8_t
{
State = 1 << 0,
Attributes = 1 << 1,
Id = 1 << 2,
MaybeClass = 1 << 3,
+ OtherPseudoClassState = 1 << 4,
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ServoElementSnapshotFlags)
/**
* This class holds all non-tree-structural state of an element that might be
* used for selector matching eventually.
*
@@ -70,16 +71,21 @@ public:
explicit ServoElementSnapshot(const Element* aElement);
~ServoElementSnapshot();
bool HasAttrs() const { return HasAny(Flags::Attributes); }
bool HasState() const { return HasAny(Flags::State); }
+ bool HasOtherPseudoClassState() const
+ {
+ return HasAny(Flags::OtherPseudoClassState);
+ }
+
/**
* Captures the given state (if not previously captured).
*/
void AddState(EventStates aState)
{
if (!HasAny(Flags::State)) {
mState = aState.ServoValue();
mContains |= Flags::State;
@@ -87,16 +93,22 @@ public:
}
/**
* Captures the given element attributes (if not previously captured).
*/
void AddAttrs(Element* aElement);
/**
+ * Captures some other pseudo-class matching state not included in
+ * EventStates.
+ */
+ void AddOtherPseudoClassState(Element* aElement);
+
+ /**
* Needed methods for attribute matching.
*/
BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const
{
MOZ_ASSERT(HasAttrs());
if (aIndex >= mAttrs.Length()) {
return BorrowedAttrInfo(nullptr, nullptr);
}
@@ -135,23 +147,37 @@ public:
bool IsInChromeDocument() const
{
return mIsInChromeDocument;
}
bool HasAny(Flags aFlags) const { return bool(mContains & aFlags); }
+ bool IsTableBorderNonzero() const
+ {
+ MOZ_ASSERT(HasOtherPseudoClassState());
+ return mIsTableBorderNonzero;
+ }
+
+ bool IsMozBrowserFrame() const
+ {
+ MOZ_ASSERT(HasOtherPseudoClassState());
+ return mIsMozBrowserFrame;
+ }
+
private:
// TODO: Profile, a 1 or 2 element AutoTArray could be worth it, given we know
// we're dealing with attribute changes when we take snapshots of attributes,
// though it can be wasted space if we deal with a lot of state-only
// snapshots.
nsTArray<ServoAttrSnapshot> mAttrs;
ServoStateType mState;
Flags mContains;
- bool mIsHTMLElementInHTMLDocument;
- bool mIsInChromeDocument;
+ bool mIsHTMLElementInHTMLDocument : 1;
+ bool mIsInChromeDocument : 1;
+ bool mIsTableBorderNonzero : 1;
+ bool mIsMozBrowserFrame : 1;
};
} // namespace mozilla
#endif