Backed out 2 changesets (bug 1799580, bug 1799343) for causing mochitest failures on win7 CLOSED TREE
Backed out changeset fb0df93a4719 (bug 1799580) Backed out changeset 493c9ca00c91 (bug 1799343)
This commit is contained in:
@@ -204,6 +204,7 @@ static FrameCtorDebugFlags gFlags[] = {
|
||||
#endif
|
||||
|
||||
#include "nsMenuFrame.h"
|
||||
#include "nsPopupSetFrame.h"
|
||||
#include "nsTreeColFrame.h"
|
||||
|
||||
//------------------------------------------------------------------
|
||||
@@ -220,6 +221,8 @@ nsIFrame* NS_NewSplitterFrame(PresShell* aPresShell, ComputedStyle* aStyle);
|
||||
|
||||
nsIFrame* NS_NewMenuPopupFrame(PresShell* aPresShell, ComputedStyle* aStyle);
|
||||
|
||||
nsIFrame* NS_NewPopupSetFrame(PresShell* aPresShell, ComputedStyle* aStyle);
|
||||
|
||||
nsIFrame* NS_NewMenuFrame(PresShell* aPresShell, ComputedStyle* aStyle,
|
||||
uint32_t aFlags);
|
||||
|
||||
@@ -601,6 +604,9 @@ class MOZ_STACK_CLASS nsFrameConstructorState {
|
||||
PresShell* mPresShell;
|
||||
nsFrameManager* mFrameManager;
|
||||
|
||||
// Frames destined for the kPopupList.
|
||||
AbsoluteFrameList mPopupList;
|
||||
|
||||
// Containing block information for out-of-flow frames.
|
||||
AbsoluteFrameList mFixedList;
|
||||
AbsoluteFrameList mAbsoluteList;
|
||||
@@ -632,6 +638,11 @@ class MOZ_STACK_CLASS nsFrameConstructorState {
|
||||
// abs-pos lists together.
|
||||
bool mFixedPosIsAbsPos;
|
||||
|
||||
// A boolean to indicate whether we have a "pending" popupgroup. That is, we
|
||||
// have already created the FrameConstructionItem for the root popupgroup but
|
||||
// we have not yet created the relevant frame.
|
||||
bool mHavePendingPopupgroup;
|
||||
|
||||
// If false (which is the default) then call SetPrimaryFrame() as needed
|
||||
// during frame construction. If true, don't make any SetPrimaryFrame()
|
||||
// calls, except for generated content which doesn't have a primary frame
|
||||
@@ -734,11 +745,13 @@ class MOZ_STACK_CLASS nsFrameConstructorState {
|
||||
* positioned
|
||||
* @param aCanBeFloated pass false if the frame isn't allowed to be
|
||||
* floated
|
||||
* @param aIsOutOfFlowPopup pass true if the frame is an out-of-flow popup
|
||||
* (XUL-only)
|
||||
*/
|
||||
void AddChild(nsIFrame* aNewFrame, nsFrameList& aFrameList,
|
||||
nsIContent* aContent, nsContainerFrame* aParentFrame,
|
||||
bool aCanBePositioned = true, bool aCanBeFloated = true,
|
||||
bool aInsertAfter = false,
|
||||
bool aIsOutOfFlowPopup = false, bool aInsertAfter = false,
|
||||
nsIFrame* aInsertAfterFrame = nullptr);
|
||||
|
||||
/**
|
||||
@@ -776,6 +789,7 @@ class MOZ_STACK_CLASS nsFrameConstructorState {
|
||||
AbsoluteFrameList* GetOutOfFlowFrameList(nsIFrame* aNewFrame,
|
||||
bool aCanBePositioned,
|
||||
bool aCanBeFloated,
|
||||
bool aIsOutOfFlowPopup,
|
||||
nsFrameState* aPlaceholderType);
|
||||
|
||||
void ConstructBackdropFrameFor(nsIContent* aContent, nsIFrame* aFrame);
|
||||
@@ -789,6 +803,7 @@ nsFrameConstructorState::nsFrameConstructorState(
|
||||
: mPresContext(aPresShell->GetPresContext()),
|
||||
mPresShell(aPresShell),
|
||||
mFrameManager(aPresShell->FrameConstructor()),
|
||||
mPopupList(nullptr),
|
||||
mFixedList(aFixedContainingBlock),
|
||||
mAbsoluteList(aAbsoluteContainingBlock),
|
||||
mFloatedList(aFloatContainingBlock),
|
||||
@@ -805,8 +820,14 @@ nsFrameConstructorState::nsFrameConstructorState(
|
||||
// block, use the abs-pos containing block's abs-pos list for fixed-pos
|
||||
// frames.
|
||||
mFixedPosIsAbsPos(aFixedContainingBlock == aAbsoluteContainingBlock),
|
||||
mHavePendingPopupgroup(false),
|
||||
mCreatingExtraFrames(false),
|
||||
mHasRenderedLegend(false) {
|
||||
nsIPopupContainer* popupContainer =
|
||||
nsIPopupContainer::GetPopupContainer(aPresShell);
|
||||
if (popupContainer) {
|
||||
mPopupList.mContainingBlock = popupContainer->GetPopupSetFrame();
|
||||
}
|
||||
MOZ_COUNT_CTOR(nsFrameConstructorState);
|
||||
}
|
||||
|
||||
@@ -833,6 +854,7 @@ void nsFrameConstructorState::ProcessFrameInsertionsForAllLists() {
|
||||
ProcessFrameInsertions(mFloatedList, nsIFrame::kFloatList);
|
||||
ProcessFrameInsertions(mAbsoluteList, nsIFrame::kAbsoluteList);
|
||||
ProcessFrameInsertions(mFixedList, nsIFrame::kFixedList);
|
||||
ProcessFrameInsertions(mPopupList, nsIFrame::kPopupList);
|
||||
}
|
||||
|
||||
void nsFrameConstructorState::PushAbsoluteContainingBlock(
|
||||
@@ -1032,7 +1054,12 @@ void nsFrameConstructorState::ReparentFloats(nsContainerFrame* aNewParent) {
|
||||
|
||||
AbsoluteFrameList* nsFrameConstructorState::GetOutOfFlowFrameList(
|
||||
nsIFrame* aNewFrame, bool aCanBePositioned, bool aCanBeFloated,
|
||||
nsFrameState* aPlaceholderType) {
|
||||
bool aIsOutOfFlowPopup, nsFrameState* aPlaceholderType) {
|
||||
if (MOZ_UNLIKELY(aIsOutOfFlowPopup)) {
|
||||
MOZ_ASSERT(mPopupList.mContainingBlock, "Must have a popup set frame!");
|
||||
*aPlaceholderType = PLACEHOLDER_FOR_POPUP;
|
||||
return &mPopupList;
|
||||
}
|
||||
const nsStyleDisplay* disp = aNewFrame->StyleDisplay();
|
||||
if (aCanBeFloated && disp->IsFloatingStyle()) {
|
||||
*aPlaceholderType = PLACEHOLDER_FOR_FLOAT;
|
||||
@@ -1084,7 +1111,7 @@ void nsFrameConstructorState::ConstructBackdropFrameFor(nsIContent* aContent,
|
||||
|
||||
nsFrameState placeholderType;
|
||||
AbsoluteFrameList* frameList =
|
||||
GetOutOfFlowFrameList(backdropFrame, true, true, &placeholderType);
|
||||
GetOutOfFlowFrameList(backdropFrame, true, true, false, &placeholderType);
|
||||
MOZ_ASSERT(placeholderType & PLACEHOLDER_FOR_TOPLAYER);
|
||||
|
||||
nsIFrame* placeholder = nsCSSFrameConstructor::CreatePlaceholderFrameFor(
|
||||
@@ -1098,12 +1125,13 @@ void nsFrameConstructorState::ConstructBackdropFrameFor(nsIContent* aContent,
|
||||
void nsFrameConstructorState::AddChild(
|
||||
nsIFrame* aNewFrame, nsFrameList& aFrameList, nsIContent* aContent,
|
||||
nsContainerFrame* aParentFrame, bool aCanBePositioned, bool aCanBeFloated,
|
||||
bool aInsertAfter, nsIFrame* aInsertAfterFrame) {
|
||||
bool aIsOutOfFlowPopup, bool aInsertAfter, nsIFrame* aInsertAfterFrame) {
|
||||
MOZ_ASSERT(!aNewFrame->GetNextSibling(), "Shouldn't happen");
|
||||
|
||||
nsFrameState placeholderType;
|
||||
AbsoluteFrameList* outOfFlowFrameList = GetOutOfFlowFrameList(
|
||||
aNewFrame, aCanBePositioned, aCanBeFloated, &placeholderType);
|
||||
AbsoluteFrameList* outOfFlowFrameList =
|
||||
GetOutOfFlowFrameList(aNewFrame, aCanBePositioned, aCanBeFloated,
|
||||
aIsOutOfFlowPopup, &placeholderType);
|
||||
|
||||
// The comments in GetGeometricParent regarding root table frames
|
||||
// all apply here, unfortunately. Thus, we need to check whether
|
||||
@@ -1160,7 +1188,8 @@ MOZ_NEVER_INLINE void nsFrameConstructorState::ProcessFrameInsertions(
|
||||
aChildListID == nsIFrame::kAbsoluteList) || \
|
||||
((&aFrameList == &mFixedList || &aFrameList == &mTopLayerFixedList) && \
|
||||
aChildListID == nsIFrame::kFixedList)
|
||||
MOZ_ASSERT(NS_NONXUL_LIST_TEST,
|
||||
MOZ_ASSERT(NS_NONXUL_LIST_TEST || (&aFrameList == &mPopupList &&
|
||||
aChildListID == nsIFrame::kPopupList),
|
||||
"Unexpected aFrameList/aChildListID combination");
|
||||
|
||||
if (aFrameList.IsEmpty()) {
|
||||
@@ -2399,12 +2428,14 @@ nsIFrame* nsCSSFrameConstructor::ConstructDocElementFrame(
|
||||
} else if (display->mDisplay == StyleDisplay::Flex ||
|
||||
display->mDisplay == StyleDisplay::WebkitBox ||
|
||||
display->mDisplay == StyleDisplay::Grid ||
|
||||
display->mDisplay == StyleDisplay::MozBox) {
|
||||
display->mDisplay == StyleDisplay::MozBox ||
|
||||
display->mDisplay == StyleDisplay::MozPopup) {
|
||||
auto func = [&] {
|
||||
if (display->mDisplay == StyleDisplay::Grid) {
|
||||
return NS_NewGridContainerFrame;
|
||||
}
|
||||
if (display->mDisplay == StyleDisplay::MozBox &&
|
||||
if ((display->mDisplay == StyleDisplay::MozBox ||
|
||||
display->mDisplay == StyleDisplay::MozPopup) &&
|
||||
!computedStyle->StyleVisibility()->EmulateMozBoxWithFlex()) {
|
||||
return NS_NewBoxFrame;
|
||||
}
|
||||
@@ -2507,6 +2538,9 @@ nsIFrame* nsCSSFrameConstructor::ConstructDocElementFrame(
|
||||
mDocElementContainingBlock->AppendFrames(kPrincipalList,
|
||||
std::move(frameList));
|
||||
|
||||
MOZ_ASSERT(!state.mHavePendingPopupgroup,
|
||||
"Should have proccessed pending popup group by now");
|
||||
|
||||
return newFrame;
|
||||
}
|
||||
|
||||
@@ -3651,13 +3685,18 @@ void nsCSSFrameConstructor::ConstructFrameFromItemInternal(
|
||||
} else {
|
||||
newFrame = (*data->mFunc.mCreationFunc)(mPresShell, computedStyle);
|
||||
|
||||
const bool allowOutOfFlow = !(bits & FCDATA_DISALLOW_OUT_OF_FLOW);
|
||||
const bool isPopup = aItem.mIsPopup;
|
||||
bool allowOutOfFlow = !(bits & FCDATA_DISALLOW_OUT_OF_FLOW);
|
||||
bool isPopup = aItem.mIsPopup;
|
||||
NS_ASSERTION(
|
||||
!isPopup || (aState.mPopupList.mContainingBlock &&
|
||||
aState.mPopupList.mContainingBlock->IsPopupSetFrame()),
|
||||
"Should have a containing block here!");
|
||||
|
||||
nsContainerFrame* geometricParent =
|
||||
(isPopup || allowOutOfFlow)
|
||||
? aState.GetGeometricParent(*display, aParentFrame)
|
||||
: aParentFrame;
|
||||
isPopup ? aState.mPopupList.mContainingBlock
|
||||
: (allowOutOfFlow
|
||||
? aState.GetGeometricParent(*display, aParentFrame)
|
||||
: aParentFrame);
|
||||
|
||||
// In the non-scrollframe case, primaryFrame and newFrame are equal; in the
|
||||
// scrollframe case, newFrame is the scrolled frame while primaryFrame is
|
||||
@@ -3738,10 +3777,21 @@ void nsCSSFrameConstructor::ConstructFrameFromItemInternal(
|
||||
}
|
||||
|
||||
aState.AddChild(primaryFrame, aFrameList, content, aParentFrame,
|
||||
allowOutOfFlow, allowOutOfFlow);
|
||||
allowOutOfFlow, allowOutOfFlow, isPopup);
|
||||
|
||||
nsContainerFrame* newFrameAsContainer = do_QueryFrame(newFrame);
|
||||
if (newFrameAsContainer) {
|
||||
// Icky XUL stuff, sadly
|
||||
|
||||
if (aItem.mIsRootPopupgroup) {
|
||||
NS_ASSERTION(nsIPopupContainer::GetPopupContainer(mPresShell) &&
|
||||
nsIPopupContainer::GetPopupContainer(mPresShell)
|
||||
->GetPopupSetFrame() == newFrame,
|
||||
"Unexpected PopupSetFrame");
|
||||
aState.mPopupList.mContainingBlock = newFrameAsContainer;
|
||||
aState.mHavePendingPopupgroup = false;
|
||||
}
|
||||
|
||||
// Process the child content if requested
|
||||
nsFrameList childList;
|
||||
nsFrameConstructorSaveState absoluteSaveState;
|
||||
@@ -4020,8 +4070,6 @@ const nsCSSFrameConstructor::FrameConstructionData*
|
||||
nsCSSFrameConstructor::FindXULTagData(const Element& aElement,
|
||||
ComputedStyle& aStyle) {
|
||||
MOZ_ASSERT(aElement.IsXULElement());
|
||||
static constexpr FrameConstructionData kPopupData(
|
||||
NS_NewMenuPopupFrame, FCDATA_IS_POPUP | FCDATA_SKIP_ABSPOS_PUSH);
|
||||
|
||||
static constexpr FrameConstructionDataByTag sXULTagData[] = {
|
||||
SIMPLE_XUL_CREATE(image, NS_NewImageBoxFrame),
|
||||
@@ -4041,21 +4089,31 @@ nsCSSFrameConstructor::FindXULTagData(const Element& aElement,
|
||||
#else
|
||||
SIMPLE_XUL_CREATE(menubar, NS_NewMenuBarFrame),
|
||||
#endif /* XP_MACOSX */
|
||||
SIMPLE_TAG_CHAIN(popupgroup, nsCSSFrameConstructor::FindPopupGroupData),
|
||||
SIMPLE_XUL_CREATE(iframe, NS_NewSubDocumentFrame),
|
||||
SIMPLE_XUL_CREATE(editor, NS_NewSubDocumentFrame),
|
||||
SIMPLE_XUL_CREATE(browser, NS_NewSubDocumentFrame),
|
||||
SIMPLE_XUL_CREATE(splitter, NS_NewSplitterFrame),
|
||||
SIMPLE_XUL_CREATE(slider, NS_NewSliderFrame),
|
||||
SIMPLE_XUL_CREATE(scrollbar, NS_NewScrollbarFrame),
|
||||
SIMPLE_XUL_CREATE(scrollbarbutton, NS_NewScrollbarButtonFrame),
|
||||
{nsGkAtoms::panel, kPopupData},
|
||||
{nsGkAtoms::menupopup, kPopupData},
|
||||
{nsGkAtoms::tooltip, kPopupData},
|
||||
};
|
||||
SIMPLE_XUL_CREATE(scrollbarbutton, NS_NewScrollbarButtonFrame)};
|
||||
|
||||
return FindDataByTag(aElement, aStyle, sXULTagData, ArrayLength(sXULTagData));
|
||||
}
|
||||
|
||||
/* static */
|
||||
const nsCSSFrameConstructor::FrameConstructionData*
|
||||
nsCSSFrameConstructor::FindPopupGroupData(const Element& aElement,
|
||||
ComputedStyle&) {
|
||||
if (!aElement.IsRootOfNativeAnonymousSubtree()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static constexpr FrameConstructionData sPopupSetData =
|
||||
SIMPLE_XUL_FCDATA(NS_NewPopupSetFrame);
|
||||
return &sPopupSetData;
|
||||
}
|
||||
|
||||
/* static */
|
||||
const nsCSSFrameConstructor::FrameConstructionData*
|
||||
nsCSSFrameConstructor::FindXULButtonData(const Element& aElement,
|
||||
@@ -4461,6 +4519,12 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay& aDisplay,
|
||||
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby));
|
||||
return &data;
|
||||
}
|
||||
case StyleDisplayInside::MozPopup: {
|
||||
static constexpr FrameConstructionData data(
|
||||
NS_NewMenuPopupFrame, FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_IS_POPUP |
|
||||
FCDATA_SKIP_ABSPOS_PUSH);
|
||||
return &data;
|
||||
}
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("unknown 'display' value");
|
||||
return nullptr;
|
||||
@@ -5319,6 +5383,11 @@ void nsCSSFrameConstructor::AddFrameConstructionItemsInternal(
|
||||
(data->mBits & FCDATA_IS_POPUP) && (!aParentFrame || // Parent is inline
|
||||
!aParentFrame->IsMenuFrame());
|
||||
|
||||
if (isPopup && !aState.mPopupList.mContainingBlock &&
|
||||
!aState.mHavePendingPopupgroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t bits = data->mBits;
|
||||
|
||||
// Inside colgroups, suppress everything except columns.
|
||||
@@ -5352,6 +5421,11 @@ void nsCSSFrameConstructor::AddFrameConstructionItemsInternal(
|
||||
// This corresponds to the Release in ConstructFramesFromItem.
|
||||
item->mContent->AddRef();
|
||||
}
|
||||
item->mIsRootPopupgroup = aContent->IsRootOfNativeAnonymousSubtree() &&
|
||||
aContent->IsXULElement(nsGkAtoms::popupgroup);
|
||||
if (item->mIsRootPopupgroup) {
|
||||
aState.mHavePendingPopupgroup = true;
|
||||
}
|
||||
item->mIsPopup = isPopup;
|
||||
|
||||
if (canHavePageBreak && display.BreakAfter()) {
|
||||
@@ -5464,6 +5538,15 @@ void nsCSSFrameConstructor::ConstructFramesFromItem(
|
||||
nsContainerFrame* aParentFrame, nsFrameList& aFrameList) {
|
||||
FrameConstructionItem& item = aIter.item();
|
||||
ComputedStyle* computedStyle = item.mComputedStyle;
|
||||
|
||||
const auto* disp = computedStyle->StyleDisplay();
|
||||
MOZ_ASSERT(!disp->IsAbsolutelyPositionedStyle() ||
|
||||
disp->DisplayInside() != StyleDisplayInside::MozBox,
|
||||
"This may be a frame that was previously blockified "
|
||||
"but isn't any longer! It probably needs explicit "
|
||||
"'display:block' to preserve behavior");
|
||||
Unused << disp; // (unused in configs that define the assertion away)
|
||||
|
||||
if (item.mIsText) {
|
||||
// If this is collapsible whitespace next to a line boundary,
|
||||
// don't create a frame. item.IsWhitespace() also sets the
|
||||
@@ -5514,6 +5597,16 @@ void nsCSSFrameConstructor::ConstructFramesFromItem(
|
||||
}
|
||||
}
|
||||
|
||||
void nsCSSFrameConstructor::ReconstructDocElementHierarchy(
|
||||
InsertionKind aInsertionKind) {
|
||||
Element* rootElement = mDocument->GetRootElement();
|
||||
if (!rootElement) {
|
||||
/* nothing to do */
|
||||
return;
|
||||
}
|
||||
RecreateFramesForContent(rootElement, aInsertionKind);
|
||||
}
|
||||
|
||||
nsContainerFrame* nsCSSFrameConstructor::GetAbsoluteContainingBlock(
|
||||
nsIFrame* aFrame, ContainingBlockType aType) {
|
||||
// Starting with aFrame, look for a frame that is absolutely positioned or
|
||||
@@ -5833,6 +5926,10 @@ bool nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling,
|
||||
}
|
||||
|
||||
StyleDisplay display = aDisplay.value();
|
||||
if (LayoutFrameType::Menu == parentType) {
|
||||
return (StyleDisplay::MozPopup == display) ==
|
||||
(StyleDisplay::MozPopup == siblingDisplay);
|
||||
}
|
||||
// To have decent performance we want to return false in cases in which
|
||||
// reordering the two siblings has no effect on display. To ensure
|
||||
// correctness, we MUST return false in cases where the two siblings have
|
||||
@@ -8267,6 +8364,16 @@ bool nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aFrame->IsPopupSetFrame()) {
|
||||
nsIPopupContainer* popupContainer =
|
||||
nsIPopupContainer::GetPopupContainer(mPresShell);
|
||||
if (popupContainer && popupContainer->GetPopupSetFrame() == aFrame) {
|
||||
TRACE("PopupSet");
|
||||
ReconstructDocElementHierarchy(InsertionKind::Async);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Reconstruct if inflowFrame is parent's only child, and parent is, or has,
|
||||
// a non-fluid continuation, i.e. it was split by bidi resolution
|
||||
if (!inFlowFrame->GetPrevSibling() && !inFlowFrame->GetNextSibling() &&
|
||||
@@ -9574,7 +9681,9 @@ void nsCSSFrameConstructor::ProcessChildren(
|
||||
itemsToConstruct.SetLineBoundaryAtEnd(true);
|
||||
}
|
||||
|
||||
// Create any anonymous frames we need here.
|
||||
// Create any anonymous frames we need here. This must happen before the
|
||||
// non-anonymous children are processed to ensure that popups are never
|
||||
// constructed before the popupset.
|
||||
AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
|
||||
GetAnonymousContent(aContent, aPossiblyLeafFrame, anonymousItems);
|
||||
#ifdef DEBUG
|
||||
@@ -9937,7 +10046,7 @@ nsFirstLetterFrame* nsCSSFrameConstructor::CreateFloatingLetterFrame(
|
||||
}
|
||||
|
||||
aState.AddChild(letterFrame, aResult, letterContent, aParentFrame, false,
|
||||
true, true, prevSibling);
|
||||
true, false, true, prevSibling);
|
||||
|
||||
if (nextTextFrame) {
|
||||
aResult.AppendFrame(nullptr, nextTextFrame);
|
||||
|
||||
Reference in New Issue
Block a user