Fix for bug 649057 (Make all nsINodeLists inherit from nsWrapperCache). r=bz.

--HG--
extra : rebase_source : 38dc8fd49822774a1ee356ab8496e2c0b908bab9
This commit is contained in:
Peter Van der Beken 2009-06-16 08:32:10 +02:00
parent eb0c1061d1
commit 66ada9b2d0
15 changed files with 111 additions and 80 deletions

View File

@ -565,7 +565,7 @@ public:
* since this can happen due to content fixup when a form spans table rows or
* table cells.
*/
static PRBool BelongsInForm(nsIDOMHTMLFormElement *aForm,
static PRBool BelongsInForm(nsIContent *aForm,
nsIContent *aContent);
static nsresult CheckQName(const nsAString& aQualifiedName,

View File

@ -39,19 +39,22 @@
#define nsINodeList_h___
#include "nsIDOMNodeList.h"
#include "nsWrapperCache.h"
class nsINode;
class nsIContent;
// IID for the nsINodeList interface
#define NS_INODELIST_IID \
{ 0x57ac9ea2, 0xe95f, 0x4856, \
{ 0xbb, 0xac, 0x82, 0x2d, 0x65, 0xb1, 0x92, 0x57 } }
{ 0xa842c1b5, 0x9a6f, 0x4afa, \
{ 0x9c, 0x1c, 0xf5, 0xf7, 0xdc, 0x70, 0x82, 0xd9 } }
/**
* An internal interface that allows QI-less getting of nodes from
* node lists and reasonably fast indexOf.
*/
class nsINodeList : public nsIDOMNodeList
class nsINodeList : public nsIDOMNodeList,
public nsWrapperCache
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_INODELIST_IID)
@ -66,6 +69,11 @@ public:
* is not in the list.
*/
virtual PRInt32 IndexOf(nsIContent* aContent) = 0;
/**
* Get the root node for this nodelist.
*/
virtual nsINode* GetParentObject() = 0;
};
#define NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(_class) \

View File

@ -90,6 +90,7 @@ DOMCI_DATA(NodeList, nsBaseContentList)
// QueryInterface implementation for nsBaseContentList
NS_INTERFACE_TABLE_HEAD(nsBaseContentList)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsBaseContentList)
NS_CONTENT_LIST_INTERFACES(nsBaseContentList)
NS_OFFSET_AND_INTERFACE_TABLE_END
@ -160,17 +161,34 @@ void nsBaseContentList::InsertElementAt(nsIContent* aContent, PRInt32 aIndex)
mElements.InsertObjectAt(aContent, aIndex);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsSimpleContentList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsSimpleContentList,
nsBaseContentList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsSimpleContentList,
nsBaseContentList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRoot)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsSimpleContentList)
NS_INTERFACE_MAP_END_INHERITING(nsBaseContentList)
NS_IMPL_ADDREF_INHERITED(nsSimpleContentList, nsBaseContentList)
NS_IMPL_RELEASE_INHERITED(nsSimpleContentList, nsBaseContentList)
// nsFormContentList
nsFormContentList::nsFormContentList(nsIDOMHTMLFormElement *aForm,
nsFormContentList::nsFormContentList(nsIContent *aForm,
nsBaseContentList& aContentList)
: nsBaseContentList()
: nsSimpleContentList(aForm)
{
// move elements that belong to mForm into this content list
PRUint32 i, length = 0;
aContentList.GetLength(&length);
for (i = 0; i < length; i++) {
@ -475,7 +493,6 @@ DOMCI_DATA(ContentList, nsContentList)
// QueryInterface implementation for nsContentList
NS_INTERFACE_TABLE_HEAD(nsContentList)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsContentList)
NS_CONTENT_LIST_INTERFACES(nsContentList)
NS_INTERFACE_TABLE_ENTRY(nsContentList, nsIHTMLCollection)

View File

@ -74,7 +74,6 @@ typedef PRBool (*nsContentListMatchFunc)(nsIContent* aContent,
typedef void (*nsContentListDestroyFunc)(void* aData);
class nsIDocument;
class nsIDOMHTMLFormElement;
class nsBaseContentList : public nsINodeList
@ -126,13 +125,35 @@ protected:
};
class nsSimpleContentList : public nsBaseContentList
{
public:
nsSimpleContentList(nsINode *aRoot) : nsBaseContentList(),
mRoot(aRoot)
{
}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsSimpleContentList,
nsBaseContentList)
virtual nsINode* GetParentObject()
{
return mRoot;
}
private:
// This has to be a strong reference, the root might go away before the list.
nsCOMPtr<nsINode> mRoot;
};
// This class is used only by form element code and this is a static
// list of elements. NOTE! This list holds strong references to
// the elements in the list.
class nsFormContentList : public nsBaseContentList
class nsFormContentList : public nsSimpleContentList
{
public:
nsFormContentList(nsIDOMHTMLFormElement *aForm,
nsFormContentList(nsIContent *aForm,
nsBaseContentList& aContentList);
};
@ -197,8 +218,7 @@ struct nsContentListKey
*/
class nsContentList : public nsBaseContentList,
public nsIHTMLCollection,
public nsStubMutationObserver,
public nsWrapperCache
public nsStubMutationObserver
{
public:
NS_DECL_ISUPPORTS_INHERITED
@ -258,6 +278,10 @@ public:
virtual PRInt32 IndexOf(nsIContent *aContent, PRBool aDoFlush);
virtual nsIContent* GetNodeAt(PRUint32 aIndex);
virtual PRInt32 IndexOf(nsIContent* aContent);
virtual nsINode* GetParentObject()
{
return mRootNode;
}
// nsIHTMLCollection
// GetNodeAt already declared as part of nsINodeList
@ -265,7 +289,6 @@ public:
nsWrapperCache** aCache);
// nsContentList public methods
NS_HIDDEN_(nsINode*) GetParentObject() { return mRootNode; }
NS_HIDDEN_(PRUint32) Length(PRBool aDoFlush);
NS_HIDDEN_(nsIContent*) Item(PRUint32 aIndex, PRBool aDoFlush);
NS_HIDDEN_(nsIContent*) NamedItem(const nsAString& aName, PRBool aDoFlush);

View File

@ -2213,21 +2213,13 @@ nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
// static
PRBool
nsContentUtils::BelongsInForm(nsIDOMHTMLFormElement *aForm,
nsContentUtils::BelongsInForm(nsIContent *aForm,
nsIContent *aContent)
{
NS_PRECONDITION(aForm, "Must have a form");
NS_PRECONDITION(aContent, "Must have a content node");
nsCOMPtr<nsIContent> form(do_QueryInterface(aForm));
if (!form) {
NS_ERROR("This should not happen, form is not an nsIContent!");
return PR_TRUE;
}
if (form == aContent) {
if (aForm == aContent) {
// A form does not belong inside itself, so we return false here
return PR_FALSE;
@ -2236,7 +2228,7 @@ nsContentUtils::BelongsInForm(nsIDOMHTMLFormElement *aForm,
nsIContent* content = aContent->GetParent();
while (content) {
if (content == form) {
if (content == aForm) {
// aContent is contained within the form so we return true.
return PR_TRUE;
@ -2253,7 +2245,7 @@ nsContentUtils::BelongsInForm(nsIDOMHTMLFormElement *aForm,
content = content->GetParent();
}
if (form->GetChildCount() > 0) {
if (aForm->GetChildCount() > 0) {
// The form is a container but aContent wasn't inside the form,
// return false
@ -2264,7 +2256,7 @@ nsContentUtils::BelongsInForm(nsIDOMHTMLFormElement *aForm,
// we check whether the content comes after the form. If it does,
// return true. If it does not, then it couldn't have been inside
// the form in the HTML.
if (PositionIsBefore(form, aContent)) {
if (PositionIsBefore(aForm, aContent)) {
// We could be in this form!
// In the future, we may want to get document.forms, look at the
// form after aForm, and if aContent is after that form after

View File

@ -215,7 +215,7 @@ static PRLogModuleInfo* gDocumentLeakPRLog;
static PRLogModuleInfo* gCspPRLog;
#endif
#define NAME_NOT_VALID ((nsBaseContentList*)1)
#define NAME_NOT_VALID ((nsSimpleContentList*)1)
nsIdentifierMapEntry::~nsIdentifierMapEntry()
{
@ -423,10 +423,10 @@ nsIdentifierMapEntry::SetImageElement(Element* aElement)
}
void
nsIdentifierMapEntry::AddNameElement(Element* aElement)
nsIdentifierMapEntry::AddNameElement(nsIDocument* aDocument, Element* aElement)
{
if (!mNameContentList) {
mNameContentList = new nsBaseContentList();
mNameContentList = new nsSimpleContentList(aDocument);
}
mNameContentList->AppendElement(aElement);
@ -2559,7 +2559,7 @@ nsDocument::AddToNameTable(Element *aElement, nsIAtom* aName)
// Null for out-of-memory
if (entry) {
entry->AddNameElement(aElement);
entry->AddNameElement(this, aElement);
}
}
@ -2846,7 +2846,7 @@ nsDocument::NodesFromRectHelper(float aX, float aY,
{
NS_ENSURE_ARG_POINTER(aReturn);
nsBaseContentList* elements = new nsBaseContentList();
nsSimpleContentList* elements = new nsSimpleContentList(this);
NS_ADDREF(elements);
*aReturn = elements;

View File

@ -167,7 +167,7 @@ public:
void SetInvalidName();
PRBool IsInvalidName();
void AddNameElement(Element* aElement);
void AddNameElement(nsIDocument* aDocument, Element* aElement);
void RemoveNameElement(Element* aElement);
PRBool IsEmpty();
nsBaseContentList* GetNameContentList() {

View File

@ -3079,7 +3079,7 @@ nsGenericElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
already_AddRefed<nsINodeList>
nsGenericElement::GetChildren(PRUint32 aFilter)
{
nsRefPtr<nsBaseContentList> list = new nsBaseContentList();
nsRefPtr<nsSimpleContentList> list = new nsSimpleContentList(this);
if (!list) {
return nsnull;
}
@ -5528,7 +5528,7 @@ nsGenericElement::doQuerySelectorAll(nsINode* aRoot,
{
NS_PRECONDITION(aReturn, "Null out param?");
nsBaseContentList* contentList = new nsBaseContentList();
nsSimpleContentList* contentList = new nsSimpleContentList(aRoot);
NS_ENSURE_TRUE(contentList, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aReturn = contentList);

View File

@ -95,8 +95,7 @@ typedef PRUptrdiff PtrBits;
* and Item to its existing child list.
* @see nsIDOMNodeList
*/
class nsChildContentList : public nsINodeList,
public nsWrapperCache
class nsChildContentList : public nsINodeList
{
public:
nsChildContentList(nsINode* aNode)
@ -118,27 +117,11 @@ public:
mNode = nsnull;
}
nsINode* GetParentObject()
virtual nsINode* GetParentObject()
{
return mNode;
}
static nsChildContentList* FromSupports(nsISupports* aSupports)
{
nsINodeList* list = static_cast<nsINodeList*>(aSupports);
#ifdef DEBUG
{
nsCOMPtr<nsINodeList> list_qi = do_QueryInterface(aSupports);
// If this assertion fires the QI implementation for the object in
// question doesn't use the nsINodeList pointer as the nsISupports
// pointer. That must be fixed, or we'll crash...
NS_ASSERTION(list_qi == list, "Uh, fix QI!");
}
#endif
return static_cast<nsChildContentList*>(list);
}
private:
// The node whose children make up the list (weak reference)
nsINode* mNode;

View File

@ -2387,7 +2387,7 @@ nsFormControlList::AddElementToTable(nsGenericHTMLFormElement* aChild,
// Found an element, create a list, add the element to the list and put
// the list in the hash
nsBaseContentList *list = new nsBaseContentList();
nsSimpleContentList *list = new nsSimpleContentList(mForm);
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
NS_ASSERTION(content->GetParent(), "Item in list without parent");
@ -2411,7 +2411,7 @@ nsFormControlList::AddElementToTable(nsGenericHTMLFormElement* aChild,
NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
// Upcast, uggly, but it works!
nsBaseContentList *list = static_cast<nsBaseContentList *>
nsSimpleContentList *list = static_cast<nsSimpleContentList *>
((nsIDOMNodeList *)nodeList.get());
NS_ASSERTION(list->Length() > 1,

View File

@ -2522,7 +2522,7 @@ nsHTMLDocument::GetPlugins(nsIDOMHTMLCollection** aPlugins)
nsresult
nsHTMLDocument::ResolveName(const nsAString& aName,
nsIDOMHTMLFormElement *aForm,
nsIContent *aForm,
nsISupports **aResult,
nsWrapperCache **aCache)
{

View File

@ -168,7 +168,7 @@ public:
NS_DECL_NSIDOMNSHTMLDOCUMENT
virtual nsresult ResolveName(const nsAString& aName,
nsIDOMHTMLFormElement *aForm,
nsIContent *aForm,
nsISupports **aResult,
nsWrapperCache **aCache);

View File

@ -55,8 +55,8 @@ class Element;
} // namespace mozilla
#define NS_IHTMLDOCUMENT_IID \
{ 0xe43a4bfd, 0xff5a, 0x40b0, \
{ 0x8c, 0x31, 0x24, 0xac, 0xe8, 0x15, 0xda, 0xf2 } }
{ 0x8cc90664, 0xb0fe, 0x4cdb, \
{ 0xa2, 0xdd, 0x25, 0xcd, 0x8c, 0x2b, 0xfd, 0x08 } }
/**
@ -75,7 +75,7 @@ public:
virtual void SetCompatibilityMode(nsCompatibility aMode) = 0;
virtual nsresult ResolveName(const nsAString& aName,
nsIDOMHTMLFormElement *aForm,
nsIContent *aForm,
nsISupports **aResult,
nsWrapperCache **aCache) = 0;

View File

@ -93,7 +93,7 @@
class nsAnonymousContentList : public nsINodeList
{
public:
nsAnonymousContentList(nsInsertionPointList* aElements);
nsAnonymousContentList(nsIContent *aContent, nsInsertionPointList* aElements);
virtual ~nsAnonymousContentList();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@ -104,6 +104,10 @@ public:
// nsINodeList interface
virtual nsIContent* GetNodeAt(PRUint32 aIndex);
virtual PRInt32 IndexOf(nsIContent* aContent);
virtual nsINode *GetParentObject()
{
return mContent;
}
PRInt32 GetInsertionPointCount() { return mElements->Length(); }
@ -111,14 +115,17 @@ public:
void RemoveInsertionPointAt(PRInt32 i) { mElements->RemoveElementAt(i); }
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ANONYMOUS_CONTENT_LIST_IID)
private:
nsCOMPtr<nsIContent> mContent;
nsInsertionPointList* mElements;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsAnonymousContentList,
NS_ANONYMOUS_CONTENT_LIST_IID)
nsAnonymousContentList::nsAnonymousContentList(nsInsertionPointList* aElements)
: mElements(aElements)
nsAnonymousContentList::nsAnonymousContentList(nsIContent *aContent,
nsInsertionPointList* aElements)
: mContent(aContent),
mElements(aElements)
{
MOZ_COUNT_CTOR(nsAnonymousContentList);
@ -149,10 +156,12 @@ NS_INTERFACE_TABLE_HEAD(nsAnonymousContentList)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsAnonymousContentList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContent)
tmp->mElements->Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsAnonymousContentList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContent)
{
PRInt32 i, count = tmp->mElements->Length();
for (i = 0; i < count; ++i) {
@ -710,7 +719,7 @@ nsBindingManager::SetContentListFor(nsIContent* aContent,
nsAnonymousContentList* contentList = nsnull;
if (aList) {
contentList = new nsAnonymousContentList(aList);
contentList = new nsAnonymousContentList(aContent, aList);
if (!contentList) {
delete aList;
return NS_ERROR_OUT_OF_MEMORY;
@ -774,7 +783,7 @@ nsBindingManager::SetAnonymousNodesFor(nsIContent* aContent,
nsAnonymousContentList* contentList = nsnull;
if (aList) {
contentList = new nsAnonymousContentList(aList);
contentList = new nsAnonymousContentList(aContent, aList);
if (!contentList) {
delete aList;
return NS_ERROR_OUT_OF_MEMORY;

View File

@ -8222,19 +8222,19 @@ nsresult
nsNodeListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj)
{
nsWrapperCache* cache = nsnull;
CallQueryInterface(nativeObj, &cache);
if (!cache) {
return nsDOMClassInfo::PreCreate(nativeObj, cx, globalObj, parentObj);
}
nsINodeList* list = static_cast<nsINodeList*>(nativeObj);
#ifdef DEBUG
{
nsCOMPtr<nsINodeList> list_qi = do_QueryInterface(nativeObj);
// nsChildContentList is the only class that uses nsNodeListSH and has a
// cached wrapper.
nsChildContentList *list = nsChildContentList::FromSupports(nativeObj);
nsINode *native_parent = list->GetParentObject();
if (!native_parent) {
return NS_ERROR_FAILURE;
// If this assertion fires the QI implementation for the object in
// question doesn't use the nsINodeList pointer as the nsISupports
// pointer. That must be fixed, or we'll crash...
NS_ASSERTION(list_qi == list, "Uh, fix QI!");
}
#endif
nsINode* native_parent = list->GetParentObject();
nsresult rv =
WrapNativeParent(cx, globalObj, native_parent, native_parent, parentObj);
@ -9426,13 +9426,12 @@ nsHTMLFormElementSH::FindNamedItem(nsIForm *aForm, jsid id,
if (!*aResult) {
nsCOMPtr<nsIContent> content(do_QueryInterface(aForm));
nsCOMPtr<nsIDOMHTMLFormElement> form_element(do_QueryInterface(aForm));
nsCOMPtr<nsIHTMLDocument> html_doc =
do_QueryInterface(content->GetDocument());
if (html_doc && form_element) {
html_doc->ResolveName(name, form_element, aResult, aCache);
if (html_doc && content) {
html_doc->ResolveName(name, content, aResult, aCache);
}
}