From 091d06b43b294390a96106e57a7462f6303107a3 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 17 Apr 2020 05:26:58 -0400 Subject: Bug 1363481 - Add the old attribute value as a parameter to Element::AfterSetAttr Tag #1375 --- dom/base/Element.cpp | 78 +++++++++++++++++++++++----------- dom/base/Element.h | 74 ++++++++++++++++++++++++-------- dom/base/nsAttrAndChildArray.cpp | 21 +++++---- dom/base/nsAttrAndChildArray.h | 18 ++++++-- dom/base/nsMappedAttributeElement.cpp | 14 +++--- dom/base/nsMappedAttributeElement.h | 9 ++-- dom/base/nsMappedAttributes.cpp | 7 +-- dom/base/nsMappedAttributes.h | 3 +- dom/base/nsStyledElement.cpp | 12 ++++-- dom/html/HTMLBodyElement.cpp | 5 ++- dom/html/HTMLBodyElement.h | 4 +- dom/html/HTMLButtonElement.cpp | 6 ++- dom/html/HTMLButtonElement.h | 6 ++- dom/html/HTMLFieldSetElement.cpp | 5 ++- dom/html/HTMLFieldSetElement.h | 4 +- dom/html/HTMLFormElement.cpp | 6 ++- dom/html/HTMLFormElement.h | 4 +- dom/html/HTMLIFrameElement.cpp | 4 +- dom/html/HTMLIFrameElement.h | 1 + dom/html/HTMLImageElement.cpp | 5 ++- dom/html/HTMLImageElement.h | 4 +- dom/html/HTMLInputElement.cpp | 6 ++- dom/html/HTMLInputElement.h | 4 +- dom/html/HTMLLinkElement.cpp | 5 ++- dom/html/HTMLLinkElement.h | 1 + dom/html/HTMLMediaElement.cpp | 5 ++- dom/html/HTMLMediaElement.h | 1 + dom/html/HTMLMenuItemElement.cpp | 5 ++- dom/html/HTMLMenuItemElement.h | 4 +- dom/html/HTMLMetaElement.cpp | 5 ++- dom/html/HTMLMetaElement.h | 4 +- dom/html/HTMLOptGroupElement.cpp | 5 ++- dom/html/HTMLOptGroupElement.h | 4 +- dom/html/HTMLOptionElement.cpp | 5 ++- dom/html/HTMLOptionElement.h | 4 +- dom/html/HTMLScriptElement.cpp | 5 ++- dom/html/HTMLScriptElement.h | 4 +- dom/html/HTMLSelectElement.cpp | 6 ++- dom/html/HTMLSelectElement.h | 4 +- dom/html/HTMLSourceElement.cpp | 5 ++- dom/html/HTMLSourceElement.h | 1 + dom/html/HTMLStyleElement.cpp | 5 ++- dom/html/HTMLStyleElement.h | 1 + dom/html/HTMLTableElement.cpp | 8 ++-- dom/html/HTMLTableElement.h | 4 +- dom/html/HTMLTextAreaElement.cpp | 5 ++- dom/html/HTMLTextAreaElement.h | 4 +- dom/html/nsGenericHTMLElement.cpp | 10 +++-- dom/html/nsGenericHTMLElement.h | 8 +++- dom/html/nsGenericHTMLFrameElement.cpp | 4 +- dom/html/nsGenericHTMLFrameElement.h | 1 + dom/svg/SVGAnimationElement.cpp | 5 ++- dom/svg/SVGAnimationElement.h | 4 +- dom/svg/SVGFEImageElement.cpp | 5 ++- dom/svg/SVGFEImageElement.h | 4 +- dom/svg/SVGImageElement.cpp | 5 ++- dom/svg/SVGImageElement.h | 4 +- dom/svg/SVGScriptElement.cpp | 5 ++- dom/svg/SVGScriptElement.h | 4 +- dom/svg/nsSVGElement.cpp | 19 ++++++--- dom/svg/nsSVGElement.h | 4 +- dom/svg/nsSVGPathGeometryElement.cpp | 5 ++- dom/svg/nsSVGPathGeometryElement.h | 4 +- dom/xul/nsXULElement.cpp | 18 +++++--- dom/xul/nsXULElement.h | 4 +- 65 files changed, 352 insertions(+), 161 deletions(-) (limited to 'dom') 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 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 oldValueAtom = oldValue->GetAsAtom(); + nsCOMPtr 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 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 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 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