mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 22:05:44 +00:00
fix a crash in table pseudo frame handling, where colgroups need a special handling as they hold only columns and and can not be parents of other frames , bug 239294 r/sr=dbaron
This commit is contained in:
parent
f297e8a3b0
commit
6e737cd1b0
@ -632,11 +632,40 @@ nsAbsoluteItems::AddChild(nsIFrame* aChild)
|
||||
|
||||
// Structures used to record the creation of pseudo table frames where
|
||||
// the content belongs to some ancestor.
|
||||
// PseudoFrames are necessary when the childframe cannot be the direct
|
||||
// ancestor of the content based parent frame. The amount of necessary pseudo
|
||||
// frames is limited as the worst case would be table frame nested directly
|
||||
// into another table frame. So the member structures of nsPseudoFrames can be
|
||||
// viewed as a ring buffer where you start with the necessary frame type and
|
||||
// add higher frames as long as necessary to fit into the initial parent frame.
|
||||
// mLowestType is some sort of stack pointer which shows the start of the
|
||||
// ringbuffer. The insertion of pseudo frames can happen between every
|
||||
// two frames so we need to push and pop the pseudo frame data when children
|
||||
// of a frame are created.
|
||||
// The colgroup frame is special as it can harbour only col children.
|
||||
// Once all children of given frame are known, the pseudo frames can be
|
||||
// processed that means attached to the corresponding parent frames.
|
||||
// The behaviour is in general described at
|
||||
// http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
|
||||
// however there are implementation details that extend the CSS 2.1
|
||||
// specification:
|
||||
// 1. every table frame is wrapped in an outer table frame, which is always a
|
||||
// pseudo frame.
|
||||
// 2. the outer table frame will be also created to hold a caption.
|
||||
// 3. each table cell will have a pseudo inner table cell frame.
|
||||
// 4. a colgroup frame is created between a column and a table
|
||||
// 5. a rowgroup frame is created between a row and a table
|
||||
// A table frame can only have rowgroups or column groups as children.
|
||||
// A outer table frame can only have one caption and one table frame
|
||||
// as children.
|
||||
// Every table even if all table frames are specified will require the
|
||||
// creation of two types of pseudo frames: the outer table frame and the inner
|
||||
// table cell frames.
|
||||
|
||||
struct nsPseudoFrameData {
|
||||
nsIFrame* mFrame;
|
||||
nsFrameItems mChildList;
|
||||
nsFrameItems mChildList2;
|
||||
nsIFrame* mFrame; // created pseudo frame
|
||||
nsFrameItems mChildList; // child frames pending to be added to the pseudo
|
||||
nsFrameItems mChildList2; // child frames pending to be added to the pseudo
|
||||
|
||||
nsPseudoFrameData();
|
||||
nsPseudoFrameData(nsPseudoFrameData& aOther);
|
||||
@ -1808,7 +1837,8 @@ ProcessPseudoCellFrame(nsIPresContext* aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// limit the processing up to the frame type indicated by aHighestType.
|
||||
// make a complete processing when aHighestType is null
|
||||
static nsresult
|
||||
ProcessPseudoFrames(nsIPresContext* aPresContext,
|
||||
nsPseudoFrames& aPseudoFrames,
|
||||
@ -1821,6 +1851,16 @@ ProcessPseudoFrames(nsIPresContext* aPresContext,
|
||||
aHighestFrame = nsnull;
|
||||
|
||||
if (nsLayoutAtoms::tableFrame == aPseudoFrames.mLowestType) {
|
||||
// if the processing should be limited to the colgroup frame and the
|
||||
// table frame is the lowest type of created pseudo frames that
|
||||
// can have pseudo frame children, process only the colgroup pseudo frames
|
||||
// and leave the table frame untouched.
|
||||
if (nsLayoutAtoms::tableColGroupFrame == aHighestType) {
|
||||
if (aPseudoFrames.mColGroup.mFrame) {
|
||||
rv = ProcessPseudoFrame(aPresContext, aPseudoFrames.mColGroup, aHighestFrame);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
rv = ProcessPseudoTableFrame(aPresContext, aPseudoFrames, aHighestFrame);
|
||||
if (nsLayoutAtoms::tableOuterFrame == aHighestType) return rv;
|
||||
|
||||
@ -2046,6 +2086,10 @@ nsCSSFrameConstructor::CreatePseudoColGroupFrame(nsIPresShell* aPresS
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
((nsTableColGroupFrame*)pseudo.mFrame)->SetColType(eColGroupAnonymousCol);
|
||||
|
||||
// Do not set aState.mPseudoFrames.mLowestType here as colgroup frame will
|
||||
// be always below a table frame but we can not descent any further as col
|
||||
// frames can not have children and will not wrap table foreign frames.
|
||||
|
||||
// set pseudo data for the parent
|
||||
if (aState.mPseudoFrames.mTableInner.mFrame) {
|
||||
aState.mPseudoFrames.mTableInner.mChildList.AddChild(pseudo.mFrame);
|
||||
@ -2962,11 +3006,8 @@ nsCSSFrameConstructor::ConstructTableForeignFrame(nsIPresShell* aPres
|
||||
nsIFrame* parentFrame = nsnull;
|
||||
aIsPseudoParent = PR_FALSE;
|
||||
|
||||
// XXX form code needs to be fixed so that the forms can work
|
||||
// without a frame.
|
||||
nsIAtom *tag = aContent->Tag();
|
||||
|
||||
// Do not construct pseudo frames for trees
|
||||
|
||||
if (MustGeneratePseudoParent(aPresContext, aParentFrameIn, tag, aContent,
|
||||
aStyleContext)) {
|
||||
// this frame may have a pseudo parent, use block frame type to
|
||||
@ -2976,21 +3017,24 @@ nsCSSFrameConstructor::ConstructTableForeignFrame(nsIPresShell* aPres
|
||||
if (!aIsPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
|
||||
ProcessPseudoFrames(aPresContext, aState.mPseudoFrames, aChildItems);
|
||||
}
|
||||
//char buf[256];
|
||||
//sprintf(buf, "anonymous frame constructed for %s", tag.get());
|
||||
//NS_WARN_IF_FALSE(PR_FALSE, buf);
|
||||
}
|
||||
|
||||
if (!parentFrame) return rv; // if pseudo frame wasn't created
|
||||
|
||||
NS_ASSERTION(parentFrame == aState.mPseudoFrames.mCellInner.mFrame,
|
||||
|
||||
// there are two situations where table related frames will wrap around
|
||||
// foreign frames
|
||||
// a) inner table cell, which is a pseudo frame
|
||||
// b) caption frame which will be always a real frame.
|
||||
NS_ASSERTION(nsLayoutAtoms::tableCaptionFrame == parentFrame->GetType() ||
|
||||
parentFrame == aState.mPseudoFrames.mCellInner.mFrame,
|
||||
"Weird parent in ConstructTableForeignFrame");
|
||||
|
||||
// Push the parent as the floater containing block
|
||||
nsFrameConstructorSaveState saveState;
|
||||
aState.PushFloatContainingBlock(parentFrame, saveState, PR_FALSE, PR_FALSE);
|
||||
|
||||
// save the pseudo frame state XXX - why
|
||||
// save the pseudo frame state now, as descendants of the child frame may require
|
||||
// other pseudo frame creations
|
||||
nsPseudoFrames prevPseudoFrames;
|
||||
aState.mPseudoFrames.Reset(&prevPseudoFrames);
|
||||
|
||||
@ -2998,7 +3042,7 @@ nsCSSFrameConstructor::ConstructTableForeignFrame(nsIPresShell* aPres
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, aContent, parentFrame, items);
|
||||
aNewFrame = items.childList;
|
||||
|
||||
// restore the pseudo frame state XXX - why
|
||||
// restore the pseudo frame state
|
||||
aState.mPseudoFrames = prevPseudoFrames;
|
||||
|
||||
if (aIsPseudoParent) {
|
||||
|
@ -632,11 +632,40 @@ nsAbsoluteItems::AddChild(nsIFrame* aChild)
|
||||
|
||||
// Structures used to record the creation of pseudo table frames where
|
||||
// the content belongs to some ancestor.
|
||||
// PseudoFrames are necessary when the childframe cannot be the direct
|
||||
// ancestor of the content based parent frame. The amount of necessary pseudo
|
||||
// frames is limited as the worst case would be table frame nested directly
|
||||
// into another table frame. So the member structures of nsPseudoFrames can be
|
||||
// viewed as a ring buffer where you start with the necessary frame type and
|
||||
// add higher frames as long as necessary to fit into the initial parent frame.
|
||||
// mLowestType is some sort of stack pointer which shows the start of the
|
||||
// ringbuffer. The insertion of pseudo frames can happen between every
|
||||
// two frames so we need to push and pop the pseudo frame data when children
|
||||
// of a frame are created.
|
||||
// The colgroup frame is special as it can harbour only col children.
|
||||
// Once all children of given frame are known, the pseudo frames can be
|
||||
// processed that means attached to the corresponding parent frames.
|
||||
// The behaviour is in general described at
|
||||
// http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
|
||||
// however there are implementation details that extend the CSS 2.1
|
||||
// specification:
|
||||
// 1. every table frame is wrapped in an outer table frame, which is always a
|
||||
// pseudo frame.
|
||||
// 2. the outer table frame will be also created to hold a caption.
|
||||
// 3. each table cell will have a pseudo inner table cell frame.
|
||||
// 4. a colgroup frame is created between a column and a table
|
||||
// 5. a rowgroup frame is created between a row and a table
|
||||
// A table frame can only have rowgroups or column groups as children.
|
||||
// A outer table frame can only have one caption and one table frame
|
||||
// as children.
|
||||
// Every table even if all table frames are specified will require the
|
||||
// creation of two types of pseudo frames: the outer table frame and the inner
|
||||
// table cell frames.
|
||||
|
||||
struct nsPseudoFrameData {
|
||||
nsIFrame* mFrame;
|
||||
nsFrameItems mChildList;
|
||||
nsFrameItems mChildList2;
|
||||
nsIFrame* mFrame; // created pseudo frame
|
||||
nsFrameItems mChildList; // child frames pending to be added to the pseudo
|
||||
nsFrameItems mChildList2; // child frames pending to be added to the pseudo
|
||||
|
||||
nsPseudoFrameData();
|
||||
nsPseudoFrameData(nsPseudoFrameData& aOther);
|
||||
@ -1808,7 +1837,8 @@ ProcessPseudoCellFrame(nsIPresContext* aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// limit the processing up to the frame type indicated by aHighestType.
|
||||
// make a complete processing when aHighestType is null
|
||||
static nsresult
|
||||
ProcessPseudoFrames(nsIPresContext* aPresContext,
|
||||
nsPseudoFrames& aPseudoFrames,
|
||||
@ -1821,6 +1851,16 @@ ProcessPseudoFrames(nsIPresContext* aPresContext,
|
||||
aHighestFrame = nsnull;
|
||||
|
||||
if (nsLayoutAtoms::tableFrame == aPseudoFrames.mLowestType) {
|
||||
// if the processing should be limited to the colgroup frame and the
|
||||
// table frame is the lowest type of created pseudo frames that
|
||||
// can have pseudo frame children, process only the colgroup pseudo frames
|
||||
// and leave the table frame untouched.
|
||||
if (nsLayoutAtoms::tableColGroupFrame == aHighestType) {
|
||||
if (aPseudoFrames.mColGroup.mFrame) {
|
||||
rv = ProcessPseudoFrame(aPresContext, aPseudoFrames.mColGroup, aHighestFrame);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
rv = ProcessPseudoTableFrame(aPresContext, aPseudoFrames, aHighestFrame);
|
||||
if (nsLayoutAtoms::tableOuterFrame == aHighestType) return rv;
|
||||
|
||||
@ -2046,6 +2086,10 @@ nsCSSFrameConstructor::CreatePseudoColGroupFrame(nsIPresShell* aPresS
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
((nsTableColGroupFrame*)pseudo.mFrame)->SetColType(eColGroupAnonymousCol);
|
||||
|
||||
// Do not set aState.mPseudoFrames.mLowestType here as colgroup frame will
|
||||
// be always below a table frame but we can not descent any further as col
|
||||
// frames can not have children and will not wrap table foreign frames.
|
||||
|
||||
// set pseudo data for the parent
|
||||
if (aState.mPseudoFrames.mTableInner.mFrame) {
|
||||
aState.mPseudoFrames.mTableInner.mChildList.AddChild(pseudo.mFrame);
|
||||
@ -2962,11 +3006,8 @@ nsCSSFrameConstructor::ConstructTableForeignFrame(nsIPresShell* aPres
|
||||
nsIFrame* parentFrame = nsnull;
|
||||
aIsPseudoParent = PR_FALSE;
|
||||
|
||||
// XXX form code needs to be fixed so that the forms can work
|
||||
// without a frame.
|
||||
nsIAtom *tag = aContent->Tag();
|
||||
|
||||
// Do not construct pseudo frames for trees
|
||||
|
||||
if (MustGeneratePseudoParent(aPresContext, aParentFrameIn, tag, aContent,
|
||||
aStyleContext)) {
|
||||
// this frame may have a pseudo parent, use block frame type to
|
||||
@ -2976,21 +3017,24 @@ nsCSSFrameConstructor::ConstructTableForeignFrame(nsIPresShell* aPres
|
||||
if (!aIsPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
|
||||
ProcessPseudoFrames(aPresContext, aState.mPseudoFrames, aChildItems);
|
||||
}
|
||||
//char buf[256];
|
||||
//sprintf(buf, "anonymous frame constructed for %s", tag.get());
|
||||
//NS_WARN_IF_FALSE(PR_FALSE, buf);
|
||||
}
|
||||
|
||||
if (!parentFrame) return rv; // if pseudo frame wasn't created
|
||||
|
||||
NS_ASSERTION(parentFrame == aState.mPseudoFrames.mCellInner.mFrame,
|
||||
|
||||
// there are two situations where table related frames will wrap around
|
||||
// foreign frames
|
||||
// a) inner table cell, which is a pseudo frame
|
||||
// b) caption frame which will be always a real frame.
|
||||
NS_ASSERTION(nsLayoutAtoms::tableCaptionFrame == parentFrame->GetType() ||
|
||||
parentFrame == aState.mPseudoFrames.mCellInner.mFrame,
|
||||
"Weird parent in ConstructTableForeignFrame");
|
||||
|
||||
// Push the parent as the floater containing block
|
||||
nsFrameConstructorSaveState saveState;
|
||||
aState.PushFloatContainingBlock(parentFrame, saveState, PR_FALSE, PR_FALSE);
|
||||
|
||||
// save the pseudo frame state XXX - why
|
||||
// save the pseudo frame state now, as descendants of the child frame may require
|
||||
// other pseudo frame creations
|
||||
nsPseudoFrames prevPseudoFrames;
|
||||
aState.mPseudoFrames.Reset(&prevPseudoFrames);
|
||||
|
||||
@ -2998,7 +3042,7 @@ nsCSSFrameConstructor::ConstructTableForeignFrame(nsIPresShell* aPres
|
||||
rv = ConstructFrame(aPresShell, aPresContext, aState, aContent, parentFrame, items);
|
||||
aNewFrame = items.childList;
|
||||
|
||||
// restore the pseudo frame state XXX - why
|
||||
// restore the pseudo frame state
|
||||
aState.mPseudoFrames = prevPseudoFrames;
|
||||
|
||||
if (aIsPseudoParent) {
|
||||
|
Loading…
Reference in New Issue
Block a user