Bug 1363481 - Add the old attribute value as a parameter to Element::AfterSetAttr

Tag #1375
This commit is contained in:
Matt A. Tobin 2020-04-17 05:26:58 -04:00 • committed by Roy Tam
commit 1f233fa14b
65 changed files with 352 additions and 161 deletions

View file

@ -2382,7 +2382,8 @@ Element::MaybeCheckSameAttrVal(int32_t aNamespaceID,
bool aNotify, bool aNotify,
nsAttrValue& aOldValue, nsAttrValue& aOldValue,
uint8_t* aModType, uint8_t* aModType,
bool* aHasListeners) bool* aHasListeners,
bool* aOldValueSet)
{ {
bool modification = false; bool modification = false;
*aHasListeners = aNotify && *aHasListeners = aNotify &&
@ -2390,6 +2391,8 @@ Element::MaybeCheckSameAttrVal(int32_t aNamespaceID,
NS_EVENT_BITS_MUTATION_ATTRMODIFIED, NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
this); this);
*aOldValueSet = false;
// If we have no listeners and aNotify is false, we are almost certainly // 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 // 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 // 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 // We have to serialize the value anyway in order to create the
// mutation event so there's no cost in doing it now. // mutation event so there's no cost in doing it now.
aOldValue.SetToSerialized(*info.mValue); aOldValue.SetToSerialized(*info.mValue);
*aOldValueSet = true;
} }
bool valueMatches = aValue.EqualsAsStrings(*info.mValue); bool valueMatches = aValue.EqualsAsStrings(*info.mValue);
if (valueMatches && aPrefix == info.mName->GetPrefix()) { if (valueMatches && aPrefix == info.mName->GetPrefix()) {
@ -2432,10 +2436,12 @@ Element::OnlyNotifySameValueSet(int32_t aNamespaceID, nsIAtom* aName,
nsIAtom* aPrefix, nsIAtom* aPrefix,
const nsAttrValueOrString& aValue, const nsAttrValueOrString& aValue,
bool aNotify, nsAttrValue& aOldValue, bool aNotify, nsAttrValue& aOldValue,
uint8_t* aModType, bool* aHasListeners) uint8_t* aModType, bool* aHasListeners,
bool* aOldValueSet)
{ {
if (!MaybeCheckSameAttrVal(aNamespaceID, aName, aPrefix, aValue, aNotify, if (!MaybeCheckSameAttrVal(aNamespaceID, aName, aPrefix, aValue, aNotify,
aOldValue, aModType, aHasListeners)) { aOldValue, aModType, aHasListeners,
aOldValueSet)) {
return false; return false;
} }
@ -2466,9 +2472,10 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
// OnlyNotifySameValueSet call. // OnlyNotifySameValueSet call.
nsAttrValueOrString value(aValue); nsAttrValueOrString value(aValue);
nsAttrValue oldValue; nsAttrValue oldValue;
bool oldValueSet;
if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify, if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
oldValue, &modType, &hasListeners)) { oldValue, &modType, &hasListeners, &oldValueSet)) {
return NS_OK; return NS_OK;
} }
@ -2501,7 +2508,8 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
attrValue.SetTo(aValue); attrValue.SetTo(aValue);
} }
return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue, return SetAttrAndNotify(aNamespaceID, aName, aPrefix,
oldValueSet ? &oldValue : nullptr,
attrValue, modType, hasListeners, aNotify, attrValue, modType, hasListeners, aNotify,
kCallAfterSetAttr, document, updateBatch); kCallAfterSetAttr, document, updateBatch);
} }
@ -2526,9 +2534,10 @@ Element::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName,
bool hasListeners; bool hasListeners;
nsAttrValueOrString value(aParsedValue); nsAttrValueOrString value(aParsedValue);
nsAttrValue oldValue; nsAttrValue oldValue;
bool oldValueSet;
if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify, if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
oldValue, &modType, &hasListeners)) { oldValue, &modType, &hasListeners, &oldValueSet)) {
return NS_OK; return NS_OK;
} }
@ -2542,7 +2551,8 @@ Element::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName,
nsIDocument* document = GetComposedDoc(); nsIDocument* document = GetComposedDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify); 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, aParsedValue, modType, hasListeners, aNotify,
kCallAfterSetAttr, document, updateBatch); kCallAfterSetAttr, document, updateBatch);
} }
@ -2551,7 +2561,7 @@ nsresult
Element::SetAttrAndNotify(int32_t aNamespaceID, Element::SetAttrAndNotify(int32_t aNamespaceID,
nsIAtom* aName, nsIAtom* aName,
nsIAtom* aPrefix, nsIAtom* aPrefix,
const nsAttrValue& aOldValue, const nsAttrValue* aOldValue,
nsAttrValue& aParsedValue, nsAttrValue& aParsedValue,
uint8_t aModType, uint8_t aModType,
bool aFireMutation, bool aFireMutation,
@ -2573,6 +2583,7 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
bool hadValidDir = false; bool hadValidDir = false;
bool hadDirAuto = false; bool hadDirAuto = false;
bool oldValueSet;
if (aNamespaceID == kNameSpaceID_None) { if (aNamespaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::dir) { if (aName == nsGkAtoms::dir) {
@ -2583,8 +2594,8 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
// XXXbz Perhaps we should push up the attribute mapping function // XXXbz Perhaps we should push up the attribute mapping function
// stuff to Element? // stuff to Element?
if (!IsAttributeMapped(aName) || if (!IsAttributeMapped(aName) ||
!SetMappedAttribute(aComposedDocument, aName, aParsedValue, &rv)) { !SetAndSwapMappedAttribute(aComposedDocument, aName, aParsedValue, &oldValueSet, &rv)) {
rv = mAttrsAndChildren.SetAndSwapAttr(aName, aParsedValue); rv = mAttrsAndChildren.SetAndSwapAttr(aName, aParsedValue, &oldValueSet);
} }
} }
else { else {
@ -2593,14 +2604,24 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
aNamespaceID, aNamespaceID,
nsIDOMNode::ATTRIBUTE_NODE); 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. // If the old value owns its own data, we know it is OK to keep using it.
const nsAttrValue* oldValue = // oldValue will be null if there was no previously set value
aParsedValue.StoresOwnData() ? &aParsedValue : &aOldValue; const nsAttrValue* oldValue;
if (aParsedValue.StoresOwnData()) {
NS_ENSURE_SUCCESS(rv, rv); 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)) { if (aComposedDocument || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
RefPtr<nsXBLBinding> binding = GetXBLBinding(); RefPtr<nsXBLBinding> binding = GetXBLBinding();
@ -2618,7 +2639,14 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
MOZ_ASSERT(data->mState == CustomElementData::State::eCustom, MOZ_ASSERT(data->mState == CustomElementData::State::eCustom,
"AttributeChanged callback should fire only if " "AttributeChanged callback should fire only if "
"custom element state is custom"); "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(); nsCOMPtr<nsIAtom> newValueAtom = valueForAfterSetAttr.GetAsAtom();
nsAutoString ns; nsAutoString ns;
nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns); nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
@ -2638,7 +2666,8 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
} }
if (aCallAfterSetAttr) { if (aCallAfterSetAttr) {
rv = AfterSetAttr(aNamespaceID, aName, &valueForAfterSetAttr, aNotify); rv = AfterSetAttr(aNamespaceID, aName, &valueForAfterSetAttr, oldValue,
aNotify);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) { 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 // Callers only compute aOldValue under certain conditions which may not
// be triggered by all nsIMutationObservers. // be triggered by all nsIMutationObservers.
nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType, nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType,
oldValue == &aParsedValue ? &aParsedValue : nullptr); aParsedValue.StoresOwnData() ? &aParsedValue : nullptr);
} }
if (aFireMutation) { if (aFireMutation) {
@ -2672,7 +2701,7 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
if (!newValue.IsEmpty()) { if (!newValue.IsEmpty()) {
mutation.mNewAttrValue = NS_Atomize(newValue); mutation.mNewAttrValue = NS_Atomize(newValue);
} }
if (!oldValue->IsEmptyString()) { if (oldValue && !oldValue->IsEmptyString()) {
mutation.mPrevAttrValue = oldValue->GetAsAtom(); mutation.mPrevAttrValue = oldValue->GetAsAtom();
} }
mutation.mAttrChange = aModType; mutation.mAttrChange = aModType;
@ -2715,9 +2744,10 @@ Element::ParseAttribute(int32_t aNamespaceID,
} }
bool bool
Element::SetMappedAttribute(nsIDocument* aDocument, Element::SetAndSwapMappedAttribute(nsIDocument* aDocument,
nsIAtom* aName, nsIAtom* aName,
nsAttrValue& aValue, nsAttrValue& aValue,
bool* aValueWasSet,
nsresult* aRetval) nsresult* aRetval)
{ {
*aRetval = NS_OK; *aRetval = NS_OK;
@ -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); NS_ENSURE_SUCCESS(rv, rv);
UpdateState(aNotify); UpdateState(aNotify);

View file

@ -537,25 +537,50 @@ public:
* values will not actually be compared if we aren't notifying and we don't * 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 * have mutation listeners (in which case it's cheap to just return false
* and let the caller go ahead and set the value). * and let the caller go ahead and set the value).
* @param aOldValue Set to the old value of the attribute, but only if there * @param aOldValue [out] Set to the old value of the attribute, but only if
* are event listeners. If set, the type of aOldValue will be either * there are event listeners. If set, the type of aOldValue will be either
* nsAttrValue::eString or nsAttrValue::eAtom. * 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 * nsIDOMMutationEvent::ADDITION, but only if this helper returns true
* @param aHasListeners Set to true if there are mutation event listeners * @param aHasListeners [out] Set to true if there are mutation event
* listening for NS_EVENT_BITS_MUTATION_ATTRMODIFIED * 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, bool MaybeCheckSameAttrVal(int32_t aNamespaceID, nsIAtom* aName,
nsIAtom* aPrefix, nsIAtom* aPrefix,
const nsAttrValueOrString& aValue, const nsAttrValueOrString& aValue,
bool aNotify, nsAttrValue& aOldValue, 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, bool OnlyNotifySameValueSet(int32_t aNamespaceID, nsIAtom* aName,
nsIAtom* aPrefix, nsIAtom* aPrefix,
const nsAttrValueOrString& aValue, const nsAttrValueOrString& aValue,
bool aNotify, nsAttrValue& aOldValue, 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, virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
const nsAString& aValue, bool aNotify) override; const nsAString& aValue, bool aNotify) override;
@ -1261,7 +1286,10 @@ protected:
* its current value) is !StoresOwnData() --- in which * its current value) is !StoresOwnData() --- in which
* case the current value is probably already useless. * case the current value is probably already useless.
* If the current value is StoresOwnData() (or absent), * 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 * @param aParsedValue parsed new value of attribute. Replaced by the
* old value of the attribute. This old value is only * old value of the attribute. This old value is only
* useful if either it or the new value is StoresOwnData. * useful if either it or the new value is StoresOwnData.
@ -1275,7 +1303,7 @@ protected:
nsresult SetAttrAndNotify(int32_t aNamespaceID, nsresult SetAttrAndNotify(int32_t aNamespaceID,
nsIAtom* aName, nsIAtom* aName,
nsIAtom* aPrefix, nsIAtom* aPrefix,
const nsAttrValue& aOldValue, const nsAttrValue* aOldValue,
nsAttrValue& aParsedValue, nsAttrValue& aParsedValue,
uint8_t aModType, uint8_t aModType,
bool aFireMutation, bool aFireMutation,
@ -1320,13 +1348,20 @@ protected:
* *
* @param aDocument the current document of this node (an optimization) * @param aDocument the current document of this node (an optimization)
* @param aName the name of the attribute * @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. * @param [out] aRetval the nsresult status of the operation, if any.
* @return true if the setting was attempted, false otherwise. * @return true if the setting was attempted, false otherwise.
*/ */
virtual bool SetMappedAttribute(nsIDocument* aDocument, virtual bool SetAndSwapMappedAttribute(nsIDocument* aDocument,
nsIAtom* aName, nsIAtom* aName,
nsAttrValue& aValue, nsAttrValue& aValue,
bool* aValueWasSet,
nsresult* aRetval); nsresult* aRetval);
/** /**
@ -1355,19 +1390,24 @@ protected:
/** /**
* Hook that is called by Element::SetAttr to allow subclasses to * Hook that is called by Element::SetAttr to allow subclasses to
* deal with attribute sets. This will only be called after we have called * deal with attribute sets. This will only be called after we have called
* SetAndTakeAttr and AttributeChanged (that is, after we have actually set * SetAndSwapAttr (that is, after we have actually set the attr). It will
* the attr). It will always be called under a scriptblocker. * always be called under a scriptblocker.
* *
* @param aNamespaceID the namespace of the attr being set * @param aNamespaceID the namespace of the attr being set
* @param aName the localname of the attribute 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 * @param aValue the value it's being set to. If null, the attr is being
* removed. * 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. * @param aNotify Whether we plan to notify document observers.
*/ */
// Note that this is inlined so that when subclasses call it it gets // Note that this is inlined so that when subclasses call it it gets
// inlined. Those calls don't go through a vtable. // inlined. Those calls don't go through a vtable.
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{ {
return NS_OK; return NS_OK;
} }

View file

@ -382,12 +382,15 @@ nsAttrAndChildArray::AttrAt(uint32_t aPos) const
} }
nsresult nsresult
nsAttrAndChildArray::SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue) nsAttrAndChildArray::SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue,
bool* aHadValue)
{ {
*aHadValue = false;
uint32_t i, slotCount = AttrSlotCount(); uint32_t i, slotCount = AttrSlotCount();
for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
if (ATTRS(mImpl)[i].mName.Equals(aLocalName)) { if (ATTRS(mImpl)[i].mName.Equals(aLocalName)) {
ATTRS(mImpl)[i].mValue.SwapValueWith(aValue); ATTRS(mImpl)[i].mValue.SwapValueWith(aValue);
*aHadValue = true;
return NS_OK; return NS_OK;
} }
} }
@ -407,21 +410,22 @@ nsAttrAndChildArray::SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue)
} }
nsresult nsresult
nsAttrAndChildArray::SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue) nsAttrAndChildArray::SetAndSwapAttr(mozilla::dom::NodeInfo* aName,
nsAttrValue& aValue, bool* aHadValue)
{ {
int32_t namespaceID = aName->NamespaceID(); int32_t namespaceID = aName->NamespaceID();
nsIAtom* localName = aName->NameAtom(); nsIAtom* localName = aName->NameAtom();
if (namespaceID == kNameSpaceID_None) { if (namespaceID == kNameSpaceID_None) {
return SetAndSwapAttr(localName, aValue); return SetAndSwapAttr(localName, aValue, aHadValue);
} }
*aHadValue = false;
uint32_t i, slotCount = AttrSlotCount(); uint32_t i, slotCount = AttrSlotCount();
for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
if (ATTRS(mImpl)[i].mName.Equals(localName, namespaceID)) { if (ATTRS(mImpl)[i].mName.Equals(localName, namespaceID)) {
ATTRS(mImpl)[i].mName.SetTo(aName); ATTRS(mImpl)[i].mName.SetTo(aName);
ATTRS(mImpl)[i].mValue.Reset();
ATTRS(mImpl)[i].mValue.SwapValueWith(aValue); ATTRS(mImpl)[i].mValue.SwapValueWith(aValue);
*aHadValue = true;
return NS_OK; return NS_OK;
} }
} }
@ -576,10 +580,11 @@ nsAttrAndChildArray::IndexOfAttr(nsIAtom* aLocalName, int32_t aNamespaceID) cons
} }
nsresult nsresult
nsAttrAndChildArray::SetAndTakeMappedAttr(nsIAtom* aLocalName, nsAttrAndChildArray::SetAndSwapMappedAttr(nsIAtom* aLocalName,
nsAttrValue& aValue, nsAttrValue& aValue,
nsMappedAttributeElement* aContent, nsMappedAttributeElement* aContent,
nsHTMLStyleSheet* aSheet) nsHTMLStyleSheet* aSheet,
bool* aHadValue)
{ {
bool willAdd = true; bool willAdd = true;
if (mImpl && mImpl->mMappedAttrs) { if (mImpl && mImpl->mMappedAttrs) {
@ -589,7 +594,7 @@ nsAttrAndChildArray::SetAndTakeMappedAttr(nsIAtom* aLocalName,
RefPtr<nsMappedAttributes> mapped = RefPtr<nsMappedAttributes> mapped =
GetModifiableMapped(aContent, aSheet, willAdd); GetModifiableMapped(aContent, aSheet, willAdd);
mapped->SetAndTakeAttr(aLocalName, aValue); mapped->SetAndSwapAttr(aLocalName, aValue, aHadValue);
return MakeMappedUnique(mapped); return MakeMappedUnique(mapped);
} }

View file

@ -91,8 +91,13 @@ public:
nsCaseTreatment aCaseSensitive) const; nsCaseTreatment aCaseSensitive) const;
const nsAttrValue* AttrAt(uint32_t aPos) const; const nsAttrValue* AttrAt(uint32_t aPos) const;
// SetAndSwapAttr swaps the current attribute value with aValue. // SetAndSwapAttr swaps the current attribute value with aValue.
nsresult SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue); // If the attribute was unset, an empty value will be swapped into aValue
nsresult SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& 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 // Remove the attr at position aPos. The value of the attr is placed in
// aValue; any value that was already in aValue is destroyed. // aValue; any value that was already in aValue is destroyed.
@ -110,9 +115,14 @@ public:
const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const; const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const;
int32_t IndexOfAttr(nsIAtom* aLocalName, int32_t aNamespaceID = kNameSpaceID_None) 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, nsMappedAttributeElement* aContent,
nsHTMLStyleSheet* aSheet); nsHTMLStyleSheet* aSheet,
bool* aHadValue);
nsresult SetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet) { nsresult SetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet) {
if (!mImpl || !mImpl->mMappedAttrs) { if (!mImpl || !mImpl->mMappedAttrs) {
return NS_OK; return NS_OK;

View file

@ -15,17 +15,19 @@ nsMappedAttributeElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
} }
bool bool
nsMappedAttributeElement::SetMappedAttribute(nsIDocument* aDocument, nsMappedAttributeElement::SetAndSwapMappedAttribute(nsIDocument* aDocument,
nsIAtom* aName, nsIAtom* aName,
nsAttrValue& aValue, nsAttrValue& aValue,
bool* aValueWasSet,
nsresult* aRetval) nsresult* aRetval)
{ {
NS_PRECONDITION(aDocument == GetComposedDoc(), "Unexpected document"); NS_PRECONDITION(aDocument == GetComposedDoc(), "Unexpected document");
nsHTMLStyleSheet* sheet = aDocument ? nsHTMLStyleSheet* sheet = aDocument ?
aDocument->GetAttributeStyleSheet() : nullptr; aDocument->GetAttributeStyleSheet() : nullptr;
*aRetval = mAttrsAndChildren.SetAndTakeMappedAttr(aName, aValue, *aRetval = mAttrsAndChildren.SetAndSwapMappedAttr(aName, aValue,
this, sheet); this, sheet, aValueWasSet);
return true; return true;
} }

View file

@ -39,9 +39,10 @@ public:
nsRuleData* aRuleData); nsRuleData* aRuleData);
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override; NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
virtual bool SetMappedAttribute(nsIDocument* aDocument, virtual bool SetAndSwapMappedAttribute(nsIDocument* aDocument,
nsIAtom* aName, nsIAtom* aName,
nsAttrValue& aValue, nsAttrValue& aValue,
bool* aValueWasSet,
nsresult* aRetval) override; nsresult* aRetval) override;
}; };

