Move where we convert things into strings into a more centralized place. bug 372075, r=bzbarsky sr=jst

This commit is contained in:
mrbkap@gmail.com 2007-07-17 13:12:21 -07:00
parent fec888e1ea
commit 243fcf04c8
5 changed files with 67 additions and 34 deletions

View File

@ -297,36 +297,23 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
}
if (NS_FAILED(rv)) {
return rv;
}
}
rv = xpc->EvalInSandboxObject(NS_ConvertUTF8toUTF16(script), cx,
sandbox, &rval);
sandbox, PR_TRUE, &rval);
// Propagate and report exceptions that happened in the
// sandbox.
if (JS_IsExceptionPending(cx)) {
JS_ReportPendingException(cx);
isUndefined = PR_TRUE;
} else {
isUndefined = rval == JSVAL_VOID;
}
isUndefined = rval == JSVAL_VOID;
if (!isUndefined && NS_SUCCEEDED(rv)) {
JSAutoRequest ar(cx);
JSString *str = JS_ValueToString(cx, rval);
if (!str) {
// Report any pending exceptions.
if (JS_IsExceptionPending(cx)) {
JS_ReportPendingException(cx);
}
// We don't know why this failed, so just use a
// generic error code. It'll be translated to a
// different one below anyways.
rv = NS_ERROR_FAILURE;
} else {
result = nsDependentJSString(str);
}
NS_ASSERTION(JSVAL_IS_STRING(rval), "evalInSandbox is broken");
result = nsDependentJSString(JSVAL_TO_STRING(rval));
}
stack->Pop(nsnull);

View File

@ -443,7 +443,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
%}
[uuid(0f2f96c2-0a66-4677-a3d8-ebb907e9b780)]
[uuid(33f03128-e8a0-4906-8cdb-79c8c1144009)]
interface nsIXPConnect : nsISupports
{
%{ C++
@ -705,11 +705,16 @@ interface nsIXPConnect : nsISupports
* the script. The actual evaluation will happen on a new
* temporary context.
* @param sandbox The sandbox object to evaluate the script in.
* @param returnStringOnly The only results to come out of the
* computation (including exceptions) will
* be coerced into strings created in the
* sandbox.
* @return The result of the evaluation as a jsval. If the caller
* intends to use the return value from this call the caller
* is responsible for rooting the jsval before making a call
* to this method.
*/
[noscript] JSVal evalInSandboxObject(in AString source, in JSContextPtr cx,
in nsIXPConnectJSObjectHolder sandbox);
in nsIXPConnectJSObjectHolder sandbox,
in PRBool returnStringOnly);
};

View File

@ -1689,7 +1689,7 @@ nsXPConnect::CreateSandbox(JSContext *cx, nsIPrincipal *principal,
NS_IMETHODIMP
nsXPConnect::EvalInSandboxObject(const nsAString& source, JSContext *cx,
nsIXPConnectJSObjectHolder *sandbox,
jsval *rval)
PRBool returnStringOnly, jsval *rval)
{
#ifdef XPCONNECT_STANDALONE
return NS_ERROR_NOT_AVAILABLE;
@ -1702,7 +1702,8 @@ nsXPConnect::EvalInSandboxObject(const nsAString& source, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv);
return xpc_EvalInSandbox(cx, obj, source,
NS_ConvertUTF16toUTF8(source).get(), 1, rval);
NS_ConvertUTF16toUTF8(source).get(), 1,
returnStringOnly, rval);
#endif /* XPCONNECT_STANDALONE */
}

View File

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=80:
* vim: set ts=8 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -3459,7 +3459,8 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source)
}
}
rv = xpc_EvalInSandbox(cx, sandbox, source, filename.get(), lineNo, rval);
rv = xpc_EvalInSandbox(cx, sandbox, source, filename.get(), lineNo,
PR_FALSE, rval);
if (NS_SUCCEEDED(rv)) {
if (JS_IsExceptionPending(cx)) {
@ -3476,7 +3477,8 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source)
#ifndef XPCONNECT_STANDALONE
nsresult
xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
const char *filename, PRInt32 lineNo, jsval *rval)
const char *filename, PRInt32 lineNo,
PRBool returnStringOnly, jsval *rval)
{
if (JS_GetClass(cx, sandbox) != &SandboxClass)
return NS_ERROR_INVALID_ARG;
@ -3521,23 +3523,56 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
nsresult rv = NS_OK;
AutoJSRequestWithNoCallContext req(sandcx->GetJSContext());
JSString *str = nsnull;
if (!JS_EvaluateUCScriptForPrincipals(sandcx->GetJSContext(), sandbox,
jsPrincipals,
reinterpret_cast<const jschar *>
(PromiseFlatString(source).get()),
source.Length(), filename, lineNo,
rval)) {
rval) ||
(returnStringOnly &&
!JSVAL_IS_VOID(*rval) &&
!(str = JS_ValueToString(sandcx->GetJSContext(), *rval)))) {
jsval exn;
if (JS_GetPendingException(sandcx->GetJSContext(), &exn)) {
AutoJSSuspendRequestWithNoCallContext sus(sandcx->GetJSContext());
AutoJSRequestWithNoCallContext cxreq(cx);
// Stash the exception in |cx| so we can execute code on
// sandcx without a pending exception.
{
AutoJSSuspendRequestWithNoCallContext sus(sandcx->GetJSContext());
AutoJSRequestWithNoCallContext cxreq(cx);
JS_SetPendingException(cx, exn);
JS_SetPendingException(cx, exn);
}
JS_ClearPendingException(sandcx->GetJSContext());
if (returnStringOnly) {
// The caller asked for strings only, convert the
// exception into a string.
str = JS_ValueToString(sandcx->GetJSContext(), exn);
AutoJSSuspendRequestWithNoCallContext sus(sandcx->GetJSContext());
AutoJSRequestWithNoCallContext cxreq(cx);
if (str) {
// We converted the exception to a string. Use that
// as the value exception.
JS_SetPendingException(cx, STRING_TO_JSVAL(str));
} else {
JS_ClearPendingException(cx);
rv = NS_ERROR_FAILURE;
}
}
// Clear str so we don't confuse callers.
str = nsnull;
} else {
rv = NS_ERROR_OUT_OF_MEMORY;
}
}
if (str) {
*rval = STRING_TO_JSVAL(str);
}
if (stack) {
stack->Pop(nsnull);
}

View File

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=80:
* vim: set ts=8 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -3752,10 +3752,15 @@ xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop);
// that *rval doesn't get collected during the call or usage after the
// call. This helper will use filename and lineNo for error reporting,
// and if no filename is provided it will use the codebase from the
// principal and line number 1 as a fallback.
// principal and line number 1 as a fallback. if returnStringOnly is
// true, then the result in *rval, or the exception in cx->exception
// will be coerced into strings. If an exception is thrown converting
// an exception to a string, evalInSandbox will return an NS_ERROR_*
// result, and cx->exception will be empty.
nsresult
xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
const char *filename, PRInt32 lineNo, jsval *rval);
const char *filename, PRInt32 lineNo,
PRBool returnStringOnly, jsval *rval);
#endif /* !XPCONNECT_STANDALONE */
/***************************************************************************/