Fix for bug 457022 (Cache DOM wrappers in the DOM object). r/sr=jst.

This commit is contained in:
Peter Van der Beken 2008-11-04 18:10:43 +01:00
Родитель a0dfe7f851
Коммит 02dedb34c2
24 изменённых файлов: 477 добавлений и 224 удалений

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

@ -902,15 +902,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIContent, NS_ICONTENT_IID)
nsContentUtils::TraverseListenerManager(tmp, cb); \ nsContentUtils::TraverseListenerManager(tmp, cb); \
} }
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_PRESERVED_WRAPPER \
{ \
nsISupports *preservedWrapper = nsnull; \
if (tmp->GetOwnerDoc()) \
preservedWrapper = tmp->GetOwnerDoc()->GetReference(tmp); \
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[preserved wrapper]");\
cb.NoteXPCOMChild(preservedWrapper); \
}
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_USERDATA \ #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_USERDATA \
if (tmp->HasProperties()) { \ if (tmp->HasProperties()) { \
nsNodeUtils::TraverseUserData(tmp, cb); \ nsNodeUtils::TraverseUserData(tmp, cb); \
@ -922,10 +913,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIContent, NS_ICONTENT_IID)
tmp->UnsetFlags(NODE_HAS_LISTENERMANAGER); \ tmp->UnsetFlags(NODE_HAS_LISTENERMANAGER); \
} }
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \
if (tmp->GetOwnerDoc()) \
tmp->GetOwnerDoc()->RemoveReference(tmp);
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA \ #define NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA \
if (tmp->HasProperties()) { \ if (tmp->HasProperties()) { \
nsNodeUtils::UnlinkUserData(tmp); \ nsNodeUtils::UnlinkUserData(tmp); \

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

@ -96,8 +96,8 @@ class nsFrameLoader;
// IID for the nsIDocument interface // IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \ #define NS_IDOCUMENT_IID \
{ 0x6304ae8e, 0x2634, 0x45ed, \ { 0x92b19d1c, 0x8f37, 0x4d4b, \
{ 0x9e, 0x09, 0x83, 0x09, 0x5b, 0x46, 0x72, 0x8b } } { 0xa3, 0x42, 0xb5, 0xc6, 0x8b, 0x54, 0xde, 0x6c } }
// Flag for AddStyleSheet(). // Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0) #define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -677,10 +677,6 @@ public:
virtual void ResetToURI(nsIURI *aURI, nsILoadGroup* aLoadGroup, virtual void ResetToURI(nsIURI *aURI, nsILoadGroup* aLoadGroup,
nsIPrincipal* aPrincipal) = 0; nsIPrincipal* aPrincipal) = 0;
virtual void AddReference(void *aKey, nsISupports *aReference) = 0;
virtual nsISupports *GetReference(void *aKey) = 0;
virtual void RemoveReference(void *aKey) = 0;
/** /**
* Set the container (docshell) for this document. * Set the container (docshell) for this document.
*/ */

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

@ -44,6 +44,7 @@
#include "nsTObserverArray.h" #include "nsTObserverArray.h"
#include "nsINodeInfo.h" #include "nsINodeInfo.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsWrapperCache.h"
class nsIContent; class nsIContent;
class nsIDocument; class nsIDocument;
@ -150,16 +151,17 @@ inline nsINode* NODE_FROM(C& aContent, D& aDocument)
// IID for the nsINode interface // IID for the nsINode interface
#define NS_INODE_IID \ #define NS_INODE_IID \
{ 0x2593b0d5, 0x9a06, 0x4d6b, \ { 0x0f7b2557, 0xa09d, 0x468f, \
{ 0x9a, 0x10, 0xb1, 0x39, 0x9f, 0x1b, 0xa0, 0x8e } } { 0x93, 0x92, 0xf1, 0xf1, 0xd1, 0xfa, 0x31, 0x78 } }
/** /**
* An internal interface that abstracts some DOMNode-related parts that both * An internal interface that abstracts some DOMNode-related parts that both
* nsIContent and nsIDocument share. An instance of this interface has a list * nsIContent and nsIDocument share. An instance of this interface has a list
* of nsIContent children and provides access to them. * of nsIContent children and provides access to them.
*/ */
class nsINode : public nsPIDOMEventTarget { class nsINode : public nsPIDOMEventTarget,
public nsWrapperCache
{
public: public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_INODE_IID) NS_DECLARE_STATIC_IID_ACCESSOR(NS_INODE_IID)
@ -850,4 +852,12 @@ extern const nsIID kThisPtrOffsetsSID;
NS_DEFINE_STATIC_IID_ACCESSOR(nsINode, NS_INODE_IID) NS_DEFINE_STATIC_IID_ACCESSOR(nsINode, NS_INODE_IID)
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_PRESERVED_WRAPPER \
tmp->TraverseWrapper(cb);
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \
tmp->ClearWrapper();
#endif /* nsINode_h___ */ #endif /* nsINode_h___ */

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

@ -358,6 +358,7 @@ nsContentList::~nsContentList()
// QueryInterface implementation for nsContentList // QueryInterface implementation for nsContentList
NS_INTERFACE_TABLE_HEAD(nsContentList) NS_INTERFACE_TABLE_HEAD(nsContentList)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsContentList) NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsContentList)
NS_CONTENT_LIST_INTERFACES(nsContentList) NS_CONTENT_LIST_INTERFACES(nsContentList)
NS_INTERFACE_TABLE_ENTRY(nsContentList, nsIHTMLCollection) NS_INTERFACE_TABLE_ENTRY(nsContentList, nsIHTMLCollection)

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

@ -54,6 +54,7 @@
#include "nsIAtom.h" #include "nsIAtom.h"
#include "nsINameSpaceManager.h" #include "nsINameSpaceManager.h"
#include "nsCycleCollectionParticipant.h" #include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
// Magic namespace id that means "match all namespaces". This is // Magic namespace id that means "match all namespaces". This is
// negative so it won't collide with actual namespace constants. // negative so it won't collide with actual namespace constants.
@ -182,7 +183,8 @@ protected:
class nsContentList : public nsBaseContentList, class nsContentList : public nsBaseContentList,
protected nsContentListKey, protected nsContentListKey,
public nsIHTMLCollection, public nsIHTMLCollection,
public nsStubMutationObserver public nsStubMutationObserver,
public nsWrapperCache
{ {
public: public:
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED

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

@ -1119,15 +1119,6 @@ nsContentUtils::doReparentContentWrapper(nsIContent *aNode,
getter_AddRefs(old_wrapper)); getter_AddRefs(old_wrapper));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (aOldDocument) {
nsCOMPtr<nsISupports> old_ref = aOldDocument->GetReference(aNode);
if (old_ref) {
// Transfer the reference from aOldDocument to aNewDocument
aOldDocument->RemoveReference(aNode);
aNewDocument->AddReference(aNode, old_ref);
}
}
// Whether or not aChild is already wrapped we must iterate through // Whether or not aChild is already wrapped we must iterate through
// its descendants since there's no guarantee that a descendant isn't // its descendants since there's no guarantee that a descendant isn't
// wrapped even if this child is not wrapped. That used to be true // wrapped even if this child is not wrapped. That used to be true

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

@ -101,6 +101,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMAttribute)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
// QueryInterface implementation for nsDOMAttribute // QueryInterface implementation for nsDOMAttribute
NS_INTERFACE_TABLE_HEAD(nsDOMAttribute) NS_INTERFACE_TABLE_HEAD(nsDOMAttribute)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_NODE_INTERFACE_TABLE7(nsDOMAttribute, nsIDOMAttr, nsIAttribute, nsINode, NS_NODE_INTERFACE_TABLE7(nsDOMAttribute, nsIDOMAttr, nsIAttribute, nsINode,
nsIDOMNode, nsIDOM3Node, nsIDOM3Attr, nsIDOMNode, nsIDOM3Node, nsIDOM3Attr,
nsPIDOMEventTarget) nsPIDOMEventTarget)

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

@ -1567,13 +1567,12 @@ nsDocument::~nsDocument()
mBoxObjectTable->EnumerateRead(ClearAllBoxObjects, nsnull); mBoxObjectTable->EnumerateRead(ClearAllBoxObjects, nsnull);
delete mBoxObjectTable; delete mBoxObjectTable;
} }
delete mContentWrapperHash;
} }
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument) NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument)
NS_INTERFACE_TABLE_HEAD(nsDocument) NS_INTERFACE_TABLE_HEAD(nsDocument)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_DOCUMENT_INTERFACE_TABLE_BEGIN(nsDocument) NS_DOCUMENT_INTERFACE_TABLE_BEGIN(nsDocument)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsINode) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsINode)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDocument) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDocument)
@ -1753,9 +1752,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mCatalogSheets) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mCatalogSheets)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mVisitednessChangedURIs) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mVisitednessChangedURIs)
// Traverse any associated preserved wrapper. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_PRESERVED_WRAPPER
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[preserved wrapper]");
cb.NoteXPCOMChild(tmp->GetReference(tmp));
if (tmp->mSubDocuments && tmp->mSubDocuments->ops) { if (tmp->mSubDocuments && tmp->mSubDocuments->ops) {
PL_DHashTableEnumerate(tmp->mSubDocuments, SubDocTraverser, &cb); PL_DHashTableEnumerate(tmp->mSubDocuments, SubDocTraverser, &cb);
@ -1786,12 +1783,10 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA
// Drop the content hash.
delete tmp->mContentWrapperHash;
tmp->mContentWrapperHash = nsnull;
tmp->mParentDocument = nsnull; tmp->mParentDocument = nsnull;
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
// nsDocument has a pretty complex destructor, so we're going to // nsDocument has a pretty complex destructor, so we're going to
// assume that *most* cycles you actually want to break somewhere // assume that *most* cycles you actually want to break somewhere
// else, and not unlink an awful lot here. // else, and not unlink an awful lot here.
@ -6228,41 +6223,6 @@ nsDocument::FlushPendingNotifications(mozFlushType aType)
} }
} }
void
nsDocument::AddReference(void *aKey, nsISupports *aReference)
{
if (mScriptGlobalObject) {
if (!mContentWrapperHash) {
mContentWrapperHash = new nsInterfaceHashtable<nsVoidPtrHashKey, nsISupports>;
if (mContentWrapperHash) {
mContentWrapperHash->Init(10);
}
}
if (mContentWrapperHash)
mContentWrapperHash->Put(aKey, aReference);
}
}
nsISupports*
nsDocument::GetReference(void *aKey)
{
// NB: This method is part of content cycle collection,
// and must *not* Addref its return value.
if (mContentWrapperHash)
return mContentWrapperHash->GetWeak(aKey);
return nsnull;
}
void
nsDocument::RemoveReference(void *aKey)
{
if (mContentWrapperHash) {
mContentWrapperHash->Remove(aKey);
}
}
nsIScriptEventManager* nsIScriptEventManager*
nsDocument::GetScriptEventManager() nsDocument::GetScriptEventManager()
{ {
@ -6873,13 +6833,6 @@ nsDocument::Destroy()
// leak-fixing if we fix DocumentViewerImpl to do cycle-collection, but // leak-fixing if we fix DocumentViewerImpl to do cycle-collection, but
// tearing down all those frame trees right now is the right thing to do. // tearing down all those frame trees right now is the right thing to do.
mExternalResourceMap.Shutdown(); mExternalResourceMap.Shutdown();
// XXX We really should let cycle collection do this, but that currently still
// leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
// When we start relying on cycle collection again we should remove the
// check for mScriptGlobalObject in AddReference.
delete mContentWrapperHash;
mContentWrapperHash = nsnull;
} }
void void

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

