Make sure not to add entries to the pending restyle hashtable while enumerating

it.   Bug 257694 (also fixes bug 256242, bug 258101).  r+sr=dbaron


git-svn-id: svn://10.0.0.236/trunk@162193 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
bzbarsky%mit.edu 2004-09-13 04:08:14 +00:00
parent 161ac90313
commit b5b1e1b77a
4 changed files with 138 additions and 62 deletions

View File

@ -13415,39 +13415,22 @@ nsresult nsCSSFrameConstructor::RemoveFixedItems(nsPresContext* aPresContext,
}
PR_STATIC_CALLBACK(PLDHashOperator)
ProcessRestyle(nsISupports* aContent,
nsCSSFrameConstructor::RestyleData& aData,
void* aPresContext)
CollectRestyles(nsISupports* aContent,
nsCSSFrameConstructor::RestyleData& aData,
void* aRestyleArrayPtr)
{
nsPresContext* context = NS_STATIC_CAST(nsPresContext*, aPresContext);
nsIContent* content = NS_STATIC_CAST(nsIContent*, aContent);
nsCSSFrameConstructor::RestyleEnumerateData** restyleArrayPtr =
NS_STATIC_CAST(nsCSSFrameConstructor::RestyleEnumerateData**,
aRestyleArrayPtr);
nsCSSFrameConstructor::RestyleEnumerateData* currentRestyle =
*restyleArrayPtr;
currentRestyle->mContent = NS_STATIC_CAST(nsIContent*, aContent);
currentRestyle->mRestyleHint = aData.mRestyleHint;
currentRestyle->mChangeHint = aData.mChangeHint;
if (!content->GetDocument() ||
content->GetDocument() != context->GetDocument()) {
// Content node has been removed from our document; nothing else to do here
return PL_DHASH_NEXT;
}
nsIPresShell* shell = context->PresShell();
// Increment to the next slot in the array
*restyleArrayPtr = currentRestyle + 1;
nsIFrame* primaryFrame = nsnull;
shell->GetPrimaryFrameFor(content, &primaryFrame);
if (aData.mRestyleHint & eReStyle_Self) {
shell->FrameConstructor()->RestyleElement(context, content, primaryFrame,
aData.mChangeHint);
} else if (aData.mChangeHint &&
(primaryFrame ||
(aData.mChangeHint & nsChangeHint_ReconstructFrame))) {
// Don't need to recompute style; just apply the hint
nsStyleChangeList changeList;
changeList.AppendChange(primaryFrame, content, aData.mChangeHint);
shell->FrameConstructor()->ProcessRestyledFrames(changeList, context);
}
if (aData.mRestyleHint & eReStyle_LaterSiblings) {
shell->FrameConstructor()->RestyleLaterSiblings(context, content);
}
return PL_DHASH_NEXT;
}
@ -13458,8 +13441,59 @@ nsCSSFrameConstructor::ProcessPendingRestyles()
nsIPresShell* shell = mDocument->GetShellAt(0);
nsPresContext* context = shell->GetPresContext();
mPendingRestyles.Enumerate(ProcessRestyle, context);
nsCSSFrameConstructor::RestyleEnumerateData* restylesToProcess =
new nsCSSFrameConstructor::RestyleEnumerateData[mPendingRestyles.Count()];
if (!restylesToProcess) {
return;
}
nsCSSFrameConstructor::RestyleEnumerateData* lastRestyle = restylesToProcess;
mPendingRestyles.Enumerate(CollectRestyles, &lastRestyle);
NS_ASSERTION(lastRestyle - restylesToProcess ==
PRInt32(mPendingRestyles.Count()),
"Enumeration screwed up somehow");
// Clear the hashtable so we don't end up trying to process a restyle we're
// already processing, sending us into an infinite loop.
mPendingRestyles.Clear();
for (nsCSSFrameConstructor::RestyleEnumerateData* currentRestyle =
restylesToProcess;
currentRestyle != lastRestyle;
++currentRestyle) {
nsIContent* content = currentRestyle->mContent;
if (!content->GetDocument() ||
content->GetDocument() != context->GetDocument()) {
// Content node has been removed from our document; nothing else
// to do here
continue;
}
nsChangeHint changeHint = currentRestyle->mChangeHint;
nsReStyleHint restyleHint = currentRestyle->mRestyleHint;
nsIFrame* primaryFrame = nsnull;
shell->GetPrimaryFrameFor(content, &primaryFrame);
if (restyleHint & eReStyle_Self) {
shell->FrameConstructor()->RestyleElement(context, content, primaryFrame,
currentRestyle->mChangeHint);
} else if (changeHint &&
(primaryFrame ||
(changeHint & nsChangeHint_ReconstructFrame))) {
// Don't need to recompute style; just apply the hint
nsStyleChangeList changeList;
changeList.AppendChange(primaryFrame, content, changeHint);
shell->FrameConstructor()->ProcessRestyledFrames(changeList, context);
}
if (restyleHint & eReStyle_LaterSiblings) {
shell->FrameConstructor()->RestyleLaterSiblings(context, content);
}
}
delete [] restylesToProcess;
}
void

View File

