Prevent circular ownership leaks via XPCOM-JS cycles through treewalker's filter, the same way we do for event listeners. b=323534 r=mrbkap sr=jst
git-svn-id: svn://10.0.0.236/trunk@187810 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
934879ff1e
commit
6af4529cc1
@ -84,11 +84,11 @@ nsTreeWalker::nsTreeWalker(nsIDOMNode *aRoot,
|
||||
PRBool aExpandEntityReferences) :
|
||||
mRoot(aRoot),
|
||||
mWhatToShow(aWhatToShow),
|
||||
mFilter(aFilter),
|
||||
mExpandEntityReferences(aExpandEntityReferences),
|
||||
mCurrentNode(aRoot),
|
||||
mPossibleIndexesPos(-1)
|
||||
{
|
||||
mFilter.Set(aFilter, this);
|
||||
|
||||
NS_ASSERTION(aRoot, "invalid root in call to nsTreeWalker constructor");
|
||||
}
|
||||
@ -105,7 +105,8 @@ nsTreeWalker::~nsTreeWalker()
|
||||
// QueryInterface implementation for nsTreeWalker
|
||||
NS_INTERFACE_MAP_BEGIN(nsTreeWalker)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMTreeWalker)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMGCParticipant)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMTreeWalker)
|
||||
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(TreeWalker)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
@ -136,8 +137,10 @@ NS_IMETHODIMP nsTreeWalker::GetWhatToShow(PRUint32 *aWhatToShow)
|
||||
NS_IMETHODIMP nsTreeWalker::GetFilter(nsIDOMNodeFilter * *aFilter)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFilter);
|
||||
*aFilter = mFilter;
|
||||
NS_IF_ADDREF(*aFilter);
|
||||
|
||||
nsCOMPtr<nsIDOMNodeFilter> filter = mFilter.Get();
|
||||
filter.swap((*aFilter = nsnull));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -269,6 +272,29 @@ NS_IMETHODIMP nsTreeWalker::NextNode(nsIDOMNode **_retval)
|
||||
_retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* nsIDOMGCParticipant functions
|
||||
*/
|
||||
/* virtual */ nsIDOMGCParticipant*
|
||||
nsTreeWalker::GetSCCIndex()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsTreeWalker::AppendReachableList(nsCOMArray<nsIDOMGCParticipant>& aArray)
|
||||
{
|
||||
nsCOMPtr<nsIDOMGCParticipant> gcp;
|
||||
|
||||
gcp = do_QueryInterface(mRoot);
|
||||
if (gcp)
|
||||
aArray.AppendObject(gcp);
|
||||
|
||||
gcp = do_QueryInterface(mCurrentNode);
|
||||
if (gcp)
|
||||
aArray.AppendObject(gcp);
|
||||
}
|
||||
|
||||
/*
|
||||
* nsTreeWalker helper functions
|
||||
*/
|
||||
@ -594,8 +620,9 @@ nsresult nsTreeWalker::TestNode(nsIDOMNode* aNode, PRInt16* _filtered)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mFilter)
|
||||
return mFilter->AcceptNode(aNode, _filtered);
|
||||
nsCOMPtr<nsIDOMNodeFilter> filter = mFilter.Get();
|
||||
if (filter)
|
||||
return filter->AcceptNode(aNode, _filtered);
|
||||
|
||||
*_filtered = nsIDOMNodeFilter::FILTER_ACCEPT;
|
||||
return NS_OK;
|
||||
|
||||
@ -49,13 +49,19 @@
|
||||
#include "nsIDOMNodeFilter.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIDOMGCParticipant.h"
|
||||
#include "nsJSUtils.h"
|
||||
|
||||
class nsTreeWalker : public nsIDOMTreeWalker
|
||||
class nsTreeWalker : public nsIDOMTreeWalker, public nsIDOMGCParticipant
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMTREEWALKER
|
||||
|
||||
// nsIDOMGCParticipant
|
||||
virtual nsIDOMGCParticipant* GetSCCIndex();
|
||||
virtual void AppendReachableList(nsCOMArray<nsIDOMGCParticipant>& aArray);
|
||||
|
||||
nsTreeWalker(nsIDOMNode *aRoot,
|
||||
PRUint32 aWhatToShow,
|
||||
nsIDOMNodeFilter *aFilter,
|
||||
@ -65,7 +71,7 @@ public:
|
||||
private:
|
||||
nsCOMPtr<nsIDOMNode> mRoot;
|
||||
PRUint32 mWhatToShow;
|
||||
nsCOMPtr<nsIDOMNodeFilter> mFilter;
|
||||
nsMarkedJSFunctionHolder<nsIDOMNodeFilter> mFilter;
|
||||
PRBool mExpandEntityReferences;
|
||||
nsCOMPtr<nsIDOMNode> mCurrentNode;
|
||||
|
||||
|
||||
@ -414,6 +414,11 @@ static const char kDOMStringBundleURL[] =
|
||||
// NOTE: DEFAULT_SCRIPTABLE_FLAGS and DOM_DEFAULT_SCRIPTABLE_FLAGS
|
||||
// are defined in nsIDOMClassInfo.h.
|
||||
|
||||
#define GCPARTICIPANT_SCRIPTABLE_FLAGS \
|
||||
(DOM_DEFAULT_SCRIPTABLE_FLAGS | \
|
||||
nsIXPCScriptable::WANT_FINALIZE | \
|
||||
nsIXPCScriptable::WANT_MARK)
|
||||
|
||||
#define WINDOW_SCRIPTABLE_FLAGS \
|
||||
(nsIXPCScriptable::WANT_GETPROPERTY | \
|
||||
nsIXPCScriptable::WANT_SETPROPERTY | \
|
||||
@ -429,12 +434,10 @@ static const char kDOMStringBundleURL[] =
|
||||
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE)
|
||||
|
||||
#define NODE_SCRIPTABLE_FLAGS \
|
||||
((DOM_DEFAULT_SCRIPTABLE_FLAGS | \
|
||||
((GCPARTICIPANT_SCRIPTABLE_FLAGS | \
|
||||
nsIXPCScriptable::WANT_PRECREATE | \
|
||||
nsIXPCScriptable::WANT_ADDPROPERTY | \
|
||||
nsIXPCScriptable::WANT_SETPROPERTY | \
|
||||
nsIXPCScriptable::WANT_FINALIZE | \
|
||||
nsIXPCScriptable::WANT_MARK) & \
|
||||
nsIXPCScriptable::WANT_SETPROPERTY) & \
|
||||
~nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY)
|
||||
|
||||
// We need to let JavaScript QI elements to interfaces that are not in
|
||||
@ -815,8 +818,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
// DOM Traversal classes
|
||||
NS_DEFINE_CLASSINFO_DATA(TreeWalker, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(TreeWalker, nsDOMGCParticipantSH,
|
||||
GCPARTICIPANT_SCRIPTABLE_FLAGS)
|
||||
|
||||
// We are now trying to preserve binary compat in classinfo. No
|
||||
// more putting things in those categories up there. New entries
|
||||
@ -6657,8 +6660,8 @@ nsEventReceiverSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
|
||||
*objp = obj;
|
||||
}
|
||||
|
||||
return nsDOMClassInfo::NewResolve(wrapper, cx, obj, id, flags, objp,
|
||||
_retval);
|
||||
return nsDOMGCParticipantSH::NewResolve(wrapper, cx, obj, id, flags, objp,
|
||||
_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -6685,19 +6688,21 @@ nsEventReceiverSH::AddProperty(nsIXPConnectWrappedNative *wrapper,
|
||||
return nsEventReceiverSH::SetProperty(wrapper, cx, obj, id, vp, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEventReceiverSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj)
|
||||
{
|
||||
// XXX clear event handlers in mListener...
|
||||
// XXX nsEventReceiverSH::Finalize: clear event handlers in mListener...
|
||||
|
||||
// DOMGCParticipant helper
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMGCParticipantSH::Finalize(nsIXPConnectWrappedNative *wrapper,
|
||||
JSContext *cx, JSObject *obj)
|
||||
{
|
||||
nsDOMClassInfo::ReleaseWrapper(wrapper);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEventReceiverSH::Mark(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, void *arg, PRUint32 *_retval)
|
||||
nsDOMGCParticipantSH::Mark(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, void *arg, PRUint32 *_retval)
|
||||
{
|
||||
nsCOMPtr<nsIDOMGCParticipant> participant(do_QueryWrappedNative(wrapper));
|
||||
|
||||
|
||||
@ -370,15 +370,39 @@ protected:
|
||||
|
||||
typedef nsDOMClassInfo nsDOMGenericSH;
|
||||
|
||||
// Scriptable helper for implementations of nsIDOMGCParticipant that
|
||||
// need a mark callback.
|
||||
class nsDOMGCParticipantSH : public nsDOMGenericSH
|
||||
{
|
||||
protected:
|
||||
nsDOMGCParticipantSH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~nsDOMGCParticipantSH()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj);
|
||||
NS_IMETHOD Mark(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, void *arg, PRUint32 *_retval);
|
||||
|
||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||
{
|
||||
return new nsDOMGCParticipantSH(aData);
|
||||
}
|
||||
};
|
||||
|
||||
// EventProp scriptable helper, this class should be the base class of
|
||||
// all objects that should support things like
|
||||
// obj.onclick=function{...}
|
||||
|
||||
class nsEventReceiverSH : public nsDOMGenericSH
|
||||
class nsEventReceiverSH : public nsDOMGCParticipantSH
|
||||
{
|
||||
protected:
|
||||
nsEventReceiverSH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
|
||||
nsEventReceiverSH(nsDOMClassInfoData* aData) : nsDOMGCParticipantSH(aData)
|
||||
{
|
||||
}
|
||||
|
||||
@ -420,10 +444,6 @@ public:
|
||||
PRBool *_retval);
|
||||
NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
|
||||
NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj);
|
||||
NS_IMETHOD Mark(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, void *arg, PRUint32 *_retval);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -260,7 +260,8 @@ PRBool
|
||||
nsMarkedJSFunctionHolder_base::TryMarkedSet(nsISupports *aPotentialFunction,
|
||||
nsIDOMGCParticipant *aParticipant)
|
||||
{
|
||||
NS_ENSURE_TRUE(aParticipant, PR_FALSE);
|
||||
if (!aParticipant)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS =
|
||||
do_QueryInterface(aPotentialFunction);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user