Bug 1355351: Simplify nsLayoutUtils callers, and make child iterators notice display: contents pseudos. r=heycam

This also happens to fix other bugs, like making display: contents pseudos
animatable, which weren't before.

MozReview-Commit-ID: LhwTPNbFvSZ

--HG--
extra : rebase_source : 785105b08d6bfa15ad257e61b769a263c6810ad0
This commit is contained in:
Emilio Cobos Álvarez 2017-04-19 12:53:57 +02:00
Родитель 135c333511
Коммит 6fe2b3e89d
10 изменённых файлов: 91 добавлений и 155 удалений

Просмотреть файл

@ -519,24 +519,17 @@ 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

Просмотреть файл

@ -1464,19 +1464,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;
}

Просмотреть файл

@ -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;
}
}

Просмотреть файл

@ -3756,11 +3756,11 @@ nsDOMWindowUtils::GetOMTAStyle(nsIDOMElement* aElement,
RefPtr<nsROCSSPrimitiveValue> 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;
}

Просмотреть файл

@ -3329,14 +3329,14 @@ ElementRestyler::MustReframeForPseudo(CSSPseudoElementType aPseudoType,
// Check for a ::before pseudo style and the absence of a ::before content,
// but only if aFrame is null or is the first continuation/ib-split.
if ((aFrame && !nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame)) ||
nsLayoutUtils::GetBeforeFrameForContent(aGenConParentFrame, aContent)) {
nsLayoutUtils::GetBeforeFrame(aContent)) {
return false;
}
} else {
// Similarly for ::after, but check for being the last continuation/
// ib-split.
if ((aFrame && nsLayoutUtils::GetNextContinuationOrIBSplitSibling(aFrame)) ||
nsLayoutUtils::GetAfterFrameForContent(aGenConParentFrame, aContent)) {
nsLayoutUtils::GetAfterFrame(aContent)) {
return false;
}
}

Просмотреть файл