View file

@ -85,15 +85,16 @@ NS_IMPL_ISUPPORTS(nsMappedAttributes,
nsIStyleRule) nsIStyleRule)
void void
nsMappedAttributes::SetAndTakeAttr(nsIAtom* aAttrName, nsAttrValue& aValue) nsMappedAttributes::SetAndSwapAttr(nsIAtom* aAttrName, nsAttrValue& aValue,
bool* aValueWasSet)
{ {
NS_PRECONDITION(aAttrName, "null name"); NS_PRECONDITION(aAttrName, "null name");
*aValueWasSet = false;
uint32_t i; uint32_t i;
for (i = 0; i < mAttrCount && !Attrs()[i].mName.IsSmaller(aAttrName); ++i) { for (i = 0; i < mAttrCount && !Attrs()[i].mName.IsSmaller(aAttrName); ++i) {
if (Attrs()[i].mName.Equals(aAttrName)) { if (Attrs()[i].mName.Equals(aAttrName)) {
Attrs()[i].mValue.Reset();
Attrs()[i].mValue.SwapValueWith(aValue); Attrs()[i].mValue.SwapValueWith(aValue);
*aValueWasSet = true;
return; return;
} }
} }

View file

@ -33,7 +33,8 @@ public:
NS_DECL_ISUPPORTS 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(nsIAtom* aAttrName) const;
const nsAttrValue* GetAttr(const nsAString& aAttrName) const; const nsAttrValue* GetAttr(const nsAString& aAttrName) const;

View file

@ -57,6 +57,7 @@ nsStyledElement::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
SetMayHaveStyle(); SetMayHaveStyle();
bool modification = false; bool modification = false;
nsAttrValue oldValue; nsAttrValue oldValue;
bool oldValueSet = false;
bool hasListeners = aNotify && bool hasListeners = aNotify &&
nsContentUtils::HasMutationListeners(this, nsContentUtils::HasMutationListeners(this,
@ -76,6 +77,7 @@ nsStyledElement::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
oldValueStr); oldValueStr);
if (modification) { if (modification) {
oldValue.SetTo(oldValueStr); oldValue.SetTo(oldValueStr);
oldValueSet = true;
} }
} }
else if (aNotify && IsInUncomposedDoc()) { else if (aNotify && IsInUncomposedDoc()) {
@ -92,9 +94,9 @@ nsStyledElement::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
nsIDocument* document = GetComposedDoc(); nsIDocument* document = GetComposedDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify); mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
return SetAttrAndNotify(kNameSpaceID_None, nsGkAtoms::style, nullptr, return SetAttrAndNotify(kNameSpaceID_None, nsGkAtoms::style, nullptr,
oldValue, attrValue, modType, hasListeners, oldValueSet ? &oldValue : nullptr, attrValue, modType,
aNotify, kDontCallAfterSetAttr, document, hasListeners, aNotify, kDontCallAfterSetAttr,
updateBatch); document, updateBatch);
} }
DeclarationBlock* DeclarationBlock*
@ -145,7 +147,9 @@ nsStyledElement::ReparseStyleAttribute(bool aForceInDataDoc)
ParseStyleAttribute(stringValue, attrValue, aForceInDataDoc); ParseStyleAttribute(stringValue, attrValue, aForceInDataDoc);
// Don't bother going through SetInlineStyleDeclaration; we don't // Don't bother going through SetInlineStyleDeclaration; we don't
// want to fire off mutation events or document notifications anyway // 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); NS_ENSURE_SUCCESS(rv, rv);
} }

