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
This commit is contained in:
Matt A. Tobin
2020-04-17 05:10:25 -04:00
committed by Roy Tam
parent 6b48075b57
commit d3ffda520f
16 changed files with 191 additions and 244 deletions
+31 -30
View File
@@ -1832,11 +1832,7 @@ nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aStat
aPseudoElement == CSSPseudoElementType::after,
"unexpected aPseudoElement");
// XXXbz is this ever true?
if (!aParentContent->IsElement()) {
NS_ERROR("Bogus generated content parent");
return;
}
MOZ_ASSERT(aParentContent->IsElement());
StyleSetHandle styleSet = mPresShell->StyleSet();
@@ -1864,6 +1860,13 @@ nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aStat
nsresult rv = NS_NewXMLElement(getter_AddRefs(container), nodeInfo.forget());
if (NS_FAILED(rv))
return;
// Cleared when the pseudo is unbound from the tree, so no need to store a
// strong reference, nor a destructor.
nsIAtom* property = isBefore
? nsGkAtoms::beforePseudoProperty : nsGkAtoms::afterPseudoProperty;
aParentContent->SetProperty(property, container.get());
container->SetIsNativeAnonymousRoot();
container->SetPseudoElementType(aPseudoElement);
@@ -6079,6 +6082,9 @@ AddGenConPseudoToFrame(nsIFrame* aOwnerFrame, nsIContent* aContent)
NS_ASSERTION(nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aOwnerFrame),
"property should only be set on first continuation/ib-sibling");
// FIXME(emilio): Remove this property, and use the frame of the generated
// content itself to tear the content down? It should be quite simpler.
nsIFrame::ContentArray* value =
aOwnerFrame->GetProperty(nsIFrame::GenConProperty());
if (!value) {
@@ -6340,7 +6346,7 @@ AdjustAppendParentForAfterContent(nsFrameManager* aFrameManager,
// frames to find the first one that is either a ::after frame for an
// ancestor of aChild or a frame that is for a node later in the
// document than aChild and return that in aAfterFrame.
if (aParentFrame->GetGenConPseudos() ||
if (aParentFrame->GetProperty(nsIFrame::GenConProperty()) ||
nsLayoutUtils::HasPseudoStyle(aContainer, aParentFrame->StyleContext(),
CSSPseudoElementType::after,
aParentFrame->PresContext()) ||
@@ -6669,9 +6675,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;
@@ -6682,9 +6687,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;
@@ -8291,26 +8295,23 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
MOZ_ASSERT(!childFrame || !GetDisplayContentsStyleFor(aChild),
"display:contents nodes shouldn't have a frame");
if (!childFrame && GetDisplayContentsStyleFor(aChild)) {
nsIFrame* ancestorFrame = nullptr;
nsIContent* ancestor = aContainer;
for (; ancestor; ancestor = ancestor->GetParent()) {
ancestorFrame = ancestor->GetPrimaryFrame();
if (ancestorFrame) {
break;
}
while (!ancestor->GetPrimaryFrame()) {
// FIXME(emilio): Should this use the flattened tree parent instead?
ancestor = ancestor->GetParent();
MOZ_ASSERT(ancestor, "we can't have a display: contents subtree root!");
}
if (ancestorFrame) {
nsIFrame* contentInsertion = ancestorFrame->GetContentInsertionFrame();
if (ancestorFrame->GetGenConPseudos() ||
(contentInsertion && contentInsertion->GetGenConPseudos())) {
*aDidReconstruct = true;
LAYOUT_PHASE_TEMP_EXIT();
// XXXmats Can we recreate frames only for the ::after/::before content?
// XXX Perhaps even only those that belong to the aChild sub-tree?
RecreateFramesForContent(ancestor, false, aFlags, aDestroyedFramesFor);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
nsIFrame* ancestorFrame = ancestor->GetPrimaryFrame();
if (ancestorFrame->GetProperty(nsIFrame::GenConProperty())) {
*aDidReconstruct = true;
LAYOUT_PHASE_TEMP_EXIT();
// XXXmats Can we recreate frames only for the ::after/::before content?
// XXX Perhaps even only those that belong to the aChild sub-tree?
RecreateFramesForContent(ancestor, false, aFlags, aDestroyedFramesFor);
LAYOUT_PHASE_TEMP_REENTER();
return;
}
FlattenedChildIterator iter(aChild);