Fixing bug 599761. Use the right compartment in jsd. r=gal.
authorJohnny Stenback <jst@mozilla.com>
Tue, 28 Sep 2010 19:29:29 -0700
changeset 54754 571523d28b41168b177295988aa6b040d0ec6d38
parent 54753 d3d26658bf500cc318931210da007baa54390ff9
child 54755 eba54c4edd6fe8109a287cb8bb1e75f6c1d6e492
push idunknown
push userunknown
push dateunknown
reviewersgal
bugs599761
milestone2.0b7pre
Fixing bug 599761. Use the right compartment in jsd. r=gal.
js/jsd/jsd_val.c
--- 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);