mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 422283. Make sure that an overflow container's next-in-flows are always also overflow containers. This means that when we convert a normal frame into an overflow container, we need to scan through its next-in-flows and make them overflow containers too. r=fantasai,sr=mats
This commit is contained in:
parent
b45eb57f56
commit
dd26ad1004
10
layout/generic/crashtests/422283-1.html
Normal file
10
layout/generic/crashtests/422283-1.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head></head>
|
||||
|
||||
<body style="-moz-column-width: 1px;"><div style="padding: 150px 0; height: 80px;"><span>
|
||||
</span>x<div></div><span>
|
||||
</span>a ! b c<div></div>
|
||||
</div></body>
|
||||
|
||||
</html>
|
24
layout/generic/crashtests/422301-1.html
Normal file
24
layout/generic/crashtests/422301-1.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
div { height: .5em; margin: 1em; }
|
||||
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function boom()
|
||||
{
|
||||
document.getElementById("b").style.padding = "";
|
||||
document.getElementById("a").style.padding = "12em";
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="boom();" style="-moz-column-width: 2em;"><div id="a"></div><div></div><div></div><div id="b" style="padding: 12em;">This is text</div>This is textThis is text<div>This is text</div></body>
|
||||
|
||||
</html>
|
@ -137,6 +137,8 @@ load 416264-1.html
|
||||
load 416476-1.html
|
||||
load 418532-1.html
|
||||
load 421404-1.html
|
||||
load 422283-1.html
|
||||
load 422301-1.html
|
||||
load 425253-1.html
|
||||
load 430352-1.html
|
||||
load 448903-1.html
|
||||
|
@ -1440,9 +1440,10 @@ nsOverflowContinuationTracker::Insert(nsIFrame* aOverflowCont,
|
||||
NS_PRECONDITION(aOverflowCont->GetPrevInFlow(),
|
||||
"overflow containers must have a prev-in-flow");
|
||||
nsresult rv = NS_OK;
|
||||
PRBool convertedToOverflowContainer = PR_FALSE;
|
||||
nsPresContext* presContext = aOverflowCont->PresContext();
|
||||
if (!mSentry || aOverflowCont != mSentry->GetNextInFlow()) {
|
||||
// Not in our list, so we need to add it
|
||||
nsPresContext* presContext = aOverflowCont->PresContext();
|
||||
if (aOverflowCont->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
|
||||
// aOverflowCont is in some other overflow container list,
|
||||
// steal it first
|
||||
@ -1455,6 +1456,7 @@ nsOverflowContinuationTracker::Insert(nsIFrame* aOverflowCont,
|
||||
}
|
||||
else {
|
||||
aOverflowCont->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
|
||||
convertedToOverflowContainer = PR_TRUE;
|
||||
}
|
||||
if (!mOverflowContList) {
|
||||
mOverflowContList = new nsFrameList();
|
||||
@ -1483,6 +1485,20 @@ nsOverflowContinuationTracker::Insert(nsIFrame* aOverflowCont,
|
||||
(mPrevOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW) !=
|
||||
(aOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW)),
|
||||
"OverflowContTracker in unexpected state");
|
||||
|
||||
if (convertedToOverflowContainer) {
|
||||
// Convert all non-overflow-container continuations of aOverflowCont
|
||||
// into overflow containers and move them to our overflow
|
||||
// tracker. This preserves the invariant that the next-continuations
|
||||
// of an overflow container are also overflow containers.
|
||||
nsIFrame* f = aOverflowCont->GetNextContinuation();
|
||||
if (f && !(f->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
|
||||
nsContainerFrame* parent = static_cast<nsContainerFrame*>(f->GetParent());
|
||||
rv = parent->StealFrame(presContext, f);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
Insert(f, aReflowStatus);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -1492,24 +1508,28 @@ nsOverflowContinuationTracker::Finish(nsIFrame* aChild)
|
||||
NS_PRECONDITION(aChild, "null ptr");
|
||||
NS_PRECONDITION(aChild->GetNextInFlow(),
|
||||
"supposed to call Finish *before* deleting next-in-flow!");
|
||||
if (aChild == mSentry) {
|
||||
// Make sure we drop all references if this was the only frame
|
||||
// in the overflow containers list
|
||||
if (mOverflowContList->FirstChild() == aChild->GetNextInFlow()
|
||||
&& !aChild->GetNextInFlow()->GetNextSibling()) {
|
||||
mOverflowContList = nsnull;
|
||||
mPrevOverflowCont = nsnull;
|
||||
mSentry = nsnull;
|
||||
mParent = static_cast<nsContainerFrame*>(aChild->GetParent());
|
||||
}
|
||||
else {
|
||||
// Step past aChild
|
||||
nsIFrame* prevOverflowCont = mPrevOverflowCont;
|
||||
StepForward();
|
||||
if (mPrevOverflowCont == aChild->GetNextInFlow()) {
|
||||
// Pull mPrevOverflowChild back to aChild's prevSibling:
|
||||
// aChild will be removed from our list by our caller
|
||||
mPrevOverflowCont = prevOverflowCont;
|
||||
|
||||
for (nsIFrame* f = aChild; f; f = f->GetNextInFlow()) {
|
||||
if (f == mSentry) {
|
||||
// Make sure we drop all references if this was the only frame
|
||||
// in the overflow containers list
|
||||
if (mOverflowContList->FirstChild() == f->GetNextInFlow()
|
||||
&& !f->GetNextInFlow()->GetNextSibling()) {
|
||||
mOverflowContList = nsnull;
|
||||
mPrevOverflowCont = nsnull;
|
||||
mSentry = nsnull;
|
||||
mParent = static_cast<nsContainerFrame*>(f->GetParent());
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// Step past aChild
|
||||
nsIFrame* prevOverflowCont = mPrevOverflowCont;
|
||||
StepForward();
|
||||
if (mPrevOverflowCont == f->GetNextInFlow()) {
|
||||
// Pull mPrevOverflowChild back to aChild's prevSibling:
|
||||
// aChild will be removed from our list by our caller
|
||||
mPrevOverflowCont = prevOverflowCont;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user