@ -1062,6 +1062,10 @@ public:
nsChangeHint mChangeHint; // The minimal change hint for "self"
};
struct RestyleEnumerateData : public RestyleData {
nsCOMPtr<nsIContent> mContent;
};
struct RestyleEvent;
friend struct RestyleEvent;

View File

@ -13415,39 +13415,22 @@ nsresult nsCSSFrameConstructor::RemoveFixedItems(nsPresContext* aPresContext,
}
PR_STATIC_CALLBACK(PLDHashOperator)
ProcessRestyle(nsISupports* aContent,
nsCSSFrameConstructor::RestyleData& aData,
void* aPresContext)
CollectRestyles(nsISupports* aContent,
nsCSSFrameConstructor::RestyleData& aData,
void* aRestyleArrayPtr)
{
nsPresContext* context = NS_STATIC_CAST(nsPresContext*, aPresContext);
nsIContent* content = NS_STATIC_CAST(nsIContent*, aContent);
nsCSSFrameConstructor::RestyleEnumerateData** restyleArrayPtr =
NS_STATIC_CAST(nsCSSFrameConstructor::RestyleEnumerateData**,
aRestyleArrayPtr);
nsCSSFrameConstructor::RestyleEnumerateData* currentRestyle =
*restyleArrayPtr;
currentRestyle->mContent = NS_STATIC_CAST(nsIContent*, aContent);
currentRestyle->mRestyleHint = aData.mRestyleHint;
currentRestyle->mChangeHint = aData.mChangeHint;
if (!content->GetDocument() ||
content->GetDocument() != context->GetDocument()) {
// Content node has been removed from our document; nothing else to do here
return PL_DHASH_NEXT;
}
nsIPresShell* shell = context->PresShell();
// Increment to the next slot in the array
*restyleArrayPtr = currentRestyle + 1;
nsIFrame* primaryFrame = nsnull;
shell->GetPrimaryFrameFor(content, &primaryFrame);
if (aData.mRestyleHint & eReStyle_Self) {
shell->FrameConstructor()->RestyleElement(context, content, primaryFrame,
aData.mChangeHint);
} else if (aData.mChangeHint &&
(primaryFrame ||
(aData.mChangeHint & nsChangeHint_ReconstructFrame))) {
// Don't need to recompute style; just apply the hint
nsStyleChangeList changeList;
changeList.AppendChange(primaryFrame, content, aData.mChangeHint);
shell->FrameConstructor()->ProcessRestyledFrames(changeList, context);
}
if (aData.mRestyleHint & eReStyle_LaterSiblings) {
shell->FrameConstructor()->RestyleLaterSiblings(context, content);
}
return PL_DHASH_NEXT;
}
@ -13458,8 +13441,59 @@ nsCSSFrameConstructor::ProcessPendingRestyles()
nsIPresShell* shell = mDocument->GetShellAt(0);
nsPresContext* context = shell->GetPresContext();
mPendingRestyles.Enumerate(ProcessRestyle, context);
nsCSSFrameConstructor::RestyleEnumerateData* restylesToProcess =
new nsCSSFrameConstructor::RestyleEnumerateData[mPendingRestyles.Count()];
if (!restylesToProcess) {
return;
}
nsCSSFrameConstructor::RestyleEnumerateData* lastRestyle = restylesToProcess;
mPendingRestyles.Enumerate(CollectRestyles, &lastRestyle);
NS_ASSERTION(lastRestyle - restylesToProcess ==
PRInt32(mPendingRestyles.Count()),
"Enumeration screwed up somehow");
// Clear the hashtable so we don't end up trying to process a restyle we're
// already processing, sending us into an infinite loop.
mPendingRestyles.Clear();
for (nsCSSFrameConstructor::RestyleEnumerateData* currentRestyle =
restylesToProcess;
currentRestyle != lastRestyle;
++currentRestyle) {
nsIContent* content = currentRestyle->mContent;
if (!content->GetDocument() ||
content->GetDocument() != context->GetDocument()) {
// Content node has been removed from our document; nothing else
// to do here
continue;
}
nsChangeHint changeHint = currentRestyle->mChangeHint;
nsReStyleHint restyleHint = currentRestyle->mRestyleHint;
nsIFrame* primaryFrame = nsnull;
shell->GetPrimaryFrameFor(content, &primaryFrame);
if (restyleHint & eReStyle_Self) {
shell->FrameConstructor()->RestyleElement(context, content, primaryFrame,
currentRestyle->mChangeHint);
} else if (changeHint &&
(primaryFrame ||
(changeHint & nsChangeHint_ReconstructFrame))) {
// Don't need to recompute style; just apply the hint
nsStyleChangeList changeList;
changeList.AppendChange(primaryFrame, content, changeHint);
shell->FrameConstructor()->ProcessRestyledFrames(changeList, context);
}
if (restyleHint & eReStyle_LaterSiblings) {
shell->FrameConstructor()->RestyleLaterSiblings(context, content);
}
}
delete [] restylesToProcess;
}
void

View File

@ -1062,6 +1062,10 @@ public:
nsChangeHint mChangeHint; // The minimal change hint for "self"
};
struct RestyleEnumerateData : public RestyleData {
nsCOMPtr<nsIContent> mContent;
};
struct RestyleEvent;
friend struct RestyleEvent;