Bug 1404324: Always remove out of flows from the placeholder frame, using its info. r=bz

MozReview-Commit-ID: 3Dt0wF2XRAH
This commit is contained in:
Emilio Cobos Álvarez 2017-10-02 21:08:50 +02:00
Родитель b0dac2b742
Коммит ae652b0b37
8 изменённых файлов: 83 добавлений и 58 удалений

Просмотреть файл

@ -1260,8 +1260,10 @@ nsFrameConstructorState::GetOutOfFlowFrameItems(nsIFrame* aNewFrame,
if (disp->mTopLayer != NS_STYLE_TOP_LAYER_NONE) {
*aPlaceholderType = PLACEHOLDER_FOR_TOPLAYER;
if (disp->mPosition == NS_STYLE_POSITION_FIXED) {
*aPlaceholderType |= PLACEHOLDER_FOR_FIXEDPOS;
return &mTopLayerFixedItems;
}
*aPlaceholderType |= PLACEHOLDER_FOR_ABSPOS;
return &mTopLayerAbsoluteItems;
}
if (disp->mPosition == NS_STYLE_POSITION_ABSOLUTE) {
@ -1303,11 +1305,11 @@ nsFrameConstructorState::ConstructBackdropFrameFor(nsIContent* aContent,
nsAbsoluteItems* frameItems = GetOutOfFlowFrameItems(backdropFrame,
true, true, false,
&placeholderType);
MOZ_ASSERT(placeholderType == PLACEHOLDER_FOR_TOPLAYER);
MOZ_ASSERT(placeholderType & PLACEHOLDER_FOR_TOPLAYER);
nsIFrame* placeholder = nsCSSFrameConstructor::
CreatePlaceholderFrameFor(mPresShell, aContent, backdropFrame,
frame, nullptr, PLACEHOLDER_FOR_TOPLAYER);
frame, nullptr, placeholderType);
nsFrameList temp(placeholder, placeholder);
frame->SetInitialChildList(nsIFrame::kBackdropList, temp);
@ -1361,7 +1363,7 @@ nsFrameConstructorState::AddChild(nsIFrame* aNewFrame,
// Add the placeholder frame to the flow
aFrameItems.AddChild(placeholderFrame);
if (placeholderType == PLACEHOLDER_FOR_TOPLAYER) {
if (placeholderType & PLACEHOLDER_FOR_TOPLAYER) {
ConstructBackdropFrameFor(aContent, aNewFrame);
}
}

Просмотреть файл

@ -1528,6 +1528,8 @@ nsLayoutUtils::GetChildListNameFor(nsIFrame* aChildFrame)
{
nsIFrame::ChildListID id = nsIFrame::kPrincipalList;
MOZ_DIAGNOSTIC_ASSERT(!(aChildFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW));
if (aChildFrame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
nsIFrame* pif = aChildFrame->GetPrevInFlow();
if (pif->GetParent() == aChildFrame->GetParent()) {
@ -1536,35 +1538,6 @@ nsLayoutUtils::GetChildListNameFor(nsIFrame* aChildFrame)
else {
id = nsIFrame::kOverflowContainersList;
}
}
// See if the frame is moved out of the flow
else if (aChildFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
// Look at the style information to tell
const nsStyleDisplay* disp = aChildFrame->StyleDisplay();
if (NS_STYLE_POSITION_ABSOLUTE == disp->mPosition) {
id = nsIFrame::kAbsoluteList;
} else if (NS_STYLE_POSITION_FIXED == disp->mPosition) {
if (nsLayoutUtils::IsReallyFixedPos(aChildFrame)) {
id = nsIFrame::kFixedList;
} else {
id = nsIFrame::kAbsoluteList;
}
#ifdef MOZ_XUL
} else if (StyleDisplay::MozPopup == disp->mDisplay) {
// Out-of-flows that are DISPLAY_POPUP must be kids of the root popup set
#ifdef DEBUG
nsIFrame* parent = aChildFrame->GetParent();
NS_ASSERTION(parent && parent->IsPopupSetFrame(), "Unexpected parent");
#endif // DEBUG
id = nsIFrame::kPopupList;
#endif // MOZ_XUL
} else {
NS_ASSERTION(aChildFrame->IsFloating(), "not a floated frame");
id = nsIFrame::kFloatList;
}
} else {
LayoutFrameType childType = aChildFrame->Type();
if (LayoutFrameType::MenuPopup == childType) {
@ -1599,19 +1572,8 @@ nsLayoutUtils::GetChildListNameFor(nsIFrame* aChildFrame)
nsContainerFrame* parent = aChildFrame->GetParent();
bool found = parent->GetChildList(id).ContainsFrame(aChildFrame);
if (!found) {
if (!(aChildFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
found = parent->GetChildList(nsIFrame::kOverflowList)
.ContainsFrame(aChildFrame);
}
else if (aChildFrame->IsFloating()) {
found = parent->GetChildList(nsIFrame::kOverflowOutOfFlowList)
.ContainsFrame(aChildFrame);
if (!found) {
found = parent->GetChildList(nsIFrame::kPushedFloatsList)
.ContainsFrame(aChildFrame);
}
}
// else it's positioned and should have been on the 'id' child list.
found = parent->GetChildList(nsIFrame::kOverflowList)
.ContainsFrame(aChildFrame);
NS_POSTCONDITION(found, "not in child list");
}
#endif

Просмотреть файл

@ -25,9 +25,9 @@ using namespace mozilla::gfx;
nsIFrame*
NS_NewPlaceholderFrame(nsIPresShell* aPresShell, nsStyleContext* aContext,
nsFrameState aTypeBit)
nsFrameState aTypeBits)
{
return new (aPresShell) nsPlaceholderFrame(aContext, aTypeBit);
return new (aPresShell) nsPlaceholderFrame(aContext, aTypeBits);
}
NS_IMPL_FRAMEARENA_HELPERS(nsPlaceholderFrame)
@ -155,6 +155,26 @@ nsPlaceholderFrame::Reflow(nsPresContext* aPresContext,
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
}
static nsIFrame::ChildListID
ChildListIDForOutOfFlow(nsFrameState aPlaceholderState, nsIFrame* aChild)
{
if (aPlaceholderState & PLACEHOLDER_FOR_FLOAT) {
return nsIFrame::kFloatList;
}
if (aPlaceholderState & PLACEHOLDER_FOR_POPUP) {
return nsIFrame::kPopupList;
}
if (aPlaceholderState & PLACEHOLDER_FOR_FIXEDPOS) {
return nsLayoutUtils::IsReallyFixedPos(aChild)
? nsIFrame::kFixedList : nsIFrame::kAbsoluteList;
}
if (aPlaceholderState & PLACEHOLDER_FOR_ABSPOS) {
return nsIFrame::kAbsoluteList;
}
MOZ_DIAGNOSTIC_ASSERT(false, "unknown list");
return nsIFrame::kFloatList;
}
void
nsPlaceholderFrame::DestroyFrom(nsIFrame* aDestructRoot)
{
@ -162,12 +182,13 @@ nsPlaceholderFrame::DestroyFrom(nsIFrame* aDestructRoot)
if (oof) {
mOutOfFlowFrame = nullptr;
oof->DeleteProperty(nsIFrame::PlaceholderFrameProperty());
// If aDestructRoot is not an ancestor of the out-of-flow frame,
// then call RemoveFrame on it here.
// Also destroy it here if it's a popup frame. (Bug 96291)
if ((GetStateBits() & PLACEHOLDER_FOR_POPUP) ||
!nsLayoutUtils::IsProperAncestorFrame(aDestructRoot, oof)) {
ChildListID listId = nsLayoutUtils::GetChildListNameFor(oof);
ChildListID listId = ChildListIDForOutOfFlow(GetStateBits(), oof);
nsFrameManager* fm = PresContext()->GetPresShell()->FrameManager();
fm->RemoveFrame(listId, oof);
}

Просмотреть файл

@ -40,7 +40,7 @@
nsIFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext,
nsFrameState aTypeBit);
nsFrameState aTypeBits);
#define PLACEHOLDER_TYPE_MASK (PLACEHOLDER_FOR_FLOAT | \
PLACEHOLDER_FOR_ABSPOS | \
@ -65,18 +65,19 @@ public:
*/
friend nsIFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext,
nsFrameState aTypeBit);
nsPlaceholderFrame(nsStyleContext* aContext, nsFrameState aTypeBit)
nsFrameState aTypeBits);
nsPlaceholderFrame(nsStyleContext* aContext, nsFrameState aTypeBits)
: nsFrame(aContext, kClassID)
, mOutOfFlowFrame(nullptr)
{
NS_PRECONDITION(aTypeBit == PLACEHOLDER_FOR_FLOAT ||
aTypeBit == PLACEHOLDER_FOR_ABSPOS ||
aTypeBit == PLACEHOLDER_FOR_FIXEDPOS ||
aTypeBit == PLACEHOLDER_FOR_POPUP ||
aTypeBit == PLACEHOLDER_FOR_TOPLAYER,
"Unexpected type bit");
AddStateBits(aTypeBit);
MOZ_ASSERT(aTypeBits == PLACEHOLDER_FOR_FLOAT ||
aTypeBits == PLACEHOLDER_FOR_ABSPOS ||
aTypeBits == PLACEHOLDER_FOR_FIXEDPOS ||
aTypeBits == PLACEHOLDER_FOR_POPUP ||
aTypeBits == (PLACEHOLDER_FOR_TOPLAYER | PLACEHOLDER_FOR_ABSPOS) ||
aTypeBits == (PLACEHOLDER_FOR_TOPLAYER | PLACEHOLDER_FOR_FIXEDPOS),
"Unexpected type bit");
AddStateBits(aTypeBits);
}
// Get/Set the associated out of flow frame

Просмотреть файл

@ -0,0 +1,12 @@
<style></style>
<script>
document.documentElement.className = 'c1'
o1 = document.createElement('form')
o2 = document.createElement('e')
o1.className = 'c2'
document.documentElement.appendChild(o1)
document.documentElement.appendChild(o2)
document.styleSheets[0].insertRule('.c1:first-line, .c2 { position:fixed', 0);
document.documentElement.getBoundingClientRect()
document.styleSheets[0].cssRules[0].style.position = 'relative'
</script>

Просмотреть файл

@ -0,0 +1,10 @@
<style>
del, *::first-line {
position: absolute;
}
</style>
<del></del>
<script>
document.documentElement.offsetTop;
document.styleSheets[0].cssRules[0].style.position = 'sticky'
</script>

Просмотреть файл

@ -0,0 +1,14 @@
<style>
del {
position: absolute;
}
body::first-line {
color: red;
}
</style>
<del></del>
<script>
document.documentElement.offsetTop;
document.styleSheets[0].cssRules[0].style.position = 'sticky'
</script>

Просмотреть файл

@ -241,3 +241,6 @@ load 1403615.html
load 1403712.html
load 1404180-1.html
load 1404316.html
load 1404324-1.html
load 1404324-2.html
load 1404324-3.html