зеркало из https://github.com/mozilla/pjs.git
Fixing bug 348062. Making nsContentList hold strong references to the nodes in the list. r+sr=bzbarsky@mit.edu
This commit is contained in:
Родитель
287e875ca9
Коммит
f922b83b05
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче