mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-12 22:28:59 +02:00
Bug 901162 - Hoist EvaluateString into nsJSUtils. r=bz
This commit is contained in:
parent
f2b057f9f0
commit
1315953921
3 changed files with 78 additions and 54 deletions
|
|
@ -1241,70 +1241,21 @@ nsJSContext::EvaluateString(const nsAString& aScript,
|
|||
bool aCoerceToString,
|
||||
JS::Value* aRetValue)
|
||||
{
|
||||
PROFILER_LABEL("JS", "EvaluateString");
|
||||
MOZ_ASSERT_IF(aOptions.versionSet, aOptions.version != JSVERSION_UNKNOWN);
|
||||
MOZ_ASSERT_IF(aCoerceToString, aRetValue);
|
||||
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
|
||||
// Unfortunately, the JS engine actually compiles scripts with a return value
|
||||
// in a different, less efficient way. Furthermore, it can't JIT them in many
|
||||
// cases. So we need to be explicitly told whether the caller cares about the
|
||||
// return value. Callers use null to indicate they don't care.
|
||||
if (aRetValue) {
|
||||
*aRetValue = JSVAL_VOID;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
if (!mScriptsEnabled) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCxPusher pusher;
|
||||
pusher.Push(mContext);
|
||||
|
||||
xpc_UnmarkGrayObject(aScopeObject);
|
||||
nsAutoMicroTask mt;
|
||||
|
||||
JSPrincipals* p = JS_GetCompartmentPrincipals(js::GetObjectCompartment(aScopeObject));
|
||||
aOptions.setPrincipals(p);
|
||||
|
||||
bool ok = false;
|
||||
nsresult rv = sSecurityManager->CanExecuteScripts(mContext, nsJSPrincipals::get(p), &ok);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(ok, NS_OK);
|
||||
|
||||
// Scope the JSAutoCompartment so that it gets destroyed before we pop the
|
||||
// cx and potentially call JS_RestoreFrameChain.
|
||||
{
|
||||
JSAutoCompartment ac(mContext, aScopeObject);
|
||||
|
||||
JS::RootedObject rootedScope(mContext, aScopeObject);
|
||||
ok = JS::Evaluate(mContext, rootedScope, aOptions,
|
||||
PromiseFlatString(aScript).get(),
|
||||
aScript.Length(), aRetValue);
|
||||
if (ok && aCoerceToString && !aRetValue->isUndefined()) {
|
||||
JSString* str = JS_ValueToString(mContext, *aRetValue);
|
||||
ok = !!str;
|
||||
*aRetValue = ok ? JS::StringValue(str) : JS::UndefinedValue();
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
if (aRetValue) {
|
||||
*aRetValue = JS::UndefinedValue();
|
||||
}
|
||||
// Tell XPConnect about any pending exceptions. This is needed
|
||||
// to avoid dropping JS exceptions in case we got here through
|
||||
// nested calls through XPConnect.
|
||||
ReportPendingException();
|
||||
AutoCxPusher pusher(mContext);
|
||||
rv = nsJSUtils::EvaluateString(mContext, aScript, aScopeObject,
|
||||
aOptions, aCoerceToString, aRetValue);
|
||||
}
|
||||
|
||||
// ScriptEvaluated needs to come after we pop the stack
|
||||
pusher.Pop();
|
||||
ScriptEvaluated(true);
|
||||
|
||||
// Wrap the return value into whatever compartment mContext was in.
|
||||
if (aRetValue && !JS_WrapValue(mContext, aRetValue))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
#include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
|
||||
|
||||
|
|
@ -192,3 +193,68 @@ nsJSUtils::CompileFunction(JSContext* aCx,
|
|||
*aFunctionObject = JS_GetFunctionObject(fun);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJSUtils::EvaluateString(JSContext* aCx,
|
||||
const nsAString& aScript,
|
||||
JS::Handle<JSObject*> aScopeObject,
|
||||
JS::CompileOptions& aOptions,
|
||||
bool aCoerceToString,
|
||||
JS::Value* aRetValue)
|
||||
{
|
||||
PROFILER_LABEL("JS", "EvaluateString");
|
||||
MOZ_ASSERT_IF(aOptions.versionSet, aOptions.version != JSVERSION_UNKNOWN);
|
||||
MOZ_ASSERT_IF(aCoerceToString, aRetValue);
|
||||
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
|
||||
|
||||
// Unfortunately, the JS engine actually compiles scripts with a return value
|
||||
// in a different, less efficient way. Furthermore, it can't JIT them in many
|
||||
// cases. So we need to be explicitly told whether the caller cares about the
|
||||
// return value. Callers use null to indicate they don't care.
|
||||
if (aRetValue) {
|
||||
*aRetValue = JSVAL_VOID;
|
||||
}
|
||||
|
||||
xpc_UnmarkGrayObject(aScopeObject);
|
||||
nsAutoMicroTask mt;
|
||||
|
||||
JSPrincipals* p = JS_GetCompartmentPrincipals(js::GetObjectCompartment(aScopeObject));
|
||||
aOptions.setPrincipals(p);
|
||||
|
||||
bool ok = false;
|
||||
nsresult rv = nsContentUtils::GetSecurityManager()->
|
||||
CanExecuteScripts(aCx, nsJSPrincipals::get(p), &ok);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(ok, NS_OK);
|
||||
|
||||
// Scope the JSAutoCompartment so that we can later wrap the return value
|
||||
// into the caller's cx.
|
||||
{
|
||||
JSAutoCompartment ac(aCx, aScopeObject);
|
||||
|
||||
JS::RootedObject rootedScope(aCx, aScopeObject);
|
||||
ok = JS::Evaluate(aCx, rootedScope, aOptions,
|
||||
PromiseFlatString(aScript).get(),
|
||||
aScript.Length(), aRetValue);
|
||||
if (ok && aCoerceToString && !aRetValue->isUndefined()) {
|
||||
JSString* str = JS_ValueToString(aCx, *aRetValue);
|
||||
ok = !!str;
|
||||
*aRetValue = ok ? JS::StringValue(str) : JS::UndefinedValue();
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
if (aRetValue) {
|
||||
*aRetValue = JS::UndefinedValue();
|
||||
}
|
||||
// Tell XPConnect about any pending exceptions. This is needed
|
||||
// to avoid dropping JS exceptions in case we got here through
|
||||
// nested calls through XPConnect.
|
||||
ReportPendingException(aCx);
|
||||
}
|
||||
|
||||
// Wrap the return value into whatever compartment aCx was in.
|
||||
if (aRetValue && !JS_WrapValue(aCx, aRetValue))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,13 @@ public:
|
|||
const nsAString& aBody,
|
||||
JSObject** aFunctionObject);
|
||||
|
||||
static nsresult EvaluateString(JSContext* aCx,
|
||||
const nsAString& aScript,
|
||||
JS::Handle<JSObject*> aScopeObject,
|
||||
JS::CompileOptions &aOptions,
|
||||
bool aCoerceToString,
|
||||
JS::Value* aRetValue);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue