Bug 565157 - typed JS_AddRoot (r=igor)
authorLuke Wagner <lw@mozilla.com>
Mon, 07 Jun 2010 17:05:02 -0700
changeset 47403 2fc2a12a4565096b07fec7981b3b254666e1d26a
parent 47402 5f425aecd7ab83b3db95fb6ba5350801cd14c16a
child 47404 6ac9c370d16c079c3b84b8a956d7ec18fec38124
child 47406 ee8c6703170cc1a14d84de86b33b0b5887ab025b
push idunknown
push userunknown
push dateunknown
reviewersigor
bugs565157
milestone1.9.3a5pre
Bug 565157 - typed JS_AddRoot (r=igor)
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
content/canvas/src/NativeJSContext.cpp
content/canvas/src/NativeJSContext.h
js/jsd/jsd_val.c
js/src/jsapi-tests/tests.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsgc.cpp
js/src/jsgc.h
js/src/json.cpp
js/src/shell/js.cpp
js/src/xpconnect/loader/mozJSComponentLoader.cpp
js/src/xpconnect/loader/mozJSComponentLoader.h
js/src/xpconnect/public/nsAutoJSValHolder.h
modules/plugin/base/src/nsJSNPRuntime.cpp
security/manager/ssl/src/nsCrypto.cpp
xpinstall/src/nsXPITriggerInfo.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1743,56 +1743,49 @@ private:
 #endif
 };
 
 class NS_STACK_CLASS nsAutoGCRoot {
 public:
   // aPtr should be the pointer to the jsval we want to protect
   nsAutoGCRoot(jsval* aPtr, nsresult* aResult
                MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM) :
-    mPtr(aPtr)
+    mPtr(aPtr), mRootType(RootType_JSVal)
   {
     MOZILLA_GUARD_OBJECT_NOTIFIER_INIT;
-    mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot");
+    mResult = *aResult = AddJSGCRoot(aPtr, RootType_JSVal, "nsAutoGCRoot");
   }
 
   // aPtr should be the pointer to the JSObject* we want to protect
   nsAutoGCRoot(JSObject** aPtr, nsresult* aResult
                MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM) :
-    mPtr(aPtr)
+    mPtr(aPtr), mRootType(RootType_Object)
   {
     MOZILLA_GUARD_OBJECT_NOTIFIER_INIT;
-    mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot");
-  }
-
-  // aPtr should be the pointer to the thing we want to protect
-  nsAutoGCRoot(void* aPtr, nsresult* aResult
-               MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM) :
-    mPtr(aPtr)
-  {
-    MOZILLA_GUARD_OBJECT_NOTIFIER_INIT;
-    mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot");
+    mResult = *aResult = AddJSGCRoot(aPtr, RootType_Object, "nsAutoGCRoot");
   }
 
   ~nsAutoGCRoot() {
     if (NS_SUCCEEDED(mResult)) {
-      RemoveJSGCRoot(mPtr);
+      RemoveJSGCRoot(mPtr, mRootType);
     }
   }
 
   static void Shutdown();
 
 private:
-  static nsresult AddJSGCRoot(void *aPtr, const char* aName);
-  static nsresult RemoveJSGCRoot(void *aPtr);
+  enum RootType { RootType_JSVal, RootType_Object };
+  static nsresult AddJSGCRoot(void *aPtr, RootType aRootType, const char* aName);
+  static nsresult RemoveJSGCRoot(void *aPtr, RootType aRootType);
 
   static nsIJSRuntimeService* sJSRuntimeService;
   static JSRuntime* sJSScriptRuntime;
 
   void* mPtr;
+  RootType mRootType;
   nsresult mResult;
   MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 class NS_STACK_CLASS nsAutoScriptBlocker {
 public:
   nsAutoScriptBlocker(MOZILLA_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
     MOZILLA_GUARD_OBJECT_NOTIFIER_INIT;
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -3077,51 +3077,57 @@ nsContentUtils::GetContentPolicy()
     sTriedToGetContentPolicy = PR_TRUE;
   }
 
   return sContentPolicyService;
 }
 
 // static
 nsresult
-nsAutoGCRoot::AddJSGCRoot(void* aPtr, const char* aName)
+nsAutoGCRoot::AddJSGCRoot(void* aPtr, RootType aRootType, const char* aName)
 {
   if (!sJSScriptRuntime) {
     nsresult rv = CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
                                  &sJSRuntimeService);
     NS_ENSURE_TRUE(sJSRuntimeService, rv);
 
     sJSRuntimeService->GetRuntime(&sJSScriptRuntime);
     if (!sJSScriptRuntime) {
       NS_RELEASE(sJSRuntimeService);
       NS_WARNING("Unable to get JS runtime from JS runtime service");
       return NS_ERROR_FAILURE;
     }
   }
 
   PRBool ok;
-  ok = ::JS_AddNamedRootRT(sJSScriptRuntime, aPtr, aName);
+  if (aRootType == RootType_JSVal)
+    ok = ::js_AddRootRT(sJSScriptRuntime, (jsval *)aPtr, aName);
+  else
+    ok = ::js_AddGCThingRootRT(sJSScriptRuntime, (void **)aPtr, aName);
   if (!ok) {
     NS_WARNING("JS_AddNamedRootRT failed");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   return NS_OK;
 }
 
 /* static */
 nsresult
-nsAutoGCRoot::RemoveJSGCRoot(void* aPtr)
+nsAutoGCRoot::RemoveJSGCRoot(void* aPtr, RootType aRootType)
 {
   if (!sJSScriptRuntime) {
     NS_NOTREACHED("Trying to remove a JS GC root when none were added");
     return NS_ERROR_UNEXPECTED;
   }
 
-  ::JS_RemoveRootRT(sJSScriptRuntime, aPtr);
+  if (aRootType == RootType_JSVal)
+    ::js_RemoveRoot(sJSScriptRuntime, (jsval *)aPtr);
+  else
+    ::js_RemoveRoot(sJSScriptRuntime, (JSObject **)aPtr);
 
   return NS_OK;
 }
 
 // static
 PRBool
 nsContentUtils::IsEventAttributeName(nsIAtom* aName, PRInt32 aType)
 {
--- a/content/canvas/src/NativeJSContext.cpp
+++ b/content/canvas/src/NativeJSContext.cpp
@@ -1,40 +1,20 @@
 #include "NativeJSContext.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIJSRuntimeService.h"
 
-nsIJSRuntimeService* NativeJSContext::sJSRuntimeService = 0;
-JSRuntime* NativeJSContext::sJSScriptRuntime = 0;
-
 PRBool
-NativeJSContext::AddGCRoot(void *aPtr, const char *aName)
+NativeJSContext::AddGCRoot(JSObject **aPtr, const char *aName)
 {
   NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
-  if (!sJSScriptRuntime) {
-    nsresult rv = CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
-                                 &sJSRuntimeService);
-    NS_ENSURE_SUCCESS(rv, PR_FALSE);
-    NS_ABORT_IF_FALSE(sJSRuntimeService, "CallGetService succeeded but returned a null pointer?");
-
-    sJSRuntimeService->GetRuntime(&sJSScriptRuntime);
-    if (!sJSScriptRuntime) {
-      NS_RELEASE(sJSRuntimeService);
-      NS_WARNING("Unable to get JS runtime from JS runtime service");
-      return PR_FALSE;
-    }
-  }
 
   PRBool ok;
-  return ok = ::JS_AddNamedRootRT(sJSScriptRuntime, aPtr, aName);
+  return ok = ::JS_AddNamedObjectRoot(ctx, aPtr, aName);
 }
 
 void
-NativeJSContext::ReleaseGCRoot(void *aPtr)
+NativeJSContext::ReleaseGCRoot(JSObject **aPtr)
 {
   NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
-  if (!sJSScriptRuntime) {
-    NS_NOTREACHED("Trying to remove a JS GC root when none were added");
-    return;
-  }
 
-  ::JS_RemoveRootRT(sJSScriptRuntime, aPtr);
+  ::JS_RemoveObjectRoot(ctx, aPtr);
 }
--- a/content/canvas/src/NativeJSContext.h
+++ b/content/canvas/src/NativeJSContext.h
@@ -57,18 +57,18 @@ public:
         if (!JSVAL_IS_NULL(val) &&
             JSVAL_IS_OBJECT(val) &&
             ::JS_IsArrayObject(ctx, JSVAL_TO_OBJECT(val)) &&
             ::JS_GetArrayLength(ctx, JSVAL_TO_OBJECT(val), sz))
             return PR_TRUE;
         return PR_FALSE;
     }
 
-    PRBool AddGCRoot (void *aPtr, const char *aName);
-    void ReleaseGCRoot (void *aPtr);
+    PRBool AddGCRoot (JSObject **aPtr, const char *aName);
+    void ReleaseGCRoot (JSObject **aPtr);
 
     void SetRetVal (PRInt32 val) {
         NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
         if (INT_FITS_IN_JSVAL(val))
             SetRetValAsJSVal(INT_TO_JSVAL(val));
         else
             SetRetVal((double) val);
     }
@@ -181,19 +181,16 @@ public:
     void SetRetVal (JSObjectHelper& objh);
 
     nsAXPCNativeCallContext *ncc;
     nsresult error;
     JSContext *ctx;
     PRUint32 argc;
     jsval *argv;
 
-    static nsIJSRuntimeService* sJSRuntimeService;
-    static JSRuntime* sJSScriptRuntime;
-
 public:
     // static JS helpers
 
     static inline PRBool JSValToFloatArray (JSContext *ctx, jsval val,
                                             jsuint cnt, float *array)
     {
         JSObject *arrayObj;
         jsuint arrayLen;
--- a/js/jsd/jsd_val.c
+++ b/js/jsd/jsd_val.c
@@ -226,17 +226,17 @@ jsd_GetValueString(JSDContext* jsdc, JSD
         else
         {
             JS_BeginRequest(cx);
             exceptionState = JS_SaveExceptionState(cx);
             jsdval->string = JS_ValueToString(cx, jsdval->val);
             JS_RestoreExceptionState(cx, exceptionState);
             if(jsdval->string)
             {
-                if(!JS_AddNamedRoot(cx, &jsdval->string, "ValueString"))
+                if(!JS_AddNamedStringRoot(cx, &jsdval->string, "ValueString"))
                     jsdval->string = NULL;
             }
             JS_EndRequest(cx);
         }
     }
     return jsdval->string;
 }
 
@@ -270,17 +270,17 @@ jsd_NewValue(JSDContext* jsdc, jsval val
 
     if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue))))
         return NULL;
 
     if(JSVAL_IS_GCTHING(val))
     {
         JSBool ok = JS_FALSE;
         JS_BeginRequest(jsdc->dumbContext);
-        ok = JS_AddNamedRoot(jsdc->dumbContext, &jsdval->val, "JSDValue");
+        ok = JS_AddNamedValueRoot(jsdc->dumbContext, &jsdval->val, "JSDValue");
         JS_EndRequest(jsdc->dumbContext);
         if(!ok)
         {
             free(jsdval);
             return NULL;
         }
     }
     jsdval->val  = val;
@@ -295,17 +295,17 @@ jsd_DropValue(JSDContext* jsdc, JSDValue
 {
     JS_ASSERT(jsdval->nref > 0);
     if(0 == --jsdval->nref)
     {
         jsd_RefreshValue(jsdc, jsdval);
         if(JSVAL_IS_GCTHING(jsdval->val))
         {
             JS_BeginRequest(jsdc->dumbContext);
-            JS_RemoveRoot(jsdc->dumbContext, &jsdval->val);
+            JS_RemoveValueRoot(jsdc->dumbContext, &jsdval->val);
             JS_EndRequest(jsdc->dumbContext);
         }
         free(jsdval);
     }
 }
 
 jsval
 jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
@@ -417,17 +417,17 @@ jsd_RefreshValue(JSDContext* jsdc, JSDVa
     JSContext* cx = jsdc->dumbContext;
 
     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);
-            JS_RemoveRoot(cx, &jsdval->string);
+            JS_RemoveStringRoot(cx, &jsdval->string);
             JS_EndRequest(cx);
         }
         jsdval->string = NULL;
     }
 
     jsdval->funName = NULL;
     jsdval->className = NULL;
     DROP_CLEAR_VALUE(jsdc, jsdval->proto);
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -47,23 +47,23 @@
 #include <string>
 
 class jsvalRoot
 {
 public:
     explicit jsvalRoot(JSContext *context, jsval value = JSVAL_NULL)
         : cx(context), v(value)
     {
-        if (!JS_AddRoot(cx, &v)) {
+        if (!JS_AddValueRoot(cx, &v)) {
             fprintf(stderr, "Out of memory in jsvalRoot constructor, aborting\n");
             abort();
         }
     }
 
-    ~jsvalRoot() { JS_RemoveRoot(cx, &v); }
+    ~jsvalRoot() { JS_RemoveValueRoot(cx, &v); }
 
     operator jsval() const { return value(); }
 
     jsvalRoot & operator=(jsval value) {
         v = value;
         return *this;
     }
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1765,47 +1765,120 @@ JS_NewDoubleValue(JSContext *cx, jsdoubl
 JS_PUBLIC_API(JSBool)
 JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
 {
     CHECK_REQUEST(cx);
     return js_NewWeaklyRootedNumber(cx, d, rval);
 }
 
 #undef JS_AddRoot
+
 JS_PUBLIC_API(JSBool)
-JS_AddRoot(JSContext *cx, void *rp)
+JS_AddValueRoot(JSContext *cx, jsval *vp)
 {
     CHECK_REQUEST(cx);
-    return js_AddRoot(cx, rp, NULL);
+    return js_AddRoot(cx, vp, NULL);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AddStringRoot(JSContext *cx, JSString **rp)
+{
+    CHECK_REQUEST(cx);
+    return js_AddGCThingRoot(cx, (void **)rp, NULL);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AddObjectRoot(JSContext *cx, JSObject **rp)
+{
+    CHECK_REQUEST(cx);
+    return js_AddGCThingRoot(cx, (void **)rp, NULL);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name)
-{
-    return js_AddRootRT(rt, rp, name);
+JS_AddDoubleRoot(JSContext *cx, jsdouble **rp)
+{
+    CHECK_REQUEST(cx);
+    return js_AddGCThingRoot(cx, (void **)rp, NULL);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AddGCThingRoot(JSContext *cx, void **rp)
+{
+    CHECK_REQUEST(cx);
+    return js_AddGCThingRoot(cx, (void **)rp, NULL);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AddNamedValueRoot(JSContext *cx, jsval *vp, const char *name)
+{
+    CHECK_REQUEST(cx);
+    return js_AddRoot(cx, vp, name);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AddNamedStringRoot(JSContext *cx, JSString **rp, const char *name)
+{
+    CHECK_REQUEST(cx);
+    return js_AddGCThingRoot(cx, (void **)rp, name);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_RemoveRoot(JSContext *cx, void *rp)
+JS_AddNamedObjectRoot(JSContext *cx, JSObject **rp, const char *name)
 {
     CHECK_REQUEST(cx);
-    return js_RemoveRoot(cx->runtime, rp);
+    return js_AddGCThingRoot(cx, (void **)rp, name);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AddNamedDoubleRoot(JSContext *cx, jsdouble **rp, const char *name)
+{
+    CHECK_REQUEST(cx);
+    return js_AddGCThingRoot(cx, (void **)rp, name);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AddNamedGCThingRoot(JSContext *cx, void **rp, const char *name)
+{
+    CHECK_REQUEST(cx);
+    return js_AddGCThingRoot(cx, (void **)rp, name);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_RemoveRootRT(JSRuntime *rt, void *rp)
-{
-    return js_RemoveRoot(rt, rp);
+JS_RemoveValueRoot(JSContext *cx, jsval *vp)
+{
+    CHECK_REQUEST(cx);
+    return js_RemoveRoot(cx->runtime, (void *)vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_RemoveStringRoot(JSContext *cx, JSString **rp)
+{
+    CHECK_REQUEST(cx);
+    return js_RemoveRoot(cx->runtime, (void *)rp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_AddNamedRoot(JSContext *cx, void *rp, const char *name)
+JS_RemoveObjectRoot(JSContext *cx, JSObject **rp)
 {
     CHECK_REQUEST(cx);
-    return js_AddRoot(cx, rp, name);
+    return js_RemoveRoot(cx->runtime, (void *)rp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_RemoveDoubleRoot(JSContext *cx, jsdouble **rp)
+{
+    CHECK_REQUEST(cx);
+    return js_RemoveRoot(cx->runtime, (void *)rp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_RemoveGCThingRoot(JSContext *cx, void **rp)
+{
+    CHECK_REQUEST(cx);
+    return js_RemoveRoot(cx->runtime, (void *)rp);
 }
 
 JS_PUBLIC_API(void)
 JS_ClearNewbornRoots(JSContext *cx)
 {
     JS_CLEAR_WEAK_ROOTS(&cx->weakRoots);
 }
 
@@ -5319,17 +5392,17 @@ JS_RestoreExceptionState(JSContext *cx, 
 }
 
 JS_PUBLIC_API(void)
 JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
 {
     CHECK_REQUEST(cx);
     if (state) {
         if (state->throwing && JSVAL_IS_GCTHING(state->exception))
-            JS_RemoveRoot(cx, &state->exception);
+            JS_RemoveValueRoot(cx, &state->exception);
         cx->free(state);
     }
 }
 
 JS_PUBLIC_API(JSErrorReport *)
 JS_ErrorFromException(JSContext *cx, jsval v)
 {
     CHECK_REQUEST(cx);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -898,51 +898,111 @@ JS_NewDouble(JSContext *cx, jsdouble d);
 
 extern JS_PUBLIC_API(JSBool)
 JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval);
 
 extern JS_PUBLIC_API(JSBool)
 JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval);
 
 /*
- * A JS GC root is a pointer to a JSObject *, JSString *, or jsdouble * that
- * itself points into the GC heap (more recently, we support this extension:
- * a root may be a pointer to a jsval v for which JSVAL_IS_GCTHING(v) is true).
+ * A GC root is a pointer to a jsval, JSObject * or JSString * that itself
+ * points into the GC heap. JS_AddValueRoot takes a pointer to a jsval and
+ * JS_AddGCThingRoot takes a pointer to a JSObject * or JString *.
+ *
+ * Note that, since JS_Add*Root stores the address of a variable (of type
+ * jsval, JSString *, or JSObject *), that variable must live until
+ * JS_Remove*Root is called to remove that variable. For example, after:
  *
- * Therefore, you never pass JSObject *obj to JS_AddRoot(cx, obj).  You always
- * call JS_AddRoot(cx, &obj), passing obj by reference.  And later, before obj
- * or the structure it is embedded within goes out of scope or is freed, you
- * must call JS_RemoveRoot(cx, &obj).
+ *   void some_function() {
+ *     jsval v;
+ *     JS_AddNamedRootedValue(cx, &v, "name");
+ *
+ * the caller must perform
  *
- * Also, use JS_AddNamedRoot(cx, &structPtr->memberObj, "structPtr->memberObj")
- * in preference to JS_AddRoot(cx, &structPtr->memberObj), in order to identify
+ *     JS_RemoveRootedValue(cx, &v);
+ *
+ * before some_function() returns.
+ *
+ * Also, use JS_AddNamed*Root(cx, &structPtr->memberObj, "structPtr->memberObj")
+ * in preference to JS_Add*Root(cx, &structPtr->memberObj), in order to identify
  * roots by their source callsites.  This way, you can find the callsite while
- * debugging if you should fail to do JS_RemoveRoot(cx, &structPtr->memberObj)
+ * debugging if you should fail to do JS_Remove*Root(cx, &structPtr->memberObj)
  * before freeing structPtr's memory.
  */
 extern JS_PUBLIC_API(JSBool)
-JS_AddRoot(JSContext *cx, void *rp);
+JS_AddValueRoot(JSContext *cx, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AddStringRoot(JSContext *cx, JSString **rp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AddObjectRoot(JSContext *cx, JSObject **rp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AddDoubleRoot(JSContext *cx, jsdouble **rp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AddGCThingRoot(JSContext *cx, void **rp);
 
 #ifdef NAME_ALL_GC_ROOTS
 #define JS_DEFINE_TO_TOKEN(def) #def
 #define JS_DEFINE_TO_STRING(def) JS_DEFINE_TO_TOKEN(def)
-#define JS_AddRoot(cx,rp) JS_AddNamedRoot((cx), (rp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__))
+#define JS_AddValueRoot(cx,vp) JS_AddNamedValueRoot((cx), (vp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__))
+#define JS_AddStringRoot(cx,rp) JS_AddNamedStringRoot((cx), (rp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__))
+#define JS_AddObjectRoot(cx,rp) JS_AddNamedObjectRoot((cx), (rp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__))
+#define JS_AddDoubleRoot(cx,rp) JS_AddNamedDoubleRoot((cx), (rp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__))
+#define JS_AddGCThingRoot(cx,rp) JS_AddNamedGCThingRoot((cx), (rp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__))
 #endif
 
 extern JS_PUBLIC_API(JSBool)
-JS_AddNamedRoot(JSContext *cx, void *rp, const char *name);
+JS_AddNamedValueRoot(JSContext *cx, jsval *vp, const char *name);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AddNamedStringRoot(JSContext *cx, JSString **rp, const char *name);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AddNamedObjectRoot(JSContext *cx, JSObject **rp, const char *name);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AddNamedDoubleRoot(JSContext *cx, jsdouble **rp, const char *name);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AddNamedGCThingRoot(JSContext *cx, void **rp, const char *name);
+
+extern JS_PUBLIC_API(JSBool)
+JS_RemoveValueRoot(JSContext *cx, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_RemoveStringRoot(JSContext *cx, JSString **rp);
 
 extern JS_PUBLIC_API(JSBool)
-JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name);
+JS_RemoveObjectRoot(JSContext *cx, JSObject **rp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_RemoveDoubleRoot(JSContext *cx, jsdouble **rp);
 
 extern JS_PUBLIC_API(JSBool)
-JS_RemoveRoot(JSContext *cx, void *rp);
-
-extern JS_PUBLIC_API(JSBool)
-JS_RemoveRootRT(JSRuntime *rt, void *rp);
+JS_RemoveGCThingRoot(JSContext *cx, void **rp);
+
+/* TODO: remove these APIs */
+
+extern JS_FRIEND_API(JSBool)
+js_AddRootRT(JSRuntime *rt, jsval *vp, const char *name);
+
+extern JS_FRIEND_API(JSBool)
+js_AddGCThingRootRT(JSRuntime *rt, void **rp, const char *name);
+
+extern JS_FRIEND_API(JSBool)
+js_RemoveRoot(JSRuntime *rt, void *rp);
+
+/*
+ * This symbol may be used by embedders to detect the change from the old
+ * JS_AddRoot(JSContext *, void *) APIs to the new ones above.
+ */
+#define JS_TYPED_ROOTING_API
 
 /*
  * The last GC thing of each type (object, string, double, external string
  * types) created on a given context is kept alive until another thing of the
  * same type is created, using a newborn root in the context.  These newborn
  * roots help native code protect newly-created GC-things from GC invocations
  * activated before those things can be rooted using local or global roots.
  *
@@ -960,17 +1020,17 @@ JS_RemoveRootRT(JSRuntime *rt, void *rp)
  */
 extern JS_PUBLIC_API(void)
 JS_ClearNewbornRoots(JSContext *cx);
 
 /*
  * Scoped local root management allows native functions, getter/setters, etc.
  * to avoid worrying about the newborn root pigeon-holes, overloading local
  * roots allocated in argv and *rval, or ending up having to call JS_Add*Root
- * and JS_RemoveRoot to manage global roots temporarily.
+ * and JS_Remove*Root to manage global roots temporarily.
  *
  * Instead, calling JS_EnterLocalRootScope and JS_LeaveLocalRootScope around
  * the body of the native hook causes the engine to allocate a local root for
  * each newborn created in between the two API calls, using a local root stack
  * associated with cx.  For example:
  *
  *    JSBool
  *    my_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
@@ -2222,23 +2282,23 @@ JS_CompileFileHandleForPrincipals(JSCont
 /*
  * NB: you must use JS_NewScriptObject and root a pointer to its return value
  * in order to keep a JSScript and its atoms safe from garbage collection after
  * creating the script via JS_Compile* and before a JS_ExecuteScript* call.
  * E.g., and without error checks:
  *
  *    JSScript *script = JS_CompileFile(cx, global, filename);
  *    JSObject *scrobj = JS_NewScriptObject(cx, script);
- *    JS_AddNamedRoot(cx, &scrobj, "scrobj");
+ *    JS_AddNamedObjectRoot(cx, &scrobj, "scrobj");
  *    do {
  *        jsval result;
  *        JS_ExecuteScript(cx, global, script, &result);
  *        JS_GC();
  *    } while (!JSVAL_IS_BOOLEAN(result) || JSVAL_TO_BOOLEAN(result));
- *    JS_RemoveRoot(cx, &scrobj);
+ *    JS_RemoveObjectRoot(cx, &scrobj);
  */
 extern JS_PUBLIC_API(JSObject *)
 JS_NewScriptObject(JSContext *cx, JSScript *script);
 
 /*
  * Infallible getter for a script's object.  If JS_NewScriptObject has not been
  * called on script yet, the return value will be null.
  */
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -1124,46 +1124,67 @@ js_FinishGC(JSRuntime *rt)
     if (!rt->gcRootsHash.empty())
         CheckLeakedRoots(rt);
 #endif
     rt->gcRootsHash.clear();
     rt->gcLocksHash.clear();
 }
 
 JSBool
-js_AddRoot(JSContext *cx, void *rp, const char *name)
+js_AddRoot(JSContext *cx, jsval *vp, const char *name)
 {
-    JSBool ok = js_AddRootRT(cx->runtime, rp, name);
+    JSBool ok = js_AddRootRT(cx->runtime, vp, name);
     if (!ok)
         JS_ReportOutOfMemory(cx);
     return ok;
 }
 
 JSBool
-js_AddRootRT(JSRuntime *rt, void *rp, const char *name)
+js_AddGCThingRoot(JSContext *cx, void **rp, const char *name)
+{
+    JSBool ok = js_AddGCThingRootRT(cx->runtime, rp, name);
+    if (!ok)
+        JS_ReportOutOfMemory(cx);
+    return ok;
+}
+
+static JSBool
+AddRoot(JSRuntime *rt, void *rp, const char *name)
 {
     js::GCRoots *roots = &rt->gcRootsHash;
 
     /*
      * Due to the long-standing, but now removed, use of rt->gcLock across the
      * bulk of js_GC, API users have come to depend on JS_AddRoot etc. locking
      * properly with a racing GC, without calling JS_AddRoot from a request.
      * We have to preserve API compatibility here, now that we avoid holding
      * rt->gcLock across the mark phase (including the root hashtable mark).
      */
     AutoLockGC lock(rt);
     js_WaitForGC(rt);
     return !!roots->put(rp, name);
 }
 
-JSBool
+JS_FRIEND_API(JSBool)
+js_AddRootRT(JSRuntime *rt, jsval *vp, const char *name)
+{
+    return AddRoot(rt, vp, name);
+}
+
+JS_FRIEND_API(JSBool)
+js_AddGCThingRootRT(JSRuntime *rt, void **rp, const char *name)
+{
+    return AddRoot(rt, rp, name);
+}
+
+JS_FRIEND_API(JSBool)
 js_RemoveRoot(JSRuntime *rt, void *rp)
 {
     /*
-     * Due to the JS_RemoveRootRT API, we may be called outside of a request.
+     * Due to the JS_RemoveRoot API, we may be called outside of a request.
      * Same synchronization drill as above in js_AddRoot.
      */
     AutoLockGC lock(rt);
     js_WaitForGC(rt);
     rt->gcRootsHash.remove(rp);
     rt->gcPoke = JS_TRUE;
     return JS_TRUE;
 }
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -94,23 +94,20 @@ js_InitGC(JSRuntime *rt, uint32 maxbytes
 extern void
 js_FinishGC(JSRuntime *rt);
 
 extern intN
 js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
                                  JSStringFinalizeOp newop);
 
 extern JSBool
-js_AddRoot(JSContext *cx, void *rp, const char *name);
+js_AddRoot(JSContext *cx, jsval *vp, const char *name);
 
 extern JSBool
-js_AddRootRT(JSRuntime *rt, void *rp, const char *name);
-
-extern JSBool
-js_RemoveRoot(JSRuntime *rt, void *rp);
+js_AddGCThingRoot(JSContext *cx, void **rp, const char *name);
 
 #ifdef DEBUG
 extern void
 js_DumpNamedRoots(JSRuntime *rt,
                   void (*dump)(const char *name, void *rp, void *data),
                   void *data);
 #endif
 
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -633,17 +633,17 @@ js_BeginJSONParse(JSContext *cx, jsval *
     if (!arr)
         return NULL;
 
     JSONParser *jp = cx->create<JSONParser>(cx);
     if (!jp)
         return NULL;
 
     jp->objectStack = arr;
-    if (!js_AddRoot(cx, &jp->objectStack, "JSON parse stack"))
+    if (!JS_AddNamedObjectRoot(cx, &jp->objectStack, "JSON parse stack"))
         goto bad;
 
     jp->statep = jp->stateStack;
     *jp->statep = JSON_PARSE_STATE_INIT;
     jp->rootVal = rootVal;
 
     return jp;
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -222,20 +222,20 @@ public:
     : cx(aCx)
     , mThrow(aThrow)
     {
         mStr = JS_ValueToString(cx, v);
         if (!aThrow && !mStr && JS_IsExceptionPending(cx)) {
             if (!JS_ReportPendingException(cx))
                 JS_ClearPendingException(cx);
         }
-        JS_AddNamedRoot(cx, &mStr, "Value ToString helper");
+        JS_AddNamedStringRoot(cx, &mStr, "Value ToString helper");
     }
     ~ToString() {
-        JS_RemoveRoot(cx, &mStr);
+        JS_RemoveStringRoot(cx, &mStr);
     }
     JSBool threw() { return !mStr; }
     jsval getJSVal() { return STRING_TO_JSVAL(mStr); }
     const char *getBytes() {
         return mStr ? JS_GetStringBytes(mStr) : "(error converting value)";
     }
 private:
     JSContext *cx;
@@ -3258,44 +3258,44 @@ Scatter(JSContext *cx, uintN argc, jsval
     if (!sd.cvar)
         goto fail;
 
     sd.results = (jsval *) malloc(n * sizeof(jsval));
     if (!sd.results)
         goto fail;
     for (i = 0; i < n; i++) {
         sd.results[i] = JSVAL_VOID;
-        ok = JS_AddRoot(cx, &sd.results[i]);
+        ok = JS_AddValueRoot(cx, &sd.results[i]);
         if (!ok) {
             while (i-- > 0)
-                JS_RemoveRoot(cx, &sd.results[i]);
+                JS_RemoveValueRoot(cx, &sd.results[i]);
             free(sd.results);
             sd.results = NULL;
             goto fail;
         }
     }
 
     sd.threads = (ScatterThreadData *) malloc(n * sizeof(ScatterThreadData));
     if (!sd.threads)
         goto fail;
     for (i = 0; i < n; i++) {
         sd.threads[i].index = i;
         sd.threads[i].shared = &sd;
         sd.threads[i].thr = NULL;
         sd.threads[i].cx = NULL;
         sd.threads[i].fn = JSVAL_NULL;
 
-        ok = JS_AddRoot(cx, &sd.threads[i].fn);
+        ok = JS_AddValueRoot(cx, &sd.threads[i].fn);
         if (ok && !JS_GetElement(cx, inArr, (jsint) i, &sd.threads[i].fn)) {
-            JS_RemoveRoot(cx, &sd.threads[i].fn);
+            JS_RemoveValueRoot(cx, &sd.threads[i].fn);
             ok = JS_FALSE;
         }
         if (!ok) {
             while (i-- > 0)
-                JS_RemoveRoot(cx, &sd.threads[i].fn);
+                JS_RemoveValueRoot(cx, &sd.threads[i].fn);
             free(sd.threads);
             sd.threads = NULL;
             goto fail;
         }
     }
 
     global = JS_GetGlobalObject(cx);
     for (i = 1; i < n; i++) {
@@ -3353,28 +3353,28 @@ success:
     *vp = OBJECT_TO_JSVAL(arr);
     ok = JS_TRUE;
 
 out:
     if (sd.threads) {
         JSContext *acx;
 
         for (i = 0; i < n; i++) {
-            JS_RemoveRoot(cx, &sd.threads[i].fn);
+            JS_RemoveValueRoot(cx, &sd.threads[i].fn);
             acx = sd.threads[i].cx;
             if (acx) {
                 JS_SetContextThread(acx);
                 DestroyContext(acx, true);
             }
         }
         free(sd.threads);
     }
     if (sd.results) {
         for (i = 0; i < n; i++)
-            JS_RemoveRoot(cx, &sd.results[i]);
+            JS_RemoveValueRoot(cx, &sd.results[i]);
         free(sd.results);
     }
     if (sd.cvar)
         PR_DestroyCondVar(sd.cvar);
     if (sd.lock)
         PR_DestroyLock(sd.lock);
 
     return ok;
@@ -4194,23 +4194,23 @@ its_setter(JSContext *cx, JSObject *obj,
   }
 
   val = new jsval;
   if (!val) {
       JS_ReportOutOfMemory(cx);
       return JS_FALSE;
   }
 
-  if (!JS_AddRoot(cx, val)) {
+  if (!JS_AddValueRoot(cx, val)) {
       delete val;
       return JS_FALSE;
   }
 
   if (!JS_SetPrivate(cx, obj, (void*)val)) {
-      JS_RemoveRoot(cx, val);
+      JS_RemoveValueRoot(cx, val);
       delete val;
       return JS_FALSE;
   }
 
   *val = *vp;
   return JS_TRUE;
 }
 
@@ -4432,17 +4432,17 @@ its_convert(JSContext *cx, JSObject *obj
 static void
 its_finalize(JSContext *cx, JSObject *obj)
 {
     jsval *rootedVal;
     if (its_noisy)
         fprintf(gOutFile, "finalizing it\n");
     rootedVal = (jsval *) JS_GetPrivate(cx, obj);
     if (rootedVal) {
-      JS_RemoveRoot(cx, rootedVal);
+      JS_RemoveValueRoot(cx, rootedVal);
       JS_SetPrivate(cx, obj, NULL);
       delete rootedVal;
     }
 }
 
 static JSClass its_class = {
     "It", JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE | JSCLASS_HAS_PRIVATE,
     its_addProperty,  its_delProperty,  its_getProperty,  its_setProperty,
@@ -5011,27 +5011,27 @@ shell(JSContext *cx, int argc, char **ar
 #endif /* JSDEBUGGER */
 
 #ifdef JS_THREADSAFE
     class ShellWorkerHooks : public js::workers::WorkerHooks {
     public:
         JSObject *newGlobalObject(JSContext *cx) { return NewGlobalObject(cx); }
     };
     ShellWorkerHooks hooks;
-    if (!JS_AddNamedRoot(cx, &gWorkers, "Workers") ||
+    if (!JS_AddNamedObjectRoot(cx, &gWorkers, "Workers") ||
         !js::workers::init(cx, &hooks, glob, &gWorkers)) {
         return 1;
     }
 #endif
 
     int result = ProcessArgs(cx, glob, argv, argc);
 
 #ifdef JS_THREADSAFE
     js::workers::finish(cx, gWorkers);
-    JS_RemoveRoot(cx, &gWorkers);
+    JS_RemoveObjectRoot(cx, &gWorkers);
     if (result == 0)
         result = gExitCode;
 #endif
 
 #ifdef JSDEBUGGER
     if (jsdc) {
 #ifdef JSDEBUGGER_C_UI
         if (jsdbc)
--- a/js/src/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/src/xpconnect/loader/mozJSComponentLoader.cpp
@@ -1389,17 +1389,17 @@ mozJSComponentLoader::GlobalForLocation(
     nsCAutoString path;
     aComponent->GetNativePath(path);
     *aLocation = ToNewCString(path);
     if (!*aLocation) {
         *aGlobal = nsnull;
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    JS_AddNamedRoot(cx, aGlobal, *aLocation);
+    JS_AddNamedObjectRoot(cx, aGlobal, *aLocation);
     return NS_OK;
 }
 
 void
 mozJSComponentLoader::UnloadModules()
 {
     mInitialized = PR_FALSE;
 
--- a/js/src/xpconnect/loader/mozJSComponentLoader.h
+++ b/js/src/xpconnect/loader/mozJSComponentLoader.h
@@ -146,17 +146,17 @@ class mozJSComponentLoader : public nsIM
         }
 
         ~ModuleEntry() {
             module = nsnull;
 
             if (global) {
                 JSAutoRequest ar(sSelf->mContext);
                 JS_ClearScope(sSelf->mContext, global);
-                JS_RemoveRoot(sSelf->mContext, &global);
+                JS_RemoveObjectRoot(sSelf->mContext, &global);
             }
 
             if (location)
                 NS_Free(location);
         }
 
         nsCOMPtr<nsIModule>  module;
         JSObject            *global;
--- a/js/src/xpconnect/public/nsAutoJSValHolder.h
+++ b/js/src/xpconnect/public/nsAutoJSValHolder.h
@@ -77,17 +77,17 @@ public:
   }
 
   /**
    * Hold by rooting on the runtime.
    * Note that mGCThing may be JSVAL_NULL, which is not a problem.
    */
   JSBool Hold(JSRuntime* aRt) {
     if (!mHeld) {
-      if (JS_AddNamedRootRT(aRt, &mGCThing, "nsAutoJSValHolder")) {
+      if (js_AddGCThingRootRT(aRt, &mGCThing, "nsAutoJSValHolder")) {
         mRt = aRt;
         mHeld = JS_TRUE;
       } else {
         Release(); // out of memory
       }
     }
     return mHeld;
   }
@@ -97,17 +97,17 @@ public:
    * the original jsval.
    */
   jsval Release() {
     NS_ASSERTION(!mHeld || mRt, "Bad!");
 
     jsval oldval = mVal;
 
     if (mHeld) {
-      JS_RemoveRootRT(mRt, &mGCThing); // infallible
+      js_RemoveRoot(mRt, &mGCThing); // infallible
       mHeld = JS_FALSE;
     }
 
     mVal = JSVAL_NULL;
     mGCThing = NULL;
     mRt = NULL;
 
     return oldval;
--- a/modules/plugin/base/src/nsJSNPRuntime.cpp
+++ b/modules/plugin/base/src/nsJSNPRuntime.cpp
@@ -578,17 +578,17 @@ nsJSObjWrapper::NP_Deallocate(NPObject *
 // static
 void
 nsJSObjWrapper::NP_Invalidate(NPObject *npobj)
 {
   nsJSObjWrapper *jsnpobj = (nsJSObjWrapper *)npobj;
 
   if (jsnpobj && jsnpobj->mJSObj) {
     // Unroot the object's JSObject
-    ::JS_RemoveRootRT(sJSRuntime, &jsnpobj->mJSObj);
+    js_RemoveRoot(sJSRuntime, &jsnpobj->mJSObj);
 
     if (sJSObjWrappers.ops) {
       // Remove the wrapper from the hash
 
       nsJSObjWrapperKey key(jsnpobj->mJSObj, jsnpobj->mNpp);
       PL_DHashTableOperate(&sJSObjWrappers, &key, PL_DHASH_REMOVE);
     }
 
@@ -1152,17 +1152,17 @@ nsJSObjWrapper::GetNewOrUsed(NPP npp, JS
   entry->mJSObjWrapper = wrapper;
 
   NS_ASSERTION(wrapper->mNpp == npp, "nsJSObjWrapper::mNpp not initialized!");
 
   JSAutoRequest ar(cx);
 
   // Root the JSObject, its lifetime is now tied to that of the
   // NPObject.
-  if (!::JS_AddNamedRoot(cx, &wrapper->mJSObj, "nsJSObjWrapper::mJSObject")) {
+  if (!::JS_AddNamedObjectRoot(cx, &wrapper->mJSObj, "nsJSObjWrapper::mJSObject")) {
     NS_ERROR("Failed to root JSObject!");
 
     _releaseobject(wrapper);
 
     PL_DHashTableRawRemove(&sJSObjWrappers, entry);
 
     return nsnull;
   }
@@ -2132,17 +2132,17 @@ CreateNPObjectMember(NPP npp, JSContext 
 
   JSObject *memobj = ::JS_NewObject(cx, &sNPObjectMemberClass, nsnull, nsnull);
   if (!memobj) {
     PR_Free(memberPrivate);
     return JS_FALSE;
   }
 
   *vp = OBJECT_TO_JSVAL(memobj);
-  ::JS_AddRoot(cx, vp);
+  ::JS_AddValueRoot(cx, vp);
 
   ::JS_SetPrivate(cx, memobj, (void *)memberPrivate);
 
   jsval fieldValue;
   NPVariant npv;
   NPBool hasProperty;
 
   if (getPropertyResult) {
@@ -2151,22 +2151,22 @@ CreateNPObjectMember(NPP npp, JSContext 
     hasProperty = true;
   }
   else {
     VOID_TO_NPVARIANT(npv);
 
     NPBool hasProperty = npobj->_class->getProperty(npobj, (NPIdentifier)id,
                                                     &npv);
     if (!ReportExceptionIfPending(cx)) {
-      ::JS_RemoveRoot(cx, vp);
+      ::JS_RemoveValueRoot(cx, vp);
       return JS_FALSE;
     }
 
     if (!hasProperty) {
-      ::JS_RemoveRoot(cx, vp);
+      ::JS_RemoveValueRoot(cx, vp);
       return JS_FALSE;
     }
   }
 
   fieldValue = NPVariantToJSVal(npp, cx, &npv);
 
   // npobjWrapper is the JSObject through which we make sure we don't
   // outlive the underlying NPObject, so make sure it points to the
@@ -2176,17 +2176,17 @@ CreateNPObjectMember(NPP npp, JSContext 
   }
 
   memberPrivate->npobjWrapper = obj;
 
   memberPrivate->fieldValue = fieldValue;
   memberPrivate->methodName = id;
   memberPrivate->npp = npp;
 
-  ::JS_RemoveRoot(cx, vp);
+  ::JS_RemoveValueRoot(cx, vp);
 
   return JS_TRUE;
 }
 
 static JSBool
 NPObjectMember_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
 {
   NPObjectMemberPrivate *memberPrivate =
--- a/security/manager/ssl/src/nsCrypto.cpp
+++ b/security/manager/ssl/src/nsCrypto.cpp
@@ -2154,26 +2154,26 @@ nsCryptoRunArgs::~nsCryptoRunArgs() {}
 
 
 nsCryptoRunnable::nsCryptoRunnable(nsCryptoRunArgs *args)
 {
   nsNSSShutDownPreventionLock locker;
   NS_ASSERTION(args,"Passed nsnull to nsCryptoRunnable constructor.");
   m_args = args;
   NS_IF_ADDREF(m_args);
-  JS_AddNamedRoot(args->m_cx, &args->m_scope,"nsCryptoRunnable::mScope");
+  JS_AddNamedObjectRoot(args->m_cx, &args->m_scope,"nsCryptoRunnable::mScope");
 }
 
 nsCryptoRunnable::~nsCryptoRunnable()
 {
   nsNSSShutDownPreventionLock locker;
 
   {
     JSAutoRequest ar(m_args->m_cx);
-    JS_RemoveRoot(m_args->m_cx, &m_args->m_scope);
+    JS_RemoveObjectRoot(m_args->m_cx, &m_args->m_scope);
   }
 
   NS_IF_RELEASE(m_args);
 }
 
 //Implementation that runs the callback passed to 
 //crypto.generateCRMFRequest as an event.
 NS_IMETHODIMP
--- a/xpinstall/src/nsXPITriggerInfo.cpp
+++ b/xpinstall/src/nsXPITriggerInfo.cpp
@@ -190,17 +190,17 @@ nsXPITriggerInfo::~nsXPITriggerInfo()
         item = Get(i);
         if (item)
             delete item;
     }
     mItems.Clear();
 
     if ( mCx && !JSVAL_IS_NULL(mCbval) ) {
         JS_BeginRequest(mCx);
-        JS_RemoveRoot( mCx, &mCbval );
+        JS_RemoveValueRoot(mCx, &mCbval );
         JS_EndRequest(mCx);
     }
 
     MOZ_COUNT_DTOR(nsXPITriggerInfo);
 }
 
 void nsXPITriggerInfo::SaveCallback( JSContext *aCx, jsval aVal )
 {
@@ -214,25 +214,25 @@ void nsXPITriggerInfo::SaveCallback( JSC
         return;
 
     mCx = aCx;
     mCbval = aVal;
     mThread = do_GetCurrentThread();
 
     if ( !JSVAL_IS_NULL(mCbval) ) {
         JS_BeginRequest(mCx);
-        JS_AddRoot( mCx, &mCbval );
+        JS_AddValueRoot(mCx, &mCbval );
         JS_EndRequest(mCx);
     }
 }
 
 XPITriggerEvent::~XPITriggerEvent()
 {
     JS_BeginRequest(cx);
-    JS_RemoveRoot(cx, &cbval);
+    JS_RemoveValueRoot(cx, &cbval);
     JS_EndRequest(cx);
 }
 
 NS_IMETHODIMP
 XPITriggerEvent::Run()
 {
     JSAutoRequest ar(cx);
 
@@ -323,17 +323,17 @@ void nsXPITriggerInfo::SendStatus(const 
         {
             event->URL      = URL;
             event->status   = status;
             event->cx       = mCx;
             event->princ    = mPrincipal;
 
             event->cbval    = mCbval;
             JS_BeginRequest(event->cx);
-            JS_AddNamedRoot(event->cx, &event->cbval,
+            JS_AddNamedValueRoot(event->cx, &event->cbval,
                             "XPITriggerEvent::cbval" );
             JS_EndRequest(event->cx);
 
             // Hold a strong reference to keep the underlying
             // JSContext from dying before we handle this event.
             event->ref      = mContextWrapper;
 
             rv = mThread->Dispatch(event, NS_DISPATCH_NORMAL);