View file

@ -307,10 +307,11 @@ HTMLBodyElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsresult nsresult
HTMLBodyElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLBodyElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, const nsAttrValue* aValue,
bool aNotify) const nsAttrValue* aOldValue, bool aNotify)
{ {
nsresult rv = nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, nsresult rv = nsGenericHTMLElement::AfterSetAttr(aNameSpaceID,
aName, aValue, aNotify); aName, aValue, aOldValue,
aNotify);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// if the last mapped attribute was removed, don't clear the // if the last mapped attribute was removed, don't clear the
// nsMappedAttributes, our style can still depend on the containing frame element // nsMappedAttributes, our style can still depend on the containing frame element

View file

@ -117,7 +117,9 @@ public:
* Called when an attribute has just been changed * Called when an attribute has just been changed
*/ */
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override; const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override;
protected: protected:
virtual ~HTMLBodyElement(); virtual ~HTMLBodyElement();

View file

@ -437,7 +437,8 @@ HTMLButtonElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult nsresult
HTMLButtonElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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 (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::type) { if (aName == nsGkAtoms::type) {
@ -452,7 +453,8 @@ HTMLButtonElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify); aValue, aOldValue,
aNotify);
} }
NS_IMETHODIMP NS_IMETHODIMP

