Bug 1184842. Allow BeforeSetAttr to preparse aValue. r=peterv

We will pass the preparsed value into AttributeWillChange.
This commit is contained in:
Robert O'Callahan 2015-08-01 17:14:06 +12:00
parent d67ff5c3b6
commit d3cac53133
23 changed files with 46 additions and 23 deletions

View File

@ -2191,6 +2191,12 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsAutoScriptBlocker scriptBlocker; nsAutoScriptBlocker scriptBlocker;
nsAttrValue attrValue; nsAttrValue attrValue;
nsAttrValue* preparsedAttrValue = value.GetStoredAttrValue();
if (preparsedAttrValue) {
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);
} }

View File

@ -1170,13 +1170,15 @@ 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. * will be null. BeforeSetAttr is allowed to modify aValue by parsing
* 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,
const nsAttrValueOrString* aValue, nsAttrValueOrString* aValue,
bool aNotify) bool aNotify)
{ {
return NS_OK; return NS_OK;

View File

@ -49,6 +49,20 @@ public:
, mCheapString(nullptr) , mCheapString(nullptr)
{ } { }
void TakeParsedValue(nsAttrValue& aValue)
{
mStoredAttrValue.SwapValueWith(aValue);
mAttrValue = &mStoredAttrValue;
mStringPtr = nullptr;
}
/**
* If TakeParsedValue has been called, returns the value that it set.
*/
nsAttrValue* GetStoredAttrValue()
{
return mAttrValue == &mStoredAttrValue ? &mStoredAttrValue : nullptr;
}
/** /**
* 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.
* *
@ -74,6 +88,7 @@ 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

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

View File

@ -80,7 +80,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,
const nsAttrValueOrString* aValue, 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

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

View File

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

@ -1020,7 +1020,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,
const nsAttrValueOrString* aValue, nsAttrValueOrString* aValue,
bool aNotify) bool aNotify)
{ {
if (aNameSpaceID == kNameSpaceID_None) { if (aNameSpaceID == kNameSpaceID_None) {

View File

@ -865,7 +865,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,
const nsAttrValueOrString* aValue, 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

@ -182,7 +182,7 @@ HTMLOptionElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
nsresult nsresult
HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValueOrString* aValue, 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,
const nsAttrValueOrString* aValue, 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

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

View File

@ -372,7 +372,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,
const nsAttrValueOrString* aValue, 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

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

View File

@ -190,7 +190,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,
const nsAttrValueOrString* aValue, 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

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

View File

@ -140,7 +140,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,
const nsAttrValueOrString* aValue, nsAttrValueOrString* aValue,
bool aNotify) override; bool aNotify) override;
// nsIMutationObserver // nsIMutationObserver

View File

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

View File

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

@ -331,7 +331,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,
const nsAttrValueOrString* aValue, nsAttrValueOrString* aValue,
bool aNotify) override final { return NS_OK; } bool aNotify) override final { return NS_OK; }
#endif // DEBUG #endif // DEBUG
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,

View File

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

View File

@ -657,7 +657,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,
const nsAttrValueOrString* aValue, 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

@ -17,7 +17,7 @@
// When processing the next thread event, the appshell may process native // When processing the next thread event, the appshell may process native
// events (if not in performance mode), which can result in suppressing the // events (if not in performance mode), which can result in suppressing the
// next thread event for at most this many ticks: // next thread event for at most this many ticks:
#define THREAD_EVENT_STARVATION_LIMIT PR_MillisecondsToInterval(20) #define THREAD_EVENT_STARVATION_LIMIT PR_MillisecondsToInterval(10)
NS_IMPL_ISUPPORTS(nsBaseAppShell, nsIAppShell, nsIThreadObserver, nsIObserver) NS_IMPL_ISUPPORTS(nsBaseAppShell, nsIAppShell, nsIThreadObserver, nsIObserver)