Bug 1365472 - Snapshot elements when their class name is animated; r?heycam
This patch causes us to trigger a snapshot whenever the class attribute of an
element is updated via SMIL animation so that when it comes time to restyle, we
have the old value of the attribute to compare against the current value.
MozReview-Commit-ID: IVYkhl2D6vz
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -123,24 +123,34 @@ nsSVGElement::GetStyle(nsIDOMCSSStyleDec
}
//----------------------------------------------------------------------
// nsSVGElement methods
void
nsSVGElement::DidAnimateClass()
{
+ // For Servo, snapshot the element before we change it.
+ nsIPresShell* shell = OwnerDoc()->GetShell();
+ if (shell) {
+ nsPresContext* presContext = shell->GetPresContext();
+ if (presContext && presContext->RestyleManager()->IsServo()) {
+ presContext->RestyleManager()
+ ->AsServo()
+ ->ClassAttributeWillBeChangedBySMIL(this);
+ }
+ }
+
nsAutoString src;
mClassAttribute.GetAnimValue(src, this);
if (!mClassAnimAttr) {
mClassAnimAttr = new nsAttrValue();
}
mClassAnimAttr->ParseAtomArray(src);
- nsIPresShell* shell = OwnerDoc()->GetShell();
if (shell) {
shell->RestyleForAnimation(this, eRestyle_Self);
}
}
nsresult
nsSVGElement::Init()
{
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -831,16 +831,30 @@ AttributeInfluencesOtherPseudoClassState
}
void
ServoRestyleManager::AttributeWillChange(Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute, int32_t aModType,
const nsAttrValue* aNewValue)
{
+ SnapshotForAttributeChange(aElement, aNameSpaceID, aAttribute);
+}
+
+void
+ServoRestyleManager::ClassAttributeWillBeChangedBySMIL(Element* aElement)
+{
+ SnapshotForAttributeChange(aElement, kNameSpaceID_None, nsGkAtoms::_class);
+}
+
+void
+ServoRestyleManager::SnapshotForAttributeChange(Element* aElement,
+ int32_t aNameSpaceID,
+ nsIAtom* aAttribute)
+{
MOZ_ASSERT(!mInStyleRefresh);
if (!aElement->HasServoData()) {
return;
}
bool influencesOtherPseudoClassState =
AttributeInfluencesOtherPseudoClassState(aElement, aAttribute);
--- a/layout/base/ServoRestyleManager.h
+++ b/layout/base/ServoRestyleManager.h
@@ -64,16 +64,17 @@ public:
void RestyleForAppend(nsIContent* aContainer,
nsIContent* aFirstNewContent);
void ContentStateChanged(nsIContent* aContent, EventStates aStateMask);
void AttributeWillChange(dom::Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType,
const nsAttrValue* aNewValue);
+ void ClassAttributeWillBeChangedBySMIL(dom::Element* aElement);
void AttributeChanged(dom::Element* aElement, int32_t aNameSpaceID,
nsIAtom* aAttribute, int32_t aModType,
const nsAttrValue* aOldValue);
nsresult ReparentStyleContext(nsIFrame* aFrame);
/**
@@ -142,16 +143,19 @@ private:
"ServoRestyleManager should only be used with a Servo-flavored "
"style backend");
return PresContext()->StyleSet()->AsServo();
}
const SnapshotTable& Snapshots() const { return mSnapshots; }
void ClearSnapshots();
ServoElementSnapshot& SnapshotFor(mozilla::dom::Element* aElement);
+ void SnapshotForAttributeChange(mozilla::dom::Element* aElement,
+ int32_t aNameSpaceID,
+ nsIAtom* aAttribute);
void DoProcessPendingRestyles(TraversalRestyleBehavior aRestyleBehavior);
// We use a separate data structure from nsStyleChangeList because we need a
// frame to create nsStyleChangeList entries, and the primary frame may not be
// attached yet.
struct ReentrantChange {
nsCOMPtr<nsIContent> mContent;