--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -2561,20 +2561,23 @@ nsCSSFrameConstructor::ConstructDocEleme
// function to this FrameConstructionData.
// XXXbz on the other hand, if we converted this whole function to
// FrameConstructionData/Item, then we'd need the right function
// here... but would probably be able to get away with less code in this
// function in general.
// Use a null PendingBinding, since our binding is not in fact pending.
static const FrameConstructionData rootSVGData = FCDATA_DECL(0, nullptr);
- already_AddRefed<ComputedStyle> extraRef =
- RefPtr<ComputedStyle>(computedStyle).forget();
- AutoFrameConstructionItem item(this, &rootSVGData, aDocElement,
- nullptr, extraRef, true, nullptr);
+ AutoFrameConstructionItem item(this,
+ &rootSVGData,
+ aDocElement,
+ nullptr,
+ RefPtr<ComputedStyle>(computedStyle).forget(),
+ true,
+ nullptr);
nsFrameItems frameItems;
contentFrame = static_cast<nsContainerFrame*>(
ConstructOuterSVG(state, item, mDocElementContainingBlock,
computedStyle->StyleDisplay(),
frameItems));
newFrame = frameItems.FirstChild();
NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
@@ -2611,20 +2614,23 @@ nsCSSFrameConstructor::ConstructDocEleme
// function to this FrameConstructionData.
// XXXbz on the other hand, if we converted this whole function to
// FrameConstructionData/Item, then we'd need the right function
// here... but would probably be able to get away with less code in this
// function in general.
// Use a null PendingBinding, since our binding is not in fact pending.
static const FrameConstructionData rootTableData = FCDATA_DECL(0, nullptr);
- already_AddRefed<ComputedStyle> extraRef =
- RefPtr<ComputedStyle>(computedStyle).forget();
- AutoFrameConstructionItem item(this, &rootTableData, aDocElement,
- nullptr, extraRef, true, nullptr);
+ AutoFrameConstructionItem item(this,
+ &rootTableData,
+ aDocElement,
+ nullptr,
+ RefPtr<ComputedStyle>(computedStyle).forget(),
+ true,
+ nullptr);
nsFrameItems frameItems;
// if the document is a table then just populate it.
contentFrame = static_cast<nsContainerFrame*>(
ConstructTable(state, item, mDocElementContainingBlock,
computedStyle->StyleDisplay(),
frameItems));
newFrame = frameItems.FirstChild();
@@ -5613,20 +5619,18 @@ ShouldSuppressFrameInNonOpenDetails(cons
return true;
}
auto* summary = HTMLSummaryElement::FromNode(aChild);
if (summary && summary->IsMainSummary()) {
return false;
}
- // Don't suppress NAC, unless it's ::before or ::after.
- if (aChild->IsRootOfAnonymousSubtree() &&
- !aChild->IsGeneratedContentContainerForBefore() &&
- !aChild->IsGeneratedContentContainerForAfter()) {
+ // Don't suppress NAC, even if it's ::before or ::after.
+ if (aChild->IsRootOfAnonymousSubtree()) {
return false;
}
return true;
}
static bool
ShouldCreateImageFrameForContent(ComputedStyle& aStyle)
@@ -5634,16 +5638,28 @@ ShouldCreateImageFrameForContent(Compute
auto& content = *aStyle.StyleContent();
if (content.ContentCount() != 1) {
return false;
}
return content.ContentAt(0).GetType() == StyleContentType::Image;
}
+static bool
+IsMainSummaryInOpenDetails(const HTMLDetailsElement* aDetails,
+ const nsIContent* aChild)
+{
+ if (!aDetails || !aDetails->Open()) {
+ return false;
+ }
+
+ auto* summary = HTMLSummaryElement::FromNode(aChild);
+ return summary && summary->IsMainSummary();
+}
+
void
nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
nsIContent* aContent,
nsContainerFrame* aParentFrame,
bool aSuppressWhiteSpaceOptimizations,
ComputedStyle* aComputedStyle,
uint32_t aFlags,
nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren,
@@ -5855,33 +5871,22 @@ nsCSSFrameConstructor::AddFrameConstruct
!display->IsAbsolutelyPositionedStyle() &&
!(aParentFrame && aParentFrame->IsGridContainerFrame()) &&
!(bits & FCDATA_IS_TABLE_PART) && !(bits & FCDATA_IS_SVG_TEXT);
if (canHavePageBreak && display->mBreakBefore) {
AddPageBreakItem(aContent, aItems);
}
- 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,
- aAnonChildren);
- }
- }
-
- if (!item) {
- item = aItems.AppendItem(this, data, aContent, pendingBinding,
- computedStyle.forget(),
- aSuppressWhiteSpaceOptimizations, aAnonChildren);
- }
+ item = new (this) FrameConstructionItem(data,
+ aContent,
+ pendingBinding,
+ computedStyle.forget(),
+ aSuppressWhiteSpaceOptimizations,
+ aAnonChildren);
item->mIsText = isText;
item->mIsGeneratedContent = isGeneratedContent;
item->mIsAnonymousContentCreatorContent =
aFlags & ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT;
if (isGeneratedContent) {
// We need to keep this alive until the frame takes ownership.
// This corresponds to the Release in ConstructFramesFromItem.
item->mContent->AddRef();
@@ -5891,20 +5896,16 @@ nsCSSFrameConstructor::AddFrameConstruct
aContent->IsRootOfNativeAnonymousSubtree();
if (item->mIsRootPopupgroup) {
aState.mHavePendingPopupgroup = true;
}
item->mIsPopup = isPopup;
item->mIsForSVGAElement = namespaceId == kNameSpaceID_SVG &&
tag == nsGkAtoms::a;
- if (canHavePageBreak && display->mBreakAfter) {
- AddPageBreakItem(aContent, aItems);
- }
-
if (bits & FCDATA_IS_INLINE) {
// To correctly set item->mIsAllInline we need to build up our child items
// right now.
BuildInlineChildItems(aState, *item,
aFlags & ITEM_IS_WITHIN_SVG_TEXT,
aFlags & ITEM_ALLOWS_TEXT_PATH_CHILD);
item->mHasInlineEnds = true;
item->mIsBlock = false;
@@ -5950,31 +5951,42 @@ nsCSSFrameConstructor::AddFrameConstruct
// out-of-flow, we can't use it here. But we _can_ say that the frame will
// for sure end up in-flow if it's not floated or absolutely positioned.
item->mIsBlock = !isInline &&
!display->IsAbsolutelyPositionedStyle() &&
!display->IsFloatingStyle() &&
!(bits & FCDATA_IS_SVG_TEXT);
}
- if (item->mIsAllInline) {
- aItems.InlineItemAdded();
- } else if (item->mIsBlock) {
- aItems.BlockItemAdded();
- }
-
// Our item should be treated as a line participant if we have the relevant
// bit and are going to be in-flow. Note that this really only matters if
// our ancestor is a box or some such, so the fact that we might have an
// inline ancestor that might become a containing block is not relevant here.
if ((bits & FCDATA_IS_LINE_PARTICIPANT) &&
((bits & FCDATA_DISALLOW_OUT_OF_FLOW) ||
!aState.GetGeometricParent(display, nullptr))) {
item->mIsLineParticipant = true;
- aItems.LineParticipantItemAdded();
+ }
+
+ FrameConstructionItemList::Iterator iter(aItems);
+ if (IsMainSummaryInOpenDetails(details, aContent)) {
+ if (!iter.IsDone() &&
+ iter.item().mIsGeneratedContent &&
+ iter.item().mContent->IsGeneratedContentContainerForBefore() &&
+ iter.item().mContent->GetParent() == details) {
+ iter.Next();
+ }
+ } else {
+ iter.SetToEnd();
+ }
+
+ iter.InsertItem(item);
+
+ if (canHavePageBreak && display->mBreakAfter) {
+ AddPageBreakItem(aContent, aItems);
}
}
/**
* Return true if the frame construction item pointed to by aIter will
* create a frame adjacent to a line boundary in the frame tree, and that
* line boundary is induced by a content node adjacent to the frame's
* content node in the content tree. The latter condition is necessary so
@@ -9466,34 +9478,34 @@ nsCSSFrameConstructor::CreateNeededAnonF
// Now, we create the anonymous flex or grid item to contain the children
// between |iter| and |endIter|.
nsAtom* pseudoType = (aParentFrame->IsFlexContainerFrame())
? nsCSSAnonBoxes::anonymousFlexItem
: nsCSSAnonBoxes::anonymousGridItem;
ComputedStyle* parentStyle = aParentFrame->Style();
nsIContent* parentContent = aParentFrame->GetContent();
- already_AddRefed<ComputedStyle> wrapperStyle =
+ RefPtr<ComputedStyle> wrapperStyle =
mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(pseudoType,
parentStyle);
static const FrameConstructionData sBlockFormattingContextFCData =
FCDATA_DECL(FCDATA_SKIP_FRAMESET |
FCDATA_USE_CHILD_ITEMS |
FCDATA_IS_WRAPPER_ANON_BOX,
NS_NewBlockFormattingContext);
FrameConstructionItem* newItem =
new (this) FrameConstructionItem(&sBlockFormattingContextFCData,
- // Use the content of our parent frame
- parentContent,
- // no pending binding
- nullptr,
- wrapperStyle,
- true, nullptr);
+ // Use the content of our parent frame
+ parentContent,
+ // no pending binding
+ nullptr,
+ wrapperStyle.forget(),
+ true, nullptr);
newItem->mIsAllInline = newItem->mHasInlineEnds =
newItem->mComputedStyle->StyleDisplay()->IsInlineOutsideStyle();
newItem->mIsBlock = !newItem->mIsAllInline;
MOZ_ASSERT(!newItem->mIsAllInline && newItem->mIsBlock,
"expecting anonymous flex/grid items to be block-level "
"(this will make a difference when we encounter "
@@ -9968,34 +9980,34 @@ nsCSSFrameConstructor::WrapItemsInPseudo
if (pseudoType == nsCSSAnonBoxes::table &&
(parentDisplay == StyleDisplay::Inline ||
parentDisplay == StyleDisplay::RubyBase ||
parentDisplay == StyleDisplay::RubyText)) {
pseudoType = nsCSSAnonBoxes::inlineTable;
}
- already_AddRefed<ComputedStyle> wrapperStyle;
+ RefPtr<ComputedStyle> wrapperStyle;
if (pseudoData.mFCData.mBits & FCDATA_IS_WRAPPER_ANON_BOX) {
wrapperStyle =
mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(pseudoType,
aParentStyle);
} else {
wrapperStyle =
mPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(pseudoType);
}
FrameConstructionItem* newItem =
new (this) FrameConstructionItem(&pseudoData.mFCData,
- // Use the content of our parent frame
- aParentContent,
- // no pending binding
- nullptr,
- wrapperStyle,
- true, nullptr);
+ // Use the content of our parent frame
+ aParentContent,
+ // no pending binding
+ nullptr,
+ wrapperStyle.forget(),
+ true, nullptr);
const nsStyleDisplay* disp = newItem->mComputedStyle->StyleDisplay();
// Here we're cheating a tad... technically, table-internal items should be
// inline if aParentFrame is inline, but they'll get wrapped in an
// inline-table in the end, so it'll all work out. In any case, arguably
// we don't need to maintain this state at this point... but it's better
// to, I guess.
newItem->mIsAllInline = newItem->mHasInlineEnds =
@@ -10040,26 +10052,26 @@ nsCSSFrameConstructor::CreateNeededPseud
if (firstDisplay == StyleDisplay::RubyBaseContainer) {
return;
}
NS_ASSERTION(firstDisplay == StyleDisplay::RubyTextContainer,
"Child of ruby frame should either a rbc or a rtc");
const PseudoParentData& pseudoData =
sPseudoParentData[eTypeRubyBaseContainer];
- already_AddRefed<ComputedStyle> pseudoStyle = mPresShell->StyleSet()->
+ RefPtr<ComputedStyle> pseudoStyle = mPresShell->StyleSet()->
ResolveInheritingAnonymousBoxStyle(*pseudoData.mPseudoType,
aParentFrame->Style());
FrameConstructionItem* newItem =
new (this) FrameConstructionItem(&pseudoData.mFCData,
// Use the content of the parent frame
aParentFrame->GetContent(),
// no pending binding
nullptr,
- pseudoStyle,
+ pseudoStyle.forget(),
true, nullptr);
newItem->mIsAllInline = true;
newItem->mChildItems.SetParentHasNoXBLChildren(true);
iter.InsertItem(newItem);
}
#ifdef DEBUG
/**
@@ -10192,17 +10204,17 @@ nsCSSFrameConstructor::AddFCItemsForAnon
true, computedStyle, flags,
anonChildren, aItemsToConstruct);
}
}
void
nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
nsIContent* aContent,
- ComputedStyle* aComputedStyle,
+ ComputedStyle* aComputedStyle,
nsContainerFrame* aFrame,
const bool aCanHaveGeneratedContent,
nsFrameItems& aFrameItems,
const bool aAllowBlockStyles,
PendingBinding* aPendingBinding,
nsIFrame* aPossiblyLeafFrame)
{
MOZ_ASSERT(aFrame, "Must have parent frame here");
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -850,49 +850,26 @@ private:
nsIContent* aContent,
PendingBinding* aPendingBinding,
already_AddRefed<ComputedStyle>&& aComputedStyle,
bool aSuppressWhiteSpaceOptimizations,
nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren)
{
FrameConstructionItem* item =
new (aFCtor) FrameConstructionItem(aFCData, aContent,
- aPendingBinding, aComputedStyle,
+ aPendingBinding,
+ std::move(aComputedStyle),
aSuppressWhiteSpaceOptimizations,
aAnonChildren);
mItems.insertBack(item);
++mItemCount;
++mDesiredParentCounts[item->DesiredParentType()];
return item;
}
- // Arguments are the same as AppendItem().
- FrameConstructionItem* PrependItem(nsCSSFrameConstructor* aFCtor,
- const FrameConstructionData* aFCData,
- nsIContent* aContent,
- PendingBinding* aPendingBinding,
- already_AddRefed<ComputedStyle>&& aComputedStyle,
- bool aSuppressWhiteSpaceOptimizations,
- nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren)
- {
- FrameConstructionItem* item =
- new (aFCtor) FrameConstructionItem(aFCData, aContent,
- aPendingBinding, aComputedStyle,
- aSuppressWhiteSpaceOptimizations,
- aAnonChildren);
- mItems.insertFront(item);
- ++mItemCount;
- ++mDesiredParentCounts[item->DesiredParentType()];
- return item;
- }
-
- void InlineItemAdded() { ++mInlineCount; }
- void BlockItemAdded() { ++mBlockCount; }
- void LineParticipantItemAdded() { ++mLineParticipantCount; }
-
class Iterator {
public:
explicit Iterator(FrameConstructionItemList& aList)
: mCurrent(aList.mItems.getFirst())
, mList(aList)
{}
Iterator(const Iterator& aOther) :
mCurrent(aOther.mCurrent),
@@ -1098,17 +1075,17 @@ private:
* frame other than the parent frame and whatever would be stored in the
* frame constructor state. You probably want to use
* AutoFrameConstructionItem instead of this struct. */
struct FrameConstructionItem final
: public mozilla::LinkedListElement<FrameConstructionItem> {
FrameConstructionItem(const FrameConstructionData* aFCData,
nsIContent* aContent,
PendingBinding* aPendingBinding,
- already_AddRefed<ComputedStyle>& aComputedStyle,
+ already_AddRefed<ComputedStyle> aComputedStyle,
bool aSuppressWhiteSpaceOptimizations,
nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren) :
mFCData(aFCData), mContent(aContent),
mPendingBinding(aPendingBinding), mComputedStyle(aComputedStyle),
mSuppressWhiteSpaceOptimizations(aSuppressWhiteSpaceOptimizations),
mIsText(false), mIsGeneratedContent(false),
mIsAnonymousContentCreatorContent(false),
mIsRootPopupgroup(false), mIsAllInline(false), mIsBlock(false),