@ -750,9 +750,6 @@ public:
nsIStyleRule* aStyleRule); nsIStyleRule* aStyleRule);
virtual void FlushPendingNotifications(mozFlushType aType); virtual void FlushPendingNotifications(mozFlushType aType);
virtual void AddReference(void *aKey, nsISupports *aReference);
virtual nsISupports *GetReference(void *aKey);
virtual void RemoveReference(void *aKey);
virtual nsIScriptEventManager* GetScriptEventManager(); virtual nsIScriptEventManager* GetScriptEventManager();
virtual void SetXMLDeclaration(const PRUnichar *aVersion, virtual void SetXMLDeclaration(const PRUnichar *aVersion,
const PRUnichar *aEncoding, const PRUnichar *aEncoding,
@ -1158,7 +1155,6 @@ protected:
PRUint8 mIdMissCount; PRUint8 mIdMissCount;
nsInterfaceHashtable<nsVoidPtrHashKey, nsPIBoxObject> *mBoxObjectTable; nsInterfaceHashtable<nsVoidPtrHashKey, nsPIBoxObject> *mBoxObjectTable;
nsInterfaceHashtable<nsVoidPtrHashKey, nsISupports> *mContentWrapperHash;
// The channel that got passed to StartDocumentLoad(), if any // The channel that got passed to StartDocumentLoad(), if any
nsCOMPtr<nsIChannel> mChannel; nsCOMPtr<nsIChannel> mChannel;

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

@ -105,7 +105,9 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericDOMDataNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGenericDOMDataNode) NS_INTERFACE_MAP_BEGIN(nsGenericDOMDataNode)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsGenericDOMDataNode)
NS_INTERFACE_MAP_ENTRY(nsIContent) NS_INTERFACE_MAP_ENTRY(nsIContent)
NS_INTERFACE_MAP_ENTRY(nsINode) NS_INTERFACE_MAP_ENTRY(nsINode)
NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget) NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget)

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

