void XPCCallContext::Init(XPCContext::LangType callerLanguage, JSBool callBeginRequest, JSObject* obj, JSObject* funobj, WrapperInitOptions wrapperInitOptions, jsid name, uintN argc, jsval *argv, jsval *rval) { if (!mXPC) return; mThreadData = XPCPerThreadData::GetData(mJSContext); if (!mThreadData) return; XPCJSContextStack* stack = mThreadData->GetJSContextStack(); JSContext* topJSContext; if (!stack || NS_FAILED(stack->Peek(&topJSContext))) { // If we don't have a stack we're probably in shutdown. NS_ASSERTION(!stack, "Bad, Peek failed!"); mJSContext = nsnull; return; } if (!mJSContext) { // This is slightly questionable. If called without an explicit // JSContext (generally a call to a wrappedJS) we will use the JSContext // on the top of the JSContext stack - if there is one - *before* // falling back on the safe JSContext. // This is good AND bad because it makes calls from JS -> native -> JS // have JS stack 'continuity' for purposes of stack traces etc. // Note: this *is* what the pre-XPCCallContext xpconnect did too. if (topJSContext) mJSContext = topJSContext; else if (NS_FAILED(stack->GetSafeJSContext(&mJSContext)) || !mJSContext) return; } if (topJSContext != mJSContext) { if (NS_FAILED(stack->Push(mJSContext))) { NS_ERROR("bad!"); return; } mContextPopRequired = true; } // Get into the request as early as we can to avoid problems with scanning // callcontexts on other threads from within the gc callbacks. NS_ASSERTION(!callBeginRequest || mCallerLanguage == NATIVE_CALLER, "Don't call JS_BeginRequest unless the caller is native."); if (callBeginRequest) JS_BeginRequest(mJSContext); mXPCContext = XPCContext::GetXPCContext(mJSContext); mPrevCallerLanguage = mXPCContext->SetCallingLangType(mCallerLanguage); // hook into call context chain for our thread mPrevCallContext = mThreadData->SetCallContext(this); // We only need to addref xpconnect once so only do it if this is the first // context in the chain. if (!mPrevCallContext) NS_ADDREF(mXPC); mState = HAVE_CONTEXT; if (!obj) return; mScopeForNewJSObjects = obj; mState = HAVE_SCOPE; mMethodIndex = 0xDEAD; mState = HAVE_OBJECT; mTearOff = nsnull; if (wrapperInitOptions == INIT_SHOULD_LOOKUP_WRAPPER) { mWrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(mJSContext, obj, funobj, &mFlattenedJSObject, &mTearOff); if (mWrapper) { DEBUG_CheckWrapperThreadSafety(mWrapper); mFlattenedJSObject = mWrapper->GetFlatJSObject(); if (mTearOff) mScriptableInfo = nsnull; else mScriptableInfo = mWrapper->GetScriptableInfo(); } else { NS_ABORT_IF_FALSE(!mFlattenedJSObject || IS_SLIM_WRAPPER(mFlattenedJSObject), "should have a slim wrapper"); } } if (!JSID_IS_VOID(name)) SetName(name); if (argc != NO_ARGS) SetArgsAndResultPtr(argc, argv, rval); CHECK_STATE(HAVE_OBJECT); }
XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage, JSContext* cx /* = nsnull */, JSObject* obj /* = nsnull */, JSObject* funobj /* = nsnull */, jsval name /* = 0 */, uintN argc /* = NO_ARGS */, jsval *argv /* = nsnull */, jsval *rval /* = nsnull */) : mState(INIT_FAILED), mXPC(nsXPConnect::GetXPConnect()), mThreadData(nsnull), mXPCContext(nsnull), mJSContext(cx), mContextPopRequired(JS_FALSE), mDestroyJSContextInDestructor(JS_FALSE), mCallerLanguage(callerLanguage), mCallee(nsnull) { // Mark our internal string wrappers as not used. Make sure we do // this before any early returns, as the destructor will assert // based on this. StringWrapperEntry *se = reinterpret_cast<StringWrapperEntry*>(&mStringWrapperData); PRUint32 i; for(i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) { se[i].mInUse = PR_FALSE; } if(!mXPC) return; mThreadData = XPCPerThreadData::GetData(mJSContext); if(!mThreadData) return; XPCJSContextStack* stack = mThreadData->GetJSContextStack(); JSContext* topJSContext; if(!stack || NS_FAILED(stack->Peek(&topJSContext))) { // If we don't have a stack we're probably in shutdown. NS_ASSERTION(!stack, "Bad, Peek failed!"); mJSContext = nsnull; return; } if(!mJSContext) { // This is slightly questionable. If called without an explicit // JSContext (generally a call to a wrappedJS) we will use the JSContext // on the top of the JSContext stack - if there is one - *before* // falling back on the safe JSContext. // This is good AND bad because it makes calls from JS -> native -> JS // have JS stack 'continuity' for purposes of stack traces etc. // Note: this *is* what the pre-XPCCallContext xpconnect did too. if(topJSContext) mJSContext = topJSContext; else if(NS_FAILED(stack->GetSafeJSContext(&mJSContext)) || !mJSContext) return; } // Get into the request as early as we can to avoid problems with scanning // callcontexts on other threads from within the gc callbacks. if(mCallerLanguage == NATIVE_CALLER) JS_BeginRequest(mJSContext); if(topJSContext != mJSContext) { if(NS_FAILED(stack->Push(mJSContext))) { NS_ERROR("bad!"); return; } mContextPopRequired = JS_TRUE; } mXPCContext = XPCContext::GetXPCContext(mJSContext); mPrevCallerLanguage = mXPCContext->SetCallingLangType(mCallerLanguage); // hook into call context chain for our thread mPrevCallContext = mThreadData->SetCallContext(this); // We only need to addref xpconnect once so only do it if this is the first // context in the chain. if(!mPrevCallContext) NS_ADDREF(mXPC); mState = HAVE_CONTEXT; if(!obj) return; mMethodIndex = 0xDEAD; mOperandJSObject = obj; mState = HAVE_OBJECT; mTearOff = nsnull; mWrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(mJSContext, obj, funobj, &mCurrentJSObject, &mTearOff); if(!mWrapper) return; DEBUG_CheckWrapperThreadSafety(mWrapper); mFlattenedJSObject = mWrapper->GetFlatJSObject(); if(mTearOff) mScriptableInfo = nsnull; else mScriptableInfo = mWrapper->GetScriptableInfo(); if(name) SetName(name); if(argc != NO_ARGS) SetArgsAndResultPtr(argc, argv, rval); CHECK_STATE(HAVE_OBJECT); }