--- a/js/jsd/jsd_val.c
+++ b/js/jsd/jsd_val.c
@@ -148,26 +148,35 @@ jsd_IsValueFunction(JSDContext* jsdc, JS
JSBool
jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval)
{
JSContext* cx = jsdc->dumbContext;
jsval val = jsdval->val;
JSFunction* fun;
JSExceptionState* exceptionState;
+ JSCrossCompartmentCall *call = NULL;
if(jsd_IsValueFunction(jsdc, jsdval))
{
JSBool ok = JS_FALSE;
JS_BeginRequest(cx);
+ call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
+ if(!call) {
+ JS_EndRequest(cx);
+
+ return JS_FALSE;
+ }
+
exceptionState = JS_SaveExceptionState(cx);
fun = JS_ValueToFunction(cx, val);
JS_RestoreExceptionState(cx, exceptionState);
if(fun)
ok = JS_GetFunctionScript(cx, fun) ? JS_FALSE : JS_TRUE;
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(cx);
JS_ASSERT(fun);
return ok;
}
return !JSVAL_IS_PRIMITIVE(val);
}
/***************************************************************************/
@@ -198,75 +207,104 @@ jsd_GetValueDouble(JSDContext* jsdc, JSD
return JSVAL_TO_DOUBLE(jsdval->val);
}
JSString*
jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
{
JSContext* cx = jsdc->dumbContext;
JSExceptionState* exceptionState;
+ JSCrossCompartmentCall *call = NULL;
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 = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
+ if(!call) {
+ JS_EndRequest(cx);
+
+ 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);
}
}
return jsdval->string;
}
const char*
jsd_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval)
{
JSContext* cx = jsdc->dumbContext;
JSFunction* fun;
JSExceptionState* exceptionState;
+ JSCrossCompartmentCall *call = NULL;
if(!jsdval->funName && jsd_IsValueFunction(jsdc, jsdval))
{
JS_BeginRequest(cx);
+
+ call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
+ if(!call) {
+ JS_EndRequest(cx);
+
+ return NULL;
+ }
+
exceptionState = JS_SaveExceptionState(cx);
fun = JS_ValueToFunction(cx, jsdval->val);
JS_RestoreExceptionState(cx, exceptionState);
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(cx);
if(!fun)
return NULL;
jsdval->funName = JS_GetFunctionName(fun);
}
return jsdval->funName;
}
/***************************************************************************/
JSDValue*
jsd_NewValue(JSDContext* jsdc, jsval val)
{
JSDValue* jsdval;
+ JSCrossCompartmentCall *call = NULL;
if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue))))
return NULL;
if(JSVAL_IS_GCTHING(val))
{
JSBool ok = JS_FALSE;
JS_BeginRequest(jsdc->dumbContext);
+
+ call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
+ if(!call) {
+ JS_EndRequest(jsdc->dumbContext);
+
+ return NULL;
+ }
+
ok = JS_AddNamedValueRoot(jsdc->dumbContext, &jsdval->val, "JSDValue");
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(jsdc->dumbContext);
if(!ok)
{
free(jsdval);
return NULL;
}
}
jsdval->val = val;
@@ -274,24 +312,34 @@ jsd_NewValue(JSDContext* jsdc, jsval val
JS_INIT_CLIST(&jsdval->props);
return jsdval;
}
void
jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval)
{
+ JSCrossCompartmentCall *call = NULL;
+
JS_ASSERT(jsdval->nref > 0);
if(0 == --jsdval->nref)
{
jsd_RefreshValue(jsdc, jsdval);
if(JSVAL_IS_GCTHING(jsdval->val))
{
JS_BeginRequest(jsdc->dumbContext);
+ call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
+ if(!call) {
+ JS_EndRequest(jsdc->dumbContext);
+
+ return;
+ }
+
JS_RemoveValueRoot(jsdc->dumbContext, &jsdval->val);
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(jsdc->dumbContext);
}
free(jsdval);
}
}
jsval
jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
@@ -357,62 +405,81 @@ static void _freeProps(JSDContext* jsdc,
CLEAR_BIT_FLAG(jsdval->flags, GOT_PROPS);
}
static JSBool _buildProps(JSDContext* jsdc, JSDValue* jsdval)
{
JSContext* cx = jsdc->dumbContext;
JSPropertyDescArray pda;
uintN i;
+ JSCrossCompartmentCall *call = NULL;
JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
JS_ASSERT(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)));
JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
if(!JSVAL_IS_OBJECT(jsdval->val) || JSVAL_IS_NULL(jsdval->val))
return JS_FALSE;
JS_BeginRequest(cx);
+ call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
+ if(!call) {
+ JS_EndRequest(jsdc->dumbContext);
+
+ return JS_FALSE;
+ }
+
if(!JS_GetPropertyDescArray(cx, JSVAL_TO_OBJECT(jsdval->val), &pda))
{
JS_EndRequest(cx);
+ JS_LeaveCrossCompartmentCall(call);
return JS_FALSE;
}
for(i = 0; i < pda.length; i++)
{
JSDProperty* prop = _newProperty(jsdc, &pda.array[i], 0);
if(!prop)
{
_freeProps(jsdc, jsdval);
break;
}
JS_APPEND_LINK(&prop->links, &jsdval->props);
}
JS_PutPropertyDescArray(cx, &pda);
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(cx);
SET_BIT_FLAG(jsdval->flags, GOT_PROPS);
return !JS_CLIST_IS_EMPTY(&jsdval->props);
}
#undef DROP_CLEAR_VALUE
#define DROP_CLEAR_VALUE(jsdc, x) if(x){jsd_DropValue(jsdc,x); x = NULL;}
void
jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval)
{
JSContext* cx = jsdc->dumbContext;
+ JSCrossCompartmentCall *call = NULL;
if(jsdval->string)
{
/* if the jsval is a string, then we didn't need to root the string */
if(!JSVAL_IS_STRING(jsdval->val))
{
JS_BeginRequest(cx);
+ call = JS_EnterCrossCompartmentCall(cx, jsdc->glob);
+ if(!call) {
+ JS_EndRequest(cx);
+
+ return;
+ }
+
JS_RemoveStringRoot(cx, &jsdval->string);
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(cx);
}
jsdval->string = NULL;
}
jsdval->funName = NULL;
jsdval->className = NULL;
DROP_CLEAR_VALUE(jsdc, jsdval->proto);
@@ -474,16 +541,17 @@ jsd_GetValueProperty(JSDContext* jsdc, J
JSObject* obj;
uintN attrs = 0;
JSBool found;
JSPropertyDesc pd;
const jschar * nameChars;
size_t nameLen;
jsval val, nameval;
jsid nameid;
+ JSCrossCompartmentCall *call = NULL;
if(!jsd_IsValueObject(jsdc, jsdval))
return NULL;
/* If we already have the prop, then return it */
while(NULL != (jsdprop = jsd_IterateProperties(jsdc, jsdval, &iter)))
{
JSString* propName = jsd_GetValueString(jsdc, jsdprop->name);
@@ -495,48 +563,57 @@ jsd_GetValueProperty(JSDContext* jsdc, J
if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
return NULL;
nameChars = JS_GetStringChars(name);
nameLen = JS_GetStringLength(name);
JS_BeginRequest(cx);
+ call = JS_EnterCrossCompartmentCall(cx, jsdc->glob);
+ if(!call) {
+ JS_EndRequest(cx);
+
+ return NULL;
+ }
JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found);
if (!found)
{
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(cx);
return NULL;
}
JS_ClearPendingException(cx);
if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, &val))
{
if (JS_IsExceptionPending(cx))
{
if (!JS_GetPendingException(cx, &pd.value))
{
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(cx);
return NULL;
}
pd.flags = JSPD_EXCEPTION;
}
else
{
pd.flags = JSPD_ERROR;
pd.value = JSVAL_VOID;
}
}
else
{
pd.value = val;
}
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(cx);
nameval = STRING_TO_JSVAL(name);
if (!JS_ValueToId(cx, nameval, &nameid) ||
!JS_IdToValue(cx, nameid, &pd.id)) {
return NULL;
}
@@ -548,131 +625,176 @@ jsd_GetValueProperty(JSDContext* jsdc, J
return _newProperty(jsdc, &pd, JSDPD_HINTED);
}
JSDValue*
jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
{
+ JSCrossCompartmentCall *call = NULL;
+
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
{
JSObject* obj;
JSObject* proto;
JS_ASSERT(!jsdval->proto);
SET_BIT_FLAG(jsdval->flags, GOT_PROTO);
if(!JSVAL_IS_OBJECT(jsdval->val))
return NULL;
if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
return NULL;
JS_BeginRequest(jsdc->dumbContext);
+ call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
+ if(!call) {
+ JS_EndRequest(jsdc->dumbContext);
+
+ return NULL;
+ }
proto = JS_GetPrototype(jsdc->dumbContext, obj);
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(jsdc->dumbContext);
if(!proto)
return NULL;
jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto));
}
if(jsdval->proto)
jsdval->proto->nref++;
return jsdval->proto;
}
JSDValue*
jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval)
{
+ JSCrossCompartmentCall *call = NULL;
+
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT)))
{
JSObject* obj;
JSObject* parent;
JS_ASSERT(!jsdval->parent);
SET_BIT_FLAG(jsdval->flags, GOT_PARENT);
if(!JSVAL_IS_OBJECT(jsdval->val))
return NULL;
if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
return NULL;
JS_BeginRequest(jsdc->dumbContext);
+ call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
+ if(!call) {
+ JS_EndRequest(jsdc->dumbContext);
+
+ return NULL;
+ }
parent = JS_GetParent(jsdc->dumbContext,obj);
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(jsdc->dumbContext);
if(!parent)
return NULL;
jsdval->parent = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(parent));
}
if(jsdval->parent)
jsdval->parent->nref++;
return jsdval->parent;
}
JSDValue*
jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
{
+ JSCrossCompartmentCall *call = NULL;
+
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
{
JSObject* obj;
JSObject* proto;
JSObject* ctor;
JS_ASSERT(!jsdval->ctor);
SET_BIT_FLAG(jsdval->flags, GOT_CTOR);
if(!JSVAL_IS_OBJECT(jsdval->val))
return NULL;
if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
return NULL;
JS_BeginRequest(jsdc->dumbContext);
+ call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
+ if(!call) {
+ JS_EndRequest(jsdc->dumbContext);
+
+ return NULL;
+ }
proto = JS_GetPrototype(jsdc->dumbContext,obj);
if(!proto)
{
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(jsdc->dumbContext);
return NULL;
}
ctor = JS_GetConstructor(jsdc->dumbContext,proto);
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(jsdc->dumbContext);
if(!ctor)
return NULL;
jsdval->ctor = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(ctor));
}
if(jsdval->ctor)
jsdval->ctor->nref++;
return jsdval->ctor;
}
const char*
jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval)
{
jsval val = jsdval->val;
+ JSCrossCompartmentCall *call = NULL;
+
if(!jsdval->className && JSVAL_IS_OBJECT(val))
{
JSObject* obj;
if(!(obj = JSVAL_TO_OBJECT(val)))
return NULL;
JS_BeginRequest(jsdc->dumbContext);
+ call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
+ if(!call) {
+ JS_EndRequest(jsdc->dumbContext);
+
+ return NULL;
+ }
if(JS_GET_CLASS(jsdc->dumbContext, obj))
jsdval->className = JS_GET_CLASS(jsdc->dumbContext, obj)->name;
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(jsdc->dumbContext);
}
return jsdval->className;
}
JSDScript*
jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval)
{
JSContext* cx = jsdc->dumbContext;
jsval val = jsdval->val;
- JSFunction* fun;
+ JSFunction* fun = NULL;
JSExceptionState* exceptionState;
JSScript* script = NULL;
JSDScript* jsdscript;
+ JSCrossCompartmentCall *call = NULL;
if (!jsd_IsValueFunction(jsdc, jsdval))
return NULL;
JS_BeginRequest(cx);
+ call = JS_EnterCrossCompartmentCall(cx, JSVAL_TO_OBJECT(val));
+ if (!call) {
+ JS_EndRequest(cx);
+
+ return NULL;
+ }
exceptionState = JS_SaveExceptionState(cx);
fun = JS_ValueToFunction(cx, val);
JS_RestoreExceptionState(cx, exceptionState);
if (fun)
script = JS_GetFunctionScript(cx, fun);
+ JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(cx);
if (!script)
return NULL;
JSD_LOCK_SCRIPTS(jsdc);
jsdscript = jsd_FindJSDScript(jsdc, script);
JSD_UNLOCK_SCRIPTS(jsdc);