View file

@ -86,8 +86,10 @@ public:
/** /**
* Called when an attribute has just been changed * Called when an attribute has just been changed
*/ */
nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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, virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute, nsIAtom* aAttribute,
const nsAString& aValue, const nsAString& aValue,

View file

@ -83,7 +83,8 @@ HTMLFieldSetElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
nsresult nsresult
HTMLFieldSetElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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 && if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled &&
nsINode::GetFirstChild()) { nsINode::GetFirstChild()) {
@ -100,7 +101,7 @@ HTMLFieldSetElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName, return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify); aValue, aOldValue, aNotify);
} }
// nsIDOMHTMLFieldSetElement // nsIDOMHTMLFieldSetElement

View file

@ -43,7 +43,9 @@ public:
virtual nsresult GetEventTargetParent( virtual nsresult GetEventTargetParent(
EventChainPreVisitor& aVisitor) override; EventChainPreVisitor& aVisitor) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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, virtual nsresult InsertChildAt(nsIContent* aChild, uint32_t aIndex,
bool aNotify) override; bool aNotify) override;

View file

@ -214,7 +214,8 @@ HTMLFormElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult nsresult
HTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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) { if (aName == nsGkAtoms::novalidate && aNameSpaceID == kNameSpaceID_None) {
// Update all form elements states because they might be [no longer] // 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) NS_IMPL_STRING_ATTR(HTMLFormElement, AcceptCharset, acceptcharset)

View file

@ -114,7 +114,9 @@ public:
nsIAtom* aPrefix, const nsAString& aValue, nsIAtom* aPrefix, const nsAString& aValue,
bool aNotify) override; bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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 * Forget all information about the current submission (and the fact that we

View file

@ -202,7 +202,7 @@ HTMLIFrameElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult nsresult
HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, const nsAttrValue* aValue,
bool aNotify) const nsAttrValue* aOldValue, bool aNotify)
{ {
if (aName == nsGkAtoms::sandbox && if (aName == nsGkAtoms::sandbox &&
aNameSpaceID == kNameSpaceID_None && mFrameLoader) { aNameSpaceID == kNameSpaceID_None && mFrameLoader) {
@ -212,7 +212,7 @@ HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
mFrameLoader->ApplySandboxFlags(GetSandboxFlags()); mFrameLoader->ApplySandboxFlags(GetSandboxFlags());
} }
return nsGenericHTMLFrameElement::AfterSetAttr(aNameSpaceID, aName, aValue, return nsGenericHTMLFrameElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify); aOldValue, aNotify);
} }
nsresult nsresult

