зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
b0dac2b742
Коммит
ae652b0b37
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче