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

In order to facilitate the movement of code with side-effects called by Element::SetAttr to Element::BeforeSetAttr and Element::AfterSetAttr, Element::AfterSetAttr should have access to the old value of the attribute. This includes information about whether there was previously a value set or not.

Accomplishing this involved passing an additional argument through functions that find and change the old attribute value in order to ensure that we can differentiate between an empty old value and an absent old value (attribute was not set).

Note that while I tried to ensure that accurate values (and their absence) are reported to Element::AfterSetAttr, I largely ignored SVG. While the old value reported for SVG values should be however accurate the value already being reported to SetAttrAndNotify was, SVG elements do not currently report unset values properly because they will never pass a null pointer to SetAttrAndNotify.

MozReview-Commit-ID: K1mha8CNFZP

--HG--
extra : rebase_source : 42776eb01451d371e4aebcc17fe3dd112c8d268b
This commit is contained in:
Kirk Steuber 2017-05-18 14:09:01 -07:00
parent d0eb7074d3
commit e74f1cd513
67 changed files with 352 additions and 160 deletions

View File

@ -2299,13 +2299,15 @@ Element::MaybeCheckSameAttrVal(int32_t aNamespaceID,
bool aNotify,
nsAttrValue& aOldValue,
uint8_t* aModType,
bool* aHasListeners)
bool* aHasListeners,
bool* aOldValueSet)
{
bool modification = false;
*aHasListeners = aNotify &&
nsContentUtils::HasMutationListeners(this,
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
@ -2330,6 +2332,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()) {
@ -2349,10 +2352,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;
}
@ -2383,9 +2388,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;
}
@ -2418,7 +2424,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);
}
@ -2443,9 +2450,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;
}
@ -2459,7 +2467,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);
}
@ -2468,7 +2477,7 @@ nsresult
Element::SetAttrAndNotify(int32_t aNamespaceID,
nsIAtom* aName,
nsIAtom* aPrefix,
const nsAttrValue& aOldValue,
const nsAttrValue* aOldValue,
nsAttrValue& aParsedValue,
uint8_t aModType,
bool aFireMutation,
@ -2489,6 +2498,7 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
bool hadValidDir = false;
bool hadDirAuto = false;
bool oldValueSet;
if (aNamespaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::dir) {
@ -2499,8 +2509,8 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
// XXXbz Perhaps we should push up the attribute mapping function
// stuff to Element?
if (!IsAttributeMapped(aName) ||
!SetMappedAttribute(aName, aParsedValue, &rv)) {
rv = mAttrsAndChildren.SetAndSwapAttr(aName, aParsedValue);
!SetAndSwapMappedAttribute(aName, aParsedValue, &oldValueSet, &rv)) {
rv = mAttrsAndChildren.SetAndSwapAttr(aName, aParsedValue, &oldValueSet);
}
}
else {
@ -2509,14 +2519,24 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
aNamespaceID,
nsIDOMNode::ATTRIBUTE_NODE);
rv = mAttrsAndChildren.SetAndSwapAttr(ni, aParsedValue);
rv = mAttrsAndChildren.SetAndSwapAttr(ni, aParsedValue, &oldValueSet);
}
NS_ENSURE_SUCCESS(rv, rv);
// If the old value owns its own data, we know it is OK to keep using it.
const nsAttrValue* oldValue =
aParsedValue.StoresOwnData() ? &aParsedValue : &aOldValue;
NS_ENSURE_SUCCESS(rv, rv);
// oldValue will be null if there was no previously set value
const nsAttrValue* oldValue;
if (aParsedValue.StoresOwnData()) {
if (oldValueSet) {
oldValue = &aParsedValue;
} else {
oldValue = nullptr;
}
} else {
// No need to conditionally assign null here. If there was no previously
// set value for the attribute, aOldValue will already be null.
oldValue = aOldValue;
}
if (aComposedDocument || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
RefPtr<nsXBLBinding> binding = GetXBLBinding();
@ -2527,7 +2547,14 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
nsIDocument* ownerDoc = OwnerDoc();
if (ownerDoc && GetCustomElementData()) {
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();
LifecycleCallbackArgs args = {
nsDependentAtomString(aName),
@ -2541,7 +2568,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) {
@ -2557,7 +2585,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) {
@ -2575,7 +2603,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;
@ -2618,9 +2646,10 @@ Element::ParseAttribute(int32_t aNamespaceID,
}
bool
Element::SetMappedAttribute(nsIAtom* aName,
nsAttrValue& aValue,
nsresult* aRetval)
Element::SetAndSwapMappedAttribute(nsIAtom* aName,
nsAttrValue& aValue,
bool* aValueWasSet,
nsresult* aRetval)
{
*aRetval = NS_OK;
return false;
@ -2775,7 +2804,7 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
ownerDoc, nsIDocument::eAttributeChanged, this, &args);
}
rv = AfterSetAttr(aNameSpaceID, aName, nullptr, aNotify);
rv = AfterSetAttr(aNameSpaceID, aName, nullptr, &oldValue, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
UpdateState(aNotify);

View File

@ -631,25 +631,49 @@ 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;
@ -1352,7 +1376,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.
@ -1366,7 +1393,7 @@ protected:
nsresult SetAttrAndNotify(int32_t aNamespaceID,
nsIAtom* aName,
nsIAtom* aPrefix,
const nsAttrValue& aOldValue,
const nsAttrValue* aOldValue,
nsAttrValue& aParsedValue,
uint8_t aModType,
bool aFireMutation,
@ -1410,13 +1437,20 @@ protected:
* returns true (the value of aRetval does not matter for that purpose).
*
* @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(nsIAtom* aName,
nsAttrValue& aValue,
nsresult* aRetval);
virtual bool SetAndSwapMappedAttribute(nsIAtom* aName,
nsAttrValue& aValue,
bool* aValueWasSet,
nsresult* aRetval);
/**
* Hook that is called by Element::SetAttr to allow subclasses to
@ -1444,19 +1478,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;
}

View File

@ -389,12 +389,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;
}
}
@ -414,21 +417,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;
}
}
@ -583,10 +587,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) {
@ -596,7 +601,7 @@ nsAttrAndChildArray::SetAndTakeMappedAttr(nsIAtom* aLocalName,
RefPtr<nsMappedAttributes> mapped =
GetModifiableMapped(aContent, aSheet, willAdd);
mapped->SetAndTakeAttr(aLocalName, aValue);
mapped->SetAndSwapAttr(aLocalName, aValue, aHadValue);
return MakeMappedUnique(mapped);
}

View File

@ -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;

View File

@ -15,13 +15,14 @@ nsMappedAttributeElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
}
bool
nsMappedAttributeElement::SetMappedAttribute(nsIAtom* aName,
nsAttrValue& aValue,
nsresult* aRetval)
nsMappedAttributeElement::SetAndSwapMappedAttribute(nsIAtom* aName,
nsAttrValue& aValue,
bool* aValueWasSet,
nsresult* aRetval)
{
nsHTMLStyleSheet* sheet = OwnerDoc()->GetAttributeStyleSheet();
*aRetval = mAttrsAndChildren.SetAndTakeMappedAttr(aName, aValue,
this, sheet);
*aRetval = mAttrsAndChildren.SetAndSwapMappedAttr(aName, aValue,
this, sheet, aValueWasSet);
return true;
}

View File

@ -40,9 +40,10 @@ public:
mozilla::GenericSpecifiedValues* aGenericData);
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
virtual bool SetMappedAttribute(nsIAtom* aName,
nsAttrValue& aValue,
nsresult* aRetval) override;
virtual bool SetAndSwapMappedAttribute(nsIAtom* aName,
nsAttrValue& aValue,
bool* aValueWasSet,
nsresult* aRetval) override;
virtual void NodeInfoChanged(nsIDocument* aOldDoc) override;
};

View File

@ -156,14 +156,16 @@ NS_IMPL_QUERY_INTERFACE(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;
}
}

View File

@ -34,7 +34,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;

View File

@ -57,6 +57,7 @@ nsStyledElement::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
SetMayHaveStyle();
bool modification = false;
nsAttrValue oldValue;
bool oldValueSet = false;
bool hasListeners = aNotify &&
nsContentUtils::HasMutationListeners(this,
@ -74,6 +75,7 @@ nsStyledElement::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
oldValueStr);
if (modification) {
oldValue.SetTo(oldValueStr);
oldValueSet = true;
}
}
else if (aNotify && IsInUncomposedDoc()) {
@ -90,9 +92,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);
}
// ---------------------------------------------------------------
@ -128,7 +130,9 @@ nsStyledElement::ReparseStyleAttribute(bool aForceInDataDoc, bool aForceIfAlread
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);
}

View File

@ -442,10 +442,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

View File

@ -119,7 +119,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();

View File

@ -428,7 +428,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) {
@ -445,7 +446,8 @@ HTMLButtonElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify);
aValue, aOldValue,
aNotify);
}
NS_IMETHODIMP

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -215,7 +215,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]
@ -231,7 +232,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)

View File

@ -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

View File

@ -174,7 +174,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) {
@ -184,7 +184,7 @@ HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
mFrameLoader->ApplySandboxFlags(GetSandboxFlags());
}
return nsGenericHTMLFrameElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify);
aOldValue, aNotify);
}
nsresult

View File

@ -57,6 +57,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;

View File

@ -396,7 +396,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) &&
@ -450,7 +451,7 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify);
aValue, aOldValue, aNotify);
}
nsresult

View File

@ -349,7 +349,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;
// Override for nsImageLoadingContent.
nsIContent* AsContent() override { return this; }

View File

@ -1398,7 +1398,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) {
//
@ -1521,7 +1522,8 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify);
aValue, aOldValue,
aNotify);
}
void

View File

@ -975,7 +975,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;
virtual void BeforeSetForm(bool aBindToTree) override;

View File

@ -346,7 +346,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
@ -415,7 +416,7 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify);
aOldValue, aNotify);
}
nsresult

View File

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

View File

@ -4235,7 +4235,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;
@ -4257,7 +4258,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,

View File

@ -140,6 +140,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,

View File

@ -115,7 +115,8 @@ HTMLMenuElement::Build(nsIMenuBuilder* aBuilder)
nsresult
HTMLMenuElement::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::type) {
if (aValue) {
@ -126,7 +127,7 @@ HTMLMenuElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify);
aOldValue, aNotify);
}
bool

View File

@ -30,8 +30,10 @@ public:
// nsIDOMHTMLMenuElement
NS_DECL_NSIDOMHTMLMENUELEMENT
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,

View File

@ -374,7 +374,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) {
// Handle type changes first, since some of the later conditions in this
@ -408,7 +409,7 @@ HTMLMenuItemElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify);
aOldValue, aNotify);
}
void

View File

@ -126,7 +126,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);

View File

@ -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

View File

@ -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);

View File

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

View File

@ -44,7 +44,9 @@ public:
bool aPreallocateChildren) const override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override;
virtual nsIDOMNode* AsDOMNode() override { return this; }

View File

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

View File

@ -50,7 +50,9 @@ public:
const nsAttrValueOrString* aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override;
void SetSelectedInternal(bool aValue, bool aNotify);

View File

@ -234,13 +234,14 @@ HTMLScriptElement::SetNoModule(bool aValue, ErrorResult& aRv)
nsresult
HTMLScriptElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify)
const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{
if (nsGkAtoms::async == aName && kNameSpaceID_None == aNamespaceID) {
mForceAsync = false;
}
return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
aNotify);
aOldValue, aNotify);
}
NS_IMETHODIMP

View File

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

View File

@ -1312,7 +1312,8 @@ HTMLSelectElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult
HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify)
const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::disabled) {
@ -1327,7 +1328,8 @@ HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify);
aValue, aOldValue,
aNotify);
}
nsresult

View File

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

View File

@ -95,7 +95,8 @@ HTMLSourceElement::UpdateMediaList(const nsAttrValue* aValue)
nsresult
HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify)
const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{
// If we are associated with a <picture> with a valid <img>, notify it of
// responsive parameter changes
@ -140,7 +141,7 @@ HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify);
aValue, aOldValue, aNotify);
}
nsresult

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1099,7 +1099,8 @@ HTMLTextAreaElement::ContentChanged(nsIContent* aContent)
nsresult
HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify)
const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
@ -1118,7 +1119,7 @@ HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify);
aOldValue, aNotify);
}
nsresult

View File

@ -365,7 +365,9 @@ protected:
void ContentChanged(nsIContent* aContent);
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom *aName,
const nsAttrValue* aValue, bool aNotify) override;
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override;
/**
* Return if an element should have a specific validity UI

View File

@ -645,7 +645,8 @@ nsGenericHTMLElement::GetHrefURIForAnchors() const
nsresult
nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify)
const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{
if (aNamespaceID == kNameSpaceID_None) {
if (IsEventAttributeName(aName) && aValue) {
@ -686,7 +687,7 @@ nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
}
return nsGenericHTMLElementBase::AfterSetAttr(aNamespaceID, aName,
aValue, aNotify);
aValue, aOldValue, aNotify);
}
EventListenerManager*
@ -1969,7 +1970,8 @@ nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsresult
nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify)
const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
// add the control to the hashtable as needed
@ -2018,7 +2020,7 @@ nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify);
aValue, aOldValue, aNotify);
}
nsresult

View File

@ -943,7 +943,9 @@ private:
protected:
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override;
virtual mozilla::EventListenerManager*
GetEventListenerManagerForAttr(nsIAtom* aAttrName,
@ -1301,7 +1303,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;
virtual void BeforeSetForm(bool aBindToTree) {}

View File

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

View File

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

View File

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

View File

@ -59,7 +59,9 @@ public:
const nsAString& aValue,
nsAttrValue& aResult) override;
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override;
const nsAttrValue* GetAnimAttr(nsIAtom* aName) const;
bool GetAnimAttr(nsIAtom* aAttName, nsAString& aResult) const;

View File

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

View File

@ -59,7 +59,9 @@ public:
bool aPreallocateChildren) const override;
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override;
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers) override;

View File

@ -36,7 +36,8 @@ SVGGeometryElement::GetNumberInfo()
nsresult
SVGGeometryElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify)
const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{
if (mCachedPath &&
aNamespaceID == kNameSpaceID_None &&
@ -44,7 +45,7 @@ SVGGeometryElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
mCachedPath = nullptr;
}
return SVGGeometryElementBase::AfterSetAttr(aNamespaceID, aName,
aValue, aNotify);
aValue, aOldValue, aNotify);
}
bool

View File

@ -52,7 +52,9 @@ public:
explicit SVGGeometryElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override;
/**
* Causes this element to discard any Path object that GetOrBuildPath may

View File

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

View File

@ -46,7 +46,9 @@ public:
// nsIContent interface
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override;
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers) override;

View File

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

View File

@ -55,7 +55,9 @@ public:
nsIContent* aBindingParent,
bool aCompileEventHandlers) override;
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override;
virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,

View File

@ -278,7 +278,9 @@ nsSVGElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
ParseStyleAttribute(stringValue, attrValue, true);
// Don't bother going through SetInlineStyleDeclaration; we don't
// want to fire off mutation events or document notifications anyway
rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue);
bool oldValueSet;
rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue,
&oldValueSet);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -287,7 +289,8 @@ nsSVGElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsresult
nsSVGElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify)
const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{
// We don't currently use nsMappedAttributes within SVG. If this changes, we
// need to be very careful because some nsAttrValues used by SVG point to
@ -317,7 +320,8 @@ nsSVGElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
NS_ENSURE_SUCCESS(rv, rv);
}
return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aNotify);
return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aOldValue,
aNotify);
}
bool
@ -1474,7 +1478,11 @@ nsSVGElement::DidChangeValue(nsIAtom* aName,
nsIDocument* document = GetComposedDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL,
kNotifyDocumentObservers);
SetAttrAndNotify(kNameSpaceID_None, aName, nullptr, aEmptyOrOldValue,
// XXX Really, the fourth argument to SetAttrAndNotify should be null if
// aEmptyOrOldValue does not represent the actual previous value of the
// attribute, but currently SVG elements do not even use the old attribute
// value in |AfterSetAttr|, so this should be ok.
SetAttrAndNotify(kNameSpaceID_None, aName, nullptr, &aEmptyOrOldValue,
aNewValue, modType, hasListeners, kNotifyDocumentObservers,
kCallAfterSetAttr, document, updateBatch);
}
@ -1496,7 +1504,8 @@ nsSVGElement::MaybeSerializeAttrBeforeRemoval(nsIAtom* aName, bool aNotify)
nsAutoString serializedValue;
attrValue->ToString(serializedValue);
nsAttrValue oldAttrValue(serializedValue);
mAttrsAndChildren.SetAndSwapAttr(aName, oldAttrValue);
bool oldValueSet;
mAttrsAndChildren.SetAndSwapAttr(aName, oldAttrValue, &oldValueSet);
}
/* static */

View File

@ -352,7 +352,9 @@ protected:
}
#endif // DEBUG
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override;
virtual bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
const nsAString& aValue, nsAttrValue& aResult) override;
static nsresult ReportAttributeParseFailure(nsIDocument* aDocument,

View File

@ -396,12 +396,15 @@ nsXULElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
attrValue.SetTo(*originalValue);
}
bool oldValueSet;
if (originalName->IsAtom()) {
rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->Atom(),
attrValue);
attrValue,
&oldValueSet);
} else {
rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->NodeInfo(),
attrValue);
attrValue,
&oldValueSet);
}
NS_ENSURE_SUCCESS(rv, rv);
element->AddListenerFor(*originalName, true);
@ -1069,7 +1072,8 @@ nsXULElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsresult
nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify)
const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aValue) {
@ -1190,7 +1194,7 @@ nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
}
return nsStyledElement::AfterSetAttr(aNamespaceID, aName,
aValue, aNotify);
aValue, aOldValue, aNotify);
}
bool
@ -1792,12 +1796,14 @@ nsXULElement::MakeHeavyweight(nsXULPrototypeElement* aPrototype)
attrValue.SetTo(protoattr->mValue);
}
bool oldValueSet;
// XXX we might wanna have a SetAndTakeAttr that takes an nsAttrName
if (protoattr->mName.IsAtom()) {
rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.Atom(), attrValue);
rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.Atom(),
attrValue, &oldValueSet);
} else {
rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.NodeInfo(),
attrValue);
attrValue, &oldValueSet);
}
NS_ENSURE_SUCCESS(rv, rv);
}

View File

@ -755,7 +755,9 @@ protected:
const nsAttrValueOrString* aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
bool aNotify) override;
virtual void UpdateEditableState(bool aNotify) override;