summaryrefslogtreecommitdiffstats
path: root/dom
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2020-04-17 05:26:58 -0400
committerMatt A. Tobin <email@mattatobin.com>2020-04-17 05:26:58 -0400
commit091d06b43b294390a96106e57a7462f6303107a3 (patch)
tree831e71266ad1a623bc0d0db5e423132cf672314e /dom
parent0f5dcf963a2479a61e370b6b6ffac41be1d5e120 (diff)
downloadUXP-091d06b43b294390a96106e57a7462f6303107a3.tar
UXP-091d06b43b294390a96106e57a7462f6303107a3.tar.gz
UXP-091d06b43b294390a96106e57a7462f6303107a3.tar.lz
UXP-091d06b43b294390a96106e57a7462f6303107a3.tar.xz
UXP-091d06b43b294390a96106e57a7462f6303107a3.zip
Bug 1363481 - Add the old attribute value as a parameter to Element::AfterSetAttr
Tag #1375
Diffstat (limited to 'dom')
-rw-r--r--dom/base/Element.cpp78
-rw-r--r--dom/base/Element.h74
-rw-r--r--dom/base/nsAttrAndChildArray.cpp21
-rw-r--r--dom/base/nsAttrAndChildArray.h18
-rw-r--r--dom/base/nsMappedAttributeElement.cpp14
-rw-r--r--dom/base/nsMappedAttributeElement.h9
-rw-r--r--dom/base/nsMappedAttributes.cpp7
-rw-r--r--dom/base/nsMappedAttributes.h3
-rw-r--r--dom/base/nsStyledElement.cpp12
-rw-r--r--dom/html/HTMLBodyElement.cpp5
-rw-r--r--dom/html/HTMLBodyElement.h4
-rw-r--r--dom/html/HTMLButtonElement.cpp6
-rw-r--r--dom/html/HTMLButtonElement.h6
-rw-r--r--dom/html/HTMLFieldSetElement.cpp5
-rw-r--r--dom/html/HTMLFieldSetElement.h4
-rw-r--r--dom/html/HTMLFormElement.cpp6
-rw-r--r--dom/html/HTMLFormElement.h4
-rw-r--r--dom/html/HTMLIFrameElement.cpp4
-rw-r--r--dom/html/HTMLIFrameElement.h1
-rw-r--r--dom/html/HTMLImageElement.cpp5
-rw-r--r--dom/html/HTMLImageElement.h4
-rw-r--r--dom/html/HTMLInputElement.cpp6
-rw-r--r--dom/html/HTMLInputElement.h4
-rw-r--r--dom/html/HTMLLinkElement.cpp5
-rw-r--r--dom/html/HTMLLinkElement.h1
-rw-r--r--dom/html/HTMLMediaElement.cpp5
-rw-r--r--dom/html/HTMLMediaElement.h1
-rw-r--r--dom/html/HTMLMenuItemElement.cpp5
-rw-r--r--dom/html/HTMLMenuItemElement.h4
-rw-r--r--dom/html/HTMLMetaElement.cpp5
-rw-r--r--dom/html/HTMLMetaElement.h4
-rw-r--r--dom/html/HTMLOptGroupElement.cpp5
-rw-r--r--dom/html/HTMLOptGroupElement.h4
-rw-r--r--dom/html/HTMLOptionElement.cpp5
-rw-r--r--dom/html/HTMLOptionElement.h4
-rw-r--r--dom/html/HTMLScriptElement.cpp5
-rw-r--r--dom/html/HTMLScriptElement.h4
-rw-r--r--dom/html/HTMLSelectElement.cpp6
-rw-r--r--dom/html/HTMLSelectElement.h4
-rw-r--r--dom/html/HTMLSourceElement.cpp5
-rw-r--r--dom/html/HTMLSourceElement.h1
-rw-r--r--dom/html/HTMLStyleElement.cpp5
-rw-r--r--dom/html/HTMLStyleElement.h1
-rw-r--r--dom/html/HTMLTableElement.cpp8
-rw-r--r--dom/html/HTMLTableElement.h4
-rw-r--r--dom/html/HTMLTextAreaElement.cpp5
-rw-r--r--dom/html/HTMLTextAreaElement.h4
-rw-r--r--dom/html/nsGenericHTMLElement.cpp10
-rw-r--r--dom/html/nsGenericHTMLElement.h8
-rw-r--r--dom/html/nsGenericHTMLFrameElement.cpp4
-rw-r--r--dom/html/nsGenericHTMLFrameElement.h1
-rw-r--r--dom/svg/SVGAnimationElement.cpp5
-rw-r--r--dom/svg/SVGAnimationElement.h4
-rw-r--r--dom/svg/SVGFEImageElement.cpp5
-rw-r--r--dom/svg/SVGFEImageElement.h4
-rw-r--r--dom/svg/SVGImageElement.cpp5
-rw-r--r--dom/svg/SVGImageElement.h4
-rw-r--r--dom/svg/SVGScriptElement.cpp5
-rw-r--r--dom/svg/SVGScriptElement.h4
-rw-r--r--dom/svg/nsSVGElement.cpp19
-rw-r--r--dom/svg/nsSVGElement.h4
-rw-r--r--dom/svg/nsSVGPathGeometryElement.cpp5
-rw-r--r--dom/svg/nsSVGPathGeometryElement.h4
-rw-r--r--dom/xul/nsXULElement.cpp18
-rw-r--r--dom/xul/nsXULElement.h4
65 files changed, 352 insertions, 161 deletions
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
index 7c5029e2e..11ad042a0 100644
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -2382,7 +2382,8 @@ Element::MaybeCheckSameAttrVal(int32_t aNamespaceID,
bool aNotify,
nsAttrValue& aOldValue,
uint8_t* aModType,
- bool* aHasListeners)
+ bool* aHasListeners,
+ bool* aOldValueSet)
{
bool modification = false;
*aHasListeners = aNotify &&
@@ -2390,6 +2391,8 @@ Element::MaybeCheckSameAttrVal(int32_t aNamespaceID,
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
this);
+ *aOldValueSet = false;
+
// If we have no listeners and aNotify is false, we are almost certainly
// coming from the content sink and will almost certainly have no previous
// value. Even if we do, setting the value is cheap when we have no
@@ -2413,6 +2416,7 @@ Element::MaybeCheckSameAttrVal(int32_t aNamespaceID,
// We have to serialize the value anyway in order to create the
// mutation event so there's no cost in doing it now.
aOldValue.SetToSerialized(*info.mValue);
+ *aOldValueSet = true;
}
bool valueMatches = aValue.EqualsAsStrings(*info.mValue);
if (valueMatches && aPrefix == info.mName->GetPrefix()) {
@@ -2432,10 +2436,12 @@ Element::OnlyNotifySameValueSet(int32_t aNamespaceID, nsIAtom* aName,
nsIAtom* aPrefix,
const nsAttrValueOrString& aValue,
bool aNotify, nsAttrValue& aOldValue,
- uint8_t* aModType, bool* aHasListeners)
+ uint8_t* aModType, bool* aHasListeners,
+ bool* aOldValueSet)
{
if (!MaybeCheckSameAttrVal(aNamespaceID, aName, aPrefix, aValue, aNotify,
- aOldValue, aModType, aHasListeners)) {
+ aOldValue, aModType, aHasListeners,
+ aOldValueSet)) {
return false;
}
@@ -2466,9 +2472,10 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
// OnlyNotifySameValueSet call.
nsAttrValueOrString value(aValue);
nsAttrValue oldValue;
+ bool oldValueSet;
if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
- oldValue, &modType, &hasListeners)) {
+ oldValue, &modType, &hasListeners, &oldValueSet)) {
return NS_OK;
}
@@ -2501,7 +2508,8 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
attrValue.SetTo(aValue);
}
- return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
+ return SetAttrAndNotify(aNamespaceID, aName, aPrefix,
+ oldValueSet ? &oldValue : nullptr,
attrValue, modType, hasListeners, aNotify,
kCallAfterSetAttr, document, updateBatch);
}
@@ -2526,9 +2534,10 @@ Element::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName,
bool hasListeners;
nsAttrValueOrString value(aParsedValue);
nsAttrValue oldValue;
+ bool oldValueSet;
if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
- oldValue, &modType, &hasListeners)) {
+ oldValue, &modType, &hasListeners, &oldValueSet)) {
return NS_OK;
}
@@ -2542,7 +2551,8 @@ Element::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName,
nsIDocument* document = GetComposedDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
- return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
+ return SetAttrAndNotify(aNamespaceID, aName, aPrefix,
+ oldValueSet ? &oldValue : nullptr,
aParsedValue, modType, hasListeners, aNotify,
kCallAfterSetAttr, document, updateBatch);
}
@@ -2551,7 +2561,7 @@ nsresult
Element::SetAttrAndNotify(int32_t aNamespaceID,
nsIAtom* aName,
nsIAtom* aPrefix,
- const nsAttrValue& aOldValue,
+ const nsAttrValue* aOldValue,
nsAttrValue& aParsedValue,
uint8_t aModType,
bool aFireMutation,
@@ -2573,6 +2583,7 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
bool hadValidDir = false;
bool hadDirAuto = false;
+ bool oldValueSet;
if (aNamespaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::dir) {
@@ -2583,8 +2594,8 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
// XXXbz Perhaps we should push up the attribute mapping function
// stuff to Element?
if (!IsAttributeMapped(aName) ||
- !SetMappedAttribute(aComposedDocument, aName, aParsedValue, &rv)) {
- rv = mAttrsAndChildren.SetAndSwapAttr(aName, aParsedValue);
+ !SetAndSwapMappedAttribute(aComposedDocument, aName, aParsedValue, &oldValueSet, &rv)) {
+ rv = mAttrsAndChildren.SetAndSwapAttr(aName, aParsedValue, &oldValueSet);
}
}
else {
@@ -2593,14 +2604,24 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
aNamespaceID,
nsIDOMNode::ATTRIBUTE_NODE);
- rv = mAttrsAndChildren.SetAndSwapAttr(ni, aParsedValue);
+ rv = mAttrsAndChildren.SetAndSwapAttr(ni, aParsedValue, &oldValueSet);
}
+ NS_ENSURE_SUCCESS(rv, rv);
// If the old value owns its own data, we know it is OK to keep using it.
- const nsAttrValue* oldValue =
- aParsedValue.StoresOwnData() ? &aParsedValue : &aOldValue;
-
- NS_ENSURE_SUCCESS(rv, rv);
+ // oldValue will be null if there was no previously set value
+ const nsAttrValue* oldValue;
+ if (aParsedValue.StoresOwnData()) {
+ if (oldValueSet) {
+ oldValue = &aParsedValue;
+ } else {
+ oldValue = nullptr;
+ }
+ } else {
+ // No need to conditionally assign null here. If there was no previously
+ // set value for the attribute, aOldValue will already be null.
+ oldValue = aOldValue;
+ }
if (aComposedDocument || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
RefPtr<nsXBLBinding> binding = GetXBLBinding();
@@ -2618,7 +2639,14 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
MOZ_ASSERT(data->mState == CustomElementData::State::eCustom,
"AttributeChanged callback should fire only if "
"custom element state is custom");
- nsCOMPtr<nsIAtom> oldValueAtom = oldValue->GetAsAtom();
+ nsCOMPtr<nsIAtom> oldValueAtom;
+ if (oldValue) {
+ oldValueAtom = oldValue->GetAsAtom();
+ } else {
+ // If there is no old value, get the value of the uninitialized attribute
+ // that was swapped with aParsedValue.
+ oldValueAtom = aParsedValue.GetAsAtom();
+ }
nsCOMPtr<nsIAtom> newValueAtom = valueForAfterSetAttr.GetAsAtom();
nsAutoString ns;
nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
@@ -2638,7 +2666,8 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
}
if (aCallAfterSetAttr) {
- rv = AfterSetAttr(aNamespaceID, aName, &valueForAfterSetAttr, aNotify);
+ rv = AfterSetAttr(aNamespaceID, aName, &valueForAfterSetAttr, oldValue,
+ aNotify);
NS_ENSURE_SUCCESS(rv, rv);
if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) {
@@ -2654,7 +2683,7 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
// Callers only compute aOldValue under certain conditions which may not
// be triggered by all nsIMutationObservers.
nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType,
- oldValue == &aParsedValue ? &aParsedValue : nullptr);
+ aParsedValue.StoresOwnData() ? &aParsedValue : nullptr);
}
if (aFireMutation) {
@@ -2672,7 +2701,7 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
if (!newValue.IsEmpty()) {
mutation.mNewAttrValue = NS_Atomize(newValue);
}
- if (!oldValue->IsEmptyString()) {
+ if (oldValue && !oldValue->IsEmptyString()) {
mutation.mPrevAttrValue = oldValue->GetAsAtom();
}
mutation.mAttrChange = aModType;
@@ -2715,10 +2744,11 @@ Element::ParseAttribute(int32_t aNamespaceID,
}
bool
-Element::SetMappedAttribute(nsIDocument* aDocument,
- nsIAtom* aName,
- nsAttrValue& aValue,
- nsresult* aRetval)
+Element::SetAndSwapMappedAttribute(nsIDocument* aDocument,
+ nsIAtom* aName,
+ nsAttrValue& aValue,
+ bool* aValueWasSet,
+ nsresult* aRetval)
{
*aRetval = NS_OK;
return false;
@@ -2886,7 +2916,7 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
}
- rv = AfterSetAttr(aNameSpaceID, aName, nullptr, aNotify);
+ rv = AfterSetAttr(aNameSpaceID, aName, nullptr, &oldValue, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
UpdateState(aNotify);
diff --git a/dom/base/Element.h b/dom/base/Element.h
index 6b55cf8cd..6f60c9ad0 100644
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -537,25 +537,50 @@ public:
* values will not actually be compared if we aren't notifying and we don't
* have mutation listeners (in which case it's cheap to just return false
* and let the caller go ahead and set the value).
- * @param aOldValue Set to the old value of the attribute, but only if there
- * are event listeners. If set, the type of aOldValue will be either
+ * @param aOldValue [out] Set to the old value of the attribute, but only if
+ * there are event listeners. If set, the type of aOldValue will be either
* nsAttrValue::eString or nsAttrValue::eAtom.
- * @param aModType Set to nsIDOMMutationEvent::MODIFICATION or to
+ * @param aModType [out] Set to nsIDOMMutationEvent::MODIFICATION or to
* nsIDOMMutationEvent::ADDITION, but only if this helper returns true
- * @param aHasListeners Set to true if there are mutation event listeners
- * listening for NS_EVENT_BITS_MUTATION_ATTRMODIFIED
+ * @param aHasListeners [out] Set to true if there are mutation event
+ * listeners listening for NS_EVENT_BITS_MUTATION_ATTRMODIFIED
+ * @param aOldValueSet [out] Indicates whether an old attribute value has been
+ * stored in aOldValue. The bool will be set to true if a value was stored.
*/
bool MaybeCheckSameAttrVal(int32_t aNamespaceID, nsIAtom* aName,
nsIAtom* aPrefix,
const nsAttrValueOrString& aValue,
bool aNotify, nsAttrValue& aOldValue,
- uint8_t* aModType, bool* aHasListeners);
+ uint8_t* aModType, bool* aHasListeners,
+ bool* aOldValueSet);
+
+ /**
+ * Notifies mutation listeners if aNotify is true, there are mutation
+ * listeners, and the attribute value is changing.
+ *
+ * @param aNamespaceID The namespace of the attribute
+ * @param aName The local name of the attribute
+ * @param aPrefix The prefix of the attribute
+ * @param aValue The value that the attribute is being changed to
+ * @param aNotify If true, mutation listeners will be notified if they exist
+ * and the attribute value is changing
+ * @param aOldValue [out] Set to the old value of the attribute, but only if
+ * there are event listeners. If set, the type of aOldValue will be either
+ * nsAttrValue::eString or nsAttrValue::eAtom.
+ * @param aModType [out] Set to nsIDOMMutationEvent::MODIFICATION or to
+ * nsIDOMMutationEvent::ADDITION, but only if this helper returns true
+ * @param aHasListeners [out] Set to true if there are mutation event
+ * listeners listening for NS_EVENT_BITS_MUTATION_ATTRMODIFIED
+ * @param aOldValueSet [out] Indicates whether an old attribute value has been
+ * stored in aOldValue. The bool will be set to true if a value was stored.
+ */
bool OnlyNotifySameValueSet(int32_t aNamespaceID, nsIAtom* aName,
nsIAtom* aPrefix,
const nsAttrValueOrString& aValue,
bool aNotify, nsAttrValue& aOldValue,
- uint8_t* aModType, bool* aHasListeners);
+ uint8_t* aModType, bool* aHasListeners,
+ bool* aOldValueSet);
virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
const nsAString& aValue, bool aNotify) override;
@@ -1261,7 +1286,10 @@ protected:
* its current value) is !StoresOwnData() --- in which
* case the current value is probably already useless.
* If the current value is StoresOwnData() (or absent),
- * aOldValue will not be used.
+ * aOldValue will not be used. aOldValue will only be set
+ * in certain circumstances (there are mutation
+ * listeners, element is a custom element, attribute was
+ * not previously unset). Otherwise it will be null.
* @param aParsedValue parsed new value of attribute. Replaced by the
* old value of the attribute. This old value is only
* useful if either it or the new value is StoresOwnData.
@@ -1275,7 +1303,7 @@ protected:
nsresult SetAttrAndNotify(int32_t aNamespaceID,
nsIAtom* aName,
nsIAtom* aPrefix,
- const nsAttrValue& aOldValue,
+ const nsAttrValue* aOldValue,
nsAttrValue& aParsedValue,
uint8_t aModType,
bool aFireMutation,
@@ -1320,14 +1348,21 @@ protected:
*
* @param aDocument the current document of this node (an optimization)
* @param aName the name of the attribute
- * @param aValue the nsAttrValue to set
+ * @param aValue the nsAttrValue to set. Will be swapped with the existing
+ * value of the attribute if the attribute already exists.
+ * @param [out] aValueWasSet If the attribute was not set previously,
+ * aValue will be swapped with an empty attribute
+ * and aValueWasSet will be set to false. Otherwise,
+ * aValueWasSet will be set to true and aValue will
+ * contain the previous value set.
* @param [out] aRetval the nsresult status of the operation, if any.
* @return true if the setting was attempted, false otherwise.
*/
- virtual bool SetMappedAttribute(nsIDocument* aDocument,
- nsIAtom* aName,
- nsAttrValue& aValue,
- nsresult* aRetval);
+ virtual bool SetAndSwapMappedAttribute(nsIDocument* aDocument,
+ nsIAtom* aName,
+ nsAttrValue& aValue,
+ bool* aValueWasSet,
+ nsresult* aRetval);
/**
* Hook that is called by Element::SetAttr to allow subclasses to
@@ -1355,19 +1390,24 @@ protected:
/**
* Hook that is called by Element::SetAttr to allow subclasses to
* deal with attribute sets. This will only be called after we have called
- * SetAndTakeAttr and AttributeChanged (that is, after we have actually set
- * the attr). It will always be called under a scriptblocker.
+ * SetAndSwapAttr (that is, after we have actually set the attr). It will
+ * always be called under a scriptblocker.
*
* @param aNamespaceID the namespace of the attr being set
* @param aName the localname of the attribute being set
* @param aValue the value it's being set to. If null, the attr is being
* removed.
+ * @param aOldValue the value that the attribute had previously. If null,
+ * the attr was not previously set. This argument may not have the
+ * correct value for SVG elements, or other cases in which the
+ * attribute value doesn't store its own data
* @param aNotify Whether we plan to notify document observers.
*/
// Note that this is inlined so that when subclasses call it it gets
// inlined. Those calls don't go through a vtable.
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
return NS_OK;
}
diff --git a/dom/base/nsAttrAndChildArray.cpp b/dom/base/nsAttrAndChildArray.cpp
index 4daac498b..f8e4c3f18 100644
--- a/dom/base/nsAttrAndChildArray.cpp
+++ b/dom/base/nsAttrAndChildArray.cpp
@@ -382,12 +382,15 @@ nsAttrAndChildArray::AttrAt(uint32_t aPos) const
}
nsresult
-nsAttrAndChildArray::SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue)
+nsAttrAndChildArray::SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue,
+ bool* aHadValue)
{
+ *aHadValue = false;
uint32_t i, slotCount = AttrSlotCount();
for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
if (ATTRS(mImpl)[i].mName.Equals(aLocalName)) {
ATTRS(mImpl)[i].mValue.SwapValueWith(aValue);
+ *aHadValue = true;
return NS_OK;
}
}
@@ -407,21 +410,22 @@ nsAttrAndChildArray::SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue)
}
nsresult
-nsAttrAndChildArray::SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue)
+nsAttrAndChildArray::SetAndSwapAttr(mozilla::dom::NodeInfo* aName,
+ nsAttrValue& aValue, bool* aHadValue)
{
int32_t namespaceID = aName->NamespaceID();
nsIAtom* localName = aName->NameAtom();
if (namespaceID == kNameSpaceID_None) {
- return SetAndSwapAttr(localName, aValue);
+ return SetAndSwapAttr(localName, aValue, aHadValue);
}
+ *aHadValue = false;
uint32_t i, slotCount = AttrSlotCount();
for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
if (ATTRS(mImpl)[i].mName.Equals(localName, namespaceID)) {
ATTRS(mImpl)[i].mName.SetTo(aName);
- ATTRS(mImpl)[i].mValue.Reset();
ATTRS(mImpl)[i].mValue.SwapValueWith(aValue);
-
+ *aHadValue = true;
return NS_OK;
}
}
@@ -576,10 +580,11 @@ nsAttrAndChildArray::IndexOfAttr(nsIAtom* aLocalName, int32_t aNamespaceID) cons
}
nsresult
-nsAttrAndChildArray::SetAndTakeMappedAttr(nsIAtom* aLocalName,
+nsAttrAndChildArray::SetAndSwapMappedAttr(nsIAtom* aLocalName,
nsAttrValue& aValue,
nsMappedAttributeElement* aContent,
- nsHTMLStyleSheet* aSheet)
+ nsHTMLStyleSheet* aSheet,
+ bool* aHadValue)
{
bool willAdd = true;
if (mImpl && mImpl->mMappedAttrs) {
@@ -589,7 +594,7 @@ nsAttrAndChildArray::SetAndTakeMappedAttr(nsIAtom* aLocalName,
RefPtr<nsMappedAttributes> mapped =
GetModifiableMapped(aContent, aSheet, willAdd);
- mapped->SetAndTakeAttr(aLocalName, aValue);
+ mapped->SetAndSwapAttr(aLocalName, aValue, aHadValue);
return MakeMappedUnique(mapped);
}
diff --git a/dom/base/nsAttrAndChildArray.h b/dom/base/nsAttrAndChildArray.h
index ffbad196c..0ce51c52e 100644
--- a/dom/base/nsAttrAndChildArray.h
+++ b/dom/base/nsAttrAndChildArray.h
@@ -91,8 +91,13 @@ public:
nsCaseTreatment aCaseSensitive) const;
const nsAttrValue* AttrAt(uint32_t aPos) const;
// SetAndSwapAttr swaps the current attribute value with aValue.
- nsresult SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue);
- nsresult SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue);
+ // If the attribute was unset, an empty value will be swapped into aValue
+ // and aHadValue will be set to false. Otherwise, aHadValue will be set to
+ // true.
+ nsresult SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue,
+ bool* aHadValue);
+ nsresult SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue,
+ bool* aHadValue);
// Remove the attr at position aPos. The value of the attr is placed in
// aValue; any value that was already in aValue is destroyed.
@@ -110,9 +115,14 @@ public:
const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const;
int32_t IndexOfAttr(nsIAtom* aLocalName, int32_t aNamespaceID = kNameSpaceID_None) const;
- nsresult SetAndTakeMappedAttr(nsIAtom* aLocalName, nsAttrValue& aValue,
+ // SetAndSwapMappedAttr swaps the current attribute value with aValue.
+ // If the attribute was unset, an empty value will be swapped into aValue
+ // and aHadValue will be set to false. Otherwise, aHadValue will be set to
+ // true.
+ nsresult SetAndSwapMappedAttr(nsIAtom* aLocalName, nsAttrValue& aValue,
nsMappedAttributeElement* aContent,
- nsHTMLStyleSheet* aSheet);
+ nsHTMLStyleSheet* aSheet,
+ bool* aHadValue);
nsresult SetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet) {
if (!mImpl || !mImpl->mMappedAttrs) {
return NS_OK;
diff --git a/dom/base/nsMappedAttributeElement.cpp b/dom/base/nsMappedAttributeElement.cpp
index 1c1f8838f..d06cbf2bc 100644
--- a/dom/base/nsMappedAttributeElement.cpp
+++ b/dom/base/nsMappedAttributeElement.cpp
@@ -15,17 +15,19 @@ nsMappedAttributeElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
}
bool
-nsMappedAttributeElement::SetMappedAttribute(nsIDocument* aDocument,
- nsIAtom* aName,
- nsAttrValue& aValue,
- nsresult* aRetval)
+nsMappedAttributeElement::SetAndSwapMappedAttribute(nsIDocument* aDocument,
+ nsIAtom* aName,
+ nsAttrValue& aValue,
+ bool* aValueWasSet,
+ nsresult* aRetval)
+
{
NS_PRECONDITION(aDocument == GetComposedDoc(), "Unexpected document");
nsHTMLStyleSheet* sheet = aDocument ?
aDocument->GetAttributeStyleSheet() : nullptr;
- *aRetval = mAttrsAndChildren.SetAndTakeMappedAttr(aName, aValue,
- this, sheet);
+ *aRetval = mAttrsAndChildren.SetAndSwapMappedAttr(aName, aValue,
+ this, sheet, aValueWasSet);
return true;
}
diff --git a/dom/base/nsMappedAttributeElement.h b/dom/base/nsMappedAttributeElement.h
index 4668b36a1..a37af85ca 100644
--- a/dom/base/nsMappedAttributeElement.h
+++ b/dom/base/nsMappedAttributeElement.h
@@ -39,10 +39,11 @@ public:
nsRuleData* aRuleData);
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
- virtual bool SetMappedAttribute(nsIDocument* aDocument,
- nsIAtom* aName,
- nsAttrValue& aValue,
- nsresult* aRetval) override;
+ virtual bool SetAndSwapMappedAttribute(nsIDocument* aDocument,
+ nsIAtom* aName,
+ nsAttrValue& aValue,
+ bool* aValueWasSet,
+ nsresult* aRetval) override;
};
#endif // NS_MAPPEDATTRIBUTEELEMENT_H_
diff --git a/dom/base/nsMappedAttributes.cpp b/dom/base/nsMappedAttributes.cpp
index 9e80c94df..05ad42310 100644
--- a/dom/base/nsMappedAttributes.cpp
+++ b/dom/base/nsMappedAttributes.cpp
@@ -85,15 +85,16 @@ NS_IMPL_ISUPPORTS(nsMappedAttributes,
nsIStyleRule)
void
-nsMappedAttributes::SetAndTakeAttr(nsIAtom* aAttrName, nsAttrValue& aValue)
+nsMappedAttributes::SetAndSwapAttr(nsIAtom* aAttrName, nsAttrValue& aValue,
+ bool* aValueWasSet)
{
NS_PRECONDITION(aAttrName, "null name");
-
+ *aValueWasSet = false;
uint32_t i;
for (i = 0; i < mAttrCount && !Attrs()[i].mName.IsSmaller(aAttrName); ++i) {
if (Attrs()[i].mName.Equals(aAttrName)) {
- Attrs()[i].mValue.Reset();
Attrs()[i].mValue.SwapValueWith(aValue);
+ *aValueWasSet = true;
return;
}
}
diff --git a/dom/base/nsMappedAttributes.h b/dom/base/nsMappedAttributes.h
index f00b888b9..0c24fd973 100644
--- a/dom/base/nsMappedAttributes.h
+++ b/dom/base/nsMappedAttributes.h
@@ -33,7 +33,8 @@ public:
NS_DECL_ISUPPORTS
- void SetAndTakeAttr(nsIAtom* aAttrName, nsAttrValue& aValue);
+ void SetAndSwapAttr(nsIAtom* aAttrName, nsAttrValue& aValue,
+ bool* aValueWasSet);
const nsAttrValue* GetAttr(nsIAtom* aAttrName) const;
const nsAttrValue* GetAttr(const nsAString& aAttrName) const;
diff --git a/dom/base/nsStyledElement.cpp b/dom/base/nsStyledElement.cpp
index cdfa56461..e3d8dfe57 100644
--- a/dom/base/nsStyledElement.cpp
+++ b/dom/base/nsStyledElement.cpp
@@ -57,6 +57,7 @@ nsStyledElement::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
SetMayHaveStyle();
bool modification = false;
nsAttrValue oldValue;
+ bool oldValueSet = false;
bool hasListeners = aNotify &&
nsContentUtils::HasMutationListeners(this,
@@ -76,6 +77,7 @@ nsStyledElement::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
oldValueStr);
if (modification) {
oldValue.SetTo(oldValueStr);
+ oldValueSet = true;
}
}
else if (aNotify && IsInUncomposedDoc()) {
@@ -92,9 +94,9 @@ nsStyledElement::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
nsIDocument* document = GetComposedDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
return SetAttrAndNotify(kNameSpaceID_None, nsGkAtoms::style, nullptr,
- oldValue, attrValue, modType, hasListeners,
- aNotify, kDontCallAfterSetAttr, document,
- updateBatch);
+ oldValueSet ? &oldValue : nullptr, attrValue, modType,
+ hasListeners, aNotify, kDontCallAfterSetAttr,
+ document, updateBatch);
}
DeclarationBlock*
@@ -145,7 +147,9 @@ nsStyledElement::ReparseStyleAttribute(bool aForceInDataDoc)
ParseStyleAttribute(stringValue, attrValue, aForceInDataDoc);
// Don't bother going through SetInlineStyleDeclaration; we don't
// want to fire off mutation events or document notifications anyway
- nsresult rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue);
+ bool oldValueSet;
+ nsresult rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue,
+ &oldValueSet);
NS_ENSURE_SUCCESS(rv, rv);
}
diff --git a/dom/html/HTMLBodyElement.cpp b/dom/html/HTMLBodyElement.cpp
index f70e20389..112d48dd1 100644
--- a/dom/html/HTMLBodyElement.cpp
+++ b/dom/html/HTMLBodyElement.cpp
@@ -307,10 +307,11 @@ HTMLBodyElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsresult
HTMLBodyElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
- bool aNotify)
+ const nsAttrValue* aOldValue, bool aNotify)
{
nsresult rv = nsGenericHTMLElement::AfterSetAttr(aNameSpaceID,
- aName, aValue, aNotify);
+ aName, aValue, aOldValue,
+ aNotify);
NS_ENSURE_SUCCESS(rv, rv);
// if the last mapped attribute was removed, don't clear the
// nsMappedAttributes, our style can still depend on the containing frame element
diff --git a/dom/html/HTMLBodyElement.h b/dom/html/HTMLBodyElement.h
index ad1f5d872..6a888c71b 100644
--- a/dom/html/HTMLBodyElement.h
+++ b/dom/html/HTMLBodyElement.h
@@ -117,7 +117,9 @@ public:
* Called when an attribute has just been changed
*/
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
protected:
virtual ~HTMLBodyElement();
diff --git a/dom/html/HTMLButtonElement.cpp b/dom/html/HTMLButtonElement.cpp
index c26e60ed0..1a76aac10 100644
--- a/dom/html/HTMLButtonElement.cpp
+++ b/dom/html/HTMLButtonElement.cpp
@@ -437,7 +437,8 @@ HTMLButtonElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult
HTMLButtonElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::type) {
@@ -452,7 +453,8 @@ HTMLButtonElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue,
+ aNotify);
}
NS_IMETHODIMP
diff --git a/dom/html/HTMLButtonElement.h b/dom/html/HTMLButtonElement.h
index 19c93e483..8bab9fd48 100644
--- a/dom/html/HTMLButtonElement.h
+++ b/dom/html/HTMLButtonElement.h
@@ -86,8 +86,10 @@ public:
/**
* Called when an attribute has just been changed
*/
- nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
diff --git a/dom/html/HTMLFieldSetElement.cpp b/dom/html/HTMLFieldSetElement.cpp
index c008b9b6d..f546cad5b 100644
--- a/dom/html/HTMLFieldSetElement.cpp
+++ b/dom/html/HTMLFieldSetElement.cpp
@@ -83,7 +83,8 @@ HTMLFieldSetElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
nsresult
HTMLFieldSetElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled &&
nsINode::GetFirstChild()) {
@@ -100,7 +101,7 @@ HTMLFieldSetElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue, aNotify);
}
// nsIDOMHTMLFieldSetElement
diff --git a/dom/html/HTMLFieldSetElement.h b/dom/html/HTMLFieldSetElement.h
index 1e9f0214f..2c0e9cc14 100644
--- a/dom/html/HTMLFieldSetElement.h
+++ b/dom/html/HTMLFieldSetElement.h
@@ -43,7 +43,9 @@ public:
virtual nsresult GetEventTargetParent(
EventChainPreVisitor& aVisitor) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
virtual nsresult InsertChildAt(nsIContent* aChild, uint32_t aIndex,
bool aNotify) override;
diff --git a/dom/html/HTMLFormElement.cpp b/dom/html/HTMLFormElement.cpp
index bdc05b053..1fdfb602e 100644
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -214,7 +214,8 @@ HTMLFormElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult
HTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aName == nsGkAtoms::novalidate && aNameSpaceID == kNameSpaceID_None) {
// Update all form elements states because they might be [no longer]
@@ -230,7 +231,8 @@ HTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
}
- return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, aNotify);
+ return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
+ aOldValue, aNotify);
}
NS_IMPL_STRING_ATTR(HTMLFormElement, AcceptCharset, acceptcharset)
diff --git a/dom/html/HTMLFormElement.h b/dom/html/HTMLFormElement.h
index e45d4c10d..6102ea61f 100644
--- a/dom/html/HTMLFormElement.h
+++ b/dom/html/HTMLFormElement.h
@@ -114,7 +114,9 @@ public:
nsIAtom* aPrefix, const nsAString& aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
/**
* Forget all information about the current submission (and the fact that we
diff --git a/dom/html/HTMLIFrameElement.cpp b/dom/html/HTMLIFrameElement.cpp
index 0d5a209c0..6ae4ec9dd 100644
--- a/dom/html/HTMLIFrameElement.cpp
+++ b/dom/html/HTMLIFrameElement.cpp
@@ -202,7 +202,7 @@ HTMLIFrameElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult
HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
- bool aNotify)
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aName == nsGkAtoms::sandbox &&
aNameSpaceID == kNameSpaceID_None && mFrameLoader) {
@@ -212,7 +212,7 @@ HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
mFrameLoader->ApplySandboxFlags(GetSandboxFlags());
}
return nsGenericHTMLFrameElement::AfterSetAttr(aNameSpaceID, aName, aValue,
- aNotify);
+ aOldValue, aNotify);
}
nsresult
diff --git a/dom/html/HTMLIFrameElement.h b/dom/html/HTMLIFrameElement.h
index 5bfda2470..23afaaddd 100644
--- a/dom/html/HTMLIFrameElement.h
+++ b/dom/html/HTMLIFrameElement.h
@@ -56,6 +56,7 @@ public:
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
bool aNotify) override;
virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
bool aNotify) override;
diff --git a/dom/html/HTMLImageElement.cpp b/dom/html/HTMLImageElement.cpp
index 5d0cfd15e..dd43ac36a 100644
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -391,7 +391,8 @@ HTMLImageElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult
HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None && mForm &&
(aName == nsGkAtoms::name || aName == nsGkAtoms::id) &&
@@ -433,7 +434,7 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue, aNotify);
}
nsresult
diff --git a/dom/html/HTMLImageElement.h b/dom/html/HTMLImageElement.h
index d92cd84b8..52480d0a0 100644
--- a/dom/html/HTMLImageElement.h
+++ b/dom/html/HTMLImageElement.h
@@ -348,7 +348,9 @@ protected:
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
// This is a weak reference that this element and the HTMLFormElement
// cooperate in maintaining.
diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
index 1d3db145a..7c2688b7e 100644
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -1287,7 +1287,8 @@ HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult
HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
//
@@ -1437,7 +1438,8 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue,
+ aNotify);
}
// nsIDOMHTMLInputElement
diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h
index d6a078f0b..48807f733 100644
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -964,7 +964,9 @@ protected:
* Called when an attribute has just been changed
*/
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
/**
* Dispatch a select event. Returns true if the event was not cancelled.
diff --git a/dom/html/HTMLLinkElement.cpp b/dom/html/HTMLLinkElement.cpp
index 4c42d310a..b05b92d7a 100644
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -348,7 +348,8 @@ HTMLLinkElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult
HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
// It's safe to call ResetLinkState here because our new attr value has
// already been set or unset. ResetLinkState needs the updated attribute
@@ -417,7 +418,7 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
- aNotify);
+ aOldValue, aNotify);
}
nsresult
diff --git a/dom/html/HTMLLinkElement.h b/dom/html/HTMLLinkElement.h
index 9c69cfb13..acac955cb 100644
--- a/dom/html/HTMLLinkElement.h
+++ b/dom/html/HTMLLinkElement.h
@@ -66,6 +66,7 @@ public:
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
bool aNotify) override;
virtual bool IsLink(nsIURI** aURI) const override;
virtual already_AddRefed<nsIURI> GetHrefURI() const override;
diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp
index bc63eab51..4bcc188d3 100644
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3774,7 +3774,8 @@ nsresult HTMLMediaElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttr,
nsresult
HTMLMediaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) {
mSrcMediaSource = nullptr;
@@ -3796,7 +3797,7 @@ HTMLMediaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue, aNotify);
}
nsresult HTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h
index 44c666f95..d81e9f591 100644
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -146,6 +146,7 @@ public:
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
bool aNotify) override;
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
diff --git a/dom/html/HTMLMenuItemElement.cpp b/dom/html/HTMLMenuItemElement.cpp
index 6a8ad8174..3245a16b1 100644
--- a/dom/html/HTMLMenuItemElement.cpp
+++ b/dom/html/HTMLMenuItemElement.cpp
@@ -380,7 +380,8 @@ HTMLMenuItemElement::GetText(nsAString& aText)
nsresult
HTMLMenuItemElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
if ((aName == nsGkAtoms::radiogroup || aName == nsGkAtoms::type) &&
@@ -404,7 +405,7 @@ HTMLMenuItemElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
- aNotify);
+ aOldValue, aNotify);
}
void
diff --git a/dom/html/HTMLMenuItemElement.h b/dom/html/HTMLMenuItemElement.h
index 1da63edd0..cb824edcc 100644
--- a/dom/html/HTMLMenuItemElement.h
+++ b/dom/html/HTMLMenuItemElement.h
@@ -125,7 +125,9 @@ protected:
protected:
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
void WalkRadioGroup(Visitor* aVisitor);
diff --git a/dom/html/HTMLMetaElement.cpp b/dom/html/HTMLMetaElement.cpp
index 47effa2bc..833c3177a 100644
--- a/dom/html/HTMLMetaElement.cpp
+++ b/dom/html/HTMLMetaElement.cpp
@@ -60,7 +60,8 @@ HTMLMetaElement::SetMetaReferrer(nsIDocument* aDocument)
nsresult
HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
nsIDocument *document = GetUncomposedDoc();
@@ -82,7 +83,7 @@ HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
- aNotify);
+ aOldValue, aNotify);
}
nsresult
diff --git a/dom/html/HTMLMetaElement.h b/dom/html/HTMLMetaElement.h
index d3f05826d..0b9117e55 100644
--- a/dom/html/HTMLMetaElement.h
+++ b/dom/html/HTMLMetaElement.h
@@ -33,7 +33,9 @@ public:
bool aNullParent = true) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
diff --git a/dom/html/HTMLOptGroupElement.cpp b/dom/html/HTMLOptGroupElement.cpp
index 0424ccef3..63af4e39f 100644
--- a/dom/html/HTMLOptGroupElement.cpp
+++ b/dom/html/HTMLOptGroupElement.cpp
@@ -101,7 +101,8 @@ HTMLOptGroupElement::RemoveChildAt(uint32_t aIndex, bool aNotify)
nsresult
HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled) {
// All our children <option> have their :disabled state depending on our
@@ -116,7 +117,7 @@ HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
- aNotify);
+ aOldValue, aNotify);
}
EventStates
diff --git a/dom/html/HTMLOptGroupElement.h b/dom/html/HTMLOptGroupElement.h
index c669f43b4..6853e51ed 100644
--- a/dom/html/HTMLOptGroupElement.h
+++ b/dom/html/HTMLOptGroupElement.h
@@ -43,7 +43,9 @@ public:
virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
virtual nsIDOMNode* AsDOMNode() override { return this; }
diff --git a/dom/html/HTMLOptionElement.cpp b/dom/html/HTMLOptionElement.cpp
index 9d861d414..410c5713e 100644
--- a/dom/html/HTMLOptionElement.cpp
+++ b/dom/html/HTMLOptionElement.cpp
@@ -244,7 +244,8 @@ HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsresult
HTMLOptionElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None &&
aName == nsGkAtoms::value && Selected()) {
@@ -258,7 +259,7 @@ HTMLOptionElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue, aNotify);
}
NS_IMETHODIMP
diff --git a/dom/html/HTMLOptionElement.h b/dom/html/HTMLOptionElement.h
index 23ef2fb5e..965cdeb8f 100644
--- a/dom/html/HTMLOptionElement.h
+++ b/dom/html/HTMLOptionElement.h
@@ -50,7 +50,9 @@ public:
const nsAttrValueOrString* aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
void SetSelectedInternal(bool aValue, bool aNotify);
diff --git a/dom/html/HTMLScriptElement.cpp b/dom/html/HTMLScriptElement.cpp
index 095b9b77d..a1bea94d9 100644
--- a/dom/html/HTMLScriptElement.cpp
+++ b/dom/html/HTMLScriptElement.cpp
@@ -232,13 +232,14 @@ HTMLScriptElement::SetNoModule(bool aValue, ErrorResult& aRv)
nsresult
HTMLScriptElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (nsGkAtoms::async == aName && kNameSpaceID_None == aNamespaceID) {
mForceAsync = false;
}
return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
- aNotify);
+ aOldValue, aNotify);
}
NS_IMETHODIMP
diff --git a/dom/html/HTMLScriptElement.h b/dom/html/HTMLScriptElement.h
index 19ceb414f..bd446fa97 100644
--- a/dom/html/HTMLScriptElement.h
+++ b/dom/html/HTMLScriptElement.h
@@ -57,7 +57,9 @@ public:
// Element
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
// WebIDL
void SetText(const nsAString& aValue, ErrorResult& rv);
diff --git a/dom/html/HTMLSelectElement.cpp b/dom/html/HTMLSelectElement.cpp
index a5f88f3fb..d11f8b90f 100644
--- a/dom/html/HTMLSelectElement.cpp
+++ b/dom/html/HTMLSelectElement.cpp
@@ -1283,7 +1283,8 @@ HTMLSelectElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult
HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::disabled) {
@@ -1297,7 +1298,8 @@ HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue,
+ aNotify);
}
nsresult
diff --git a/dom/html/HTMLSelectElement.h b/dom/html/HTMLSelectElement.h
index 8eb7fa410..90e13da7a 100644
--- a/dom/html/HTMLSelectElement.h
+++ b/dom/html/HTMLSelectElement.h
@@ -378,7 +378,9 @@ public:
const nsAttrValueOrString* aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
bool aNotify) override;
diff --git a/dom/html/HTMLSourceElement.cpp b/dom/html/HTMLSourceElement.cpp
index 73d9c9d8c..93a17ea8c 100644
--- a/dom/html/HTMLSourceElement.cpp
+++ b/dom/html/HTMLSourceElement.cpp
@@ -98,7 +98,8 @@ HTMLSourceElement::UpdateMediaList(const nsAttrValue* aValue)
nsresult
HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
// If we are associated with a <picture> with a valid <img>, notify it of
// responsive parameter changes
@@ -143,7 +144,7 @@ HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue, aNotify);
}
nsresult
diff --git a/dom/html/HTMLSourceElement.h b/dom/html/HTMLSourceElement.h
index 595e21015..71b676c2c 100644
--- a/dom/html/HTMLSourceElement.h
+++ b/dom/html/HTMLSourceElement.h
@@ -110,6 +110,7 @@ protected:
protected:
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
bool aNotify) override;
private:
diff --git a/dom/html/HTMLStyleElement.cpp b/dom/html/HTMLStyleElement.cpp
index 329dda648..743f4addb 100644
--- a/dom/html/HTMLStyleElement.cpp
+++ b/dom/html/HTMLStyleElement.cpp
@@ -171,7 +171,8 @@ HTMLStyleElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsresult
HTMLStyleElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::title ||
@@ -185,7 +186,7 @@ HTMLStyleElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
- aNotify);
+ aOldValue, aNotify);
}
NS_IMETHODIMP
diff --git a/dom/html/HTMLStyleElement.h b/dom/html/HTMLStyleElement.h
index 6b2a12b1f..bd69a6aa1 100644
--- a/dom/html/HTMLStyleElement.h
+++ b/dom/html/HTMLStyleElement.h
@@ -48,6 +48,7 @@ public:
bool aNullParent = true) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
bool aNotify) override;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
diff --git a/dom/html/HTMLTableElement.cpp b/dom/html/HTMLTableElement.cpp
index df84a0f77..e6aa71e51 100644
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -933,7 +933,9 @@ HTMLTableElement::BuildInheritedAttributes()
if (modifiableMapped) {
nsAttrValue val(*value);
- modifiableMapped->SetAndTakeAttr(nsGkAtoms::cellpadding, val);
+ bool oldValueSet;
+ modifiableMapped->SetAndSwapAttr(nsGkAtoms::cellpadding, val,
+ &oldValueSet);
}
newAttrs = sheet->UniqueMappedAttributes(modifiableMapped);
NS_ASSERTION(newAttrs, "out of memory, but handling gracefully");
@@ -994,13 +996,13 @@ HTMLTableElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult
HTMLTableElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
- bool aNotify)
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) {
BuildInheritedAttributes();
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
- aNotify);
+ aOldValue, aNotify);
}
} // namespace dom
diff --git a/dom/html/HTMLTableElement.h b/dom/html/HTMLTableElement.h
index 0e907cf54..ce9d224b9 100644
--- a/dom/html/HTMLTableElement.h
+++ b/dom/html/HTMLTableElement.h
@@ -194,7 +194,9 @@ public:
* Called when an attribute has just been changed
*/
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTableElement,
nsGenericHTMLElement)
diff --git a/dom/html/HTMLTextAreaElement.cpp b/dom/html/HTMLTextAreaElement.cpp
index c929daebd..f25241d60 100644
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -1348,7 +1348,8 @@ HTMLTextAreaElement::ContentChanged(nsIContent* aContent)
nsresult
HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
@@ -1367,7 +1368,7 @@ HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue,
- aNotify);
+ aOldValue, aNotify);
}
nsresult
diff --git a/dom/html/HTMLTextAreaElement.h b/dom/html/HTMLTextAreaElement.h
index 8723e85f6..5ab58554e 100644
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -357,7 +357,9 @@ protected:
void ContentChanged(nsIContent* aContent);
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom *aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
/**
* Return if an element should have a specific validity UI
diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp
index 30ecd8508..569dae6c2 100644
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -656,7 +656,8 @@ nsGenericHTMLElement::GetHrefURIForAnchors() const
nsresult
nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNamespaceID == kNameSpaceID_None) {
if (IsEventAttributeName(aName) && aValue) {
@@ -697,7 +698,7 @@ nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
}
return nsGenericHTMLElementBase::AfterSetAttr(aNamespaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue, aNotify);
}
EventListenerManager*
@@ -2015,7 +2016,8 @@ nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult
nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
// add the control to the hashtable as needed
@@ -2064,7 +2066,7 @@ nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue, aNotify);
}
nsresult
diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h
index a8a0d2596..b9c034049 100644
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -915,7 +915,9 @@ private:
protected:
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
virtual mozilla::EventListenerManager*
GetEventListenerManagerForAttr(nsIAtom* aAttrName,
@@ -1267,7 +1269,9 @@ protected:
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
/**
* This method will update the form owner, using @form or looking to a parent.
diff --git a/dom/html/nsGenericHTMLFrameElement.cpp b/dom/html/nsGenericHTMLFrameElement.cpp
index 0a69116a1..1aeb0a7d2 100644
--- a/dom/html/nsGenericHTMLFrameElement.cpp
+++ b/dom/html/nsGenericHTMLFrameElement.cpp
@@ -413,7 +413,7 @@ PrincipalAllowsBrowserFrame(nsIPrincipal* aPrincipal)
/* virtual */ nsresult
nsGenericHTMLFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
- bool aNotify)
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aName == nsGkAtoms::scrolling && aNameSpaceID == kNameSpaceID_None) {
if (mFrameLoader) {
@@ -445,7 +445,7 @@ nsGenericHTMLFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
- aNotify);
+ aOldValue, aNotify);
}
void
diff --git a/dom/html/nsGenericHTMLFrameElement.h b/dom/html/nsGenericHTMLFrameElement.h
index 0367a7fe1..1570b1956 100644
--- a/dom/html/nsGenericHTMLFrameElement.h
+++ b/dom/html/nsGenericHTMLFrameElement.h
@@ -65,6 +65,7 @@ public:
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
bool aNotify) override;
virtual void DestroyContent() override;
diff --git a/dom/svg/SVGAnimationElement.cpp b/dom/svg/SVGAnimationElement.cpp
index d6550c96e..90c26657f 100644
--- a/dom/svg/SVGAnimationElement.cpp
+++ b/dom/svg/SVGAnimationElement.cpp
@@ -299,11 +299,12 @@ SVGAnimationElement::ParseAttribute(int32_t aNamespaceID,
nsresult
SVGAnimationElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
nsresult rv =
SVGAnimationElementBase::AfterSetAttr(aNamespaceID, aName, aValue,
- aNotify);
+ aOldValue, aNotify);
if (SVGTests::IsConditionalProcessingAttribute(aName)) {
bool isDisabled = !SVGTests::PassesConditionalProcessingTests();
diff --git a/dom/svg/SVGAnimationElement.h b/dom/svg/SVGAnimationElement.h
index 9bcbdf0c2..eb602c4a8 100644
--- a/dom/svg/SVGAnimationElement.h
+++ b/dom/svg/SVGAnimationElement.h
@@ -58,7 +58,9 @@ public:
const nsAString& aValue,
nsAttrValue& aResult) override;
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
const nsAttrValue* GetAnimAttr(nsIAtom* aName) const;
bool GetAnimAttr(nsIAtom* aAttName, nsAString& aResult) const;
diff --git a/dom/svg/SVGFEImageElement.cpp b/dom/svg/SVGFEImageElement.cpp
index f235d5ccb..5492f291d 100644
--- a/dom/svg/SVGFEImageElement.cpp
+++ b/dom/svg/SVGFEImageElement.cpp
@@ -119,7 +119,8 @@ SVGFEImageElement::IsAttributeMapped(const nsIAtom* name) const
nsresult
SVGFEImageElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aName == nsGkAtoms::href &&
(aNamespaceID == kNameSpaceID_XLink ||
@@ -139,7 +140,7 @@ SVGFEImageElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
}
return SVGFEImageElementBase::AfterSetAttr(aNamespaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue, aNotify);
}
void
diff --git a/dom/svg/SVGFEImageElement.h b/dom/svg/SVGFEImageElement.h
index edf6f065d..a5b76066a 100644
--- a/dom/svg/SVGFEImageElement.h
+++ b/dom/svg/SVGFEImageElement.h
@@ -58,7 +58,9 @@ public:
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers) override;
diff --git a/dom/svg/SVGImageElement.cpp b/dom/svg/SVGImageElement.cpp
index 524485dee..e240ee416 100644
--- a/dom/svg/SVGImageElement.cpp
+++ b/dom/svg/SVGImageElement.cpp
@@ -150,7 +150,8 @@ SVGImageElement::AsyncEventRunning(AsyncEventDispatcher* aEvent)
nsresult
SVGImageElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aName == nsGkAtoms::href &&
(aNamespaceID == kNameSpaceID_None ||
@@ -169,7 +170,7 @@ SVGImageElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
}
}
return SVGImageElementBase::AfterSetAttr(aNamespaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue, aNotify);
}
void
diff --git a/dom/svg/SVGImageElement.h b/dom/svg/SVGImageElement.h
index 85730212b..e8ea95499 100644
--- a/dom/svg/SVGImageElement.h
+++ b/dom/svg/SVGImageElement.h
@@ -46,7 +46,9 @@ public:
// nsIContent interface
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers) override;
diff --git a/dom/svg/SVGScriptElement.cpp b/dom/svg/SVGScriptElement.cpp
index ffc049c21..0cc827b9f 100644
--- a/dom/svg/SVGScriptElement.cpp
+++ b/dom/svg/SVGScriptElement.cpp
@@ -211,7 +211,8 @@ SVGScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsresult
SVGScriptElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if ((aNamespaceID == kNameSpaceID_XLink ||
aNamespaceID == kNameSpaceID_None) &&
@@ -219,7 +220,7 @@ SVGScriptElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
MaybeProcessScript();
}
return SVGScriptElementBase::AfterSetAttr(aNamespaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue, aNotify);
}
bool
diff --git a/dom/svg/SVGScriptElement.h b/dom/svg/SVGScriptElement.h
index 620a1bcde..d3a233b72 100644
--- a/dom/svg/SVGScriptElement.h
+++ b/dom/svg/SVGScriptElement.h
@@ -55,7 +55,9 @@ public:
nsIContent* aBindingParent,
bool aCompileEventHandlers) override;
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
diff --git a/dom/svg/nsSVGElement.cpp b/dom/svg/nsSVGElement.cpp
index df646fe7d..25d6d944d 100644
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -273,7 +273,9 @@ nsSVGElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
ParseStyleAttribute(stringValue, attrValue, true);
// Don't bother going through SetInlineStyleDeclaration; we don't
// want to fire off mutation events or document notifications anyway
- rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue);
+ bool oldValueSet;
+ rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue,
+ &oldValueSet);
NS_ENSURE_SUCCESS(rv, rv);
}
@@ -282,7 +284,8 @@ nsSVGElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsresult
nsSVGElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
// We don't currently use nsMappedAttributes within SVG. If this changes, we
// need to be very careful because some nsAttrValues used by SVG point to
@@ -310,7 +313,8 @@ nsSVGElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
NS_ENSURE_SUCCESS(rv, rv);
}
- return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aNotify);
+ return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aOldValue,
+ aNotify);
}
bool
@@ -1514,7 +1518,11 @@ nsSVGElement::DidChangeValue(nsIAtom* aName,
nsIDocument* document = GetComposedDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL,
kNotifyDocumentObservers);
- SetAttrAndNotify(kNameSpaceID_None, aName, nullptr, aEmptyOrOldValue,
+ // XXX Really, the fourth argument to SetAttrAndNotify should be null if
+ // aEmptyOrOldValue does not represent the actual previous value of the
+ // attribute, but currently SVG elements do not even use the old attribute
+ // value in |AfterSetAttr|, so this should be ok.
+ SetAttrAndNotify(kNameSpaceID_None, aName, nullptr, &aEmptyOrOldValue,
aNewValue, modType, hasListeners, kNotifyDocumentObservers,
kCallAfterSetAttr, document, updateBatch);
}
@@ -1536,7 +1544,8 @@ nsSVGElement::MaybeSerializeAttrBeforeRemoval(nsIAtom* aName, bool aNotify)
nsAutoString serializedValue;
attrValue->ToString(serializedValue);
nsAttrValue oldAttrValue(serializedValue);
- mAttrsAndChildren.SetAndSwapAttr(aName, oldAttrValue);
+ bool oldValueSet;
+ mAttrsAndChildren.SetAndSwapAttr(aName, oldAttrValue, &oldValueSet);
}
/* static */
diff --git a/dom/svg/nsSVGElement.h b/dom/svg/nsSVGElement.h
index 79278365a..4e8c7a938 100644
--- a/dom/svg/nsSVGElement.h
+++ b/dom/svg/nsSVGElement.h
@@ -336,7 +336,9 @@ protected:
}
#endif // DEBUG
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
virtual bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
const nsAString& aValue, nsAttrValue& aResult) override;
static nsresult ReportAttributeParseFailure(nsIDocument* aDocument,
diff --git a/dom/svg/nsSVGPathGeometryElement.cpp b/dom/svg/nsSVGPathGeometryElement.cpp
index ea2e1c7c4..9b9e96c8f 100644
--- a/dom/svg/nsSVGPathGeometryElement.cpp
+++ b/dom/svg/nsSVGPathGeometryElement.cpp
@@ -26,7 +26,8 @@ nsSVGPathGeometryElement::nsSVGPathGeometryElement(already_AddRefed<mozilla::dom
nsresult
nsSVGPathGeometryElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (mCachedPath &&
aNamespaceID == kNameSpaceID_None &&
@@ -34,7 +35,7 @@ nsSVGPathGeometryElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
mCachedPath = nullptr;
}
return nsSVGPathGeometryElementBase::AfterSetAttr(aNamespaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue, aNotify);
}
bool
diff --git a/dom/svg/nsSVGPathGeometryElement.h b/dom/svg/nsSVGPathGeometryElement.h
index 1091fa0dc..29e90c4e0 100644
--- a/dom/svg/nsSVGPathGeometryElement.h
+++ b/dom/svg/nsSVGPathGeometryElement.h
@@ -45,7 +45,9 @@ public:
explicit nsSVGPathGeometryElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
/**
* Causes this element to discard any Path object that GetOrBuildPath may
diff --git a/dom/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp
index e96bbeef4..af050d9f8 100644
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -360,12 +360,15 @@ nsXULElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
attrValue.SetTo(*originalValue);
}
+ bool oldValueSet;
if (originalName->IsAtom()) {
rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->Atom(),
- attrValue);
+ attrValue,
+ &oldValueSet);
} else {
rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->NodeInfo(),
- attrValue);
+ attrValue,
+ &oldValueSet);
}
NS_ENSURE_SUCCESS(rv, rv);
element->AddListenerFor(*originalName, true);
@@ -1053,7 +1056,8 @@ nsXULElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsresult
nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aValue) {
@@ -1174,7 +1178,7 @@ nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
}
return nsStyledElement::AfterSetAttr(aNamespaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue, aNotify);
}
bool
@@ -1908,12 +1912,14 @@ nsXULElement::MakeHeavyweight(nsXULPrototypeElement* aPrototype)
attrValue.SetTo(protoattr->mValue);
}
+ bool oldValueSet;
// XXX we might wanna have a SetAndTakeAttr that takes an nsAttrName
if (protoattr->mName.IsAtom()) {
- rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.Atom(), attrValue);
+ rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.Atom(),
+ attrValue, &oldValueSet);
} else {
rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.NodeInfo(),
- attrValue);
+ attrValue, &oldValueSet);
}
NS_ENSURE_SUCCESS(rv, rv);
}
diff --git a/dom/xul/nsXULElement.h b/dom/xul/nsXULElement.h
index c2dcadf5f..a30714145 100644
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -627,7 +627,9 @@ protected:
const nsAttrValueOrString* aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify) override;
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
virtual void UpdateEditableState(bool aNotify) override;