Bug 1409083 Part 3: Add a GetFirstNonAnonBoxDescendant function to unpack anonymous flex items.
This patch is effectively just resurrecting a function that was previously removed in https://hg.mozilla.org/mozilla-central/rev/173a4f49dfe3#l1.96 .
MozReview-Commit-ID: 4PXSOu4tzzU
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -152,16 +152,59 @@ ConvertLegacyStyleToJustifyContent(const
return NS_STYLE_ALIGN_SPACE_BETWEEN;
}
MOZ_ASSERT_UNREACHABLE("Unrecognized mBoxPack enum value");
// Fall back to default value of "justify-content" property:
return NS_STYLE_ALIGN_FLEX_START;
}
+// Helper-function to find the first non-anonymous-box descendent of aFrame.
+static nsIFrame*
+GetFirstNonAnonBoxDescendant(nsIFrame* aFrame)
+{
+ while (aFrame) {
+ nsAtom* pseudoTag = aFrame->StyleContext()->GetPseudo();
+
+ // If aFrame isn't an anonymous container, then it'll do.
+ if (!pseudoTag || // No pseudotag.
+ !nsCSSAnonBoxes::IsAnonBox(pseudoTag) || // Pseudotag isn't anon.
+ nsCSSAnonBoxes::IsNonElement(pseudoTag)) { // Text, not a container.
+ break;
+ }
+
+ // Otherwise, descend to its first child and repeat.
+
+ // SPECIAL CASE: if we're dealing with an anonymous table, then it might
+ // be wrapping something non-anonymous in its caption or col-group lists
+ // (instead of its principal child list), so we have to look there.
+ // (Note: For anonymous tables that have a non-anon cell *and* a non-anon
+ // column, we'll always return the column. This is fine; we're really just
+ // looking for a handle to *anything* with a meaningful content node inside
+ // the table, for use in DOM comparisons to things outside of the table.)
+ if (MOZ_UNLIKELY(aFrame->IsTableWrapperFrame())) {
+ nsIFrame* captionDescendant =
+ GetFirstNonAnonBoxDescendant(aFrame->GetChildList(kCaptionList).FirstChild());
+ if (captionDescendant) {
+ return captionDescendant;
+ }
+ } else if (MOZ_UNLIKELY(aFrame->IsTableFrame())) {
+ nsIFrame* colgroupDescendant =
+ GetFirstNonAnonBoxDescendant(aFrame->GetChildList(kColGroupList).FirstChild());
+ if (colgroupDescendant) {
+ return colgroupDescendant;
+ }
+ }
+
+ // USUAL CASE: Descend to the first child in principal list.
+ aFrame = aFrame->PrincipalChildList().FirstChild();
+ }
+ return aFrame;
+}
+
// Indicates whether advancing along the given axis is equivalent to
// increasing our X or Y position (as opposed to decreasing it).
static inline bool
AxisGrowsInPositiveDirection(AxisOrientationType aAxis)
{
return eAxis_LR == aAxis || eAxis_TB == aAxis;
}
@@ -4306,20 +4349,42 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
ComputedFlexLineInfo::GrowthState::UNCHANGED;
// The remaining lineInfo properties will be filled out at the
// end of this function, when we have real values. But we still
// add all the items here, so we can capture computed data for
// each item.
for (const FlexItem* item = line->GetFirstItem(); item;
item = item->getNext()) {
+ nsIFrame* frame = item->Frame();
+
+ // The frame may be for an element, or it may be for an
+ // anonymous flex item, e.g. wrapping one or more text nodes.
+ // DevTools wants the content node for the actual child in
+ // the DOM tree, so we descend through anonymous boxes.
+ nsIFrame* targetFrame = GetFirstNonAnonBoxDescendant(frame);
+ nsIContent* content = targetFrame->GetContent();
+
+ // Skip over content that is only whitespace, which might
+ // have been broken off from a text node which is our real
+ // target.
+ while (content && content->TextIsOnlyWhitespace()) {
+ // If content is only whitespace, try the frame sibling.
+ targetFrame = targetFrame->GetNextSibling();
+ if (targetFrame) {
+ content = targetFrame->GetContent();
+ } else {
+ content = nullptr;
+ }
+ }
+
ComputedFlexItemInfo* itemInfo =
lineInfo->mItems.AppendElement();
- itemInfo->mNode = item->Frame()->GetContent();
+ itemInfo->mNode = content;
// mMainBaseSize and itemInfo->mMainDeltaSize will
// be filled out in ResolveFlexibleLengths().
// Other FlexItem properties can be captured now.
itemInfo->mMainMinSize = item->GetMainMinSize();
itemInfo->mMainMaxSize = item->GetMainMaxSize();
itemInfo->mCrossMinSize = item->GetCrossMinSize();