From 4198b5588fe3d10a5840471fbd376b7b3b321a56 Mon Sep 17 00:00:00 2001 From: Andrew Drake Date: Tue, 14 Dec 2010 13:24:00 -0800 Subject: [PATCH] Bug 617870, rest of bug 609141 - Cross-compartment calls for JSD, add JSScript* option for JS_EnterCrossCompartmentCall. r=jorendorff --HG-- extra : rebase_source : bc60e91a6804470e28038cc62e60eca16710776c --- js/jsd/jsd_xpc.cpp | 46 +++++++++++++++++++++++++++++++++------------- js/src/jsapi.cpp | 38 ++++++++++++++++++++++++++++++++++++++ js/src/jsapi.h | 5 +++++ 3 files changed, 76 insertions(+), 13 deletions(-) diff --git a/js/jsd/jsd_xpc.cpp b/js/jsd/jsd_xpc.cpp index 0e895026f530..190f65591122 100644 --- a/js/jsd/jsd_xpc.cpp +++ b/js/jsd/jsd_xpc.cpp @@ -1033,17 +1033,27 @@ jsdScript::CreatePPLineMap() JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL); JSFunction *fun = JSD_GetJSFunction (mCx, mScript); JSScript *script; + JSString *jsstr; PRUint32 baseLine; PRBool scriptOwner = PR_FALSE; if (fun) { - uintN nargs = JS_GetFunctionArgumentCount(cx, fun); - if (nargs > 12) - return nsnull; - JSString *jsstr = JS_DecompileFunctionBody (cx, fun, 4); - if (!jsstr) - return nsnull; - + uintN nargs; + + /* Enter a new block so we can leave before the end of this block */ + do { + JSAutoEnterCompartment ac; + if (!ac.enter(cx, JS_GetFunctionObject(fun))) + return nsnull; + + nargs = JS_GetFunctionArgumentCount(cx, fun); + if (nargs > 12) + return nsnull; + jsstr = JS_DecompileFunctionBody (cx, fun, 4); + if (!jsstr) + return nsnull; + } while(false); + const char *argnames[] = {"arg1", "arg2", "arg3", "arg4", "arg5", "arg6", "arg7", "arg8", "arg9", "arg10", "arg11", "arg12" }; @@ -1055,10 +1065,19 @@ jsdScript::CreatePPLineMap() return nsnull; baseLine = 3; } else { - JSString *jsstr = JS_DecompileScript (cx, JSD_GetJSScript(mCx, mScript), - "ppscript", 4); - if (!jsstr) - return nsnull; + /* Enter a new block so we can leave before the end of this block */ + do { + script = JSD_GetJSScript(mCx, mScript); + + JSAutoEnterCompartment ac; + if (!ac.enter(cx, script)) + return nsnull; + + jsstr = JS_DecompileScript (cx, JSD_GetJSScript(mCx, mScript), + "ppscript", 4); + if (!jsstr) + return nsnull; + } while(false); script = JS_CompileUCScript (cx, obj, JS_GetStringChars(jsstr), @@ -1343,14 +1362,15 @@ jsdScript::GetFunctionSource(nsAString & aFunctionSource) JSAutoRequest ar(cx); JSString *jsstr; + JSAutoEnterCompartment ac; if (fun) { - JSAutoEnterCompartment ac; if (!ac.enter(cx, JS_GetFunctionObject(fun))) return NS_ERROR_FAILURE; jsstr = JS_DecompileFunction (cx, fun, 4); } else { JSScript *script = JSD_GetJSScript (mCx, mScript); - js::SwitchToCompartment sc(cx, script->compartment); + if (!ac.enter(cx, script)) + return NS_ERROR_FAILURE; jsstr = JS_DecompileScript (cx, script, "ppscript", 4); } if (!jsstr) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 705174242558..8e1cf6df316e 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -111,6 +111,16 @@ using namespace js; using namespace js::gc; +static JSClass dummy_class = { + "jdummy", + JSCLASS_GLOBAL_FLAGS, + JS_PropertyStub, JS_PropertyStub, + JS_PropertyStub, JS_PropertyStub, + JS_EnumerateStub, JS_ResolveStub, + JS_ConvertStub, NULL, + JSCLASS_NO_OPTIONAL_MEMBERS +}; + class AutoVersionAPI { JSContext * const cx; @@ -1169,6 +1179,22 @@ JS_EnterCrossCompartmentCall(JSContext *cx, JSObject *target) return reinterpret_cast(call); } +JS_PUBLIC_API(JSCrossCompartmentCall *) +JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target) +{ + CHECK_REQUEST(cx); + + JS_ASSERT(target); + JSObject *scriptObject = target->u.object; + if (!scriptObject) { + SwitchToCompartment sc(cx, target->compartment); + scriptObject = JS_NewGlobalObject(cx, &dummy_class); + if (!scriptObject) + return NULL; + } + return JS_EnterCrossCompartmentCall(cx, scriptObject); +} + JS_PUBLIC_API(void) JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall *call) { @@ -1190,6 +1216,18 @@ JSAutoEnterCompartment::enter(JSContext *cx, JSObject *target) return call != NULL; } +bool +JSAutoEnterCompartment::enter(JSContext *cx, JSScript *target) +{ + JS_ASSERT(!call); + if (cx->compartment == target->compartment) { + call = reinterpret_cast(1); + return true; + } + call = JS_EnterCrossCompartmentCallScript(cx, target); + return call != NULL; +} + void JSAutoEnterCompartment::enterAndIgnoreErrors(JSContext *cx, JSObject *target) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index d17b1aa28155..2f289eaedfa5 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -979,6 +979,9 @@ JS_SetWrapObjectCallbacks(JSRuntime *rt, extern JS_PUBLIC_API(JSCrossCompartmentCall *) JS_EnterCrossCompartmentCall(JSContext *cx, JSObject *target); +extern JS_PUBLIC_API(JSCrossCompartmentCall *) +JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target); + extern JS_PUBLIC_API(void) JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall *call); @@ -1009,6 +1012,8 @@ class JS_PUBLIC_API(JSAutoEnterCompartment) bool enter(JSContext *cx, JSObject *target); + bool enter(JSContext *cx, JSScript *target); + void enterAndIgnoreErrors(JSContext *cx, JSObject *target); bool entered() const { return call != NULL; }