In certain dynamic updates, frames scheduled to be reprocessed could be destroyed in a ripple effect. Since this was a root problem, the patch fixes the crasher bugs 123049, 133219 154797 187671 187890, r=bzbarsky, sr=dbaron

This commit is contained in:
rbs%maths.uq.edu.au 2003-01-20 01:07:03 +00:00
parent 7a9a568e7f
commit e54e375728
8 changed files with 120 additions and 4 deletions

View File

@ -129,6 +129,7 @@ LAYOUT_ATOM(textFrame, "TextFrame")
LAYOUT_ATOM(viewportFrame, "ViewportFrame")
// Alphabetical list of frame property names
LAYOUT_ATOM(changeListProperty, "ChangeListProperty")
LAYOUT_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") // nsPoint*
LAYOUT_ATOM(IBSplitSpecialPrevSibling, "IBSplitSpecialPrevSibling")// nsIFrame*
LAYOUT_ATOM(IBSplitSpecialSibling, "IBSplitSpecialSibling") // nsIFrame*

View File

@ -113,6 +113,7 @@
#include "nsChildIterator.h"
#include "nsCSSRendering.h"
#include "nsISelectElement.h"
#include "nsLayoutErrors.h"
static NS_DEFINE_CID(kTextNodeCID, NS_TEXTNODE_CID);
static NS_DEFINE_CID(kHTMLElementFactoryCID, NS_HTML_ELEMENT_FACTORY_CID);
@ -10311,11 +10312,42 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList,
nsIPresContext* aPresContext)
{
PRInt32 count = aChangeList.Count();
while (0 < count--) {
if (!count)
return NS_OK;
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
// Mark frames so that we skip frames that die along the way, bug 123049.
// A frame can be in the list multiple times with different hints. Further
// optmization is possible if nsStyleChangeList::AppendChange could coalesce
PRInt32 index = count;
while (0 <= --index) {
const nsStyleChangeData* changeData;
aChangeList.ChangeAt(index, &changeData);
if (changeData->mFrame) {
frameManager->SetFrameProperty(changeData->mFrame,
nsLayoutAtoms::changeListProperty, nsnull, nsnull);
}
}
index = count;
while (0 <= --index) {
nsIFrame* frame;
nsIContent* content;
nsChangeHint hint;
aChangeList.ChangeAt(count, frame, content, hint);
aChangeList.ChangeAt(index, frame, content, hint);
// skip any frame that has been destroyed due to a ripple effect
if (frame) {
void* dummy;
nsresult res = frameManager->GetFrameProperty(frame,
nsLayoutAtoms::changeListProperty, 0, &dummy);
if (NS_IFRAME_MGR_PROP_NOT_THERE == res)
continue;
}
if (hint & nsChangeHint_ReconstructDoc) {
NS_ERROR("This shouldn't happen");
@ -10323,6 +10355,7 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList,
if (hint & nsChangeHint_ReconstructFrame) {
RecreateFramesForContent(aPresContext, content);
} else {
NS_ASSERTION(frame, "This shouldn't happen");
if (hint & nsChangeHint_ReflowFrame) {
StyleChangeReflow(aPresContext, frame, nsnull);
}
@ -10347,6 +10380,18 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList,
}
#endif
}
// cleanup references
index = count;
while (0 <= --index) {
const nsStyleChangeData* changeData;
aChangeList.ChangeAt(index, &changeData);
if (changeData->mFrame) {
frameManager->RemoveFrameProperty(changeData->mFrame,
nsLayoutAtoms::changeListProperty);
}
}
aChangeList.Clear();
return NS_OK;
}

View File

@ -129,6 +129,7 @@ LAYOUT_ATOM(textFrame, "TextFrame")
LAYOUT_ATOM(viewportFrame, "ViewportFrame")
// Alphabetical list of frame property names
LAYOUT_ATOM(changeListProperty, "ChangeListProperty")
LAYOUT_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") // nsPoint*
LAYOUT_ATOM(IBSplitSpecialPrevSibling, "IBSplitSpecialPrevSibling")// nsIFrame*
LAYOUT_ATOM(IBSplitSpecialSibling, "IBSplitSpecialSibling") // nsIFrame*

View File

@ -72,6 +72,16 @@ nsStyleChangeList::ChangeAt(PRInt32 aIndex, nsIFrame*& aFrame, nsIContent*& aCon
return NS_ERROR_ILLEGAL_VALUE;
}
nsresult
nsStyleChangeList::ChangeAt(PRInt32 aIndex, const nsStyleChangeData** aChangeData) const
{
if ((0 <= aIndex) && (aIndex < mCount)) {
*aChangeData = &mArray[aIndex];
return NS_OK;
}
return NS_ERROR_ILLEGAL_VALUE;
}
nsresult
nsStyleChangeList::AppendChange(nsIFrame* aFrame, nsIContent* aContent, nsChangeHint aHint)
{

View File

@ -64,6 +64,8 @@ public:
nsresult ChangeAt(PRInt32 aIndex, nsIFrame*& aFrame, nsIContent*& aContent,
nsChangeHint& aHint) const;
nsresult ChangeAt(PRInt32 aIndex, const nsStyleChangeData** aChangeData) const;
nsresult AppendChange(nsIFrame* aFrame, nsIContent* aContent, nsChangeHint aHint);
void Clear(void);

View File

@ -64,6 +64,8 @@ public:
nsresult ChangeAt(PRInt32 aIndex, nsIFrame*& aFrame, nsIContent*& aContent,
nsChangeHint& aHint) const;
nsresult ChangeAt(PRInt32 aIndex, const nsStyleChangeData** aChangeData) const;
nsresult AppendChange(nsIFrame* aFrame, nsIContent* aContent, nsChangeHint aHint);
void Clear(void);

View File

@ -72,6 +72,16 @@ nsStyleChangeList::ChangeAt(PRInt32 aIndex, nsIFrame*& aFrame, nsIContent*& aCon
return NS_ERROR_ILLEGAL_VALUE;
}
nsresult
nsStyleChangeList::ChangeAt(PRInt32 aIndex, const nsStyleChangeData** aChangeData) const
{
if ((0 <= aIndex) && (aIndex < mCount)) {
*aChangeData = &mArray[aIndex];
return NS_OK;
}
return NS_ERROR_ILLEGAL_VALUE;
}
nsresult
nsStyleChangeList::AppendChange(nsIFrame* aFrame, nsIContent* aContent, nsChangeHint aHint)
{

View File

@ -113,6 +113,7 @@
#include "nsChildIterator.h"
#include "nsCSSRendering.h"
#include "nsISelectElement.h"
#include "nsLayoutErrors.h"
static NS_DEFINE_CID(kTextNodeCID, NS_TEXTNODE_CID);
static NS_DEFINE_CID(kHTMLElementFactoryCID, NS_HTML_ELEMENT_FACTORY_CID);
@ -10311,11 +10312,42 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList,
nsIPresContext* aPresContext)
{
PRInt32 count = aChangeList.Count();
while (0 < count--) {
if (!count)
return NS_OK;
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
// Mark frames so that we skip frames that die along the way, bug 123049.
// A frame can be in the list multiple times with different hints. Further
// optmization is possible if nsStyleChangeList::AppendChange could coalesce
PRInt32 index = count;
while (0 <= --index) {
const nsStyleChangeData* changeData;
aChangeList.ChangeAt(index, &changeData);
if (changeData->mFrame) {
frameManager->SetFrameProperty(changeData->mFrame,
nsLayoutAtoms::changeListProperty, nsnull, nsnull);
}
}
index = count;
while (0 <= --index) {
nsIFrame* frame;
nsIContent* content;
nsChangeHint hint;
aChangeList.ChangeAt(count, frame, content, hint);
aChangeList.ChangeAt(index, frame, content, hint);
// skip any frame that has been destroyed due to a ripple effect
if (frame) {
void* dummy;
nsresult res = frameManager->GetFrameProperty(frame,
nsLayoutAtoms::changeListProperty, 0, &dummy);
if (NS_IFRAME_MGR_PROP_NOT_THERE == res)
continue;
}
if (hint & nsChangeHint_ReconstructDoc) {
NS_ERROR("This shouldn't happen");
@ -10323,6 +10355,7 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList,
if (hint & nsChangeHint_ReconstructFrame) {
RecreateFramesForContent(aPresContext, content);
} else {
NS_ASSERTION(frame, "This shouldn't happen");
if (hint & nsChangeHint_ReflowFrame) {
StyleChangeReflow(aPresContext, frame, nsnull);
}
@ -10347,6 +10380,18 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList,
}
#endif
}
// cleanup references
index = count;
while (0 <= --index) {
const nsStyleChangeData* changeData;
aChangeList.ChangeAt(index, &changeData);
if (changeData->mFrame) {
frameManager->RemoveFrameProperty(changeData->mFrame,
nsLayoutAtoms::changeListProperty);
}
}
aChangeList.Clear();
return NS_OK;
}