@ -462,6 +462,7 @@ NS_IMPL_ADDREF(nsChildContentList)
NS_IMPL_RELEASE(nsChildContentList) NS_IMPL_RELEASE(nsChildContentList)
NS_INTERFACE_TABLE_HEAD(nsChildContentList) NS_INTERFACE_TABLE_HEAD(nsChildContentList)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsChildContentList) NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsChildContentList)
NS_INTERFACE_TABLE_ENTRY(nsChildContentList, nsINodeList) NS_INTERFACE_TABLE_ENTRY(nsChildContentList, nsINodeList)
NS_INTERFACE_TABLE_ENTRY(nsChildContentList, nsIDOMNodeList) NS_INTERFACE_TABLE_ENTRY(nsChildContentList, nsIDOMNodeList)
@ -4066,7 +4067,9 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGenericElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGenericElement) NS_INTERFACE_MAP_BEGIN(nsGenericElement)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsGenericElement)
NS_INTERFACE_MAP_ENTRY(nsIContent) NS_INTERFACE_MAP_ENTRY(nsIContent)
NS_INTERFACE_MAP_ENTRY(nsINode) NS_INTERFACE_MAP_ENTRY(nsINode)
NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget) NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget)

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

@ -89,7 +89,8 @@ typedef unsigned long PtrBits;
* and Item to its existing child list. * and Item to its existing child list.
* @see nsIDOMNodeList * @see nsIDOMNodeList
*/ */
class nsChildContentList : public nsINodeList class nsChildContentList : public nsINodeList,
public nsWrapperCache
{ {
public: public:
nsChildContentList(nsINode* aNode) nsChildContentList(nsINode* aNode)
@ -110,6 +111,27 @@ public:
mNode = nsnull; mNode = nsnull;
} }
nsISupports* 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: private:
// The node whose children make up the list (weak reference) // The node whose children make up the list (weak reference)
nsINode* mNode; nsINode* mNode;

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

@ -564,26 +564,15 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
} }
} }
else if (nodeInfoManager) { else if (nodeInfoManager) {
nsCOMPtr<nsISupports> oldRef;
nsIDocument* oldDoc = aNode->GetOwnerDoc(); nsIDocument* oldDoc = aNode->GetOwnerDoc();
if (oldDoc) { if (oldDoc && aNode->IsNodeOfType(nsINode::eELEMENT)) {
if (aNode->IsNodeOfType(nsINode::eELEMENT)) { oldDoc->ClearBoxObjectFor(static_cast<nsIContent*>(aNode));
oldDoc->ClearBoxObjectFor(static_cast<nsIContent*>(aNode));
}
oldRef = oldDoc->GetReference(aNode);
if (oldRef) {
oldDoc->RemoveReference(aNode);
}
} }
aNode->mNodeInfo.swap(newNodeInfo); aNode->mNodeInfo.swap(newNodeInfo);
nsIDocument* newDoc = aNode->GetOwnerDoc(); nsIDocument* newDoc = aNode->GetOwnerDoc();
if (newDoc) { if (newDoc) {
if (oldRef) {
newDoc->AddReference(aNode, oldRef);
}
nsPIDOMWindow* window = newDoc->GetInnerWindow(); nsPIDOMWindow* window = newDoc->GetInnerWindow();
if (window) { if (window) {
nsCOMPtr<nsIEventListenerManager> elm; nsCOMPtr<nsIEventListenerManager> elm;

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

@ -530,13 +530,7 @@ GetDocumentFromScriptContext(nsIScriptContext *aScriptContext)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXHREventTarget) NS_IMPL_CYCLE_COLLECTION_CLASS(nsXHREventTarget)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXHREventTarget) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXHREventTarget)
if (tmp->mOwner) { NS_IMPL_CYCLE_COLLECTION_TRAVERSE_PRESERVED_WRAPPER
nsCOMPtr<nsIDocument> doc =
do_QueryInterface(tmp->mOwner->GetExtantDocument());
if (doc) {
cb.NoteXPCOMChild(doc->GetReference(tmp));
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadListener) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnAbortListener) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnAbortListener)
@ -548,13 +542,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXHREventTarget)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXHREventTarget) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXHREventTarget)
if (tmp->mOwner) { NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
nsCOMPtr<nsIDocument> doc =
do_QueryInterface(tmp->mOwner->GetExtantDocument());
if (doc) {
doc->RemoveReference(tmp);
}
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadListener) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnErrorListener) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnErrorListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnAbortListener) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnAbortListener)
@ -565,7 +553,9 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXHREventTarget)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOwner) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOwner)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXHREventTarget) NS_INTERFACE_MAP_BEGIN(nsXHREventTarget)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsXHREventTarget)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXMLHttpRequestEventTarget) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXMLHttpRequestEventTarget)
NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequestEventTarget) NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequestEventTarget)
NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget) NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget)

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

