--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -5559,32 +5559,16 @@ nsCSSFrameConstructor::AddFrameConstruct
return;
}
RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(aContent);
DoAddFrameConstructionItems(aState, aContent, computedStyle,
aSuppressWhiteSpaceOptimizations, parentFrame,
nullptr, aItems);
}
-void
-nsCSSFrameConstructor::SetAsUndisplayedContent(nsFrameConstructorState& aState,
- FrameConstructionItemList& aList,
- nsIContent* aContent,
- ComputedStyle* aComputedStyle,
- bool aIsGeneratedContent)
-{
- if (aComputedStyle->GetPseudo()) {
- if (aIsGeneratedContent) {
- aContent->UnbindFromTree();
- }
- return;
- }
- MOZ_ASSERT(!aIsGeneratedContent, "Should have had pseudo type");
-}
-
// Whether we should suppress frames for a child under a <select> frame.
//
// Never create frames for non-option/optgroup kids of <select> and non-option
// kids of <optgroup> inside a <select>.
// XXXbz it's not clear how this should best work with XBL.
static bool
ShouldSuppressFrameInSelect(const nsIContent* aParent,
const nsIContent* aChild)
@@ -5712,22 +5696,32 @@ nsCSSFrameConstructor::AddFrameConstruct
if (overridenNamespace == kNameSpaceID_XUL) {
tag = overridenTag;
}
}
}
}
const bool isGeneratedContent = !!(aFlags & ITEM_IS_GENERATED_CONTENT);
+ MOZ_ASSERT(!isGeneratedContent || computedStyle->GetPseudo(),
+ "Generated content should be a pseudo-element");
+
+ FrameConstructionItem* item = nullptr;
+ auto cleanupGeneratedContent = mozilla::MakeScopeExit([&]() {
+ if (isGeneratedContent && !item) {
+ MOZ_ASSERT(!IsDisplayContents(aContent),
+ "This would need to change if we support display: contents "
+ "in generated content");
+ aContent->UnbindFromTree();
+ }
+ });
// Pre-check for display "none" - if we find that, don't create
// any frame at all
if (display->mDisplay == StyleDisplay::None) {
- SetAsUndisplayedContent(aState, aItems, aContent, computedStyle,
- isGeneratedContent);
return;
}
if (display->mDisplay == StyleDisplay::Contents) {
if (aParentFrame) {
// FIXME(emilio): Pretty sure aParentFrame can't be null here.
aParentFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT);
}
@@ -5753,32 +5747,26 @@ nsCSSFrameConstructor::AddFrameConstruct
aItems);
return;
}
bool isText = !aContent->IsElement();
nsIContent* parent = aParentFrame ? aParentFrame->GetContent() : nullptr;
if (ShouldSuppressFrameInSelect(parent, aContent)) {
- if (!isText) {
- SetAsUndisplayedContent(aState, aItems, aContent, computedStyle,
- isGeneratedContent);
- }
return;
}
// When constructing a child of a non-open <details>, create only the frame
// for the main <summary> element, and skip other elements. This only applies
// to things that are not roots of native anonymous subtrees (except for
// ::before and ::after); we always want to create "internal" anonymous
// content.
auto* details = HTMLDetailsElement::FromNodeOrNull(parent);
if (ShouldSuppressFrameInNonOpenDetails(details, aContent)) {
- SetAsUndisplayedContent(aState, aItems, aContent, computedStyle,
- isGeneratedContent);
return;
}
bool isPopup = false;
// Try to find frame construction data for this content
const FrameConstructionData* data;
if (isText) {
data = FindTextData(aParentFrame);
@@ -5790,18 +5778,16 @@ nsCSSFrameConstructor::AddFrameConstruct
Element* element = aContent->AsElement();
// Don't create frames for non-SVG element children of SVG elements.
if (namespaceId != kNameSpaceID_SVG &&
((aParentFrame &&
IsFrameForSVG(aParentFrame) &&
!aParentFrame->IsFrameOfType(nsIFrame::eSVGForeignObject)) ||
(aFlags & ITEM_IS_WITHIN_SVG_TEXT))) {
- SetAsUndisplayedContent(aState, aItems, element, computedStyle,
- isGeneratedContent);
return;
}
data = FindHTMLData(element, tag, namespaceId, aParentFrame,
computedStyle);
if (!data) {
data = FindXULTagData(element, tag, namespaceId, computedStyle);
}
@@ -5823,57 +5809,52 @@ nsCSSFrameConstructor::AddFrameConstruct
// And general display types
if (!data) {
data = FindDisplayData(display, element, computedStyle);
}
MOZ_ASSERT(data, "Should have frame construction data now");
if (data->mBits & FCDATA_SUPPRESS_FRAME) {
- SetAsUndisplayedContent(aState, aItems, element, computedStyle, isGeneratedContent);
return;
}
#ifdef MOZ_XUL
if ((data->mBits & FCDATA_IS_POPUP) &&
(!aParentFrame || // Parent is inline
!aParentFrame->IsMenuFrame())) {
if (!aState.mPopupItems.containingBlock &&
!aState.mHavePendingPopupgroup) {
- SetAsUndisplayedContent(aState, aItems, element, computedStyle,
- isGeneratedContent);
return;
}
isPopup = true;
}
#endif /* MOZ_XUL */
}
uint32_t bits = data->mBits;
// Inside colgroups, suppress everything except columns.
if (aParentFrame && aParentFrame->IsTableColGroupFrame() &&
(!(bits & FCDATA_IS_TABLE_PART) ||
display->mDisplay != StyleDisplay::TableColumn)) {
- SetAsUndisplayedContent(aState, aItems, aContent, computedStyle, isGeneratedContent);
return;
}
bool canHavePageBreak =
(aFlags & ITEM_ALLOW_PAGE_BREAK) && aState.mPresContext->IsPaginated() &&
!display->IsAbsolutelyPositionedStyle() &&
!(aParentFrame && aParentFrame->IsGridContainerFrame()) &&
!(bits & FCDATA_IS_TABLE_PART) && !(bits & FCDATA_IS_SVG_TEXT);
if (canHavePageBreak && display->mBreakBefore) {
AddPageBreakItem(aContent, aItems);
}
- FrameConstructionItem* item = nullptr;
if (details && details->Open()) {
auto* summary = HTMLSummaryElement::FromNode(aContent);
if (summary && summary->IsMainSummary()) {
// If details is open, the main summary needs to be rendered as if it is
// the first child, so add the item to the front of the item list.
item = aItems.PrependItem(this, data, aContent, pendingBinding,
computedStyle.forget(),
aSuppressWhiteSpaceOptimizations,
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -2113,27 +2113,16 @@ private:
// may be constructed based on tag, not based on aDisplay!
bool IsValidSibling(nsIFrame* aSibling,
nsIContent* aContent,
mozilla::StyleDisplay& aDisplay);
void QuotesDirty();
void CountersDirty();
- /**
- * Add the pair (aContent, aComputedStyle) to the undisplayed items
- * in aList as needed. This method enforces the invariant that all
- * styles in the undisplayed content map must be non-pseudo contexts and also
- * handles unbinding undisplayed generated content as needed.
- */
- void SetAsUndisplayedContent(nsFrameConstructorState& aState,
- FrameConstructionItemList& aList,
- nsIContent* aContent,
- ComputedStyle* aComputedStyle,
- bool aIsGeneratedContent);
// Create touch caret frame.
void ConstructAnonymousContentForCanvas(nsFrameConstructorState& aState,
nsIFrame* aFrame,
nsIContent* aDocElement);
public:
friend class nsFrameConstructorState;