зеркало из https://github.com/mozilla/gecko-dev.git
Expose method for getting a 'safe' JSContext appropriate for use on the current thread. This will help travis fix bug 33489. r=brendan@mozilla.org.
This commit is contained in:
Родитель
8acaad0615
Коммит
7ab8e93ba3
|
@ -40,8 +40,16 @@
|
|||
[uuid(c67d8270-3189-11d3-9885-006008962422)]
|
||||
interface nsIJSContextStack : nsISupports
|
||||
{
|
||||
readonly attribute PRInt32 Count;
|
||||
JSContext Peek();
|
||||
JSContext Pop();
|
||||
void Push(in JSContext cx);
|
||||
readonly attribute PRInt32 count;
|
||||
JSContext peek();
|
||||
JSContext pop();
|
||||
void push(in JSContext cx);
|
||||
};
|
||||
|
||||
[uuid(a1339ae0-05c1-11d4-8f92-0010a4e73d9a)]
|
||||
interface nsIThreadJSContextStack : nsIJSContextStack
|
||||
{
|
||||
/* inherits methods of nsIJSContextStack */
|
||||
|
||||
readonly attribute JSContext safeJSContext;
|
||||
};
|
||||
|
|
|
@ -46,135 +46,11 @@ nsXPConnect* nsXPConnect::gSelf = nsnull;
|
|||
|
||||
/***************************************************************************/
|
||||
|
||||
class xpcPerThreadData
|
||||
{
|
||||
public:
|
||||
xpcPerThreadData();
|
||||
~xpcPerThreadData();
|
||||
|
||||
nsIXPCException* GetException();
|
||||
void SetException(nsIXPCException* aException);
|
||||
|
||||
JSContext* GetJSContext();
|
||||
|
||||
private:
|
||||
nsIXPCException* mException;
|
||||
JSContext* mCX;
|
||||
};
|
||||
|
||||
xpcPerThreadData::xpcPerThreadData()
|
||||
: mException(nsnull),
|
||||
mCX(nsnull)
|
||||
{
|
||||
// empty...
|
||||
}
|
||||
|
||||
xpcPerThreadData::~xpcPerThreadData()
|
||||
{
|
||||
NS_IF_RELEASE(mException);
|
||||
if(mCX)
|
||||
JS_DestroyContext(mCX);
|
||||
}
|
||||
|
||||
nsIXPCException*
|
||||
xpcPerThreadData::GetException()
|
||||
{
|
||||
NS_IF_ADDREF(mException);
|
||||
return mException;
|
||||
}
|
||||
|
||||
void
|
||||
xpcPerThreadData::SetException(nsIXPCException* aException)
|
||||
{
|
||||
NS_IF_ADDREF(aException);
|
||||
NS_IF_RELEASE(mException);
|
||||
mException = aException;
|
||||
}
|
||||
|
||||
static JSClass global_class = {
|
||||
"globalForDefaultXPConnectJSContext", 0,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||
};
|
||||
|
||||
JSContext*
|
||||
xpcPerThreadData::GetJSContext()
|
||||
{
|
||||
if(!mCX)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIJSRuntimeService, rtsvc, "nsJSRuntimeService", &rv);
|
||||
if(NS_SUCCEEDED(rv) && NS_SUCCEEDED(rtsvc->GetRuntime(&rt)))
|
||||
{
|
||||
NS_WITH_SERVICE(nsIXPConnect, xpc, nsIXPConnect::GetCID(), &rv);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
mCX = JS_NewContext(rt, 8192);
|
||||
if(mCX)
|
||||
{
|
||||
JSObject *glob;
|
||||
glob = JS_NewObject(mCX, &global_class, NULL, NULL);
|
||||
if(!glob ||
|
||||
!JS_InitStandardClasses(mCX, glob) ||
|
||||
NS_FAILED(xpc->InitClasses(mCX, glob)))
|
||||
{
|
||||
JS_DestroyContext(mCX);
|
||||
mCX = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mCX;
|
||||
}
|
||||
|
||||
/*************************************************/
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void)
|
||||
xpc_ThreadDataDtorCB(void* ptr)
|
||||
{
|
||||
xpcPerThreadData* data = (xpcPerThreadData*) ptr;
|
||||
if(data)
|
||||
delete data;
|
||||
}
|
||||
|
||||
static xpcPerThreadData*
|
||||
GetPerThreadData()
|
||||
{
|
||||
#define BAD_TLS_INDEX ((PRUintn) -1)
|
||||
xpcPerThreadData* data;
|
||||
static PRUintn index = BAD_TLS_INDEX;
|
||||
if(index == BAD_TLS_INDEX)
|
||||
{
|
||||
if(PR_FAILURE == PR_NewThreadPrivateIndex(&index, xpc_ThreadDataDtorCB))
|
||||
{
|
||||
NS_ASSERTION(0, "PR_NewThreadPrivateIndex failed!");
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
data = (xpcPerThreadData*) PR_GetThreadPrivate(index);
|
||||
if(!data)
|
||||
{
|
||||
if(nsnull != (data = new xpcPerThreadData()))
|
||||
{
|
||||
if(PR_FAILURE == PR_SetThreadPrivate(index, data))
|
||||
{
|
||||
NS_ASSERTION(0, "PR_SetThreadPrivate failed!");
|
||||
delete data;
|
||||
data = nsnull;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERTION(0, "new xpcPerThreadData failed!");
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
// XXX In the worst case this makes 3 trips to get TLS (Thread Locl Storage).
|
||||
// Since nsXPCThreadJSContextStackImpl is in our module and uses our
|
||||
// xpcPerThreadData we could add static methods to nsXPCThreadJSContextStackImpl
|
||||
// which take xpcPerThreadData as a param and do the below with only one trip
|
||||
// to TLS.
|
||||
|
||||
AutoPushCompatibleJSContext::AutoPushCompatibleJSContext(JSRuntime* rt, nsXPConnect* xpc /*= nsnull*/)
|
||||
: mCX(nsnull)
|
||||
|
@ -183,34 +59,30 @@ AutoPushCompatibleJSContext::AutoPushCompatibleJSContext(JSRuntime* rt, nsXPConn
|
|||
mContextStack = nsXPConnect::GetContextStack(xpc);
|
||||
if(mContextStack)
|
||||
{
|
||||
JSContext* current;
|
||||
JSContext* cx;
|
||||
JSContext* safeCX;
|
||||
|
||||
if(NS_SUCCEEDED(mContextStack->Peek(¤t)))
|
||||
if(NS_SUCCEEDED(mContextStack->Peek(&cx)))
|
||||
{
|
||||
// Is the current runtime compatible?
|
||||
if(current && JS_GetRuntime(current) == rt)
|
||||
if(cx && JS_GetRuntime(cx) == rt)
|
||||
{
|
||||
mCX = current;
|
||||
mCX = cx;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The stack is either empty or the context is of the wrong
|
||||
// runtime. Either way we need to *get* a compatible runtime
|
||||
// and push it on the stack. xpconnect's per thread data will
|
||||
// give us a JSContext.
|
||||
// and push it on the stack.
|
||||
|
||||
xpcPerThreadData* data = GetPerThreadData();
|
||||
if(data)
|
||||
if(NS_SUCCEEDED(mContextStack->GetSafeJSContext(&safeCX)) &&
|
||||
safeCX && JS_GetRuntime(safeCX) == rt &&
|
||||
NS_SUCCEEDED(mContextStack->Push(safeCX)))
|
||||
{
|
||||
JSContext* ourCX = data->GetJSContext();
|
||||
if(ourCX && JS_GetRuntime(ourCX) == rt &&
|
||||
NS_SUCCEEDED(mContextStack->Push(ourCX)))
|
||||
{
|
||||
mCX = ourCX;
|
||||
// Leave the reference to the mContextStack to
|
||||
// indicate that we need to pop it in our dtor.
|
||||
return;
|
||||
}
|
||||
mCX = safeCX;
|
||||
// Leave the reference to the mContextStack to
|
||||
// indicate that we need to pop it in our dtor.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -268,7 +140,7 @@ nsXPConnect::nsXPConnect()
|
|||
mThrower = new XPCJSThrower(JS_TRUE);
|
||||
|
||||
nsServiceManager::GetService("nsThreadJSContextStack",
|
||||
NS_GET_IID(nsIJSContextStack),
|
||||
NS_GET_IID(nsIThreadJSContextStack),
|
||||
(nsISupports **)&mContextStack);
|
||||
|
||||
#ifdef XPC_TOOLS_SUPPORT
|
||||
|
@ -378,11 +250,11 @@ nsXPConnect::ReleaseXPConnectSingleton()
|
|||
if(GetRuntime() && GetRuntime()->GetJSRuntime())
|
||||
{
|
||||
AutoPushCompatibleJSContext a(GetRuntime()->GetJSRuntime());
|
||||
if(a.GetJSContext())
|
||||
if(a.GetSafeJSContext())
|
||||
{
|
||||
FILE* oldFileHandle = js_DumpGCHeap;
|
||||
js_DumpGCHeap = stdout;
|
||||
js_ForceGC(a.GetJSContext());
|
||||
js_ForceGC(a.GetSafeJSContext());
|
||||
js_DumpGCHeap = oldFileHandle;
|
||||
}
|
||||
}
|
||||
|
@ -419,10 +291,10 @@ nsXPConnect::GetInterfaceInfoManager(nsXPConnect* xpc /*= nsnull*/)
|
|||
}
|
||||
|
||||
// static
|
||||
nsIJSContextStack*
|
||||
nsIThreadJSContextStack*
|
||||
nsXPConnect::GetContextStack(nsXPConnect* xpc /*= nsnull*/)
|
||||
{
|
||||
nsIJSContextStack* cs;
|
||||
nsIThreadJSContextStack* cs;
|
||||
nsXPConnect* xpcl = xpc;
|
||||
|
||||
if(!xpcl && !(xpcl = GetXPConnect()))
|
||||
|
@ -764,7 +636,7 @@ nsXPConnect::GetPendingException(nsIXPCException * *aPendingException)
|
|||
{
|
||||
NS_ENSURE_ARG_POINTER(aPendingException);
|
||||
|
||||
xpcPerThreadData* data = GetPerThreadData();
|
||||
xpcPerThreadData* data = xpcPerThreadData::GetData();
|
||||
if(!data)
|
||||
{
|
||||
*aPendingException = nsnull;
|
||||
|
@ -778,7 +650,7 @@ nsXPConnect::GetPendingException(nsIXPCException * *aPendingException)
|
|||
NS_IMETHODIMP
|
||||
nsXPConnect::SetPendingException(nsIXPCException * aPendingException)
|
||||
{
|
||||
xpcPerThreadData* data = GetPerThreadData();
|
||||
xpcPerThreadData* data = xpcPerThreadData::GetData();
|
||||
if(!data)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
@ -884,13 +756,13 @@ nsXPConnect::DebugDumpJSStack(PRBool showArgs, PRBool showLocals, PRBool showThi
|
|||
#ifdef DEBUG
|
||||
JSContext* cx;
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIJSContextStack, stack, "nsThreadJSContextStack", &rv);
|
||||
NS_WITH_SERVICE(nsIThreadJSContextStack, stack, "nsThreadJSContextStack", &rv);
|
||||
if(NS_FAILED(rv))
|
||||
printf("failed to get nsIJSContextStack service!\n");
|
||||
printf("failed to get nsIThreadJSContextStack service!\n");
|
||||
else if(NS_FAILED(stack->Peek(&cx)))
|
||||
printf("failed to peek into nsIJSContextStack service!\n");
|
||||
printf("failed to peek into nsIThreadJSContextStack service!\n");
|
||||
else if(!cx)
|
||||
printf("there is no JSContext on the nsIJSContextStack!\n");
|
||||
printf("there is no JSContext on the nsIThreadJSContextStack!\n");
|
||||
else
|
||||
xpc_DumpJSStack(cx, showArgs, showLocals, showThisProps);
|
||||
#endif
|
||||
|
@ -904,13 +776,13 @@ nsXPConnect::DebugDumpEvalInJSStackFrame(PRUint32 aFrameNumber, const char *aSou
|
|||
#ifdef DEBUG
|
||||
JSContext* cx;
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIJSContextStack, stack, "nsThreadJSContextStack", &rv);
|
||||
NS_WITH_SERVICE(nsIThreadJSContextStack, stack, "nsThreadJSContextStack", &rv);
|
||||
if(NS_FAILED(rv))
|
||||
printf("failed to get nsIJSContextStack service!\n");
|
||||
printf("failed to get nsIThreadJSContextStack service!\n");
|
||||
else if(NS_FAILED(stack->Peek(&cx)))
|
||||
printf("failed to peek into nsIJSContextStack service!\n");
|
||||
printf("failed to peek into nsIThreadJSContextStack service!\n");
|
||||
else if(!cx)
|
||||
printf("there is no JSContext on the nsIJSContextStack!\n");
|
||||
printf("there is no JSContext on the nsIThreadJSContextStack!\n");
|
||||
else
|
||||
xpc_DumpEvalInJSStackFrame(cx, aFrameNumber, aSourceText);
|
||||
#endif
|
||||
|
|
|
@ -135,7 +135,7 @@ public:
|
|||
// these all return an AddRef'd object (or nsnull on failure)
|
||||
static nsXPConnect* GetXPConnect();
|
||||
static nsIInterfaceInfoManager* GetInterfaceInfoManager(nsXPConnect* xpc = nsnull);
|
||||
static nsIJSContextStack* GetContextStack(nsXPConnect* xpc = nsnull);
|
||||
static nsIThreadJSContextStack* GetContextStack(nsXPConnect* xpc = nsnull);
|
||||
static XPCJSThrower* GetJSThrower(nsXPConnect* xpc = nsnull);
|
||||
static XPCJSRuntime* GetRuntime(nsXPConnect* xpc = nsnull);
|
||||
static XPCContext* GetContext(JSContext* cx, nsXPConnect* xpc = nsnull);
|
||||
|
@ -167,7 +167,7 @@ private:
|
|||
nsIXPCScriptable* mArbitraryScriptable;
|
||||
nsIInterfaceInfoManager* mInterfaceInfoManager;
|
||||
XPCJSThrower* mThrower;
|
||||
nsIJSContextStack* mContextStack;
|
||||
nsIThreadJSContextStack* mContextStack;
|
||||
nsIXPCSecurityManager* mDefaultSecurityManager;
|
||||
PRUint16 mDefaultSecurityManagerFlags;
|
||||
#ifdef XPC_TOOLS_SUPPORT
|
||||
|
@ -424,7 +424,7 @@ private:
|
|||
AutoPushJSContext(); // no implementation
|
||||
|
||||
private:
|
||||
nsIJSContextStack* mContextStack;
|
||||
nsIThreadJSContextStack* mContextStack;
|
||||
#ifdef DEBUG
|
||||
JSContext* mDebugCX;
|
||||
#endif
|
||||
|
@ -459,7 +459,7 @@ private:
|
|||
AutoPushCompatibleJSContext(); // no implementation
|
||||
|
||||
private:
|
||||
nsIJSContextStack* mContextStack;
|
||||
nsIThreadJSContextStack* mContextStack;
|
||||
JSContext* mCX;
|
||||
};
|
||||
|
||||
|
@ -1339,21 +1339,54 @@ private:
|
|||
|
||||
/***************************************************************************/
|
||||
|
||||
// All of our thread local storage.
|
||||
|
||||
class xpcPerThreadData
|
||||
{
|
||||
public:
|
||||
// Get the instance of this object for the current thread
|
||||
static xpcPerThreadData* GetData();
|
||||
|
||||
xpcPerThreadData();
|
||||
~xpcPerThreadData();
|
||||
|
||||
nsIXPCException* GetException();
|
||||
void SetException(nsIXPCException* aException);
|
||||
|
||||
JSContext* GetSafeJSContext();
|
||||
nsDeque* GetJSContextStack();
|
||||
|
||||
PRBool IsValid() const;
|
||||
|
||||
private:
|
||||
nsIXPCException* mException;
|
||||
nsDeque* mJSContextStack;
|
||||
JSContext* mSafeJSContext;
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
#define NS_XPC_THREAD_JSCONTEXT_STACK_CID \
|
||||
{ 0xff8c4d10, 0x3194, 0x11d3, \
|
||||
{ 0x98, 0x85, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
|
||||
|
||||
class nsXPCThreadJSContextStackImpl : public nsIJSContextStack
|
||||
class nsXPCThreadJSContextStackImpl : public nsIThreadJSContextStack
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIJSCONTEXTSTACK
|
||||
NS_DECL_NSITHREADJSCONTEXTSTACK
|
||||
|
||||
static nsXPCThreadJSContextStackImpl* GetSingleton();
|
||||
static void FreeSingleton();
|
||||
|
||||
nsXPCThreadJSContextStackImpl();
|
||||
virtual ~nsXPCThreadJSContextStackImpl();
|
||||
|
||||
private:
|
||||
nsDeque* GetStackForCurrentThread()
|
||||
{xpcPerThreadData* data = xpcPerThreadData::GetData();
|
||||
return data ? data->GetJSContextStack() : nsnull;}
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
|
|
@ -37,52 +37,6 @@
|
|||
|
||||
#include "xpcprivate.h"
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void)
|
||||
xpc_StackDtorCB(void* ptr)
|
||||
{
|
||||
nsDeque* myStack = (nsDeque*) ptr;
|
||||
if(myStack)
|
||||
delete myStack;
|
||||
}
|
||||
|
||||
static nsDeque*
|
||||
GetMyStack()
|
||||
{
|
||||
#define BAD_TLS_INDEX ((PRUintn) -1)
|
||||
nsDeque* myStack;
|
||||
static PRUintn index = BAD_TLS_INDEX;
|
||||
if(index == BAD_TLS_INDEX)
|
||||
{
|
||||
if(PR_FAILURE == PR_NewThreadPrivateIndex(&index, xpc_StackDtorCB))
|
||||
{
|
||||
NS_ASSERTION(0, "PR_NewThreadPrivateIndex failed!");
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
myStack = (nsDeque*) PR_GetThreadPrivate(index);
|
||||
if(!myStack)
|
||||
{
|
||||
if(nsnull != (myStack = new nsDeque(nsnull)))
|
||||
{
|
||||
if(PR_FAILURE == PR_SetThreadPrivate(index, myStack))
|
||||
{
|
||||
NS_ASSERTION(0, "PR_SetThreadPrivate failed!");
|
||||
delete myStack;
|
||||
myStack = nsnull;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERTION(0, "new nsDeque failed!");
|
||||
}
|
||||
}
|
||||
return myStack;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*
|
||||
* This object holds state that we don't want to lose!
|
||||
*
|
||||
|
@ -91,7 +45,7 @@ GetMyStack()
|
|||
* is using it.
|
||||
*/
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXPCThreadJSContextStackImpl, nsIJSContextStack)
|
||||
NS_IMPL_ISUPPORTS2(nsXPCThreadJSContextStackImpl, nsIThreadJSContextStack, nsIJSContextStack)
|
||||
|
||||
static nsXPCThreadJSContextStackImpl* gXPCThreadJSContextStack = nsnull;
|
||||
|
||||
|
@ -144,7 +98,7 @@ nsXPCThreadJSContextStackImpl::GetCount(PRInt32 *aCount)
|
|||
if(!aCount)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsDeque* myStack = GetMyStack();
|
||||
nsDeque* myStack = GetStackForCurrentThread();
|
||||
|
||||
if(!myStack)
|
||||
{
|
||||
|
@ -163,7 +117,7 @@ nsXPCThreadJSContextStackImpl::Peek(JSContext * *_retval)
|
|||
if(!_retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsDeque* myStack = GetMyStack();
|
||||
nsDeque* myStack = GetStackForCurrentThread();
|
||||
|
||||
if(!myStack)
|
||||
{
|
||||
|
@ -183,7 +137,7 @@ nsXPCThreadJSContextStackImpl::Peek(JSContext * *_retval)
|
|||
NS_IMETHODIMP
|
||||
nsXPCThreadJSContextStackImpl::Pop(JSContext * *_retval)
|
||||
{
|
||||
nsDeque* myStack = GetMyStack();
|
||||
nsDeque* myStack = GetStackForCurrentThread();
|
||||
|
||||
if(!myStack)
|
||||
{
|
||||
|
@ -205,7 +159,7 @@ nsXPCThreadJSContextStackImpl::Pop(JSContext * *_retval)
|
|||
NS_IMETHODIMP
|
||||
nsXPCThreadJSContextStackImpl::Push(JSContext * cx)
|
||||
{
|
||||
nsDeque* myStack = GetMyStack();
|
||||
nsDeque* myStack = GetStackForCurrentThread();
|
||||
|
||||
if(!myStack)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -213,3 +167,152 @@ nsXPCThreadJSContextStackImpl::Push(JSContext * cx)
|
|||
myStack->Push(cx);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute JSContext SafeJSContext; */
|
||||
NS_IMETHODIMP
|
||||
nsXPCThreadJSContextStackImpl::GetSafeJSContext(JSContext * *aSafeJSContext)
|
||||
{
|
||||
NS_ASSERTION(aSafeJSContext, "loser!");
|
||||
|
||||
xpcPerThreadData* data = xpcPerThreadData::GetData();
|
||||
if(!data)
|
||||
{
|
||||
*aSafeJSContext = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JSContext* ptr = *aSafeJSContext = data->GetSafeJSContext();
|
||||
return ptr ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
xpcPerThreadData::xpcPerThreadData()
|
||||
: mException(nsnull),
|
||||
mJSContextStack(new nsDeque(nsnull)),
|
||||
mSafeJSContext(nsnull)
|
||||
{
|
||||
// empty...
|
||||
}
|
||||
|
||||
xpcPerThreadData::~xpcPerThreadData()
|
||||
{
|
||||
NS_IF_RELEASE(mException);
|
||||
if(mJSContextStack)
|
||||
delete mJSContextStack;
|
||||
if(mSafeJSContext)
|
||||
JS_DestroyContext(mSafeJSContext);
|
||||
}
|
||||
|
||||
PRBool
|
||||
xpcPerThreadData::IsValid() const
|
||||
{
|
||||
return mJSContextStack != nsnull;
|
||||
}
|
||||
|
||||
nsIXPCException*
|
||||
xpcPerThreadData::GetException()
|
||||
{
|
||||
NS_IF_ADDREF(mException);
|
||||
return mException;
|
||||
}
|
||||
|
||||
void
|
||||
xpcPerThreadData::SetException(nsIXPCException* aException)
|
||||
{
|
||||
NS_IF_ADDREF(aException);
|
||||
NS_IF_RELEASE(mException);
|
||||
mException = aException;
|
||||
}
|
||||
|
||||
nsDeque*
|
||||
xpcPerThreadData::GetJSContextStack()
|
||||
{
|
||||
return mJSContextStack;
|
||||
}
|
||||
|
||||
/**************************/
|
||||
|
||||
static JSClass global_class = {
|
||||
"global_for_xpcPerThreadData_SafeJSContext", 0,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||
};
|
||||
|
||||
JSContext*
|
||||
xpcPerThreadData::GetSafeJSContext()
|
||||
{
|
||||
if(!mSafeJSContext)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
nsCOMPtr<nsIJSRuntimeService> rtsvc =
|
||||
do_GetService("nsJSRuntimeService");
|
||||
if(rtsvc && NS_SUCCEEDED(rtsvc->GetRuntime(&rt)) && rt)
|
||||
{
|
||||
nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
|
||||
if(xpc)
|
||||
{
|
||||
mSafeJSContext = JS_NewContext(rt, 8192);
|
||||
if(mSafeJSContext)
|
||||
{
|
||||
JSObject *glob;
|
||||
glob = JS_NewObject(mSafeJSContext, &global_class, NULL, NULL);
|
||||
if(!glob ||
|
||||
!JS_InitStandardClasses(mSafeJSContext, glob) ||
|
||||
NS_FAILED(xpc->InitClasses(mSafeJSContext, glob)))
|
||||
{
|
||||
JS_DestroyContext(mSafeJSContext);
|
||||
mSafeJSContext = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mSafeJSContext;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void)
|
||||
xpc_ThreadDataDtorCB(void* ptr)
|
||||
{
|
||||
xpcPerThreadData* data = (xpcPerThreadData*) ptr;
|
||||
if(data)
|
||||
delete data;
|
||||
}
|
||||
|
||||
// static
|
||||
xpcPerThreadData*
|
||||
xpcPerThreadData::GetData()
|
||||
{
|
||||
static const PRUintn BAD_TLS_INDEX = (PRUintn) -1;
|
||||
static PRUintn index = BAD_TLS_INDEX;
|
||||
xpcPerThreadData* data;
|
||||
if(index == BAD_TLS_INDEX)
|
||||
{
|
||||
if(PR_FAILURE == PR_NewThreadPrivateIndex(&index, xpc_ThreadDataDtorCB))
|
||||
{
|
||||
NS_ASSERTION(0, "PR_NewThreadPrivateIndex failed!");
|
||||
index = BAD_TLS_INDEX;
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
data = (xpcPerThreadData*) PR_GetThreadPrivate(index);
|
||||
if(!data)
|
||||
{
|
||||
data = new xpcPerThreadData();
|
||||
if(!data || !data->IsValid())
|
||||
{
|
||||
NS_ASSERTION(0, "new xpcPerThreadData() failed!");
|
||||
if(data)
|
||||
delete data;
|
||||
return nsnull;
|
||||
}
|
||||
if(PR_FAILURE == PR_SetThreadPrivate(index, data))
|
||||
{
|
||||
NS_ASSERTION(0, "PR_SetThreadPrivate failed!");
|
||||
delete data;
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче