From 7614fdb51b177e6975fce5bf9a7facef170e61aa Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 17 Apr 2020 05:10:25 -0400 Subject: Bug 1355351 - Make pseudo-elements return the correct style via getComputedStyle * Add a node property to access the ::before and ::after pseudo-elements * Look for the frame for ::before and ::after pseudos * Clean up pseudo-element props * Simplify nsLayoutUtils callers, and make child iterators notice display: contents pseudos Tag #1375 --- dom/animation/EffectCompositor.cpp | 22 +++------- dom/animation/KeyframeEffectReadOnly.cpp | 12 +++--- dom/base/ChildIterator.cpp | 73 ++++++++++++-------------------- dom/base/nsDOMWindowUtils.cpp | 6 +-- dom/base/nsGkAtomList.h | 2 + dom/xml/nsXMLElement.cpp | 23 ++++++++++ dom/xml/nsXMLElement.h | 3 ++ 7 files changed, 69 insertions(+), 72 deletions(-) (limited to 'dom') diff --git a/dom/animation/EffectCompositor.cpp b/dom/animation/EffectCompositor.cpp index c88cabe90..49da3c033 100644 --- a/dom/animation/EffectCompositor.cpp +++ b/dom/animation/EffectCompositor.cpp @@ -356,24 +356,16 @@ EffectCompositor::GetElementToRestyle(dom::Element* aElement, return aElement; } - nsIFrame* primaryFrame = aElement->GetPrimaryFrame(); - if (!primaryFrame) { - return nullptr; - } - nsIFrame* pseudoFrame; if (aPseudoType == CSSPseudoElementType::before) { - pseudoFrame = nsLayoutUtils::GetBeforeFrame(primaryFrame); - } else if (aPseudoType == CSSPseudoElementType::after) { - pseudoFrame = nsLayoutUtils::GetAfterFrame(primaryFrame); - } else { - NS_NOTREACHED("Should not try to get the element to restyle for a pseudo " - "other that :before or :after"); - return nullptr; + return nsLayoutUtils::GetBeforePseudo(aElement); } - if (!pseudoFrame) { - return nullptr; + if (aPseudoType == CSSPseudoElementType::after) { + return nsLayoutUtils::GetAfterPseudo(aElement); } - return pseudoFrame->GetContent()->AsElement(); + + NS_NOTREACHED("Should not try to get the element to restyle for a pseudo " + "other that :before or :after"); + return nullptr; } bool diff --git a/dom/animation/KeyframeEffectReadOnly.cpp b/dom/animation/KeyframeEffectReadOnly.cpp index 639e0b2b0..164ee0292 100644 --- a/dom/animation/KeyframeEffectReadOnly.cpp +++ b/dom/animation/KeyframeEffectReadOnly.cpp @@ -1105,19 +1105,17 @@ KeyframeEffectReadOnly::GetAnimationFrame() const return nullptr; } - nsIFrame* frame = mTarget->mElement->GetPrimaryFrame(); - if (!frame) { - return nullptr; - } - + nsIFrame* frame; if (mTarget->mPseudoType == CSSPseudoElementType::before) { - frame = nsLayoutUtils::GetBeforeFrame(frame); + frame = nsLayoutUtils::GetBeforeFrame(mTarget->mElement); } else if (mTarget->mPseudoType == CSSPseudoElementType::after) { - frame = nsLayoutUtils::GetAfterFrame(frame); + frame = nsLayoutUtils::GetAfterFrame(mTarget->mElement); } else { + frame = mTarget->mElement->GetPrimaryFrame(); MOZ_ASSERT(mTarget->mPseudoType == CSSPseudoElementType::NotPseudo, "unknown mTarget->mPseudoType"); } + if (!frame) { return nullptr; } diff --git a/dom/base/ChildIterator.cpp b/dom/base/ChildIterator.cpp index fb07e9a21..23b919516 100644 --- a/dom/base/ChildIterator.cpp +++ b/dom/base/ChildIterator.cpp @@ -317,11 +317,9 @@ AllChildrenIterator::Get() const { switch (mPhase) { case eAtBeforeKid: { - nsIFrame* frame = mOriginalContent->GetPrimaryFrame(); - MOZ_ASSERT(frame, "No frame at eAtBeforeKid phase"); - nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(frame); - MOZ_ASSERT(beforeFrame, "No content before frame at eAtBeforeKid phase"); - return beforeFrame->GetContent(); + Element* before = nsLayoutUtils::GetBeforePseudo(mOriginalContent); + MOZ_ASSERT(before, "No content before frame at eAtBeforeKid phase"); + return before; } case eAtExplicitKids: @@ -331,11 +329,9 @@ AllChildrenIterator::Get() const return mAnonKids[mAnonKidsIdx]; case eAtAfterKid: { - nsIFrame* frame = mOriginalContent->GetPrimaryFrame(); - MOZ_ASSERT(frame, "No frame at eAtAfterKid phase"); - nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(frame); - MOZ_ASSERT(afterFrame, "No content before frame at eAtBeforeKid phase"); - return afterFrame->GetContent(); + Element* after = nsLayoutUtils::GetAfterPseudo(mOriginalContent); + MOZ_ASSERT(after, "No content after frame at eAtAfterKid phase"); + return after; } default: @@ -349,15 +345,10 @@ AllChildrenIterator::Seek(nsIContent* aChildToFind) { if (mPhase == eAtBegin || mPhase == eAtBeforeKid) { mPhase = eAtExplicitKids; - nsIFrame* frame = mOriginalContent->GetPrimaryFrame(); - if (frame) { - nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(frame); - if (beforeFrame) { - if (beforeFrame->GetContent() == aChildToFind) { - mPhase = eAtBeforeKid; - return true; - } - } + Element* beforePseudo = nsLayoutUtils::GetBeforePseudo(mOriginalContent); + if (beforePseudo && beforePseudo == aChildToFind) { + mPhase = eAtBeforeKid; + return true; } } @@ -404,13 +395,10 @@ AllChildrenIterator::GetNextChild() { if (mPhase == eAtBegin) { mPhase = eAtExplicitKids; - nsIFrame* frame = mOriginalContent->GetPrimaryFrame(); - if (frame) { - nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(frame); - if (beforeFrame) { - mPhase = eAtBeforeKid; - return beforeFrame->GetContent(); - } + Element* beforeContent = nsLayoutUtils::GetBeforePseudo(mOriginalContent); + if (beforeContent) { + mPhase = eAtBeforeKid; + return beforeContent; } } @@ -446,13 +434,10 @@ AllChildrenIterator::GetNextChild() return mAnonKids[mAnonKidsIdx]; } - nsIFrame* frame = mOriginalContent->GetPrimaryFrame(); - if (frame) { - nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(frame); - if (afterFrame) { - mPhase = eAtAfterKid; - return afterFrame->GetContent(); - } + Element* afterContent = nsLayoutUtils::GetAfterPseudo(mOriginalContent); + if (afterContent) { + mPhase = eAtAfterKid; + return afterContent; } } @@ -466,13 +451,10 @@ AllChildrenIterator::GetPreviousChild() if (mPhase == eAtEnd) { MOZ_ASSERT(mAnonKidsIdx == mAnonKids.Length()); mPhase = eAtAnonKids; - nsIFrame* frame = mOriginalContent->GetPrimaryFrame(); - if (frame) { - nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(frame); - if (afterFrame) { - mPhase = eAtAfterKid; - return afterFrame->GetContent(); - } + Element* afterContent = nsLayoutUtils::GetAfterPseudo(mOriginalContent); + if (afterContent) { + mPhase = eAtAfterKid; + return afterContent; } } @@ -501,13 +483,10 @@ AllChildrenIterator::GetPreviousChild() return kid; } - nsIFrame* frame = mOriginalContent->GetPrimaryFrame(); - if (frame) { - nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(frame); - if (beforeFrame) { - mPhase = eAtBeforeKid; - return beforeFrame->GetContent(); - } + Element* beforeContent = nsLayoutUtils::GetBeforePseudo(mOriginalContent); + if (beforeContent) { + mPhase = eAtBeforeKid; + return beforeContent; } } diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 2ab5937ac..3f5b54c94 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -3657,11 +3657,11 @@ nsDOMWindowUtils::GetOMTAStyle(nsIDOMElement* aElement, RefPtr cssValue = nullptr; nsIFrame* frame = element->GetPrimaryFrame(); - if (frame && !aPseudoElement.IsEmpty()) { + if (!aPseudoElement.IsEmpty()) { if (aPseudoElement.EqualsLiteral("::before")) { - frame = nsLayoutUtils::GetBeforeFrame(frame); + frame = nsLayoutUtils::GetBeforeFrame(element); } else if (aPseudoElement.EqualsLiteral("::after")) { - frame = nsLayoutUtils::GetAfterFrame(frame); + frame = nsLayoutUtils::GetAfterFrame(element); } else { return NS_ERROR_INVALID_ARG; } diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h index c7c1197b1..2f0e30387 100644 --- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -2144,12 +2144,14 @@ GK_ATOM(ongamepaddisconnected, "ongamepaddisconnected") #endif // Content property names +GK_ATOM(afterPseudoProperty, "afterPseudoProperty") // nsXMLElement* GK_ATOM(animationsProperty, "AnimationsProperty") // FrameAnimations* GK_ATOM(animationsOfBeforeProperty, "AnimationsOfBeforeProperty") // FrameAnimations* GK_ATOM(animationsOfAfterProperty, "AnimationsOfAfterProperty") // FrameAnimations* GK_ATOM(animationEffectsProperty, "AnimationEffectsProperty") // EffectSet* GK_ATOM(animationEffectsForBeforeProperty, "AnimationsEffectsForBeforeProperty") // EffectSet* GK_ATOM(animationEffectsForAfterProperty, "AnimationsEffectsForAfterProperty") // EffectSet* +GK_ATOM(beforePseudoProperty, "beforePseudoProperty") // nsXMLElement* GK_ATOM(cssPseudoElementBeforeProperty, "CSSPseudoElementBeforeProperty") // CSSPseudoElement* GK_ATOM(cssPseudoElementAfterProperty, "CSSPseudoElementAfterProperty") // CSSPseudoElement* GK_ATOM(transitionsProperty, "TransitionsProperty") // FrameTransitions* diff --git a/dom/xml/nsXMLElement.cpp b/dom/xml/nsXMLElement.cpp index 45163a1c4..ad0314f4c 100644 --- a/dom/xml/nsXMLElement.cpp +++ b/dom/xml/nsXMLElement.cpp @@ -9,6 +9,7 @@ #include "mozilla/dom/ElementInlines.h" #include "nsContentUtils.h" // nsAutoScriptBlocker +using namespace mozilla; using namespace mozilla::dom; nsresult @@ -29,4 +30,26 @@ nsXMLElement::WrapNode(JSContext *aCx, JS::Handle aGivenProto) return ElementBinding::Wrap(aCx, this, aGivenProto); } +void +nsXMLElement::UnbindFromTree(bool aDeep, bool aNullParent) +{ + CSSPseudoElementType pseudoType = GetPseudoElementType(); + bool isBefore = pseudoType == CSSPseudoElementType::before; + nsIAtom* property = isBefore + ? nsGkAtoms::beforePseudoProperty : nsGkAtoms::afterPseudoProperty; + + switch (pseudoType) { + case CSSPseudoElementType::before: + case CSSPseudoElementType::after: { + MOZ_ASSERT(GetParent()); + MOZ_ASSERT(GetParent()->IsElement()); + GetParent()->DeleteProperty(property); + break; + } + default: + break; + } + Element::UnbindFromTree(aDeep, aNullParent); +} + NS_IMPL_ELEMENT_CLONE(nsXMLElement) diff --git a/dom/xml/nsXMLElement.h b/dom/xml/nsXMLElement.h index d16b82f39..85f79970c 100644 --- a/dom/xml/nsXMLElement.h +++ b/dom/xml/nsXMLElement.h @@ -35,6 +35,9 @@ public: virtual nsIDOMNode* AsDOMNode() override { return this; } + virtual void UnbindFromTree(bool aDeep = true, + bool aNullParent = true) override; + protected: virtual ~nsXMLElement() {} -- cgit v1.2.3