зеркало из https://github.com/mozilla/gecko-dev.git
Fix crash bug 322348 by making ReParentStyleContext more sane. r+sr=dbaron
This commit is contained in:
Родитель
403cbe4cd1
Коммит
4b74ae14f8
|
@ -11887,14 +11887,12 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
|
|||
// Support for :first-line style
|
||||
|
||||
static void
|
||||
ReparentFrame(nsPresContext* aPresContext,
|
||||
ReparentFrame(nsFrameManager* aFrameManager,
|
||||
nsIFrame* aNewParentFrame,
|
||||
nsStyleContext* aParentStyleContext,
|
||||
nsIFrame* aFrame)
|
||||
{
|
||||
aFrame->SetParent(aNewParentFrame);
|
||||
aPresContext->FrameManager()->ReParentStyleContext(aFrame,
|
||||
aParentStyleContext);
|
||||
aFrameManager->ReParentStyleContext(aFrame);
|
||||
}
|
||||
|
||||
// Special routine to handle placing a list of frames into a block
|
||||
|
@ -11959,8 +11957,10 @@ nsCSSFrameConstructor::WrapFramesInFirstLineFrame(
|
|||
|
||||
// Give the inline frames to the lineFrame <b>after</b> reparenting them
|
||||
kid = firstInlineFrame;
|
||||
NS_ASSERTION(lineFrame->GetStyleContext() == firstLineStyle,
|
||||
"Bogus style context on line frame");
|
||||
while (kid) {
|
||||
ReparentFrame(aState.mPresContext, lineFrame, firstLineStyle, kid);
|
||||
ReparentFrame(aState.mFrameManager, lineFrame, kid);
|
||||
kid = kid->GetNextSibling();
|
||||
}
|
||||
lineFrame->SetInitialChildList(aState.mPresContext, nsnull,
|
||||
|
@ -12004,7 +12004,6 @@ nsCSSFrameConstructor::AppendFirstLineFrames(
|
|||
return rv;
|
||||
}
|
||||
nsIFrame* lineFrame = lastBlockKid;
|
||||
nsStyleContext* firstLineStyle = lineFrame->GetStyleContext();
|
||||
|
||||
// Find the first and last inline frame in aFrameItems
|
||||
nsIFrame* kid = aFrameItems.childList;
|
||||
|
@ -12032,7 +12031,7 @@ nsCSSFrameConstructor::AppendFirstLineFrames(
|
|||
lastInlineFrame->SetNextSibling(nsnull);
|
||||
kid = firstInlineFrame;
|
||||
while (kid) {
|
||||
ReparentFrame(aState.mPresContext, lineFrame, firstLineStyle, kid);
|
||||
ReparentFrame(aState.mFrameManager, lineFrame, kid);
|
||||
kid = kid->GetNextSibling();
|
||||
}
|
||||
aState.mFrameManager->AppendFrames(lineFrame, nsnull, firstInlineFrame);
|
||||
|
@ -12074,12 +12073,10 @@ nsCSSFrameConstructor::InsertFirstLineFrames(
|
|||
if (firstBlockKid->GetType() == nsLayoutAtoms::lineFrame) {
|
||||
// We already have a first-line frame
|
||||
nsIFrame* lineFrame = firstBlockKid;
|
||||
nsStyleContext* firstLineStyle = lineFrame->GetStyleContext();
|
||||
|
||||
if (isInline) {
|
||||
// Easy case: the new inline frame will go into the lineFrame.
|
||||
ReparentFrame(aState.mPresContext, lineFrame, firstLineStyle,
|
||||
newFrame);
|
||||
ReparentFrame(aState.mFrameManager, lineFrame, newFrame);
|
||||
aState.mFrameManager->InsertFrames(lineFrame, nsnull, nsnull,
|
||||
newFrame);
|
||||
|
||||
|
@ -12120,7 +12117,9 @@ nsCSSFrameConstructor::InsertFirstLineFrames(
|
|||
|
||||
// Give the inline frames to the lineFrame <b>after</b>
|
||||
// reparenting them
|
||||
ReparentFrame(aPresContext, lineFrame, firstLineStyle, newFrame);
|
||||
NS_ASSERTION(lineFrame->GetStyleContext() == firstLineStyle,
|
||||
"Bogus style context on line frame");
|
||||
ReparentFrame(aPresContext, lineFrame, newFrame);
|
||||
lineFrame->SetInitialChildList(aState.mPresContext, nsnull,
|
||||
newFrame);
|
||||
}
|
||||
|
@ -12179,8 +12178,7 @@ nsCSSFrameConstructor::InsertFirstLineFrames(
|
|||
else {
|
||||
// We got lucky: aPrevSibling was the last inline frame in
|
||||
// the line-frame.
|
||||
ReparentFrame(aState.mPresContext, aBlockFrame, firstLineStyle,
|
||||
newFrame);
|
||||
ReparentFrame(aState.mFrameManager, aBlockFrame, newFrame);
|
||||
aState.mFrameManager->InsertFrames(aBlockFrame, nsnull,
|
||||
prevSiblingParent, newFrame);
|
||||
aFrameItems.childList = nsnull;
|
||||
|
|
|
@ -891,82 +891,98 @@ nsFrameManager::DebugVerifyStyleTree(nsIFrame* aFrame)
|
|||
#endif // DEBUG
|
||||
|
||||
nsresult
|
||||
nsFrameManager::ReParentStyleContext(nsIFrame* aFrame,
|
||||
nsStyleContext* aNewParentContext)
|
||||
nsFrameManager::ReParentStyleContext(nsIFrame* aFrame)
|
||||
{
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (aFrame) {
|
||||
// DO NOT verify the style tree before reparenting. The frame
|
||||
// tree has already been changed, so this check would just fail.
|
||||
nsStyleContext* oldContext = aFrame->GetStyleContext();
|
||||
if (oldContext) {
|
||||
nsPresContext *presContext = GetPresContext();
|
||||
nsRefPtr<nsStyleContext> newContext;
|
||||
result = NS_OK;
|
||||
newContext = mStyleSet->ReParentStyleContext(presContext, oldContext,
|
||||
aNewParentContext);
|
||||
if (newContext) {
|
||||
if (newContext != oldContext) {
|
||||
PRInt32 listIndex = 0;
|
||||
nsIAtom* childList = nsnull;
|
||||
nsIFrame* child;
|
||||
// DO NOT verify the style tree before reparenting. The frame
|
||||
// tree has already been changed, so this check would just fail.
|
||||
nsStyleContext* oldContext = aFrame->GetStyleContext();
|
||||
// XXXbz can oldContext really ever be null?
|
||||
if (oldContext) {
|
||||
nsPresContext *presContext = GetPresContext();
|
||||
nsRefPtr<nsStyleContext> newContext;
|
||||
nsIFrame* providerFrame = nsnull;
|
||||
PRBool providerIsChild = PR_FALSE;
|
||||
nsIFrame* providerChild = nsnull;
|
||||
aFrame->GetParentStyleContextFrame(presContext, &providerFrame,
|
||||
&providerIsChild);
|
||||
nsStyleContext* newParentContext = nsnull;
|
||||
if (providerIsChild) {
|
||||
ReParentStyleContext(providerFrame);
|
||||
newParentContext = providerFrame->GetStyleContext();
|
||||
providerChild = providerFrame;
|
||||
} else if (providerFrame) {
|
||||
newParentContext = providerFrame->GetStyleContext();
|
||||
} else {
|
||||
NS_NOTREACHED("Reparenting something that has no usable parent? "
|
||||
"Shouldn't happen!");
|
||||
}
|
||||
|
||||
newContext = mStyleSet->ReParentStyleContext(presContext, oldContext,
|
||||
newParentContext);
|
||||
if (newContext) {
|
||||
if (newContext != oldContext) {
|
||||
PRInt32 listIndex = 0;
|
||||
nsIAtom* childList = nsnull;
|
||||
nsIFrame* child;
|
||||
|
||||
aFrame->SetStyleContext(newContext);
|
||||
aFrame->SetStyleContext(newContext);
|
||||
|
||||
do {
|
||||
child = aFrame->GetFirstChild(childList);
|
||||
while (child) {
|
||||
if (NS_FRAME_OUT_OF_FLOW != (child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
|
||||
// only do frames that are in flow
|
||||
if (nsLayoutAtoms::placeholderFrame == child->GetType()) {
|
||||
// get out of flow frame and recurse there
|
||||
nsIFrame* outOfFlowFrame =
|
||||
nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
|
||||
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
|
||||
do {
|
||||
child = aFrame->GetFirstChild(childList);
|
||||
while (child) {
|
||||
// only do frames that are in flow
|
||||
if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
|
||||
if (nsLayoutAtoms::placeholderFrame == child->GetType()) {
|
||||
// get out of flow frame and recurse there
|
||||
nsIFrame* outOfFlowFrame =
|
||||
nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
|
||||
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
|
||||
|
||||
result = ReParentStyleContext(outOfFlowFrame, newContext);
|
||||
NS_ASSERTION(outOfFlowFrame != providerChild,
|
||||
"Out of flow provider?");
|
||||
|
||||
// reparent placeholder's context under out of flow frame
|
||||
nsStyleContext* outOfFlowContext = outOfFlowFrame->GetStyleContext();
|
||||
ReParentStyleContext(child, outOfFlowContext);
|
||||
}
|
||||
else { // regular frame
|
||||
result = ReParentStyleContext(child, newContext);
|
||||
}
|
||||
ReParentStyleContext(outOfFlowFrame);
|
||||
|
||||
// reparent placeholder too
|
||||
ReParentStyleContext(child);
|
||||
}
|
||||
|
||||
child = child->GetNextSibling();
|
||||
}
|
||||
|
||||
childList = aFrame->GetAdditionalChildListName(listIndex++);
|
||||
} while (childList);
|
||||
|
||||
// do additional contexts
|
||||
PRInt32 contextIndex = -1;
|
||||
while (1) {
|
||||
nsStyleContext* oldExtraContext = aFrame->GetAdditionalStyleContext(++contextIndex);
|
||||
if (oldExtraContext) {
|
||||
nsRefPtr<nsStyleContext> newExtraContext;
|
||||
newExtraContext = mStyleSet->ReParentStyleContext(presContext,
|
||||
oldExtraContext,
|
||||
newContext);
|
||||
if (newExtraContext) {
|
||||
aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
|
||||
else if (child != providerChild) {
|
||||
// regular frame, not reparented yet
|
||||
ReParentStyleContext(child);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = NS_OK; // ok not to have extras (or run out)
|
||||
break;
|
||||
|
||||
child = child->GetNextSibling();
|
||||
}
|
||||
|
||||
childList = aFrame->GetAdditionalChildListName(listIndex++);
|
||||
} while (childList);
|
||||
|
||||
// do additional contexts
|
||||
PRInt32 contextIndex = -1;
|
||||
while (1) {
|
||||
nsStyleContext* oldExtraContext =
|
||||
aFrame->GetAdditionalStyleContext(++contextIndex);
|
||||
if (oldExtraContext) {
|
||||
nsRefPtr<nsStyleContext> newExtraContext;
|
||||
newExtraContext = mStyleSet->ReParentStyleContext(presContext,
|
||||
oldExtraContext,
|
||||
newContext);
|
||||
if (newExtraContext) {
|
||||
aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
VerifyStyleTree(GetPresContext(), aFrame, aNewParentContext);
|
||||
#endif
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
VerifyStyleTree(GetPresContext(), aFrame, newParentContext);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsChangeHint
|
||||
|
|
|
@ -158,13 +158,14 @@ public:
|
|||
NS_HIDDEN_(void) NotifyDestroyingFrame(nsIFrame* aFrame);
|
||||
|
||||
/*
|
||||
* Reparent the style contexts of this frame subtree to live under the new
|
||||
* given parent style context. The StyleContextParent of aFrame should be
|
||||
* changed _before_ this method is called, so that style tree verification
|
||||
* can take place correctly.
|
||||
* Reparent the style contexts of this frame subtree. The parent frame of
|
||||
* aFrame must be changed to the new parent before this function is called;
|
||||
* the new parent style context will be automatically computed based on the
|
||||
* new position in the frame tree.
|
||||
*
|
||||
* @param aFrame the root of the subtree to reparent. Must not be null.
|
||||
*/
|
||||
NS_HIDDEN_(nsresult) ReParentStyleContext(nsIFrame* aFrame,
|
||||
nsStyleContext* aNewParentContext);
|
||||
NS_HIDDEN_(nsresult) ReParentStyleContext(nsIFrame* aFrame);
|
||||
|
||||
/*
|
||||
* Re-resolve the style contexts for a frame tree. Returns the top-level
|
||||
|
|
|
@ -690,11 +690,10 @@ nsFieldSetFrame::MaybeSetLegend(nsIFrame* aFrameList, nsIAtom* aListName)
|
|||
void
|
||||
nsFieldSetFrame::ReParentFrameList(nsIFrame* aFrameList)
|
||||
{
|
||||
nsFrameManager* frameManager = mContentFrame->GetPresContext()->FrameManager();
|
||||
nsStyleContext* newParentContext = mContentFrame->GetStyleContext();
|
||||
nsFrameManager* frameManager = GetPresContext()->FrameManager();
|
||||
for (nsIFrame* frame = aFrameList; frame; frame = frame->GetNextSibling()) {
|
||||
frame->SetParent(mContentFrame);
|
||||
frameManager->ReParentStyleContext(frame, newParentContext);
|
||||
frameManager->ReParentStyleContext(frame);
|
||||
}
|
||||
mContentFrame->AddStateBits(GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW);
|
||||
}
|
||||
|
|
|
@ -146,7 +146,8 @@ nsFirstLetterFrame::SetInitialChildList(nsPresContext* aPresContext,
|
|||
nsFrameManager *frameManager = aPresContext->FrameManager();
|
||||
|
||||
for (nsIFrame* frame = aChildList; frame; frame = frame->GetNextSibling()) {
|
||||
frameManager->ReParentStyleContext(frame, mStyleContext);
|
||||
NS_ASSERTION(frame->GetParent() == this, "Unexpected parent");
|
||||
frameManager->ReParentStyleContext(frame);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -844,14 +844,15 @@ NS_IMETHODIMP nsInlineFrame::GetAccessible(nsIAccessible** aAccessible)
|
|||
|
||||
static void
|
||||
ReParentChildListStyle(nsPresContext* aPresContext,
|
||||
nsStyleContext* aParentStyleContext,
|
||||
nsFrameList& aFrameList)
|
||||
nsFrameList& aFrameList,
|
||||
nsIFrame* aParentFrame)
|
||||
{
|
||||
nsFrameManager *frameManager = aPresContext->FrameManager();
|
||||
|
||||
for (nsIFrame* kid = aFrameList.FirstChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
frameManager->ReParentStyleContext(kid, aParentStyleContext);
|
||||
NS_ASSERTION(kid->GetParent() == aParentFrame, "Bogus parentage");
|
||||
frameManager->ReParentStyleContext(kid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -898,7 +899,8 @@ nsFirstLineFrame::PullOneFrame(nsPresContext* aPresContext, InlineReflowState& i
|
|||
if (frame && !GetPrevInFlow()) {
|
||||
// We are a first-line frame. Fixup the child frames
|
||||
// style-context that we just pulled.
|
||||
aPresContext->FrameManager()->ReParentStyleContext(frame, mStyleContext);
|
||||
NS_ASSERTION(frame->GetParent() == this, "Incorrect parent?");
|
||||
aPresContext->FrameManager()->ReParentStyleContext(frame);
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
@ -921,7 +923,7 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext,
|
|||
nsFrameList frames(prevOverflowFrames);
|
||||
|
||||
mFrames.InsertFrames(this, nsnull, prevOverflowFrames);
|
||||
ReParentChildListStyle(aPresContext, mStyleContext, frames);
|
||||
ReParentChildListStyle(aPresContext, frames, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -932,7 +934,7 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext,
|
|||
nsFrameList frames(overflowFrames);
|
||||
|
||||
mFrames.AppendFrames(nsnull, overflowFrames);
|
||||
ReParentChildListStyle(aPresContext, mStyleContext, frames);
|
||||
ReParentChildListStyle(aPresContext, frames, this);
|
||||
}
|
||||
|
||||
// Set our own reflow state (additional state above and beyond
|
||||
|
@ -993,7 +995,7 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext,
|
|||
SetStyleContext(newSC);
|
||||
|
||||
// Re-resolve all children
|
||||
ReParentChildListStyle(aPresContext, mStyleContext, mFrames);
|
||||
ReParentChildListStyle(aPresContext, mFrames, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче