Fixing bug 348062. Making nsContentList hold strong references to the nodes in the list. r+sr=bzbarsky@mit.edu

This commit is contained in:
jst%mozilla.jstenback.com 2006-08-25 17:45:25 +00:00
Родитель 988d792046
Коммит 95c7fd00f8
6 изменённых файлов: 49 добавлений и 77 удалений

Просмотреть файл

@ -77,8 +77,6 @@ nsBaseContentList::nsBaseContentList()
nsBaseContentList::~nsBaseContentList()
{
// mElements only has weak references to the content objects so we
// don't need to do any cleanup here.
}
@ -105,8 +103,8 @@ nsBaseContentList::GetLength(PRUint32* aLength)
NS_IMETHODIMP
nsBaseContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
{
nsISupports *tmp = NS_REINTERPRET_CAST(nsISupports *,
mElements.SafeElementAt(aIndex));
nsISupports *tmp = mElements.SafeObjectAt(aIndex);
if (!tmp) {
*aReturn = nsnull;
@ -119,15 +117,13 @@ nsBaseContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
void
nsBaseContentList::AppendElement(nsIContent *aContent)
{
// Shouldn't hold a reference since we'll be told when the content
// leaves the root or the root will be destroyed.
mElements.AppendElement(aContent);
mElements.AppendObject(aContent);
}
void
nsBaseContentList::RemoveElement(nsIContent *aContent)
{
mElements.RemoveElement(aContent);
mElements.RemoveObject(aContent);
}
PRInt32
@ -175,47 +171,6 @@ nsFormContentList::nsFormContentList(nsIDOMHTMLFormElement *aForm,
}
}
nsFormContentList::~nsFormContentList()
{
Reset();
}
void
nsFormContentList::AppendElement(nsIContent *aContent)
{
NS_ADDREF(aContent);
nsBaseContentList::AppendElement(aContent);
}
void
nsFormContentList::RemoveElement(nsIContent *aContent)
{
PRInt32 i = mElements.IndexOf(aContent);
if (i >= 0) {
nsIContent *content = NS_STATIC_CAST(nsIContent *, mElements.ElementAt(i));
NS_RELEASE(content);
mElements.RemoveElementAt(i);
}
}
void
nsFormContentList::Reset()
{
PRInt32 i, length = mElements.Count();
for (i = 0; i < length; i++) {
nsIContent *content = NS_STATIC_CAST(nsIContent *, mElements.ElementAt(i));
NS_RELEASE(content);
}
nsBaseContentList::Reset();
}
// Hashtable for storing nsContentLists
static PLDHashTable gContentListHashTable;
@ -439,7 +394,7 @@ nsContentList::Item(PRUint32 aIndex, PRBool aDoFlush)
NS_ASSERTION(!mRootNode || mState != LIST_DIRTY,
"PopulateSelf left the list in a dirty (useless) state!");
return NS_STATIC_CAST(nsIContent *, mElements.SafeElementAt(aIndex));
return mElements.SafeObjectAt(aIndex);
}
nsIContent *
@ -454,8 +409,7 @@ nsContentList::NamedItem(const nsAString& aName, PRBool aDoFlush)
NS_ENSURE_TRUE(name, nsnull);
for (i = 0; i < count; i++) {
nsIContent *content = NS_STATIC_CAST(nsIContent *,
mElements.ElementAt(i));
nsIContent *content = mElements[i];
// XXX Should this pass eIgnoreCase?
if (content &&
(content->AttrValueIs(kNameSpaceID_None, nsHTMLAtoms::name,
@ -494,6 +448,21 @@ nsContentList::NodeWillBeDestroyed(const nsINode* aNode)
Reset();
}
// static
void
nsContentList::OnDocumentDestroy(nsIDocument *aDocument)
{
// If our content list cache holds a list used for a document that's
// now being destroyed, free the cache to prevent the list from
// staying around until the next use of content lists ends up
// replacing what's in the cache.
if (gCachedContentList && gCachedContentList->mRootNode &&
gCachedContentList->mRootNode->GetOwnerDoc() == aDocument) {
NS_RELEASE(gCachedContentList);
}
}
NS_IMETHODIMP
nsContentList::GetLength(PRUint32* aLength)
{
@ -553,10 +522,11 @@ nsContentList::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
mState = LIST_DIRTY;
}
} else {
// We no longer match aContent. Remove it from our list. If
// it's already not there, this is a no-op, which is fine.
// Either way, no change of mState is required here.
mElements.RemoveElement(aContent);
// We no longer match aContent. Remove it from our list. If it's
// already not there, this is a no-op (though a potentially
// expensive one). Either way, no change of mState is required
// here.
mElements.RemoveObject(aContent);
}
}
@ -593,8 +563,7 @@ nsContentList::ContentAppended(nsIDocument *aDocument, nsIContent* aContainer,
if (ourCount == 0) {
appendToList = PR_TRUE;
} else {
nsIContent* ourLastContent =
NS_STATIC_CAST(nsIContent*, mElements.ElementAt(ourCount - 1));
nsIContent* ourLastContent = mElements[ourCount - 1];
/*
* We want to append instead of invalidating if the first thing
* that got appended comes after ourLastContent.
@ -748,7 +717,7 @@ nsContentList::PopulateWith(nsIContent *aContent, PRUint32& aElementsToAppend)
"We should never be trying to match mRootNode");
if (Match(aContent)) {
mElements.AppendElement(aContent);
mElements.AppendObject(aContent);
--aElementsToAppend;
if (aElementsToAppend == 0)
return;
@ -838,8 +807,7 @@ nsContentList::PopulateSelf(PRUint32 aNeededLength)
// If we already have nodes start searching at the last one, otherwise
// start searching at the root.
nsINode* startRoot = count == 0 ? mRootNode :
NS_STATIC_CAST(nsIContent*, mElements.ElementAt(count - 1));
nsINode* startRoot = count == 0 ? mRootNode : mElements[count - 1];
PopulateWithStartingAfter(startRoot, nsnull, elementsToAppend);
NS_ASSERTION(elementsToAppend + mElements.Count() == invariant,

Просмотреть файл

@ -45,7 +45,7 @@
#define nsContentList_h___
#include "nsISupports.h"
#include "nsVoidArray.h"
#include "nsCOMArray.h"
#include "nsString.h"
#include "nsIDOMHTMLCollection.h"
#include "nsIDOMNodeList.h"
@ -89,7 +89,7 @@ public:
static void Shutdown();
protected:
nsAutoVoidArray mElements;
nsCOMArray<nsIContent> mElements;
};
@ -101,12 +101,6 @@ class nsFormContentList : public nsBaseContentList
public:
nsFormContentList(nsIDOMHTMLFormElement *aForm,
nsBaseContentList& aContentList);
virtual ~nsFormContentList();
virtual void AppendElement(nsIContent *aContent);
virtual void RemoveElement(nsIContent *aContent);
virtual void Reset();
};
/**
@ -236,6 +230,8 @@ public:
nsIContent* aChild, PRInt32 aIndexInContainer);
virtual void NodeWillBeDestroyed(const nsINode *aNode);
static void OnDocumentDestroy(nsIDocument *aDocument);
protected:
/**
* Returns whether the content element matches our criterion

Просмотреть файл

@ -4347,7 +4347,8 @@ nsDocument::DispatchEvent(nsIDOMEvent* aEvent, PRBool *_retval)
nsEventStatus status = nsEventStatus_eIgnore;
nsresult rv =
nsEventDispatcher::DispatchDOMEvent(NS_STATIC_CAST(nsINode*, this),
nsnull, aEvent, context, &status);
nsnull, aEvent, context, &status,
PR_FALSE);
*_retval = (status != nsEventStatus_eConsumeNoDefault);
return rv;
@ -5151,6 +5152,8 @@ nsDocument::Destroy()
}
mLayoutHistoryState = nsnull;
nsContentList::OnDocumentDestroy(this);
}
already_AddRefed<nsILayoutHistoryState>

Просмотреть файл

@ -428,7 +428,8 @@ nsGenericDOMDataNode::AppendData(const nsAString& aData)
mutation.mPrevAttrValue = oldValue;
mutation.mNewAttrValue = GetCurrentValueAtom();
nsEventDispatcher::Dispatch(this, nsnull, &mutation);
nsEventDispatcher::Dispatch(this, nsnull, &mutation, nsnull, nsnull, nsnull,
PR_FALSE, PR_FALSE);
}
// Notify observers
@ -1000,7 +1001,8 @@ nsGenericDOMDataNode::SetText(const PRUnichar* aBuffer,
do_GetAtom(Substring(aBuffer, aBuffer + aLength));
}
nsEventDispatcher::Dispatch(this, nsnull, &mutation);
nsEventDispatcher::Dispatch(this, nsnull, &mutation, nsnull, nsnull, nsnull,
PR_FALSE, PR_FALSE);
}
// Trigger a reflow

Просмотреть файл

@ -2422,7 +2422,8 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEINSERTED);
mutation.mRelatedNode = do_QueryInterface(container);
nsEventDispatcher::Dispatch(aKid, nsnull, &mutation);
nsEventDispatcher::Dispatch(aKid, nsnull, &mutation, nsnull, nsnull,
nsnull, PR_FALSE, PR_FALSE);
}
}
@ -2471,7 +2472,8 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEREMOVED);
mutation.mRelatedNode = do_QueryInterface(container);
nsEventDispatcher::Dispatch(aKid, nsnull, &mutation);
nsEventDispatcher::Dispatch(aKid, nsnull, &mutation, nsnull, nsnull,
nsnull, PR_FALSE, PR_FALSE);
}
// Someone may have removed the kid or any of its siblings while that event
@ -3411,7 +3413,8 @@ nsGenericElement::SetAttrAndNotify(PRInt32 aNamespaceID,
mutation.mPrevAttrValue = do_GetAtom(aOldValue);
}
mutation.mAttrChange = modType;
nsEventDispatcher::Dispatch(this, nsnull, &mutation);
nsEventDispatcher::Dispatch(this, nsnull, &mutation, nsnull, nsnull,
nsnull, PR_FALSE, PR_FALSE);
}
if (aNotify) {
@ -3611,7 +3614,8 @@ nsGenericElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
mutation.mPrevAttrValue = do_GetAtom(value);
mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
nsEventDispatcher::Dispatch(this, nsnull, &mutation);
nsEventDispatcher::Dispatch(this, nsnull, &mutation, nsnull, nsnull, nsnull,
PR_FALSE, PR_FALSE);
}
// Clear binding to nsIDOMNamedNodeMap

Просмотреть файл

@ -64,7 +64,6 @@ nsCOMArray_base::~nsCOMArray_base()
PRInt32
nsCOMArray_base::IndexOfObject(nsISupports* aObject) const {
NS_ENSURE_TRUE(aObject, -1);
nsCOMPtr<nsISupports> supports = do_QueryInterface(aObject);
NS_ENSURE_TRUE(supports, -1);