mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Fix for bug 565742 (too much QIing/Addrefing/Releasing under NativeInterface2JSObject). r=smaug, a=bsmedberg.
This commit is contained in:
parent
72204735c9
commit
1de207af3c
@ -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:
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
@ -123,6 +128,23 @@ 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);
|
||||
|
||||
|
@ -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__ */
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
void SetCanonical(already_AddRefed<nsISupports> aCanonical)
|
||||
if (mCanonical)
|
||||
{
|
||||
mCanonical = aCanonical.get();
|
||||
if (mCanonical) {
|
||||
mCanonicalIsStrong = PR_TRUE;
|
||||
// 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()
|
||||
template <class T>
|
||||
inline
|
||||
qsObjectHelper(nsRefPtr<T>& aObject, nsWrapperCache *aCache)
|
||||
: xpcObjectHelper(ToSupports(aObject.get()),
|
||||
ToCanonicalSupports(aObject.get()), aCache, QS_IS_NODE(T))
|
||||
{
|
||||
if (!mCanonical) {
|
||||
CallQueryInterface(mObject, &mCanonical);
|
||||
mCanonicalIsStrong = PR_TRUE;
|
||||
}
|
||||
return mCanonical;
|
||||
}
|
||||
|
||||
already_AddRefed<nsISupports> TakeCanonical()
|
||||
if (mCanonical)
|
||||
{
|
||||
nsISupports* retval = mCanonical;
|
||||
if (mCanonicalIsStrong) {
|
||||
mCanonicalIsStrong = PR_FALSE;
|
||||
} else {
|
||||
NS_IF_ADDREF(mCanonical);
|
||||
// Transfer the strong reference.
|
||||
mCanonicalStrong = dont_AddRef(mCanonical);
|
||||
aObject.forget();
|
||||
}
|
||||
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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user