Bug 628758 - Various compartment and request fixes for JSD (r=luke)

--HG--
extra : rebase_source : 98a06e6f9c7528ebbdbaa445d7cc8e28973d5d02
This commit is contained in:
Steve Fink 2011-01-27 18:31:48 -08:00
parent 5d5948d114
commit 2af7d0908f
3 changed files with 127 additions and 61 deletions

View File

@ -527,6 +527,9 @@ jsd_GetScriptLineExtent(JSDContext* jsdc, JSDScript *jsdscript)
jsuword
jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, uintN line)
{
jsuword pc;
JSCrossCompartmentCall *call;
#ifdef LIVEWIRE
if( jsdscript && jsdscript->lwscript )
{
@ -537,20 +540,28 @@ jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, uintN line)
}
#endif
return (jsuword) JS_LineNumberToPC(jsdc->dumbContext,
jsdscript->script, line );
call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script);
if(!call)
return 0;
pc = (jsuword) JS_LineNumberToPC(jsdc->dumbContext, jsdscript->script, line );
JS_LeaveCrossCompartmentCall(call);
return pc;
}
uintN
jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc)
{
JSCrossCompartmentCall *call;
uintN first = jsdscript->lineBase;
uintN last = first + jsd_GetScriptLineExtent(jsdc, jsdscript) - 1;
uintN line = pc
? JS_PCToLineNumber(jsdc->dumbContext,
jsdscript->script,
(jsbytecode*)pc)
: 0;
uintN line = 0;
call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script);
if(!call)
return 0;
if (pc)
line = JS_PCToLineNumber(jsdc->dumbContext, jsdscript->script, (jsbytecode*)pc);
JS_LeaveCrossCompartmentCall(call);
if( line < first )
return first;
@ -594,10 +605,15 @@ jsd_GetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc* hook, void** callerdata)
JSBool
jsd_EnableSingleStepInterrupts(JSDContext* jsdc, JSDScript* jsdscript, JSBool enable)
{
JSCrossCompartmentCall *call;
JSBool rv;
call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script);
if(!call)
return JS_FALSE;
JSD_LOCK();
rv = JS_SetSingleStepMode(jsdc->dumbContext, jsdscript->script, enable);
JSD_UNLOCK();
JS_LeaveCrossCompartmentCall(call);
return rv;
}
@ -802,6 +818,8 @@ jsd_SetExecutionHook(JSDContext* jsdc,
void* callerdata)
{
JSDExecHook* jsdhook;
JSBool rv;
JSCrossCompartmentCall *call;
JSD_LOCK();
if( ! hook )
@ -831,10 +849,20 @@ jsd_SetExecutionHook(JSDContext* jsdc,
jsdhook->hook = hook;
jsdhook->callerdata = callerdata;
if( ! JS_SetTrap(jsdc->dumbContext, jsdscript->script,
(jsbytecode*)pc, jsd_TrapHandler,
PRIVATE_TO_JSVAL(jsdhook)) )
{
call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script);
if(!call) {
free(jsdhook);
JSD_UNLOCK();
return JS_FALSE;
}
rv = JS_SetTrap(jsdc->dumbContext, jsdscript->script,
(jsbytecode*)pc, jsd_TrapHandler,
PRIVATE_TO_JSVAL(jsdhook));
JS_LeaveCrossCompartmentCall(call);
if ( ! rv ) {
free(jsdhook);
JSD_UNLOCK();
return JS_FALSE;
@ -851,6 +879,7 @@ jsd_ClearExecutionHook(JSDContext* jsdc,
JSDScript* jsdscript,
jsuword pc)
{
JSCrossCompartmentCall *call;
JSDExecHook* jsdhook;
JSD_LOCK();
@ -862,9 +891,17 @@ jsd_ClearExecutionHook(JSDContext* jsdc,
return JS_FALSE;
}
call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script);
if(!call) {
JSD_UNLOCK();
return JS_FALSE;
}
JS_ClearTrap(jsdc->dumbContext, jsdscript->script,
(jsbytecode*)pc, NULL, NULL );
JS_LeaveCrossCompartmentCall(call);
JS_REMOVE_LINK(&jsdhook->links);
free(jsdhook);
@ -886,6 +923,7 @@ jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript)
free(jsdhook);
}
/* No cross-compartment call here because we may be in the middle of GC */
JS_ClearScriptTraps(jsdc->dumbContext, jsdscript->script);
JSD_UNLOCK();

View File

@ -211,36 +211,50 @@ jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
JSContext* cx = jsdc->dumbContext;
JSExceptionState* exceptionState;
JSCrossCompartmentCall *call = NULL;
jsval stringval;
JSString *string;
JSBool needWrap;
JSObject *scopeObj;
if(!jsdval->string)
{
/* if the jsval is a string, then we don't need to double root it */
if(JSVAL_IS_STRING(jsdval->val))
jsdval->string = JSVAL_TO_STRING(jsdval->val);
else
{
JS_BeginRequest(cx);
call = JSVAL_IS_PRIMITIVE(jsdval->val)
? NULL
: JS_EnterCrossCompartmentCall(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
if(!call) {
JS_EndRequest(cx);
if(jsdval->string)
return jsdval->string;
return NULL;
}
exceptionState = JS_SaveExceptionState(cx);
jsdval->string = JS_ValueToString(cx, jsdval->val);
JS_RestoreExceptionState(cx, exceptionState);
if(jsdval->string)
{
if(!JS_AddNamedStringRoot(cx, &jsdval->string, "ValueString"))
jsdval->string = NULL;
}
JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(cx);
}
/* Reuse the string without copying or re-rooting it */
if(JSVAL_IS_STRING(jsdval->val)) {
jsdval->string = JSVAL_TO_STRING(jsdval->val);
return jsdval->string;
}
JS_BeginRequest(cx);
/* Objects call JS_ValueToString in their own compartment. */
scopeObj = JSVAL_IS_OBJECT(jsdval->val) ? JSVAL_TO_OBJECT(jsdval->val) : jsdc->glob;
call = JS_EnterCrossCompartmentCall(cx, scopeObj);
if(!call) {
JS_EndRequest(cx);
return NULL;
}
exceptionState = JS_SaveExceptionState(cx);
string = JS_ValueToString(cx, jsdval->val);
JS_RestoreExceptionState(cx, exceptionState);
JS_LeaveCrossCompartmentCall(call);
stringval = STRING_TO_JSVAL(string);
call = JS_EnterCrossCompartmentCall(cx, jsdc->glob);
if(!call || !JS_WrapValue(cx, &stringval)) {
JS_EndRequest(cx);
return NULL;
}
jsdval->string = JSVAL_TO_STRING(stringval);
if(!JS_AddNamedStringRoot(cx, &jsdval->string, "ValueString"))
jsdval->string = NULL;
JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(cx);
return jsdval->string;
}
@ -281,6 +295,11 @@ jsd_GetValueFunctionId(JSDContext* jsdc, JSDValue* jsdval)
/***************************************************************************/
/*
* Create a new JSD value referring to a jsval. Copy string values into the
* JSD compartment. Leave all other GCTHINGs in their native compartments
* and access them through cross-compartment calls.
*/
JSDValue*
jsd_NewValue(JSDContext* jsdc, jsval val)
{
@ -292,7 +311,7 @@ jsd_NewValue(JSDContext* jsdc, jsval val)
if(JSVAL_IS_GCTHING(val))
{
JSBool ok = JS_FALSE;
JSBool ok;
JS_BeginRequest(jsdc->dumbContext);
call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
@ -303,6 +322,12 @@ jsd_NewValue(JSDContext* jsdc, jsval val)
}
ok = JS_AddNamedValueRoot(jsdc->dumbContext, &jsdval->val, "JSDValue");
if(ok && JSVAL_IS_STRING(val)) {
if(!JS_WrapValue(jsdc->dumbContext, &val)) {
ok = JS_FALSE;
}
}
JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(jsdc->dumbContext);
if(!ok)

View File

@ -1040,16 +1040,17 @@ jsdScript::CreatePPLineMap()
JSAutoRequest ar(cx);
JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
JSFunction *fun = JSD_GetJSFunction (mCx, mScript);
JSScript *script;
JSString *jsstr;
JSScript *script; /* In JSD compartment */
PRUint32 baseLine;
PRBool scriptOwner = PR_FALSE;
JSString *jsstr;
size_t length;
const jschar *chars;
if (fun) {
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;
@ -1060,13 +1061,12 @@ jsdScript::CreatePPLineMap()
jsstr = JS_DecompileFunctionBody (cx, fun, 4);
if (!jsstr)
return nsnull;
} while(false);
size_t length;
const jschar *chars = JS_GetStringCharsAndLength(cx, jsstr, &length);
if (!chars)
return nsnull;
if (!(chars = JS_GetStringCharsAndLength(cx, jsstr, &length)))
return nsnull;
}
JS::Anchor<JSString *> kungFuDeathGrip(jsstr);
const char *argnames[] = {"arg1", "arg2", "arg3", "arg4",
"arg5", "arg6", "arg7", "arg8",
"arg9", "arg10", "arg11", "arg12" };
@ -1076,27 +1076,24 @@ jsdScript::CreatePPLineMap()
return nsnull;
baseLine = 3;
} else {
/* Enter a new block so we can leave before the end of this block */
do {
script = JSD_GetJSScript(mCx, mScript);
script = JSD_GetJSScript(mCx, mScript);
JSString *jsstr;
{
JSAutoEnterCompartment ac;
if (!ac.enter(cx, script))
return nsnull;
jsstr = JS_DecompileScript (cx, JSD_GetJSScript(mCx, mScript),
"ppscript", 4);
jsstr = JS_DecompileScript (cx, JSD_GetJSScript(mCx, mScript), "ppscript", 4);
if (!jsstr)
return nsnull;
} while(false);
size_t length;
const jschar *chars = JS_GetStringCharsAndLength(cx, jsstr, &length);
if (!chars)
return nsnull;
if (!(chars = JS_GetStringCharsAndLength(cx, jsstr, &length)))
return nsnull;
}
script = JS_CompileUCScript (cx, obj, chars, length,
"x-jsd:ppbuffer?type=script", 1);
JS::Anchor<JSString *> kungFuDeathGrip(jsstr);
script = JS_CompileUCScript (cx, obj, chars, length, "x-jsd:ppbuffer?type=script", 1);
if (!script)
return nsnull;
scriptOwner = PR_TRUE;
@ -1190,6 +1187,9 @@ jsdScript::GetVersion (PRInt32 *_rval)
ASSERT_VALID_EPHEMERAL;
JSContext *cx = JSD_GetDefaultJSContext (mCx);
JSScript *script = JSD_GetJSScript(mCx, mScript);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, script))
return NS_ERROR_FAILURE;
*_rval = static_cast<PRInt32>(JS_GetScriptVersion(cx, script));
return NS_OK;
}
@ -1288,6 +1288,9 @@ jsdScript::GetParameterNames(PRUint32* count, PRUnichar*** paramNames)
JSFunction *fun = JSD_GetJSFunction (mCx, mScript);
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, JS_GetFunctionObject(fun)))
return NS_ERROR_FAILURE;
uintN nargs;
if (!fun ||