From d3cac531339b0d2070d6d16109594f2c6db1f9c6 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Sat, 1 Aug 2015 17:14:06 +1200 Subject: [PATCH] Bug 1184842. Allow BeforeSetAttr to preparse aValue. r=peterv We will pass the preparsed value into AttributeWillChange. --- dom/base/Element.cpp | 8 +++++++- dom/base/Element.h | 6 ++++-- dom/base/nsAttrValueOrString.h | 15 +++++++++++++++ dom/html/HTMLButtonElement.cpp | 2 +- dom/html/HTMLButtonElement.h | 2 +- dom/html/HTMLImageElement.cpp | 2 +- dom/html/HTMLImageElement.h | 2 +- dom/html/HTMLInputElement.cpp | 2 +- dom/html/HTMLInputElement.h | 2 +- dom/html/HTMLOptionElement.cpp | 2 +- dom/html/HTMLOptionElement.h | 2 +- dom/html/HTMLSelectElement.cpp | 2 +- dom/html/HTMLSelectElement.h | 2 +- dom/html/HTMLTableElement.cpp | 2 +- dom/html/HTMLTableElement.h | 2 +- dom/html/HTMLTextAreaElement.cpp | 2 +- dom/html/HTMLTextAreaElement.h | 2 +- dom/html/nsGenericHTMLElement.cpp | 2 +- dom/html/nsGenericHTMLElement.h | 2 +- dom/svg/nsSVGElement.h | 2 +- dom/xul/nsXULElement.cpp | 2 +- dom/xul/nsXULElement.h | 2 +- widget/nsBaseAppShell.cpp | 2 +- 23 files changed, 46 insertions(+), 23 deletions(-) diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index b98f5bf9d15..d41ef9d671f 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -2191,6 +2191,12 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName, nsAutoScriptBlocker scriptBlocker; 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)) { attrValue.SetTo(aValue); } @@ -3505,4 +3511,4 @@ Element::GetReferrerPolicy() } } return net::RP_Unset; -} \ No newline at end of file +} diff --git a/dom/base/Element.h b/dom/base/Element.h index 4fb639e452c..7a12d678834 100644 --- a/dom/base/Element.h +++ b/dom/base/Element.h @@ -1170,13 +1170,15 @@ protected: * @param aName the localname of the attribute being set * @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 - * 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. */ // Note that this is inlined so that when subclasses call it it gets // inlined. Those calls don't go through a vtable. virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) { return NS_OK; diff --git a/dom/base/nsAttrValueOrString.h b/dom/base/nsAttrValueOrString.h index 07476e5cba8..d98d703af33 100644 --- a/dom/base/nsAttrValueOrString.h +++ b/dom/base/nsAttrValueOrString.h @@ -49,6 +49,20 @@ public: , 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. * @@ -74,6 +88,7 @@ protected: const nsAttrValue* mAttrValue; mutable const nsAString* mStringPtr; mutable nsCheapString mCheapString; + nsAttrValue mStoredAttrValue; }; #endif // nsAttrValueOrString_h___ diff --git a/dom/html/HTMLButtonElement.cpp b/dom/html/HTMLButtonElement.cpp index 1596dd2c4cd..9ced076e53d 100644 --- a/dom/html/HTMLButtonElement.cpp +++ b/dom/html/HTMLButtonElement.cpp @@ -493,7 +493,7 @@ HTMLButtonElement::DoneCreatingElement() nsresult HTMLButtonElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) { if (aNotify && aName == nsGkAtoms::disabled && diff --git a/dom/html/HTMLButtonElement.h b/dom/html/HTMLButtonElement.h index 2300ef8f28c..8a48beaa111 100644 --- a/dom/html/HTMLButtonElement.h +++ b/dom/html/HTMLButtonElement.h @@ -80,7 +80,7 @@ public: * Called when an attribute is about to be changed */ virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) override; /** * Called when an attribute has just been changed diff --git a/dom/html/HTMLImageElement.cpp b/dom/html/HTMLImageElement.cpp index e9458f60d42..1203b632401 100644 --- a/dom/html/HTMLImageElement.cpp +++ b/dom/html/HTMLImageElement.cpp @@ -375,7 +375,7 @@ HTMLImageElement::GetAttributeMappingFunction() const nsresult HTMLImageElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) { diff --git a/dom/html/HTMLImageElement.h b/dom/html/HTMLImageElement.h index 45b3c2ab132..4f3912ed4ce 100644 --- a/dom/html/HTMLImageElement.h +++ b/dom/html/HTMLImageElement.h @@ -334,7 +334,7 @@ protected: void UpdateFormOwner(); virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 4df8f95e630..29ab2200418 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -1020,7 +1020,7 @@ HTMLInputElement::Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) co nsresult HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h index 7471b893116..8e593779d7b 100644 --- a/dom/html/HTMLInputElement.h +++ b/dom/html/HTMLInputElement.h @@ -865,7 +865,7 @@ protected: * Called when an attribute is about to be changed */ virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) override; /** * Called when an attribute has just been changed diff --git a/dom/html/HTMLOptionElement.cpp b/dom/html/HTMLOptionElement.cpp index 54c0287aa3d..330ace3cedb 100644 --- a/dom/html/HTMLOptionElement.cpp +++ b/dom/html/HTMLOptionElement.cpp @@ -182,7 +182,7 @@ HTMLOptionElement::GetAttributeChangeHint(const nsIAtom* aAttribute, nsresult HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) { nsresult rv = nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName, diff --git a/dom/html/HTMLOptionElement.h b/dom/html/HTMLOptionElement.h index a4cd24d9c5b..e220b84df32 100644 --- a/dom/html/HTMLOptionElement.h +++ b/dom/html/HTMLOptionElement.h @@ -47,7 +47,7 @@ public: int32_t aModType) const override; virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, bool aNotify) override; diff --git a/dom/html/HTMLSelectElement.cpp b/dom/html/HTMLSelectElement.cpp index e914ced62cc..766d5ecab12 100644 --- a/dom/html/HTMLSelectElement.cpp +++ b/dom/html/HTMLSelectElement.cpp @@ -1325,7 +1325,7 @@ HTMLSelectElement::UnbindFromTree(bool aDeep, bool aNullParent) nsresult HTMLSelectElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) { if (aNotify && aName == nsGkAtoms::disabled && diff --git a/dom/html/HTMLSelectElement.h b/dom/html/HTMLSelectElement.h index 6150dc17a32..06d1a5d51c8 100644 --- a/dom/html/HTMLSelectElement.h +++ b/dom/html/HTMLSelectElement.h @@ -372,7 +372,7 @@ public: bool aCompileEventHandlers) override; virtual void UnbindFromTree(bool aDeep, bool aNullParent) override; virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, bool aNotify) override; diff --git a/dom/html/HTMLTableElement.cpp b/dom/html/HTMLTableElement.cpp index 7762c28bed5..e0e1e41a44a 100644 --- a/dom/html/HTMLTableElement.cpp +++ b/dom/html/HTMLTableElement.cpp @@ -954,7 +954,7 @@ HTMLTableElement::UnbindFromTree(bool aDeep, bool aNullParent) nsresult HTMLTableElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) { if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) { diff --git a/dom/html/HTMLTableElement.h b/dom/html/HTMLTableElement.h index d6fecdab277..ee3b16cd126 100644 --- a/dom/html/HTMLTableElement.h +++ b/dom/html/HTMLTableElement.h @@ -190,7 +190,7 @@ public: * Called when an attribute is about to be changed */ virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) override; /** * Called when an attribute has just been changed diff --git a/dom/html/HTMLTextAreaElement.cpp b/dom/html/HTMLTextAreaElement.cpp index c3051192a0b..7c2a38d7c86 100644 --- a/dom/html/HTMLTextAreaElement.cpp +++ b/dom/html/HTMLTextAreaElement.cpp @@ -1212,7 +1212,7 @@ HTMLTextAreaElement::UnbindFromTree(bool aDeep, bool aNullParent) nsresult HTMLTextAreaElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) { if (aNotify && aName == nsGkAtoms::disabled && diff --git a/dom/html/HTMLTextAreaElement.h b/dom/html/HTMLTextAreaElement.h index 5232bb102b8..6a42b780e10 100644 --- a/dom/html/HTMLTextAreaElement.h +++ b/dom/html/HTMLTextAreaElement.h @@ -140,7 +140,7 @@ public: * Called when an attribute is about to be changed */ virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) override; // nsIMutationObserver diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index b010706ca8e..13eeeda845c 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -2119,7 +2119,7 @@ nsGenericHTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent) nsresult nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h index c152657f842..c12f999b4a3 100644 --- a/dom/html/nsGenericHTMLElement.h +++ b/dom/html/nsGenericHTMLElement.h @@ -1355,7 +1355,7 @@ protected: virtual ~nsGenericHTMLFormElement(); virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, diff --git a/dom/svg/nsSVGElement.h b/dom/svg/nsSVGElement.h index e512b031c9f..12f35d7d5e8 100644 --- a/dom/svg/nsSVGElement.h +++ b/dom/svg/nsSVGElement.h @@ -331,7 +331,7 @@ protected: // BeforeSetAttr since it would involve allocating extra SVG value types. // See the comment in nsSVGElement::WillChangeValue. virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) override final { return NS_OK; } #endif // DEBUG virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, diff --git a/dom/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp index 3e0ea8d90c9..cb1965f9719 100644 --- a/dom/xul/nsXULElement.cpp +++ b/dom/xul/nsXULElement.cpp @@ -1046,7 +1046,7 @@ nsXULElement::UnregisterAccessKey(const nsAString& aOldValue) nsresult nsXULElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, bool aNotify) + nsAttrValueOrString* aValue, bool aNotify) { if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::accesskey && IsInDoc()) { diff --git a/dom/xul/nsXULElement.h b/dom/xul/nsXULElement.h index 3b4a88e0e03..cb6a631185d 100644 --- a/dom/xul/nsXULElement.h +++ b/dom/xul/nsXULElement.h @@ -657,7 +657,7 @@ protected: nsresult MakeHeavyweight(nsXULPrototypeElement* aPrototype); virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValueOrString* aValue, + nsAttrValueOrString* aValue, bool aNotify) override; virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, bool aNotify) override; diff --git a/widget/nsBaseAppShell.cpp b/widget/nsBaseAppShell.cpp index d194abdd517..db59bf80dac 100644 --- a/widget/nsBaseAppShell.cpp +++ b/widget/nsBaseAppShell.cpp @@ -17,7 +17,7 @@ // When processing the next thread event, the appshell may process native // events (if not in performance mode), which can result in suppressing the // 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)