void nsJSUtils::ReportPendingException(JSContext *aContext) { if (JS_IsExceptionPending(aContext)) { bool saved = JS_SaveFrameChain(aContext); { // JS_SaveFrameChain set the compartment of aContext to null, so we need // to enter a compartment. The question is, which one? We don't want to // enter the original compartment of aContext (or the compartment of the // current exception on aContext, for that matter) because when we // JS_ReportPendingException the JS engine can try to duck-type the // exception and produce a JSErrorReport. It will then pass that // JSErrorReport to the error reporter on aContext, which might expose // information from it to script via onerror handlers. So it's very // important that the duck typing happen in the same compartment as the // onerror handler. In practice, that's the compartment of the window (or // otherwise default global) of aContext, so use that here. nsIScriptContext* scx = GetScriptContextFromJSContext(aContext); JS::Rooted<JSObject*> scope(aContext); scope = scx ? scx->GetWindowProxy() : js::DefaultObjectForContextOrNull(aContext); if (!scope) { // The SafeJSContext has no default object associated with it. MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aContext == nsContentUtils::GetSafeJSContext()); scope = xpc::UnprivilegedJunkScope(); // Usage approved by bholley } JSAutoCompartment ac(aContext, scope); JS_ReportPendingException(aContext); } if (saved) { JS_RestoreFrameChain(aContext); } } }
/* JSContext pop (); */ NS_IMETHODIMP XPCJSContextStack::Pop(JSContext * *_retval) { NS_ASSERTION(!mStack.IsEmpty(), "ThreadJSContextStack underflow"); PRUint32 idx = mStack.Length() - 1; // The thing we're popping NS_ASSERTION(!mStack[idx].frame, "Shouldn't have a pending frame to restore on the context " "we're popping!"); if(_retval) *_retval = mStack[idx].cx; mStack.RemoveElementAt(idx); if(idx > 0) { --idx; // Advance to new top of the stack XPCJSContextInfo & e = mStack[idx]; NS_ASSERTION(!e.frame || e.cx, "Shouldn't have frame without a cx!"); if(e.requestDepth) JS_ResumeRequest(e.cx, e.requestDepth); e.requestDepth = 0; if(e.cx && e.frame) { // Pop() can be called outside any request for e.cx. JSAutoRequest ar(e.cx); JS_RestoreFrameChain(e.cx, e.frame); e.frame = nsnull; } } return NS_OK; }
~SafeCallGuard() { if (cx) { JS_SetOptions(cx, options); JS_RestoreFrameChain(cx, fp); js_RestoreRegExpStatics(cx, &statics, &tvr, &tvr2); nsIScriptSecurityManager_1_9_2 *ssm = XPCWrapper::GetSecurityManager(); if (ssm) { ssm->PopContextPrincipal(cx); } } }
void nsJSUtils::ReportPendingException(JSContext *aContext) { if (JS_IsExceptionPending(aContext)) { bool saved = JS_SaveFrameChain(aContext); { JSAutoCompartment ac(aContext, js::DefaultObjectForContextOrNull(aContext)); JS_ReportPendingException(aContext); } if (saved) { JS_RestoreFrameChain(aContext); } } }
bool CallTrusted(JSContext *cx, unsigned argc, jsval *vp) { if (!JS_SaveFrameChain(cx)) return false; bool ok = false; { JSAutoCompartment ac(cx, trusted_glob); ok = JS_CallFunctionValue(cx, nullptr, JS::ObjectValue(*trusted_fun), 0, nullptr, vp); } JS_RestoreFrameChain(cx); return ok; }
static bool CallTrusted(JSContext *cx, unsigned argc, jsval *vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); if (!JS_SaveFrameChain(cx)) return false; bool ok = false; { JSAutoCompartment ac(cx, trusted_glob); JS::RootedValue funVal(cx, JS::ObjectValue(*trusted_fun)); ok = JS_CallFunctionValue(cx, JS::NullPtr(), funVal, JS::HandleValueArray::empty(), args.rval()); } JS_RestoreFrameChain(cx); return ok; }
void nsJSUtils::ReportPendingException(JSContext *aContext) { if (JS_IsExceptionPending(aContext)) { bool saved = JS_SaveFrameChain(aContext); { nsIScriptContext* scx = GetScriptContextFromJSContext(aContext); JS::Rooted<JSObject*> scope(aContext); scope = scx ? scx->GetWindowProxy() : js::DefaultObjectForContextOrNull(aContext); JSAutoCompartment ac(aContext, scope); JS_ReportPendingException(aContext); } if (saved) { JS_RestoreFrameChain(aContext); } } }
JSBool CallTrusted(JSContext *cx, unsigned argc, jsval *vp) { if (!JS_SaveFrameChain(cx)) return JS_FALSE; JSBool ok = JS_FALSE; { JSAutoEnterCompartment ac; ok = ac.enter(cx, trusted_glob.get()); if (!ok) goto out; ok = JS_CallFunctionValue(cx, NULL, OBJECT_TO_JSVAL(trusted_fun.get()), 0, NULL, vp); } out: JS_RestoreFrameChain(cx); return ok; }
nsresult nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement) { NS_PRECONDITION(IsCompiled(), "Can't execute uncompiled method"); if (!mJSMethodObject) { // Nothing to do here return NS_OK; } // Get the script context the same way // nsXBLProtoImpl::InstallImplementation does. nsIDocument* document = aBoundElement->OwnerDoc(); nsIScriptGlobalObject* global = document->GetScriptGlobalObject(); if (!global) { return NS_OK; } nsCOMPtr<nsIScriptContext> context = global->GetContext(); if (!context) { return NS_OK; } JSContext* cx = context->GetNativeContext(); JSObject* globalObject = global->GetGlobalJSObject(); nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper; jsval v; nsresult rv = nsContentUtils::WrapNative(cx, globalObject, aBoundElement, &v, getter_AddRefs(wrapper)); NS_ENSURE_SUCCESS(rv, rv); JSObject* thisObject = JSVAL_TO_OBJECT(v); JSAutoRequest ar(cx); JSAutoEnterCompartment ac; if (!ac.enter(cx, thisObject)) return NS_ERROR_UNEXPECTED; // Clone the function object, using thisObject as the parent so "this" is in // the scope chain of the resulting function (for backwards compat to the // days when this was an event handler). JSObject* method = ::JS_CloneFunctionObject(cx, mJSMethodObject, thisObject); if (!method) return NS_ERROR_OUT_OF_MEMORY; // Now call the method // Use nsCxPusher to make sure we call ScriptEvaluated when we're done. nsCxPusher pusher; NS_ENSURE_STATE(pusher.Push(aBoundElement)); // Check whether it's OK to call the method. rv = nsContentUtils::GetSecurityManager()->CheckFunctionAccess(cx, method, thisObject); JSBool ok = JS_TRUE; if (NS_SUCCEEDED(rv)) { jsval retval; ok = ::JS_CallFunctionValue(cx, thisObject, OBJECT_TO_JSVAL(method), 0 /* argc */, nsnull /* argv */, &retval); } if (!ok) { // If a constructor or destructor threw an exception, it doesn't stop // anything else. We just report it. Note that we need to set aside the // frame chain here, since the constructor invocation is not related to // whatever is on the stack right now, really. JSBool saved = JS_SaveFrameChain(cx); JS_ReportPendingException(cx); if (saved) JS_RestoreFrameChain(cx); return NS_ERROR_FAILURE; } return NS_OK; }