mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 08:12:05 +00:00
Bug 715634 - Cleanup XPCJSContextStack; r=bholley
This commit is contained in:
parent
d2be610370
commit
7cf1cd311b
@ -40,8 +40,12 @@
|
||||
|
||||
/* Call context. */
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "xpcprivate.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
|
||||
JSContext* cx /* = nsnull */,
|
||||
JSObject* obj /* = nsnull */,
|
||||
@ -107,15 +111,15 @@ XPCCallContext::Init(XPCContext::LangType callerLanguage,
|
||||
return;
|
||||
|
||||
XPCJSContextStack* stack = mThreadData->GetJSContextStack();
|
||||
JSContext* topJSContext;
|
||||
|
||||
if (!stack || NS_FAILED(stack->Peek(&topJSContext))) {
|
||||
if (!stack) {
|
||||
// If we don't have a stack we're probably in shutdown.
|
||||
NS_ASSERTION(!stack, "Bad, Peek failed!");
|
||||
mJSContext = nsnull;
|
||||
return;
|
||||
}
|
||||
|
||||
JSContext *topJSContext = stack->Peek();
|
||||
|
||||
if (!mJSContext) {
|
||||
// This is slightly questionable. If called without an explicit
|
||||
// JSContext (generally a call to a wrappedJS) we will use the JSContext
|
||||
@ -125,14 +129,17 @@ XPCCallContext::Init(XPCContext::LangType callerLanguage,
|
||||
// have JS stack 'continuity' for purposes of stack traces etc.
|
||||
// Note: this *is* what the pre-XPCCallContext xpconnect did too.
|
||||
|
||||
if (topJSContext)
|
||||
if (topJSContext) {
|
||||
mJSContext = topJSContext;
|
||||
else if (NS_FAILED(stack->GetSafeJSContext(&mJSContext)) || !mJSContext)
|
||||
return;
|
||||
} else {
|
||||
mJSContext = stack->GetSafeJSContext();
|
||||
if (!mJSContext)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (topJSContext != mJSContext) {
|
||||
if (NS_FAILED(stack->Push(mJSContext))) {
|
||||
if (!stack->Push(mJSContext)) {
|
||||
NS_ERROR("bad!");
|
||||
return;
|
||||
}
|
||||
@ -346,13 +353,8 @@ XPCCallContext::~XPCCallContext()
|
||||
XPCJSContextStack* stack = mThreadData->GetJSContextStack();
|
||||
NS_ASSERTION(stack, "bad!");
|
||||
if (stack) {
|
||||
#ifdef DEBUG
|
||||
JSContext* poppedCX;
|
||||
nsresult rv = stack->Pop(&poppedCX);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && poppedCX == mJSContext, "bad pop");
|
||||
#else
|
||||
(void) stack->Pop(nsnull);
|
||||
#endif
|
||||
DebugOnly<JSContext*> poppedCX = stack->Pop();
|
||||
NS_ASSERTION(poppedCX == mJSContext, "bad pop");
|
||||
}
|
||||
}
|
||||
|
||||
@ -519,10 +521,7 @@ XPCLazyCallContext::AssertContextIsTopOfStack(JSContext* cx)
|
||||
XPCPerThreadData* tls = XPCPerThreadData::GetData(cx);
|
||||
XPCJSContextStack* stack = tls->GetJSContextStack();
|
||||
|
||||
JSContext* topJSContext;
|
||||
nsresult rv = stack->Peek(&topJSContext);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "XPCJSContextStack::Peek failed");
|
||||
|
||||
JSContext *topJSContext = stack->Peek();
|
||||
NS_ASSERTION(cx == topJSContext, "wrong context on XPCJSContextStack!");
|
||||
}
|
||||
#endif
|
||||
|
@ -42,6 +42,8 @@
|
||||
|
||||
/* The "Components" xpcom objects for JavaScript. */
|
||||
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
#include "xpcprivate.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "xpcIJSModuleLoader.h"
|
||||
@ -59,6 +61,7 @@
|
||||
#include "jsgc.h"
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace js;
|
||||
/***************************************************************************/
|
||||
// stuff used by all
|
||||
@ -3444,7 +3447,7 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
|
||||
XPCPerThreadData *data = XPCPerThreadData::GetData(cx);
|
||||
XPCJSContextStack *stack = nsnull;
|
||||
if (data && (stack = data->GetJSContextStack())) {
|
||||
if (NS_FAILED(stack->Push(sandcx->GetJSContext()))) {
|
||||
if (!stack->Push(sandcx->GetJSContext())) {
|
||||
JS_ReportError(cx,
|
||||
"Unable to initialize XPConnect with the sandbox context");
|
||||
JSPRINCIPALS_DROP(cx, jsPrincipals);
|
||||
@ -3467,9 +3470,8 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
|
||||
JSString *str = nsnull;
|
||||
|
||||
if (!ac.enter(sandcx->GetJSContext(), sandbox)) {
|
||||
if (stack) {
|
||||
stack->Pop(nsnull);
|
||||
}
|
||||
if (stack)
|
||||
unused << stack->Pop();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -3545,9 +3547,8 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
|
||||
}
|
||||
}
|
||||
|
||||
if (stack) {
|
||||
stack->Pop(nsnull);
|
||||
}
|
||||
if (stack)
|
||||
unused << stack->Pop();
|
||||
|
||||
JSPRINCIPALS_DROP(cx, jsPrincipals);
|
||||
|
||||
|
@ -1125,9 +1125,7 @@ xpc_qsAssertContextOK(JSContext *cx)
|
||||
XPCPerThreadData *thread = XPCPerThreadData::GetData(cx);
|
||||
XPCJSContextStack* stack = thread->GetJSContextStack();
|
||||
|
||||
JSContext* topJSContext = nsnull;
|
||||
nsresult rv = stack->Peek(&topJSContext);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "XPCJSContextStack::Peek failed");
|
||||
JSContext *topJSContext = stack->Peek();
|
||||
|
||||
// This is what we're actually trying to assert here.
|
||||
NS_ASSERTION(cx == topJSContext, "wrong context on XPCJSContextStack!");
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=80:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
@ -52,14 +52,6 @@ using namespace mozilla;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
XPCJSContextStack::XPCJSContextStack()
|
||||
: mStack(),
|
||||
mSafeJSContext(nsnull),
|
||||
mOwnSafeJSContext(nsnull)
|
||||
{
|
||||
// empty...
|
||||
}
|
||||
|
||||
XPCJSContextStack::~XPCJSContextStack()
|
||||
{
|
||||
if (mOwnSafeJSContext) {
|
||||
@ -69,54 +61,37 @@ XPCJSContextStack::~XPCJSContextStack()
|
||||
}
|
||||
}
|
||||
|
||||
/* readonly attribute PRInt32 count; */
|
||||
NS_IMETHODIMP
|
||||
XPCJSContextStack::GetCount(PRInt32 *aCount)
|
||||
JSContext*
|
||||
XPCJSContextStack::Pop()
|
||||
{
|
||||
*aCount = mStack.Length();
|
||||
return NS_OK;
|
||||
}
|
||||
MOZ_ASSERT(!mStack.IsEmpty());
|
||||
|
||||
/* JSContext peek (); */
|
||||
NS_IMETHODIMP
|
||||
XPCJSContextStack::Peek(JSContext * *_retval)
|
||||
{
|
||||
*_retval = mStack.IsEmpty() ? nsnull : mStack[mStack.Length() - 1].cx;
|
||||
return NS_OK;
|
||||
}
|
||||
uint32_t idx = mStack.Length() - 1; // The thing we're popping
|
||||
|
||||
/* JSContext pop (); */
|
||||
NS_IMETHODIMP
|
||||
XPCJSContextStack::Pop(JSContext * *_retval)
|
||||
{
|
||||
NS_ASSERTION(!mStack.IsEmpty(), "ThreadJSContextStack underflow");
|
||||
|
||||
PRUint32 idx = mStack.Length() - 1; // The thing we're popping
|
||||
|
||||
if (_retval)
|
||||
*_retval = mStack[idx].cx;
|
||||
JSContext *cx = mStack[idx].cx;
|
||||
|
||||
mStack.RemoveElementAt(idx);
|
||||
if (idx > 0) {
|
||||
--idx; // Advance to new top of the stack
|
||||
if (idx == 0)
|
||||
return cx;
|
||||
|
||||
XPCJSContextInfo & e = mStack[idx];
|
||||
NS_ASSERTION(!e.suspendDepth || e.cx, "Shouldn't have suspendDepth without a cx!");
|
||||
if (e.cx) {
|
||||
if (e.suspendDepth) {
|
||||
JS_ResumeRequest(e.cx, e.suspendDepth);
|
||||
e.suspendDepth = 0;
|
||||
}
|
||||
--idx; // Advance to new top of the stack
|
||||
|
||||
if (e.savedFrameChain) {
|
||||
// Pop() can be called outside any request for e.cx.
|
||||
JSAutoRequest ar(e.cx);
|
||||
JS_RestoreFrameChain(e.cx);
|
||||
e.savedFrameChain = false;
|
||||
}
|
||||
XPCJSContextInfo &e = mStack[idx];
|
||||
NS_ASSERTION(!e.suspendDepth || e.cx, "Shouldn't have suspendDepth without a cx!");
|
||||
if (e.cx) {
|
||||
if (e.suspendDepth) {
|
||||
JS_ResumeRequest(e.cx, e.suspendDepth);
|
||||
e.suspendDepth = 0;
|
||||
}
|
||||
|
||||
if (e.savedFrameChain) {
|
||||
// Pop() can be called outside any request for e.cx.
|
||||
JSAutoRequest ar(e.cx);
|
||||
JS_RestoreFrameChain(e.cx);
|
||||
e.savedFrameChain = false;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
return cx;
|
||||
}
|
||||
|
||||
static nsIPrincipal*
|
||||
@ -131,53 +106,54 @@ GetPrincipalFromCx(JSContext *cx)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/* void push (in JSContext cx); */
|
||||
NS_IMETHODIMP
|
||||
XPCJSContextStack::Push(JSContext * cx)
|
||||
bool
|
||||
XPCJSContextStack::Push(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT_IF(cx, JS_GetContextThread(cx));
|
||||
if (mStack.Length() > 0) {
|
||||
XPCJSContextInfo & e = mStack[mStack.Length() - 1];
|
||||
if (e.cx) {
|
||||
if (e.cx == cx) {
|
||||
nsIScriptSecurityManager* ssm = XPCWrapper::GetSecurityManager();
|
||||
if (ssm) {
|
||||
if (nsIPrincipal* globalObjectPrincipal = GetPrincipalFromCx(cx)) {
|
||||
nsIPrincipal* subjectPrincipal = ssm->GetCxSubjectPrincipal(cx);
|
||||
bool equals = false;
|
||||
globalObjectPrincipal->Equals(subjectPrincipal, &equals);
|
||||
if (equals) {
|
||||
goto append;
|
||||
}
|
||||
MOZ_ASSERT_IF(cx, JS_GetContextThread(cx));
|
||||
if (mStack.Length() == 0) {
|
||||
mStack.AppendElement(cx);
|
||||
return true;
|
||||
}
|
||||
|
||||
XPCJSContextInfo &e = mStack[mStack.Length() - 1];
|
||||
if (e.cx) {
|
||||
if (e.cx == cx) {
|
||||
nsIScriptSecurityManager* ssm = XPCWrapper::GetSecurityManager();
|
||||
if (ssm) {
|
||||
if (nsIPrincipal* globalObjectPrincipal = GetPrincipalFromCx(cx)) {
|
||||
nsIPrincipal* subjectPrincipal = ssm->GetCxSubjectPrincipal(cx);
|
||||
bool equals = false;
|
||||
globalObjectPrincipal->Equals(subjectPrincipal, &equals);
|
||||
if (equals) {
|
||||
mStack.AppendElement(cx);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Push() can be called outside any request for e.cx.
|
||||
JSAutoRequest ar(e.cx);
|
||||
if (!JS_SaveFrameChain(e.cx))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
e.savedFrameChain = true;
|
||||
}
|
||||
|
||||
if (!cx)
|
||||
e.suspendDepth = JS_SuspendRequest(e.cx);
|
||||
}
|
||||
|
||||
{
|
||||
// Push() can be called outside any request for e.cx.
|
||||
JSAutoRequest ar(e.cx);
|
||||
if (!JS_SaveFrameChain(e.cx))
|
||||
return false;
|
||||
e.savedFrameChain = true;
|
||||
}
|
||||
|
||||
if (!cx)
|
||||
e.suspendDepth = JS_SuspendRequest(e.cx);
|
||||
}
|
||||
|
||||
append:
|
||||
if (!mStack.AppendElement(cx))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return NS_OK;
|
||||
mStack.AppendElement(cx);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
JSBool
|
||||
XPCJSContextStack::DEBUG_StackHasJSContext(JSContext* aJSContext)
|
||||
bool
|
||||
XPCJSContextStack::DEBUG_StackHasJSContext(JSContext *cx)
|
||||
{
|
||||
for (PRUint32 i = 0; i < mStack.Length(); i++)
|
||||
if (aJSContext == mStack[i].cx)
|
||||
if (cx == mStack[i].cx)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@ -211,88 +187,89 @@ static JSClass global_class = {
|
||||
extern void
|
||||
mozJSLoaderErrorReporter(JSContext *cx, const char *message, JSErrorReport *rep);
|
||||
|
||||
/* attribute JSContext safeJSContext; */
|
||||
NS_IMETHODIMP
|
||||
XPCJSContextStack::GetSafeJSContext(JSContext * *aSafeJSContext)
|
||||
JSContext*
|
||||
XPCJSContextStack::GetSafeJSContext()
|
||||
{
|
||||
if (!mSafeJSContext) {
|
||||
// Start by getting the principal holder and principal for this
|
||||
// context. If we can't manage that, don't bother with the rest.
|
||||
nsRefPtr<nsNullPrincipal> principal = new nsNullPrincipal();
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop;
|
||||
if (principal) {
|
||||
nsresult rv = principal->Init();
|
||||
if (NS_SUCCEEDED(rv))
|
||||
sop = new PrincipalHolder(principal);
|
||||
}
|
||||
if (!sop) {
|
||||
*aSafeJSContext = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
if (mSafeJSContext)
|
||||
return mSafeJSContext;
|
||||
|
||||
// Start by getting the principal holder and principal for this
|
||||
// context. If we can't manage that, don't bother with the rest.
|
||||
nsRefPtr<nsNullPrincipal> principal = new nsNullPrincipal();
|
||||
nsresult rv = principal->Init();
|
||||
if (NS_FAILED(rv))
|
||||
return NULL;
|
||||
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop = new PrincipalHolder(principal);
|
||||
|
||||
nsRefPtr<nsXPConnect> xpc = nsXPConnect::GetXPConnect();
|
||||
if (!xpc)
|
||||
return NULL;
|
||||
|
||||
XPCJSRuntime* xpcrt = xpc->GetRuntime();
|
||||
if (!xpcrt)
|
||||
return NULL;
|
||||
|
||||
JSRuntime *rt = xpcrt->GetJSRuntime();
|
||||
if (!rt)
|
||||
return NULL;
|
||||
|
||||
mSafeJSContext = JS_NewContext(rt, 8192);
|
||||
if (!mSafeJSContext)
|
||||
return NULL;
|
||||
|
||||
JSObject *glob;
|
||||
{
|
||||
// scoped JS Request
|
||||
JSAutoRequest req(mSafeJSContext);
|
||||
|
||||
JS_SetErrorReporter(mSafeJSContext, mozJSLoaderErrorReporter);
|
||||
|
||||
// Because we can run off the main thread, we create an MT
|
||||
// global object. Our principal is the unique key.
|
||||
JSCompartment *compartment;
|
||||
nsresult rv = xpc_CreateMTGlobalObject(mSafeJSContext,
|
||||
&global_class,
|
||||
principal, &glob,
|
||||
&compartment);
|
||||
if (NS_FAILED(rv))
|
||||
glob = nsnull;
|
||||
|
||||
if (glob) {
|
||||
// Make sure the context is associated with a proper compartment
|
||||
// and not the default compartment.
|
||||
JS_SetGlobalObject(mSafeJSContext, glob);
|
||||
|
||||
// Note: make sure to set the private before calling
|
||||
// InitClasses
|
||||
nsIScriptObjectPrincipal* priv = nsnull;
|
||||
sop.swap(priv);
|
||||
if (!JS_SetPrivate(mSafeJSContext, glob, priv)) {
|
||||
// Drop the whole thing
|
||||
NS_RELEASE(priv);
|
||||
glob = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
JSRuntime *rt;
|
||||
XPCJSRuntime* xpcrt;
|
||||
|
||||
nsXPConnect* xpc = nsXPConnect::GetXPConnect();
|
||||
nsCOMPtr<nsIXPConnect> xpcholder(static_cast<nsIXPConnect*>(xpc));
|
||||
|
||||
if (xpc && (xpcrt = xpc->GetRuntime()) && (rt = xpcrt->GetJSRuntime())) {
|
||||
JSObject *glob;
|
||||
mSafeJSContext = JS_NewContext(rt, 8192);
|
||||
if (mSafeJSContext) {
|
||||
// scoped JS Request
|
||||
JSAutoRequest req(mSafeJSContext);
|
||||
|
||||
JS_SetErrorReporter(mSafeJSContext, mozJSLoaderErrorReporter);
|
||||
|
||||
// Because we can run off the main thread, we create an MT
|
||||
// global object. Our principal is the unique key.
|
||||
JSCompartment *compartment;
|
||||
nsresult rv = xpc_CreateMTGlobalObject(mSafeJSContext,
|
||||
&global_class,
|
||||
principal, &glob,
|
||||
&compartment);
|
||||
if (NS_FAILED(rv))
|
||||
glob = nsnull;
|
||||
|
||||
if (glob) {
|
||||
// Make sure the context is associated with a proper compartment
|
||||
// and not the default compartment.
|
||||
JS_SetGlobalObject(mSafeJSContext, glob);
|
||||
|
||||
// Note: make sure to set the private before calling
|
||||
// InitClasses
|
||||
nsIScriptObjectPrincipal* priv = nsnull;
|
||||
sop.swap(priv);
|
||||
if (!JS_SetPrivate(mSafeJSContext, glob, priv)) {
|
||||
// Drop the whole thing
|
||||
NS_RELEASE(priv);
|
||||
glob = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// After this point either glob is null and the
|
||||
// nsIScriptObjectPrincipal ownership is either handled by the
|
||||
// nsCOMPtr or dealt with, or we'll release in the finalize
|
||||
// hook.
|
||||
if (glob && NS_FAILED(xpc->InitClasses(mSafeJSContext, glob))) {
|
||||
glob = nsnull;
|
||||
}
|
||||
|
||||
}
|
||||
if (mSafeJSContext && !glob) {
|
||||
// Destroy the context outside the scope of JSAutoRequest that
|
||||
// uses the context in its destructor.
|
||||
JS_DestroyContext(mSafeJSContext);
|
||||
mSafeJSContext = nsnull;
|
||||
}
|
||||
// Save it off so we can destroy it later.
|
||||
mOwnSafeJSContext = mSafeJSContext;
|
||||
// After this point either glob is null and the
|
||||
// nsIScriptObjectPrincipal ownership is either handled by the
|
||||
// nsCOMPtr or dealt with, or we'll release in the finalize
|
||||
// hook.
|
||||
if (glob && NS_FAILED(xpc->InitClasses(mSafeJSContext, glob))) {
|
||||
glob = nsnull;
|
||||
}
|
||||
}
|
||||
if (mSafeJSContext && !glob) {
|
||||
// Destroy the context outside the scope of JSAutoRequest that
|
||||
// uses the context in its destructor.
|
||||
JS_DestroyContext(mSafeJSContext);
|
||||
mSafeJSContext = nsnull;
|
||||
}
|
||||
|
||||
*aSafeJSContext = mSafeJSContext;
|
||||
return mSafeJSContext ? NS_OK : NS_ERROR_UNEXPECTED;
|
||||
// Save it off so we can destroy it later.
|
||||
mOwnSafeJSContext = mSafeJSContext;
|
||||
|
||||
return mSafeJSContext;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -534,9 +534,8 @@ GetContextFromObject(JSObject *obj)
|
||||
// Don't stomp over a running context.
|
||||
XPCJSContextStack* stack =
|
||||
XPCPerThreadData::GetData(nsnull)->GetJSContextStack();
|
||||
JSContext* topJSContext;
|
||||
|
||||
if (stack && NS_SUCCEEDED(stack->Peek(&topJSContext)) && topJSContext)
|
||||
if (stack && stack->Peek())
|
||||
return nsnull;
|
||||
|
||||
// In order to get a context, we need a context.
|
||||
|
@ -1311,7 +1311,7 @@ public:
|
||||
~AutoPopJSContext()
|
||||
{
|
||||
if (mCx)
|
||||
mStack->Pop(nsnull);
|
||||
mStack->Pop();
|
||||
}
|
||||
|
||||
void PushIfNotTop(JSContext *cx)
|
||||
@ -1319,10 +1319,9 @@ public:
|
||||
NS_ASSERTION(cx, "Null context!");
|
||||
NS_ASSERTION(!mCx, "This class is only meant to be used once!");
|
||||
|
||||
JSContext *cxTop = nsnull;
|
||||
mStack->Peek(&cxTop);
|
||||
JSContext *cxTop = mStack->Peek();
|
||||
|
||||
if (cxTop != cx && NS_SUCCEEDED(mStack->Push(cx)))
|
||||
if (cxTop != cx && mStack->Push(cx))
|
||||
mCx = cx;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
@ -2463,8 +2463,7 @@ nsXPConnect::UnregisterGCCallback(JSGCCallback func)
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::GetCount(PRInt32 *aCount)
|
||||
{
|
||||
if (!aCount)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
MOZ_ASSERT(aCount);
|
||||
|
||||
XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull);
|
||||
|
||||
@ -2473,15 +2472,15 @@ nsXPConnect::GetCount(PRInt32 *aCount)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return data->GetJSContextStack()->GetCount(aCount);
|
||||
*aCount = data->GetJSContextStack()->Count();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* JSContext Peek (); */
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::Peek(JSContext * *_retval)
|
||||
{
|
||||
if (!_retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
MOZ_ASSERT(_retval);
|
||||
|
||||
XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull);
|
||||
|
||||
@ -2490,7 +2489,8 @@ nsXPConnect::Peek(JSContext * *_retval)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return data->GetJSContextStack()->Peek(_retval);
|
||||
*_retval = data->GetJSContextStack()->Peek();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
@ -2581,11 +2581,14 @@ nsXPConnect::Pop(JSContext * *_retval)
|
||||
|
||||
if (!data) {
|
||||
if (_retval)
|
||||
*_retval = nsnull;
|
||||
*_retval = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return data->GetJSContextStack()->Pop(_retval);
|
||||
JSContext *cx = data->GetJSContextStack()->Pop();
|
||||
if (_retval)
|
||||
*_retval = cx;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void Push (in JSContext cx); */
|
||||
@ -2598,7 +2601,7 @@ nsXPConnect::Push(JSContext * cx)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (gDebugMode != gDesiredDebugMode && NS_IsMainThread()) {
|
||||
const nsTArray<XPCJSContextInfo>* stack = data->GetJSContextStack()->GetStack();
|
||||
const InfallibleTArray<XPCJSContextInfo>* stack = data->GetJSContextStack()->GetStack();
|
||||
if (!gDesiredDebugMode) {
|
||||
/* Turn off debug mode immediately, even if JS code is currently running */
|
||||
CheckForDebugMode(mRuntime->GetJSRuntime());
|
||||
@ -2616,7 +2619,7 @@ nsXPConnect::Push(JSContext * cx)
|
||||
}
|
||||
}
|
||||
|
||||
return data->GetJSContextStack()->Push(cx);
|
||||
return data->GetJSContextStack()->Push(cx) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* attribute JSContext SafeJSContext; */
|
||||
@ -2632,7 +2635,8 @@ nsXPConnect::GetSafeJSContext(JSContext * *aSafeJSContext)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return data->GetJSContextStack()->GetSafeJSContext(aSafeJSContext);
|
||||
*aSafeJSContext = data->GetJSContextStack()->GetSafeJSContext();
|
||||
return *aSafeJSContext ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
|
@ -3583,21 +3583,36 @@ struct XPCJSContextInfo {
|
||||
class XPCJSContextStack
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIJSCONTEXTSTACK
|
||||
NS_DECL_NSITHREADJSCONTEXTSTACK
|
||||
XPCJSContextStack()
|
||||
: mSafeJSContext(NULL)
|
||||
, mOwnSafeJSContext(NULL)
|
||||
{ }
|
||||
|
||||
XPCJSContextStack();
|
||||
virtual ~XPCJSContextStack();
|
||||
|
||||
uint32_t Count()
|
||||
{
|
||||
return mStack.Length();
|
||||
}
|
||||
|
||||
JSContext *Peek()
|
||||
{
|
||||
return mStack.IsEmpty() ? NULL : mStack[mStack.Length() - 1].cx;
|
||||
}
|
||||
|
||||
JSContext *Pop();
|
||||
bool Push(JSContext *cx);
|
||||
JSContext *GetSafeJSContext();
|
||||
|
||||
#ifdef DEBUG
|
||||
JSBool DEBUG_StackHasJSContext(JSContext* aJSContext);
|
||||
bool DEBUG_StackHasJSContext(JSContext *cx);
|
||||
#endif
|
||||
|
||||
const nsTArray<XPCJSContextInfo>* GetStack()
|
||||
const InfallibleTArray<XPCJSContextInfo>* GetStack()
|
||||
{ return &mStack; }
|
||||
|
||||
private:
|
||||
nsAutoTArray<XPCJSContextInfo, 16> mStack;
|
||||
AutoInfallibleTArray<XPCJSContextInfo, 16> mStack;
|
||||
JSContext* mSafeJSContext;
|
||||
JSContext* mOwnSafeJSContext;
|
||||
};
|
||||
@ -3615,7 +3630,7 @@ public:
|
||||
NS_DECL_NSIJSCONTEXTSTACKITERATOR
|
||||
|
||||
private:
|
||||
const nsTArray<XPCJSContextInfo> *mStack;
|
||||
const InfallibleTArray<XPCJSContextInfo> *mStack;
|
||||
PRUint32 mPosition;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user