View file

@ -56,6 +56,7 @@ public:
bool aNotify) override; bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override; bool aNotify) override;
virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
bool aNotify) override; bool aNotify) override;

View file

@ -391,7 +391,8 @@ HTMLImageElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult nsresult
HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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 && if (aNameSpaceID == kNameSpaceID_None && mForm &&
(aName == nsGkAtoms::name || aName == nsGkAtoms::id) && (aName == nsGkAtoms::name || aName == nsGkAtoms::id) &&
@ -433,7 +434,7 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify); aValue, aOldValue, aNotify);
} }
nsresult nsresult

View file

@ -348,7 +348,9 @@ protected:
bool aNotify) override; bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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 // This is a weak reference that this element and the HTMLFormElement
// cooperate in maintaining. // cooperate in maintaining.

View file

@ -1287,7 +1287,8 @@ HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult nsresult
HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{ {
if (aNameSpaceID == kNameSpaceID_None) { if (aNameSpaceID == kNameSpaceID_None) {
// //
@ -1437,7 +1438,8 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify); aValue, aOldValue,
aNotify);
} }
// nsIDOMHTMLInputElement // nsIDOMHTMLInputElement

View file

@ -964,7 +964,9 @@ protected:
* Called when an attribute has just been changed * Called when an attribute has just been changed
*/ */
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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. * Dispatch a select event. Returns true if the event was not cancelled.

View file

@ -348,7 +348,8 @@ HTMLLinkElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult nsresult
HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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 // It's safe to call ResetLinkState here because our new attr value has
// already been set or unset. ResetLinkState needs the updated attribute // 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, return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify); aOldValue, aNotify);
} }
nsresult nsresult

View file

@ -66,6 +66,7 @@ public:
bool aNotify) override; bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override; bool aNotify) override;
virtual bool IsLink(nsIURI** aURI) const override; virtual bool IsLink(nsIURI** aURI) const override;
virtual already_AddRefed<nsIURI> GetHrefURI() const override; virtual already_AddRefed<nsIURI> GetHrefURI() const override;

View file

@ -3774,7 +3774,8 @@ nsresult HTMLMediaElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttr,
nsresult nsresult
HTMLMediaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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) { if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) {
mSrcMediaSource = nullptr; mSrcMediaSource = nullptr;
@ -3796,7 +3797,7 @@ HTMLMediaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify); aValue, aOldValue, aNotify);
} }
nsresult HTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsresult HTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,

View file

@ -146,6 +146,7 @@ public:
bool aNotify) override; bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override; bool aNotify) override;
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,

View file

@ -380,7 +380,8 @@ HTMLMenuItemElement::GetText(nsAString& aText)
nsresult nsresult
HTMLMenuItemElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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 (aNameSpaceID == kNameSpaceID_None) {
if ((aName == nsGkAtoms::radiogroup || aName == nsGkAtoms::type) && if ((aName == nsGkAtoms::radiogroup || aName == nsGkAtoms::type) &&
@ -404,7 +405,7 @@ HTMLMenuItemElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify); aOldValue, aNotify);
} }
void void

View file

@ -125,7 +125,9 @@ protected:
protected: protected:
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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); void WalkRadioGroup(Visitor* aVisitor);

View file

@ -60,7 +60,8 @@ HTMLMetaElement::SetMetaReferrer(nsIDocument* aDocument)
nsresult nsresult
HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{ {
if (aNameSpaceID == kNameSpaceID_None) { if (aNameSpaceID == kNameSpaceID_None) {
nsIDocument *document = GetUncomposedDoc(); nsIDocument *document = GetUncomposedDoc();
@ -82,7 +83,7 @@ HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify); aOldValue, aNotify);
} }
nsresult nsresult

View file

@ -33,7 +33,9 @@ public:
bool aNullParent = true) override; bool aNullParent = true) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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); void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);

View file

@ -102,7 +102,8 @@ HTMLOptGroupElement::RemoveChildAt(uint32_t aIndex, bool aNotify)
nsresult nsresult
HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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) { if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled) {
// All our children <option> have their :disabled state depending on our // All our children <option> have their :disabled state depending on our
@ -117,7 +118,7 @@ HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify); aOldValue, aNotify);
} }
EventStates EventStates

View file

@ -43,7 +43,9 @@ public:
virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override; virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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; } virtual nsIDOMNode* AsDOMNode() override { return this; }

View file

@ -244,7 +244,8 @@ HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsresult nsresult
HTMLOptionElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLOptionElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{ {
if (aNameSpaceID == kNameSpaceID_None && if (aNameSpaceID == kNameSpaceID_None &&
aName == nsGkAtoms::value && Selected()) { aName == nsGkAtoms::value && Selected()) {
@ -258,7 +259,7 @@ HTMLOptionElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify); aValue, aOldValue, aNotify);
} }
NS_IMETHODIMP NS_IMETHODIMP

View file

@ -50,7 +50,9 @@ public:
const nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) override; bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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); void SetSelectedInternal(bool aValue, bool aNotify);

View file

@ -232,13 +232,14 @@ HTMLScriptElement::SetNoModule(bool aValue, ErrorResult& aRv)
nsresult nsresult
HTMLScriptElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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) { if (nsGkAtoms::async == aName && kNameSpaceID_None == aNamespaceID) {
mForceAsync = false; mForceAsync = false;
} }
return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue, return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
aNotify); aOldValue, aNotify);
} }
NS_IMETHODIMP NS_IMETHODIMP

View file

@ -57,7 +57,9 @@ public:
// Element // Element
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override; const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override;
// WebIDL // WebIDL
void SetText(const nsAString& aValue, ErrorResult& rv); void SetText(const nsAString& aValue, ErrorResult& rv);

View file

@ -1283,7 +1283,8 @@ HTMLSelectElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult nsresult
HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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 (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::disabled) { if (aName == nsGkAtoms::disabled) {
@ -1297,7 +1298,8 @@ HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify); aValue, aOldValue,
aNotify);
} }
nsresult nsresult

View file

@ -378,7 +378,9 @@ public:
const nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) override; bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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, virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
bool aNotify) override; bool aNotify) override;

View file

@ -98,7 +98,8 @@ HTMLSourceElement::UpdateMediaList(const nsAttrValue* aValue)
nsresult nsresult
HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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 // If we are associated with a <picture> with a valid <img>, notify it of
// responsive parameter changes // responsive parameter changes
@ -143,7 +144,7 @@ HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify); aValue, aOldValue, aNotify);
} }
nsresult nsresult

View file

@ -110,6 +110,7 @@ protected:
protected: protected:
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override; bool aNotify) override;
private: private:

View file

@ -171,7 +171,8 @@ HTMLStyleElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsresult nsresult
HTMLStyleElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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 (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::title || if (aName == nsGkAtoms::title ||
@ -185,7 +186,7 @@ HTMLStyleElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify); aOldValue, aNotify);
} }
NS_IMETHODIMP NS_IMETHODIMP

View file

@ -48,6 +48,7 @@ public:
bool aNullParent = true) override; bool aNullParent = true) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override; bool aNotify) override;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;

View file

@ -933,7 +933,9 @@ HTMLTableElement::BuildInheritedAttributes()
if (modifiableMapped) { if (modifiableMapped) {
nsAttrValue val(*value); nsAttrValue val(*value);
modifiableMapped->SetAndTakeAttr(nsGkAtoms::cellpadding, val); bool oldValueSet;
modifiableMapped->SetAndSwapAttr(nsGkAtoms::cellpadding, val,
&oldValueSet);
} }
newAttrs = sheet->UniqueMappedAttributes(modifiableMapped); newAttrs = sheet->UniqueMappedAttributes(modifiableMapped);
NS_ASSERTION(newAttrs, "out of memory, but handling gracefully"); NS_ASSERTION(newAttrs, "out of memory, but handling gracefully");
@ -994,13 +996,13 @@ HTMLTableElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult nsresult
HTMLTableElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLTableElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, const nsAttrValue* aValue,
bool aNotify) const nsAttrValue* aOldValue, bool aNotify)
{ {
if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) {
BuildInheritedAttributes(); BuildInheritedAttributes();
} }
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify); aOldValue, aNotify);
} }
} // namespace dom } // namespace dom

View file

@ -194,7 +194,9 @@ public:
* Called when an attribute has just been changed * Called when an attribute has just been changed
*/ */
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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, NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTableElement,
nsGenericHTMLElement) nsGenericHTMLElement)

View file

