From cbde7ac9977f246111135fe4628159e77b1b0421 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 24 Mar 2017 15:28:19 -0700 Subject: [PATCH] Bug 1330051; Reparse style attribute when adopting across style backends; r=bz MozReview-Commit-ID: LWN57KApiMu --- dom/base/Element.cpp | 2 +- dom/base/Element.h | 7 ++++--- dom/base/nsStyledElement.cpp | 15 ++++++++++++--- dom/base/nsStyledElement.h | 7 +++++-- dom/html/HTMLImageElement.cpp | 1 + dom/html/nsGenericHTMLElement.cpp | 1 + dom/svg/nsSVGElement.cpp | 1 + dom/svg/nsSVGElement.h | 2 +- layout/reftests/bugs/1330051-ref.svg | 17 +++++++++++++++++ layout/reftests/bugs/1330051.svg | 17 +++++++++++++++++ layout/reftests/bugs/reftest-stylo.list | 1 + layout/reftests/bugs/reftest.list | 1 + 12 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 layout/reftests/bugs/1330051-ref.svg create mode 100644 layout/reftests/bugs/1330051.svg diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 76b47b427255..9b580736f58a 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -1673,7 +1673,7 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent, // XXXbz if we already have a style attr parsed, this won't do // anything... need to fix that. // If MayHaveStyle() is true, we must be an nsStyledElement - static_cast(this)->ReparseStyleAttribute(false); + static_cast(this)->ReparseStyleAttribute(false, false); } if (aDocument) { diff --git a/dom/base/Element.h b/dom/base/Element.h index 83d2fb7308e8..bf1319bb5780 100644 --- a/dom/base/Element.h +++ b/dom/base/Element.h @@ -1154,10 +1154,11 @@ public: * node has been changed. * * The new document can be reached via OwnerDoc(). + * + * If you override this method, + * please call up to the parent NodeInfoChanged. */ - virtual void NodeInfoChanged(nsIDocument* aOldDoc) - { - } + virtual void NodeInfoChanged(nsIDocument* aOldDoc) {} /** * Parse a string into an nsAttrValue for a CORS attribute. This diff --git a/dom/base/nsStyledElement.cpp b/dom/base/nsStyledElement.cpp index f5383094e7fe..484f4308c473 100644 --- a/dom/base/nsStyledElement.cpp +++ b/dom/base/nsStyledElement.cpp @@ -101,7 +101,7 @@ nsStyledElement::Style() if (!slots->mStyle) { // Just in case... - ReparseStyleAttribute(true); + ReparseStyleAttribute(true, false); slots->mStyle = new nsDOMCSSAttributeDeclaration(this, false); SetMayHaveStyle(); @@ -111,13 +111,13 @@ nsStyledElement::Style() } nsresult -nsStyledElement::ReparseStyleAttribute(bool aForceInDataDoc) +nsStyledElement::ReparseStyleAttribute(bool aForceInDataDoc, bool aForceIfAlreadyParsed) { if (!MayHaveStyle()) { return NS_OK; } const nsAttrValue* oldVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style); - if (oldVal && oldVal->Type() != nsAttrValue::eCSSDeclaration) { + if (oldVal && (aForceIfAlreadyParsed || oldVal->Type() != nsAttrValue::eCSSDeclaration)) { nsAttrValue attrValue; nsAutoString stringValue; oldVal->ToString(stringValue); @@ -131,6 +131,15 @@ nsStyledElement::ReparseStyleAttribute(bool aForceInDataDoc) return NS_OK; } +void +nsStyledElement::NodeInfoChanged(nsIDocument* aOldDoc) +{ + nsStyledElementBase::NodeInfoChanged(aOldDoc); + if (OwnerDoc()->GetStyleBackendType() != aOldDoc->GetStyleBackendType()) { + ReparseStyleAttribute(false, /* aForceIfAlreadyParsed */ true); + } +} + nsICSSDeclaration* nsStyledElement::GetExistingStyle() { diff --git a/dom/base/nsStyledElement.h b/dom/base/nsStyledElement.h index affd3c1f9b1b..f5accb924ef1 100644 --- a/dom/base/nsStyledElement.h +++ b/dom/base/nsStyledElement.h @@ -76,9 +76,12 @@ protected: * Create the style struct from the style attr. Used when an element is * first put into a document. Only has an effect if the old value is a * string. If aForceInDataDoc is true, will reparse even if we're in a data - * document. + * document. If aForceIfAlreadyParsed is set, this will always reparse even + * if the value has already been parsed. */ - nsresult ReparseStyleAttribute(bool aForceInDataDoc); + nsresult ReparseStyleAttribute(bool aForceInDataDoc, bool aForceIfAlreadyParsed); + + virtual void NodeInfoChanged(nsIDocument* aOldDoc) override; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsStyledElement, NS_STYLED_ELEMENT_IID) diff --git a/dom/html/HTMLImageElement.cpp b/dom/html/HTMLImageElement.cpp index 7e391ff1f60b..a0ceffaec5bb 100644 --- a/dom/html/HTMLImageElement.cpp +++ b/dom/html/HTMLImageElement.cpp @@ -712,6 +712,7 @@ HTMLImageElement::IntrinsicState() const void HTMLImageElement::NodeInfoChanged(nsIDocument* aOldDoc) { + nsGenericHTMLElement::NodeInfoChanged(aOldDoc); // Resetting the last selected source if adoption steps are run. mLastSelectedSource = nullptr; } diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index 8ed078b8acad..e483da40b51b 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -2841,6 +2841,7 @@ nsGenericHTMLFormElementWithState::RestoreFormControlState() void nsGenericHTMLFormElementWithState::NodeInfoChanged(nsIDocument* aOldDoc) { + nsGenericHTMLElement::NodeInfoChanged(aOldDoc); mStateKey.SetIsVoid(true); } diff --git a/dom/svg/nsSVGElement.cpp b/dom/svg/nsSVGElement.cpp index ea82e9b2e768..9fb41a508860 100644 --- a/dom/svg/nsSVGElement.cpp +++ b/dom/svg/nsSVGElement.cpp @@ -909,6 +909,7 @@ nsSVGElement::IsNodeOfType(uint32_t aFlags) const void nsSVGElement::NodeInfoChanged(nsIDocument* aOldDoc) { + nsSVGElementBase::NodeInfoChanged(aOldDoc); aOldDoc->UnscheduleSVGForPresAttrEvaluation(this); mContentDeclarationBlock = nullptr; OwnerDoc()->ScheduleSVGForPresAttrEvaluation(this); diff --git a/dom/svg/nsSVGElement.h b/dom/svg/nsSVGElement.h index 409a0b2d95b4..1f6bdb71a64b 100644 --- a/dom/svg/nsSVGElement.h +++ b/dom/svg/nsSVGElement.h @@ -118,7 +118,7 @@ public: * We override the default to unschedule computation of Servo declaration blocks * when adopted across documents. */ - virtual void NodeInfoChanged(nsIDocument* aOldDoc) override; + virtual void NodeInfoChanged(nsIDocument* aOldDoc) final; NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override; void WalkAnimatedContentStyleRules(nsRuleWalker* aRuleWalker); diff --git a/layout/reftests/bugs/1330051-ref.svg b/layout/reftests/bugs/1330051-ref.svg new file mode 100644 index 000000000000..78aa47e79f34 --- /dev/null +++ b/layout/reftests/bugs/1330051-ref.svg @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/layout/reftests/bugs/1330051.svg b/layout/reftests/bugs/1330051.svg new file mode 100644 index 000000000000..90965e93019f --- /dev/null +++ b/layout/reftests/bugs/1330051.svg @@ -0,0 +1,17 @@ + + + +
This should remain green
+
+ +
\ No newline at end of file diff --git a/layout/reftests/bugs/reftest-stylo.list b/layout/reftests/bugs/reftest-stylo.list index b4f0979367e1..0264e9d1a7ec 100644 --- a/layout/reftests/bugs/reftest-stylo.list +++ b/layout/reftests/bugs/reftest-stylo.list @@ -1988,5 +1988,6 @@ HTTP == 652991-1b.html 652991-1b.html HTTP == 652991-2.html 652991-2.html HTTP == 652991-3.html 652991-3.html fails HTTP == 652991-4.html 652991-4.html +== 1330051.svg 1330051.svg diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 932c96cf7206..d80d10c9af77 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1989,3 +1989,4 @@ fuzzy(2,40000) == 1316719-1b.html 1316719-1-ref.html fuzzy(2,40000) == 1316719-1c.html 1316719-1-ref.html skip-if(Android) != 1318769-1.html 1318769-1-ref.html == 1322512-1.html 1322512-1-ref.html +== 1330051.svg 1330051-ref.svg