зеркало из https://github.com/mozilla/gecko-dev.git
Bug 537624. Don't set up undisplayed entries until we're sure we're creating frames from the relevant FrameConstructionItemList. r=roc
This commit is contained in:
Родитель
7cd871dc54
Коммит
a90ab1fdc8
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
|
||||
function boom()
|
||||
{
|
||||
var a = document.getElementById("a");
|
||||
var b = document.getElementById("b");
|
||||
a.insertBefore(b, a.firstChild);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="boom();"><span id="a"><div></div></span><span id="b"><span style="display: none;"></span><span style="display: none;"></span></span></body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script>
|
||||
function boom()
|
||||
{
|
||||
var a = document.createElementNS("http://www.w3.org/1999/xhtml", "span");
|
||||
var b = document.createElementNS("http://www.w3.org/1999/xhtml", "span");
|
||||
var x = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
|
||||
var y = document.createElementNS("http://www.w3.org/1999/xhtml", "basefont");
|
||||
var z = document.createElementNS("http://www.w3.org/1999/xhtml", "body");
|
||||
z.setAttributeNS(null, "link", "#333333");
|
||||
|
||||
document.documentElement.appendChild(a);
|
||||
b.appendChild(x);
|
||||
b.appendChild(y);
|
||||
document.documentElement.offsetHeight;
|
||||
a.appendChild(b);
|
||||
document.documentElement.offsetHeight;
|
||||
document.createElementNS("http://www.w3.org/1999/xhtml", "div").appendChild(y);
|
||||
b.appendChild(z);
|
||||
}
|
||||
</script>
|
||||
<body onload="boom();"></body>
|
|
@ -299,6 +299,7 @@ load 536720.xul
|
|||
load 537059-1.xhtml
|
||||
load 537141-1.xhtml
|
||||
load 537562-1.xhtml
|
||||
load 537624-1.html
|
||||
load 537631-1.html
|
||||
load 538082-1.xul
|
||||
load 538207-1.xhtml
|
||||
|
@ -352,3 +353,4 @@ load 722137.html
|
|||
load 725535.html
|
||||
load 727601.html
|
||||
load 736389-1.xhtml
|
||||
load 736924-1.html
|
||||
|
|
|
@ -4933,6 +4933,7 @@ nsCSSFrameConstructor::ConstructFrame(nsFrameConstructorState& aState,
|
|||
NS_PRECONDITION(nsnull != aParentFrame, "no parent frame");
|
||||
FrameConstructionItemList items;
|
||||
AddFrameConstructionItems(aState, aContent, true, aParentFrame, items);
|
||||
items.SetTriedConstructingFrames();
|
||||
|
||||
for (FCItemIterator iter(items); !iter.IsDone(); iter.Next()) {
|
||||
NS_ASSERTION(iter.item().DesiredParentType() == GetParentType(aParentFrame),
|
||||
|
@ -4995,16 +4996,11 @@ nsCSSFrameConstructor::AddFrameConstructionItems(nsFrameConstructorState& aState
|
|||
aItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set aContent as undisplayed content with style context aStyleContext. This
|
||||
* method enforces the invariant that all style contexts in the undisplayed
|
||||
* content map must be non-pseudo contexts and also handles unbinding
|
||||
* undisplayed generated content as needed.
|
||||
*/
|
||||
static void
|
||||
SetAsUndisplayedContent(nsFrameManager* aFrameManager, nsIContent* aContent,
|
||||
nsStyleContext* aStyleContext,
|
||||
bool aIsGeneratedContent)
|
||||
/* static */ void
|
||||
nsCSSFrameConstructor::SetAsUndisplayedContent(FrameConstructionItemList& aList,
|
||||
nsIContent* aContent,
|
||||
nsStyleContext* aStyleContext,
|
||||
bool aIsGeneratedContent)
|
||||
{
|
||||
if (aStyleContext->GetPseudo()) {
|
||||
if (aIsGeneratedContent) {
|
||||
|
@ -5014,7 +5010,7 @@ SetAsUndisplayedContent(nsFrameManager* aFrameManager, nsIContent* aContent,
|
|||
}
|
||||
|
||||
NS_ASSERTION(!aIsGeneratedContent, "Should have had pseudo type");
|
||||
aFrameManager->SetUndisplayedContent(aContent, aStyleContext);
|
||||
aList.AppendUndisplayedItem(aContent, aStyleContext);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -5079,7 +5075,7 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
|
|||
// Pre-check for display "none" - if we find that, don't create
|
||||
// any frame at all
|
||||
if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
|
||||
SetAsUndisplayedContent(this, aContent, styleContext, isGeneratedContent);
|
||||
SetAsUndisplayedContent(aItems, aContent, styleContext, isGeneratedContent);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -5103,7 +5099,8 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
|
|||
!aContent->IsRootOfNativeAnonymousSubtree()) {
|
||||
// No frame for aContent
|
||||
if (!isText) {
|
||||
SetAsUndisplayedContent(this, aContent, styleContext, isGeneratedContent);
|
||||
SetAsUndisplayedContent(aItems, aContent, styleContext,
|
||||
isGeneratedContent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -5127,7 +5124,7 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
|
|||
aParentFrame->IsFrameOfType(nsIFrame::eSVG) &&
|
||||
!aParentFrame->IsFrameOfType(nsIFrame::eSVGForeignObject)
|
||||
) {
|
||||
SetAsUndisplayedContent(this, element, styleContext,
|
||||
SetAsUndisplayedContent(aItems, element, styleContext,
|
||||
isGeneratedContent);
|
||||
return;
|
||||
}
|
||||
|
@ -5158,7 +5155,7 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
|
|||
NS_ASSERTION(data, "Should have frame construction data now");
|
||||
|
||||
if (data->mBits & FCDATA_SUPPRESS_FRAME) {
|
||||
SetAsUndisplayedContent(this, element, styleContext, isGeneratedContent);
|
||||
SetAsUndisplayedContent(aItems, element, styleContext, isGeneratedContent);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -5168,7 +5165,7 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
|
|||
aParentFrame->GetType() != nsGkAtoms::menuFrame)) {
|
||||
if (!aState.mPopupItems.containingBlock &&
|
||||
!aState.mHavePendingPopupgroup) {
|
||||
SetAsUndisplayedContent(this, element, styleContext,
|
||||
SetAsUndisplayedContent(aItems, element, styleContext,
|
||||
isGeneratedContent);
|
||||
return;
|
||||
}
|
||||
|
@ -5185,7 +5182,7 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
|
|||
aParentFrame->GetType() == nsGkAtoms::tableColGroupFrame &&
|
||||
(!(bits & FCDATA_IS_TABLE_PART) ||
|
||||
display->mDisplay != NS_STYLE_DISPLAY_TABLE_COLUMN)) {
|
||||
SetAsUndisplayedContent(this, aContent, styleContext, isGeneratedContent);
|
||||
SetAsUndisplayedContent(aItems, aContent, styleContext, isGeneratedContent);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -8717,6 +8714,7 @@ nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame)
|
|||
ITEM_ALLOW_XBL_BASE |
|
||||
ITEM_ALLOW_PAGE_BREAK,
|
||||
items);
|
||||
items.SetTriedConstructingFrames();
|
||||
for (FCItemIterator iter(items); !iter.IsDone(); iter.Next()) {
|
||||
NS_ASSERTION(iter.item().DesiredParentType() ==
|
||||
GetParentType(canvasFrame),
|
||||
|
@ -9442,6 +9440,8 @@ nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState& aSta
|
|||
nsIFrame* aParentFrame,
|
||||
nsFrameItems& aFrameItems)
|
||||
{
|
||||
aItems.SetTriedConstructingFrames();
|
||||
|
||||
nsresult rv = CreateNeededTablePseudos(aState, aItems, aParentFrame);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -11832,7 +11832,10 @@ Iterator::AppendItemsToList(const Iterator& aEnd,
|
|||
NS_ASSERTION(&aTargetList != &mList, "Unexpected call");
|
||||
NS_PRECONDITION(mEnd == aEnd.mEnd, "end iterator for some other list?");
|
||||
|
||||
if (!AtStart() || !aEnd.IsDone() || !aTargetList.IsEmpty()) {
|
||||
// We can't just move our guts to the other list if it already has
|
||||
// some information or if we're not moving our entire list.
|
||||
if (!AtStart() || !aEnd.IsDone() || !aTargetList.IsEmpty() ||
|
||||
!aTargetList.mUndisplayedItems.IsEmpty()) {
|
||||
do {
|
||||
AppendItemToList(aTargetList);
|
||||
} while (*this != aEnd);
|
||||
|
@ -11841,7 +11844,8 @@ Iterator::AppendItemsToList(const Iterator& aEnd,
|
|||
|
||||
// move over the list of items
|
||||
PR_INSERT_AFTER(&aTargetList.mItems, &mList.mItems);
|
||||
PR_REMOVE_LINK(&mList.mItems);
|
||||
// Need to init when we remove to makd ~FrameConstructionItemList work right.
|
||||
PR_REMOVE_AND_INIT_LINK(&mList.mItems);
|
||||
|
||||
// Copy over the various counters
|
||||
aTargetList.mInlineCount = mList.mInlineCount;
|
||||
|
@ -11851,7 +11855,11 @@ Iterator::AppendItemsToList(const Iterator& aEnd,
|
|||
memcpy(aTargetList.mDesiredParentCounts, mList.mDesiredParentCounts,
|
||||
sizeof(aTargetList.mDesiredParentCounts));
|
||||
|
||||
// Swap out undisplayed item arrays, before we nuke the array on our end
|
||||
aTargetList.mUndisplayedItems.SwapElements(mList.mUndisplayedItems);
|
||||
|
||||
// reset mList
|
||||
mList.~FrameConstructionItemList();
|
||||
new (&mList) FrameConstructionItemList();
|
||||
|
||||
// Point ourselves to aEnd, as advertised
|
||||
|
|
|
@ -816,7 +816,8 @@ private:
|
|||
mItemCount(0),
|
||||
mLineBoundaryAtStart(false),
|
||||
mLineBoundaryAtEnd(false),
|
||||
mParentHasNoXBLChildren(false)
|
||||
mParentHasNoXBLChildren(false),
|
||||
mTriedConstructingFrames(false)
|
||||
{
|
||||
PR_INIT_CLIST(&mItems);
|
||||
memset(mDesiredParentCounts, 0, sizeof(mDesiredParentCounts));
|
||||
|
@ -832,6 +833,20 @@ private:
|
|||
|
||||
// Leaves our mItems pointing to deleted memory in both directions,
|
||||
// but that's OK at this point.
|
||||
|
||||
// Create the undisplayed entries for our mUndisplayedItems, if any, but
|
||||
// only if we have tried constructing frames for this item list. If we
|
||||
// haven't, then we're just throwing it away and will probably try again.
|
||||
if (!mUndisplayedItems.IsEmpty() && mTriedConstructingFrames) {
|
||||
// We could store the frame manager in a member, but just
|
||||
// getting it off the style context is not too bad.
|
||||
nsFrameManager *mgr =
|
||||
mUndisplayedItems[0].mStyleContext->PresContext()->FrameManager();
|
||||
for (PRUint32 i = 0; i < mUndisplayedItems.Length(); ++i) {
|
||||
UndisplayedItem& item = mUndisplayedItems[i];
|
||||
mgr->SetUndisplayedContent(item.mContent, item.mStyleContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetLineBoundaryAtStart(bool aBoundary) { mLineBoundaryAtStart = aBoundary; }
|
||||
|
@ -839,6 +854,7 @@ private:
|
|||
void SetParentHasNoXBLChildren(bool aHasNoXBLChildren) {
|
||||
mParentHasNoXBLChildren = aHasNoXBLChildren;
|
||||
}
|
||||
void SetTriedConstructingFrames() { mTriedConstructingFrames = true; }
|
||||
bool HasLineBoundaryAtStart() { return mLineBoundaryAtStart; }
|
||||
bool HasLineBoundaryAtEnd() { return mLineBoundaryAtEnd; }
|
||||
bool ParentHasNoXBLChildren() { return mParentHasNoXBLChildren; }
|
||||
|
@ -871,6 +887,11 @@ private:
|
|||
return item;
|
||||
}
|
||||
|
||||
void AppendUndisplayedItem(nsIContent* aContent,
|
||||
nsStyleContext* aStyleContext) {
|
||||
mUndisplayedItems.AppendElement(UndisplayedItem(aContent, aStyleContext));
|
||||
}
|
||||
|
||||
void InlineItemAdded() { ++mInlineCount; }
|
||||
void BlockItemAdded() { ++mBlockCount; }
|
||||
void LineParticipantItemAdded() { ++mLineParticipantCount; }
|
||||
|
@ -977,6 +998,15 @@ private:
|
|||
return static_cast<FrameConstructionItem*>(item);
|
||||
}
|
||||
|
||||
struct UndisplayedItem {
|
||||
UndisplayedItem(nsIContent* aContent, nsStyleContext* aStyleContext) :
|
||||
mContent(aContent), mStyleContext(aStyleContext)
|
||||
{}
|
||||
|
||||
nsIContent * const mContent;
|
||||
nsRefPtr<nsStyleContext> mStyleContext;
|
||||
};
|
||||
|
||||
// Adjust our various counts for aItem being added or removed. aDelta
|
||||
// should be either +1 or -1 depending on which is happening.
|
||||
void AdjustCountsForItem(FrameConstructionItem* aItem, PRInt32 aDelta);
|
||||
|
@ -995,6 +1025,10 @@ private:
|
|||
bool mLineBoundaryAtEnd;
|
||||
// True if the parent is guaranteed to have no XBL anonymous children
|
||||
bool mParentHasNoXBLChildren;
|
||||
// True if we have tried constructing frames from this list
|
||||
bool mTriedConstructingFrames;
|
||||
|
||||
nsTArray<UndisplayedItem> mUndisplayedItems;
|
||||
};
|
||||
|
||||
typedef FrameConstructionItemList::Iterator FCItemIterator;
|
||||
|
@ -1097,7 +1131,7 @@ private:
|
|||
FrameConstructionItemList mChildItems;
|
||||
|
||||
private:
|
||||
FrameConstructionItem(const FrameConstructionItem& aOther); /* not implemented */
|
||||
FrameConstructionItem(const FrameConstructionItem& aOther) MOZ_DELETE; /* not implemented */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1779,6 +1813,18 @@ private:
|
|||
mDocument->SetNeedLayoutFlush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the pair (aContent, aStyleContext) to the undisplayed items
|
||||
* in aList as needed. This method enforces the invariant that all
|
||||
* style contexts in the undisplayed content map must be non-pseudo
|
||||
* contexts and also handles unbinding undisplayed generated content
|
||||
* as needed.
|
||||
*/
|
||||
static void SetAsUndisplayedContent(FrameConstructionItemList& aList,
|
||||
nsIContent* aContent,
|
||||
nsStyleContext* aStyleContext,
|
||||
bool aIsGeneratedContent);
|
||||
|
||||
public:
|
||||
|
||||
friend class nsFrameConstructorState;
|
||||
|
|
Загрузка…
Ссылка в новой задаче