Bug 959787 - Handlify some friend and debug APIs r=sfink r=bholley
authorJon Coppeard <jcoppeard@mozilla.com>
Mon, 17 Mar 2014 16:17:58 +0000
changeset 173899 0ae9c4eef8d6ec3c7ddf977ca9a9efd1758183ec
parent 173898 9f41c59d6a59f8f0241c14b9b63d00902a54d958
child 173900 bf236376056cb28b4703f357ff5fb200a0b7ac1a
push id41129
push userjcoppeard@mozilla.com
push dateMon, 17 Mar 2014 16:23:07 +0000
treeherdermozilla-inbound@0ae9c4eef8d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink, bholley
bugs959787
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 959787 - Handlify some friend and debug APIs r=sfink r=bholley
dom/bindings/BindingUtils.cpp
js/jsd/jsd_val.cpp
js/public/OldDebugAPI.h
js/src/builtin/TestingFunctions.cpp
js/src/jsapi-tests/testCloneScript.cpp
js/src/jsapi-tests/testOriginPrincipals.cpp
js/src/jsapi-tests/testXDR.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsobj.cpp
js/src/jsweakmap.cpp
js/src/vm/Debugger.cpp
js/src/vm/Debugger.h
js/src/vm/OldDebugAPI.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/wrappers/XrayWrapper.cpp
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -1760,17 +1760,17 @@ ReparentWrapper(JSContext* aCx, JS::Hand
   }
 
   bool preserving = cache->PreservingWrapper();
   cache->SetPreservingWrapper(false);
   cache->SetWrapper(aObj);
   cache->SetPreservingWrapper(preserving);
 
   if (propertyHolder) {
-    JSObject* copyTo;
+    JS::Rooted<JSObject*> copyTo(aCx);
     if (isProxy) {
       copyTo = DOMProxyHandler::EnsureExpandoObject(aCx, aObj);
     } else {
       copyTo = aObj;
     }
 
     if (!copyTo || !JS_CopyPropertiesFrom(aCx, copyTo, propertyHolder)) {
       MOZ_CRASH();
--- a/js/jsd/jsd_val.cpp
+++ b/js/jsd/jsd_val.cpp
@@ -673,27 +673,26 @@ jsd_GetValueClassName(JSDContext* jsdc, 
     return jsdval->className;
 }
 
 JSDScript*
 jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval)
 {
     AutoSafeJSContext cx;
     JS::RootedValue val(cx, jsdval->val);
-    JSFunction* fun = nullptr;
     JS::RootedScript script(cx);
     JSDScript* jsdscript;
 
     if (!jsd_IsValueFunction(jsdc, jsdval))
         return nullptr;
 
     {
         JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(val));
         AutoSaveExceptionState as(cx);
-        fun = JSD_GetValueFunction(jsdc, jsdval);
+        JS::RootedFunction fun(cx, JSD_GetValueFunction(jsdc, jsdval));
         if (fun)
             script = JS_GetFunctionScript(cx, fun);
     }
 
     if (!script)
         return nullptr;
 
     JSD_LOCK_SCRIPTS(jsdc);
--- a/js/public/OldDebugAPI.h
+++ b/js/public/OldDebugAPI.h
@@ -220,18 +220,18 @@ extern JS_PUBLIC_API(bool)
 JS_SetInterrupt(JSRuntime *rt, JSInterruptHook handler, void *closure);
 
 extern JS_PUBLIC_API(bool)
 JS_ClearInterrupt(JSRuntime *rt, JSInterruptHook *handlerp, void **closurep);
 
 /************************************************************************/
 
 extern JS_PUBLIC_API(bool)
-JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id,
-                 JSWatchPointHandler handler, JSObject *closure);
+JS_SetWatchPoint(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
+                 JSWatchPointHandler handler, JS::HandleObject closure);
 
 extern JS_PUBLIC_API(bool)
 JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsid id,
                    JSWatchPointHandler *handlerp, JSObject **closurep);
 
 extern JS_PUBLIC_API(bool)
 JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj);
 
@@ -267,17 +267,17 @@ JS_LocalNameToAtom(uintptr_t w);
 
 extern JS_PUBLIC_API(JSString *)
 JS_AtomKey(JSAtom *atom);
 
 extern JS_PUBLIC_API(void)
 JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mark);
 
 extern JS_PUBLIC_API(JSScript *)