@ -73,6 +73,7 @@
#include "nsITimer.h" #include "nsITimer.h"
#include "nsIPrivateDOMEvent.h" #include "nsIPrivateDOMEvent.h"
#include "nsDOMProgressEvent.h" #include "nsDOMProgressEvent.h"
#include "nsIScriptGlobalObject.h"
class nsILoadGroup; class nsILoadGroup;
@ -159,7 +160,8 @@ protected:
class nsXHREventTarget : public nsIXMLHttpRequestEventTarget, class nsXHREventTarget : public nsIXMLHttpRequestEventTarget,
public nsPIDOMEventTarget, public nsPIDOMEventTarget,
public nsIDOMNSEventTarget public nsIDOMNSEventTarget,
public nsWrapperCache
{ {
public: public:
nsXHREventTarget() : mLang(nsIProgrammingLanguage::JAVASCRIPT) {} nsXHREventTarget() : mLang(nsIProgrammingLanguage::JAVASCRIPT) {}
@ -207,6 +209,36 @@ public:
} }
return NS_OK; return NS_OK;
} }
void GetParentObject(nsIScriptGlobalObject **aParentObject)
{
if (mOwner) {
CallQueryInterface(mOwner, aParentObject);
}
else {
*aParentObject = nsnull;
}
}
static nsXHREventTarget* FromSupports(nsISupports* aSupports)
{
nsIXMLHttpRequestEventTarget* target =
static_cast<nsIXMLHttpRequestEventTarget*>(aSupports);
#ifdef DEBUG
{
nsCOMPtr<nsIXMLHttpRequestEventTarget> target_qi =
do_QueryInterface(aSupports);
// If this assertion fires the QI implementation for the object in
// question doesn't use the nsIXMLHttpRequestEventTarget pointer as the
// nsISupports pointer. That must be fixed, or we'll crash...
NS_ASSERTION(target_qi == target, "Uh, fix QI!");
}
#endif
return static_cast<nsXHREventTarget*>(target);
}
protected: protected:
nsRefPtr<nsDOMEventListenerWrapper> mOnLoadListener; nsRefPtr<nsDOMEventListenerWrapper> mOnLoadListener;
nsRefPtr<nsDOMEventListenerWrapper> mOnErrorListener; nsRefPtr<nsDOMEventListenerWrapper> mOnErrorListener;

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

@ -151,13 +151,7 @@ nsXBLProtoImpl::InitTargetObjects(nsXBLPrototypeBinding* aBinding,
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return rv; return rv;
// Root ourselves in the document. aBoundElement->PreserveWrapper();
nsIDocument* doc = aBoundElement->GetOwnerDoc();
if (doc) {
nsCOMPtr<nsIXPConnectWrappedNative> nativeWrapper(do_QueryInterface(wrapper));
if (nativeWrapper)
doc->AddReference(aBoundElement, nativeWrapper);
}
wrapper.swap(*aScriptObjectHolder); wrapper.swap(*aScriptObjectHolder);

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

@ -71,6 +71,7 @@ EXPORTS=nsIScriptContext.h \
nsDOMString.h \ nsDOMString.h \
nsDOMJSUtils.h \ nsDOMJSUtils.h \
nsDOMScriptObjectHolder.h \ nsDOMScriptObjectHolder.h \
nsWrapperCache.h \
$(NULL) $(NULL)
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk

137
dom/public/nsWrapperCache.h Normal file
Просмотреть файл

@ -0,0 +1,137 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Gecko DOM code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsWrapperCache_h___
#define nsWrapperCache_h___
#include "nsCycleCollectionParticipant.h"
typedef unsigned long PtrBits;
#define NS_WRAPPERCACHE_IID \
{ 0x3a51ca81, 0xddab, 0x422c, \
{ 0x95, 0x3a, 0x13, 0x06, 0x28, 0x0e, 0xee, 0x14 } }
/**
* Class to store the XPCWrappedNative for an object. This can only be used
* with objects that only have one XPCWrappedNative at a time (usually ensured
* by setting an explicit parent in the PreCreate hook for the class). This
* object can be gotten by calling QueryInterface, note that this breaks XPCOM
* rules a bit (this object doesn't derive from nsISupports).
*/
class nsWrapperCache
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_WRAPPERCACHE_IID)
nsWrapperCache() : mWrapperPtrBits(0)
{
}
~nsWrapperCache()
{
if (PreservingWrapper()) {
GetWrapper()->Release();
}
}
/**
* This method returns an nsIXPConnectWrappedNative, but we want to avoid
* including nsIXPConnect, because we don't want to make everyone require
* JS and XPConnect.
*/
nsISupports* GetWrapper()
{
return reinterpret_cast<nsISupports*>(mWrapperPtrBits & ~kWrapperBitMask);
}
/**
* This method takes an nsIXPConnectWrappedNative, but we want to avoid
* including nsIXPConnect, because we don't want to make everyone require
* JS and XPConnect.
*/
void SetWrapper(nsISupports* aWrapper)
{
NS_ASSERTION(!mWrapperPtrBits, "Already have a wrapper!");
mWrapperPtrBits = reinterpret_cast<PtrBits>(aWrapper);
}
void ClearWrapper()
{
if (PreservingWrapper()) {
GetWrapper()->Release();
}
mWrapperPtrBits = 0;
}
void PreserveWrapper()
{
NS_ASSERTION(mWrapperPtrBits, "No wrapper to preserve?");
if (!PreservingWrapper()) {
NS_ADDREF(reinterpret_cast<nsISupports*>(mWrapperPtrBits));
mWrapperPtrBits |= WRAPPER_BIT_PRESERVED;
}
}
void TraverseWrapper(nsCycleCollectionTraversalCallback &cb)
{
if (PreservingWrapper()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mWrapper");
cb.NoteXPCOMChild(GetWrapper());
}
}
private:
PRBool PreservingWrapper()
{
return mWrapperPtrBits & WRAPPER_BIT_PRESERVED;
}
enum { WRAPPER_BIT_PRESERVED = 1 << 0 };
enum { kWrapperBitMask = 0x1 };
PtrBits mWrapperPtrBits;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperCache, NS_WRAPPERCACHE_IID)
#define NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY \
if ( aIID.Equals(NS_GET_IID(nsWrapperCache)) ) { \
*aInstancePtr = static_cast<nsWrapperCache*>(this); \
return NS_OK; \
}
#endif /* nsWrapperCache_h___ */

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

