From 32838fc08a3081f1fa9070bcdbb3e97fc2322901 Mon Sep 17 00:00:00 2001 From: "peterv%propagandism.org" Date: Tue, 7 Feb 2006 14:34:10 +0000 Subject: [PATCH] Fix for bug 315901 (Move RangeList and EventListenerManager hashes to nsContentUtils). r/sr=jst. git-svn-id: svn://10.0.0.236/trunk@189306 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/public/nsContentUtils.h | 72 ++++ mozilla/content/base/src/nsContentUtils.cpp | 385 +++++++++++++++++- .../content/base/src/nsGenericDOMDataNode.cpp | 161 +------- .../content/base/src/nsGenericDOMDataNode.h | 7 +- mozilla/content/base/src/nsGenericElement.cpp | 353 ++-------------- mozilla/content/base/src/nsGenericElement.h | 63 +-- mozilla/content/base/src/nsRange.cpp | 2 +- mozilla/content/base/src/nsRange.h | 2 +- .../html/content/src/nsHTMLInputElement.cpp | 1 + .../content/svg/content/src/nsSVGElement.cpp | 1 + mozilla/layout/build/nsLayoutModule.cpp | 7 +- .../parser/htmlparser/src/CParserContext.cpp | 1 - 12 files changed, 532 insertions(+), 523 deletions(-) diff --git a/mozilla/content/base/public/nsContentUtils.h b/mozilla/content/base/public/nsContentUtils.h index b17cec4fa09..d521633c250 100644 --- a/mozilla/content/base/public/nsContentUtils.h +++ b/mozilla/content/base/public/nsContentUtils.h @@ -82,6 +82,7 @@ class nsILineBreaker; class nsIWordBreaker; class nsIEventQueueService; class nsIJSRuntimeService; +class nsIEventListenerManager; struct JSRuntime; #ifdef MOZ_XTF class nsIXTFService; @@ -711,6 +712,77 @@ public: PRBool aCancelable, PRBool *aDefaultAction = nsnull); + /** + * Add aRange to the list of ranges with a start- or endpoint containing + * aContent. aCreated will be set to PR_TRUE if this call created a new list + * (meaning the list was empty before the call to AddToRangeList). + * + * @param aContent The node contained in the start- or endpoint of aRange. + * @param aRange The range containing aContent in its start- or endpoint. + * @param aCreated [out] Set to PR_TRUE if a new list was created. + */ + static nsresult AddToRangeList(nsIContent *aContent, nsIDOMRange *aRange, + PRBool *aCreated); + + /** + * Remove aRange from the list of ranges with a start- or endpoint containing + * aContent. This will return PR_TRUE if aRange was the last range in the + * list. + * + * @param aContent The node for which to remove aRange. + * @param aRange The range to remove. + * @return PR_TRUE if aRange was the last range in the list. + */ + static PRBool RemoveFromRangeList(nsIContent *aContent, nsIDOMRange *aRange); + + /** + * Look up the list of ranges containing aContent. + * + * @param aContent The node for which to look up the range list. + * @return The range list if one exists. + */ + static const nsVoidArray* LookupRangeList(const nsIContent *aContent); + + /** + * Remove the list of ranges containing aContent as their start- or endpoint. + * + * @param aContent The node for which to remove the range list. + */ + static void RemoveRangeList(nsIContent *aContent); + + /** + * Look up the eventlistener manager for aContent. + * + * @param aContent The node for which to look up the eventlistener manager. + * @return The eventlistener manager if one exists. + */ + static nsIEventListenerManager *LookupListenerManager(nsIContent *aContent); + + /** + * Get the eventlistener manager for aContent. This creates a new event- + * listener manager if none exist, in that case aCreated is set to PR_TRUE. + * + * @param aContent The node for which to get the eventlistener manager. + * @param aResult [out] Set to the eventlistener manager for aContent. + * @param aCreated [out] Set to PR_TRUE if a new eventlistener manager was + * created. + */ + static nsresult GetListenerManager(nsIContent *aContent, + nsIEventListenerManager **aResult, + PRBool *aCreated); + + /** + * Remove the eventlistener manager for aContent. + * + * @param aContent The node for which to remove the eventlistener manager. + */ + static void RemoveListenerManager(nsIContent *aContent); + + static PRBool IsInitialized() + { + return sInitialized; + } + private: static nsresult doReparentContentWrapper(nsIContent *aChild, JSContext *cx, diff --git a/mozilla/content/base/src/nsContentUtils.cpp b/mozilla/content/base/src/nsContentUtils.cpp index 21c43dcd7c3..9077102a3d5 100644 --- a/mozilla/content/base/src/nsContentUtils.cpp +++ b/mozilla/content/base/src/nsContentUtils.cpp @@ -101,7 +101,6 @@ #include "nsILoadGroup.h" #include "nsContentPolicyUtils.h" #include "nsDOMString.h" -#include "nsGenericElement.h" #include "nsNodeInfoManager.h" #include "nsCRT.h" #include "nsIDOMEvent.h" @@ -128,6 +127,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID); #include "nsEscape.h" #include "nsICharsetConverterManager.h" #include "nsXULAtoms.h" +#include "nsIEventListenerManager.h" // for ReportToConsole #include "nsIStringBundle.h" @@ -166,6 +166,98 @@ PRInt32 nsContentUtils::sScriptRootCount = 0; PRBool nsContentUtils::sInitialized = PR_FALSE; +static PLDHashTable sRangeListsHash; +static PLDHashTable sEventListenerManagersHash; + +class RangeListMapEntry : public PLDHashEntryHdr +{ +public: + RangeListMapEntry(const void *aKey) + : mKey(aKey), mRangeList(nsnull) + { + } + + ~RangeListMapEntry() + { + delete mRangeList; + } + +private: + const void *mKey; // must be first to look like PLDHashEntryStub + +public: + // We want mRangeList to be an nsAutoVoidArray but we can't make an + // nsAutoVoidArray a direct member of RangeListMapEntry since it + // will be moved around in memory, and nsAutoVoidArray can't deal + // with that. + nsVoidArray *mRangeList; +}; + +class EventListenerManagerMapEntry : public PLDHashEntryHdr +{ +public: + EventListenerManagerMapEntry(const void *aKey) + : mKey(aKey) + { + } + + ~EventListenerManagerMapEntry() + { + if (mListenerManager) { + mListenerManager->Disconnect(); + } + } + +private: + const void *mKey; // must be first, to look like PLDHashEntryStub + +public: + nsCOMPtr mListenerManager; +}; + +PR_STATIC_CALLBACK(PRBool) +RangeListHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, + const void *key) +{ + // Initialize the entry with placement new + new (entry) RangeListMapEntry(key); + return PR_TRUE; +} + +PR_STATIC_CALLBACK(void) +RangeListHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) +{ + RangeListMapEntry *r = NS_STATIC_CAST(RangeListMapEntry *, entry); + + // Let the RangeListMapEntry clean itself up... + r->~RangeListMapEntry(); +} + +PR_STATIC_CALLBACK(PRBool) +EventListenerManagerHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, + const void *key) +{ + // Initialize the entry with placement new + new (entry) EventListenerManagerMapEntry(key); + return PR_TRUE; +} + +PR_STATIC_CALLBACK(void) +EventListenerManagerHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) +{ + EventListenerManagerMapEntry *lm = + NS_STATIC_CAST(EventListenerManagerMapEntry *, entry); + + // Let the EventListenerManagerMapEntry clean itself up... + lm->~EventListenerManagerMapEntry(); +} + +PR_STATIC_CALLBACK(void) +NopClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) +{ + // Do nothing +} + // static nsresult nsContentUtils::Init() @@ -189,9 +281,6 @@ nsContentUtils::Init() rv = NS_GetNameSpaceManager(&sNameSpaceManager); NS_ENSURE_SUCCESS(rv, rv); - rv = nsGenericElement::InitHashes(); - NS_ENSURE_SUCCESS(rv, rv); - rv = CallGetService(nsIXPConnect::GetCID(), &sXPConnect); NS_ENSURE_SUCCESS(rv, rv); @@ -226,6 +315,53 @@ nsContentUtils::Init() return NS_ERROR_OUT_OF_MEMORY; } + if (!sRangeListsHash.ops) { + static PLDHashTableOps hash_table_ops = + { + PL_DHashAllocTable, + PL_DHashFreeTable, + PL_DHashGetKeyStub, + PL_DHashVoidPtrKeyStub, + PL_DHashMatchEntryStub, + PL_DHashMoveEntryStub, + RangeListHashClearEntry, + PL_DHashFinalizeStub, + RangeListHashInitEntry + }; + + if (!PL_DHashTableInit(&sRangeListsHash, &hash_table_ops, nsnull, + sizeof(RangeListMapEntry), 16)) { + sRangeListsHash.ops = nsnull; + + return NS_ERROR_OUT_OF_MEMORY; + } + } + + if (!sEventListenerManagersHash.ops) { + static PLDHashTableOps hash_table_ops = + { + PL_DHashAllocTable, + PL_DHashFreeTable, + PL_DHashGetKeyStub, + PL_DHashVoidPtrKeyStub, + PL_DHashMatchEntryStub, + PL_DHashMoveEntryStub, + EventListenerManagerHashClearEntry, + PL_DHashFinalizeStub, + EventListenerManagerHashInitEntry + }; + + if (!PL_DHashTableInit(&sEventListenerManagersHash, &hash_table_ops, + nsnull, sizeof(EventListenerManagerMapEntry), 16)) { + sEventListenerManagersHash.ops = nsnull; + + PL_DHashTableFinish(&sRangeListsHash); + sRangeListsHash.ops = nsnull; + + return NS_ERROR_OUT_OF_MEMORY; + } + } + sInitialized = PR_TRUE; return NS_OK; @@ -473,6 +609,53 @@ nsContentUtils::Shutdown() delete sPtrsToPtrsToRelease; sPtrsToPtrsToRelease = nsnull; } + + if (sRangeListsHash.ops) { + NS_ASSERTION(sRangeListsHash.entryCount == 0, + "Range list hash not empty at shutdown!"); + + // We're already being shut down and if there are entries left in + // this hash at this point it means we leaked nsGenericElements or + // nsGenericDOMDataNodes. Since we're already partly through the + // shutdown process it's too late to release what's held on to by + // this hash (since the teardown code relies on some things being + // around that aren't around any more) so we rather leak what's + // already leaked in stead of crashing trying to release what + // should've been released much earlier on. + + // Copy the ops out of the hash table + PLDHashTableOps hash_table_ops = *sRangeListsHash.ops; + + // Set the clearEntry hook to be a nop + hash_table_ops.clearEntry = NopClearEntry; + + // Set the ops in the hash table to be the new ops + sRangeListsHash.ops = &hash_table_ops; + + PL_DHashTableFinish(&sRangeListsHash); + + sRangeListsHash.ops = nsnull; + } + + if (sEventListenerManagersHash.ops) { + NS_ASSERTION(sEventListenerManagersHash.entryCount == 0, + "Event listener manager hash not empty at shutdown!"); + + // See comment above. + + // Copy the ops out of the hash table + PLDHashTableOps hash_table_ops = *sEventListenerManagersHash.ops; + + // Set the clearEntry hook to be a nop + hash_table_ops.clearEntry = NopClearEntry; + + // Set the ops in the hash table to be the new ops + sEventListenerManagersHash.ops = &hash_table_ops; + + PL_DHashTableFinish(&sEventListenerManagersHash); + + sEventListenerManagersHash.ops = nsnull; + } } // static @@ -2614,3 +2797,197 @@ nsContentUtils::HasNonEmptyAttr(nsIContent* aContent, PRInt32 aNameSpaceID, return aContent->FindAttrValueIn(aNameSpaceID, aName, strings, eCaseMatters) == nsIContent::ATTR_VALUE_NO_MATCH; } + +/* static */ +nsIEventListenerManager* +nsContentUtils::LookupListenerManager(nsIContent *aContent) +{ + if (!sEventListenerManagersHash.ops) { + // We're already shut down. + + return nsnull; + } + + EventListenerManagerMapEntry *entry = + NS_STATIC_CAST(EventListenerManagerMapEntry *, + PL_DHashTableOperate(&sEventListenerManagersHash, aContent, + PL_DHASH_LOOKUP)); + + return PL_DHASH_ENTRY_IS_BUSY(entry) ? entry->mListenerManager : nsnull; +} + +/* static */ +nsresult +nsContentUtils::GetListenerManager(nsIContent *aContent, + nsIEventListenerManager **aResult, + PRBool *aCreated) +{ + *aResult = nsnull; + *aCreated = PR_FALSE; + + if (!sEventListenerManagersHash.ops) { + // We're already shut down, don't bother creating an event listener + // manager. + + return NS_ERROR_NOT_AVAILABLE; + } + + EventListenerManagerMapEntry *entry = + NS_STATIC_CAST(EventListenerManagerMapEntry *, + PL_DHashTableOperate(&sEventListenerManagersHash, aContent, + PL_DHASH_ADD)); + + if (!entry) { + return NS_ERROR_OUT_OF_MEMORY; + } + + if (!entry->mListenerManager) { + nsresult rv = + NS_NewEventListenerManager(getter_AddRefs(entry->mListenerManager)); + + if (NS_FAILED(rv)) { + PL_DHashTableRawRemove(&sEventListenerManagersHash, entry); + + return rv; + } + + entry->mListenerManager->SetListenerTarget(aContent); + + *aCreated = PR_TRUE; + } + + NS_ADDREF(*aResult = entry->mListenerManager); + + return NS_OK; +} + +/* static */ +void +nsContentUtils::RemoveListenerManager(nsIContent *aContent) +{ + if (sEventListenerManagersHash.ops) { + PL_DHashTableOperate(&sEventListenerManagersHash, aContent, + PL_DHASH_REMOVE); + } +} + +/* static */ +nsresult +nsContentUtils::AddToRangeList(nsIContent *aContent, nsIDOMRange *aRange, + PRBool *aCreated) +{ + *aCreated = PR_FALSE; + + if (!sRangeListsHash.ops) { + // We've already been shut down, don't bother adding a range... + + return NS_OK; + } + + RangeListMapEntry *entry = + NS_STATIC_CAST(RangeListMapEntry *, + PL_DHashTableOperate(&sRangeListsHash, aContent, + PL_DHASH_ADD)); + + if (!entry) { + return NS_ERROR_OUT_OF_MEMORY; + } + + // lazy allocation of range list + if (!entry->mRangeList) { + entry->mRangeList = new nsAutoVoidArray(); + + if (!entry->mRangeList) { + PL_DHashTableRawRemove(&sRangeListsHash, entry); + + return NS_ERROR_OUT_OF_MEMORY; + } + + *aCreated = PR_TRUE; + } + else { + // Make sure we don't add a range that is already in the list! + PRInt32 i = entry->mRangeList->IndexOf(aRange); + + if (i >= 0) { + // Range is already in the list, so there is nothing to do! + + return NS_OK; + } + } + + // dont need to addref - this call is made by the range object + // itself + PRBool rv = entry->mRangeList->AppendElement(aRange); + if (!rv) { + if (entry->mRangeList->Count() == 0) { + // Fresh entry, remove it from the hash... + + PL_DHashTableRawRemove(&sRangeListsHash, entry); + } + + return NS_ERROR_OUT_OF_MEMORY; + } + + return NS_OK; +} + +/* static */ +PRBool +nsContentUtils::RemoveFromRangeList(nsIContent *aContent, nsIDOMRange *aRange) +{ + if (!sRangeListsHash.ops) { + // We've already been shut down, don't bother removing a range... + + return PR_FALSE; + } + + RangeListMapEntry *entry = + NS_STATIC_CAST(RangeListMapEntry *, + PL_DHashTableOperate(&sRangeListsHash, aContent, + PL_DHASH_LOOKUP)); + + if (PL_DHASH_ENTRY_IS_FREE(entry)) { + return PR_FALSE; + } + + NS_ASSERTION(entry->mRangeList, "In the hash but without an object?"); + + // dont need to release - this call is made by the range object itself + entry->mRangeList->RemoveElement(aRange); + + if (entry->mRangeList->Count() != 0) { + return PR_FALSE; + } + + PL_DHashTableRawRemove(&sRangeListsHash, entry); + + return PR_TRUE; +} + +/* static */ +const nsVoidArray* +nsContentUtils::LookupRangeList(const nsIContent *aContent) +{ + if (!sRangeListsHash.ops) { + // We've already been shut down, don't bother getting a range list... + + return nsnull; + } + + RangeListMapEntry *entry = + NS_STATIC_CAST(RangeListMapEntry *, + PL_DHashTableOperate(&sRangeListsHash, aContent, + PL_DHASH_LOOKUP)); + + return PL_DHASH_ENTRY_IS_BUSY(entry) ? entry->mRangeList : nsnull; +} + +/* static */ +void +nsContentUtils::RemoveRangeList(nsIContent *aContent) +{ + if (sRangeListsHash.ops) { + PL_DHashTableOperate(&sRangeListsHash, aContent, PL_DHASH_REMOVE); + } +} diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.cpp b/mozilla/content/base/src/nsGenericDOMDataNode.cpp index 3569b4af54b..92e02c1e261 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.cpp +++ b/mozilla/content/base/src/nsGenericDOMDataNode.cpp @@ -77,13 +77,11 @@ nsGenericDOMDataNode::~nsGenericDOMDataNode() } if (CouldHaveEventListenerManager()) { - PL_DHashTableOperate(&nsGenericElement::sEventListenerManagersHash, - this, PL_DHASH_REMOVE); + nsContentUtils::RemoveListenerManager(this); } if (CouldHaveRangeList()) { - PL_DHashTableOperate(&nsGenericElement::sRangeListsHash, - this, PL_DHASH_REMOVE); + nsContentUtils::RemoveRangeList(this); } } @@ -385,7 +383,7 @@ nsGenericDOMDataNode::SetData(const nsAString& aData) // we can lie and say we are deleting all the text, since in a total // text replacement we should just collapse all the ranges. - nsVoidArray *rangeList = LookupRangeList(); + const nsVoidArray *rangeList = GetRangeList(); if (rangeList) { nsRange::TextOwnerChanged(this, rangeList, 0, mText.GetLength(), 0); } @@ -516,7 +514,7 @@ nsGenericDOMDataNode::ReplaceData(PRUint32 aOffset, PRUint32 aCount, } // inform any enclosed ranges of change - nsVoidArray *rangeList = LookupRangeList(); + const nsVoidArray *rangeList = GetRangeList(); if (rangeList) { nsRange::TextOwnerChanged(this, rangeList, aOffset, endOffset, dataLength); } @@ -546,38 +544,12 @@ nsGenericDOMDataNode::ReplaceData(PRUint32 aOffset, PRUint32 aCount, nsresult nsGenericDOMDataNode::GetListenerManager(nsIEventListenerManager **aResult) { - nsCOMPtr listener_manager; - LookupListenerManager(getter_AddRefs(listener_manager)); - - if (listener_manager) { - *aResult = listener_manager; - NS_ADDREF(*aResult); - - return NS_OK; + PRBool created; + nsresult rv = nsContentUtils::GetListenerManager(this, aResult, &created); + if (NS_SUCCEEDED(rv) && created) { + SetHasEventListenerManager(); } - - if (!nsGenericElement::sEventListenerManagersHash.ops) { - nsresult rv = nsGenericElement::InitHashes(); - NS_ENSURE_SUCCESS(rv, rv); - } - - nsresult rv = NS_NewEventListenerManager(aResult); - NS_ENSURE_SUCCESS(rv, rv); - - // Add a mapping to the hash table - EventListenerManagerMapEntry *entry = - NS_STATIC_CAST(EventListenerManagerMapEntry *, - PL_DHashTableOperate(&nsGenericElement:: - sEventListenerManagersHash, this, - PL_DHASH_ADD)); - - entry->mListenerManager = *aResult; - - entry->mListenerManager->SetListenerTarget(this); - - SetHasEventListenerManager(); - - return NS_OK; + return rv; } //---------------------------------------------------------------------- @@ -875,8 +847,12 @@ nsGenericDOMDataNode::HandleDOMEvent(nsPresContext* aPresContext, } } - nsCOMPtr listener_manager; - LookupListenerManager(getter_AddRefs(listener_manager)); + // Weak pointer, which is fine since the hash table owns the + // listener manager + nsIEventListenerManager *listener_manager = nsnull; + if (CouldHaveEventListenerManager()) { + listener_manager = nsContentUtils::LookupListenerManager(this); + } //Local handling stage //Check for null ELM, check if we're a non-bubbling event in the bubbling state (bubbling state @@ -988,79 +964,26 @@ nsGenericDOMDataNode::MayHaveFrame() const nsresult nsGenericDOMDataNode::RangeAdd(nsIDOMRange* aRange) { - // lazy allocation of range list - - if (!nsGenericElement::sRangeListsHash.ops) { - nsresult rv = nsGenericElement::InitHashes(); - NS_ENSURE_SUCCESS(rv, rv); - } - - RangeListMapEntry *entry = - NS_STATIC_CAST(RangeListMapEntry *, - PL_DHashTableOperate(&nsGenericElement::sRangeListsHash, - this, PL_DHASH_ADD)); - - if (!entry) { - return NS_ERROR_OUT_OF_MEMORY; - } - - nsVoidArray *range_list = entry->mRangeList; - - if (!range_list) { - range_list = new nsAutoVoidArray(); - - if (!range_list) { - PL_DHashTableRawRemove(&nsGenericElement::sRangeListsHash, entry); - - return NS_ERROR_OUT_OF_MEMORY; - } - - entry->mRangeList = range_list; - + PRBool created; + nsresult rv = nsContentUtils::AddToRangeList(this, aRange, &created); + if (NS_SUCCEEDED(rv) && created) { SetHasRangeList(); - } else { - // Make sure we don't add a range that is already - // in the list! - PRInt32 i = range_list->IndexOf(aRange); - - if (i >= 0) { - // Range is already in the list, so there is nothing to do! - - return NS_OK; - } } - - // don't need to addref - this call is made by the range object itself - PRBool rv = range_list->AppendElement(aRange); - - return rv ? NS_OK : NS_ERROR_FAILURE; + return rv; } - void nsGenericDOMDataNode::RangeRemove(nsIDOMRange* aRange) { - if (!CouldHaveRangeList()) { - return; - } - - RangeListMapEntry *entry = - NS_STATIC_CAST(RangeListMapEntry *, - PL_DHashTableOperate(&nsGenericElement::sRangeListsHash, - this, PL_DHASH_LOOKUP)); - - // Don't need to release: this call is made by the range object itself. - if (entry && PL_DHASH_ENTRY_IS_BUSY(entry) && - entry->mRangeList->RemoveElement(aRange) && - entry->mRangeList->Count() == 0) { - PL_DHashTableRawRemove(&nsGenericElement::sRangeListsHash, entry); + if (CouldHaveRangeList()) { + nsContentUtils::RemoveFromRangeList(this, aRange); } } const nsVoidArray * nsGenericDOMDataNode::GetRangeList() const { - return LookupRangeList(); + return CouldHaveRangeList() ? nsContentUtils::LookupRangeList(this) : nsnull; } nsIContent * @@ -1349,46 +1272,6 @@ nsGenericDOMDataNode::AppendTextTo(nsAString& aResult) mText.AppendTo(aResult); } -void -nsGenericDOMDataNode::LookupListenerManager(nsIEventListenerManager **aListenerManager) const -{ - *aListenerManager = nsnull; - - if (!CouldHaveEventListenerManager()) { - return; - } - - EventListenerManagerMapEntry *entry = - NS_STATIC_CAST(EventListenerManagerMapEntry *, - PL_DHashTableOperate(&nsGenericElement:: - sEventListenerManagersHash, this, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_BUSY(entry)) { - *aListenerManager = entry->mListenerManager; - NS_ADDREF(*aListenerManager); - } -} - -nsVoidArray * -nsGenericDOMDataNode::LookupRangeList() const -{ - if (!CouldHaveRangeList()) { - return nsnull; - } - - RangeListMapEntry *entry = - NS_STATIC_CAST(RangeListMapEntry *, - PL_DHashTableOperate(&nsGenericElement::sRangeListsHash, - this, PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_BUSY(entry)) { - return entry->mRangeList; - } - - return nsnull; -} - void nsGenericDOMDataNode::SetBidiStatus() { nsIDocument *document = GetCurrentDoc(); diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.h b/mozilla/content/base/src/nsGenericDOMDataNode.h index fd6410d0c18..c9c003acb83 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.h +++ b/mozilla/content/base/src/nsGenericDOMDataNode.h @@ -299,9 +299,6 @@ protected: private: enum { PARENT_BIT_IS_IN_A_HASH = 0x2 }; - void LookupListenerManager(nsIEventListenerManager **aListenerManager) const; - nsVoidArray *LookupRangeList() const; - void SetBidiStatus(); already_AddRefed GetCurrentValueAtom(); @@ -327,12 +324,12 @@ private: PRBool CouldHaveRangeList() const { - return GetIsInAHash() && nsGenericElement::sRangeListsHash.ops; + return GetIsInAHash(); } PRBool CouldHaveEventListenerManager() const { - return GetIsInAHash() && nsGenericElement::sEventListenerManagersHash.ops; + return GetIsInAHash(); } }; diff --git a/mozilla/content/base/src/nsGenericElement.cpp b/mozilla/content/base/src/nsGenericElement.cpp index a8d3bfcbbec..0eadf64cc04 100644 --- a/mozilla/content/base/src/nsGenericElement.cpp +++ b/mozilla/content/base/src/nsGenericElement.cpp @@ -126,8 +126,6 @@ DebugListContentTree(nsIContent* aElement) #endif -PLDHashTable nsGenericElement::sRangeListsHash; -PLDHashTable nsGenericElement::sEventListenerManagersHash; PRInt32 nsIContent::sTabFocusModel = eTabFocus_any; PRBool nsIContent::sTabFocusModelAppliesToXUL = PR_FALSE; nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult); @@ -790,67 +788,6 @@ nsDOMSlots::IsEmpty() return (!mChildNodes && !mStyle && !mAttributeMap && !mBindingParent); } -PR_STATIC_CALLBACK(void) -NopClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) -{ - // Do nothing -} - -// static -void -nsGenericElement::Shutdown() -{ - nsDOMEventRTTearoff::Shutdown(); - - if (sRangeListsHash.ops) { - NS_ASSERTION(sRangeListsHash.entryCount == 0, - "nsGenericElement's range hash not empty at shutdown!"); - - // We're already being shut down and if there are entries left in - // this hash at this point it means we leaked nsGenericElements or - // nsGenericDOMDataNodes. Since we're already partly through the - // shutdown process it's too late to release what's held on to by - // this hash (since the teardown code relies on some things being - // around that aren't around any more) so we rather leak what's - // already leaked in stead of crashing trying to release what - // should've been released much earlier on. - - // Copy the ops out of the hash table - PLDHashTableOps hash_table_ops = *sRangeListsHash.ops; - - // Set the clearEntry hook to be a nop - hash_table_ops.clearEntry = NopClearEntry; - - // Set the ops in the hash table to be the new ops - sRangeListsHash.ops = &hash_table_ops; - - PL_DHashTableFinish(&sRangeListsHash); - - sRangeListsHash.ops = nsnull; - } - - if (sEventListenerManagersHash.ops) { - NS_ASSERTION(sEventListenerManagersHash.entryCount == 0, - "nsGenericElement's event listener manager hash not empty " - "at shutdown!"); - - // See comment above. - - // Copy the ops out of the hash table - PLDHashTableOps hash_table_ops = *sEventListenerManagersHash.ops; - - // Set the clearEntry hook to be a nop - hash_table_ops.clearEntry = NopClearEntry; - - // Set the ops in the hash table to be the new ops - sEventListenerManagersHash.ops = &hash_table_ops; - - PL_DHashTableFinish(&sEventListenerManagersHash); - - sEventListenerManagersHash.ops = nsnull; - } -} - nsGenericElement::nsGenericElement(nsINodeInfo *aNodeInfo) : nsIXMLContent(aNodeInfo), mFlagsOrSlots(GENERIC_ELEMENT_DOESNT_HAVE_DOMSLOTS) @@ -876,38 +813,26 @@ nsGenericElement::~nsGenericElement() if (HasRangeList()) { #ifdef DEBUG - { - RangeListMapEntry *entry = - NS_STATIC_CAST(RangeListMapEntry *, - PL_DHashTableOperate(&sRangeListsHash, this, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_FREE(entry)) { - NS_ERROR("Huh, our bit says we have a range list, but there's nothing " - "in the hash!?!!"); - } + if (!nsContentUtils::LookupRangeList(this) && + nsContentUtils::IsInitialized()) { + NS_ERROR("Huh, our bit says we have a range list, but there's nothing " + "in the hash!?!!"); } #endif - PL_DHashTableOperate(&sRangeListsHash, this, PL_DHASH_REMOVE); + nsContentUtils::RemoveRangeList(this); } if (HasEventListenerManager()) { #ifdef DEBUG - { - EventListenerManagerMapEntry *entry = - NS_STATIC_CAST(EventListenerManagerMapEntry *, - PL_DHashTableOperate(&sEventListenerManagersHash, this, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_FREE(entry)) { - NS_ERROR("Huh, our bit says we have a listener manager list, " - "but there's nothing in the hash!?!!"); - } + if (!nsContentUtils::LookupListenerManager(this) && + nsContentUtils::IsInitialized()) { + NS_ERROR("Huh, our bit says we have a listener manager list, " + "but there's nothing in the hash!?!!"); } #endif - PL_DHashTableOperate(&sEventListenerManagersHash, this, PL_DHASH_REMOVE); + nsContentUtils::RemoveListenerManager(this); } if (HasDOMSlots()) { @@ -919,102 +844,6 @@ nsGenericElement::~nsGenericElement() // No calling GetFlags() beyond this point... } -PR_STATIC_CALLBACK(PRBool) -RangeListHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, - const void *key) -{ - // Initialize the entry with placement new - new (entry) RangeListMapEntry(key); - return PR_TRUE; -} - -PR_STATIC_CALLBACK(void) -RangeListHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) -{ - RangeListMapEntry *r = NS_STATIC_CAST(RangeListMapEntry *, entry); - - // Let the RangeListMapEntry clean itself up... - r->~RangeListMapEntry(); -} - -PR_STATIC_CALLBACK(PRBool) -EventListenerManagerHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, - const void *key) -{ - // Initialize the entry with placement new - new (entry) EventListenerManagerMapEntry(key); - return PR_TRUE; -} - -PR_STATIC_CALLBACK(void) -EventListenerManagerHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) -{ - EventListenerManagerMapEntry *lm = - NS_STATIC_CAST(EventListenerManagerMapEntry *, entry); - - // Let the EventListenerManagerMapEntry clean itself up... - lm->~EventListenerManagerMapEntry(); -} - - -// static -nsresult -nsGenericElement::InitHashes() -{ - NS_ASSERTION(sizeof(PtrBits) == sizeof(void *), - "Eeek! You'll need to adjust the size of PtrBits to the size " - "of a pointer on your platform."); - - if (!sRangeListsHash.ops) { - static PLDHashTableOps hash_table_ops = - { - PL_DHashAllocTable, - PL_DHashFreeTable, - PL_DHashGetKeyStub, - PL_DHashVoidPtrKeyStub, - PL_DHashMatchEntryStub, - PL_DHashMoveEntryStub, - RangeListHashClearEntry, - PL_DHashFinalizeStub, - RangeListHashInitEntry - }; - - if (!PL_DHashTableInit(&sRangeListsHash, &hash_table_ops, nsnull, - sizeof(RangeListMapEntry), 16)) { - sRangeListsHash.ops = nsnull; - - return NS_ERROR_OUT_OF_MEMORY; - } - } - - if (!sEventListenerManagersHash.ops) { - static PLDHashTableOps hash_table_ops = - { - PL_DHashAllocTable, - PL_DHashFreeTable, - PL_DHashGetKeyStub, - PL_DHashVoidPtrKeyStub, - PL_DHashMatchEntryStub, - PL_DHashMoveEntryStub, - EventListenerManagerHashClearEntry, - PL_DHashFinalizeStub, - EventListenerManagerHashInitEntry - }; - - if (!PL_DHashTableInit(&sEventListenerManagersHash, &hash_table_ops, - nsnull, sizeof(EventListenerManagerMapEntry), 16)) { - sEventListenerManagersHash.ops = nsnull; - - PL_DHashTableFinish(&sRangeListsHash); - sRangeListsHash.ops = nsnull; - - return NS_ERROR_OUT_OF_MEMORY; - } - } - - return NS_OK; -} - /** * During the Mark phase of the GC, we need to mark all of the preserved * wrappers that are reachable via DOM APIs. Since reachability for DOM @@ -2168,19 +1997,18 @@ nsGenericElement::HandleDOMEvent(nsPresContext* aPresContext, nsIEventListenerManager *lm = nsnull; if (HasEventListenerManager()) { - EventListenerManagerMapEntry *entry = - NS_STATIC_CAST(EventListenerManagerMapEntry *, - PL_DHashTableOperate(&sEventListenerManagersHash, this, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_FREE(entry)) { - NS_ERROR("Huh, our bit says we have an event listener manager, but " - "there's nothing in the hash!?!!"); + lm = nsContentUtils::LookupListenerManager(NS_STATIC_CAST(nsIXMLContent*, + this)); + if (!lm) { +#ifdef DEBUG + if (nsContentUtils::IsInitialized()) { + NS_ERROR("Huh, our bit says we have an event listener manager, but " + "there's nothing in the hash!?!!"); + } +#endif return NS_ERROR_UNEXPECTED; } - - lm = entry->mListenerManager; } //Local handling stage @@ -2459,62 +2287,18 @@ nsGenericElement::GetBaseURI() const nsresult nsGenericElement::RangeAdd(nsIDOMRange* aRange) { - if (!sRangeListsHash.ops) { - // We've already been shut down, don't bother adding a range... - - return NS_OK; - } - - RangeListMapEntry *entry = - NS_STATIC_CAST(RangeListMapEntry *, - PL_DHashTableOperate(&sRangeListsHash, this, PL_DHASH_ADD)); - - if (!entry) { - return NS_ERROR_OUT_OF_MEMORY; - } - - // lazy allocation of range list - if (!entry->mRangeList) { - NS_ASSERTION(!(GetFlags() & GENERIC_ELEMENT_HAS_RANGELIST), + PRBool created; + nsresult rv = + nsContentUtils::AddToRangeList(NS_STATIC_CAST(nsIXMLContent*, this), + aRange, &created); + if (NS_SUCCEEDED(rv) && created) { + NS_ASSERTION(!HasRangeList(), "Huh, nsGenericElement flags don't reflect reality!!!"); - - entry->mRangeList = new nsAutoVoidArray(); - - if (!entry->mRangeList) { - PL_DHashTableRawRemove(&sRangeListsHash, entry); - - return NS_ERROR_OUT_OF_MEMORY; - } - SetFlags(GENERIC_ELEMENT_HAS_RANGELIST); } - - // Make sure we don't add a range that is already in the list! - PRInt32 i = entry->mRangeList->IndexOf(aRange); - - if (i >= 0) { - // Range is already in the list, so there is nothing to do! - - return NS_OK; - } - - // don't need to addref - this call is made by the range object - // itself - PRBool rv = entry->mRangeList->AppendElement(aRange); - if (!rv) { - if (entry->mRangeList->Count() == 0) { - // Fresh entry, remove it from the hash... - - PL_DHashTableRawRemove(&sRangeListsHash, entry); - } - - return NS_ERROR_OUT_OF_MEMORY; - } - - return NS_OK; + return rv; } - void nsGenericElement::RangeRemove(nsIDOMRange* aRange) { @@ -2522,28 +2306,10 @@ nsGenericElement::RangeRemove(nsIDOMRange* aRange) return; } - RangeListMapEntry *entry = - NS_STATIC_CAST(RangeListMapEntry *, - PL_DHashTableOperate(&sRangeListsHash, this, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_FREE(entry)) { - NS_ERROR("Huh, our bit says we have a range list, but there's nothing " - "in the hash!?!!"); - - return; - } - - if (!entry->mRangeList) { - return; - } - - // don't need to release - this call is made by the range object itself - entry->mRangeList->RemoveElement(aRange); - - if (entry->mRangeList->Count() == 0) { - PL_DHashTableRawRemove(&sRangeListsHash, entry); - + PRBool removed = + nsContentUtils::RemoveFromRangeList(NS_STATIC_CAST(nsIXMLContent*, this), + aRange); + if (removed) { UnsetFlags(GENERIC_ELEMENT_HAS_RANGELIST); } } @@ -2555,19 +2321,14 @@ nsGenericElement::GetRangeList() const return nsnull; } - RangeListMapEntry *entry = - NS_STATIC_CAST(RangeListMapEntry *, - PL_DHashTableOperate(&sRangeListsHash, this, - PL_DHASH_LOOKUP)); + const nsVoidArray* rangeList = + nsContentUtils::LookupRangeList(NS_STATIC_CAST(const nsIXMLContent*, this)); - if (PL_DHASH_ENTRY_IS_FREE(entry)) { - NS_ERROR("Huh, our bit says we have a range list, but there's nothing " - "in the hash!?!!"); + NS_ASSERTION(rangeList || !nsContentUtils::IsInitialized(), + "Huh, our bit says we have a range list, but there's nothing " + "in the hash!?!!"); - return nsnull; - } - - return entry->mRangeList; + return rangeList; } void @@ -2643,44 +2404,14 @@ nsGenericElement::IsContentOfType(PRUint32 aFlags) const nsresult nsGenericElement::GetListenerManager(nsIEventListenerManager **aResult) { - *aResult = nsnull; - - if (!sEventListenerManagersHash.ops) { - // We're already shut down, don't bother creating a event listener - // manager. - - return NS_ERROR_NOT_AVAILABLE; - } - - EventListenerManagerMapEntry *entry = - NS_STATIC_CAST(EventListenerManagerMapEntry *, - PL_DHashTableOperate(&sEventListenerManagersHash, this, - PL_DHASH_ADD)); - - if (!entry) { - return NS_ERROR_OUT_OF_MEMORY; - } - - if (!entry->mListenerManager) { - nsresult rv = - NS_NewEventListenerManager(getter_AddRefs(entry->mListenerManager)); - - if (NS_FAILED(rv)) { - PL_DHashTableRawRemove(&sEventListenerManagersHash, entry); - - return rv; - } - - entry->mListenerManager->SetListenerTarget(NS_STATIC_CAST(nsIXMLContent *, - this)); - + PRBool created; + nsresult rv = + nsContentUtils::GetListenerManager(NS_STATIC_CAST(nsIXMLContent*, this), + aResult, &created); + if (NS_SUCCEEDED(rv) && created) { SetFlags(GENERIC_ELEMENT_HAS_LISTENERMANAGER); } - - *aResult = entry->mListenerManager; - NS_ADDREF(*aResult); - - return NS_OK; + return rv; } // virtual diff --git a/mozilla/content/base/src/nsGenericElement.h b/mozilla/content/base/src/nsGenericElement.h index 509642764fe..19b59dd52fe 100644 --- a/mozilla/content/base/src/nsGenericElement.h +++ b/mozilla/content/base/src/nsGenericElement.h @@ -48,9 +48,7 @@ #include "nsIDOMNSEventTarget.h" #include "nsILinkHandler.h" #include "nsGenericDOMNodeList.h" -#include "nsIEventListenerManager.h" #include "nsContentUtils.h" -#include "pldhash.h" #include "nsAttrAndChildArray.h" class nsIDOMAttr; @@ -66,6 +64,7 @@ class nsVoidArray; class nsINodeInfo; class nsIControllers; class nsIDOMNSFeatureFactory; +class nsIEventListenerManager; typedef unsigned long PtrBits; @@ -175,53 +174,6 @@ public: }; }; -class RangeListMapEntry : public PLDHashEntryHdr -{ -public: - RangeListMapEntry(const void *aKey) - : mKey(aKey), mRangeList(nsnull) - { - } - - ~RangeListMapEntry() - { - delete mRangeList; - } - -private: - const void *mKey; // must be first to look like PLDHashEntryStub - -public: - // We want mRangeList to be an nsAutoVoidArray but we can't make an - // nsAutoVoidArray a direct member of RangeListMapEntry since it - // will be moved around in memory, and nsAutoVoidArray can't deal - // with that. - nsVoidArray *mRangeList; -}; - -class EventListenerManagerMapEntry : public PLDHashEntryHdr -{ -public: - EventListenerManagerMapEntry(const void *aKey) - : mKey(aKey) - { - } - - ~EventListenerManagerMapEntry() - { - if (mListenerManager) { - mListenerManager->Disconnect(); - } - } - -private: - const void *mKey; // must be first, to look like PLDHashEntryStub - -public: - nsCOMPtr mListenerManager; -}; - - /** * A tearoff class for nsGenericElement to implement the nsIDOM3Node functions */ @@ -349,9 +301,6 @@ public: */ nsresult PostQueryInterface(REFNSIID aIID, void** aInstancePtr); - /** Free globals, to be called from module destructor */ - static void Shutdown(); - // nsIDOMGCParticipant interface methods virtual nsIDOMGCParticipant* GetSCCIndex(); virtual void AppendReachableList(nsCOMArray& aArray); @@ -712,11 +661,6 @@ public: nsIDocument* aDocument, nsAttrAndChildArray& aChildArray); - static nsresult InitHashes(); - - static PLDHashTable sEventListenerManagersHash; - static PLDHashTable sRangeListsHash; - /** * Struct that stores info on an attribute. The name and value must * either both be null or both be non-null. @@ -965,15 +909,14 @@ protected: { PtrBits flags = GetFlags(); - return (flags & GENERIC_ELEMENT_HAS_RANGELIST && sRangeListsHash.ops); + return (flags & GENERIC_ELEMENT_HAS_RANGELIST); } PRBool HasEventListenerManager() const { PtrBits flags = GetFlags(); - return (flags & GENERIC_ELEMENT_HAS_LISTENERMANAGER && - sEventListenerManagersHash.ops); + return (flags & GENERIC_ELEMENT_HAS_LISTENERMANAGER); } PRBool HasProperties() const diff --git a/mozilla/content/base/src/nsRange.cpp b/mozilla/content/base/src/nsRange.cpp index 84e69fc03a7..355a86cf64e 100644 --- a/mozilla/content/base/src/nsRange.cpp +++ b/mozilla/content/base/src/nsRange.cpp @@ -2250,7 +2250,7 @@ nsresult nsRange::OwnerChildReplaced(nsIContent* aParentNode, PRInt32 aOffset, n nsresult -nsRange::TextOwnerChanged(nsIContent* aTextNode, nsVoidArray *aRangeList, +nsRange::TextOwnerChanged(nsIContent* aTextNode, const nsVoidArray *aRangeList, PRInt32 aStartChanged, PRInt32 aEndChanged, PRInt32 aReplaceLength) { diff --git a/mozilla/content/base/src/nsRange.h b/mozilla/content/base/src/nsRange.h index ea2e92ab5c9..d3b7ce729b3 100644 --- a/mozilla/content/base/src/nsRange.h +++ b/mozilla/content/base/src/nsRange.h @@ -120,7 +120,7 @@ public: static NS_METHOD OwnerChildReplaced(nsIContent* aParentNode, PRInt32 aOffset, nsIContent* aReplacedNode); static nsresult TextOwnerChanged(nsIContent *aTextNode, - nsVoidArray *aRangeList, + const nsVoidArray *aRangeList, PRInt32 aStartOffset, PRInt32 aEndOffset, PRInt32 aReplaceLength); diff --git a/mozilla/content/html/content/src/nsHTMLInputElement.cpp b/mozilla/content/html/content/src/nsHTMLInputElement.cpp index 79540c63008..0ccfebd4d0b 100644 --- a/mozilla/content/html/content/src/nsHTMLInputElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLInputElement.cpp @@ -89,6 +89,7 @@ #include "nsIDOMMutationEvent.h" #include "nsIDOMEventReceiver.h" #include "nsMutationEvent.h" +#include "nsIEventListenerManager.h" #include "nsRuleData.h" diff --git a/mozilla/content/svg/content/src/nsSVGElement.cpp b/mozilla/content/svg/content/src/nsSVGElement.cpp index 57fd365e9ae..2566d2487b4 100644 --- a/mozilla/content/svg/content/src/nsSVGElement.cpp +++ b/mozilla/content/svg/content/src/nsSVGElement.cpp @@ -65,6 +65,7 @@ #include "nsGenericHTMLElement.h" #include "nsNodeInfoManager.h" #include "nsIScriptGlobalObject.h" +#include "nsIEventListenerManager.h" nsSVGElement::nsSVGElement(nsINodeInfo *aNodeInfo) : nsGenericElement(aNodeInfo) diff --git a/mozilla/layout/build/nsLayoutModule.cpp b/mozilla/layout/build/nsLayoutModule.cpp index b5a2a3776d5..18b45c57573 100644 --- a/mozilla/layout/build/nsLayoutModule.cpp +++ b/mozilla/layout/build/nsLayoutModule.cpp @@ -131,6 +131,7 @@ // Transformiix stuff #include "nsXPathEvaluator.h" #include "txMozillaXSLTProcessor.h" +#include "txXSLTProcessor.h" #include "nsXPath1Scheme.h" #include "nsXFormsXPathEvaluator.h" @@ -281,6 +282,10 @@ Initialize(nsIModule* aSelf) return NS_OK; } + NS_ASSERTION(sizeof(PtrBits) == sizeof(void *), + "Eeek! You'll need to adjust the size of PtrBits to the size " + "of a pointer on your platform."); + gInitialized = PR_TRUE; nsJSEnvironment::Startup(); @@ -390,7 +395,7 @@ Shutdown() txXSLTProcessor::shutdown(); nsDOMAttribute::Shutdown(); nsRange::Shutdown(); - nsGenericElement::Shutdown(); + nsDOMEventRTTearoff::Shutdown(); nsEventListenerManager::Shutdown(); nsContentList::Shutdown(); nsComputedDOMStyle::Shutdown(); diff --git a/mozilla/parser/htmlparser/src/CParserContext.cpp b/mozilla/parser/htmlparser/src/CParserContext.cpp index e716208e1ec..2a184fea40b 100644 --- a/mozilla/parser/htmlparser/src/CParserContext.cpp +++ b/mozilla/parser/htmlparser/src/CParserContext.cpp @@ -43,7 +43,6 @@ #include "prenv.h" #include "nsIHTMLContentSink.h" #include "nsHTMLTokenizer.h" -#include "nsExpatDriver.h" MOZ_DECL_CTOR_COUNTER(CParserContext)