@ -335,25 +335,16 @@ ServoRestyleManager::FrameForPseudoElement(const nsIContent* aContent,
nsIAtom* aPseudoTagOrNull)
{
MOZ_ASSERT_IF(aPseudoTagOrNull, aContent->IsElement());
nsIFrame* primaryFrame = aContent->GetPrimaryFrame();
if (!aPseudoTagOrNull) {
return primaryFrame;
return aContent->GetPrimaryFrame();
}
// FIXME(emilio): Need to take into account display: contents pseudos!
if (!primaryFrame) {
return nullptr;
}
// NOTE: we probably need to special-case display: contents here. Gecko's
// RestyleManager passes the primary frame of the parent instead.
if (aPseudoTagOrNull == nsCSSPseudoElements::before) {
return nsLayoutUtils::GetBeforeFrameForContent(primaryFrame, aContent);
return nsLayoutUtils::GetBeforeFrame(aContent);
}
if (aPseudoTagOrNull == nsCSSPseudoElements::after) {
return nsLayoutUtils::GetAfterFrameForContent(primaryFrame, aContent);
return nsLayoutUtils::GetAfterFrame(aContent);
}
MOZ_CRASH("Unkown pseudo-element given to "

Просмотреть файл

@ -6738,9 +6738,8 @@ nsCSSFrameConstructor::FindFrameForContentSibling(nsIContent* aContent,
nsIFrame* sibling = aContent->GetPrimaryFrame();
if (!sibling && GetDisplayContentsStyleFor(aContent)) {
// A display:contents node - check if it has a ::before / ::after frame...
sibling = aPrevSibling ?
nsLayoutUtils::GetAfterFrameForContent(aParentFrame, aContent) :
nsLayoutUtils::GetBeforeFrameForContent(aParentFrame, aContent);
sibling = aPrevSibling ? nsLayoutUtils::GetAfterFrame(aContent)
: nsLayoutUtils::GetBeforeFrame(aContent);
if (!sibling) {
// ... then recurse into children ...
const bool forward = !aPrevSibling;
@ -6751,9 +6750,8 @@ nsCSSFrameConstructor::FindFrameForContentSibling(nsIContent* aContent,
}
if (!sibling) {
// ... then ::after / ::before on the opposite end.
sibling = aPrevSibling ?
nsLayoutUtils::GetBeforeFrameForContent(aParentFrame, aContent) :
nsLayoutUtils::GetAfterFrameForContent(aParentFrame, aContent);
sibling = aPrevSibling ? nsLayoutUtils::GetAfterFrame(aContent)
: nsLayoutUtils::GetBeforeFrame(aContent);
}
if (!sibling) {
return nullptr;

Просмотреть файл

@ -1585,36 +1585,40 @@ nsLayoutUtils::GetChildListNameFor(nsIFrame* aChildFrame)
return id;
}
/*static*/ nsIFrame*
nsLayoutUtils::GetBeforeFrameForContent(nsIFrame* aFrame,
const nsIContent* aContent)
static Element*
GetPseudo(const nsIContent* aContent, nsIAtom* aPseudoProperty)
{
auto* pseudo =
static_cast<Element*>(aContent->GetProperty(nsGkAtoms::beforePseudoProperty));
MOZ_ASSERT(aPseudoProperty == nsGkAtoms::beforePseudoProperty ||
aPseudoProperty == nsGkAtoms::afterPseudoProperty);
return static_cast<Element*>(aContent->GetProperty(aPseudoProperty));
}
/*static*/ Element*
nsLayoutUtils::GetBeforePseudo(const nsIContent* aContent)
{
return GetPseudo(aContent, nsGkAtoms::beforePseudoProperty);
}
/*static*/ nsIFrame*
nsLayoutUtils::GetBeforeFrame(const nsIContent* aContent)
{
Element* pseudo = GetBeforePseudo(aContent);
return pseudo ? pseudo->GetPrimaryFrame() : nullptr;
}
/*static*/ nsIFrame*
nsLayoutUtils::GetBeforeFrame(nsIFrame* aFrame)
/*static*/ Element*
nsLayoutUtils::GetAfterPseudo(const nsIContent* aContent)
{
return GetBeforeFrameForContent(aFrame, aFrame->GetContent());
return GetPseudo(aContent, nsGkAtoms::afterPseudoProperty);
}
/*static*/ nsIFrame*
nsLayoutUtils::GetAfterFrameForContent(nsIFrame* aFrame,
const nsIContent* aContent)
nsLayoutUtils::GetAfterFrame(const nsIContent* aContent)
{
auto* pseudo =
static_cast<Element*>(aContent->GetProperty(nsGkAtoms::afterPseudoProperty));
Element* pseudo = GetAfterPseudo(aContent);
return pseudo ? pseudo->GetPrimaryFrame() : nullptr;
}
/*static*/ nsIFrame*
nsLayoutUtils::GetAfterFrame(nsIFrame* aFrame)
{
return GetAfterFrameForContent(aFrame, aFrame->GetContent());
}
// static
nsIFrame*
nsLayoutUtils::GetClosestFrameOfType(nsIFrame* aFrame,

Просмотреть файл

@ -286,50 +286,26 @@ public:
static mozilla::layout::FrameChildListID GetChildListNameFor(nsIFrame* aChildFrame);
/**
* GetBeforeFrameForContent returns the ::before frame for aContent, if
* one exists. This is typically O(1). The frame passed in must be
* the first-in-flow.
*
* @param aGenConParentFrame an ancestor of the ::before frame
* @param aContent the content whose ::before is wanted
* @return the ::before frame or nullptr if there isn't one
* Returns the ::before pseudo-element for aContent, if any.
*/
static nsIFrame* GetBeforeFrameForContent(nsIFrame* aGenConParentFrame,
const nsIContent* aContent);
static mozilla::dom::Element* GetBeforePseudo(const nsIContent* aContent);
/**
* GetBeforeFrame returns the outermost ::before frame of the given frame, if
* one exists. This is typically O(1). The frame passed in must be
* the first-in-flow.
*
* @param aFrame the frame whose ::before is wanted
* @return the :before frame or nullptr if there isn't one
* Returns the frame corresponding to the ::before pseudo-element for
* aContent, if any.
*/
static nsIFrame* GetBeforeFrame(nsIFrame* aFrame);
static nsIFrame* GetBeforeFrame(const nsIContent* aContent);
/**
* GetAfterFrameForContent returns the ::after frame for aContent, if one
* exists. This will walk the in-flow chain of aGenConParentFrame to the
* last-in-flow if needed. This function is typically O(N) in the number
* of child frames, following in-flows, etc.
*
* @param aGenConParentFrame an ancestor of the ::after frame
* @param aContent the content whose ::after is wanted
* @return the ::after frame or nullptr if there isn't one
* Returns the ::after pseudo-element for aContent, if any.
*/
static nsIFrame* GetAfterFrameForContent(nsIFrame* aGenConParentFrame,
const nsIContent* aContent);
static mozilla::dom::Element* GetAfterPseudo(const nsIContent* aContent);
/**
* GetAfterFrame returns the outermost ::after frame of the given frame, if one
* exists. This will walk the in-flow chain to the last-in-flow if
* needed. This function is typically O(N) in the number of child
* frames, following in-flows, etc.
*
* @param aFrame the frame whose ::after is wanted
* @return the :after frame or nullptr if there isn't one
* Returns the frame corresponding to the ::after pseudo-element for aContent,
* if any.
*/
static nsIFrame* GetAfterFrame(nsIFrame* aFrame);
static nsIFrame* GetAfterFrame(const nsIContent* aContent);
/**
* Given a frame, search up the frame tree until we find an

Просмотреть файл

@ -10365,19 +10365,16 @@ nsIFrame::IsPseudoStackingContextFromStyle() {
Element*
nsIFrame::GetPseudoElement(CSSPseudoElementType aType)
{
nsIFrame* frame = nullptr;
if (aType == CSSPseudoElementType::before) {
frame = nsLayoutUtils::GetBeforeFrame(this);
} else if (aType == CSSPseudoElementType::after) {
frame = nsLayoutUtils::GetAfterFrame(this);
if (!mContent) {
return nullptr;
}
if (frame) {
nsIContent* content = frame->GetContent();
if (content->IsElement()) {
return content->AsElement();
}
if (aType == CSSPseudoElementType::before) {
return nsLayoutUtils::GetBeforePseudo(mContent);
}
if (aType == CSSPseudoElementType::after) {
return nsLayoutUtils::GetAfterPseudo(mContent);
}
return nullptr;