@ -171,6 +171,7 @@
// ContentList includes // ContentList includes
#include "nsContentList.h" #include "nsContentList.h"
#include "nsGenericElement.h"
// Event related includes // Event related includes
#include "nsIEventListenerManager.h" #include "nsIEventListenerManager.h"
@ -212,7 +213,7 @@
#include "nsIDOMLSProgressEvent.h" #include "nsIDOMLSProgressEvent.h"
#include "nsIDOMParser.h" #include "nsIDOMParser.h"
#include "nsIDOMSerializer.h" #include "nsIDOMSerializer.h"
#include "nsIXMLHttpRequest.h" #include "nsXMLHttpRequest.h"
// includes needed for the prototype chain interfaces // includes needed for the prototype chain interfaces
#include "nsIDOMNavigator.h" #include "nsIDOMNavigator.h"
@ -489,7 +490,8 @@ static const char kDOMStringBundleURL[] =
((DOM_DEFAULT_SCRIPTABLE_FLAGS | \ ((DOM_DEFAULT_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_GETPROPERTY | \ nsIXPCScriptable::WANT_GETPROPERTY | \
nsIXPCScriptable::WANT_ADDPROPERTY | \ nsIXPCScriptable::WANT_ADDPROPERTY | \
nsIXPCScriptable::WANT_SETPROPERTY) & \ nsIXPCScriptable::WANT_SETPROPERTY | \
nsIXPCScriptable::WANT_FINALIZE) & \
~nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY) ~nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY)
// We need to let JavaScript QI elements to interfaces that are not in // We need to let JavaScript QI elements to interfaces that are not in
@ -513,15 +515,22 @@ static const char kDOMStringBundleURL[] =
nsIXPCScriptable::WANT_ADDPROPERTY | \ nsIXPCScriptable::WANT_ADDPROPERTY | \
nsIXPCScriptable::WANT_DELPROPERTY | \ nsIXPCScriptable::WANT_DELPROPERTY | \
nsIXPCScriptable::WANT_GETPROPERTY | \ nsIXPCScriptable::WANT_GETPROPERTY | \
nsIXPCScriptable::WANT_ENUMERATE | \ nsIXPCScriptable::WANT_ENUMERATE)
nsIXPCScriptable::WANT_POSTCREATE | \
nsIXPCScriptable::WANT_FINALIZE)
#define ARRAY_SCRIPTABLE_FLAGS \ #define ARRAY_SCRIPTABLE_FLAGS \
(DOM_DEFAULT_SCRIPTABLE_FLAGS | \ (DOM_DEFAULT_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_GETPROPERTY | \ nsIXPCScriptable::WANT_GETPROPERTY | \
nsIXPCScriptable::WANT_ENUMERATE) nsIXPCScriptable::WANT_ENUMERATE)
#define NODELIST_SCRIPTABLE_FLAGS \
(ARRAY_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_FINALIZE)
#define EVENTTARGET_SCRIPTABLE_FLAGS \
(DOM_DEFAULT_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_ADDPROPERTY | \
nsIXPCScriptable::WANT_FINALIZE)
#define DOMCLASSINFO_STANDARD_FLAGS \ #define DOMCLASSINFO_STANDARD_FLAGS \
(nsIClassInfo::MAIN_THREAD_ONLY | nsIClassInfo::DOM_OBJECT) (nsIClassInfo::MAIN_THREAD_ONLY | nsIClassInfo::DOM_OBJECT)
@ -632,7 +641,7 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(ProcessingInstruction, nsNodeSH, NS_DEFINE_CLASSINFO_DATA(ProcessingInstruction, nsNodeSH,
NODE_SCRIPTABLE_FLAGS) NODE_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(Notation, nsNodeSH, NODE_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(Notation, nsNodeSH, NODE_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(NodeList, nsNodeListSH, ARRAY_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(NodeList, nsNodeListSH, NODELIST_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(NamedNodeMap, nsNamedNodeMapSH, NS_DEFINE_CLASSINFO_DATA(NamedNodeMap, nsNamedNodeMapSH,
ARRAY_SCRIPTABLE_FLAGS) ARRAY_SCRIPTABLE_FLAGS)
@ -883,9 +892,7 @@ static nsDOMClassInfoData sClassInfoData[] = {
ARRAY_SCRIPTABLE_FLAGS) ARRAY_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA_WITH_NAME(ContentList, HTMLCollection, NS_DEFINE_CLASSINFO_DATA_WITH_NAME(ContentList, HTMLCollection,
nsContentListSH, nsContentListSH, NODELIST_SCRIPTABLE_FLAGS)
ARRAY_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_PRECREATE)
NS_DEFINE_CLASSINFO_DATA(XMLStylesheetProcessingInstruction, nsNodeSH, NS_DEFINE_CLASSINFO_DATA(XMLStylesheetProcessingInstruction, nsNodeSH,
NODE_SCRIPTABLE_FLAGS) NODE_SCRIPTABLE_FLAGS)
@ -1206,8 +1213,7 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(XMLHttpProgressEvent, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(XMLHttpProgressEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(XMLHttpRequest, nsEventTargetSH, NS_DEFINE_CLASSINFO_DATA(XMLHttpRequest, nsEventTargetSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS | EVENTTARGET_SCRIPTABLE_FLAGS)
nsIXPCScriptable::WANT_ADDPROPERTY)
NS_DEFINE_CLASSINFO_DATA(ClientRect, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(ClientRect, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -1278,8 +1284,7 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(XMLHttpRequestUpload, nsEventTargetSH, NS_DEFINE_CLASSINFO_DATA(XMLHttpRequestUpload, nsEventTargetSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS | EVENTTARGET_SCRIPTABLE_FLAGS)
nsIXPCScriptable::WANT_ADDPROPERTY)
// DOM Traversal NodeIterator class // DOM Traversal NodeIterator class
NS_DEFINE_CLASSINFO_DATA(NodeIterator, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(NodeIterator, nsDOMGenericSH,
@ -4167,28 +4172,14 @@ nsDOMClassInfo::GetClassInfoInstance(nsDOMClassInfoData* aData)
} }
// static // static
nsresult void
nsDOMClassInfo::PreserveNodeWrapper(nsIXPConnectWrappedNative *aWrapper) nsDOMClassInfo::PreserveNodeWrapper(nsIXPConnectWrappedNative *aWrapper)
{ {
nsISupports *native = aWrapper->Native(); nsWrapperCache* cache;
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(native)); CallQueryInterface(aWrapper->Native(), &cache);
if (cache) {
nsCOMPtr<nsIDocument> doc; cache->PreserveWrapper();
if (node) {
nsCOMPtr<nsIDOMDocument> domdoc;
node->GetOwnerDocument(getter_AddRefs(domdoc));
doc = do_QueryInterface(domdoc);
} }
if (!doc) {
doc = do_QueryInterface(native);
}
if (doc) {
nsCOMPtr<nsINode> n(do_QueryInterface(node));
doc->AddReference(n, aWrapper);
}
return NS_OK;
} }
@ -6910,6 +6901,16 @@ nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj,
return rv; return rv;
} }
NS_IMETHODIMP
nsNodeSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj)
{
nsINode* node = static_cast<nsINode*>(wrapper->Native());
node->SetWrapper(wrapper);
return nsEventReceiverSH::PostCreate(wrapper, cx, obj);
}
NS_IMETHODIMP NS_IMETHODIMP
nsNodeSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, nsNodeSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsval id, jsval *vp, PRBool *_retval) JSObject *obj, jsval id, jsval *vp, PRBool *_retval)
@ -6928,6 +6929,13 @@ nsNodeSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return DefineVoidProp(cx, obj, id, objp); return DefineVoidProp(cx, obj, id, objp);
} }
if (id == sOnload_id || id == sOnerror_id) {
// Make sure that this node can't go away while waiting for a
// network load that could fire an event handler.
nsINode* node = static_cast<nsINode*>(wrapper->Native());
node->PreserveWrapper();
}
return nsEventReceiverSH::NewResolve(wrapper, cx, obj, id, flags, objp, return nsEventReceiverSH::NewResolve(wrapper, cx, obj, id, flags, objp,
_retval); _retval);
} }
@ -6996,6 +7004,16 @@ nsNodeSH::GetFlags(PRUint32 *aFlags)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsNodeSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj)
{
nsINode* node = static_cast<nsINode*>(wrapper->Native());
node->ClearWrapper();
return NS_OK;
}
// EventReceiver helper // EventReceiver helper
// static // static
@ -7246,12 +7264,6 @@ nsEventReceiverSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
JSContext *cx, JSObject *obj, jsval id, JSContext *cx, JSObject *obj, jsval id,
PRUint32 flags, JSObject **objp, PRBool *_retval) PRUint32 flags, JSObject **objp, PRBool *_retval)
{ {
if (id == sOnload_id || id == sOnerror_id) {
// Make sure that this node can't go away while waiting for a
// network load that could fire an event handler.
nsDOMClassInfo::PreserveNodeWrapper(wrapper);
}
if (!JSVAL_IS_STRING(id)) { if (!JSVAL_IS_STRING(id)) {
return NS_OK; return NS_OK;
} }
@ -7336,6 +7348,30 @@ nsEventReceiverSH::AddProperty(nsIXPConnectWrappedNative *wrapper,
// EventTarget helper // EventTarget helper
NS_IMETHODIMP
nsEventTargetSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj)
{
nsXHREventTarget *target = nsXHREventTarget::FromSupports(nativeObj);
nsCOMPtr<nsIScriptGlobalObject> native_parent;
target->GetParentObject(getter_AddRefs(native_parent));
*parentObj = native_parent ? native_parent->GetGlobalJSObject() : globalObj;
return NS_OK;
}
NS_IMETHODIMP
nsEventTargetSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj)
{
nsXHREventTarget *target = nsXHREventTarget::FromSupports(wrapper->Native());
target->SetWrapper(wrapper);
return nsDOMGenericSH::PostCreate(wrapper, cx, obj);
}
NS_IMETHODIMP NS_IMETHODIMP
nsEventTargetSH::NewResolve(nsIXPConnectWrappedNative *wrapper, nsEventTargetSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
JSContext *cx, JSObject *obj, jsval id, JSContext *cx, JSObject *obj, jsval id,
@ -7358,26 +7394,24 @@ nsEventTargetSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
if (id == sAddEventListener_id) { if (id == sAddEventListener_id) {
return NS_OK; return NS_OK;
} }
nsISupports* native = wrapper->Native();
nsCOMPtr<nsPIDOMEventTarget> target = do_QueryInterface(native); nsXHREventTarget *target = nsXHREventTarget::FromSupports(wrapper->Native());
if (target) { target->PreserveWrapper();
nsCOMPtr<nsIScriptContext> scriptContext;
target->GetContextForEventHandlers(getter_AddRefs(scriptContext));
if (scriptContext) {
nsCOMPtr<nsPIDOMWindow> window =
do_QueryInterface(scriptContext->GetGlobalObject());
if (window) {
nsCOMPtr<nsIDocument> doc =
do_QueryInterface(window->GetExtantDocument());
if (doc) {
doc->AddReference(native, wrapper);
}
}
}
}
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsEventTargetSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj)
{
nsXHREventTarget *target = nsXHREventTarget::FromSupports(wrapper->Native());
target->ClearWrapper();
return NS_OK;
}
// Element helper // Element helper
NS_IMETHODIMP NS_IMETHODIMP
@ -7650,6 +7684,49 @@ nsArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// NodeList scriptable helper // NodeList scriptable helper
nsresult
nsNodeListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj)
{
nsWrapperCache* cache;
CallQueryInterface(nativeObj, &cache);
if (!cache) {
*parentObj = globalObj;
return NS_OK;
}
// nsChildContentList is the only class that uses nsNodeListSH and has a
// cached wrapper.
nsChildContentList *list = nsChildContentList::FromSupports(nativeObj);
nsISupports *native_parent = list->GetParentObject();
if (!native_parent) {
return NS_ERROR_FAILURE;
}
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, globalObj, native_parent,
NS_GET_IID(nsISupports), &v,
getter_AddRefs(holder));
*parentObj = JSVAL_TO_OBJECT(v);
return rv;
}
NS_IMETHODIMP
nsNodeListSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj)
{
nsWrapperCache* cache;
CallQueryInterface(wrapper->Native(), &cache);
if (cache) {
cache->SetWrapper(wrapper);
}
return nsArraySH::PostCreate(wrapper, cx, obj);
}
nsresult nsresult
nsNodeListSH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx, nsNodeListSH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRUint32 *length) JSObject *obj, PRUint32 *length)
@ -7688,6 +7765,19 @@ nsNodeListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
return list->GetNodeAt(aIndex); return list->GetNodeAt(aIndex);
} }
NS_IMETHODIMP
nsNodeListSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj)
{
nsWrapperCache* cache;
CallQueryInterface(wrapper->Native(), &cache);
if (cache) {
cache->ClearWrapper();
}
return NS_OK;
}
// StringList scriptable helper // StringList scriptable helper
@ -7825,8 +7915,7 @@ nsContentListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
nsISupports *native_parent = contentList->GetParentObject(); nsISupports *native_parent = contentList->GetParentObject();
if (!native_parent) { if (!native_parent) {
*parentObj = globalObj; return NS_ERROR_FAILURE;
return NS_OK;
} }
jsval v; jsval v;
@ -7840,6 +7929,16 @@ nsContentListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
return rv; return rv;
} }
NS_IMETHODIMP
nsContentListSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj)
{
nsContentList *list = nsContentList::FromSupports(wrapper->Native());
list->SetWrapper(wrapper);
return nsNamedArraySH::PostCreate(wrapper, cx, obj);
}
nsresult nsresult
nsContentListSH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx, nsContentListSH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRUint32 *length) JSObject *obj, PRUint32 *length)
@ -7867,6 +7966,15 @@ nsContentListSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
return list->GetNamedItem(aName, aResult); return list->GetNamedItem(aName, aResult);
} }
NS_IMETHODIMP
nsContentListSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj)
{
nsContentList *list = nsContentList::FromSupports(wrapper->Native());
list->ClearWrapper();
return NS_OK;
}
// Document helper for document.location and document.on* // Document helper for document.location and document.on*
@ -8091,7 +8199,7 @@ nsDocumentSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
doc->SetJSObject(nsnull); doc->SetJSObject(nsnull);
return NS_OK; return nsNodeSH::Finalize(wrapper, cx, obj);
} }
// HTMLDocument helper // HTMLDocument helper

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

