diff --git a/mozilla/content/base/public/nsINode.h b/mozilla/content/base/public/nsINode.h index 1a52203b170..acf8c0b27ca 100644 --- a/mozilla/content/base/public/nsINode.h +++ b/mozilla/content/base/public/nsINode.h @@ -112,6 +112,8 @@ public: class nsINode : public nsINode_base { public: friend class nsNodeUtils; + friend class nsNodeWeakReference; + friend class nsNodeSupportsWeakRefTearoff; #ifdef MOZILLA_INTERNAL_API nsINode(nsINodeInfo* aNodeInfo) @@ -551,7 +553,8 @@ public: public: nsSlots(PtrBits aFlags) : mFlags(aFlags), - mChildNodes(nsnull) + mChildNodes(nsnull), + mWeakReference(nsnull) { } @@ -579,6 +582,11 @@ public: * MSVC 7 doesn't like this as an nsRefPtr */ nsChildContentList* mChildNodes; + + /** + * Weak reference to this node + */ + nsNodeWeakReference* mWeakReference; }; #ifdef DEBUG diff --git a/mozilla/content/base/src/nsDOMAttribute.cpp b/mozilla/content/base/src/nsDOMAttribute.cpp index 7afc906b0e1..3338c06adf6 100644 --- a/mozilla/content/base/src/nsDOMAttribute.cpp +++ b/mozilla/content/base/src/nsDOMAttribute.cpp @@ -81,6 +81,8 @@ NS_INTERFACE_MAP_BEGIN(nsDOMAttribute) NS_INTERFACE_MAP_ENTRY(nsIDOMNode) NS_INTERFACE_MAP_ENTRY(nsIDOM3Node) NS_INTERFACE_MAP_ENTRY(nsIDOM3Attr) + NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference, + new nsNodeSupportsWeakRefTearoff(this)) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMAttr) NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(Attr) NS_INTERFACE_MAP_END diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.cpp b/mozilla/content/base/src/nsGenericDOMDataNode.cpp index bfa97e0a97e..131c58fd488 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.cpp +++ b/mozilla/content/base/src/nsGenericDOMDataNode.cpp @@ -93,6 +93,8 @@ NS_INTERFACE_MAP_BEGIN(nsGenericDOMDataNode) nsDOMEventRTTearoff::Create(this)) NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNSEventTarget, nsDOMEventRTTearoff::Create(this)) + NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference, + new nsNodeSupportsWeakRefTearoff(this)) NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOM3Node, new nsNode3Tearoff(this)) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent) NS_INTERFACE_MAP_END diff --git a/mozilla/content/base/src/nsGenericElement.cpp b/mozilla/content/base/src/nsGenericElement.cpp index a7cd24b3fa7..1de36b270c8 100644 --- a/mozilla/content/base/src/nsGenericElement.cpp +++ b/mozilla/content/base/src/nsGenericElement.cpp @@ -144,6 +144,10 @@ nsINode::nsSlots::~nsSlots() mChildNodes->DropReference(); NS_RELEASE(mChildNodes); } + + if (mWeakReference) { + mWeakReference->NoticeNodeDestruction(); + } } //---------------------------------------------------------------------- @@ -609,6 +613,54 @@ nsNode3Tearoff::IsDefaultNamespace(const nsAString& aNamespaceURI, return NS_OK; } +//---------------------------------------------------------------------- + +NS_IMPL_ISUPPORTS1(nsNodeWeakReference, + nsIWeakReference) + +nsNodeWeakReference::~nsNodeWeakReference() +{ + if (mNode) { + NS_ASSERTION(mNode->GetSlots() && + mNode->GetSlots()->mWeakReference == this, + "Weak reference has wrong value"); + mNode->GetSlots()->mWeakReference = nsnull; + } +} + +NS_IMETHODIMP +nsNodeWeakReference::QueryReferent(const nsIID& aIID, void** aInstancePtr) +{ + return mNode ? mNode->QueryInterface(aIID, aInstancePtr) : + NS_ERROR_NULL_POINTER; +} + + +NS_INTERFACE_MAP_BEGIN(nsNodeSupportsWeakRefTearoff) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) +NS_INTERFACE_MAP_END_AGGREGATED(mNode) + +NS_IMPL_ADDREF(nsNodeSupportsWeakRefTearoff) +NS_IMPL_RELEASE(nsNodeSupportsWeakRefTearoff) + +NS_IMETHODIMP +nsNodeSupportsWeakRefTearoff::GetWeakReference(nsIWeakReference** aInstancePtr) +{ + nsINode::nsSlots* slots = mNode->GetSlots(); + NS_ENSURE_TRUE(slots, NS_ERROR_OUT_OF_MEMORY); + + if (!slots->mWeakReference) { + slots->mWeakReference = new nsNodeWeakReference(mNode); + NS_ENSURE_TRUE(slots->mWeakReference, NS_ERROR_OUT_OF_MEMORY); + } + + NS_ADDREF(*aInstancePtr = slots->mWeakReference); + + return NS_OK; +} + +//---------------------------------------------------------------------- + nsDOMEventRTTearoff * nsDOMEventRTTearoff::mCachedEventTearoff[NS_EVENT_TEAROFF_CACHE_SIZE]; @@ -2963,6 +3015,8 @@ NS_INTERFACE_MAP_BEGIN(nsGenericElement) nsDOMEventRTTearoff::Create(this)) NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNSEventTarget, nsDOMEventRTTearoff::Create(this)) + NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference, + new nsNodeSupportsWeakRefTearoff(this)) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent) NS_INTERFACE_MAP_END diff --git a/mozilla/content/base/src/nsGenericElement.h b/mozilla/content/base/src/nsGenericElement.h index dfee4f03e0c..c74c1deccec 100644 --- a/mozilla/content/base/src/nsGenericElement.h +++ b/mozilla/content/base/src/nsGenericElement.h @@ -60,6 +60,7 @@ #include "nsAttrAndChildArray.h" #include "mozFlushType.h" #include "nsDOMAttributeMap.h" +#include "nsIWeakReference.h" class nsIDOMAttr; class nsIDOMEventListener; @@ -107,7 +108,7 @@ private: }; /** - * A tearoff class for nsGenericElement to implement the nsIDOM3Node functions + * A tearoff class for nsGenericElement to implement additional interfaces */ class nsNode3Tearoff : public nsIDOM3Node { @@ -138,6 +139,55 @@ private: nsCOMPtr mContent; }; +/** + * A class that implements nsIWeakReference + */ + +class nsNodeWeakReference : public nsIWeakReference +{ +public: + nsNodeWeakReference(nsINode* aNode) + : mNode(aNode) + { + } + + ~nsNodeWeakReference(); + + // nsISupports + NS_DECL_ISUPPORTS + + // nsIWeakReference + NS_DECL_NSIWEAKREFERENCE + + void NoticeNodeDestruction() + { + mNode = nsnull; + } + +private: + nsINode* mNode; +}; + +/** + * Tearoff to use for nodes to implement nsISupportsWeakReference + */ +class nsNodeSupportsWeakRefTearoff : public nsISupportsWeakReference +{ +public: + nsNodeSupportsWeakRefTearoff(nsINode* aNode) + : mNode(aNode) + { + } + + // nsISupports + NS_DECL_ISUPPORTS + + // nsISupportsWeakReference + NS_DECL_NSISUPPORTSWEAKREFERENCE + +private: + nsCOMPtr mNode; +}; #define NS_EVENT_TEAROFF_CACHE_SIZE 4 @@ -905,6 +955,11 @@ public: */ nsIControllers* mControllers; // [OWNER] }; + + /** + * Weak reference to this node + */ + nsNodeWeakReference* mWeakReference; }; protected: