diff --git a/mozilla/js/src/xpconnect/src/xpcprivate.h b/mozilla/js/src/xpconnect/src/xpcprivate.h index dbfdbdc70fa..54fc9c33c73 100644 --- a/mozilla/js/src/xpconnect/src/xpcprivate.h +++ b/mozilla/js/src/xpconnect/src/xpcprivate.h @@ -2515,6 +2515,7 @@ private: static void BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz); static JSBool ThrowExceptionObject(JSContext* cx, nsIException* e); + static JSBool CheckForPendingException(nsresult result, XPCCallContext &ccx); private: static JSBool sVerbose; diff --git a/mozilla/js/src/xpconnect/src/xpcthrower.cpp b/mozilla/js/src/xpconnect/src/xpcthrower.cpp index a00da11b889..a33163dc154 100644 --- a/mozilla/js/src/xpconnect/src/xpcthrower.cpp +++ b/mozilla/js/src/xpconnect/src/xpcthrower.cpp @@ -49,11 +49,41 @@ void XPCThrower::Throw(nsresult rv, JSContext* cx) { const char* format; + if(JS_IsExceptionPending(cx)) + return; if(!nsXPCException::NameAndFormatForNSResult(rv, nsnull, &format)) format = ""; BuildAndThrowException(cx, rv, format); } +/* + * If there has already been an exception thrown, see if we're throwing the + * same sort of exception, and if we are, don't clobber the old one. ccx + * should be the current call context. + */ +// static +JSBool +XPCThrower::CheckForPendingException(nsresult result, XPCCallContext &ccx) +{ + nsXPConnect* xpc = nsXPConnect::GetXPConnect(); + if(!xpc) + return JS_FALSE; + + nsCOMPtr e; + xpc->GetPendingException(getter_AddRefs(e)); + if(!e) + return JS_FALSE; + xpc->SetPendingException(nsnull); + + nsresult e_result; + if(NS_FAILED(e->GetResult(&e_result)) || e_result != result) + return JS_FALSE; + + if(!ThrowExceptionObject(ccx, e)) + JS_ReportOutOfMemory(ccx); + return JS_TRUE; +} + // static void XPCThrower::Throw(nsresult rv, XPCCallContext& ccx) @@ -61,6 +91,9 @@ XPCThrower::Throw(nsresult rv, XPCCallContext& ccx) char* sz; const char* format; + if(CheckForPendingException(rv, ccx)) + return; + if(!nsXPCException::NameAndFormatForNSResult(rv, nsnull, &format)) format = ""; @@ -91,24 +124,8 @@ XPCThrower::ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx) * call. So we'll just throw that exception into our JS. */ - nsXPConnect* xpc = nsXPConnect::GetXPConnect(); - if(xpc) - { - nsCOMPtr e; - xpc->GetPendingException(getter_AddRefs(e)); - if(e) - { - xpc->SetPendingException(nsnull); - - nsresult e_result; - if(NS_SUCCEEDED(e->GetResult(&e_result)) && e_result == result) - { - if(!ThrowExceptionObject(ccx, e)) - JS_ReportOutOfMemory(ccx); - return; - } - } - } + if(CheckForPendingException(result, ccx)) + return; // else... diff --git a/mozilla/js/src/xpconnect/src/xpcwrappednative.cpp b/mozilla/js/src/xpconnect/src/xpcwrappednative.cpp index 9f4d2ae038e..4e61e0312d1 100644 --- a/mozilla/js/src/xpconnect/src/xpcwrappednative.cpp +++ b/mozilla/js/src/xpconnect/src/xpcwrappednative.cpp @@ -461,8 +461,10 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx, XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo(); if(si && si->GetFlags().WantPostCreate()) { - si->GetCallback()-> - PostCreate(wrapper, ccx, wrapper->GetFlatJSObject()); + rv = si->GetCallback()-> + PostCreate(wrapper, ccx, wrapper->GetFlatJSObject()); + if(NS_FAILED(rv)) + return rv; } }