[gjs/wip/ptomato/mozjs31prep: 5/6] js: Rooted objects in private access functions



commit 09da66899a48f278de527b70b22784a688c5b05f
Author: Philip Chimento <philip endlessm com>
Date:   Thu Sep 29 18:37:42 2016 -0700

    js: Rooted objects in private access functions
    
    Starting with the functions defined in jsapi-util.h's
    GJS_DEFINE_PRIV_FROM_JS macro, we convert the JSObject pointers there to
    JS::HandleObjects, in order to be able to pass them to
    JS_GetInstancePrivate() in mozjs31 which will only accept HandleObjects.
    
    We work backwards from there, in a huge cascade, changing JSObject* to
    JS::HandleObject in all function argument types that call into those
    functions, and rooting the objects with JS::RootedObject where they are
    created.
    
    This is mostly straightforward but object_init_list in object.cpp needed
    some extra attention. Normally objects are rooted for the duration of a
    scope. In this case, we used a GSList to keep track of the objects past
    the end of the scope, so they could be fetched again in the GObject's
    construct() vfunc. With the normal rooting, that does not work because
    the objects can be moved or GC'd after the original scope ends. Instead
    we have to use JS_AddNamedObjectRoot() and JS_RemoveObjectRoot(). This
    can be changed to a nicer API in mozjs31, JS::PersistentRooted.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=742249

 gi/arg.cpp                        |   33 +++++----
 gi/boxed.cpp                      |   44 ++++++-----
 gi/boxed.h                        |    4 +-
 gi/function.cpp                   |   64 ++++++++--------
 gi/function.h                     |   24 +++---
 gi/fundamental.cpp                |   76 ++++++++----------
 gi/fundamental.h                  |   16 +++--
 gi/gerror.cpp                     |   28 ++++----
 gi/gerror.h                       |    4 +-
 gi/gtype.cpp                      |   20 +++--
 gi/gtype.h                        |    6 +-
 gi/keep-alive.cpp                 |   14 ++--
 gi/ns.cpp                         |    6 +-
 gi/object.cpp                     |  150 ++++++++++++++++++-------------------
 gi/object.h                       |   21 +++--
 gi/param.cpp                      |   12 ++--
 gi/param.h                        |   15 ++--
 gi/repo.cpp                       |    5 +-
 gi/union.cpp                      |   39 +++++-----
 gi/union.h                        |    8 +-
 gi/value.cpp                      |   20 +++---
 gjs/byteArray.cpp                 |   55 +++++++-------
 gjs/byteArray.h                   |   22 +++---
 gjs/importer.cpp                  |    7 +-
 gjs/jsapi-util.cpp                |   40 ++++++----
 gjs/jsapi-util.h                  |   18 ++--
 modules/cairo-context.cpp         |   50 ++++++-------
 modules/cairo-image-surface.cpp   |    9 +-
 modules/cairo-linear-gradient.cpp |    5 +-
 modules/cairo-path.cpp            |    4 +-
 modules/cairo-pattern.cpp         |    2 +-
 modules/cairo-pdf-surface.cpp     |    5 +-
 modules/cairo-private.h           |    6 +-
 modules/cairo-ps-surface.cpp      |    5 +-
 modules/cairo-radial-gradient.cpp |    5 +-
 modules/cairo-region.cpp          |   25 +++---
 modules/cairo-solid-pattern.cpp   |    5 +-
 modules/cairo-surface-pattern.cpp |    5 +-
 modules/cairo-surface.cpp         |    7 +-
 modules/cairo-svg-surface.cpp     |    5 +-
 modules/system.cpp                |    5 +-
 41 files changed, 448 insertions(+), 446 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index 78e47de..8a9fb47 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -619,6 +619,7 @@ gjs_gtypearray_to_array(JSContext   *context,
     /* add one so we're always zero terminated */
     result = (GType *) g_malloc0((length+1) * sizeof(GType));
 
+    JS::RootedObject elem_obj(context);
     for (i = 0; i < length; ++i) {
         JS::Value elem;
         GType gtype;
@@ -633,7 +634,8 @@ gjs_gtypearray_to_array(JSContext   *context,
         if (!elem.isObjectOrNull())
             goto err;
 
-        gtype = gjs_gtype_get_actual_gtype(context, elem.toObjectOrNull());
+        elem_obj = elem.toObjectOrNull();
+        gtype = gjs_gtype_get_actual_gtype(context, elem_obj);
         if (gtype == G_TYPE_INVALID)
             goto err;
 
@@ -1275,7 +1277,8 @@ gjs_value_to_g_argument(JSContext      *context,
     case GI_TYPE_TAG_GTYPE:
         if (value.isObjectOrNull()) {
             GType gtype;
-            gtype = gjs_gtype_get_actual_gtype(context, value.toObjectOrNull());
+            JS::RootedObject obj(context, value.toObjectOrNull());
+            gtype = gjs_gtype_get_actual_gtype(context, obj);
             if (gtype == G_TYPE_INVALID)
                 wrong = true;
             arg->v_ssize = gtype;
@@ -1323,8 +1326,9 @@ gjs_value_to_g_argument(JSContext      *context,
         if (value.isNull()) {
             arg->v_pointer = NULL;
         } else if (value.isObject()) {
-            if (gjs_typecheck_gerror(context, &value.toObject(), true)) {
-                arg->v_pointer = gjs_gerror_from_error(context, &value.toObject());
+            JS::RootedObject obj(context, &value.toObject());
+            if (gjs_typecheck_gerror(context, obj, true)) {
+                arg->v_pointer = gjs_gerror_from_error(context, obj);
 
                 if (transfer != GI_TRANSFER_NOTHING)
                     arg->v_pointer = g_error_copy ((const GError *) arg->v_pointer);
@@ -1412,7 +1416,7 @@ gjs_value_to_g_argument(JSContext      *context,
             } else if (value.isNull()) {
                 arg->v_pointer = NULL;
             } else if (value.isObject()) {
-                JSObject *obj = &value.toObject();
+                JS::RootedObject obj(context, &value.toObject());
                 if (interface_type == GI_INFO_TYPE_STRUCT &&
                     g_struct_info_is_gtype_struct((GIStructInfo*)interface_info)) {
                     GType actual_gtype;
@@ -1730,17 +1734,16 @@ gjs_value_to_g_argument(JSContext      *context,
         /* First, let's handle the case where we're passed an instance
          * of our own byteArray class.
          */
-        if (value.isObjectOrNull() &&
-            gjs_typecheck_bytearray(context, value.toObjectOrNull(), false))
-            {
-                JSObject *bytearray_obj = value.toObjectOrNull();
-                if (array_type == GI_ARRAY_TYPE_BYTE_ARRAY) {
-                    arg->v_pointer = gjs_byte_array_get_byte_array(context, bytearray_obj);
-                    break;
-                } else {
-                    /* Fall through, !handled */
-                }
+        if (value.isObjectOrNull()) {
+            JS::RootedObject bytearray_obj(context, value.toObjectOrNull());
+            if (gjs_typecheck_bytearray(context, bytearray_obj, false)
+                && array_type == GI_ARRAY_TYPE_BYTE_ARRAY) {
+                arg->v_pointer = gjs_byte_array_get_byte_array(context, bytearray_obj);
+                break;
+            } else {
+                /* Fall through, !handled */
             }
+        }
 
         if (!gjs_array_to_explicit_array_internal(context,
                                                   value,
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 87c6433..b769e1d 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -204,7 +204,8 @@ boxed_get_copy_source(JSContext *context,
     if (!value.isObject())
         return false;
 
-    if (!priv_from_js_with_typecheck(context, &value.toObject(), &source_priv))
+    JS::RootedObject object(context, &value.toObject());
+    if (!priv_from_js_with_typecheck(context, object, &source_priv))
         return false;
 
     if (!g_base_info_equal((GIBaseInfo*) priv->info, (GIBaseInfo*) source_priv->info))
@@ -427,7 +428,7 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
     GJS_NATIVE_CONSTRUCTOR_VARIABLES(boxed)
     Boxed *priv;
     Boxed *proto_priv;
-    JSObject *proto;
+    JS::RootedObject proto(context);
     Boxed *source_priv;
     JS::Value actual_rval;
     bool retval;
@@ -443,10 +444,11 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
 
     gjs_debug_lifecycle(GJS_DEBUG_GBOXED,
                         "boxed constructor, obj %p priv %p",
-                        object, priv);
+                        object.get(), priv);
 
-    JS_GetPrototype(context, object, &proto);
-    gjs_debug_lifecycle(GJS_DEBUG_GBOXED, "boxed instance __proto__ is %p", proto);
+    JS_GetPrototype(context, object, proto.address());
+    gjs_debug_lifecycle(GJS_DEBUG_GBOXED, "boxed instance __proto__ is %p",
+                        proto.get());
     /* If we're the prototype, then post-construct we'll fill in priv->info.
      * If we are not the prototype, though, then we'll get ->info from the
      * prototype and then create a GObject if we don't have one already.
@@ -583,7 +585,6 @@ get_nested_interface_object (JSContext   *context,
                              JS::Value   *value)
 {
     JSObject *obj;
-    JSObject *proto;
     int offset;
     Boxed *priv;
     Boxed *proto_priv;
@@ -596,7 +597,9 @@ get_nested_interface_object (JSContext   *context,
         return false;
     }
 
-    proto = gjs_lookup_generic_prototype(context, (GIBoxedInfo*) interface_info);
+    JS::RootedObject proto(context,
+                           gjs_lookup_generic_prototype(context,
+                                                        (GIBoxedInfo*) interface_info));
     proto_priv = priv_from_js(context, proto);
 
     offset = g_field_info_get_offset (field_info);
@@ -707,7 +710,6 @@ set_nested_interface_object (JSContext   *context,
                              GIBaseInfo  *interface_info,
                              JS::Value    value)
 {
-    JSObject *proto;
     int offset;
     Boxed *proto_priv;
     Boxed *source_priv;
@@ -720,14 +722,17 @@ set_nested_interface_object (JSContext   *context,
         return false;
     }
 
-    proto = gjs_lookup_generic_prototype(context, (GIBoxedInfo*) interface_info);
+    JS::RootedObject proto(context,
+                           gjs_lookup_generic_prototype(context,
+                                                        (GIBoxedInfo*) interface_info));
     proto_priv = priv_from_js(context, proto);
 
     /* If we can't directly copy from the source object we need
      * to construct a new temporary object.
      */
     if (!boxed_get_copy_source(context, proto_priv, value, &source_priv)) {
-        JSObject *tmp_object = gjs_construct_object_dynamic(context, proto, 1, &value);
+        JS::RootedObject tmp_object(context,
+                                    gjs_construct_object_dynamic(context, proto, 1, &value));
         if (!tmp_object)
             return false;
 
@@ -893,7 +898,7 @@ to_string_func(JSContext *context,
                JS::Value *vp)
 {
     JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
-    JSObject *obj = rec.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, rec.thisv().toObjectOrNull());
 
     Boxed *priv;
     bool ret = false;
@@ -1196,7 +1201,6 @@ gjs_boxed_from_c_struct(JSContext             *context,
                         GjsBoxedCreationFlags  flags)
 {
     JSObject *obj;
-    JSObject *proto;
     Boxed *priv;
     Boxed *proto_priv;
 
@@ -1207,7 +1211,7 @@ gjs_boxed_from_c_struct(JSContext             *context,
                       "Wrapping struct %s %p with JSObject",
                       g_base_info_get_name((GIBaseInfo *)info), gboxed);
 
-    proto = gjs_lookup_generic_prototype(context, info);
+    JS::RootedObject proto(context, gjs_lookup_generic_prototype(context, info));
     proto_priv = priv_from_js(context, proto);
 
     obj = JS_NewObjectWithGivenProto(context,
@@ -1248,8 +1252,8 @@ gjs_boxed_from_c_struct(JSContext             *context,
 }
 
 void*
-gjs_c_struct_from_boxed(JSContext    *context,
-                        JSObject     *obj)
+gjs_c_struct_from_boxed(JSContext       *context,
+                        JS::HandleObject obj)
 {
     Boxed *priv;
 
@@ -1264,11 +1268,11 @@ gjs_c_struct_from_boxed(JSContext    *context,
 }
 
 bool
-gjs_typecheck_boxed(JSContext     *context,
-                    JSObject      *object,
-                    GIStructInfo  *expected_info,
-                    GType          expected_type,
-                    bool           throw_error)
+gjs_typecheck_boxed(JSContext       *context,
+                    JS::HandleObject object,
+                    GIStructInfo    *expected_info,
+                    GType            expected_type,
+                    bool             throw_error)
 {
     Boxed *priv;
     bool result;
diff --git a/gi/boxed.h b/gi/boxed.h
index f9cfcae..698ed59 100644
--- a/gi/boxed.h
+++ b/gi/boxed.h
@@ -47,13 +47,13 @@ void      gjs_define_boxed_class       (JSContext             *context,
 JSObject* gjs_lookup_boxed_prototype   (JSContext             *context,
                                         GIBoxedInfo           *info);
 void*     gjs_c_struct_from_boxed      (JSContext             *context,
-                                        JSObject              *obj);
+                                        JS::HandleObject       obj);
 JSObject* gjs_boxed_from_c_struct      (JSContext             *context,
                                         GIStructInfo          *info,
                                         void                  *gboxed,
                                         GjsBoxedCreationFlags  flags);
 bool      gjs_typecheck_boxed          (JSContext             *context,
-                                        JSObject              *obj,
+                                        JS::HandleObject       obj,
                                         GIStructInfo          *expected_info,
                                         GType                  expected_type,
                                         bool                   throw_error);
diff --git a/gi/function.cpp b/gi/function.cpp
index fe650ad..123eb55 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -537,10 +537,10 @@ get_length_from_arg (GArgument *arg, GITypeTag tag)
 }
 
 static bool
-gjs_fill_method_instance (JSContext  *context,
-                          JSObject   *obj,
-                          Function   *function,
-                          GIArgument *out_arg)
+gjs_fill_method_instance(JSContext       *context,
+                         JS::HandleObject obj,
+                         Function        *function,
+                         GIArgument      *out_arg)
 {
     GIBaseInfo *container = g_base_info_get_container((GIBaseInfo *) function->info);
     GIInfoType type = g_base_info_get_type(container);
@@ -665,13 +665,13 @@ gjs_fill_method_instance (JSContext  *context,
  * providing a @r_value argument.
  */
 static bool
-gjs_invoke_c_function(JSContext      *context,
-                      Function       *function,
-                      JSObject       *obj, /* "this" object */
-                      unsigned        js_argc,
-                      JS::Value      *js_argv,
-                      JS::Value      *js_rval,
-                      GArgument      *r_value)
+gjs_invoke_c_function(JSContext       *context,
+                      Function        *function,
+                      JS::HandleObject obj, /* "this" object */
+                      unsigned         js_argc,
+                      JS::Value       *js_argv,
+                      JS::Value       *js_rval,
+                      GArgument       *r_value)
 {
     /* These first four are arrays which hold argument pointers.
      * @in_arg_cvalues: C values which are passed on input (in or inout)
@@ -1300,8 +1300,8 @@ function_call(JSContext *context,
               JS::Value *vp)
 {
     JS::CallArgs js_argv = JS::CallArgsFromVp (js_argc, vp);
-    JSObject *object = js_argv.thisv().toObjectOrNull();
-    JSObject *callee = &js_argv.callee();
+    JS::RootedObject object(context, js_argv.thisv().toObjectOrNull()),
+        callee(context, &js_argv.callee());
 
     bool success;
     Function *priv;
@@ -1309,8 +1309,8 @@ function_call(JSContext *context,
 
     priv = priv_from_js(context, callee);
     gjs_debug_marshal(GJS_DEBUG_GFUNCTION,
-                      "Call callee %p priv %p this obj %p %s", callee, priv,
-                      object,
+                      "Call callee %p priv %p this obj %p %s", callee.get(),
+                      priv, object.get(),
                       JS_GetTypeName(context, JS_TypeOfValue(context, JS::ObjectOrNullValue(object))));
 
     if (priv == NULL)
@@ -1401,7 +1401,6 @@ function_to_string (JSContext *context,
     Function *priv;
     gchar *string;
     bool free;
-    JSObject *self;
     JS::Value retval;
     bool ret = false;
     int i, n_args, n_jsargs;
@@ -1414,7 +1413,7 @@ function_to_string (JSContext *context,
         gjs_throw(context, "this cannot be null");
         return false;
     }
-    self = &rec.thisv().toObject();
+    JS::RootedObject self(context, &rec.thisv().toObject());
 
     priv = priv_from_js (context, self);
     if (priv == NULL) {
@@ -1661,7 +1660,6 @@ function_new(JSContext      *context,
              GType           gtype,
              GICallableInfo *info)
 {
-    JSObject *function;
     JSObject *global;
     Function *priv;
     JSBool found;
@@ -1709,7 +1707,8 @@ function_new(JSContext      *context,
                   gjs_function_class.name, prototype);
     }
 
-    function = JS_NewObject(context, &gjs_function_class, NULL, global);
+    JS::RootedObject function(context,
+                              JS_NewObject(context, &gjs_function_class, NULL, global));
     if (function == NULL) {
         gjs_debug(GJS_DEBUG_GFUNCTION, "Failed to construct function");
         return NULL;
@@ -1724,7 +1723,8 @@ function_new(JSContext      *context,
     JS_SetPrivate(function, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_GFUNCTION,
-                        "function constructor, obj %p priv %p", function, priv);
+                        "function constructor, obj %p priv %p", function.get(),
+                        priv);
 
     if (!init_cached_function_data(context, priv, gtype, (GICallableInfo *)info))
       return NULL;
@@ -1781,12 +1781,12 @@ gjs_define_function(JSContext      *context,
 
 
 bool
-gjs_invoke_c_function_uncached (JSContext      *context,
-                                GIFunctionInfo *info,
-                                JSObject       *obj,
-                                unsigned        argc,
-                                JS::Value      *argv,
-                                JS::Value      *rval)
+gjs_invoke_c_function_uncached(JSContext       *context,
+                               GIFunctionInfo  *info,
+                               JS::HandleObject obj,
+                               unsigned         argc,
+                               JS::Value       *argv,
+                               JS::Value       *rval)
 {
   Function function;
   bool result;
@@ -1801,12 +1801,12 @@ gjs_invoke_c_function_uncached (JSContext      *context,
 }
 
 bool
-gjs_invoke_constructor_from_c (JSContext      *context,
-                               JSObject       *constructor,
-                               JSObject       *obj,
-                               unsigned        argc,
-                               JS::Value      *argv,
-                               GArgument      *rvalue)
+gjs_invoke_constructor_from_c(JSContext       *context,
+                              JS::HandleObject constructor,
+                              JS::HandleObject obj,
+                              unsigned         argc,
+                              JS::Value       *argv,
+                              GArgument       *rvalue)
 {
     Function *priv;
 
diff --git a/gi/function.h b/gi/function.h
index 48469a4..f86b815 100644
--- a/gi/function.h
+++ b/gi/function.h
@@ -67,19 +67,19 @@ JSObject* gjs_define_function   (JSContext      *context,
                                  GType           gtype,
                                  GICallableInfo *info);
 
-bool      gjs_invoke_c_function_uncached (JSContext      *context,
-                                          GIFunctionInfo *info,
-                                          JSObject       *obj,
-                                          unsigned        argc,
-                                          JS::Value      *argv,
-                                          JS::Value      *rval);
+bool      gjs_invoke_c_function_uncached(JSContext       *context,
+                                         GIFunctionInfo  *info,
+                                         JS::HandleObject obj,
+                                         unsigned         argc,
+                                         JS::Value       *argv,
+                                         JS::Value       *rval);
 
-bool      gjs_invoke_constructor_from_c (JSContext      *context,
-                                         JSObject       *constructor,
-                                         JSObject       *obj,
-                                         unsigned        argc,
-                                         JS::Value      *argv,
-                                         GArgument      *rvalue);
+bool      gjs_invoke_constructor_from_c(JSContext       *context,
+                                        JS::HandleObject constructor,
+                                        JS::HandleObject obj,
+                                        unsigned         argc,
+                                        JS::Value       *argv,
+                                        GArgument       *rvalue);
 
 void     gjs_init_cinvoke_profiling (void);
 
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index 36787e3..430c348 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -132,14 +132,14 @@ static inline Fundamental *
 proto_priv_from_js(JSContext *context,
                    JSObject  *obj)
 {
-    JSObject *proto;
-    JS_GetPrototype(context, obj, &proto);
+    JS::RootedObject proto(context);
+    JS_GetPrototype(context, obj, proto.address());
     return (Fundamental*) priv_from_js(context, proto);
 }
 
 static FundamentalInstance *
-init_fundamental_instance(JSContext *context,
-                          JSObject  *object)
+init_fundamental_instance(JSContext       *context,
+                          JS::HandleObject object)
 {
     Fundamental *proto_priv;
     FundamentalInstance *priv;
@@ -155,7 +155,7 @@ init_fundamental_instance(JSContext *context,
 
     gjs_debug_lifecycle(GJS_DEBUG_GFUNDAMENTAL,
                         "fundamental instance constructor, obj %p priv %p",
-                        object, priv);
+                        object.get(), priv);
 
     proto_priv = proto_priv_from_js(context, object);
     g_assert(proto_priv != NULL);
@@ -168,10 +168,10 @@ init_fundamental_instance(JSContext *context,
 }
 
 static void
-associate_js_instance_to_fundamental(JSContext *context,
-                                     JSObject  *object,
-                                     void      *gfundamental,
-                                     bool       owned_ref)
+associate_js_instance_to_fundamental(JSContext       *context,
+                                     JS::HandleObject object,
+                                     void            *gfundamental,
+                                     bool             owned_ref)
 {
     FundamentalInstance *priv;
 
@@ -183,7 +183,7 @@ associate_js_instance_to_fundamental(JSContext *context,
 
     gjs_debug_lifecycle(GJS_DEBUG_GFUNDAMENTAL,
                         "associated JSObject %p with fundamental %p",
-                        object, gfundamental);
+                        object.get(), gfundamental);
 
     if (!owned_ref)
         priv->prototype->ref_function(gfundamental);
@@ -382,14 +382,13 @@ fundamental_instance_new_resolve(JSContext  *context,
 static bool
 fundamental_invoke_constructor(FundamentalInstance *priv,
                                JSContext           *context,
-                               JSObject            *obj,
+                               JS::HandleObject     obj,
                                unsigned             argc,
                                JS::Value           *argv,
                                GArgument           *rvalue)
 {
     JS::Value js_constructor, js_constructor_func;
     jsid constructor_const;
-    bool ret = false;
 
     constructor_const = gjs_context_get_const_string(context, GJS_STRING_CONSTRUCTOR);
     if (!gjs_object_require_property(context, obj, NULL,
@@ -399,7 +398,7 @@ fundamental_invoke_constructor(FundamentalInstance *priv,
                    "Couldn't find a constructor for type %s.%s",
                    g_base_info_get_namespace((GIBaseInfo*) priv->prototype->info),
                    g_base_info_get_name((GIBaseInfo*) priv->prototype->info));
-        goto end;
+        return false;
     }
 
     if (!gjs_object_require_property(context, js_constructor.toObjectOrNull(), NULL,
@@ -408,13 +407,11 @@ fundamental_invoke_constructor(FundamentalInstance *priv,
                    "Couldn't find a constructor for type %s.%s",
                    g_base_info_get_namespace((GIBaseInfo*) priv->prototype->info),
                    g_base_info_get_name((GIBaseInfo*) priv->prototype->info));
-        goto end;
+        return false;
     }
 
-    ret = gjs_invoke_constructor_from_c(context, js_constructor_func.toObjectOrNull(), obj, argc, argv, 
rvalue);
-
- end:
-    return ret;
+    JS::RootedObject constructor(context, js_constructor_func.toObjectOrNull());
+    return gjs_invoke_constructor_from_c(context, constructor, obj, argc, argv, rvalue);
 }
 
 /* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
@@ -438,7 +435,7 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(fundamental_instance)
 
     gjs_debug_lifecycle(GJS_DEBUG_GFUNDAMENTAL,
                         "fundamental constructor, obj %p priv %p",
-                        object, priv);
+                        object.get(), priv);
 
     if (!fundamental_invoke_constructor(priv, context, object, argc, argv.array(), &ret_value))
         return false;
@@ -501,7 +498,7 @@ to_string_func(JSContext *context,
                JS::Value *vp)
 {
     JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
-    JSObject *obj = rec.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, rec.thisv().toObjectOrNull());
 
     FundamentalInstance *priv;
     bool ret = false;
@@ -753,12 +750,11 @@ gjs_object_from_g_fundamental(JSContext    *context,
                               void         *gfundamental)
 {
     JSObject *proto;
-    JSObject *object;
 
     if (gfundamental == NULL)
         return NULL;
 
-    object = _fundamental_lookup_object(gfundamental);
+    JS::RootedObject object(context, _fundamental_lookup_object(gfundamental));
     if (object)
         return object;
 
@@ -791,11 +787,11 @@ gjs_fundamental_from_g_value(JSContext    *context,
                              const GValue *value,
                              GType         gtype)
 {
-    JSObject *proto;
     Fundamental *proto_priv;
     void *fobj;
 
-    proto = gjs_lookup_fundamental_prototype_from_gtype(context, gtype);
+    JS::RootedObject proto(context,
+                           gjs_lookup_fundamental_prototype_from_gtype(context, gtype));
     if (!proto)
         return NULL;
 
@@ -812,8 +808,8 @@ gjs_fundamental_from_g_value(JSContext    *context,
 }
 
 void*
-gjs_g_fundamental_from_object(JSContext *context,
-                              JSObject  *obj)
+gjs_g_fundamental_from_object(JSContext       *context,
+                              JS::HandleObject obj)
 {
     FundamentalInstance *priv;
 
@@ -824,7 +820,7 @@ gjs_g_fundamental_from_object(JSContext *context,
 
     if (priv == NULL) {
         gjs_throw(context,
-                  "No introspection information for %p", obj);
+                  "No introspection information for %p", obj.get());
         return NULL;
     }
 
@@ -840,18 +836,18 @@ gjs_g_fundamental_from_object(JSContext *context,
 }
 
 bool
-gjs_typecheck_is_fundamental(JSContext     *context,
-                             JSObject      *object,
-                             bool           throw_error)
+gjs_typecheck_is_fundamental(JSContext       *context,
+                             JS::HandleObject object,
+                             bool             throw_error)
 {
     return do_base_typecheck(context, object, throw_error);
 }
 
 bool
-gjs_typecheck_fundamental(JSContext *context,
-                          JSObject  *object,
-                          GType      expected_gtype,
-                          bool       throw_error)
+gjs_typecheck_fundamental(JSContext       *context,
+                          JS::HandleObject object,
+                          GType            expected_gtype,
+                          bool             throw_error)
 {
     FundamentalInstance *priv;
     bool result;
@@ -901,11 +897,9 @@ void *
 gjs_fundamental_ref(JSContext     *context,
                     void          *gfundamental)
 {
-    JSObject *proto;
     Fundamental *proto_priv;
-
-    proto = gjs_lookup_fundamental_prototype_from_gtype(context,
-                                                        G_TYPE_FROM_INSTANCE(gfundamental));
+    JS::RootedObject proto(context,
+        gjs_lookup_fundamental_prototype_from_gtype(context, G_TYPE_FROM_INSTANCE(gfundamental)));
 
     proto_priv = (Fundamental *) priv_from_js(context, proto);
 
@@ -916,11 +910,9 @@ void
 gjs_fundamental_unref(JSContext    *context,
                       void         *gfundamental)
 {
-    JSObject *proto;
     Fundamental *proto_priv;
-
-    proto = gjs_lookup_fundamental_prototype_from_gtype(context,
-                                                        G_TYPE_FROM_INSTANCE(gfundamental));
+    JS::RootedObject proto(context,
+        gjs_lookup_fundamental_prototype_from_gtype(context, G_TYPE_FROM_INSTANCE(gfundamental)));
 
     proto_priv = (Fundamental *) priv_from_js(context, proto);
 
diff --git a/gi/fundamental.h b/gi/fundamental.h
index 31bd2d0..dec8fcf 100644
--- a/gi/fundamental.h
+++ b/gi/fundamental.h
@@ -40,15 +40,19 @@ bool      gjs_define_fundamental_class       (JSContext     *context,
 JSObject* gjs_object_from_g_fundamental      (JSContext     *context,
                                               GIObjectInfo  *info,
                                               void          *fobj);
-void*     gjs_g_fundamental_from_object      (JSContext     *context,
-                                              JSObject      *obj);
+
+void     *gjs_g_fundamental_from_object(JSContext       *context,
+                                        JS::HandleObject obj);
+
 JSObject *gjs_fundamental_from_g_value       (JSContext     *context,
                                               const GValue  *value,
                                               GType          gtype);
-bool      gjs_typecheck_fundamental          (JSContext     *context,
-                                              JSObject      *object,
-                                              GType          expected_gtype,
-                                              bool           throw_error);
+
+bool      gjs_typecheck_fundamental(JSContext       *context,
+                                    JS::HandleObject object,
+                                    GType            expected_gtype,
+                                    bool             throw_error);
+
 bool      gjs_typecheck_is_fundamental       (JSContext     *context,
                                               JSObject      *object,
                                               bool           throw_error);
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index a6c6ec9..5db3300 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -60,7 +60,6 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(error)
     GJS_NATIVE_CONSTRUCTOR_VARIABLES(error)
     Error *priv;
     Error *proto_priv;
-    JSObject *proto;
     jsid message_name, code_name;
     JS::Value v_message, v_code;
     gchar *message;
@@ -82,10 +81,12 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(error)
 
     gjs_debug_lifecycle(GJS_DEBUG_GERROR,
                         "GError constructor, obj %p priv %p",
-                        object, priv);
+                        object.get(), priv);
 
-    JS_GetPrototype(context, object, &proto);
-    gjs_debug_lifecycle(GJS_DEBUG_GERROR, "GError instance __proto__ is %p", proto);
+    JS::RootedObject proto(context);
+    JS_GetPrototype(context, object, proto.address());
+    gjs_debug_lifecycle(GJS_DEBUG_GERROR, "GError instance __proto__ is %p",
+                        proto.get());
 
     /* If we're the prototype, then post-construct we'll fill in priv->info.
      * If we are not the prototype, though, then we'll get ->info from the
@@ -211,7 +212,6 @@ error_to_string(JSContext *context,
                 JS::Value *vp)
 {
     JS::Value v_self;
-    JSObject *self;
     Error *priv;
     JS::Value v_out;
     gchar *descr;
@@ -225,7 +225,7 @@ error_to_string(JSContext *context,
         return false;
     }
 
-    self = &v_self.toObject();
+    JS::RootedObject self(context, &v_self.toObject());
     priv = priv_from_js(context, self);
 
     if (priv == NULL)
@@ -290,7 +290,8 @@ error_constructor_value_of(JSContext *context,
         return false;
     }
 
-    priv = priv_from_js(context, &v_prototype.toObject());
+    JS::RootedObject prototype(context, &v_prototype.toObject());
+    priv = priv_from_js(context, prototype);
 
     if (priv == NULL)
         return false;
@@ -473,7 +474,6 @@ gjs_error_from_gerror(JSContext             *context,
                       bool                   add_stack)
 {
     JSObject *obj;
-    JSObject *proto;
     Error *priv;
     Error *proto_priv;
     GIEnumInfo *info;
@@ -500,7 +500,7 @@ gjs_error_from_gerror(JSContext             *context,
                       "Wrapping struct %s with JSObject",
                       g_base_info_get_name((GIBaseInfo *)info));
 
-    proto = gjs_lookup_generic_prototype(context, info);
+    JS::RootedObject proto(context, gjs_lookup_generic_prototype(context, info));
     proto_priv = priv_from_js(context, proto);
 
     obj = JS_NewObjectWithGivenProto(context,
@@ -522,8 +522,8 @@ gjs_error_from_gerror(JSContext             *context,
 }
 
 GError*
-gjs_gerror_from_error(JSContext    *context,
-                      JSObject     *obj)
+gjs_gerror_from_error(JSContext       *context,
+                      JS::HandleObject obj)
 {
     Error *priv;
 
@@ -553,9 +553,9 @@ gjs_gerror_from_error(JSContext    *context,
 }
 
 bool
-gjs_typecheck_gerror (JSContext *context,
-                      JSObject  *obj,
-                      bool       throw_error)
+gjs_typecheck_gerror (JSContext       *context,
+                      JS::HandleObject obj,
+                      bool             throw_error)
 {
     if (gjs_typecheck_boxed (context, obj, NULL, G_TYPE_ERROR, false))
         return true;
diff --git a/gi/gerror.h b/gi/gerror.h
index 7c9fde0..46e2862 100644
--- a/gi/gerror.h
+++ b/gi/gerror.h
@@ -36,12 +36,12 @@ void      gjs_define_error_class       (JSContext             *context,
                                         JSObject              *in_object,
                                         GIEnumInfo            *info);
 GError*   gjs_gerror_from_error        (JSContext             *context,
-                                        JSObject              *obj);
+                                        JS::HandleObject       obj);
 JSObject* gjs_error_from_gerror        (JSContext             *context,
                                         GError                *gerror,
                                         bool                   add_stack);
 bool      gjs_typecheck_gerror         (JSContext             *context,
-                                        JSObject              *obj,
+                                        JS::HandleObject       obj,
                                         bool                   throw_error);
 
 G_END_DECLS
diff --git a/gi/gtype.cpp b/gi/gtype.cpp
index f148a78..a9fca23 100644
--- a/gi/gtype.cpp
+++ b/gi/gtype.cpp
@@ -67,7 +67,7 @@ to_string_func(JSContext *context,
                JS::Value *vp)
 {
     JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
-    JSObject *obj = rec.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, rec.thisv().toObjectOrNull());
 
     GType gtype;
     gchar *strval;
@@ -157,9 +157,9 @@ gjs_gtype_create_gtype_wrapper (JSContext *context,
 }
 
 static GType
-_gjs_gtype_get_actual_gtype (JSContext *context,
-                             JSObject  *object,
-                             int        recurse)
+_gjs_gtype_get_actual_gtype(JSContext       *context,
+                            JS::HandleObject object,
+                            int              recurse)
 {
     GType gtype = G_TYPE_INVALID;
     JS::Value gtype_val = JS::UndefinedValue();
@@ -181,8 +181,10 @@ _gjs_gtype_get_actual_gtype (JSContext *context,
             goto out;
     }
 
-    if (recurse > 0 && gtype_val.isObject())
-        gtype = _gjs_gtype_get_actual_gtype(context, &gtype_val.toObject(), recurse - 1);
+    if (recurse > 0 && gtype_val.isObject()) {
+        JS::RootedObject gtype_obj(context, &gtype_val.toObject());
+        gtype = _gjs_gtype_get_actual_gtype(context, gtype_obj, recurse - 1);
+    }
 
  out:
     JS_EndRequest(context);
@@ -190,8 +192,8 @@ _gjs_gtype_get_actual_gtype (JSContext *context,
 }
 
 GType
-gjs_gtype_get_actual_gtype (JSContext *context,
-                            JSObject  *object)
+gjs_gtype_get_actual_gtype(JSContext       *context,
+                           JS::HandleObject object)
 {
     /* 2 means: recurse at most three times (including this
        call).
@@ -206,7 +208,7 @@ gjs_gtype_get_actual_gtype (JSContext *context,
 
 bool
 gjs_typecheck_gtype (JSContext             *context,
-                     JSObject              *obj,
+                     JS::HandleObject       obj,
                      bool                   throw_error)
 {
     return do_base_typecheck(context, obj, throw_error);
diff --git a/gi/gtype.h b/gi/gtype.h
index c3b999b..f9fa179 100644
--- a/gi/gtype.h
+++ b/gi/gtype.h
@@ -40,11 +40,11 @@ JS::Value   gjs_gtype_create_proto         (JSContext       *context,
 JSObject * gjs_gtype_create_gtype_wrapper (JSContext *context,
                                            GType      gtype);
 
-GType      gjs_gtype_get_actual_gtype (JSContext *context,
-                                       JSObject  *object);
+GType       gjs_gtype_get_actual_gtype(JSContext       *context,
+                                       JS::HandleObject object);
 
 bool        gjs_typecheck_gtype         (JSContext             *context,
-                                         JSObject              *obj,
+                                         JS::HandleObject       obj,
                                          bool                   throw_error);
 
 const char *gjs_get_names_from_gtype_and_gi_info(GType        gtype,
diff --git a/gi/keep-alive.cpp b/gi/keep-alive.cpp
index ae98a44..900562a 100644
--- a/gi/keep-alive.cpp
+++ b/gi/keep-alive.cpp
@@ -178,7 +178,6 @@ JSObject*
 gjs_keep_alive_new(JSContext *context)
 {
     KeepAlive *priv;
-    JSObject *keep_alive = NULL;
     JSObject *global;
     JSBool found;
 
@@ -190,14 +189,14 @@ gjs_keep_alive_new(JSContext *context)
 
     g_assert(context != NULL);
 
-    JS_BeginRequest(context);
+    JSAutoRequest ar(context);
 
     global = gjs_get_import_global(context);
 
     g_assert(global != NULL);
 
     if (!JS_HasProperty(context, global, gjs_keep_alive_class.name, &found))
-        goto out;
+        return NULL;
 
     if (!found) {
         JSObject *prototype;
@@ -239,7 +238,8 @@ gjs_keep_alive_new(JSContext *context)
               "Creating new keep-alive object for context %p global %p",
               context, global);
 
-    keep_alive = JS_NewObject(context, &gjs_keep_alive_class, NULL, global);
+    JS::RootedObject keep_alive(context,
+                                JS_NewObject(context, &gjs_keep_alive_class, NULL, global));
     if (keep_alive == NULL) {
         gjs_log_exception(context);
         g_error("Failed to create keep_alive object");
@@ -252,10 +252,8 @@ gjs_keep_alive_new(JSContext *context)
     JS_SetPrivate(keep_alive, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_KEEP_ALIVE,
-                        "keep_alive constructor, obj %p priv %p", keep_alive, priv);
-
- out:
-    JS_EndRequest(context);
+                        "keep_alive constructor, obj %p priv %p",
+                        keep_alive.get(), priv);
 
     return keep_alive;
 }
diff --git a/gi/ns.cpp b/gi/ns.cpp
index 22d5d71..54fb1cf 100644
--- a/gi/ns.cpp
+++ b/gi/ns.cpp
@@ -203,7 +203,6 @@ static JSObject*
 ns_new(JSContext    *context,
        const char   *ns_name)
 {
-    JSObject *ns;
     JSObject *global;
     Ns *priv;
     JSBool found;
@@ -244,7 +243,7 @@ ns_new(JSContext    *context,
                   gjs_ns_class.name, prototype);
     }
 
-    ns = JS_NewObject(context, &gjs_ns_class, NULL, global);
+    JS::RootedObject ns(context, JS_NewObject(context, &gjs_ns_class, NULL, global));
     if (ns == NULL)
         g_error("No memory to create ns object");
 
@@ -255,7 +254,8 @@ ns_new(JSContext    *context,
     g_assert(priv_from_js(context, ns) == NULL);
     JS_SetPrivate(ns, priv);
 
-    gjs_debug_lifecycle(GJS_DEBUG_GNAMESPACE, "ns constructor, obj %p priv %p", ns, priv);
+    gjs_debug_lifecycle(GJS_DEBUG_GNAMESPACE, "ns constructor, obj %p priv %p",
+                        ns.get(), priv);
 
     priv = priv_from_js(context, ns);
     priv->gi_namespace = g_strdup(ns_name);
diff --git a/gi/object.cpp b/gi/object.cpp
index 2a0eacb..d07ebfc 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -23,6 +23,7 @@
 
 #include <config.h>
 
+#include <memory>
 #include <string.h>
 
 #include <gjs/gi.h>
@@ -242,8 +243,8 @@ static inline ObjectInstance *
 proto_priv_from_js(JSContext *context,
                    JSObject  *obj)
 {
-    JSObject *proto;
-    JS_GetPrototype(context, obj, &proto);
+    JS::RootedObject proto(context);
+    JS_GetPrototype(context, obj, proto.address());
     return priv_from_js(context, proto);
 }
 
@@ -1147,8 +1148,8 @@ gjs_object_prepare_shutdown (JSContext *context)
 }
 
 static ObjectInstance *
-init_object_private (JSContext *context,
-                     JSObject  *object)
+init_object_private (JSContext       *context,
+                     JS::HandleObject object)
 {
     ObjectInstance *proto_priv;
     ObjectInstance *priv;
@@ -1163,7 +1164,8 @@ init_object_private (JSContext *context,
     JS_SetPrivate(object, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_GOBJECT,
-                        "obj instance constructor, obj %p priv %p", object, priv);
+                        "obj instance constructor, obj %p priv %p",
+                        object.get(), priv);
 
     proto_priv = proto_priv_from_js(context, object);
     g_assert(proto_priv != NULL);
@@ -1178,9 +1180,9 @@ init_object_private (JSContext *context,
 }
 
 static void
-associate_js_gobject (JSContext      *context,
-                      JSObject       *object,
-                      GObject        *gobj)
+associate_js_gobject (JSContext       *context,
+                      JS::HandleObject object,
+                      GObject         *gobj)
 {
     ObjectInstance *priv;
 
@@ -1240,25 +1242,24 @@ disassociate_js_gobject (GObject   *gobj)
 }
 
 static bool
-object_instance_init (JSContext *context,
-                      JSObject **object,
-                      unsigned   argc,
-                      JS::Value *argv)
+object_instance_init (JSContext              *context,
+                      JS::MutableHandleObject object,
+                      unsigned                argc,
+                      JS::Value              *argv)
 {
     ObjectInstance *priv;
     GType gtype;
     GParameter *params;
     int n_params;
     GTypeQuery query;
-    JSObject *old_jsobj;
     GObject *gobj;
 
-    priv = (ObjectInstance *) JS_GetPrivate(*object);
+    priv = (ObjectInstance *) JS_GetPrivate(object);
 
     gtype = priv->gtype;
     g_assert(gtype != G_TYPE_NONE);
 
-    if (!object_instance_props_to_g_parameters(context, *object, argc, argv,
+    if (!object_instance_props_to_g_parameters(context, object, argc, argv,
                                                gtype,
                                                &params, &n_params)) {
         return false;
@@ -1268,15 +1269,19 @@ object_instance_init (JSContext *context,
        will be popped in gjs_object_custom_init() later
        down.
     */
-    if (g_type_get_qdata(gtype, gjs_is_custom_type_quark()))
-        object_init_list = g_slist_prepend(object_init_list, *object);
+    if (g_type_get_qdata(gtype, gjs_is_custom_type_quark())) {
+        // COMPAT: Replace with JS::PersistentRootedObject in mozjs31
+        object_init_list = g_slist_prepend(object_init_list, object.get());
+        JS_AddNamedObjectRoot(context, (JSObject **) &object_init_list->data,
+                              "object_init_list");
+    }
 
     gobj = (GObject*) g_object_newv(gtype, n_params, params);
 
     free_g_params(params, n_params);
 
-    old_jsobj = peek_js_obj(gobj);
-    if (old_jsobj != NULL && old_jsobj != *object) {
+    JS::RootedObject old_jsobj(context, peek_js_obj(gobj));
+    if (old_jsobj != NULL && old_jsobj != object) {
         /* g_object_newv returned an object that's already tracked by a JS
          * object. Let's assume this is a singleton like IBus.IBus and return
          * the existing JS wrapper object.
@@ -1286,7 +1291,7 @@ object_instance_init (JSContext *context,
          * we're not actually using it, so just let it get collected. Avoiding
          * this would require a non-trivial amount of work.
          * */
-        *object = old_jsobj;
+        object.set(old_jsobj);
         g_object_unref(gobj); /* We already own a reference */
         gobj = NULL;
         goto out;
@@ -1312,7 +1317,7 @@ object_instance_init (JSContext *context,
     }
 
     if (priv->gobj == NULL)
-        associate_js_gobject(context, *object, gobj);
+        associate_js_gobject(context, object, gobj);
     /* We now have both a ref and a toggle ref, we only want the
      * toggle ref. This may immediately remove the GC root
      * we just added, since refcount may drop to 1.
@@ -1564,7 +1569,7 @@ real_connect_func(JSContext *context,
                   bool       after)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj = argv.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());
 
     ObjectInstance *priv;
     GClosure *closure;
@@ -1579,7 +1584,7 @@ real_connect_func(JSContext *context,
         return false;
 
     priv = priv_from_js(context, obj);
-    gjs_debug_gsignal("connect obj %p priv %p argc %d", obj, priv, argc);
+    gjs_debug_gsignal("connect obj %p priv %p argc %d", obj.get(), priv, argc);
     if (priv == NULL) {
         throw_priv_is_null_error(context);
         return false; /* wrong class passed in */
@@ -1666,7 +1671,7 @@ emit_func(JSContext *context,
           JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj = argv.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());
 
     ObjectInstance *priv;
     guint signal_id;
@@ -1684,7 +1689,7 @@ emit_func(JSContext *context,
         return false;
 
     priv = priv_from_js(context, obj);
-    gjs_debug_gsignal("emit obj %p priv %p argc %d", obj, priv, argc);
+    gjs_debug_gsignal("emit obj %p priv %p argc %d", obj.get(), priv, argc);
 
     if (priv == NULL) {
         throw_priv_is_null_error(context);
@@ -1789,7 +1794,7 @@ to_string_func(JSContext *context,
                JS::Value *vp)
 {
     JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
-    JSObject *obj = rec.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, rec.thisv().toObjectOrNull());
 
     ObjectInstance *priv;
     bool ret = false;
@@ -1841,7 +1846,7 @@ init_func (JSContext *context,
            JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj = argv.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());
 
     bool ret;
 
@@ -2061,13 +2066,12 @@ JSObject*
 gjs_object_from_g_object(JSContext    *context,
                          GObject      *gobj)
 {
-    JSObject *obj;
     JSObject *global;
 
     if (gobj == NULL)
         return NULL;
 
-    obj = peek_js_obj(gobj);
+    JS::RootedObject obj(context, peek_js_obj(gobj));
 
     if (obj == NULL) {
         /* We have to create a wrapper */
@@ -2104,8 +2108,8 @@ gjs_object_from_g_object(JSContext    *context,
 }
 
 GObject*
-gjs_g_object_from_object(JSContext    *context,
-                         JSObject     *obj)
+gjs_g_object_from_object(JSContext       *context,
+                         JS::HandleObject obj)
 {
     ObjectInstance *priv;
 
@@ -2117,18 +2121,18 @@ gjs_g_object_from_object(JSContext    *context,
 }
 
 bool
-gjs_typecheck_is_object(JSContext     *context,
-                        JSObject      *object,
-                        bool           throw_error)
+gjs_typecheck_is_object(JSContext       *context,
+                        JS::HandleObject object,
+                        bool             throw_error)
 {
     return do_base_typecheck(context, object, throw_error);
 }
 
 bool
-gjs_typecheck_object(JSContext     *context,
-                     JSObject      *object,
-                     GType          expected_type,
-                     bool           throw_error)
+gjs_typecheck_object(JSContext       *context,
+                     JS::HandleObject object,
+                     GType            expected_type,
+                     bool             throw_error)
 {
     ObjectInstance *priv;
     bool result;
@@ -2267,7 +2271,7 @@ gjs_hook_up_vfunc(JSContext *cx,
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
     gchar *name;
-    JSObject *object;
+    JS::RootedObject object(cx);
     JSObject *function;
     ObjectInstance *priv;
     GType gtype, info_gtype;
@@ -2278,7 +2282,7 @@ gjs_hook_up_vfunc(JSContext *cx,
 
     if (!gjs_parse_call_args(cx, "hook_up_vfunc",
                         "oso", argv,
-                        "object", &object,
+                        "object", object.address(),
                         "name", &name,
                         "function", &function))
         return false;
@@ -2520,14 +2524,14 @@ gjs_override_property(JSContext *cx,
 {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
     gchar *name = NULL;
-    JSObject *type;
+    JS::RootedObject type(cx);
     GParamSpec *pspec;
     GParamSpec *new_pspec;
     GType gtype;
 
     if (!gjs_parse_call_args(cx, "override_property", "so", args,
                              "name", &name,
-                             "type", &type))
+                             "type", type.address()))
         return false;
 
     if ((gtype = gjs_gtype_get_actual_gtype(cx, type)) == G_TYPE_INVALID) {
@@ -2622,14 +2626,16 @@ gjs_object_custom_init(GTypeInstance *instance,
 {
     GjsContext *gjs_context;
     JSContext *context;
-    JSObject *object;
     ObjectInstance *priv;
     JS::Value v, r;
 
     if (!object_init_list)
       return;
 
-    object = (JSObject*) object_init_list->data;
+    gjs_context = gjs_context_get_current();
+    context = (JSContext*) gjs_context_get_native_context(gjs_context);
+
+    JS::RootedObject object(context, (JSObject*) object_init_list->data);
     priv = (ObjectInstance*) JS_GetPrivate(object);
 
     if (priv->gtype != G_TYPE_FROM_INSTANCE (instance)) {
@@ -2639,12 +2645,10 @@ gjs_object_custom_init(GTypeInstance *instance,
         return;
     }
 
+    JS_RemoveObjectRoot(context, (JSObject **) &object_init_list->data);
     object_init_list = g_slist_delete_link(object_init_list,
                                            object_init_list);
 
-    gjs_context = gjs_context_get_current();
-    context = (JSContext*) gjs_context_get_native_context(gjs_context);
-
     associate_js_gobject(context, object, G_OBJECT (instance));
 
     if (!gjs_object_get_property_const(context, object,
@@ -2724,7 +2728,8 @@ get_interface_gtypes(JSContext *cx,
             return false;
         }
 
-        iface_type = gjs_gtype_get_actual_gtype(cx, &iface_val.toObject());
+        JS::RootedObject iface(cx, &iface_val.toObject());
+        iface_type = gjs_gtype_get_actual_gtype(cx, iface);
         if (iface_type == G_TYPE_INVALID) {
             gjs_throw (cx, "Invalid parameter interfaces (element %d was not a GType)", i);
             return false;
@@ -2860,7 +2865,8 @@ gjs_register_type(JSContext *cx,
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
     gchar *name;
-    JSObject *parent, *constructor, *interfaces, *properties, *module;
+    JS::RootedObject parent(cx);
+    JSObject *constructor, *interfaces, *properties, *module;
     GType instance_type, parent_type;
     GTypeQuery query;
     GTypeModule *type_module;
@@ -2887,7 +2893,7 @@ gjs_register_type(JSContext *cx,
 
     if (!gjs_parse_call_args(cx, "register_type",
                         "osoo", argv,
-                        "parent", &parent,
+                        "parent", parent.address(),
                         "name", &name,
                         "interfaces", &interfaces,
                         "properties", &properties))
@@ -2968,26 +2974,23 @@ gjs_signal_new(JSContext *cx,
                JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj;
     GType gtype;
-    gchar *signal_name = NULL;
+    char *signal_name_tmp = NULL;
     GSignalAccumulator accumulator;
     gint signal_id;
     guint i, n_parameters;
     GType *params, return_type;
-    bool ret;
 
     if (argc != 6)
         return false;
 
-    JS_BeginRequest(cx);
+    JSAutoRequest ar(cx);
 
-    if (!gjs_string_to_utf8(cx, argv[1], &signal_name)) {
-        ret = false;
-        goto out;
-    }
+    if (!gjs_string_to_utf8(cx, argv[1], &signal_name_tmp))
+        return false;
+    std::unique_ptr<char, decltype(&g_free)> signal_name(signal_name_tmp, g_free);
 
-    obj = &argv[0].toObject();
+    JS::RootedObject obj(cx, &argv[0].toObject());
     if (!gjs_typecheck_gtype(cx, obj, true))
         return false;
 
@@ -3004,34 +3007,33 @@ gjs_signal_new(JSContext *cx,
         accumulator = NULL;
     }
 
-    return_type = gjs_gtype_get_actual_gtype(cx, &argv[4].toObject());
+    JS::RootedObject gtype_obj(cx, &argv[4].toObject());
+    return_type = gjs_gtype_get_actual_gtype(cx, gtype_obj);
 
     if (accumulator == g_signal_accumulator_true_handled && return_type != G_TYPE_BOOLEAN) {
         gjs_throw (cx, "GObject.SignalAccumulator.TRUE_HANDLED can only be used with boolean signals");
-        ret = false;
-        goto out;
+        return false;
     }
 
-    if (!JS_GetArrayLength(cx, &argv[5].toObject(), &n_parameters)) {
-        ret = false;
-        goto out;
-    }
+    if (!JS_GetArrayLength(cx, &argv[5].toObject(), &n_parameters))
+        return false;
+
     params = g_newa(GType, n_parameters);
     for (i = 0; i < n_parameters; i++) {
         JS::Value gtype_val;
         if (!JS_GetElement(cx, &argv[5].toObject(), i, &gtype_val) ||
             !gtype_val.isObject()) {
             gjs_throw(cx, "Invalid signal parameter number %d", i);
-            ret = false;
-            goto out;
+            return false;
         }
 
-        params[i] = gjs_gtype_get_actual_gtype(cx, &gtype_val.toObject());
+        JS::RootedObject gtype(cx, &gtype_val.toObject());
+        params[i] = gjs_gtype_get_actual_gtype(cx, gtype);
     }
 
     gtype = gjs_gtype_get_actual_gtype(cx, obj);
 
-    signal_id = g_signal_newv(signal_name,
+    signal_id = g_signal_newv(signal_name.get(),
                               gtype,
                               (GSignalFlags) argv[2].toInt32(), /* signal_flags */
                               NULL, /* class closure */
@@ -3043,13 +3045,7 @@ gjs_signal_new(JSContext *cx,
                               params);
 
     argv.rval().setInt32(signal_id);
-    ret = true;
-
- out:
-    JS_EndRequest(cx);
-
-    free (signal_name);
-    return ret;
+    return true;
 }
 
 static JSFunctionSpec module_funcs[] = {
diff --git a/gi/object.h b/gi/object.h
index 01ca87d..4eb77a5 100644
--- a/gi/object.h
+++ b/gi/object.h
@@ -41,15 +41,18 @@ bool      gjs_lookup_object_constructor (JSContext     *context,
                                          JS::Value     *value_p);
 JSObject* gjs_object_from_g_object      (JSContext     *context,
                                          GObject       *gobj);
-GObject*  gjs_g_object_from_object      (JSContext     *context,
-                                         JSObject      *obj);
-bool      gjs_typecheck_object          (JSContext     *context,
-                                         JSObject      *obj,
-                                         GType          expected_type,
-                                         bool           throw_error);
-bool      gjs_typecheck_is_object       (JSContext     *context,
-                                         JSObject      *obj,
-                                         bool           throw_error);
+
+GObject  *gjs_g_object_from_object(JSContext       *context,
+                                   JS::HandleObject obj);
+
+bool      gjs_typecheck_object(JSContext       *context,
+                               JS::HandleObject obj,
+                               GType            expected_type,
+                               bool             throw_error);
+
+bool      gjs_typecheck_is_object(JSContext       *context,
+                                  JS::HandleObject obj,
+                                  bool             throw_error);
 
 void      gjs_object_prepare_shutdown   (JSContext     *context);
 
diff --git a/gi/param.cpp b/gi/param.cpp
index c6e08f5..934387d 100644
--- a/gi/param.cpp
+++ b/gi/param.cpp
@@ -294,8 +294,8 @@ gjs_param_from_g_param(JSContext    *context,
 }
 
 GParamSpec*
-gjs_g_param_from_param(JSContext    *context,
-                       JSObject     *obj)
+gjs_g_param_from_param(JSContext       *context,
+                       JS::HandleObject obj)
 {
     Param *priv;
 
@@ -308,10 +308,10 @@ gjs_g_param_from_param(JSContext    *context,
 }
 
 bool
-gjs_typecheck_param(JSContext     *context,
-                    JSObject      *object,
-                    GType          expected_type,
-                    bool           throw_error)
+gjs_typecheck_param(JSContext       *context,
+                    JS::HandleObject object,
+                    GType            expected_type,
+                    bool             throw_error)
 {
     Param *priv;
     bool result;
diff --git a/gi/param.h b/gi/param.h
index abf3f39..c957818 100644
--- a/gi/param.h
+++ b/gi/param.h
@@ -33,14 +33,17 @@ G_BEGIN_DECLS
 
 void        gjs_define_param_class     (JSContext  *context,
                                         JSObject   *in_object);
-GParamSpec* gjs_g_param_from_param     (JSContext  *context,
-                                        JSObject   *obj);
+
+GParamSpec *gjs_g_param_from_param (JSContext       *context,
+                                    JS::HandleObject obj);
+
 JSObject*   gjs_param_from_g_param     (JSContext  *context,
                                         GParamSpec *param);
-bool        gjs_typecheck_param        (JSContext  *context,
-                                        JSObject   *obj,
-                                        GType       expected_type,
-                                        bool        throw_error);
+
+bool        gjs_typecheck_param(JSContext       *context,
+                                JS::HandleObject obj,
+                                GType            expected_type,
+                                bool             throw_error);
 
 G_END_DECLS
 
diff --git a/gi/repo.cpp b/gi/repo.cpp
index ccd5ca8..745fd0f 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -248,7 +248,6 @@ static JSObject*
 repo_new(JSContext *context)
 {
     Repo *priv;
-    JSObject *repo;
     JSObject *global;
     JSObject *versions;
     JSObject *private_ns;
@@ -290,7 +289,7 @@ repo_new(JSContext *context)
                   gjs_repo_class.name, prototype);
     }
 
-    repo = JS_NewObject(context, &gjs_repo_class, NULL, global);
+    JS::RootedObject repo(context, JS_NewObject(context, &gjs_repo_class, NULL, global));
     if (repo == NULL) {
         gjs_throw(context, "No memory to create repo object");
         return NULL;
@@ -304,7 +303,7 @@ repo_new(JSContext *context)
     JS_SetPrivate(repo, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_GREPO,
-                        "repo constructor, obj %p priv %p", repo, priv);
+                        "repo constructor, obj %p priv %p", repo.get(), priv);
 
     versions = JS_NewObject(context, NULL, NULL, global);
     versions_name = gjs_context_get_const_string(context, GJS_STRING_GI_VERSIONS);
diff --git a/gi/union.cpp b/gi/union.cpp
index 7ffad0e..f74fd56 100644
--- a/gi/union.cpp
+++ b/gi/union.cpp
@@ -139,9 +139,9 @@ union_new_resolve(JSContext *context,
 }
 
 static void*
-union_new(JSContext   *context,
-          JSObject    *obj, /* "this" for constructor */
-          GIUnionInfo *info)
+union_new(JSContext       *context,
+          JS::HandleObject obj, /* "this" for constructor */
+          GIUnionInfo     *info)
 {
     int n_methods;
     int i;
@@ -172,10 +172,12 @@ union_new(JSContext   *context,
              * creates a JSObject wrapper for the union that we immediately
              * discard.
              */
-            if (rval.isNull())
+            if (rval.isNull()) {
                 return NULL;
-            else
-                return gjs_c_union_from_union(context, &rval.toObject());
+            } else {
+                JS::RootedObject rval_obj(context, &rval.toObject());
+                return gjs_c_union_from_union(context, rval_obj);
+            }
         }
 
         g_base_info_unref((GIBaseInfo*) func_info);
@@ -192,7 +194,7 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(union)
     GJS_NATIVE_CONSTRUCTOR_VARIABLES(union)
     Union *priv;
     Union *proto_priv;
-    JSObject *proto;
+    JS::RootedObject proto(context);
     void *gboxed;
 
     GJS_NATIVE_CONSTRUCTOR_PRELUDE(union);
@@ -206,10 +208,11 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(union)
 
     gjs_debug_lifecycle(GJS_DEBUG_GBOXED,
                         "union constructor, obj %p priv %p",
-                        object, priv);
+                        object.get(), priv);
 
-    JS_GetPrototype(context, object, &proto);
-    gjs_debug_lifecycle(GJS_DEBUG_GBOXED, "union instance __proto__ is %p", proto);
+    JS_GetPrototype(context, object, proto.address());
+    gjs_debug_lifecycle(GJS_DEBUG_GBOXED, "union instance __proto__ is %p",
+                        proto.get());
 
     /* If we're the prototype, then post-construct we'll fill in priv->info.
      * If we are not the prototype, though, then we'll get ->info from the
@@ -285,7 +288,7 @@ to_string_func(JSContext *context,
                JS::Value *vp)
 {
     JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
-    JSObject *obj = rec.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, rec.thisv().toObjectOrNull());
 
     Union *priv;
     bool ret = false;
@@ -442,8 +445,8 @@ gjs_union_from_c_union(JSContext    *context,
 }
 
 void*
-gjs_c_union_from_union(JSContext    *context,
-                       JSObject     *obj)
+gjs_c_union_from_union(JSContext       *context,
+                       JS::HandleObject obj)
 {
     Union *priv;
 
@@ -456,11 +459,11 @@ gjs_c_union_from_union(JSContext    *context,
 }
 
 bool
-gjs_typecheck_union(JSContext     *context,
-                    JSObject      *object,
-                    GIStructInfo  *expected_info,
-                    GType          expected_type,
-                    bool           throw_error)
+gjs_typecheck_union(JSContext       *context,
+                    JS::HandleObject object,
+                    GIStructInfo    *expected_info,
+                    GType            expected_type,
+                    bool             throw_error)
 {
     Union *priv;
     bool result;
diff --git a/gi/union.h b/gi/union.h
index 6332d63..fabc065 100644
--- a/gi/union.h
+++ b/gi/union.h
@@ -34,13 +34,15 @@ G_BEGIN_DECLS
 bool      gjs_define_union_class       (JSContext    *context,
                                         JSObject     *in_object,
                                         GIUnionInfo  *info);
-void*     gjs_c_union_from_union       (JSContext    *context,
-                                        JSObject     *obj);
+
+void     *gjs_c_union_from_union(JSContext       *context,
+                                 JS::HandleObject obj);
+
 JSObject* gjs_union_from_c_union       (JSContext    *context,
                                         GIUnionInfo  *info,
                                         void         *gboxed);
 bool      gjs_typecheck_union          (JSContext             *context,
-                                        JSObject              *obj,
+                                        JS::HandleObject       obj,
                                         GIStructInfo          *expected_info,
                                         GType                  expected_type,
                                         bool                   throw_error);
diff --git a/gi/value.cpp b/gi/value.cpp
index 16eb8e7..fc8e50d 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -355,8 +355,10 @@ gjs_value_guess_g_type(JSContext *context,
     if (value.isBoolean())
         return G_TYPE_BOOLEAN;
 
-    if (value.isObject())
-        return gjs_gtype_get_actual_gtype(context, &value.toObject());
+    if (value.isObject()) {
+        JS::RootedObject obj(context, &value.toObject());
+        return gjs_gtype_get_actual_gtype(context, obj);
+    }
 
     return G_TYPE_INVALID;
 }
@@ -480,8 +482,7 @@ gjs_value_to_g_value_internal(JSContext    *context,
         if (value.isNull()) {
             /* nothing to do */
         } else if (value.isObject()) {
-            JSObject *obj;
-            obj = &value.toObject();
+            JS::RootedObject obj(context, &value.toObject());
 
             if (!gjs_typecheck_object(context, obj, gtype, true))
                 return false;
@@ -542,8 +543,7 @@ gjs_value_to_g_value_internal(JSContext    *context,
         if (value.isNull()) {
             /* nothing to do */
         } else if (value.isObject()) {
-            JSObject *obj;
-            obj = &value.toObject();
+            JS::RootedObject obj(context, &value.toObject());
 
             if (g_type_is_a(gtype, G_TYPE_ERROR)) {
                 /* special case GError */
@@ -611,7 +611,7 @@ gjs_value_to_g_value_internal(JSContext    *context,
         if (value.isNull()) {
             /* nothing to do */
         } else if (value.isObject()) {
-            JSObject *obj = &value.toObject();
+            JS::RootedObject obj(context, &value.toObject());
 
             if (!gjs_typecheck_boxed(context, obj, NULL, G_TYPE_VARIANT, true))
                 return false;
@@ -675,8 +675,7 @@ gjs_value_to_g_value_internal(JSContext    *context,
         if (value.isNull()) {
             /* nothing to do */
         } else if (value.isObject()) {
-            JSObject *obj;
-            obj = &value.toObject();
+            JS::RootedObject obj(context, &value.toObject());
 
             if (!gjs_typecheck_param(context, obj, gtype, true))
                 return false;
@@ -700,7 +699,8 @@ gjs_value_to_g_value_internal(JSContext    *context,
             return false;
         }
 
-        type = gjs_gtype_get_actual_gtype(context, &value.toObject());
+        JS::RootedObject obj(context, &value.toObject());
+        type = gjs_gtype_get_actual_gtype(context, obj);
         g_value_set_gtype(gvalue, type);
     } else if (g_type_is_a(gtype, G_TYPE_POINTER)) {
         if (value.isNull()) {
diff --git a/gjs/byteArray.cpp b/gjs/byteArray.cpp
index 16793b1..eeb38a1 100644
--- a/gjs/byteArray.cpp
+++ b/gjs/byteArray.cpp
@@ -71,9 +71,9 @@ struct JSClass gjs_byte_array_class = {
 };
 
 bool
-gjs_typecheck_bytearray(JSContext     *context,
-                        JSObject      *object,
-                        bool           throw_error)
+gjs_typecheck_bytearray(JSContext       *context,
+                        JS::HandleObject object,
+                        bool             throw_error)
 {
     return do_base_typecheck(context, object, throw_error);
 }
@@ -411,7 +411,7 @@ to_string_func(JSContext *context,
                JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *object = argv.thisv().toObjectOrNull();
+    JS::RootedObject object(context, argv.thisv().toObjectOrNull());
     ByteArrayInstance *priv;
     char *encoding;
     bool encoding_is_utf8;
@@ -509,7 +509,7 @@ to_gbytes_func(JSContext *context,
                JS::Value *vp)
 {
     JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
-    JSObject *object = rec.thisv().toObjectOrNull();
+    JS::RootedObject object(context, rec.thisv().toObjectOrNull());
     ByteArrayInstance *priv;
     JSObject *ret_bytes_obj;
     GIBaseInfo *gbytes_info;
@@ -551,11 +551,11 @@ byte_array_get_prototype(JSContext *context)
 static JSObject*
 byte_array_new(JSContext *context)
 {
-    JSObject *array;
     ByteArrayInstance *priv;
 
-    array = JS_NewObject(context, &gjs_byte_array_class,
-                         byte_array_get_prototype(context), NULL);
+    JS::RootedObject array(context,
+                           JS_NewObject(context, &gjs_byte_array_class,
+                                        byte_array_get_prototype(context), NULL));
 
     priv = g_slice_new0(ByteArrayInstance);
 
@@ -728,14 +728,12 @@ from_gbytes_func(JSContext *context,
                  JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *bytes_obj;
+    JS::RootedObject bytes_obj(context);
     GBytes *gbytes;
     ByteArrayInstance *priv;
-    JSObject *obj;
-    bool ret = false;
 
     if (!gjs_parse_call_args(context, "overrides_gbytes_to_array", "o", argv,
-                        "bytes", &bytes_obj))
+                             "bytes", bytes_obj.address()))
         return false;
 
     if (!gjs_typecheck_boxed(context, bytes_obj, NULL, G_TYPE_BYTES, true))
@@ -743,7 +741,7 @@ from_gbytes_func(JSContext *context,
 
     gbytes = (GBytes*) gjs_c_struct_from_boxed(context, bytes_obj);
 
-    obj = byte_array_new(context);
+    JS::RootedObject obj(context, byte_array_new(context));
     if (obj == NULL)
         return false;
     priv = priv_from_js(context, obj);
@@ -751,23 +749,22 @@ from_gbytes_func(JSContext *context,
 
     priv->bytes = g_bytes_ref(gbytes);
 
-    ret = true;
     argv.rval().setObject(*obj);
-    return ret;
+    return true;
 }
 
 JSObject *
 gjs_byte_array_from_byte_array (JSContext *context,
                                 GByteArray *array)
 {
-    JSObject *object;
     ByteArrayInstance *priv;
 
     g_return_val_if_fail(context != NULL, NULL);
     g_return_val_if_fail(array != NULL, NULL);
 
-    object = JS_NewObject(context, &gjs_byte_array_class,
-                          byte_array_get_prototype(context), NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_byte_array_class,
+                                         byte_array_get_prototype(context), NULL));
     if (!object) {
         gjs_throw(context, "failed to create byte array");
         return NULL;
@@ -787,14 +784,14 @@ JSObject *
 gjs_byte_array_from_bytes (JSContext *context,
                            GBytes    *bytes)
 {
-    JSObject *object;
     ByteArrayInstance *priv;
 
     g_return_val_if_fail(context != NULL, NULL);
     g_return_val_if_fail(bytes != NULL, NULL);
 
-    object = JS_NewObject(context, &gjs_byte_array_class,
-                          byte_array_get_prototype(context), NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_byte_array_class,
+                                         byte_array_get_prototype(context), NULL));
     if (!object) {
         gjs_throw(context, "failed to create byte array");
         return NULL;
@@ -809,8 +806,8 @@ gjs_byte_array_from_bytes (JSContext *context,
 }
 
 GBytes *
-gjs_byte_array_get_bytes (JSContext  *context,
-                          JSObject   *object)
+gjs_byte_array_get_bytes (JSContext       *context,
+                          JS::HandleObject object)
 {
     ByteArrayInstance *priv;
     priv = priv_from_js(context, object);
@@ -822,8 +819,8 @@ gjs_byte_array_get_bytes (JSContext  *context,
 }
 
 GByteArray *
-gjs_byte_array_get_byte_array (JSContext   *context,
-                               JSObject    *obj)
+gjs_byte_array_get_byte_array (JSContext       *context,
+                               JS::HandleObject obj)
 {
     ByteArrayInstance *priv;
     priv = priv_from_js(context, obj);
@@ -835,10 +832,10 @@ gjs_byte_array_get_byte_array (JSContext   *context,
 }
 
 void
-gjs_byte_array_peek_data (JSContext  *context,
-                          JSObject   *obj,
-                          guint8    **out_data,
-                          gsize      *out_len)
+gjs_byte_array_peek_data (JSContext       *context,
+                          JS::HandleObject obj,
+                          guint8         **out_data,
+                          gsize           *out_len)
 {
     ByteArrayInstance *priv;
     priv = priv_from_js(context, obj);
diff --git a/gjs/byteArray.h b/gjs/byteArray.h
index e969059..b001946 100644
--- a/gjs/byteArray.h
+++ b/gjs/byteArray.h
@@ -34,9 +34,9 @@
 
 G_BEGIN_DECLS
 
-bool          gjs_typecheck_bytearray    (JSContext     *context,
-                                          JSObject      *obj,
-                                          bool           throw_error);
+bool        gjs_typecheck_bytearray(JSContext       *context,
+                                    JS::HandleObject obj,
+                                    bool             throw_error);
 
 bool          gjs_define_byte_array_stuff    (JSContext  *context,
                                               JSObject  **module_out);
@@ -46,16 +46,16 @@ JSObject *    gjs_byte_array_from_byte_array (JSContext  *context,
 JSObject *    gjs_byte_array_from_bytes (JSContext  *context,
                                          GBytes *bytes);
 
-GByteArray *   gjs_byte_array_get_byte_array (JSContext  *context,
-                                              JSObject   *object);
+GByteArray *gjs_byte_array_get_byte_array(JSContext       *context,
+                                          JS::HandleObject object);
 
-GBytes *      gjs_byte_array_get_bytes (JSContext  *context,
-                                        JSObject   *object);
+GBytes     *gjs_byte_array_get_bytes(JSContext       *context,
+                                     JS::HandleObject object);
 
-void          gjs_byte_array_peek_data (JSContext  *context,
-                                        JSObject   *object,
-                                        guint8    **out_data,
-                                        gsize      *out_len);
+void        gjs_byte_array_peek_data(JSContext       *context,
+                                     JS::HandleObject object,
+                                     guint8         **out_data,
+                                     gsize           *out_len);
 
 G_END_DECLS
 
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index 845a294..9e07c65 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -936,7 +936,6 @@ static JSObject*
 importer_new(JSContext *context,
              bool       is_root)
 {
-    JSObject *importer;
     Importer *priv;
     JSObject *global;
     JSBool found;
@@ -977,7 +976,8 @@ importer_new(JSContext *context,
                   gjs_importer_class.name, prototype);
     }
 
-    importer = JS_NewObject(context, &gjs_importer_class, NULL, global);
+    JS::RootedObject importer(context,
+                              JS_NewObject(context, &gjs_importer_class, NULL, global));
     if (importer == NULL)
         g_error("No memory to create importer importer");
 
@@ -990,7 +990,8 @@ importer_new(JSContext *context,
     JS_SetPrivate(importer, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_IMPORTER,
-                        "importer constructor, obj %p priv %p", importer, priv);
+                        "importer constructor, obj %p priv %p", importer.get(),
+                        priv);
 
     return importer;
 }
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index 6d6942c..f748d86 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -473,13 +473,23 @@ gjs_explain_scope(JSContext  *context,
     JS_EndRequest(context);
 }
 
+static char *
+utf8_exception_from_non_gerror_value(JSContext *cx,
+                                     JS::Value  exc)
+{
+    char *utf8_exception = NULL;
+    JSString *exc_str = JS_ValueToString(cx, exc);
+    if (exc_str != NULL)
+        gjs_string_to_utf8(cx, JS::StringValue(exc_str), &utf8_exception);
+    return utf8_exception;
+}
+
 bool
 gjs_log_exception_full(JSContext *context,
                        JS::Value  exc,
                        JSString  *message)
 {
     JS::Value stack;
-    JSString *exc_str;
     char *utf8_exception, *utf8_message;
     bool is_syntax;
 
@@ -487,32 +497,28 @@ gjs_log_exception_full(JSContext *context,
 
     is_syntax = false;
 
-    if (exc.isObject() &&
-        gjs_typecheck_boxed(context, &exc.toObject(), NULL, G_TYPE_ERROR, false)) {
-        GError *gerror;
-
-        gerror = (GError*) gjs_c_struct_from_boxed(context, &exc.toObject());
-        utf8_exception = g_strdup_printf("GLib.Error %s: %s",
-                                         g_quark_to_string(gerror->domain),
-                                         gerror->message);
+    if (!exc.isObject()) {
+        utf8_exception = utf8_exception_from_non_gerror_value(context, exc);
     } else {
-        if (exc.isObject()) {
+        JS::RootedObject exc_obj(context, &exc.toObject());
+        if (gjs_typecheck_boxed(context, exc_obj, NULL, G_TYPE_ERROR, false)) {
+            GError *gerror = (GError *) gjs_c_struct_from_boxed(context, exc_obj);
+            utf8_exception = g_strdup_printf("GLib.Error %s: %s",
+                                             g_quark_to_string(gerror->domain),
+                                             gerror->message);
+        } else {
             JS::Value js_name;
             char *utf8_name;
 
-            if (gjs_object_get_property_const(context, &exc.toObject(),
+            if (gjs_object_get_property_const(context, exc_obj,
                                               GJS_STRING_NAME, &js_name) &&
                 js_name.isString() &&
                 gjs_string_to_utf8(context, js_name, &utf8_name)) {
                 is_syntax = strcmp("SyntaxError", utf8_name) == 0;
             }
-        }
 
-        exc_str = JS_ValueToString(context, exc);
-        if (exc_str != NULL)
-            gjs_string_to_utf8(context, JS::StringValue(exc_str), &utf8_exception);
-        else
-            utf8_exception = NULL;
+            utf8_exception = utf8_exception_from_non_gerror_value(context, exc);
+        }
     }
 
     if (message != NULL)
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 23244ea..5b6b3ef 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -80,15 +80,15 @@ typedef struct GjsRootedArray GjsRootedArray;
  */
 #define GJS_DEFINE_PRIV_FROM_JS(type, klass)                          \
     __attribute__((unused)) static inline bool                          \
-    do_base_typecheck(JSContext *context,                               \
-                      JSObject  *object,                                \
-                      bool       throw_error)                           \
+    do_base_typecheck(JSContext       *context,                         \
+                      JS::HandleObject object,                          \
+                      bool             throw_error)                     \
     {                                                                   \
         return gjs_typecheck_instance(context, object, &klass, throw_error);  \
     }                                                                   \
     static inline type *                                                \
-    priv_from_js(JSContext *context,                                    \
-                 JSObject  *object)                                     \
+    priv_from_js(JSContext       *context,                              \
+                 JS::HandleObject object)                               \
     {                                                                   \
         type *priv;                                                     \
         JS_BeginRequest(context);                                       \
@@ -97,9 +97,9 @@ typedef struct GjsRootedArray GjsRootedArray;
         return priv;                                                    \
     }                                                                   \
     __attribute__((unused)) static bool                                 \
-    priv_from_js_with_typecheck(JSContext *context,                     \
-                                JSObject  *object,                      \
-                                type      **out)                        \
+    priv_from_js_with_typecheck(JSContext       *context,               \
+                                JS::HandleObject object,                \
+                                type           **out)                   \
     {                                                                   \
         if (!do_base_typecheck(context, object, false))                 \
             return false;                                               \
@@ -220,7 +220,7 @@ gjs_##name##_constructor(JSContext  *context,           \
  * be at the very top.
  */
 #define GJS_NATIVE_CONSTRUCTOR_VARIABLES(name)          \
-    JSObject *object = NULL;                                            \
+    JS::RootedObject object(context, NULL);                         \
     JS::CallArgs argv G_GNUC_UNUSED = JS::CallArgsFromVp(argc, vp);
 
 /**
diff --git a/modules/cairo-context.cpp b/modules/cairo-context.cpp
index 3191833..9a59d72 100644
--- a/modules/cairo-context.cpp
+++ b/modules/cairo-context.cpp
@@ -37,7 +37,7 @@ mname##_func(JSContext *context,                    \
               JS::Value *vp)                        \
 {                                                   \
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);             \
-    JSObject *obj = argv.thisv().toObjectOrNull();  \
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());  \
     cairo_t *cr;
 
 #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END                               \
@@ -253,9 +253,9 @@ GJS_DEFINE_PROTO_WITH_GTYPE("CairoContext", cairo_context, CAIRO_GOBJECT_TYPE_CO
 GJS_DEFINE_PRIV_FROM_JS(GjsCairoContext, gjs_cairo_context_class);
 
 static void
-_gjs_cairo_context_construct_internal(JSContext *context,
-                                      JSObject *obj,
-                                      cairo_t *cr)
+_gjs_cairo_context_construct_internal(JSContext       *context,
+                                      JS::HandleObject obj,
+                                      cairo_t         *cr)
 {
     GjsCairoContext *priv;
 
@@ -407,7 +407,7 @@ dispose_func(JSContext *context,
              JS::Value *vp)
 {
     JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
-    JSObject *obj = rec.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, rec.thisv().toObjectOrNull());
 
     GjsCairoContext *priv;
 
@@ -426,7 +426,7 @@ appendPath_func(JSContext *context,
                 JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj = argv.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());
 
     JSObject *path_wrapper;
     cairo_path_t *path;
@@ -454,7 +454,7 @@ copyPath_func(JSContext *context,
               JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj = argv.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());
 
     cairo_path_t *path;
     cairo_t *cr;
@@ -474,7 +474,7 @@ copyPathFlat_func(JSContext *context,
                   JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj = argv.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());
 
     cairo_path_t *path;
     cairo_t *cr;
@@ -494,7 +494,7 @@ mask_func(JSContext *context,
           JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj = argv.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());
 
     JSObject *pattern_wrapper;
     cairo_pattern_t *pattern;
@@ -526,7 +526,7 @@ maskSurface_func(JSContext *context,
                  JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj = argv.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());
 
     JSObject *surface_wrapper;
     double x, y;
@@ -562,7 +562,7 @@ setDash_func(JSContext *context,
              JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj = argv.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());
 
     guint i;
     cairo_t *cr;
@@ -625,7 +625,7 @@ setSource_func(JSContext *context,
                JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj = argv.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());
 
     JSObject *pattern_wrapper;
     cairo_pattern_t *pattern;
@@ -659,7 +659,7 @@ setSourceSurface_func(JSContext *context,
                       JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj = argv.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());
 
     JSObject *surface_wrapper;
     double x, y;
@@ -696,7 +696,7 @@ showText_func(JSContext *context,
               JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj = argv.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());
 
     char *utf8;
     cairo_t *cr;
@@ -724,7 +724,7 @@ selectFontFace_func(JSContext *context,
                     JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *obj = argv.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull());
 
     char *family;
     cairo_font_slant_t slant;
@@ -755,7 +755,7 @@ popGroup_func(JSContext *context,
               JS::Value *vp)
 {
     JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
-    JSObject *obj = rec.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, rec.thisv().toObjectOrNull());
 
     cairo_t *cr;
     cairo_pattern_t *pattern;
@@ -788,7 +788,7 @@ getSource_func(JSContext *context,
                JS::Value *vp)
 {
     JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
-    JSObject *obj = rec.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, rec.thisv().toObjectOrNull());
 
     cairo_t *cr;
     cairo_pattern_t *pattern;
@@ -822,7 +822,7 @@ getTarget_func(JSContext *context,
                JS::Value *vp)
 {
     JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
-    JSObject *obj = rec.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, rec.thisv().toObjectOrNull());
 
     cairo_t *cr;
     cairo_surface_t *surface;
@@ -856,7 +856,7 @@ getGroupTarget_func(JSContext *context,
                     JS::Value *vp)
 {
     JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
-    JSObject *obj = rec.thisv().toObjectOrNull();
+    JS::RootedObject obj(context, rec.thisv().toObjectOrNull());
 
     cairo_t *cr;
     cairo_surface_t *surface;
@@ -990,9 +990,8 @@ JSObject *
 gjs_cairo_context_from_context(JSContext *context,
                                cairo_t *cr)
 {
-    JSObject *object;
-
-    object = JS_NewObject(context, &gjs_cairo_context_class, NULL, NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_cairo_context_class, NULL, NULL));
     if (!object)
         return NULL;
 
@@ -1002,8 +1001,8 @@ gjs_cairo_context_from_context(JSContext *context,
 }
 
 cairo_t *
-gjs_cairo_context_get_context(JSContext *context,
-                              JSObject *object)
+gjs_cairo_context_get_context(JSContext       *context,
+                              JS::HandleObject object)
 {
     GjsCairoContext *priv;
     priv = priv_from_js(context, object);
@@ -1022,10 +1021,9 @@ context_to_g_argument(JSContext      *context,
                       bool            may_be_null,
                       GArgument      *arg)
 {
-    JSObject *obj;
+    JS::RootedObject obj(context, value.toObjectOrNull());
     cairo_t *cr;
 
-    obj = value.toObjectOrNull();
     cr = gjs_cairo_context_get_context(context, obj);
     if (!cr)
         return false;
diff --git a/modules/cairo-image-surface.cpp b/modules/cairo-image-surface.cpp
index f3e08dc..645257f 100644
--- a/modules/cairo-image-surface.cpp
+++ b/modules/cairo-image-surface.cpp
@@ -76,7 +76,6 @@ createFromPNG_func(JSContext *context,
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
     char *filename;
     cairo_surface_t *surface;
-    JSObject *surface_wrapper;
 
     if (!gjs_parse_call_args(context, "createFromPNG", "s", argv,
                         "filename", &filename))
@@ -87,7 +86,8 @@ createFromPNG_func(JSContext *context,
     if (!gjs_cairo_check_status(context, cairo_surface_status(surface), "surface"))
         return false;
 
-    surface_wrapper = JS_NewObject(context, &gjs_cairo_image_surface_class, NULL, NULL);
+    JS::RootedObject surface_wrapper(context,
+                                     JS_NewObject(context, &gjs_cairo_image_surface_class, NULL, NULL));
     if (!surface_wrapper) {
         gjs_throw(context, "failed to create surface");
         return false;
@@ -217,13 +217,12 @@ JSObject *
 gjs_cairo_image_surface_from_surface(JSContext       *context,
                                      cairo_surface_t *surface)
 {
-    JSObject *object;
-
     g_return_val_if_fail(context != NULL, NULL);
     g_return_val_if_fail(surface != NULL, NULL);
     g_return_val_if_fail(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE, NULL);
 
-    object = JS_NewObject(context, &gjs_cairo_image_surface_class, NULL, NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_cairo_image_surface_class, NULL, NULL));
     if (!object) {
         gjs_throw(context, "failed to create image surface");
         return NULL;
diff --git a/modules/cairo-linear-gradient.cpp b/modules/cairo-linear-gradient.cpp
index 27e346d..37b9f92 100644
--- a/modules/cairo-linear-gradient.cpp
+++ b/modules/cairo-linear-gradient.cpp
@@ -77,13 +77,12 @@ JSObject *
 gjs_cairo_linear_gradient_from_pattern(JSContext       *context,
                                        cairo_pattern_t *pattern)
 {
-    JSObject *object;
-
     g_return_val_if_fail(context != NULL, NULL);
     g_return_val_if_fail(pattern != NULL, NULL);
     g_return_val_if_fail(cairo_pattern_get_type(pattern) == CAIRO_PATTERN_TYPE_LINEAR, NULL);
 
-    object = JS_NewObject(context, &gjs_cairo_linear_gradient_class, NULL, NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_cairo_linear_gradient_class, NULL, NULL));
     if (!object) {
         gjs_throw(context, "failed to create linear gradient pattern");
         return NULL;
diff --git a/modules/cairo-path.cpp b/modules/cairo-path.cpp
index 87eb600..7921a3f 100644
--- a/modules/cairo-path.cpp
+++ b/modules/cairo-path.cpp
@@ -69,13 +69,13 @@ JSObject *
 gjs_cairo_path_from_path(JSContext    *context,
                          cairo_path_t *path)
 {
-    JSObject *object;
     GjsCairoPath *priv;
 
     g_return_val_if_fail(context != NULL, NULL);
     g_return_val_if_fail(path != NULL, NULL);
 
-    object = JS_NewObject(context, &gjs_cairo_path_class, NULL, NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_cairo_path_class, NULL, NULL));
     if (!object) {
         gjs_throw(context, "failed to create path");
         return NULL;
diff --git a/modules/cairo-pattern.cpp b/modules/cairo-pattern.cpp
index 186b347..ac60af6 100644
--- a/modules/cairo-pattern.cpp
+++ b/modules/cairo-pattern.cpp
@@ -105,7 +105,7 @@ JSFunctionSpec gjs_cairo_pattern_proto_funcs[] = {
  */
 void
 gjs_cairo_pattern_construct(JSContext       *context,
-                            JSObject        *object,
+                            JS::HandleObject object,
                             cairo_pattern_t *pattern)
 {
     GjsCairoPattern *priv;
diff --git a/modules/cairo-pdf-surface.cpp b/modules/cairo-pdf-surface.cpp
index f971a3b..0aee113 100644
--- a/modules/cairo-pdf-surface.cpp
+++ b/modules/cairo-pdf-surface.cpp
@@ -83,13 +83,12 @@ JSObject *
 gjs_cairo_pdf_surface_from_surface(JSContext       *context,
                                    cairo_surface_t *surface)
 {
-    JSObject *object;
-
     g_return_val_if_fail(context != NULL, NULL);
     g_return_val_if_fail(surface != NULL, NULL);
     g_return_val_if_fail(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_PDF, NULL);
 
-    object = JS_NewObject(context, &gjs_cairo_pdf_surface_class, NULL, NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_cairo_pdf_surface_class, NULL, NULL));
     if (!object) {
         gjs_throw(context, "failed to create pdf surface");
         return NULL;
diff --git a/modules/cairo-private.h b/modules/cairo-private.h
index 3879f4c..97e3380 100644
--- a/modules/cairo-private.h
+++ b/modules/cairo-private.h
@@ -42,7 +42,7 @@ JS::Value        gjs_cairo_context_create_proto         (JSContext       *contex
                                                          const char      *proto_name,
                                                          JSObject        *parent);
 cairo_t *        gjs_cairo_context_get_context          (JSContext       *context,
-                                                         JSObject        *object);
+                                                         JS::HandleObject object);
 JSObject *       gjs_cairo_context_from_context         (JSContext       *context,
                                                          cairo_t         *cr);
 void             gjs_cairo_context_init                 (JSContext       *context);
@@ -65,7 +65,7 @@ JS::Value        gjs_cairo_surface_create_proto         (JSContext       *contex
                                                          const char      *proto_name,
                                                          JSObject        *parent);
 void             gjs_cairo_surface_construct            (JSContext       *context,
-                                                         JSObject        *object,
+                                                         JS::HandleObject object,
                                                          cairo_surface_t *surface);
 void             gjs_cairo_surface_finalize_surface     (JSFreeOp        *fop,
                                                          JSObject        *object);
@@ -120,7 +120,7 @@ JS::Value        gjs_cairo_pattern_create_proto         (JSContext       *contex
                                                          const char      *proto_name,
                                                          JSObject        *parent);
 void             gjs_cairo_pattern_construct            (JSContext       *context,
-                                                         JSObject        *object,
+                                                         JS::HandleObject object,
                                                          cairo_pattern_t *pattern);
 void             gjs_cairo_pattern_finalize_pattern     (JSFreeOp        *fop,
                                                          JSObject        *object);
diff --git a/modules/cairo-ps-surface.cpp b/modules/cairo-ps-surface.cpp
index b33b85e..a7e4736 100644
--- a/modules/cairo-ps-surface.cpp
+++ b/modules/cairo-ps-surface.cpp
@@ -92,13 +92,12 @@ JSObject *
 gjs_cairo_ps_surface_from_surface(JSContext       *context,
                                   cairo_surface_t *surface)
 {
-    JSObject *object;
-
     g_return_val_if_fail(context != NULL, NULL);
     g_return_val_if_fail(surface != NULL, NULL);
     g_return_val_if_fail(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_PS, NULL);
 
-    object = JS_NewObject(context, &gjs_cairo_ps_surface_class, NULL, NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_cairo_ps_surface_class, NULL, NULL));
     if (!object) {
         gjs_throw(context, "failed to create ps surface");
         return NULL;
diff --git a/modules/cairo-radial-gradient.cpp b/modules/cairo-radial-gradient.cpp
index f5c21ec..9df421e 100644
--- a/modules/cairo-radial-gradient.cpp
+++ b/modules/cairo-radial-gradient.cpp
@@ -79,13 +79,12 @@ JSObject *
 gjs_cairo_radial_gradient_from_pattern(JSContext       *context,
                                        cairo_pattern_t *pattern)
 {
-    JSObject *object;
-
     g_return_val_if_fail(context != NULL, NULL);
     g_return_val_if_fail(pattern != NULL, NULL);
     g_return_val_if_fail(cairo_pattern_get_type(pattern) == CAIRO_PATTERN_TYPE_RADIAL, NULL);
 
-    object = JS_NewObject(context, &gjs_cairo_radial_gradient_class, NULL, NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_cairo_radial_gradient_class, NULL, NULL));
     if (!object) {
         gjs_throw(context, "failed to create radial gradient pattern");
         return NULL;
diff --git a/modules/cairo-region.cpp b/modules/cairo-region.cpp
index 1a6ec48..e635ecf 100644
--- a/modules/cairo-region.cpp
+++ b/modules/cairo-region.cpp
@@ -40,8 +40,9 @@ GJS_DEFINE_PROTO_WITH_GTYPE("CairoRegion", cairo_region, CAIRO_GOBJECT_TYPE_REGI
 GJS_DEFINE_PRIV_FROM_JS(GjsCairoRegion, gjs_cairo_region_class);
 
 static cairo_region_t *
-get_region(JSContext *context,
-           JSObject *obj) {
+get_region(JSContext       *context,
+           JS::HandleObject obj)
+{
     GjsCairoRegion *priv = priv_from_js(context, obj);
     if (priv == NULL)
         return NULL;
@@ -55,7 +56,7 @@ fill_rectangle(JSContext *context, JSObject *obj,
 
 #define PRELUDE                                                 \
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);          \
-    JSObject *obj = argv.thisv().toObjectOrNull();              \
+    JS::RootedObject obj(context, argv.thisv().toObjectOrNull()); \
     cairo_region_t *this_region = get_region(context, obj);
 
 #define RETURN_STATUS                                           \
@@ -68,10 +69,10 @@ fill_rectangle(JSContext *context, JSObject *obj,
                   JS::Value *vp)                                \
     {                                                           \
         PRELUDE;                                                \
-        JSObject *other_obj;                                    \
+        JS::RootedObject other_obj(context);                    \
         cairo_region_t *other_region;                           \
         if (!gjs_parse_call_args(context, #method, "o", argv,   \
-                            "other_region", &other_obj))        \
+                                 "other_region", other_obj.address())) \
             return false;                                       \
                                                                 \
         this_region = get_region(context, obj);                 \
@@ -221,9 +222,9 @@ JSFunctionSpec gjs_cairo_region_proto_funcs[] = {
 };
 
 static void
-_gjs_cairo_region_construct_internal(JSContext *context,
-                                     JSObject *obj,
-                                     cairo_region_t *region)
+_gjs_cairo_region_construct_internal(JSContext       *context,
+                                     JS::HandleObject obj,
+                                     cairo_region_t  *region)
 {
     GjsCairoRegion *priv;
 
@@ -274,9 +275,8 @@ static JSObject *
 gjs_cairo_region_from_region(JSContext *context,
                              cairo_region_t *region)
 {
-    JSObject *object;
-
-    object = JS_NewObject(context, &gjs_cairo_region_class, NULL, NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_cairo_region_class, NULL, NULL));
     if (!object)
         return NULL;
 
@@ -294,10 +294,9 @@ region_to_g_argument(JSContext      *context,
                      bool            may_be_null,
                      GArgument      *arg)
 {
-    JSObject *obj;
+    JS::RootedObject obj(context, &value.toObject());
     cairo_region_t *region;
 
-    obj = &value.toObject();
     region = get_region(context, obj);
     if (!region)
         return false;
diff --git a/modules/cairo-solid-pattern.cpp b/modules/cairo-solid-pattern.cpp
index 8ecb1a4..3b8673d 100644
--- a/modules/cairo-solid-pattern.cpp
+++ b/modules/cairo-solid-pattern.cpp
@@ -107,13 +107,12 @@ JSObject *
 gjs_cairo_solid_pattern_from_pattern(JSContext       *context,
                                      cairo_pattern_t *pattern)
 {
-    JSObject *object;
-
     g_return_val_if_fail(context != NULL, NULL);
     g_return_val_if_fail(pattern != NULL, NULL);
     g_return_val_if_fail(cairo_pattern_get_type(pattern) == CAIRO_PATTERN_TYPE_SOLID, NULL);
 
-    object = JS_NewObject(context, &gjs_cairo_solid_pattern_class, NULL, NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_cairo_solid_pattern_class, NULL, NULL));
     if (!object) {
         gjs_throw(context, "failed to create solid pattern");
         return NULL;
diff --git a/modules/cairo-surface-pattern.cpp b/modules/cairo-surface-pattern.cpp
index 4598e5a..13f885b 100644
--- a/modules/cairo-surface-pattern.cpp
+++ b/modules/cairo-surface-pattern.cpp
@@ -190,13 +190,12 @@ JSObject *
 gjs_cairo_surface_pattern_from_pattern(JSContext       *context,
                                        cairo_pattern_t *pattern)
 {
-    JSObject *object;
-
     g_return_val_if_fail(context != NULL, NULL);
     g_return_val_if_fail(pattern != NULL, NULL);
     g_return_val_if_fail(cairo_pattern_get_type(pattern) == CAIRO_PATTERN_TYPE_SURFACE, NULL);
 
-    object = JS_NewObject(context, &gjs_cairo_surface_pattern_class, NULL, NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_cairo_surface_pattern_class, NULL, NULL));
     if (!object) {
         gjs_throw(context, "failed to create surface pattern");
         return NULL;
diff --git a/modules/cairo-surface.cpp b/modules/cairo-surface.cpp
index 82848a0..5d51022 100644
--- a/modules/cairo-surface.cpp
+++ b/modules/cairo-surface.cpp
@@ -145,7 +145,7 @@ JSFunctionSpec gjs_cairo_surface_proto_funcs[] = {
  */
 void
 gjs_cairo_surface_construct(JSContext       *context,
-                            JSObject        *object,
+                            JS::HandleObject object,
                             cairo_surface_t *surface)
 {
     GjsCairoSurface *priv;
@@ -196,8 +196,6 @@ JSObject *
 gjs_cairo_surface_from_surface(JSContext       *context,
                                cairo_surface_t *surface)
 {
-    JSObject *object;
-
     g_return_val_if_fail(context != NULL, NULL);
     g_return_val_if_fail(surface != NULL, NULL);
 
@@ -214,7 +212,8 @@ gjs_cairo_surface_from_surface(JSContext       *context,
             break;
     }
 
-    object = JS_NewObject(context, &gjs_cairo_surface_class, NULL, NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_cairo_surface_class, NULL, NULL));
     if (!object) {
         gjs_throw(context, "failed to create surface");
         return NULL;
diff --git a/modules/cairo-svg-surface.cpp b/modules/cairo-svg-surface.cpp
index d95d00c..3b3eb6c 100644
--- a/modules/cairo-svg-surface.cpp
+++ b/modules/cairo-svg-surface.cpp
@@ -83,13 +83,12 @@ JSObject *
 gjs_cairo_svg_surface_from_surface(JSContext       *context,
                                    cairo_surface_t *surface)
 {
-    JSObject *object;
-
     g_return_val_if_fail(context != NULL, NULL);
     g_return_val_if_fail(surface != NULL, NULL);
     g_return_val_if_fail(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_SVG, NULL);
 
-    object = JS_NewObject(context, &gjs_cairo_svg_surface_class, NULL, NULL);
+    JS::RootedObject object(context,
+                            JS_NewObject(context, &gjs_cairo_svg_surface_class, NULL, NULL));
     if (!object) {
         gjs_throw(context, "failed to create svg surface");
         return NULL;
diff --git a/modules/system.cpp b/modules/system.cpp
index 333f86a..22b5a86 100644
--- a/modules/system.cpp
+++ b/modules/system.cpp
@@ -63,10 +63,11 @@ gjs_refcount(JSContext *context,
              JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    JSObject *target_obj;
+    JS::RootedObject target_obj(context);
     GObject *obj;
 
-    if (!gjs_parse_call_args(context, "refcount", "o", argv, "object", &target_obj))
+    if (!gjs_parse_call_args(context, "refcount", "o", argv,
+                             "object", target_obj.address()))
         return false;
 
     if (!gjs_typecheck_object(context, target_obj, G_TYPE_OBJECT, true))


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]