@ -172,7 +172,7 @@ public:
::JS_GET_CLASS(cx, obj) == sXPCNativeWrapperClass; ::JS_GET_CLASS(cx, obj) == sXPCNativeWrapperClass;
} }
static nsresult PreserveNodeWrapper(nsIXPConnectWrappedNative *aWrapper); static void PreserveNodeWrapper(nsIXPConnectWrappedNative *aWrapper);
protected: protected:
friend nsIClassInfo* NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID); friend nsIClassInfo* NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID);
@ -400,11 +400,17 @@ protected:
{ {
} }
public: public:
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj);
NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj);
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsval id, PRUint32 flags, JSObject *obj, jsval id, PRUint32 flags,
JSObject **objp, PRBool *_retval); JSObject **objp, PRBool *_retval);
NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsval id, jsval *vp, PRBool *_retval); JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData) static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
{ {
@ -556,6 +562,8 @@ protected:
public: public:
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx, NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj); JSObject *globalObj, JSObject **parentObj);
NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj);
NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsval id, jsval *vp, PRBool *_retval); JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
@ -566,6 +574,8 @@ public:
NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsval id, jsval *vp, PRBool *_retval); JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
NS_IMETHOD GetFlags(PRUint32 *aFlags); NS_IMETHOD GetFlags(PRUint32 *aFlags);
NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData) static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
{ {
@ -668,6 +678,13 @@ protected:
} }
public: public:
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj);
NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj);
NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj);
virtual nsresult GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx, virtual nsresult GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRUint32 *length); JSObject *obj, PRUint32 *length);
virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex, virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
@ -779,6 +796,10 @@ protected:
public: public:
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx, NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj); JSObject *globalObj, JSObject **parentObj);
NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj);
NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj);
virtual nsresult GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx, virtual nsresult GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRUint32 *length); JSObject *obj, PRUint32 *length);

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

@ -1001,13 +1001,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocumentPrincipal) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocumentPrincipal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc)
// Traverse any associated preserved wrappers.
{
if (tmp->mDoc) {
cb.NoteXPCOMChild(tmp->mDoc->GetReference(tmp));
}
}
// Traverse stuff from nsPIDOMWindow // Traverse stuff from nsPIDOMWindow
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChromeEventHandler) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChromeEventHandler)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument)
@ -1040,12 +1033,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mApplicationCache) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mApplicationCache)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocumentPrincipal) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocumentPrincipal)
// Unlink any associated preserved wrapper.
if (tmp->mDoc) {
tmp->mDoc->RemoveReference(tmp);
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDoc)
}
// Unlink stuff from nsPIDOMWindow // Unlink stuff from nsPIDOMWindow
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChromeEventHandler) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChromeEventHandler)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument)

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

@ -3372,7 +3372,8 @@ nsJSContext::ScriptExecuted()
NS_IMETHODIMP NS_IMETHODIMP
nsJSContext::PreserveWrapper(nsIXPConnectWrappedNative *aWrapper) nsJSContext::PreserveWrapper(nsIXPConnectWrappedNative *aWrapper)
{ {
return nsDOMClassInfo::PreserveNodeWrapper(aWrapper); nsDOMClassInfo::PreserveNodeWrapper(aWrapper);
return NS_OK;
} }
//static //static

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

