diff --git a/js/src/xpconnect/src/xpcconvert.cpp b/js/src/xpconnect/src/xpcconvert.cpp index 2adc4a93acf2..dd088d9339e4 100644 --- a/js/src/xpconnect/src/xpcconvert.cpp +++ b/js/src/xpconnect/src/xpcconvert.cpp @@ -827,35 +827,42 @@ XPCConvert::JSObject2NativeInterface(XPCCallContext& ccx, nsISupports* iface; - // is this really a native xpcom object with a wrapper? - XPCWrappedNative* wrappedNative = - XPCWrappedNative::GetWrappedNativeOfJSObject(cx, src); - if(wrappedNative) + + if(!aOuter) { - iface = wrappedNative->GetIdentityObject(); - // is the underlying object the right interface? - if(wrappedNative->GetIID().Equals(*iid)) + // Note that if we have a non-null aOuter then it means that we are + // forcing the creation of a wrapper even if the object *is* a + // wrappedNative or other wise has 'nsISupportness'. + // This allows wrapJSAggregatedToNative to work. + + // Is this really a native xpcom object with a wrapper? + XPCWrappedNative* wrappedNative = + XPCWrappedNative::GetWrappedNativeOfJSObject(cx, src); + if(wrappedNative) { - NS_ADDREF(iface); - *dest = iface; - return JS_TRUE; + iface = wrappedNative->GetIdentityObject(); + // is the underlying object the right interface? + if(wrappedNative->GetIID().Equals(*iid)) + { + NS_ADDREF(iface); + *dest = iface; + return JS_TRUE; + } + else + return NS_SUCCEEDED(iface->QueryInterface(*iid, dest)); + } + // else... + + // Does the JSObject have 'nsISupportness'? + // XXX hmm, I wonder if this matters anymore with no + // oldstyle DOM objects around. + if(GetISupportsFromJSObject(cx, src, &iface)) + { + if(iface) + return NS_SUCCEEDED(iface->QueryInterface(*iid, dest)); + return JS_FALSE; + } - else - return NS_SUCCEEDED(iface->QueryInterface(*iid, dest)); - } - // else... - - // Does the JSObject have 'nsISupportness'? (as do DOM objects.) - // Note that if we have a non-null aOuter then it means that we are - // forcing the creation of a wrapper even if the object *does* have - // 'nsISupportness'. This allows wrapJSAggregatedToNative to work - // with JSObjects that happen to have 'nsISupportness'. - if(!aOuter && GetISupportsFromJSObject(cx, src, &iface)) - { - if(iface) - return NS_SUCCEEDED(iface->QueryInterface(*iid, dest)); - return JS_FALSE; - } // else... diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 9b9ed729c4be..596215727a91 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -2505,6 +2505,13 @@ public: void ClearRecentContext() {mMostRecentJSContext = nsnull; mMostRecentXPCContext = nsnull;} +#ifdef XPC_CHECK_WRAPPER_THREADSAFETY + JSUint32 IncrementWrappedNativeThreadsafetyReportDepth() + {return ++mWrappedNativeThreadsafetyReportDepth;} + void ClearWrappedNativeThreadsafetyReportDepth() + {mWrappedNativeThreadsafetyReportDepth = 0;} +#endif + private: XPCPerThreadData(); @@ -2521,6 +2528,9 @@ private: nsIExceptionManager* mExceptionManager; nsIException* mException; JSBool mExceptionManagerNotAvailable; +#ifdef XPC_CHECK_WRAPPER_THREADSAFETY + JSUint32 mWrappedNativeThreadsafetyReportDepth; +#endif static PRLock* gLock; static XPCPerThreadData* gThreads; diff --git a/js/src/xpconnect/src/xpcthreadcontext.cpp b/js/src/xpconnect/src/xpcthreadcontext.cpp index ba1979d36a35..ed0dd6609c3f 100644 --- a/js/src/xpconnect/src/xpcthreadcontext.cpp +++ b/js/src/xpconnect/src/xpcthreadcontext.cpp @@ -347,7 +347,9 @@ XPCPerThreadData::XPCPerThreadData() mExceptionManager(nsnull), mException(nsnull), mExceptionManagerNotAvailable(JS_FALSE) - +#ifdef XPC_CHECK_WRAPPER_THREADSAFETY + , mWrappedNativeThreadsafetyReportDepth(0) +#endif { if(gLock) { diff --git a/js/src/xpconnect/src/xpcwrappednative.cpp b/js/src/xpconnect/src/xpcwrappednative.cpp index 42178632700d..5bdc5e850426 100644 --- a/js/src/xpconnect/src/xpcwrappednative.cpp +++ b/js/src/xpconnect/src/xpcwrappednative.cpp @@ -781,10 +781,10 @@ XPCWrappedNative::AddRef(void) NS_LOG_ADDREF(this, cnt, "XPCWrappedNative", sizeof(*this)); if(2 == cnt && IsValid()) { - XPCCallContext ccx(NATIVE_CALLER); - if(ccx.IsValid()) - JS_AddNamedRoot(ccx, &mFlatJSObject, - "XPCWrappedNative::mFlatJSObject"); + XPCJSRuntime* rt = GetRuntime(); + if(rt) + JS_AddNamedRootRT(rt->GetJSRuntime(), &mFlatJSObject, + "XPCWrappedNative::mFlatJSObject"); } return cnt; } @@ -2671,6 +2671,10 @@ void DEBUG_ReportWrapperThreadSafetyError(XPCCallContext& ccx, const char* msg, const XPCWrappedNative* wrapper) { + XPCPerThreadData* tls = ccx.GetThreadData(); + if(1 != tls->IncrementWrappedNativeThreadsafetyReportDepth()) + return; + printf("---------------------------------------------------------------\n"); printf("!!!!! XPConnect wrapper thread use error...\n"); @@ -2686,7 +2690,8 @@ void DEBUG_ReportWrapperThreadSafetyError(XPCCallContext& ccx, printf(" JS call stack...\n"); xpc_DumpJSStack(ccx, JS_TRUE, JS_TRUE, JS_TRUE); printf("---------------------------------------------------------------\n"); - + + tls->ClearWrappedNativeThreadsafetyReportDepth(); } void DEBUG_CheckWrapperThreadSafety(const XPCWrappedNative* wrapper) @@ -2710,8 +2715,9 @@ void DEBUG_CheckWrapperThreadSafety(const XPCWrappedNative* wrapper) { XPCCallContext ccx(NATIVE_CALLER); DEBUG_ReportWrapperThreadSafetyError(ccx, - "Wrapper accessed on multiple threads without having an " - "nsIClassInfo that set the 'THREADSAFE' flag", wrapper); + "XPConnect WrappedNative is being accessed on multiple threads but " + "the underlying native xpcom object does not have a " + "nsIClassInfo with the 'THREADSAFE' flag set", wrapper); } } #endif