From f4a1d0123c41647f2f05aeaa2ae14bd1806fbb5c Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 17 Apr 2020 06:12:55 -0400 Subject: Bug 1375701 - Atomize class attribute value in the parser in the innerHTML case Tag #1375 --- dom/base/Element.cpp | 41 +++++++++++++++++++++++++++++++++++++++-- dom/base/Element.h | 7 +++++++ 2 files changed, 46 insertions(+), 2 deletions(-) (limited to 'dom') diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 96ccfd52a..31af0c1db 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -2450,12 +2450,45 @@ Element::OnlyNotifySameValueSet(int32_t aNamespaceID, nsIAtom* aName, return true; } +nsresult +Element::SetSingleClassFromParser(nsIAtom* aSingleClassName) +{ + // Keep this in sync with SetAttr and SetParsedAttr below. + + if (!mAttrsAndChildren.CanFitMoreAttrs()) { + return NS_ERROR_FAILURE; + } + + nsAttrValue value(aSingleClassName); + + nsIDocument* document = GetComposedDoc(); + mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, false); + + // In principle, BeforeSetAttr should be called here if a node type + // existed that wanted to do something special for class, but there + // is no such node type, so calling SetMayHaveClass() directly. + SetMayHaveClass(); + + return SetAttrAndNotify(kNameSpaceID_None, + nsGkAtoms::_class, + nullptr, // prefix + nullptr, // old value + value, + static_cast(nsIDOMMutationEvent::ADDITION), + false, // hasListeners + false, // notify + kCallAfterSetAttr, + document, + updateBatch); +} + nsresult Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName, nsIAtom* aPrefix, const nsAString& aValue, bool aNotify) { - // Keep this in sync with SetParsedAttr below + // Keep this in sync with SetParsedAttr below and SetSingleClassFromParser + // above. NS_ENSURE_ARG_POINTER(aName); NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown, @@ -2520,7 +2553,7 @@ Element::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName, nsIAtom* aPrefix, nsAttrValue& aParsedValue, bool aNotify) { - // Keep this in sync with SetAttr above + // Keep this in sync with SetAttr and SetSingleClassFromParser above NS_ENSURE_ARG_POINTER(aName); NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown, @@ -2764,6 +2797,10 @@ Element::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, // If it is ever made to be exact, we probably need to handle this // similarly to how ids are handled in PreIdMaybeChange and // PostIdMaybeChange. + // Note that SetSingleClassFromParser inlines BeforeSetAttr and + // calls SetMayHaveClass directly. Making a subclass take action + // on the class attribute in a BeforeSetAttr override would + // require revising SetSingleClassFromParser. SetMayHaveClass(); } } diff --git a/dom/base/Element.h b/dom/base/Element.h index 76f0767e6..88f416be7 100644 --- a/dom/base/Element.h +++ b/dom/base/Element.h @@ -601,6 +601,13 @@ public: uint8_t* aModType, bool* aHasListeners, bool* aOldValueSet); + /** + * Sets the class attribute to a value that contains no whitespace. + * Assumes that we are not notifying and that the attribute hasn't been + * set previously. + */ + nsresult SetSingleClassFromParser(nsIAtom* aSingleClassName); + virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix, const nsAString& aValue, bool aNotify) override; // aParsedValue receives the old value of the attribute. That's useful if -- cgit v1.2.3