@ -48,6 +48,7 @@
#include "nsIAtom.h" #include "nsIAtom.h"
#include "XPCWrapper.h" #include "XPCWrapper.h"
#include "nsJSPrincipals.h" #include "nsJSPrincipals.h"
#include "nsWrapperCache.h"
//#define STRICT_CHECK_OF_UNICODE //#define STRICT_CHECK_OF_UNICODE
#ifdef STRICT_CHECK_OF_UNICODE #ifdef STRICT_CHECK_OF_UNICODE
@ -1091,15 +1092,28 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx,
if(!iface) if(!iface)
return JS_FALSE; return JS_FALSE;
nsresult rv;
XPCWrappedNative* wrapper; XPCWrappedNative* wrapper;
nsresult rv = XPCWrappedNative::GetNewOrUsed(ccx, src, xpcscope, nsWrapperCache* cache;
iface, isGlobal, src->QueryInterface(NS_GET_IID(nsWrapperCache), (void**)&cache);
&wrapper); if(cache &&
(wrapper = static_cast<XPCWrappedNative*>(cache->GetWrapper())))
{
NS_ADDREF(wrapper);
wrapper->FindTearOff(ccx, iface, JS_FALSE, &rv);
}
else
{
rv = XPCWrappedNative::GetNewOrUsed(ccx, src, xpcscope, iface,
isGlobal, &wrapper);
}
if(pErr) if(pErr)
*pErr = rv; *pErr = rv;
if(NS_SUCCEEDED(rv) && wrapper) if(NS_SUCCEEDED(rv) && wrapper)
{ {
uint32 flags = 0; uint32 flags = 0;
JSObject *flat = wrapper->GetFlatJSObject();
if (allowNativeWrapper && wrapper->GetScope() != xpcscope) if (allowNativeWrapper && wrapper->GetScope() != xpcscope)
{ {
// Cross scope access detected. Check if chrome code // Cross scope access detected. Check if chrome code
@ -1157,7 +1171,6 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx,
flags = script ? JS_GetScriptFilenameFlags(script) : 0; flags = script ? JS_GetScriptFilenameFlags(script) : 0;
NS_ASSERTION(flags != JSFILENAME_NULL, "null script filename"); NS_ASSERTION(flags != JSFILENAME_NULL, "null script filename");
JSObject *flat = wrapper->GetFlatJSObject();
if(!JS_IsSystemObject(ccx, flat)) if(!JS_IsSystemObject(ccx, flat))
{ {
@ -1265,7 +1278,6 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx,
} }
} }
JSObject *flat = wrapper->GetFlatJSObject();
const char *name = STOBJ_GET_CLASS(flat)->name; const char *name = STOBJ_GET_CLASS(flat)->name;
if(allowNativeWrapper && if(allowNativeWrapper &&
!(flags & JSFILENAME_SYSTEM) && !(flags & JSFILENAME_SYSTEM) &&

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

@ -45,6 +45,7 @@
#include "nsCRT.h" #include "nsCRT.h"
#include "XPCNativeWrapper.h" #include "XPCNativeWrapper.h"
#include "XPCWrapper.h" #include "XPCWrapper.h"
#include "nsWrapperCache.h"
/***************************************************************************/ /***************************************************************************/
@ -589,27 +590,13 @@ XPCWrappedNative::GetUsedOnly(XPCCallContext& ccx,
XPCWrappedNative** resultWrapper) XPCWrappedNative** resultWrapper)
{ {
NS_ASSERTION(Object, "XPCWrappedNative::GetUsedOnly was called with a null Object"); NS_ASSERTION(Object, "XPCWrappedNative::GetUsedOnly was called with a null Object");
nsCOMPtr<nsISupports> identity;
#ifdef XPC_IDISPATCH_SUPPORT
// XXX See GetNewOrUsed for more info on this
if(Interface->GetIID()->Equals(NSID_IDISPATCH))
identity = Object;
else
#endif
identity = do_QueryInterface(Object);
if(!identity)
{
NS_ERROR("This XPCOM object fails in QueryInterface to nsISupports!");
return NS_ERROR_FAILURE;
}
XPCWrappedNative* wrapper; XPCWrappedNative* wrapper;
Native2WrappedNativeMap* map = Scope->GetWrappedNativeMap(); nsWrapperCache* cache;
Object->QueryInterface(NS_GET_IID(nsWrapperCache), (void**)&cache);
{ // scoped lock if(cache)
XPCAutoLock lock(Scope->GetRuntime()->GetMapLock()); {
wrapper = map->Find(identity); wrapper = static_cast<XPCWrappedNative*>(cache->GetWrapper());
if(!wrapper) if(!wrapper)
{ {
*resultWrapper = nsnull; *resultWrapper = nsnull;
@ -617,6 +604,36 @@ XPCWrappedNative::GetUsedOnly(XPCCallContext& ccx,
} }
NS_ADDREF(wrapper); NS_ADDREF(wrapper);
} }
else
{
nsCOMPtr<nsISupports> identity;
#ifdef XPC_IDISPATCH_SUPPORT
// XXX See GetNewOrUsed for more info on this
if(Interface->GetIID()->Equals(NSID_IDISPATCH))
identity = Object;
else
#endif
identity = do_QueryInterface(Object);
if(!identity)
{
NS_ERROR("This XPCOM object fails in QueryInterface to nsISupports!");
return NS_ERROR_FAILURE;
}
Native2WrappedNativeMap* map = Scope->GetWrappedNativeMap();
{ // scoped lock
XPCAutoLock lock(Scope->GetRuntime()->GetMapLock());
wrapper = map->Find(identity);
if(!wrapper)
{
*resultWrapper = nsnull;
return NS_OK;
}
NS_ADDREF(wrapper);
}
}
nsresult rv; nsresult rv;
if(!wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv)) if(!wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv))