Fix for bug 565742 (too much QIing/Addrefing/Releasing under NativeInterface2JSObject). r=smaug, a=bsmedberg.

This commit is contained in:
Peter Van der Beken 2010-07-13 17:44:51 +02:00
parent 72204735c9
commit 1de207af3c
14 changed files with 293 additions and 223 deletions

View File

@ -1152,7 +1152,7 @@ public:
void SetHasRenderingObservers(bool aValue)
{ mNodeHasRenderingObservers = aValue; }
// Optimized way to get classinfo. May return null.
// Optimized way to get classinfo.
virtual nsXPCClassInfo* GetClassInfo() = 0;
protected:

View File

@ -110,21 +110,17 @@ Canvas2D_GetStyleHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
case nsIDOMCanvasRenderingContext2D::CMG_STYLE_PATTERN:
{
nsWrapperCache* cache = xpc_qsGetWrapperCache(resultInterface);
qsObjectHelper helper(ToSupports(resultInterface));
helper.SetNode(resultInterface);
helper.SetCanonical(ToCanonicalSupports(resultInterface));
return xpc_qsXPCOMObjectToJsval(lccx, &helper, cache,
qsObjectHelper helper(resultInterface,
xpc_qsGetWrapperCache(resultInterface));
return xpc_qsXPCOMObjectToJsval(lccx, helper,
&NS_GET_IID(nsIDOMCanvasPattern),
&interfaces[k_nsIDOMCanvasPattern], vp);
}
case nsIDOMCanvasRenderingContext2D::CMG_STYLE_GRADIENT:
{
nsWrapperCache* cache = xpc_qsGetWrapperCache(resultInterface);
qsObjectHelper helper(ToSupports(resultInterface));
helper.SetNode(resultInterface);
helper.SetCanonical(ToCanonicalSupports(resultInterface));
return xpc_qsXPCOMObjectToJsval(lccx, &helper, cache,
qsObjectHelper helper(resultInterface,
xpc_qsGetWrapperCache(resultInterface));
return xpc_qsXPCOMObjectToJsval(lccx, helper,
&NS_GET_IID(nsIDOMCanvasGradient),
&interfaces[k_nsIDOMCanvasGradient], vp);
}

View File

@ -124,11 +124,17 @@ nsXTFElementWrapper::QueryInterface(REFNSIID aIID, void** aInstancePtr)
NS_PRECONDITION(aInstancePtr, "null out param");
NS_IMPL_QUERY_CYCLE_COLLECTION(nsXTFElementWrapper)
if (aIID.Equals(NS_GET_IID(nsIClassInfo))) {
if (aIID.Equals(NS_GET_IID(nsIClassInfo)) ||
aIID.Equals(NS_GET_IID(nsXPCClassInfo))) {
*aInstancePtr = static_cast<nsIClassInfo*>(this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIXPCScriptable))) {
*aInstancePtr = static_cast<nsIXPCScriptable*>(this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIXTFElementWrapper))) {
*aInstancePtr = static_cast<nsIXTFElementWrapper*>(this);
NS_ADDREF_THIS();
@ -681,8 +687,7 @@ nsXTFElementWrapper::GetInterfaces(PRUint32* aCount, nsIID*** aArray)
PRUint32 xtfCount = 0;
nsIID** xtfArray = nsnull;
nsCOMPtr<nsIClassInfo> baseCi =
NS_GetDOMClassInfoInstance(eDOMClassInfo_Element_id);
nsCOMPtr<nsIClassInfo> baseCi = GetBaseXPCClassInfo();
if (baseCi) {
baseCi->GetInterfaces(&baseCount, &baseArray);
}
@ -740,8 +745,7 @@ nsXTFElementWrapper::GetHelperForLanguage(PRUint32 language,
nsISupports** aHelper)
{
*aHelper = nsnull;
nsCOMPtr<nsIClassInfo> ci =
NS_GetDOMClassInfoInstance(eDOMClassInfo_Element_id);
nsCOMPtr<nsIClassInfo> ci = GetBaseXPCClassInfo();
return
ci ? ci->GetHelperForLanguage(language, aHelper) : NS_ERROR_NOT_AVAILABLE;
}

View File

@ -54,7 +54,7 @@ typedef nsXMLElement nsXTFElementWrapperBase;
class nsXTFElementWrapper : public nsXTFElementWrapperBase,
public nsIXTFElementWrapper,
public nsIClassInfo
public nsXPCClassInfo
{
public:
nsXTFElementWrapper(already_AddRefed<nsINodeInfo> aNodeInfo, nsIXTFElement* aXTFElement);
@ -72,6 +72,11 @@ public:
NS_DECL_NSIXTFELEMENTWRAPPER
// nsIContent specializations:
#ifdef HAVE_CPP_AMBIGUITY_RESOLVING_USING
using nsINode::GetProperty;
using nsINode::SetProperty;
#endif
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
@ -122,7 +127,24 @@ public:
// nsIClassInfo interface
NS_DECL_NSICLASSINFO
// nsIXPCScriptable interface
NS_FORWARD_SAFE_NSIXPCSCRIPTABLE(GetBaseXPCClassInfo())
// nsXPCClassInfo
virtual void PreserveWrapper(nsISupports *aNative)
{
nsXPCClassInfo *ci = GetBaseXPCClassInfo();
if (ci) {
ci->PreserveWrapper(aNative);
}
}
virtual PRUint32 GetInterfacesBitmap()
{
nsXPCClassInfo *ci = GetBaseXPCClassInfo();
return ci ? ci->GetInterfacesBitmap() : 0;
}
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
nsresult CloneState(nsIDOMElement *aElement)
@ -131,15 +153,20 @@ public:
}
nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
// XTF elements have special classinfo,
// so this optimization needs to be disabled.
virtual nsXPCClassInfo* GetClassInfo() { return nsnull; }
virtual nsXPCClassInfo* GetClassInfo() { return this; }
protected:
virtual nsIXTFElement* GetXTFElement() const
{
return mXTFElement;
}
static nsXPCClassInfo* GetBaseXPCClassInfo()
{
return static_cast<nsXPCClassInfo*>(
NS_GetDOMClassInfoInstance(eDOMClassInfo_Element_id));
}
// implementation helpers:
PRBool QueryInterfaceInner(REFNSIID aIID, void** result);

View File

@ -76,6 +76,8 @@ xpc_qsUnwrapArg<_interface>(JSContext *cx, \
return rv; \
}
#undef DOMCI_CASTABLE_INTERFACE
#define DOMCI_CASTABLE_INTERFACE(_interface, _base, _bit, _extra) \
DEFINE_UNWRAP_CAST(_interface, _base, _bit)
@ -157,10 +159,4 @@ ToCanonicalSupports(nsContentList *p)
return static_cast<nsINodeList*>(p);
}
inline already_AddRefed<nsISupports>
ToCanonicalSupports(nsCOMPtr<nsIContent>& p)
{
return p.forget().get();
}
#endif /* nsDOMQS_h__ */

View File

@ -1149,11 +1149,13 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
if(NS_FAILED(InitClasses(aJSContext, tempGlobal)))
return UnexpectedFailure(NS_ERROR_FAILURE);
nsresult rv;
xpcObjectHelper helper(aCOMObj);
if(!XPCConvert::NativeInterface2JSObject(ccx, &v,
getter_AddRefs(holder),
aCOMObj, &aIID, nsnull,
nsnull, tempGlobal,
PR_FALSE, OBJ_IS_GLOBAL, &rv))
helper, &aIID, nsnull,
tempGlobal, PR_FALSE,
OBJ_IS_GLOBAL, &rv))
return UnexpectedFailure(rv);
NS_ASSERTION(NS_SUCCEEDED(rv) && holder, "Didn't wrap properly");
@ -1233,10 +1235,10 @@ NativeInterface2JSObject(XPCLazyCallContext & lccx,
nsIXPConnectJSObjectHolder **aHolder)
{
nsresult rv;
if(!XPCConvert::NativeInterface2JSObject(lccx, aVal, aHolder, aCOMObj, aIID,
nsnull, aCache, aScope,
aAllowWrapping, OBJ_IS_NOT_GLOBAL,
&rv))
xpcObjectHelper helper(aCOMObj, aCache);
if(!XPCConvert::NativeInterface2JSObject(lccx, aVal, aHolder, helper, aIID,
nsnull, aScope, aAllowWrapping,
OBJ_IS_NOT_GLOBAL, &rv))
return rv;
#ifdef DEBUG

View File

@ -708,12 +708,10 @@ def writeResultConv(f, type, jsvalPtr, jsvalRef):
" return JS_TRUE;\n"
" }\n"
" }\n"
" qsObjectHelper helper(ToSupports(result));\n"
" helper.SetNode(result);\n"
" helper.SetCanonical(ToCanonicalSupports(result));\n"
" // After this point do not use 'result'!\n"
" qsObjectHelper helper(result, cache);\n"
" return xpc_qsXPCOMObjectToJsval(lccx, "
"&helper, cache, &NS_GET_IID(%s), &interfaces[k_%s], %s);\n"
"helper, &NS_GET_IID(%s), &interfaces[k_%s], %s);\n"
% (jsvalPtr, type.name, type.name, jsvalPtr))
return
@ -1250,12 +1248,10 @@ def writeTraceableResultConv(f, type):
" return wrapper;\n"
" }\n"
" }\n"
" qsObjectHelper helper(ToSupports(result));\n"
" helper.SetNode(result);\n"
" helper.SetCanonical(ToCanonicalSupports(result));\n"
" // After this point do not use 'result'!\n"
" qsObjectHelper helper(result, cache);\n"
" JSBool ok = xpc_qsXPCOMObjectToJsval(lccx, "
"&helper, cache, &NS_GET_IID(%s), &interfaces[k_%s], "
"helper, &NS_GET_IID(%s), &interfaces[k_%s], "
"&vp.array[0]);\n"
% (type.name, type.name))
f.write(" if (!ok) {\n");

View File

@ -4196,7 +4196,8 @@ nsXPCComponents::AttachNewComponentsObject(XPCCallContext& ccx,
return JS_FALSE;
nsCOMPtr<XPCWrappedNative> wrapper;
XPCWrappedNative::GetNewOrUsed(ccx, cholder, aScope, iface, nsnull,
xpcObjectHelper helper(cholder);
XPCWrappedNative::GetNewOrUsed(ccx, helper, aScope, iface,
OBJ_IS_NOT_GLOBAL, getter_AddRefs(wrapper));
if(!wrapper)
return JS_FALSE;

View File

@ -469,8 +469,9 @@ XPCConvert::NativeData2JS(XPCLazyCallContext& lccx, jsval* d, const void* s,
// global object will not have been collected, and
// therefore this NativeInterface2JSObject will not end up
// creating a new XPCNativeScriptableShared.
if(!NativeInterface2JSObject(lccx, d, nsnull, iface, iid,
nsnull, nsnull, scope, PR_TRUE,
xpcObjectHelper helper(iface);
if(!NativeInterface2JSObject(lccx, d, nsnull, helper, iid,
nsnull, scope, PR_TRUE,
OBJ_IS_NOT_GLOBAL, pErr))
return JS_FALSE;
@ -1084,15 +1085,13 @@ JSBool
XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
jsval* d,
nsIXPConnectJSObjectHolder** dest,
nsISupports* src,
xpcObjectHelper& aHelper,
const nsID* iid,
XPCNativeInterface** Interface,
nsWrapperCache *cache,
JSObject* scope,
PRBool allowNativeWrapper,
PRBool isGlobal,
nsresult* pErr,
qsObjectHelper* aHelper)
nsresult* pErr)
{
NS_ASSERTION(scope, "bad param");
NS_ASSERTION(!Interface || iid,
@ -1101,6 +1100,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
*d = JSVAL_NULL;
if(dest)
*dest = nsnull;
nsISupports *src = aHelper.Object();
if(!src)
return JS_TRUE;
if(pErr)
@ -1149,8 +1149,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
if(!xpcscope)
return JS_FALSE;
if(!cache)
CallQueryInterface(src, &cache);
nsWrapperCache *cache = aHelper.GetWrapperCache();
PRBool tryConstructSlimWrapper = PR_FALSE;
JSObject *flat;
@ -1186,7 +1185,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
return JS_FALSE;
jsval slim;
if(ConstructSlimWrapper(ccx, src, aHelper, cache, xpcscope, &slim))
if(ConstructSlimWrapper(ccx, aHelper, xpcscope, &slim))
{
*d = slim;
return JS_TRUE;
@ -1234,8 +1233,8 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
if(!ccx.IsValid())
return JS_FALSE;
rv = XPCWrappedNative::GetNewOrUsed(ccx, src, xpcscope, iface,
cache, isGlobal,
rv = XPCWrappedNative::GetNewOrUsed(ccx, aHelper, xpcscope, iface,
isGlobal,
getter_AddRefs(strongWrapper));
wrapper = strongWrapper;

View File

@ -149,7 +149,7 @@ static FARPROC GetProcAddressA(HMODULE hMod, wchar_t *procName);
#undef GetClassName
#endif
class qsObjectHelper;
#include "nsINode.h"
/***************************************************************************/
// Compile time switches for instrumentation and stuff....
@ -211,13 +211,6 @@ void DEBUG_CheckWrapperThreadSafety(const XPCWrappedNative* wrapper);
#define DEBUG_CheckWrapperThreadSafety(w) ((void)0)
#endif
/***************************************************************************/
// Defeat possible Windows macro-mangling of the name
#ifdef GetClassInfo
#undef GetClassInfo
#endif
/***************************************************************************/
// default initial sizes for maps (hashtables)
@ -2287,11 +2280,9 @@ private:
QITableEntry* mOffsets;
};
class xpcObjectHelper;
extern JSBool ConstructSlimWrapper(XPCCallContext &ccx,
nsISupports *p,
qsObjectHelper* aHelper,
nsWrapperCache* aCache,
xpcObjectHelper &aHelper,
XPCWrappedNativeScope* xpcScope,
jsval *rval);
extern JSBool MorphSlimWrapper(JSContext *cx, JSObject *obj);
@ -2514,16 +2505,11 @@ public:
GetRuntime() const {XPCWrappedNativeScope* scope = GetScope();
return scope ? scope->GetRuntime() : nsnull;}
/**
* If Object has a nsWrapperCache it should be passed in. If a cache is
* passed in then cache->GetWrapper() must be null.
*/
static nsresult
GetNewOrUsed(XPCCallContext& ccx,
nsISupports* Object,
xpcObjectHelper& helper,
XPCWrappedNativeScope* Scope,
XPCNativeInterface* Interface,
nsWrapperCache* cache,
JSBool isGlobal,
XPCWrappedNative** wrapper);
@ -3065,6 +3051,105 @@ private:
/***************************************************************************/
// data conversion
class xpcObjectHelper
{
public:
xpcObjectHelper(nsISupports *aObject, nsWrapperCache *aCache = nsnull)
: mCanonical(nsnull),
mObject(aObject),
mCache(aCache),
mIsNode(PR_FALSE)
{
if(!mCache)
{
if(aObject)
CallQueryInterface(aObject, &mCache);
else
mCache = nsnull;
}
}
nsISupports* Object()
{
return mObject;
}
nsISupports* GetCanonical()
{
if (!mCanonical) {
mCanonicalStrong = do_QueryInterface(mObject);
mCanonical = mCanonicalStrong;
}
return mCanonical;
}
already_AddRefed<nsISupports> forgetCanonical()
{
NS_ASSERTION(mCanonical, "Huh, no canonical to forget?");
if (!mCanonicalStrong)
mCanonicalStrong = mCanonical;
mCanonical = nsnull;
return mCanonicalStrong.forget();
}
nsIClassInfo *GetClassInfo()
{
if(mXPCClassInfo)
return mXPCClassInfo;
if(!mClassInfo)
mClassInfo = do_QueryInterface(mObject);
return mClassInfo;
}
nsXPCClassInfo *GetXPCClassInfo()
{
if(!mXPCClassInfo)
{
if(mIsNode)
mXPCClassInfo = static_cast<nsINode*>(GetCanonical())->GetClassInfo();
else
CallQueryInterface(mObject, getter_AddRefs(mXPCClassInfo));
}
return mXPCClassInfo;
}
already_AddRefed<nsXPCClassInfo> forgetXPCClassInfo()
{
GetXPCClassInfo();
return mXPCClassInfo.forget();
}
nsWrapperCache *GetWrapperCache()
{
return mCache;
}
protected:
xpcObjectHelper(nsISupports *aObject, nsISupports *aCanonical,
nsWrapperCache *aCache, PRBool aIsNode)
: mCanonical(aCanonical),
mObject(aObject),
mCache(aCache),
mIsNode(aIsNode)
{
if(!mCache && aObject)
CallQueryInterface(aObject, &mCache);
}
nsCOMPtr<nsISupports> mCanonicalStrong;
nsISupports* mCanonical;
private:
xpcObjectHelper(xpcObjectHelper& aOther);
nsISupports* mObject;
nsWrapperCache* mCache;
nsCOMPtr<nsIClassInfo> mClassInfo;
nsRefPtr<nsXPCClassInfo> mXPCClassInfo;
PRBool mIsNode;
};
// class here just for static methods
class XPCConvert
{
@ -3121,33 +3206,29 @@ public:
static JSBool NativeInterface2JSObject(XPCCallContext& ccx,
jsval* d,
nsIXPConnectJSObjectHolder** dest,
nsISupports* src,
xpcObjectHelper& aHelper,
const nsID* iid,
XPCNativeInterface** Interface,
nsWrapperCache *cache,
JSObject* scope,
PRBool allowNativeWrapper,
PRBool isGlobal,
nsresult* pErr,
qsObjectHelper* aHelper = nsnull)
nsresult* pErr)
{
XPCLazyCallContext lccx(ccx);
return NativeInterface2JSObject(lccx, d, dest, src, iid, Interface,
cache, scope, allowNativeWrapper,
isGlobal, pErr, aHelper);
return NativeInterface2JSObject(lccx, d, dest, aHelper, iid, Interface,
scope, allowNativeWrapper, isGlobal,
pErr);
}
static JSBool NativeInterface2JSObject(XPCLazyCallContext& lccx,
jsval* d,
nsIXPConnectJSObjectHolder** dest,
nsISupports* src,
xpcObjectHelper& aHelper,
const nsID* iid,
XPCNativeInterface** Interface,
nsWrapperCache *cache,
JSObject* scope,
PRBool allowNativeWrapper,
PRBool isGlobal,
nsresult* pErr,
qsObjectHelper* aHelper = nsnull);
nsresult* pErr);
static JSBool GetNativeInterfaceFromJSObject(XPCCallContext& ccx,
void** dest, JSObject* src,

View File

@ -1110,8 +1110,7 @@ xpc_qsStringToJsstring(JSContext *cx, nsString &str, JSString **rval)
}
JSBool
xpc_qsXPCOMObjectToJsval(XPCLazyCallContext &lccx, qsObjectHelper* aHelper,
nsWrapperCache *cache,
xpc_qsXPCOMObjectToJsval(XPCLazyCallContext &lccx, qsObjectHelper &aHelper,
const nsIID *iid, XPCNativeInterface **iface,
jsval *rval)
{
@ -1130,12 +1129,9 @@ xpc_qsXPCOMObjectToJsval(XPCLazyCallContext &lccx, qsObjectHelper* aHelper,
nsresult rv;
if(!XPCConvert::NativeInterface2JSObject(lccx, rval, nsnull,
aHelper->Object(),
iid, iface,
cache,
aHelper, iid, iface,
lccx.GetCurrentJSObject(), PR_TRUE,
OBJ_IS_NOT_GLOBAL, &rv,
aHelper))
OBJ_IS_NOT_GLOBAL, &rv))
{
// I can't tell if NativeInterface2JSObject throws JS exceptions
// or not. This is a sloppy stab at the right semantics; the

View File

@ -78,78 +78,87 @@ struct xpc_qsHashEntry {
size_t chain;
};
class qsObjectHelper
inline nsISupports*
ToSupports(nsISupports *p)
{
return p;
}
inline nsISupports*
ToCanonicalSupports(nsISupports* p)
{
return nsnull;
}
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
_MSC_FULL_VER >= 140050215
/* Use a compiler intrinsic if one is available. */
#define QS_CASTABLE_TO(_interface, _class) __is_base_of(_interface, _class)
#else
/* The generic version of this predicate relies on the overload resolution
* rules. If |_class| inherits from |_interface|, the |_interface*|
* overload of DOMCI_CastableTo<_interface>::p() will be chosen, otherwise
* the |void*| overload will be chosen. There is no definition of these
* functions; we determine which overload was selected by inspecting the
* size of the return type.
*/
template <typename Interface> struct QS_CastableTo {
struct false_type { int x[1]; };
struct true_type { int x[2]; };
static false_type p(void*);
static true_type p(Interface*);
};
#define QS_CASTABLE_TO(_interface, _class) \
(sizeof(QS_CastableTo<_interface>::p(static_cast<_class*>(0))) == \
sizeof(QS_CastableTo<_interface>::true_type))
#endif
#define QS_IS_NODE(_class) \
QS_CASTABLE_TO(nsINode, _class) || \
QS_CASTABLE_TO(nsIDOMNode, _class)
class qsObjectHelper : public xpcObjectHelper
{
public:
qsObjectHelper(nsISupports* aObject)
: mObject(aObject),
mCanonical(nsnull),
mCanonicalIsStrong(PR_FALSE),
mNode(nsnull) {}
~qsObjectHelper()
template <class T>
inline
qsObjectHelper(T *aObject, nsWrapperCache *aCache)
: xpcObjectHelper(ToSupports(aObject), ToCanonicalSupports(aObject),
aCache, QS_IS_NODE(T))
{}
template <class T>
inline
qsObjectHelper(nsCOMPtr<T>& aObject, nsWrapperCache *aCache)
: xpcObjectHelper(ToSupports(aObject.get()),
ToCanonicalSupports(aObject.get()), aCache, QS_IS_NODE(T))
{
if (mCanonicalIsStrong) {
NS_RELEASE(mCanonical);
if (mCanonical)
{
// Transfer the strong reference.
mCanonicalStrong = dont_AddRef(mCanonical);
aObject.forget();
}
}
void SetCanonical(already_AddRefed<nsISupports> aCanonical)
template <class T>
inline
qsObjectHelper(nsRefPtr<T>& aObject, nsWrapperCache *aCache)
: xpcObjectHelper(ToSupports(aObject.get()),
ToCanonicalSupports(aObject.get()), aCache, QS_IS_NODE(T))
{
mCanonical = aCanonical.get();
if (mCanonical) {
mCanonicalIsStrong = PR_TRUE;
if (mCanonical)
{
// Transfer the strong reference.
mCanonicalStrong = dont_AddRef(mCanonical);
aObject.forget();
}
}
void SetCanonical(nsISupports* aCanonical) { mCanonical = aCanonical; }
void SetNode(nsINode* aNode) { mNode = aNode; }
void SetNode(void* /*aDummy*/) { }
nsISupports* Object() { return mObject; }
nsISupports* GetCanonical()
{
if (!mCanonical) {
CallQueryInterface(mObject, &mCanonical);
mCanonicalIsStrong = PR_TRUE;
}
return mCanonical;
}
already_AddRefed<nsISupports> TakeCanonical()
{
nsISupports* retval = mCanonical;
if (mCanonicalIsStrong) {
mCanonicalIsStrong = PR_FALSE;
} else {
NS_IF_ADDREF(mCanonical);
}
mCanonical = nsnull;
return retval;
}
already_AddRefed<nsXPCClassInfo> GetXPCClassInfo()
{
nsRefPtr<nsXPCClassInfo> ci;
if (mNode) {
ci = mNode->GetClassInfo();
} else {
CallQueryInterface(mObject, getter_AddRefs(ci));
}
return ci.forget();
}
private:
qsObjectHelper(qsObjectHelper& aOther) {}
qsObjectHelper() {}
nsISupports* mObject;
nsISupports* mCanonical;
PRBool mCanonicalIsStrong;
nsINode* mNode;
};
JSBool
@ -630,8 +639,7 @@ xpc_qsGetWrapperCache(void *p)
*/
JSBool
xpc_qsXPCOMObjectToJsval(XPCLazyCallContext &lccx,
qsObjectHelper* aHelper,
nsWrapperCache *cache,
qsObjectHelper &aHelper,
const nsIID *iid,
XPCNativeInterface **iface,
jsval *rval);
@ -644,18 +652,6 @@ xpc_qsVariantToJsval(XPCLazyCallContext &ccx,
nsIVariant *p,
jsval *rval);
inline nsISupports*
ToSupports(nsISupports *p)
{
return p;
}
inline nsISupports*
ToCanonicalSupports(nsISupports* p)
{
return nsnull;
}
#ifdef DEBUG
void
xpc_qsAssertContextOK(JSContext *cx);

View File

@ -1430,10 +1430,11 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
if(newThis)
{
jsval v;
xpcObjectHelper helper(newThis);
JSBool ok =
XPCConvert::NativeInterface2JSObject(ccx,
&v, nsnull, newThis, newWrapperIID,
nsnull, nsnull, obj, PR_FALSE, PR_FALSE,
&v, nsnull, helper, newWrapperIID,
nsnull, obj, PR_FALSE, PR_FALSE,
nsnull);
if(newWrapperIID)
nsMemory::Free(newWrapperIID);

View File

@ -296,30 +296,24 @@ FinishCreate(XPCCallContext& ccx,
// static
nsresult
XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
nsISupports* Object,
xpcObjectHelper& helper,
XPCWrappedNativeScope* Scope,
XPCNativeInterface* Interface,
nsWrapperCache *cache,
JSBool isGlobal,
XPCWrappedNative** resultWrapper)
{
nsWrapperCache *cache = helper.GetWrapperCache();
NS_ASSERTION(!cache || !cache->GetWrapper(),
"We assume the caller already checked if it could get the "
"wrapper from the cache.");
nsresult rv;
#ifdef DEBUG
NS_ASSERTION(!Scope->GetRuntime()->GetThreadRunningGC(),
"XPCWrappedNative::GetNewOrUsed called during GC");
{
nsWrapperCache *cache2 = nsnull;
CallQueryInterface(Object, &cache2);
NS_ASSERTION(!cache == !cache2, "Caller should pass in the cache!");
}
#endif
nsCOMPtr<nsISupports> identity;
nsISupports *identity;
#ifdef XPC_IDISPATCH_SUPPORT
// XXX This is done for the benefit of some warped COM implementations
// where QI(IID_IUnknown, a.b) == QI(IID_IUnknown, a). If someone passes
@ -329,10 +323,10 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
PRBool isIDispatch = Interface &&
Interface->GetIID()->Equals(NSID_IDISPATCH);
if(isIDispatch)
identity = Object;
identity = helper.Object();
else
#endif
identity = do_QueryInterface(Object);
identity = helper.GetCanonical();
if(!identity)
{
@ -396,18 +390,17 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
JSBool isClassInfo = Interface &&
Interface->GetIID()->Equals(NS_GET_IID(nsIClassInfo));
nsCOMPtr<nsIClassInfo> info;
if(!isClassInfo)
info = do_QueryInterface(identity);
nsIClassInfo *info = helper.GetClassInfo();
#ifdef XPC_IDISPATCH_SUPPORT
// If this is an IDispatch wrapper and it didn't give us a class info
// we'll provide a default one
nsCOMPtr<nsIClassInfo> dispatchInfo;
if(isIDispatch && !info)
{
info = dont_AddRef(static_cast<nsIClassInfo*>
dispatchInfo = dont_AddRef(static_cast<nsIClassInfo*>
(XPCIDispatchClassInfo::GetSingleton()));
info = dispatchInfo;
}
#endif
@ -456,8 +449,8 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
XPCWrappedNativeScope* betterScope =
XPCWrappedNativeScope::FindInJSObjectScope(ccx, parent);
if(betterScope != Scope)
return GetNewOrUsed(ccx, identity, betterScope, Interface,
cache, isGlobal, resultWrapper);
return GetNewOrUsed(ccx, helper, betterScope, Interface,
isGlobal, resultWrapper);
newParentVal = OBJECT_TO_JSVAL(parent);
}
@ -510,6 +503,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
}
else
{
nsISupports *Object = helper.Object();
if(nsXPCWrappedJSClass::IsWrappedJS(Object))
{
nsCOMPtr<nsIXPConnectWrappedJS> wrappedjs(do_QueryInterface(Object));
@ -542,8 +536,8 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
proto->CacheOffsets(identity);
wrapper = needsXOW
? new XPCWrappedNativeWithXOW(identity.get(), proto)
: new XPCWrappedNative(identity.get(), proto);
? new XPCWrappedNativeWithXOW(identity, proto)
: new XPCWrappedNative(identity, proto);
if(!wrapper)
return NS_ERROR_FAILURE;
}
@ -560,8 +554,8 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
return NS_ERROR_FAILURE;
wrapper = needsXOW
? new XPCWrappedNativeWithXOW(identity.get(), Scope, set)
: new XPCWrappedNative(identity.get(), Scope, set);
? new XPCWrappedNativeWithXOW(identity, Scope, set)
: new XPCWrappedNative(identity, Scope, set);
if(!wrapper)
return NS_ERROR_FAILURE;
@ -570,8 +564,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
// The strong reference was taken over by the wrapper, so make the nsCOMPtr
// forget about it.
// Note that identity is null from here on!
identity.forget();
helper.forgetCanonical();
NS_ADDREF(wrapper);
@ -3853,25 +3846,11 @@ static PRUint32 sSlimWrappers;
JSBool
ConstructSlimWrapper(XPCCallContext &ccx,
nsISupports *p,
qsObjectHelper* aHelper,
nsWrapperCache* cache,
xpcObjectHelper &aHelper,
XPCWrappedNativeScope* xpcScope, jsval *rval)
{
nsCOMPtr<nsISupports> strongIdentity;
nsISupports* identityObj = aHelper ? aHelper->GetCanonical() : nsnull;
if (!identityObj) {
strongIdentity = do_QueryInterface(p);
identityObj = strongIdentity.get();
}
nsRefPtr<nsXPCClassInfo> classInfoHelper;
if (aHelper) {
classInfoHelper = aHelper->GetXPCClassInfo();
}
if (!classInfoHelper) {
CallQueryInterface(p, getter_AddRefs(classInfoHelper));
}
nsISupports *identityObj = aHelper.GetCanonical();
nsXPCClassInfo *classInfoHelper = aHelper.GetXPCClassInfo();
JSUint32 flagsInt;
nsresult rv = classInfoHelper->GetScriptableFlags(&flagsInt);
@ -3915,6 +3894,7 @@ ConstructSlimWrapper(XPCCallContext &ccx,
// The PreCreate hook could have forced the creation of a wrapper, need
// to check for that here and return early.
nsWrapperCache *cache = aHelper.GetWrapperCache();
JSObject* wrapper = cache->GetWrapper();
if(wrapper)
{
@ -3923,16 +3903,15 @@ ConstructSlimWrapper(XPCCallContext &ccx,
return JS_TRUE;
}
nsIClassInfo* classInfo = classInfoHelper;
PRUint32 interfacesBitmap = classInfoHelper->GetInterfacesBitmap();
XPCNativeScriptableCreateInfo
sciProto(classInfoHelper.forget().get(), flags, interfacesBitmap);
sciProto(aHelper.forgetXPCClassInfo(), flags, interfacesBitmap);
AutoMarkingWrappedNativeProtoPtr xpcproto(ccx);
JSBool isGlobal = JS_FALSE;
xpcproto = XPCWrappedNativeProto::GetNewOrUsed(ccx, xpcScope, classInfo,
&sciProto, JS_FALSE,
isGlobal);
xpcproto = XPCWrappedNativeProto::GetNewOrUsed(ccx, xpcScope,
classInfoHelper, &sciProto,
JS_FALSE, isGlobal);
if(!xpcproto)
return JS_FALSE;
@ -3952,11 +3931,7 @@ ConstructSlimWrapper(XPCCallContext &ccx,
return JS_FALSE;
// Transfer ownership to the wrapper's private.
if (strongIdentity) {
strongIdentity.forget();
} else {
aHelper->TakeCanonical();
}
aHelper.forgetCanonical();
cache->SetWrapper(wrapper);