@ -1348,7 +1348,8 @@ HTMLTextAreaElement::ContentChanged(nsIContent* aContent)
nsresult nsresult
HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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 (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled || if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
@ -1367,7 +1368,7 @@ HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue, return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify); aOldValue, aNotify);
} }
nsresult nsresult

View file

@ -357,7 +357,9 @@ protected:
void ContentChanged(nsIContent* aContent); void ContentChanged(nsIContent* aContent);
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom *aName, 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 * Return if an element should have a specific validity UI

View file

@ -656,7 +656,8 @@ nsGenericHTMLElement::GetHrefURIForAnchors() const
nsresult nsresult
nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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 (aNamespaceID == kNameSpaceID_None) {
if (IsEventAttributeName(aName) && aValue) { if (IsEventAttributeName(aName) && aValue) {
@ -697,7 +698,7 @@ nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
} }
return nsGenericHTMLElementBase::AfterSetAttr(aNamespaceID, aName, return nsGenericHTMLElementBase::AfterSetAttr(aNamespaceID, aName,
aValue, aNotify); aValue, aOldValue, aNotify);
} }
EventListenerManager* EventListenerManager*
@ -2015,7 +2016,8 @@ nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult nsresult
nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{ {
if (aNameSpaceID == kNameSpaceID_None) { if (aNameSpaceID == kNameSpaceID_None) {
// add the control to the hashtable as needed // add the control to the hashtable as needed
@ -2064,7 +2066,7 @@ nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify); aValue, aOldValue, aNotify);
} }
nsresult nsresult

View file

@ -915,7 +915,9 @@ private:
protected: protected:
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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* virtual mozilla::EventListenerManager*
GetEventListenerManagerForAttr(nsIAtom* aAttrName, GetEventListenerManagerForAttr(nsIAtom* aAttrName,
@ -1269,7 +1271,9 @@ protected:
bool aNotify) override; bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, 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. * This method will update the form owner, using @form or looking to a parent.

View file

@ -413,7 +413,7 @@ PrincipalAllowsBrowserFrame(nsIPrincipal* aPrincipal)
/* virtual */ nsresult /* virtual */ nsresult
nsGenericHTMLFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsGenericHTMLFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, const nsAttrValue* aValue,
bool aNotify) const nsAttrValue* aOldValue, bool aNotify)
{ {
if (aName == nsGkAtoms::scrolling && aNameSpaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::scrolling && aNameSpaceID == kNameSpaceID_None) {
if (mFrameLoader) { if (mFrameLoader) {
@ -445,7 +445,7 @@ nsGenericHTMLFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify); aOldValue, aNotify);
} }
void void

View file

@ -65,6 +65,7 @@ public:
bool aNotify) override; bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override; bool aNotify) override;
virtual void DestroyContent() override; virtual void DestroyContent() override;

View file

@ -299,11 +299,12 @@ SVGAnimationElement::ParseAttribute(int32_t aNamespaceID,
nsresult nsresult
SVGAnimationElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, SVGAnimationElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{ {
nsresult rv = nsresult rv =
SVGAnimationElementBase::AfterSetAttr(aNamespaceID, aName, aValue, SVGAnimationElementBase::AfterSetAttr(aNamespaceID, aName, aValue,
aNotify); aOldValue, aNotify);
if (SVGTests::IsConditionalProcessingAttribute(aName)) { if (SVGTests::IsConditionalProcessingAttribute(aName)) {
bool isDisabled = !SVGTests::PassesConditionalProcessingTests(); bool isDisabled = !SVGTests::PassesConditionalProcessingTests();

View file

@ -58,7 +58,9 @@ public:
const nsAString& aValue, const nsAString& aValue,
nsAttrValue& aResult) override; nsAttrValue& aResult) override;
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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; const nsAttrValue* GetAnimAttr(nsIAtom* aName) const;
bool GetAnimAttr(nsIAtom* aAttName, nsAString& aResult) const; bool GetAnimAttr(nsIAtom* aAttName, nsAString& aResult) const;

View file

@ -119,7 +119,8 @@ SVGFEImageElement::IsAttributeMapped(const nsIAtom* name) const
nsresult nsresult
SVGFEImageElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, SVGFEImageElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{ {
if (aName == nsGkAtoms::href && if (aName == nsGkAtoms::href &&
(aNamespaceID == kNameSpaceID_XLink || (aNamespaceID == kNameSpaceID_XLink ||
@ -139,7 +140,7 @@ SVGFEImageElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
} }
return SVGFEImageElementBase::AfterSetAttr(aNamespaceID, aName, return SVGFEImageElementBase::AfterSetAttr(aNamespaceID, aName,
aValue, aNotify); aValue, aOldValue, aNotify);
} }
void void

View file

@ -58,7 +58,9 @@ public:
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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, virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent, nsIContent* aBindingParent,
bool aCompileEventHandlers) override; bool aCompileEventHandlers) override;

View file

@ -150,7 +150,8 @@ SVGImageElement::AsyncEventRunning(AsyncEventDispatcher* aEvent)
nsresult nsresult
SVGImageElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, SVGImageElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{ {
if (aName == nsGkAtoms::href && if (aName == nsGkAtoms::href &&
(aNamespaceID == kNameSpaceID_None || (aNamespaceID == kNameSpaceID_None ||
@ -169,7 +170,7 @@ SVGImageElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
} }
} }
return SVGImageElementBase::AfterSetAttr(aNamespaceID, aName, return SVGImageElementBase::AfterSetAttr(aNamespaceID, aName,
aValue, aNotify); aValue, aOldValue, aNotify);
} }
void void

View file

@ -46,7 +46,9 @@ public:
// nsIContent interface // nsIContent interface
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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, virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent, nsIContent* aBindingParent,
bool aCompileEventHandlers) override; bool aCompileEventHandlers) override;

View file

@ -211,7 +211,8 @@ SVGScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsresult nsresult
SVGScriptElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, SVGScriptElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{ {
if ((aNamespaceID == kNameSpaceID_XLink || if ((aNamespaceID == kNameSpaceID_XLink ||
aNamespaceID == kNameSpaceID_None) && aNamespaceID == kNameSpaceID_None) &&
@ -219,7 +220,7 @@ SVGScriptElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
MaybeProcessScript(); MaybeProcessScript();
} }
return SVGScriptElementBase::AfterSetAttr(aNamespaceID, aName, return SVGScriptElementBase::AfterSetAttr(aNamespaceID, aName,
aValue, aNotify); aValue, aOldValue, aNotify);
} }
bool bool

View file

@ -55,7 +55,9 @@ public:
nsIContent* aBindingParent, nsIContent* aBindingParent,
bool aCompileEventHandlers) override; bool aCompileEventHandlers) override;
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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, virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute, nsIAtom* aAttribute,
const nsAString& aValue, const nsAString& aValue,

