From e1eaaf62edae7b8e9f630030345920ae7db76c62 Mon Sep 17 00:00:00 2001 From: "bzbarsky%mit.edu" Date: Mon, 4 Dec 2006 20:35:55 +0000 Subject: [PATCH] Make ReconstructDocElementHierarchy work correctly even if we first blew away a pseudo which had the root as its content. Bug 343293, r+sr=roc git-svn-id: svn://10.0.0.236/trunk@216439 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/base/nsCSSFrameConstructor.cpp | 6 +- mozilla/layout/base/nsFrameManager.cpp | 64 +++++++++++-------- mozilla/layout/base/nsFrameManager.h | 8 +++ mozilla/layout/generic/nsImageMap.cpp | 2 +- 4 files changed, 49 insertions(+), 31 deletions(-) diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index abbb7579a95..4049f8bd845 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -667,8 +667,7 @@ DoCleanupFrameReferences(nsFrameManager* aFrameManager, } // Remove the mapping from the content object to its frame - aFrameManager->SetPrimaryFrameFor(content, nsnull); - aFrameIn->RemovedAsPrimaryFrame(); + aFrameManager->RemoveAsPrimaryFrame(content, aFrameIn); aFrameManager->ClearAllUndisplayedContentIn(content); // Recursively walk the child frames. @@ -9620,8 +9619,7 @@ DoDeletingFrameSubtree(nsFrameManager* aFrameManager, // Remove the mapping from the content object to its frame. nsIContent* content = aFrame->GetContent(); if (content) { - aFrameManager->SetPrimaryFrameFor(content, nsnull); - aFrame->RemovedAsPrimaryFrame(); + aFrameManager->RemoveAsPrimaryFrame(content, aFrame); aFrameManager->ClearAllUndisplayedContentIn(content); } diff --git a/mozilla/layout/base/nsFrameManager.cpp b/mozilla/layout/base/nsFrameManager.cpp index aa393d15d6f..3c8bb21328f 100644 --- a/mozilla/layout/base/nsFrameManager.cpp +++ b/mozilla/layout/base/nsFrameManager.cpp @@ -423,44 +423,56 @@ nsFrameManager::SetPrimaryFrameFor(nsIContent* aContent, nsIFrame* aPrimaryFrame) { NS_ENSURE_ARG_POINTER(aContent); - // it's ok if aPrimaryFrame is null + NS_ASSERTION(aPrimaryFrame && aPrimaryFrame->GetParent(), + "BOGUS!"); - // If aPrimaryFrame is NULL, then remove the mapping - if (!aPrimaryFrame) { - if (mPrimaryFrameMap.ops) { - PL_DHashTableOperate(&mPrimaryFrameMap, aContent, PL_DHASH_REMOVE); - } - } else { // This code should be used if/when we switch back to a 2-word entry // in the primary frame map. #if 0 - NS_PRECONDITION(aPrimaryFrame->GetContent() == aContent, "wrong content"); + NS_PRECONDITION(aPrimaryFrame->GetContent() == aContent, "wrong content"); #endif - // Create a new hashtable if necessary - if (!mPrimaryFrameMap.ops) { - if (!PL_DHashTableInit(&mPrimaryFrameMap, PL_DHashGetStubOps(), nsnull, - sizeof(PrimaryFrameMapEntry), 16)) { - mPrimaryFrameMap.ops = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } + // Create a new hashtable if necessary + if (!mPrimaryFrameMap.ops) { + if (!PL_DHashTableInit(&mPrimaryFrameMap, PL_DHashGetStubOps(), nsnull, + sizeof(PrimaryFrameMapEntry), 16)) { + mPrimaryFrameMap.ops = nsnull; + return NS_ERROR_OUT_OF_MEMORY; } - - // Add a mapping to the hash table - PrimaryFrameMapEntry *entry = NS_STATIC_CAST(PrimaryFrameMapEntry*, - PL_DHashTableOperate(&mPrimaryFrameMap, aContent, PL_DHASH_ADD)); -#ifdef DEBUG_dbaron - if (entry->frame) { - NS_WARNING("already have primary frame for content"); - } -#endif - entry->frame = aPrimaryFrame; - entry->content = aContent; } + + // Add a mapping to the hash table + PrimaryFrameMapEntry *entry = NS_STATIC_CAST(PrimaryFrameMapEntry*, + PL_DHashTableOperate(&mPrimaryFrameMap, aContent, PL_DHASH_ADD)); +#ifdef DEBUG_dbaron + if (entry->frame) { + NS_WARNING("already have primary frame for content"); + } +#endif + entry->frame = aPrimaryFrame; + entry->content = aContent; return NS_OK; } +void +nsFrameManager::RemoveAsPrimaryFrame(nsIContent* aContent, + nsIFrame* aPrimaryFrame) +{ + NS_PRECONDITION(aPrimaryFrame, "Must have a frame"); + if (aContent && mPrimaryFrameMap.ops) { + PrimaryFrameMapEntry *entry = NS_STATIC_CAST(PrimaryFrameMapEntry*, + PL_DHashTableOperate(&mPrimaryFrameMap, aContent, PL_DHASH_LOOKUP)); + if (PL_DHASH_ENTRY_IS_BUSY(entry) && entry->frame == aPrimaryFrame) { + // Don't use PL_DHashTableRawRemove, since we want the table to + // shrink as needed. + PL_DHashTableOperate(&mPrimaryFrameMap, aContent, PL_DHASH_REMOVE); + } + } + + aPrimaryFrame->RemovedAsPrimaryFrame(); +} + void nsFrameManager::ClearPrimaryFrameMap() { diff --git a/mozilla/layout/base/nsFrameManager.h b/mozilla/layout/base/nsFrameManager.h index dd598ae4ee0..113b6160fac 100644 --- a/mozilla/layout/base/nsFrameManager.h +++ b/mozilla/layout/base/nsFrameManager.h @@ -114,8 +114,16 @@ public: // instead of calling IndexOf(aContent). NS_HIDDEN_(nsIFrame*) GetPrimaryFrameFor(nsIContent* aContent, PRInt32 aIndexHint); + // aPrimaryFrame must not be null. If you're trying to remove a primary frame + // mapping, use RemoveAsPrimaryFrame. NS_HIDDEN_(nsresult) SetPrimaryFrameFor(nsIContent* aContent, nsIFrame* aPrimaryFrame); + // If aPrimaryFrame is the current primary frame for aContent, remove the + // relevant hashtable entry. If the current primary frame for aContent is + // null, this does nothing. aPrimaryFrame must not be null, and this method + // handles calling RemovedAsPrimaryFrame on aPrimaryFrame. + NS_HIDDEN_(void) RemoveAsPrimaryFrame(nsIContent* aContent, + nsIFrame* aPrimaryFrame); NS_HIDDEN_(void) ClearPrimaryFrameMap(); // Placeholder frame functions diff --git a/mozilla/layout/generic/nsImageMap.cpp b/mozilla/layout/generic/nsImageMap.cpp index 17547ee743d..4836eb401cf 100644 --- a/mozilla/layout/generic/nsImageMap.cpp +++ b/mozilla/layout/generic/nsImageMap.cpp @@ -762,7 +762,7 @@ nsImageMap::FreeAreas() PRInt32 i, n = mAreas.Count(); for (i = 0; i < n; i++) { Area* area = (Area*) mAreas.ElementAt(i); - frameManager->SetPrimaryFrameFor(area->mArea, nsnull); + frameManager->RemoveAsPrimaryFrame(area->mArea, mImageFrame); nsCOMPtr areaContent; area->GetArea(getter_AddRefs(areaContent));