From 928b5dc750f7adb0dc30960f3b758f985674457e Mon Sep 17 00:00:00 2001 From: "brendan%mozilla.org" Date: Mon, 5 Jun 2006 07:18:02 +0000 Subject: [PATCH] Fix orange balsa by landing mrbkap's patch for 326497, plus other fixes (340340, r=mrbkap). --- content/base/src/nsScriptLoader.cpp | 12 ++--- dom/src/base/nsDOMClassInfo.cpp | 35 ++++++++++----- dom/src/base/nsDOMClassInfo.h | 1 + js/src/xpconnect/src/xpcprivate.h | 1 + js/src/xpconnect/src/xpcthrower.cpp | 53 +++++++++++++++-------- js/src/xpconnect/src/xpcwrappednative.cpp | 6 ++- 6 files changed, 73 insertions(+), 35 deletions(-) diff --git a/content/base/src/nsScriptLoader.cpp b/content/base/src/nsScriptLoader.cpp index 9f7fa25d2185..f4221b85bee2 100644 --- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -750,15 +750,17 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest, mCurrentScript = aRequest->mElement; PRBool isUndefined; - context->EvaluateString(aScript, globalObject->GetGlobalJSObject(), - mDocument->NodePrincipal(), url.get(), - aRequest->mLineNo, aRequest->mJSVersion, nsnull, - &isUndefined); + rv = context->EvaluateString(aScript, globalObject->GetGlobalJSObject(), + mDocument->NodePrincipal(), url.get(), + aRequest->mLineNo, aRequest->mJSVersion, nsnull, + &isUndefined); // Put the old script back in case it wants to do anything else. mCurrentScript = oldCurrent; - ::JS_ReportPendingException(cx); + if (NS_FAILED(rv)) { + ::JS_ReportPendingException(cx); + } if (changed) { ::JS_SetOptions(cx, options); } diff --git a/dom/src/base/nsDOMClassInfo.cpp b/dom/src/base/nsDOMClassInfo.cpp index 06cdbd6568e0..f032ebd353ef 100644 --- a/dom/src/base/nsDOMClassInfo.cpp +++ b/dom/src/base/nsDOMClassInfo.cpp @@ -3352,10 +3352,20 @@ nsDOMClassInfo::PostCreate(nsIXPConnectWrappedNative *wrapper, } #endif + // Look up the name of our constructor in the current global scope. We do + // this because triggering this lookup can cause us to call + // nsWindowSH::NewResolve, which will end up in nsWindowSH::GlobalResolve. + // GlobalResolve does some prototype magic (which satisfies the if condition + // above) in order to make sure that prototype delegation works correctly. + // Consider if a site sets HTMLElement.prototype.foopy = function () { ... } + // Now, calling document.body.foopy() needs to ensure that looking up foopy + // on document.body's prototype will find the right function. This + // LookupProperty accomplishes that. + // XXX This shouldn't need to go through the JS engine. Instead, we should + // be calling nsWindowSH::GlobalResolve directly. JSObject *global = GetGlobalJSObject(cx, obj); - jsval val; - if (!::JS_GetProperty(cx, global, mData->mName, &val)) { + if (!::JS_LookupProperty(cx, global, mData->mName, &val)) { return NS_ERROR_UNEXPECTED; } @@ -4692,14 +4702,19 @@ public: nsresult Install(JSContext *cx, JSObject *target, jsval thisAsVal) { - if (!::JS_DefineUCProperty(cx, target, - NS_REINTERPRET_CAST(const jschar *, mClassName), - nsCRT::strlen(mClassName), thisAsVal, nsnull, - nsnull, 0)) { - return NS_ERROR_UNEXPECTED; - } - - return NS_OK; + PRBool doSecurityCheckInAddProperty = + nsDOMClassInfo::sDoSecurityCheckInAddProperty; + nsDOMClassInfo::sDoSecurityCheckInAddProperty = PR_FALSE; + + JSBool ok = + ::JS_DefineUCProperty(cx, target, + NS_REINTERPRET_CAST(const jschar *, mClassName), + nsCRT::strlen(mClassName), thisAsVal, nsnull, + nsnull, 0); + + nsDOMClassInfo::sDoSecurityCheckInAddProperty = + doSecurityCheckInAddProperty; + return ok ? NS_OK : NS_ERROR_UNEXPECTED; } private: diff --git a/dom/src/base/nsDOMClassInfo.h b/dom/src/base/nsDOMClassInfo.h index c5abff7629aa..87c145ce8104 100644 --- a/dom/src/base/nsDOMClassInfo.h +++ b/dom/src/base/nsDOMClassInfo.h @@ -397,6 +397,7 @@ protected: static const JSClass *sObjectClass; static const JSClass *sXPCNativeWrapperClass; +public: static PRBool sDoSecurityCheckInAddProperty; }; diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index ba2881b70485..e55c68acf801 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -2510,6 +2510,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/js/src/xpconnect/src/xpcthrower.cpp b/js/src/xpconnect/src/xpcthrower.cpp index a00da11b8896..a33163dc1545 100644 --- a/js/src/xpconnect/src/xpcthrower.cpp +++ b/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/js/src/xpconnect/src/xpcwrappednative.cpp b/js/src/xpconnect/src/xpcwrappednative.cpp index ffa3e342bcff..bf2c8959f887 100644 --- a/js/src/xpconnect/src/xpcwrappednative.cpp +++ b/js/src/xpconnect/src/xpcwrappednative.cpp @@ -457,8 +457,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; } }