-JS_GetFunctionScript(JSContext *cx, JSFunction *fun);
+JS_GetFunctionScript(JSContext *cx, JS::HandleFunction fun);
 
 extern JS_PUBLIC_API(JSNative)
 JS_GetFunctionNative(JSContext *cx, JSFunction *fun);
 
 extern JS_PUBLIC_API(JSPrincipals *)
 JS_GetScriptPrincipals(JSScript *script);
 
 extern JS_PUBLIC_API(JSPrincipals *)
@@ -355,17 +355,17 @@ typedef struct JSPropertyDesc {
 typedef struct JSPropertyDescArray {
     uint32_t        length;     /* number of elements in array */
     JSPropertyDesc  *array;     /* alloc'd by Get, freed by Put */
 } JSPropertyDescArray;
 
 typedef struct JSScopeProperty JSScopeProperty;
 
 extern JS_PUBLIC_API(bool)
-JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda);
+JS_GetPropertyDescArray(JSContext *cx, JS::HandleObject obj, JSPropertyDescArray *pda);
 
 extern JS_PUBLIC_API(void)
 JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
 
 /************************************************************************/
 
 /*
  * JSAbstractFramePtr is the public version of AbstractFramePtr, a pointer to a
@@ -524,17 +524,17 @@ JS_GetGlobalDebugHooks(JSRuntime *rt);
 /**
  * Add various profiling-related functions as properties of the given object.
  */
 extern JS_PUBLIC_API(bool)
 JS_DefineProfilingFunctions(JSContext *cx, JSObject *obj);
 
 /* Defined in vm/Debugger.cpp. */
 extern JS_PUBLIC_API(bool)
-JS_DefineDebuggerObject(JSContext *cx, JSObject *obj);
+JS_DefineDebuggerObject(JSContext *cx, JS::HandleObject obj);
 
 extern JS_PUBLIC_API(void)
 JS_DumpPCCounts(JSContext *cx, JSScript *script);
 
 extern JS_PUBLIC_API(void)
 JS_DumpCompartmentPCCounts(JSContext *cx);
 
 namespace js {
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -650,17 +650,18 @@ NondeterministicGetWeakMapKeys(JSContext
     }
     if (!args[0].isObject()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
                              "nondeterministicGetWeakMapKeys", "WeakMap",
                              InformalValueTypeName(args[0]));
         return false;
     }
     RootedObject arr(cx);
-    if (!JS_NondeterministicGetWeakMapKeys(cx, &args[0].toObject(), arr.address()))
+    RootedObject mapObj(cx, &args[0].toObject());
+    if (!JS_NondeterministicGetWeakMapKeys(cx, mapObj, &arr))
         return false;
     if (!arr) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
                              "nondeterministicGetWeakMapKeys", "WeakMap",
                              args[0].toObject().getClass()->name);
         return false;
     }
     args.rval().setObject(*arr);
--- a/js/src/jsapi-tests/testCloneScript.cpp
+++ b/js/src/jsapi-tests/testCloneScript.cpp
@@ -121,17 +121,17 @@ BEGIN_TEST(test_cloneScriptWithPrincipal
     }
 
     // Clone into B
     {
         JSAutoCompartment b(cx, B);
         JS::RootedObject cloned(cx);
         CHECK(cloned = JS_CloneFunctionObject(cx, obj, B));
 
-        JSFunction *fun;
+        JS::RootedFunction fun(cx);
         JS::RootedValue clonedValue(cx, JS::ObjectValue(*cloned));
         CHECK(fun = JS_ValueToFunction(cx, clonedValue));
 
         JSScript *script;
         CHECK(script = JS_GetFunctionScript(cx, fun));
 
         CHECK(JS_GetScriptPrincipals(script) == principalsB);
 
--- a/js/src/jsapi-tests/testOriginPrincipals.cpp
+++ b/js/src/jsapi-tests/testOriginPrincipals.cpp
@@ -84,17 +84,18 @@ testOuter(const char *asciiChars)
 }
 
 bool
 testInner(const char *asciiChars, JSPrincipals *principal, JSPrincipals *originPrincipal)
 {
     JS::RootedValue rval(cx);
     CHECK(eval(asciiChars, principal, originPrincipal, &rval));
 
-    JSScript *script = JS_GetFunctionScript(cx, &rval.toObject().as<JSFunction>());
+    JS::RootedFunction fun(cx, &rval.toObject().as<JSFunction>());
+    JSScript *script = JS_GetFunctionScript(cx, fun);
     CHECK(JS_GetScriptPrincipals(script) == principal);
     CHECK(JS_GetScriptOriginPrincipals(script) == originPrincipal);
 
     return true;
 }
 
 bool
 testError(const char *asciiChars)
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -49,17 +49,18 @@ FreezeThaw(JSContext *cx, JS::HandleScri
                                         script->principals(), script->originPrincipals());
     js_free(memory);
     return script2;
 }
 
 static JSScript *
 GetScript(JSContext *cx, JS::HandleObject funobj)
 {
-    return JS_GetFunctionScript(cx, JS_GetObjectFunction(funobj));
+    JS::RootedFunction fun(cx, JS_GetObjectFunction(funobj));
+    return JS_GetFunctionScript(cx, fun);
 }
 
 static JSObject *
 FreezeThaw(JSContext *cx, JS::HandleObject funobj)
 {
     // freeze
     uint32_t nbytes;
     void *memory = JS_EncodeInterpretedFunction(cx, funobj, &nbytes);
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -75,17 +75,17 @@ JS_GetAnonymousString(JSRuntime *rt)
 
 JS_FRIEND_API(void)
 JS_SetIsWorkerRuntime(JSRuntime *rt)
 {
     rt->setIsWorkerRuntime();
 }
 
 JS_FRIEND_API(JSObject *)
-JS_FindCompilationScope(JSContext *cx, JSObject *objArg)
+JS_FindCompilationScope(JSContext *cx, HandleObject objArg)
 {
     RootedObject obj(cx, objArg);
 
     /*
      * We unwrap wrappers here. This is a little weird, but it's what's being
      * asked of us.
      */
     if (obj->is<WrapperObject>())
@@ -104,20 +104,18 @@ JS_FRIEND_API(JSFunction *)
 JS_GetObjectFunction(JSObject *obj)
 {
     if (obj->is<JSFunction>())
         return &obj->as<JSFunction>();
     return nullptr;
 }
 
 JS_FRIEND_API(bool)
-JS_SplicePrototype(JSContext *cx, JSObject *objArg, JSObject *protoArg)
+JS_SplicePrototype(JSContext *cx, HandleObject obj, HandleObject proto)
 {
-    RootedObject obj(cx, objArg);
-    RootedObject proto(cx, protoArg);
     /*
      * Change the prototype of an object which hasn't been used anywhere
      * and does not share its type with another object. Unlike JS_SetPrototype,
      * does not nuke type information for the object.
      */
     CHECK_REQUEST(cx);
 
     if (!obj->hasSingletonType()) {
@@ -128,20 +126,19 @@ JS_SplicePrototype(JSContext *cx, JSObje
         return JS_SetPrototype(cx, obj, proto);
     }
 
     Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
     return obj->splicePrototype(cx, obj->getClass(), tagged);
 }
 
 JS_FRIEND_API(JSObject *)
-JS_NewObjectWithUniqueType(JSContext *cx, const JSClass *clasp, JSObject *protoArg, JSObject *parentArg)
+JS_NewObjectWithUniqueType(JSContext *cx, const JSClass *clasp, HandleObject proto,
+                           HandleObject parent)
 {
-    RootedObject proto(cx, protoArg);
-    RootedObject parent(cx, parentArg);
     /*
      * Create our object with a null proto and then splice in the correct proto
      * after we setSingletonType, so that we don't pollute the default
      * TypeObject attached to our proto with information about our object, since
      * we're not going to be using that TypeObject anyway.
      */
     RootedObject obj(cx, NewObjectWithGivenProto(cx, (const js::Class *)clasp, nullptr,
                                                  parent, SingletonObject));
@@ -283,19 +280,18 @@ DefineHelpProperty(JSContext *cx, Handle
         return false;
     jsval v = STRING_TO_JSVAL(atom);
     return JS_DefineProperty(cx, obj, prop, v,
                              JS_PropertyStub, JS_StrictPropertyStub,
                              JSPROP_READONLY | JSPROP_PERMANENT);
 }
 
 JS_FRIEND_API(bool)
-JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *objArg, const JSFunctionSpecWithHelp *fs)
+JS_DefineFunctionsWithHelp(JSContext *cx, HandleObject obj, const JSFunctionSpecWithHelp *fs)
 {
-    RootedObject obj(cx, objArg);
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     for (; fs->name; fs++) {
         JSAtom *atom = Atomize(cx, fs->name, strlen(fs->name));
         if (!atom)
             return false;
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -48,38 +48,39 @@ JS_SetGrayGCRootsTracer(JSRuntime *rt, J
 
 extern JS_FRIEND_API(JSString *)
 JS_GetAnonymousString(JSRuntime *rt);
 
 extern JS_FRIEND_API(void)
 JS_SetIsWorkerRuntime(JSRuntime *rt);
 
 extern JS_FRIEND_API(JSObject *)
-JS_FindCompilationScope(JSContext *cx, JSObject *obj);
+JS_FindCompilationScope(JSContext *cx, JS::HandleObject obj);
 
 extern JS_FRIEND_API(JSFunction *)
 JS_GetObjectFunction(JSObject *obj);
 
 extern JS_FRIEND_API(bool)
-JS_SplicePrototype(JSContext *cx, JSObject *obj, JSObject *proto);
+JS_SplicePrototype(JSContext *cx, JS::HandleObject obj, JS::HandleObject proto);
 
 extern JS_FRIEND_API(JSObject *)
-JS_NewObjectWithUniqueType(JSContext *cx, const JSClass *clasp, JSObject *proto, JSObject *parent);
+JS_NewObjectWithUniqueType(JSContext *cx, const JSClass *clasp, JS::HandleObject proto,
+                           JS::HandleObject parent);
 
 extern JS_FRIEND_API(uint32_t)
 JS_ObjectCountDynamicSlots(JS::HandleObject obj);
 
 extern JS_FRIEND_API(size_t)
 JS_SetProtoCalled(JSContext *cx);
 
 extern JS_FRIEND_API(size_t)
 JS_GetCustomIteratorCount(JSContext *cx);
 
 extern JS_FRIEND_API(bool)
-JS_NondeterministicGetWeakMapKeys(JSContext *cx, JSObject *obj, JSObject **ret);
+JS_NondeterministicGetWeakMapKeys(JSContext *cx, JS::HandleObject obj, JS::MutableHandleObject ret);
 
 /*
  * Determine whether the given object is backed by a DeadObjectProxy.
  *
  * Such objects hold no other objects (they have no outgoing reference edges)
  * and will throw if you touch them (e.g. by reading/writing a property).
  */
 extern JS_FRIEND_API(bool)
@@ -180,17 +181,17 @@ js_DumpChars(const jschar *s, size_t n);
 /*
  * Copies all own properties from |obj| to |target|. |obj| must be a "native"
  * object (that is to say, normal-ish - not an Array or a Proxy).
  *
  * This function immediately enters a compartment, and does not impose any
  * restrictions on the compartment of |cx|.
  */
 extern JS_FRIEND_API(bool)
-JS_CopyPropertiesFrom(JSContext *cx, JSObject *target, JSObject *obj);
+JS_CopyPropertiesFrom(JSContext *cx, JS::HandleObject target, JS::HandleObject obj);
 
 /*
  * Single-property version of the above. This function asserts that an |own|
  * property of the given name exists on |obj|.
  *
  * On entry, |cx| must be same-compartment with |obj|.
  */
 extern JS_FRIEND_API(bool)
@@ -217,17 +218,17 @@ struct JSFunctionSpecWithHelp {
 };
 
 #define JS_FN_HELP(name,call,nargs,flags,usage,help)                          \
     {name, call, nargs, (flags) | JSPROP_ENUMERATE | JSFUN_STUB_GSOPS, usage, help}
 #define JS_FS_HELP_END                                                        \
     {nullptr, nullptr, 0, 0, nullptr, nullptr}
 
 extern JS_FRIEND_API(bool)
-JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *obj, const JSFunctionSpecWithHelp *fs);
+JS_DefineFunctionsWithHelp(JSContext *cx, JS::HandleObject obj, const JSFunctionSpecWithHelp *fs);
 
 namespace js {
 
 /*
  * Helper Macros for creating JSClasses that function as proxies.
  *
  * NB: The macro invocation must be surrounded by braces, so as to
  *     allow for potention JSClass extensions.
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1743,20 +1743,18 @@ JS_CopyPropertyFrom(JSContext *cx, Handl
     if (!cx->compartment()->wrapId(cx, wrappedId.address()))
         return false;
 
     bool ignored;
     return DefineOwnProperty(cx, target, wrappedId, desc, &ignored);
 }
 
 JS_FRIEND_API(bool)
-JS_CopyPropertiesFrom(JSContext *cx, JSObject *targetArg, JSObject *objArg)
-{
-    RootedObject target(cx, targetArg);
-    RootedObject obj(cx, objArg);
+JS_CopyPropertiesFrom(JSContext *cx, HandleObject target, HandleObject obj)
+{
     JSAutoCompartment ac(cx, obj);
 
     AutoIdVector props(cx);
     if (!GetPropertyNames(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN, &props))
         return false;
 
     for (size_t i = 0; i < props.length(); ++i) {
         if (!JS_CopyPropertyFrom(cx, props.handleAt(i), target, obj))
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -345,22 +345,22 @@ WeakMap_set_impl(JSContext *cx, CallArgs
 static bool
 WeakMap_set(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsWeakMap, WeakMap_set_impl>(cx, args);
 }
 
 JS_FRIEND_API(bool)
-JS_NondeterministicGetWeakMapKeys(JSContext *cx, JSObject *objArg, JSObject **ret)
+JS_NondeterministicGetWeakMapKeys(JSContext *cx, HandleObject objArg, MutableHandleObject ret)
 {
     RootedObject obj(cx, objArg);
     obj = UncheckedUnwrap(obj);
     if (!obj || !obj->is<WeakMapObject>()) {
-        *ret = nullptr;
+        ret.set(nullptr);
         return true;
     }
     RootedObject arr(cx, NewDenseEmptyArray(cx));
     if (!arr)
         return false;
     ObjectValueMap *map = obj->as<WeakMapObject>().getMap();
     if (map) {
         // Prevent GC from mutating the weakmap while iterating.
@@ -368,17 +368,17 @@ JS_NondeterministicGetWeakMapKeys(JSCont
         for (ObjectValueMap::Base::Range r = map->all(); !r.empty(); r.popFront()) {
             RootedObject key(cx, r.front().key());
             if (!cx->compartment()->wrap(cx, &key))
                 return false;
             if (!NewbornArrayPush(cx, arr, ObjectValue(*key)))
                 return false;
         }
     }
-    *ret = arr;
+    ret.set(arr);
     return true;
 }
 
 static void
 WeakMap_mark(JSTracer *trc, JSObject *obj)
 {
     if (ObjectValueMap *map = obj->as<WeakMapObject>().getMap())
         map->trace(trc);
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -5890,20 +5890,18 @@ static const JSFunctionSpec DebuggerEnv_
     JS_FS_END
 };
 
 
 
 /*** Glue ****************************************************************************************/
 
 extern JS_PUBLIC_API(bool)
-JS_DefineDebuggerObject(JSContext *cx, JSObject *obj_)
-{
-    RootedObject obj(cx, obj_);
-
+JS_DefineDebuggerObject(JSContext *cx, HandleObject obj)
+{
     RootedObject
         objProto(cx),
         debugCtor(cx),
         debugProto(cx),
         frameProto(cx),
         scriptProto(cx),
         sourceProto(cx),
         objectProto(cx),
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -154,17 +154,17 @@ class DebuggerWeakMap : private WeakMap<
  * environments and objects are really two different concepts.
  */
 typedef JSObject Env;
 
 class Debugger : private mozilla::LinkedListElement<Debugger>
 {
     friend class Breakpoint;
     friend class mozilla::LinkedListElement<Debugger>;
-    friend bool (::JS_DefineDebuggerObject)(JSContext *cx, JSObject *obj);
+    friend bool (::JS_DefineDebuggerObject)(JSContext *cx, JS::HandleObject obj);
 
   public:
     enum Hook {
         OnDebuggerStatement,
         OnExceptionUnwind,
         OnNewScript,
         OnEnterFrame,
         OnNewGlobalObject,
--- a/js/src/vm/OldDebugAPI.cpp
+++ b/js/src/vm/OldDebugAPI.cpp
@@ -289,23 +289,21 @@ JS_ClearInterrupt(JSRuntime *rt, JSInter
     rt->debugHooks.interruptHook = 0;
     rt->debugHooks.interruptHookData = 0;
     return true;
 }
 
 /************************************************************************/
 
 JS_PUBLIC_API(bool)
-JS_SetWatchPoint(JSContext *cx, JSObject *obj_, jsid id_,
-                 JSWatchPointHandler handler, JSObject *closure_)
+JS_SetWatchPoint(JSContext *cx, HandleObject origobj, HandleId id,
+                 JSWatchPointHandler handler, HandleObject closure)
 {
-    assertSameCompartment(cx, obj_);
+    assertSameCompartment(cx, origobj);
 
-    RootedId id(cx, id_);
-    RootedObject origobj(cx, obj_), closure(cx, closure_);
     RootedObject obj(cx, GetInnerObject(cx, origobj));
     if (!obj)
         return false;
 
     RootedId propid(cx);
 
     if (JSID_IS_INT(id)) {
         propid = id;
@@ -491,24 +489,23 @@ JS_AtomKey(JSAtom *atom)
 
 extern JS_PUBLIC_API(void)
 JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mem)
 {
     cx->tempLifoAlloc().release(*reinterpret_cast<LifoAlloc::Mark*>(mem));
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
+JS_GetFunctionScript(JSContext *cx, HandleFunction fun)
 {
     if (fun->isNative())
         return nullptr;
     if (fun->isInterpretedLazy()) {
-        RootedFunction rootedFun(cx, fun);
-        AutoCompartment funCompartment(cx, rootedFun);
-        JSScript *script = rootedFun->getOrCreateScript(cx);
+        AutoCompartment funCompartment(cx, fun);
+        JSScript *script = fun->getOrCreateScript(cx);
         if (!script)
             MOZ_CRASH();
         return script;
     }
     return fun->nonLazyScript();
 }
 
 JS_PUBLIC_API(JSNative)
@@ -654,20 +651,18 @@ GetPropertyDesc(JSContext *cx, JSObject 
               |  (!shape->configurable() ? JSPD_PERMANENT : 0);
     pd->spare = 0;
     pd->alias = JSVAL_VOID;
 
     return true;
 }
 
 JS_PUBLIC_API(bool)
-JS_GetPropertyDescArray(JSContext *cx, JSObject *obj_, JSPropertyDescArray *pda)
+JS_GetPropertyDescArray(JSContext *cx, JS::HandleObject obj, JSPropertyDescArray *pda)
 {
-    RootedObject obj(cx, obj_);
-
     assertSameCompartment(cx, obj);
     uint32_t i = 0;
     JSPropertyDesc *pd = nullptr;
 
     if (obj->is<DebugScopeObject>()) {
         AutoIdVector props(cx);
         if (!Proxy::enumerate(cx, obj, props))
             return false;
@@ -990,17 +985,17 @@ class AutoPropertyDescArray
         PodZero(&descArray_);
     }
     ~AutoPropertyDescArray()
     {
         if (descArray_.array)
             JS_PutPropertyDescArray(cx_, &descArray_);
     }
 
-    void fetch(JSObject *obj) {
+    void fetch(JS::HandleObject obj) {
         JS_ASSERT(!descArray_.array);
         if (!JS_GetPropertyDescArray(cx_, obj, &descArray_))
             descArray_.array = nullptr;
     }
 
     JSPropertyDescArray * operator ->() {
         return &descArray_;
     }
@@ -1054,18 +1049,20 @@ FormatFrame(JSContext *cx, const NonBuil
     RootedString funname(cx);
     if (fun)
         funname = fun->atom();
 
     RootedValue thisVal(cx);
     AutoPropertyDescArray thisProps(cx);
     if (iter.computeThis(cx)) {
         thisVal = iter.thisv();
-        if (showThisProps && !thisVal.isPrimitive())
-            thisProps.fetch(&thisVal.toObject());
+        if (showThisProps && !thisVal.isPrimitive()) {
+            RootedObject thisObj(cx, &thisVal.toObject());
+            thisProps.fetch(thisObj);
+        }
     }
 
     // print the frame number and function name
     if (funname) {
         JSAutoByteString funbytes;
         buf = JS_sprintf_append(buf, "%d %s(", num, funbytes.encodeLatin1(cx, funname));
     } else if (fun) {
         buf = JS_sprintf_append(buf, "%d anonymous(", num);
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2876,17 +2876,18 @@ nsXPCComponents_Utils::NondeterministicG
                                                       JSContext *aCx,
                                                       MutableHandleValue aKeys)
 {
     if (!aMap.isObject()) {
         aKeys.setUndefined();
         return NS_OK;
     }
     RootedObject objRet(aCx);
-    if (!JS_NondeterministicGetWeakMapKeys(aCx, &aMap.toObject(), objRet.address()))
+    RootedObject mapObj(aCx, &aMap.toObject());
+    if (!JS_NondeterministicGetWeakMapKeys(aCx, mapObj, &objRet))
         return NS_ERROR_OUT_OF_MEMORY;
      aKeys.set(objRet ? ObjectValue(*objRet) : UndefinedValue());
     return NS_OK;
 }
 
 /* void getDebugObject(); */
 NS_IMETHODIMP
 nsXPCComponents_Utils::GetJSTestingFunctions(JSContext *cx,
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -189,17 +189,18 @@ XPCWrappedNative::WrapNewGlobal(xpcObjec
         XPCWrappedNativeProto::GetNewOrUsed(scope,
                                             nativeHelper.GetClassInfo(), &sciProto,
                                             /* callPostCreatePrototype = */ false);
     if (!proto)
         return NS_ERROR_FAILURE;
 
     // Set up the prototype on the global.
     MOZ_ASSERT(proto->GetJSProtoObject());
-    bool success = JS_SplicePrototype(cx, global, proto->GetJSProtoObject());
+    RootedObject protoObj(cx, proto->GetJSProtoObject());
+    bool success = JS_SplicePrototype(cx, global, protoObj);
     if (!success)
         return NS_ERROR_FAILURE;
 
     // Construct the wrapper, which takes over the strong reference to the
     // native object.
     nsRefPtr<XPCWrappedNative> wrapper =
         new XPCWrappedNative(nativeHelper.forgetCanonical(), proto);
 
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -1349,18 +1349,21 @@ static const uint8_t HAS_ORIGIN_PRINCIPA
 
 static nsresult
 WriteScriptOrFunction(nsIObjectOutputStream *stream, JSContext *cx,
                       JSScript *scriptArg, HandleObject functionObj)
 {
     // Exactly one of script or functionObj must be given
     MOZ_ASSERT(!scriptArg != !functionObj);
 
-    RootedScript script(cx, scriptArg ? scriptArg :
-                                        JS_GetFunctionScript(cx, JS_GetObjectFunction(functionObj)));
+    RootedScript script(cx, scriptArg);
+    if (!script) {
+        RootedFunction fun(cx, JS_GetObjectFunction(functionObj));
+        script.set(JS_GetFunctionScript(cx, fun));
+    }
 
     nsIPrincipal *principal =
         nsJSPrincipals::get(JS_GetScriptPrincipals(script));
     nsIPrincipal *originPrincipal =
         nsJSPrincipals::get(JS_GetScriptOriginPrincipals(script));
 
     uint8_t flags = 0;
     if (principal)
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -482,18 +482,18 @@ XrayTraits::cloneExpandoChain(JSContext 
 
     RootedObject oldHead(cx, getExpandoChain(src));
     while (oldHead) {
         RootedObject exclusive(cx, JS_GetReservedSlot(oldHead,
                                                       JSSLOT_EXPANDO_EXCLUSIVE_GLOBAL)
                                                      .toObjectOrNull());
         if (!JS_WrapObject(cx, &exclusive))
             return false;
-        JSObject *newHead = attachExpandoObject(cx, dst, GetExpandoObjectPrincipal(oldHead),
-                                                exclusive);
+        RootedObject newHead(cx, attachExpandoObject(cx, dst, GetExpandoObjectPrincipal(oldHead),
+                                                     exclusive));
         if (!JS_CopyPropertiesFrom(cx, newHead, oldHead))
             return false;
         oldHead = JS_GetReservedSlot(oldHead, JSSLOT_EXPANDO_NEXT).toObjectOrNull();
     }
     return true;
 }
 
 namespace XrayUtils {