View file

@ -273,7 +273,9 @@ nsSVGElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
ParseStyleAttribute(stringValue, attrValue, true); ParseStyleAttribute(stringValue, attrValue, true);
// Don't bother going through SetInlineStyleDeclaration; we don't // Don't bother going through SetInlineStyleDeclaration; we don't
// want to fire off mutation events or document notifications anyway // 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); NS_ENSURE_SUCCESS(rv, rv);
} }
@ -282,7 +284,8 @@ nsSVGElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsresult nsresult
nsSVGElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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 // 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 // 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); NS_ENSURE_SUCCESS(rv, rv);
} }
return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aNotify); return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aOldValue,
aNotify);
} }
bool bool
@ -1514,7 +1518,11 @@ nsSVGElement::DidChangeValue(nsIAtom* aName,
nsIDocument* document = GetComposedDoc(); nsIDocument* document = GetComposedDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL,
kNotifyDocumentObservers); 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, aNewValue, modType, hasListeners, kNotifyDocumentObservers,
kCallAfterSetAttr, document, updateBatch); kCallAfterSetAttr, document, updateBatch);
} }
@ -1536,7 +1544,8 @@ nsSVGElement::MaybeSerializeAttrBeforeRemoval(nsIAtom* aName, bool aNotify)
nsAutoString serializedValue; nsAutoString serializedValue;
attrValue->ToString(serializedValue); attrValue->ToString(serializedValue);
nsAttrValue oldAttrValue(serializedValue); nsAttrValue oldAttrValue(serializedValue);
mAttrsAndChildren.SetAndSwapAttr(aName, oldAttrValue); bool oldValueSet;
mAttrsAndChildren.SetAndSwapAttr(aName, oldAttrValue, &oldValueSet);
} }
/* static */ /* static */

View file

@ -336,7 +336,9 @@ protected:
} }
#endif // DEBUG #endif // DEBUG
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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, virtual bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
const nsAString& aValue, nsAttrValue& aResult) override; const nsAString& aValue, nsAttrValue& aResult) override;
static nsresult ReportAttributeParseFailure(nsIDocument* aDocument, static nsresult ReportAttributeParseFailure(nsIDocument* aDocument,

View file

@ -26,7 +26,8 @@ nsSVGPathGeometryElement::nsSVGPathGeometryElement(already_AddRefed<mozilla::dom
nsresult nsresult
nsSVGPathGeometryElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, nsSVGPathGeometryElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{ {
if (mCachedPath && if (mCachedPath &&
aNamespaceID == kNameSpaceID_None && aNamespaceID == kNameSpaceID_None &&
@ -34,7 +35,7 @@ nsSVGPathGeometryElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
mCachedPath = nullptr; mCachedPath = nullptr;
} }
return nsSVGPathGeometryElementBase::AfterSetAttr(aNamespaceID, aName, return nsSVGPathGeometryElementBase::AfterSetAttr(aNamespaceID, aName,
aValue, aNotify); aValue, aOldValue, aNotify);
} }
bool bool

View file

@ -45,7 +45,9 @@ public:
explicit nsSVGPathGeometryElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo); explicit nsSVGPathGeometryElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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 * Causes this element to discard any Path object that GetOrBuildPath may

View file

@ -360,12 +360,15 @@ nsXULElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
attrValue.SetTo(*originalValue); attrValue.SetTo(*originalValue);
} }
bool oldValueSet;
if (originalName->IsAtom()) { if (originalName->IsAtom()) {
rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->Atom(), rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->Atom(),
attrValue); attrValue,
&oldValueSet);
} else { } else {
rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->NodeInfo(), rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->NodeInfo(),
attrValue); attrValue,
&oldValueSet);
} }
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
element->AddListenerFor(*originalName, true); element->AddListenerFor(*originalName, true);
@ -1053,7 +1056,8 @@ nsXULElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsresult nsresult
nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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 (aNamespaceID == kNameSpaceID_None) {
if (aValue) { if (aValue) {
@ -1174,7 +1178,7 @@ nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
} }
return nsStyledElement::AfterSetAttr(aNamespaceID, aName, return nsStyledElement::AfterSetAttr(aNamespaceID, aName,
aValue, aNotify); aValue, aOldValue, aNotify);
} }
bool bool
@ -1908,12 +1912,14 @@ nsXULElement::MakeHeavyweight(nsXULPrototypeElement* aPrototype)
attrValue.SetTo(protoattr->mValue); attrValue.SetTo(protoattr->mValue);
} }
bool oldValueSet;
// XXX we might wanna have a SetAndTakeAttr that takes an nsAttrName // XXX we might wanna have a SetAndTakeAttr that takes an nsAttrName
if (protoattr->mName.IsAtom()) { if (protoattr->mName.IsAtom()) {
rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.Atom(), attrValue); rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.Atom(),
attrValue, &oldValueSet);
} else { } else {
rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.NodeInfo(), rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.NodeInfo(),
attrValue); attrValue, &oldValueSet);
} }
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }

View file

@ -627,7 +627,9 @@ protected:
const nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) override; bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, 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; virtual void UpdateEditableState(bool aNotify) override;