Bug 656197 part 1. Remove the generic attr preparsing mechanism from BeforeSetAttr and just preparse class attributes directly in the one place that needs to do it. r=smaug

This removes the requirement that BeforeSetAttr comes before AttributeWillChange
(which needs the preparsed new value).

MozReview-Commit-ID: 87C6Mjc7ARh
This commit is contained in:
Boris Zbarsky
2017-03-16 14:50:41 -04:00
parent 1af41b0c0b
commit d40e452ea9
26 changed files with 49 additions and 66 deletions

View File

@@ -2320,6 +2320,9 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
uint8_t modType; uint8_t modType;
bool hasListeners; bool hasListeners;
// We don't want to spend time preparsing class attributes if the value is not
// changing, so just init our nsAttrValueOrString with aValue for the
// OnlyNotifySameValueSet call.
nsAttrValueOrString value(aValue); nsAttrValueOrString value(aValue);
nsAttrValue oldValue; nsAttrValue oldValue;
@@ -2328,9 +2331,18 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
return NS_OK; return NS_OK;
} }
nsAttrValue attrValue;
nsAttrValue* preparsedAttrValue;
if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::_class) {
attrValue.ParseAtomArray(aValue);
value.ResetToAttrValue(attrValue);
preparsedAttrValue = &attrValue;
} else {
preparsedAttrValue = nullptr;
}
nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify); nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsAttrValue* preparsedAttrValue = value.GetStoredAttrValue();
if (aNotify) { if (aNotify) {
nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType, nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType,
@@ -2341,12 +2353,8 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
// out to id-observers // out to id-observers
nsAutoScriptBlocker scriptBlocker; nsAutoScriptBlocker scriptBlocker;
nsAttrValue attrValue; // Even the value was pre-parsed, we still need to call ParseAttribute because
if (preparsedAttrValue) { // it can have side effects.
attrValue.SwapValueWith(*preparsedAttrValue);
}
// Even the value was pre-parsed in BeforeSetAttr, we still need to call
// ParseAttribute because it can have side effects.
if (!ParseAttribute(aNamespaceID, aName, aValue, attrValue)) { if (!ParseAttribute(aNamespaceID, aName, aValue, attrValue)) {
attrValue.SetTo(aValue); attrValue.SetTo(aValue);
} }
@@ -2520,25 +2528,6 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
return NS_OK; return NS_OK;
} }
nsresult
Element::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, bool aNotify)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::_class) {
// aValue->GetAttrValue will only be non-null here when this is called
// via Element::SetParsedAttr. This shouldn't happen for "class", but
// this will handle it.
if (aValue && !aValue->GetAttrValue()) {
nsAttrValue attr;
attr.ParseAtomArray(aValue->String());
aValue->TakeParsedValue(attr);
}
}
}
return NS_OK;
}
bool bool
Element::ParseAttribute(int32_t aNamespaceID, Element::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute, nsIAtom* aAttribute,

View File

@@ -1380,16 +1380,17 @@ protected:
* @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 represented as either a string or * @param aValue the value it's being set to represented as either a string or
* a parsed nsAttrValue. Alternatively, if the attr is being removed it * a parsed nsAttrValue. Alternatively, if the attr is being removed it
* will be null. BeforeSetAttr is allowed to modify aValue by parsing * will be null.
* the string to an nsAttrValue (to avoid having to reparse it in
* ParseAttribute).
* @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 BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify); bool aNotify)
{
return NS_OK;
}
/** /**
* Hook that is called by Element::SetAttr to allow subclasses to * Hook that is called by Element::SetAttr to allow subclasses to

View File

@@ -49,20 +49,13 @@ public:
, mCheapString(nullptr) , mCheapString(nullptr)
{ } { }
void TakeParsedValue(nsAttrValue& aValue) void ResetToAttrValue(const nsAttrValue& aValue)
{ {
mStoredAttrValue.SwapValueWith(aValue); mAttrValue = &aValue;
mAttrValue = &mStoredAttrValue;
mStringPtr = nullptr; mStringPtr = nullptr;
// No need to touch mCheapString here. If we need to use it, we will reset
// it to the rigthe value anyway.
} }
/**
* If TakeParsedValue has been called, returns the value that it set.
*/
nsAttrValue* GetStoredAttrValue()
{
return mAttrValue == &mStoredAttrValue ? &mStoredAttrValue : nullptr;
}
const nsAttrValue* GetAttrValue() { return mAttrValue; }
/** /**
* Returns a reference to the string value of the contents of this object. * Returns a reference to the string value of the contents of this object.
@@ -89,7 +82,6 @@ protected:
const nsAttrValue* mAttrValue; const nsAttrValue* mAttrValue;
mutable const nsAString* mStringPtr; mutable const nsAString* mStringPtr;
mutable nsCheapString mCheapString; mutable nsCheapString mCheapString;
nsAttrValue mStoredAttrValue;
}; };
#endif // nsAttrValueOrString_h___ #endif // nsAttrValueOrString_h___

View File

@@ -423,7 +423,7 @@ HTMLButtonElement::DoneCreatingElement()
nsresult nsresult
HTMLButtonElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLButtonElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) bool aNotify)
{ {
if (aNotify && aName == nsGkAtoms::disabled && if (aNotify && aName == nsGkAtoms::disabled &&

View File

@@ -81,7 +81,7 @@ public:
* Called when an attribute is about to be changed * Called when an attribute is about to be changed
*/ */
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) override; bool aNotify) override;
/** /**
* Called when an attribute has just been changed * Called when an attribute has just been changed

View File

@@ -46,7 +46,7 @@ HTMLDetailsElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
nsresult nsresult
HTMLDetailsElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLDetailsElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, bool aNotify) const nsAttrValueOrString* aValue, bool aNotify)
{ {
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::open) { if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::open) {
bool setOpen = aValue != nullptr; bool setOpen = aValue != nullptr;

View File

@@ -38,7 +38,8 @@ public:
int32_t aModType) const override; int32_t aModType) const override;
nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, bool aNotify) override; const nsAttrValueOrString* aValue,
bool aNotify) override;
// HTMLDetailsElement WebIDL // HTMLDetailsElement WebIDL
bool Open() const { return GetBoolAttr(nsGkAtoms::open); } bool Open() const { return GetBoolAttr(nsGkAtoms::open); }

View File

@@ -368,7 +368,7 @@ HTMLImageElement::GetAttributeMappingFunction() const
nsresult nsresult
HTMLImageElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLImageElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) bool aNotify)
{ {

View File

@@ -344,7 +344,7 @@ protected:
void UpdateFormOwner(); void UpdateFormOwner();
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
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,

View File

@@ -1358,7 +1358,7 @@ HTMLInputElement::Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) co
nsresult nsresult
HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) bool aNotify)
{ {
if (aNameSpaceID == kNameSpaceID_None) { if (aNameSpaceID == kNameSpaceID_None) {

View File

@@ -965,7 +965,7 @@ protected:
* Called when an attribute is about to be changed * Called when an attribute is about to be changed
*/ */
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) override; bool aNotify) override;
/** /**
* Called when an attribute has just been changed * Called when an attribute has just been changed

View File

@@ -333,7 +333,7 @@ HTMLLinkElement::UpdateImport()
nsresult nsresult
HTMLLinkElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLLinkElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, bool aNotify) const nsAttrValueOrString* aValue, bool aNotify)
{ {
if (aNameSpaceID == kNameSpaceID_None && if (aNameSpaceID == kNameSpaceID_None &&
(aName == nsGkAtoms::href || aName == nsGkAtoms::rel)) { (aName == nsGkAtoms::href || aName == nsGkAtoms::rel)) {

View File

@@ -62,7 +62,7 @@ public:
virtual void UnbindFromTree(bool aDeep = true, virtual void UnbindFromTree(bool aDeep = true,
bool aNullParent = true) override; bool aNullParent = true) override;
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
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, const nsAttrValue* aValue,

View File

@@ -181,7 +181,7 @@ HTMLOptionElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
nsresult nsresult
HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) bool aNotify)
{ {
nsresult rv = nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName, nsresult rv = nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName,

View File

@@ -47,7 +47,7 @@ public:
int32_t aModType) const override; int32_t aModType) const override;
virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
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, bool aNotify) override;

View File

@@ -1296,7 +1296,7 @@ HTMLSelectElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsresult nsresult
HTMLSelectElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLSelectElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) bool aNotify)
{ {
if (aNotify && aName == nsGkAtoms::disabled && if (aNotify && aName == nsGkAtoms::disabled &&

View File

@@ -382,7 +382,7 @@ public:
bool aCompileEventHandlers) override; bool aCompileEventHandlers) override;
virtual void UnbindFromTree(bool aDeep, bool aNullParent) override; virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
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, bool aNotify) override;

View File

@@ -937,7 +937,7 @@ HTMLTableElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsresult nsresult
HTMLTableElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLTableElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) bool aNotify)
{ {
if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) {

View File

@@ -202,7 +202,7 @@ public:
* Called when an attribute is about to be changed * Called when an attribute is about to be changed
*/ */
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) override; bool aNotify) override;
/** /**
* Called when an attribute has just been changed * Called when an attribute has just been changed

View File

@@ -985,7 +985,7 @@ HTMLTextAreaElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsresult nsresult
HTMLTextAreaElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, HTMLTextAreaElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) bool aNotify)
{ {
if (aNotify && aName == nsGkAtoms::disabled && if (aNotify && aName == nsGkAtoms::disabled &&

View File

@@ -147,7 +147,7 @@ public:
* Called when an attribute is about to be changed * Called when an attribute is about to be changed
*/ */
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) override; bool aNotify) override;
// nsIMutationObserver // nsIMutationObserver

View File

@@ -1929,7 +1929,7 @@ nsGenericHTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsresult nsresult
nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) bool aNotify)
{ {
if (aNameSpaceID == kNameSpaceID_None) { if (aNameSpaceID == kNameSpaceID_None) {

View File

@@ -1296,7 +1296,7 @@ protected:
virtual ~nsGenericHTMLFormElement(); virtual ~nsGenericHTMLFormElement();
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
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,

View File

@@ -343,7 +343,7 @@ protected:
// BeforeSetAttr since it would involve allocating extra SVG value types. // BeforeSetAttr since it would involve allocating extra SVG value types.
// See the comment in nsSVGElement::WillChangeValue. // See the comment in nsSVGElement::WillChangeValue.
virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, const nsAttrValueOrString* aValue,
bool aNotify) override final bool aNotify) override final
{ {
return nsSVGElementBase::BeforeSetAttr(aNamespaceID, aName, aValue, aNotify); return nsSVGElementBase::BeforeSetAttr(aNamespaceID, aName, aValue, aNotify);

View File

@@ -1018,7 +1018,7 @@ nsXULElement::UnregisterAccessKey(const nsAString& aOldValue)
nsresult nsresult
nsXULElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, nsXULElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, bool aNotify) const nsAttrValueOrString* aValue, bool aNotify)
{ {
if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::accesskey && if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::accesskey &&
IsInUncomposedDoc()) { IsInUncomposedDoc()) {

View File

@@ -751,7 +751,7 @@ protected:
nsresult MakeHeavyweight(nsXULPrototypeElement* aPrototype); nsresult MakeHeavyweight(nsXULPrototypeElement* aPrototype);
virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
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, bool aNotify) override;