[gjs/wip/ptomato/mozjs31prep: 3/8] js: Root gjs_string_from_utf8()



commit 4e182b8c65400efb0779f6a3056bfdb39dadd26c
Author: Philip Chimento <philip endlessm com>
Date:   Thu Oct 13 15:43:32 2016 -0700

    js: Root gjs_string_from_utf8()
    
    Starting with gjs_string_from_utf8(), we convert the JS::Value out-arg to
    JS::MutableHandleValue. Working backwards from there in a huge cascade,
    we change JS::Value * to JS::MutableHandleValue in many functions that
    call gjs_string_from_utf8(), and root the values with JS::RootedValue
    where they are created.
    
    This is mostly straightforward, though requires replacing a few instances
    of a stack-allocated JS::Value array created with g_newa(), with
    JS::AutoValueVector instead.
    
    In the course of moving to more RAII classes such as JS::Rooted<T>, we
    can get rid of some more gotos in favour of returns.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=742249

 gi/arg.cpp                |  271 ++++++++++++++++++---------------------------
 gi/arg.h                  |   27 +++--
 gi/boxed.cpp              |   20 +---
 gi/foreign.cpp            |    8 +-
 gi/foreign.h              |   16 ++-
 gi/function.cpp           |   35 +++---
 gi/fundamental.cpp        |   15 +--
 gi/gerror.cpp             |   16 +--
 gi/gtype.cpp              |   13 +--
 gi/interface.cpp          |    8 +-
 gi/interface.h            |    6 +-
 gi/ns.cpp                 |   12 +--
 gi/object.cpp             |   37 ++----
 gi/object.h               |    8 +-
 gi/proxyutils.cpp         |   14 +-
 gi/proxyutils.h           |   14 +-
 gi/repo.cpp               |    2 +-
 gi/union.cpp              |   14 +--
 gi/value.cpp              |   90 ++++++++--------
 gi/value.h                |    8 +-
 gjs/byteArray.cpp         |   12 +--
 gjs/importer.cpp          |    3 +-
 gjs/jsapi-util-error.cpp  |    5 +-
 gjs/jsapi-util-string.cpp |   25 ++--
 gjs/jsapi-util.h          |   18 ++--
 gjs/runtime.cpp           |    6 +-
 modules/cairo-context.cpp |    8 +-
 modules/cairo-region.cpp  |    8 +-
 modules/cairo-surface.cpp |    8 +-
 modules/system.cpp        |   10 +-
 test/gjs-tests.cpp        |    2 +-
 31 files changed, 308 insertions(+), 431 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index 3d252e7..f0c00ba 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -434,40 +434,32 @@ gjs_object_to_g_hash(JSContext   *context,
 }
 
 bool
-gjs_array_from_strv(JSContext   *context,
-                    JS::Value   *value_p,
-                    const char **strv)
+gjs_array_from_strv(JSContext             *context,
+                    JS::MutableHandleValue value_p,
+                    const char           **strv)
 {
     JSObject *obj;
-    JS::Value elem;
     guint i;
-    bool result = false;
 
     obj = JS_NewArrayObject(context, 0, NULL);
     if (obj == NULL)
         return false;
 
-    *value_p = JS::ObjectValue(*obj);
+    value_p.setObject(*obj);
 
-    elem = JS::UndefinedValue();
-    JS_AddValueRoot(context, &elem);
+    JS::RootedValue elem(context);
 
     for (i = 0; strv[i] != NULL; i++) {
         if (!gjs_string_from_utf8 (context, strv[i], -1, &elem))
-            goto out;
+            return false;
 
         if (!JS_DefineElement(context, obj, i, elem,
                               NULL, NULL, JSPROP_ENUMERATE)) {
-            goto out;
+            return false;
         }
     }
 
-    result = true;
-
-out:
-    JS_RemoveValueRoot(context, &elem);
-
-    return result;
+    return true;
 }
 
 bool
@@ -828,27 +820,28 @@ gjs_array_to_flat_gvalue_array(JSContext   *context,
 }
 
 static bool
-gjs_array_from_flat_gvalue_array(JSContext   *context,
-                                 gpointer     array,
-                                 unsigned int length,
-                                 JS::Value   *value)
+gjs_array_from_flat_gvalue_array(JSContext             *context,
+                                 gpointer               array,
+                                 unsigned               length,
+                                 JS::MutableHandleValue value)
 {
     GValue *values = (GValue *)array;
     unsigned int i;
-    JS::Value *elems = g_newa(JS::Value, length);
+    JS::AutoValueVector elems(context);
+    elems.resize(length);
     bool result = true;
 
     for (i = 0; i < length; i ++) {
         GValue *gvalue = &values[i];
-        result = gjs_value_from_g_value(context, &elems[i], gvalue);
+        result = gjs_value_from_g_value(context, elems.handleAt(i), gvalue);
         if (!result)
             break;
     }
 
     if (result) {
         JSObject *jsarray;
-        jsarray = JS_NewArrayObject(context, length, elems);
-        *value = JS::ObjectOrNullValue(jsarray);
+        jsarray = JS_NewArrayObject(context, length, elems.begin());
+        value.setObjectOrNull(jsarray);
     }
 
     return result;
@@ -2043,29 +2036,24 @@ gjs_value_to_explicit_array (JSContext  *context,
 }
 
 static bool
-gjs_array_from_g_list (JSContext  *context,
-                       JS::Value  *value_p,
-                       GITypeTag   list_tag,
-                       GITypeInfo *param_info,
-                       GList      *list,
-                       GSList     *slist)
+gjs_array_from_g_list (JSContext             *context,
+                       JS::MutableHandleValue value_p,
+                       GITypeTag              list_tag,
+                       GITypeInfo            *param_info,
+                       GList                 *list,
+                       GSList                *slist)
 {
     JSObject *obj;
     unsigned int i;
-    JS::Value elem;
     GArgument arg;
-    bool result;
 
     obj = JS_NewArrayObject(context, 0, NULL);
     if (obj == NULL)
         return false;
 
-    *value_p = JS::ObjectValue(*obj);
-
-    elem = JS::UndefinedValue();
-    JS_AddValueRoot(context, &elem);
+    value_p.setObject(*obj);
 
-    result = false;
+    JS::RootedValue elem(context);
 
     i = 0;
     if (list_tag == GI_TYPE_TAG_GLIST) {
@@ -2075,12 +2063,12 @@ gjs_array_from_g_list (JSContext  *context,
             if (!gjs_value_from_g_argument(context, &elem,
                                            param_info, &arg,
                                            true))
-                goto out;
+                return false;
 
             if (!JS_DefineElement(context, obj,
                                   i, elem,
                                   NULL, NULL, JSPROP_ENUMERATE)) {
-                goto out;
+                return false;
             }
             ++i;
         }
@@ -2091,41 +2079,32 @@ gjs_array_from_g_list (JSContext  *context,
             if (!gjs_value_from_g_argument(context, &elem,
                                            param_info, &arg,
                                            true))
-                goto out;
+                return false;
 
             if (!JS_DefineElement(context, obj,
                                   i, elem,
                                   NULL, NULL, JSPROP_ENUMERATE)) {
-                goto out;
+                return false;
             }
             ++i;
         }
     }
 
-    result = true;
-
- out:
-    JS_RemoveValueRoot(context, &elem);
-
-    return result;
+    return true;
 }
 
 static bool
-gjs_array_from_carray_internal (JSContext  *context,
-                                JS::Value  *value_p,
-                                GITypeInfo *param_info,
-                                guint       length,
-                                gpointer    array)
+gjs_array_from_carray_internal (JSContext             *context,
+                                JS::MutableHandleValue value_p,
+                                GITypeInfo            *param_info,
+                                guint                  length,
+                                gpointer               array)
 {
     JSObject *obj;
-    JS::Value elem;
     GArgument arg;
-    bool result;
     GITypeTag element_type;
     guint i;
 
-    result = false;
-
     element_type = g_type_info_get_tag(param_info);
 
     if (is_gvalue_flat_array(param_info, element_type))
@@ -2141,36 +2120,30 @@ gjs_array_from_carray_internal (JSContext  *context,
         obj = gjs_byte_array_from_byte_array (context, &gbytearray);
         if (obj == NULL)
             return false;
-        *value_p = JS::ObjectValue(*obj);
+        value_p.setObject(*obj);
         return true;
     }
 
     /* Special case array(unichar) to be a string in JS */
-    if (element_type == GI_TYPE_TAG_UNICHAR) {
-        JS::RootedValue value_out(context);
-        if (!gjs_string_from_ucs4(context, (gunichar *) array, length, &value_out))
-            return false;
-        *value_p = value_out.get();
-        return true;
-    }
+    if (element_type == GI_TYPE_TAG_UNICHAR)
+        return gjs_string_from_ucs4(context, (gunichar *) array, length, value_p);
 
     obj = JS_NewArrayObject(context, 0, NULL);
     if (obj == NULL)
         return false;
 
-    *value_p = JS::ObjectValue(*obj);
+    value_p.setObject(*obj);
 
-    elem = JS::UndefinedValue();
-    JS_AddValueRoot(context, &elem);
+    JS::RootedValue elem(context);
 
 #define ITERATE(type) \
     for (i = 0; i < length; i++) { \
         arg.v_##type = *(((g##type*)array) + i);                         \
         if (!gjs_value_from_g_argument(context, &elem, param_info, &arg, true)) \
-          goto finally; \
+            return false; \
         if (!JS_DefineElement(context, obj, i, elem, NULL, NULL, \
               JSPROP_ENUMERATE)) \
-          goto finally; \
+            return false; \
     }
 
     switch (element_type) {
@@ -2229,10 +2202,10 @@ gjs_array_from_carray_internal (JSContext  *context,
                   arg.v_pointer = ((char*)array) + (struct_size * i);
 
                   if (!gjs_value_from_g_argument(context, &elem, param_info, &arg, true))
-                      goto finally;
+                      return false;
                   if (!JS_DefineElement(context, obj, i, elem, NULL, NULL,
                                         JSPROP_ENUMERATE))
-                      goto finally;
+                      return false;
               }
 
               break;
@@ -2252,24 +2225,19 @@ gjs_array_from_carray_internal (JSContext  *context,
           break;
         default:
           gjs_throw(context, "Unknown Array element-type %d", element_type);
-          goto finally;
+          return false;
     }
 
 #undef ITERATE
 
-    result = true;
-
-finally:
-    JS_RemoveValueRoot(context, &elem);
-
-    return result;
+    return true;
 }
 
 static bool
-gjs_array_from_fixed_size_array (JSContext  *context,
-                                 JS::Value  *value_p,
-                                 GITypeInfo *type_info,
-                                 gpointer    array)
+gjs_array_from_fixed_size_array (JSContext             *context,
+                                 JS::MutableHandleValue value_p,
+                                 GITypeInfo            *type_info,
+                                 gpointer               array)
 {
     gint length;
     GITypeInfo *param_info;
@@ -2289,11 +2257,11 @@ gjs_array_from_fixed_size_array (JSContext  *context,
 }
 
 bool
-gjs_value_from_explicit_array(JSContext  *context,
-                              JS::Value  *value_p,
-                              GITypeInfo *type_info,
-                              GArgument  *arg,
-                              int         length)
+gjs_value_from_explicit_array(JSContext             *context,
+                              JS::MutableHandleValue value_p,
+                              GITypeInfo            *type_info,
+                              GIArgument            *arg,
+                              int                    length)
 {
     GITypeInfo *param_info;
     bool res;
@@ -2308,11 +2276,11 @@ gjs_value_from_explicit_array(JSContext  *context,
 }
 
 static bool
-gjs_array_from_boxed_array (JSContext   *context,
-                            JS::Value   *value_p,
-                            GIArrayType  array_type,
-                            GITypeInfo  *param_info,
-                            GArgument   *arg)
+gjs_array_from_boxed_array (JSContext             *context,
+                            JS::MutableHandleValue value_p,
+                            GIArrayType            array_type,
+                            GITypeInfo            *param_info,
+                            GArgument             *arg)
 {
     GArray *array;
     GPtrArray *ptr_array;
@@ -2320,7 +2288,7 @@ gjs_array_from_boxed_array (JSContext   *context,
     gsize length = 0;
 
     if (arg->v_pointer == NULL) {
-        *value_p = JS::NullValue();
+        value_p.setNull();
         return true;
     }
 
@@ -2345,20 +2313,16 @@ gjs_array_from_boxed_array (JSContext   *context,
 }
 
 static bool
-gjs_array_from_zero_terminated_c_array (JSContext  *context,
-                                        JS::Value  *value_p,
-                                        GITypeInfo *param_info,
-                                        gpointer    c_array)
+gjs_array_from_zero_terminated_c_array (JSContext             *context,
+                                        JS::MutableHandleValue value_p,
+                                        GITypeInfo            *param_info,
+                                        gpointer               c_array)
 {
     JSObject *obj;
-    JS::Value elem;
     GArgument arg;
-    bool result;
     GITypeTag element_type;
     guint i;
 
-    result = false;
-
     element_type = g_type_info_get_tag(param_info);
 
     /* Special case array(guint8) */
@@ -2371,28 +2335,21 @@ gjs_array_from_zero_terminated_c_array (JSContext  *context,
         obj = gjs_byte_array_from_byte_array (context, &gbytearray);
         if (obj == NULL)
             return false;
-        *value_p = JS::ObjectValue(*obj);
+        value_p.setObject(*obj);
         return true;
     }
 
     /* Special case array(gunichar) to JS string */
-    if (element_type == GI_TYPE_TAG_UNICHAR) {
-        JS::RootedValue value_out(context);
-
-        if (!gjs_string_from_ucs4(context, (gunichar *) c_array, -1, &value_out))
-            return false;
-        *value_p = value_out.get();
-        return true;
-    }
+    if (element_type == GI_TYPE_TAG_UNICHAR)
+        return gjs_string_from_ucs4(context, (gunichar *) c_array, -1, value_p);
 
     obj = JS_NewArrayObject(context, 0, NULL);
     if (obj == NULL)
         return false;
 
-    *value_p = JS::ObjectValue(*obj);
+    value_p.setObject(*obj);
 
-    elem = JS::UndefinedValue();
-    JS_AddValueRoot(context, &elem);
+    JS::RootedValue elem(context);
 
 #define ITERATE(type) \
     do { \
@@ -2400,10 +2357,10 @@ gjs_array_from_zero_terminated_c_array (JSContext  *context,
         for (i = 0; array[i]; i++) { \
             arg.v_##type = array[i]; \
             if (!gjs_value_from_g_argument(context, &elem, param_info, &arg, true)) \
-                goto finally; \
+                return false; \
             if (!JS_DefineElement(context, obj, i, elem, NULL, NULL, \
                                   JSPROP_ENUMERATE)) \
-                goto finally; \
+                return false; \
         } \
     } while(0);
 
@@ -2454,41 +2411,35 @@ gjs_array_from_zero_terminated_c_array (JSContext  *context,
          * zero */
         case GI_TYPE_TAG_BOOLEAN:
             gjs_throw(context, "Boolean zero-terminated array not supported");
-            goto finally;
+            return false;
         default:
           gjs_throw(context, "Unknown element-type %d", element_type);
-          goto finally;
+          return false;
     }
 
 #undef ITERATE
 
-    result = true;
-
-finally:
-    JS_RemoveValueRoot(context, &elem);
-
-    return result;
+    return true;
 }
 
 
 static bool
-gjs_object_from_g_hash (JSContext  *context,
-                        JS::Value  *value_p,
-                        GITypeInfo *key_param_info,
-                        GITypeInfo *val_param_info,
-                        GHashTable *hash)
+gjs_object_from_g_hash (JSContext             *context,
+                        JS::MutableHandleValue value_p,
+                        GITypeInfo            *key_param_info,
+                        GITypeInfo            *val_param_info,
+                        GHashTable            *hash)
 {
     GHashTableIter iter;
     JSObject *obj;
     JSString *keystr;
     char     *keyutf8 = NULL;
-    JS::Value keyjs, valjs;
     GArgument keyarg, valarg;
     bool result;
 
     // a NULL hash table becomes a null JS value
     if (hash==NULL) {
-        *value_p = JS::NullValue();
+        value_p.setNull();
         return true;
     }
 
@@ -2496,14 +2447,9 @@ gjs_object_from_g_hash (JSContext  *context,
     if (obj == NULL)
         return false;
 
-    *value_p = JS::ObjectValue(*obj);
-    JS_AddObjectRoot(context, &obj);
+    value_p.setObject(*obj);
 
-    keyjs = JS::UndefinedValue();
-    JS_AddValueRoot(context, &keyjs);
-
-    valjs = JS::UndefinedValue();
-    JS_AddValueRoot(context, &valjs);
+    JS::RootedValue keyjs(context), valjs(context);
 
     keystr = NULL;
     JS_AddStringRoot(context, &keystr);
@@ -2542,20 +2488,17 @@ gjs_object_from_g_hash (JSContext  *context,
 
  out:
     if (keyutf8) g_free(keyutf8);
-    JS_RemoveObjectRoot(context, &obj);
-    JS_RemoveValueRoot(context, &keyjs);
-    JS_RemoveValueRoot(context, &valjs);
     JS_RemoveStringRoot(context, &keystr);
 
     return result;
 }
 
 bool
-gjs_value_from_g_argument (JSContext  *context,
-                           JS::Value  *value_p,
-                           GITypeInfo *type_info,
-                           GArgument  *arg,
-                           bool        copy_structs)
+gjs_value_from_g_argument (JSContext             *context,
+                           JS::MutableHandleValue value_p,
+                           GITypeInfo            *type_info,
+                           GArgument             *arg,
+                           bool                   copy_structs)
 {
     GITypeTag type_tag;
 
@@ -2565,62 +2508,62 @@ gjs_value_from_g_argument (JSContext  *context,
                       "Converting GArgument %s to JS::Value",
                       g_type_tag_to_string(type_tag));
 
-    *value_p = JS::NullValue();
+    value_p.setNull();
 
     switch (type_tag) {
     case GI_TYPE_TAG_VOID:
-        *value_p = JS::UndefinedValue(); /* or JS::NullValue() ? */
+        value_p.setUndefined(); /* or .setNull() ? */
         break;
 
     case GI_TYPE_TAG_BOOLEAN:
-        *value_p = JS::BooleanValue(!!arg->v_int);
+        value_p.setBoolean(!!arg->v_int);
         break;
 
     case GI_TYPE_TAG_INT32:
-        *value_p = JS::NumberValue(arg->v_int);
+        value_p.setInt32(arg->v_int);
         break;
 
     case GI_TYPE_TAG_UINT32:
-        *value_p = JS::NumberValue(arg->v_uint);
+        value_p.setNumber(arg->v_uint);
         break;
 
     case GI_TYPE_TAG_INT64:
-        *value_p = JS::NumberValue(arg->v_int64);
+        value_p.set(JS::NumberValue(arg->v_int64));
         break;
 
     case GI_TYPE_TAG_UINT64:
-        *value_p = JS::NumberValue(arg->v_uint64);
+        value_p.set(JS::NumberValue(arg->v_uint64));
         break;
 
     case GI_TYPE_TAG_UINT16:
-        *value_p = JS::NumberValue(arg->v_uint16);
+        value_p.setInt32(arg->v_uint16);
         break;
 
     case GI_TYPE_TAG_INT16:
-        *value_p = JS::NumberValue(arg->v_int16);
+        value_p.setInt32(arg->v_int16);
         break;
 
     case GI_TYPE_TAG_UINT8:
-        *value_p = JS::NumberValue(arg->v_uint8);
+        value_p.setInt32(arg->v_uint8);
         break;
 
     case GI_TYPE_TAG_INT8:
-        *value_p = JS::NumberValue(arg->v_int8);
+        value_p.setInt32(arg->v_int8);
         break;
 
     case GI_TYPE_TAG_FLOAT:
-        *value_p = JS::NumberValue(arg->v_float);
+        value_p.setNumber(arg->v_float);
         break;
 
     case GI_TYPE_TAG_DOUBLE:
-        *value_p = JS::NumberValue(arg->v_double);
+        value_p.setNumber(arg->v_double);
         break;
 
     case GI_TYPE_TAG_GTYPE:
         {
             JSObject *obj;
             obj = gjs_gtype_create_gtype_wrapper(context, arg->v_ssize);
-            *value_p = JS::ObjectOrNullValue(obj);
+            value_p.setObjectOrNull(obj);
         }
         break;
 
@@ -2667,7 +2610,7 @@ gjs_value_from_g_argument (JSContext  *context,
             if (arg->v_pointer) {
                 JSObject *obj = gjs_error_from_gerror(context, (GError *) arg->v_pointer, false);
                 if (obj) {
-                    *value_p = JS::ObjectValue(*obj);
+                    value_p.setObject(*obj);
                     return true;
                 }
 
@@ -2678,7 +2621,7 @@ gjs_value_from_g_argument (JSContext  *context,
 
     case GI_TYPE_TAG_INTERFACE:
         {
-            JS::Value value;
+            JS::RootedValue value(context);
             GIBaseInfo* interface_info;
             GIInfoType interface_type;
             GType gtype;
@@ -2686,8 +2629,6 @@ gjs_value_from_g_argument (JSContext  *context,
             interface_info = g_type_info_get_interface(type_info);
             g_assert(interface_info != NULL);
 
-            value = JS::UndefinedValue();
-
             interface_type = g_base_info_get_type(interface_info);
 
             if (interface_type == GI_INFO_TYPE_UNRESOLVED) {
@@ -2842,7 +2783,7 @@ gjs_value_from_g_argument (JSContext  *context,
             if (value.isUndefined())
                 return false;
 
-            *value_p = value;
+            value_p.set(value);
         }
         break;
 
@@ -2879,7 +2820,7 @@ gjs_value_from_g_argument (JSContext  *context,
                 gjs_throw(context, "Couldn't convert GByteArray to a ByteArray");
                 return false;
             }
-            *value_p = JS::ObjectValue(*array);
+            value_p.setObject(*array);
         } else {
             /* this assumes the array type is one of GArray, GPtrArray or
              * GByteArray */
diff --git a/gi/arg.h b/gi/arg.h
index ca6fdcf..eb7d30f 100644
--- a/gi/arg.h
+++ b/gi/arg.h
@@ -67,16 +67,17 @@ bool gjs_value_to_g_argument (JSContext      *context,
                               bool            may_be_null,
                               GArgument      *arg);
 
-bool gjs_value_from_g_argument (JSContext  *context,
-                                JS::Value  *value_p,
-                                GITypeInfo *type_info,
-                                GArgument  *arg,
-                                bool        copy_structs);
-bool gjs_value_from_explicit_array (JSContext  *context,
-                                    JS::Value  *value_p,
-                                    GITypeInfo *type_info,
-                                    GArgument  *arg,
-                                    int         length);
+bool gjs_value_from_g_argument(JSContext             *context,
+                               JS::MutableHandleValue value_p,
+                               GITypeInfo            *type_info,
+                               GIArgument            *arg,
+                               bool                   copy_structs);
+
+bool gjs_value_from_explicit_array(JSContext             *context,
+                                   JS::MutableHandleValue value_p,
+                                   GITypeInfo            *type_info,
+                                   GIArgument            *arg,
+                                   int                    length);
 
 bool gjs_g_argument_release    (JSContext  *context,
                                 GITransfer  transfer,
@@ -108,9 +109,9 @@ bool _gjs_enum_value_is_valid (JSContext  *context,
 gint64 _gjs_enum_from_int (GIEnumInfo *enum_info,
                            int         int_value);
 
-bool gjs_array_from_strv (JSContext   *context,
-                          JS::Value   *value_p,
-                          const char **strv);
+bool gjs_array_from_strv(JSContext             *context,
+                         JS::MutableHandleValue value_p,
+                         const char           **strv);
 
 bool gjs_array_to_strv (JSContext   *context,
                         JS::Value    array_value,
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index b3ca35e..098c0ef 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -688,10 +688,7 @@ boxed_field_getter (JSContext              *context,
         goto out;
     }
 
-    if (!gjs_value_from_g_argument (context, value.address(),
-                                    type_info,
-                                    &arg,
-                                    true))
+    if (!gjs_value_from_g_argument(context, value, type_info, &arg, true))
         goto out;
 
     success = true;
@@ -898,18 +895,9 @@ to_string_func(JSContext *context,
                JS::Value *vp)
 {
     GJS_GET_PRIV(context, argc, vp, rec, obj, Boxed, priv);
-
-    bool ret = false;
-    JS::Value retval;
-
-    if (!_gjs_proxy_to_string_func(context, obj, "boxed", (GIBaseInfo*)priv->info,
-                                   priv->gtype, priv->gboxed, &retval))
-        goto out;
-
-    ret = true;
-    rec.rval().set(retval);
- out:
-    return ret;
+    return _gjs_proxy_to_string_func(context, obj, "boxed",
+                                     (GIBaseInfo*)priv->info, priv->gtype,
+                                     priv->gboxed, rec.rval());
 }
 
 /* The bizarre thing about this vtable is that it applies to both
diff --git a/gi/foreign.cpp b/gi/foreign.cpp
index c220213..db934e1 100644
--- a/gi/foreign.cpp
+++ b/gi/foreign.cpp
@@ -160,10 +160,10 @@ gjs_struct_foreign_convert_to_g_argument(JSContext      *context,
 }
 
 bool
-gjs_struct_foreign_convert_from_g_argument(JSContext  *context,
-                                           JS::Value  *value_p,
-                                           GIBaseInfo *interface_info,
-                                           GArgument  *arg)
+gjs_struct_foreign_convert_from_g_argument(JSContext             *context,
+                                           JS::MutableHandleValue value_p,
+                                           GIBaseInfo            *interface_info,
+                                           GIArgument            *arg)
 {
     GjsForeignInfo *foreign;
 
diff --git a/gi/foreign.h b/gi/foreign.h
index afd3884..f7050d7 100644
--- a/gi/foreign.h
+++ b/gi/foreign.h
@@ -37,9 +37,10 @@ typedef bool (*GjsArgOverrideToGArgumentFunc) (JSContext      *context,
                                                bool            may_be_null,
                                                GArgument      *arg);
 
-typedef bool (*GjsArgOverrideFromGArgumentFunc)    (JSContext *context,
-                                                    JS::Value *value_p,
-                                                    GArgument *arg);
+typedef bool (*GjsArgOverrideFromGArgumentFunc) (JSContext             *context,
+                                                 JS::MutableHandleValue value_p,
+                                                 GIArgument            *arg);
+
 typedef bool (*GjsArgOverrideReleaseGArgumentFunc) (JSContext *context,
                                                     GITransfer transfer,
                                                     GArgument *arg);
@@ -62,10 +63,11 @@ bool  gjs_struct_foreign_convert_to_g_argument   (JSContext      *context,
                                                   GITransfer      transfer,
                                                   bool            may_be_null,
                                                   GArgument      *arg);
-bool  gjs_struct_foreign_convert_from_g_argument (JSContext      *context,
-                                                  JS::Value      *value_p,
-                                                  GIBaseInfo     *interface_info,
-                                                  GArgument      *arg);
+bool gjs_struct_foreign_convert_from_g_argument(JSContext             *context,
+                                                JS::MutableHandleValue value_p,
+                                                GIBaseInfo            *interface_info,
+                                                GIArgument            *arg);
+
 bool  gjs_struct_foreign_release_g_argument      (JSContext      *context,
                                                   GITransfer      transfer,
                                                   GIBaseInfo     *interface_info,
diff --git a/gi/function.cpp b/gi/function.cpp
index 85cf723..020fbcd 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -175,7 +175,7 @@ gjs_callback_closure(ffi_cif *cif,
     JSObject *func_obj;
     GjsCallbackTrampoline *trampoline;
     int i, n_args, n_jsargs, n_outargs;
-    JS::Value *jsargs, rval;
+    JS::Value rval;
     JSObject *this_object;
     GITypeInfo ret_type;
     bool success = false;
@@ -211,7 +211,10 @@ gjs_callback_closure(ffi_cif *cif,
     g_assert(n_args >= 0);
 
     n_outargs = 0;
-    jsargs = (JS::Value *)g_newa(JS::Value, n_args);
+    JS::AutoValueVector jsargs(context);
+    jsargs.resize(n_args);
+    JS::Value *args_ptr = jsargs.begin();
+
     for (i = 0, n_jsargs = 0; i < n_args; i++) {
         GIArgInfo arg_info;
         GITypeInfo type_info;
@@ -241,7 +244,7 @@ gjs_callback_closure(ffi_cif *cif,
                 gint array_length_pos = g_type_info_get_array_length(&type_info);
                 GIArgInfo array_length_arg;
                 GITypeInfo arg_type_info;
-                JS::Value length;
+                JS::RootedValue length(context);
 
                 g_callable_info_load_arg(trampoline->info, array_length_pos, &array_length_arg);
                 g_arg_info_load_type(&array_length_arg, &arg_type_info);
@@ -250,14 +253,14 @@ gjs_callback_closure(ffi_cif *cif,
                                                (GArgument *) args[array_length_pos], true))
                     goto out;
 
-                if (!gjs_value_from_explicit_array(context, &jsargs[n_jsargs++],
+                if (!gjs_value_from_explicit_array(context, jsargs.handleAt(n_jsargs++),
                                                    &type_info, (GArgument*) args[i], length.toInt32()))
                     goto out;
                 break;
             }
             case PARAM_NORMAL:
                 if (!gjs_value_from_g_argument(context,
-                                               &jsargs[n_jsargs++],
+                                               jsargs.handleAt(n_jsargs++),
                                                &type_info,
                                                (GArgument *) args[i], false))
                     goto out;
@@ -270,7 +273,7 @@ gjs_callback_closure(ffi_cif *cif,
     if (trampoline->is_vfunc) {
         g_assert(n_args > 0);
         this_object = jsargs[0].toObjectOrNull();
-        jsargs++;
+        args_ptr++;
         n_jsargs--;
     } else {
         this_object = NULL;
@@ -280,7 +283,7 @@ gjs_callback_closure(ffi_cif *cif,
                               this_object,
                               trampoline->js_function,
                               n_jsargs,
-                              jsargs,
+                              args_ptr,
                               &rval)) {
         goto out;
     }
@@ -1025,7 +1028,7 @@ gjs_invoke_c_function(JSContext       *context,
             if (array_length_pos >= 0) {
                 GIArgInfo array_length_arg;
                 GITypeInfo arg_type_info;
-                JS::Value length;
+                JS::RootedValue length(context);
 
                 g_callable_info_load_arg(function->info, array_length_pos, &array_length_arg);
                 g_arg_info_load_type(&array_length_arg, &arg_type_info);
@@ -1036,7 +1039,7 @@ gjs_invoke_c_function(JSContext       *context,
                                                         true);
                 if (!arg_failed && js_rval) {
                     arg_failed = !gjs_value_from_explicit_array(context,
-                                                                &return_values[next_rval],
+                                                                return_values.handleAt(next_rval),
                                                                 &return_info,
                                                                 &return_gargument,
                                                                 length.toInt32());
@@ -1051,7 +1054,8 @@ gjs_invoke_c_function(JSContext       *context,
                     failed = true;
             } else {
                 if (js_rval)
-                    arg_failed = !gjs_value_from_g_argument(context, &return_values[next_rval],
+                    arg_failed = !gjs_value_from_g_argument(context,
+                                                            return_values.handleAt(next_rval),
                                                             &return_info, &return_gargument,
                                                             true);
                 /* Free GArgument, the JS::Value should have ref'd or copied it */
@@ -1157,7 +1161,7 @@ release:
             GArgument *arg;
             bool arg_failed = false;
             gint array_length_pos;
-            JS::Value array_length;
+            JS::RootedValue array_length(context, JS::Int32Value(0));
             GITransfer transfer;
 
             g_assert(next_rval < function->js_out_argc);
@@ -1180,14 +1184,14 @@ release:
                                                             true);
                     if (!arg_failed) {
                         arg_failed = !gjs_value_from_explicit_array(context,
-                                                                    &return_values[next_rval],
+                                                                    return_values.handleAt(next_rval),
                                                                     &arg_type_info,
                                                                     arg,
                                                                     array_length.toInt32());
                     }
                 } else {
                     arg_failed = !gjs_value_from_g_argument(context,
-                                                            &return_values[next_rval],
+                                                            return_values.handleAt(next_rval),
                                                             &arg_type_info,
                                                             arg,
                                                             true);
@@ -1391,7 +1395,6 @@ function_to_string (JSContext *context,
     GJS_GET_PRIV(context, argc, vp, rec, to, Function, priv);
     gchar *string;
     bool free;
-    JS::Value retval;
     bool ret = false;
     int i, n_args, n_jsargs;
     GString *arg_names_str;
@@ -1441,10 +1444,8 @@ function_to_string (JSContext *context,
     g_free(arg_names);
 
  out:
-    if (gjs_string_from_utf8(context, string, -1, &retval)) {
-        rec.rval().set(retval);
+    if (gjs_string_from_utf8(context, string, -1, rec.rval()))
         ret = true;
-    }
 
     if (free)
         g_free(string);
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index 19013f9..383f2fa 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -499,8 +499,6 @@ to_string_func(JSContext *context,
                JS::Value *vp)
 {
     GJS_GET_PRIV(context, argc, vp, rec, obj, FundamentalInstance, priv);
-    bool ret = false;
-    JS::Value retval;
 
     if (!priv->prototype) {
         Fundamental *proto_priv = (Fundamental *) priv;
@@ -509,21 +507,18 @@ to_string_func(JSContext *context,
                                        (GIBaseInfo *) proto_priv->info,
                                        proto_priv->gtype,
                                        proto_priv->gfundamental,
-                                       &retval))
-            goto out;
+                                       rec.rval()))
+            return false;
     } else {
         if (!_gjs_proxy_to_string_func(context, obj, "fundamental",
                                        (GIBaseInfo *) priv->prototype->info,
                                        priv->prototype->gtype,
                                        priv->gfundamental,
-                                       &retval))
-            goto out;
+                                       rec.rval()))
+            return false;
     }
 
-    ret = true;
-    rec.rval().set(retval);
- out:
-    return ret;
+    return true;
 }
 
 /* The bizarre thing about this vtable is that it applies to both
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index 661c090..b1c0136 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -163,8 +163,6 @@ error_get_message(JSContext *context,
                   JS::Value *vp)
 {
     GJS_GET_PRIV(context, argc, vp, args, obj, Error, priv);
-    JS::Value retval;
-    bool ret = false;
 
     if (priv == NULL)
         return false;
@@ -175,11 +173,7 @@ error_get_message(JSContext *context,
         return false;
     }
 
-    // FIXME: root gjs_string_from_utf8()
-    ret = gjs_string_from_utf8(context, priv->gerror->message, -1, &retval);
-    if (ret)
-        args.rval().set(retval);
-    return ret;
+    return gjs_string_from_utf8(context, priv->gerror->message, -1, args.rval());
 }
 
 static JSBool
@@ -208,14 +202,13 @@ error_to_string(JSContext *context,
                 JS::Value *vp)
 {
     GJS_GET_PRIV(context, argc, vp, rec, self, Error, priv);
-    JS::Value v_out;
     gchar *descr;
     bool retval;
 
     if (priv == NULL)
         return false;
 
-    v_out = JS::UndefinedValue();
+    rec.rval().setUndefined();
     retval = false;
 
     /* We follow the same pattern as standard JS errors, at the expense of
@@ -226,7 +219,7 @@ error_to_string(JSContext *context,
                                 g_base_info_get_namespace(priv->info),
                                 g_base_info_get_name(priv->info));
 
-        if (!gjs_string_from_utf8(context, descr, -1, &v_out))
+        if (!gjs_string_from_utf8(context, descr, -1, rec.rval()))
             goto out;
     } else {
         descr = g_strdup_printf("%s.%s: %s",
@@ -234,11 +227,10 @@ error_to_string(JSContext *context,
                                 g_base_info_get_name(priv->info),
                                 priv->gerror->message);
 
-        if (!gjs_string_from_utf8(context, descr, -1, &v_out))
+        if (!gjs_string_from_utf8(context, descr, -1, rec.rval()))
             goto out;
     }
 
-    rec.rval().set(v_out);
     retval = true;
 
  out:
diff --git a/gi/gtype.cpp b/gi/gtype.cpp
index 6c3518c..84ff1c7 100644
--- a/gi/gtype.cpp
+++ b/gi/gtype.cpp
@@ -69,7 +69,6 @@ to_string_func(JSContext *context,
     GType gtype;
     gchar *strval;
     bool ret;
-    JS::Value retval;
 
     gtype = GPOINTER_TO_SIZE(priv);
 
@@ -78,9 +77,7 @@ to_string_func(JSContext *context,
     else
         strval = g_strdup_printf("[object GType for '%s']",
                                  g_type_name(gtype));
-    ret = gjs_string_from_utf8(context, strval, -1, &retval);
-    if (ret)
-        rec.rval().set(retval);
+    ret = gjs_string_from_utf8(context, strval, -1, rec.rval());
     g_free(strval);
     return ret;
 }
@@ -92,20 +89,14 @@ get_name_func (JSContext *context,
 {
     GJS_GET_PRIV(context, argc, vp, rec, obj, void, priv);
     GType gtype;
-    bool ret;
-    JS::Value retval;
 
     gtype = GPOINTER_TO_SIZE(priv);
 
     if (gtype == 0) {
         rec.rval().setNull();
         return true;
-    } else {
-        ret = gjs_string_from_utf8(context, g_type_name(gtype), -1, &retval);
-        if (ret)
-            rec.rval().set(retval);
-        return ret;
     }
+    return gjs_string_from_utf8(context, g_type_name(gtype), -1, rec.rval());
 }
 
 /* Properties */
diff --git a/gi/interface.cpp b/gi/interface.cpp
index cee0538..d06199a 100644
--- a/gi/interface.cpp
+++ b/gi/interface.cpp
@@ -239,9 +239,9 @@ gjs_define_interface_class(JSContext       *context,
 }
 
 bool
-gjs_lookup_interface_constructor(JSContext *context,
-                                 GType      gtype,
-                                 JS::Value *value_p)
+gjs_lookup_interface_constructor(JSContext             *context,
+                                 GType                  gtype,
+                                 JS::MutableHandleValue value_p)
 {
     JSObject *constructor;
     GIBaseInfo *interface_info;
@@ -263,6 +263,6 @@ gjs_lookup_interface_constructor(JSContext *context,
 
     g_base_info_unref(interface_info);
 
-    *value_p = JS::ObjectValue(*constructor);
+    value_p.setObject(*constructor);
     return true;
 }
diff --git a/gi/interface.h b/gi/interface.h
index 4640f8a..0dc5e56 100644
--- a/gi/interface.h
+++ b/gi/interface.h
@@ -38,9 +38,9 @@ bool gjs_define_interface_class (JSContext       *context,
                                  GType            gtype,
                                  JSObject       **constructor_p);
 
-bool gjs_lookup_interface_constructor (JSContext     *context,
-                                       GType          gtype,
-                                       JS::Value     *value_p);
+bool gjs_lookup_interface_constructor(JSContext             *context,
+                                      GType                  gtype,
+                                      JS::MutableHandleValue value_p);
 
 G_END_DECLS
 
diff --git a/gi/ns.cpp b/gi/ns.cpp
index b89f948..33335ba 100644
--- a/gi/ns.cpp
+++ b/gi/ns.cpp
@@ -132,19 +132,11 @@ get_name (JSContext *context,
           JS::Value *vp)
 {
     GJS_GET_PRIV(context, argc, vp, args, obj, Ns, priv);
-    JS::Value retval;
-    bool ret = false;
 
     if (priv == NULL)
-        goto out;
+        return false;
 
-    if (gjs_string_from_utf8(context, priv->gi_namespace, -1, &retval)) {
-        args.rval().set(retval);
-        ret = true;
-    }
-
- out:
-    return ret;
+    return gjs_string_from_utf8(context, priv->gi_namespace, -1, args.rval());
 }
 
 GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT(ns)
diff --git a/gi/object.cpp b/gi/object.cpp
index 0a8444e..6231f62 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -305,7 +305,7 @@ object_instance_get_prop(JSContext              *context,
     g_value_init(&gvalue, G_PARAM_SPEC_VALUE_TYPE(param));
     g_object_get_property(priv->gobj, param->name,
                           &gvalue);
-    if (!gjs_value_from_g_value(context, value_p.address(), &gvalue)) {
+    if (!gjs_value_from_g_value(context, value_p, &gvalue)) {
         g_value_unset(&gvalue);
         ret = false;
         goto out;
@@ -1671,7 +1671,6 @@ emit_func(JSContext *context,
     GValue rvalue = G_VALUE_INIT;
     unsigned int i;
     bool failed;
-    JS::Value retval;
     bool ret = false;
 
     gjs_debug_gsignal("emit obj %p priv %p argc %d", obj.get(), priv, argc);
@@ -1750,23 +1749,18 @@ emit_func(JSContext *context,
     }
 
     if (signal_query.return_type != G_TYPE_NONE) {
-        if (!gjs_value_from_g_value(context,
-                                    &retval,
-                                    &rvalue))
+        if (!gjs_value_from_g_value(context, argv.rval(), &rvalue))
             failed = true;
 
         g_value_unset(&rvalue);
     } else {
-        retval.setUndefined();
+        argv.rval().setUndefined();
     }
 
     for (i = 0; i < (signal_query.n_params + 1); ++i) {
         g_value_unset(&instance_and_args[i]);
     }
 
-    if (!failed)
-        argv.rval().set(retval);
-
     ret = !failed;
  out:
     g_free(signal_name);
@@ -1779,22 +1773,17 @@ to_string_func(JSContext *context,
                JS::Value *vp)
 {
     GJS_GET_PRIV(context, argc, vp, rec, obj, ObjectInstance, priv);
-    bool ret = false;
-    JS::Value retval;
 
     if (priv == NULL) {
         throw_priv_is_null_error(context);
-        goto out;  /* wrong class passed in */
+        return false;  /* wrong class passed in */
     }
     
     if (!_gjs_proxy_to_string_func(context, obj, "object", (GIBaseInfo*)priv->info,
-                                   priv->gtype, priv->gobj, &retval))
-        goto out;
+                                   priv->gtype, priv->gobj, rec.rval()))
+        return false;
 
-    ret = true;
-    rec.rval().set(retval);
- out:
-    return ret;
+    return true;
 }
 
 struct JSClass gjs_object_instance_class = {
@@ -2393,14 +2382,14 @@ jsobj_set_gproperty (JSContext    *context,
                      const GValue *value,
                      GParamSpec   *pspec)
 {
-    JS::Value jsvalue;
+    JS::RootedValue jsvalue(context);
     gchar *underscore_name;
 
     if (!gjs_value_from_g_value(context, &jsvalue, value))
         return;
 
     underscore_name = hyphen_to_underscore((gchar *)pspec->name);
-    if (!JS_SetProperty(context, object, underscore_name, &jsvalue))
+    if (!JS_SetProperty(context, object, underscore_name, jsvalue.address()))
         gjs_log_exception(context);
     g_free (underscore_name);
 }
@@ -3051,9 +3040,9 @@ gjs_define_private_gi_stuff(JSContext *context,
 }
 
 bool
-gjs_lookup_object_constructor(JSContext *context,
-                              GType      gtype,
-                              JS::Value *value_p)
+gjs_lookup_object_constructor(JSContext             *context,
+                              GType                  gtype,
+                              JS::MutableHandleValue value_p)
 {
     JSObject *constructor;
     GIObjectInfo *object_info;
@@ -3072,6 +3061,6 @@ gjs_lookup_object_constructor(JSContext *context,
     if (object_info)
         g_base_info_unref((GIBaseInfo*)object_info);
 
-    *value_p = JS::ObjectValue(*constructor);
+    value_p.setObject(*constructor);
     return true;
 }
diff --git a/gi/object.h b/gi/object.h
index 4eb77a5..f09d473 100644
--- a/gi/object.h
+++ b/gi/object.h
@@ -36,9 +36,11 @@ void      gjs_define_object_class       (JSContext     *context,
                                          GIObjectInfo  *info,
                                          GType          gtype,
                                          JSObject     **constructor_p);
-bool      gjs_lookup_object_constructor (JSContext     *context,
-                                         GType          gtype,
-                                         JS::Value     *value_p);
+
+bool gjs_lookup_object_constructor(JSContext             *context,
+                                   GType                  gtype,
+                                   JS::MutableHandleValue value_p);
+
 JSObject* gjs_object_from_g_object      (JSContext     *context,
                                          GObject       *gobj);
 
diff --git a/gi/proxyutils.cpp b/gi/proxyutils.cpp
index d7fe5cc..df0063a 100644
--- a/gi/proxyutils.cpp
+++ b/gi/proxyutils.cpp
@@ -32,13 +32,13 @@
  * and a memory address.
  */
 bool
-_gjs_proxy_to_string_func(JSContext  *context,
-                          JSObject   *this_obj,
-                          const char *objtype,
-                          GIBaseInfo *info,
-                          GType       gtype,
-                          gpointer    native_address,
-                          JS::Value  *rval)
+_gjs_proxy_to_string_func(JSContext             *context,
+                          JSObject              *this_obj,
+                          const char            *objtype,
+                          GIBaseInfo            *info,
+                          GType                  gtype,
+                          gpointer               native_address,
+                          JS::MutableHandleValue rval)
 {
     GString *buf;
     bool ret = false;
diff --git a/gi/proxyutils.h b/gi/proxyutils.h
index dc1e051..e689cb6 100644
--- a/gi/proxyutils.h
+++ b/gi/proxyutils.h
@@ -29,13 +29,13 @@
 
 G_BEGIN_DECLS
 
-bool _gjs_proxy_to_string_func (JSContext  *context,
-                                JSObject   *this_obj,
-                                const char *objtype,
-                                GIBaseInfo *info,
-                                GType       gtype,
-                                gpointer    native_address,
-                                JS::Value  *ret);
+bool _gjs_proxy_to_string_func(JSContext             *context,
+                               JSObject              *this_obj,
+                               const char            *objtype,
+                               GIBaseInfo            *info,
+                               GType                  gtype,
+                               gpointer               native_address,
+                               JS::MutableHandleValue ret);
 
 G_END_DECLS
 
diff --git a/gi/repo.cpp b/gi/repo.cpp
index 2f5ae4e..1b60039 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -350,7 +350,7 @@ gjs_define_constant(JSContext      *context,
                     JSObject       *in_object,
                     GIConstantInfo *info)
 {
-    JS::Value value;
+    JS::RootedValue value(context);
     GArgument garg = { 0, };
     GITypeInfo *type_info;
     const char *name;
diff --git a/gi/union.cpp b/gi/union.cpp
index cd5c2de..a494622 100644
--- a/gi/union.cpp
+++ b/gi/union.cpp
@@ -288,17 +288,9 @@ to_string_func(JSContext *context,
                JS::Value *vp)
 {
     GJS_GET_PRIV(context, argc, vp, rec, obj, Union, priv);
-    bool ret = false;
-    JS::Value retval;
-
-    if (!_gjs_proxy_to_string_func(context, obj, "union", (GIBaseInfo*)priv->info,
-                                   priv->gtype, priv->gboxed, &retval))
-        goto out;
-
-    ret = true;
-    rec.rval().set(retval);
- out:
-    return ret;
+    return _gjs_proxy_to_string_func(context, obj, "union",
+                                     (GIBaseInfo*)priv->info, priv->gtype,
+                                     priv->gboxed, rec.rval());
 }
 
 /* The bizarre thing about this vtable is that it applies to both
diff --git a/gi/value.cpp b/gi/value.cpp
index a71c07f..f34017a 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -40,12 +40,12 @@
 
 #include <girepository.h>
 
-static bool gjs_value_from_g_value_internal(JSContext    *context,
-                                            JS::Value    *value_p,
-                                            const GValue *gvalue,
-                                            bool          no_copy,
-                                            GSignalQuery *signal_query,
-                                            gint          arg_n);
+static bool gjs_value_from_g_value_internal(JSContext             *context,
+                                            JS::MutableHandleValue value_p,
+                                            const GValue          *gvalue,
+                                            bool                   no_copy,
+                                            GSignalQuery          *signal_query,
+                                            int                    arg_n);
 
 /*
  * Gets signal introspection info about closure, or NULL if not found. Currently
@@ -83,16 +83,16 @@ get_signal_info_if_available(GSignalQuery *signal_query)
  * in array_value, with its length stored in array_length_value.
  */
 static bool
-gjs_value_from_array_and_length_values(JSContext    *context,
-                                       JS::Value    *value_p,
-                                       GITypeInfo   *array_type_info,
-                                       const GValue *array_value,
-                                       const GValue *array_length_value,
-                                       bool          no_copy,
-                                       GSignalQuery *signal_query,
-                                       int           array_length_arg_n)
+gjs_value_from_array_and_length_values(JSContext             *context,
+                                       JS::MutableHandleValue value_p,
+                                       GITypeInfo            *array_type_info,
+                                       const GValue          *array_value,
+                                       const GValue          *array_length_value,
+                                       bool                   no_copy,
+                                       GSignalQuery          *signal_query,
+                                       int                    array_length_arg_n)
 {
-    JS::Value array_length;
+    JS::RootedValue array_length(context);
     GArgument array_arg;
 
     g_assert(G_VALUE_HOLDS_POINTER(array_value));
@@ -172,8 +172,7 @@ closure_marshal(GClosure        *closure,
     argc = n_param_values;
     rval = JS::UndefinedValue();
     JS::AutoValueVector argv(context);
-    for (i = 0; i < argc; i++)
-        argv.append(JS::UndefinedValue());
+    argv.resize(argc);
 
     JS_AddValueRoot(context, &rval);
 
@@ -251,13 +250,14 @@ closure_marshal(GClosure        *closure,
         if (array_len_index != -1) {
             const GValue *array_len_gval = &param_values[array_len_index];
             res = gjs_value_from_array_and_length_values(context,
-                                                         &argv[argv_index],
+                                                         argv.handleAt(argv_index),
                                                          type_info_for[i],
                                                          gval, array_len_gval,
                                                          no_copy, &signal_query,
                                                          array_len_index);
         } else {
-            res = gjs_value_from_g_value_internal(context, &argv[argv_index],
+            res = gjs_value_from_g_value_internal(context,
+                                                  argv.handleAt(argv_index),
                                                   gval, no_copy, &signal_query,
                                                   i);
         }
@@ -776,12 +776,12 @@ convert_int_to_enum (GType  gtype,
 }
 
 static bool
-gjs_value_from_g_value_internal(JSContext    *context,
-                                JS::Value    *value_p,
-                                const GValue *gvalue,
-                                bool          no_copy,
-                                GSignalQuery *signal_query,
-                                gint          arg_n)
+gjs_value_from_g_value_internal(JSContext             *context,
+                                JS::MutableHandleValue value_p,
+                                const GValue          *gvalue,
+                                bool                   no_copy,
+                                GSignalQuery          *signal_query,
+                                int                    arg_n)
 {
     GType gtype;
 
@@ -797,7 +797,7 @@ gjs_value_from_g_value_internal(JSContext    *context,
         if (v == NULL) {
             gjs_debug_marshal(GJS_DEBUG_GCLOSURE,
                               "Converting NULL string to JS::NullValue()");
-            *value_p = JS::NullValue();
+            value_p.setNull();
         } else {
             if (!gjs_string_from_utf8(context, v, -1, value_p))
                 return false;
@@ -805,31 +805,31 @@ gjs_value_from_g_value_internal(JSContext    *context,
     } else if (gtype == G_TYPE_CHAR) {
         char v;
         v = g_value_get_schar(gvalue);
-        *value_p = JS::Int32Value(v);
+        value_p.setInt32(v);
     } else if (gtype == G_TYPE_UCHAR) {
         unsigned char v;
         v = g_value_get_uchar(gvalue);
-        *value_p = JS::Int32Value(v);
+        value_p.setInt32(v);
     } else if (gtype == G_TYPE_INT) {
         int v;
         v = g_value_get_int(gvalue);
-        *value_p = JS::NumberValue(v);
+        value_p.set(JS::NumberValue(v));
     } else if (gtype == G_TYPE_UINT) {
         guint v;
         v = g_value_get_uint(gvalue);
-        *value_p = JS::NumberValue(v);
+        value_p.setNumber(v);
     } else if (gtype == G_TYPE_DOUBLE) {
         double d;
         d = g_value_get_double(gvalue);
-        *value_p = JS::NumberValue(d);
+        value_p.setNumber(d);
     } else if (gtype == G_TYPE_FLOAT) {
         double d;
         d = g_value_get_float(gvalue);
-        *value_p = JS::NumberValue(d);
+        value_p.setNumber(d);
     } else if (gtype == G_TYPE_BOOLEAN) {
         bool v;
         v = g_value_get_boolean(gvalue);
-        *value_p = JS::BooleanValue(!!v);
+        value_p.setBoolean(!!v);
     } else if (g_type_is_a(gtype, G_TYPE_OBJECT) || g_type_is_a(gtype, G_TYPE_INTERFACE)) {
         GObject *gobj;
         JSObject *obj;
@@ -837,7 +837,7 @@ gjs_value_from_g_value_internal(JSContext    *context,
         gobj = (GObject*) g_value_get_object(gvalue);
 
         obj = gjs_object_from_g_object(context, gobj);
-        *value_p = JS::ObjectOrNullValue(obj);
+        value_p.setObjectOrNull(obj);
     } else if (gtype == G_TYPE_STRV) {
         if (!gjs_array_from_strv (context,
                                   value_p,
@@ -868,7 +868,7 @@ gjs_value_from_g_value_internal(JSContext    *context,
         /* special case GError */
         if (g_type_is_a(gtype, G_TYPE_ERROR)) {
             obj = gjs_error_from_gerror(context, (GError*) gboxed, false);
-            *value_p = JS::ObjectOrNullValue(obj);
+            value_p.setObjectOrNull(obj);
 
             return true;
         }
@@ -913,10 +913,10 @@ gjs_value_from_g_value_internal(JSContext    *context,
             return false;
         }
 
-        *value_p = JS::ObjectOrNullValue(obj);
+        value_p.setObjectOrNull(obj);
         g_base_info_unref(info);
     } else if (g_type_is_a(gtype, G_TYPE_ENUM)) {
-        *value_p = convert_int_to_enum(gtype, g_value_get_enum(gvalue));
+        value_p.set(convert_int_to_enum(gtype, g_value_get_enum(gvalue)));
     } else if (g_type_is_a(gtype, G_TYPE_PARAM)) {
         GParamSpec *gparam;
         JSObject *obj;
@@ -924,7 +924,7 @@ gjs_value_from_g_value_internal(JSContext    *context,
         gparam = g_value_get_param(gvalue);
 
         obj = gjs_param_from_g_param(context, gparam);
-        *value_p = JS::ObjectOrNullValue(obj);
+        value_p.setObjectOrNull(obj);
     } else if (signal_query && g_type_is_a(gtype, G_TYPE_POINTER)) {
         bool res;
         GArgument arg;
@@ -968,7 +968,7 @@ gjs_value_from_g_value_internal(JSContext    *context,
         pointer = g_value_get_pointer(gvalue);
 
         if (pointer == NULL) {
-            *value_p = JS::NullValue();
+            value_p.setNull();
         } else {
             gjs_throw(context,
                       "Can't convert non-null pointer to JS value");
@@ -980,14 +980,14 @@ gjs_value_from_g_value_internal(JSContext    *context,
         g_value_init(&double_value, G_TYPE_DOUBLE);
         g_value_transform(gvalue, &double_value);
         v = g_value_get_double(&double_value);
-        *value_p = JS::NumberValue(v);
+        value_p.setNumber(v);
     } else if (g_value_type_transformable(gtype, G_TYPE_INT)) {
         GValue int_value = { 0, };
         int v;
         g_value_init(&int_value, G_TYPE_INT);
         g_value_transform(gvalue, &int_value);
         v = g_value_get_int(&int_value);
-        *value_p = JS::NumberValue(v);
+        value_p.set(JS::NumberValue(v));
     } else if (G_TYPE_IS_INSTANTIATABLE(gtype)) {
         /* The gtype is none of the above, it should be a custom
            fundamental type. */
@@ -996,7 +996,7 @@ gjs_value_from_g_value_internal(JSContext    *context,
         if (obj == NULL)
             return false;
         else
-            *value_p = JS::ObjectValue(*obj);
+            value_p.setObject(*obj);
     } else {
         gjs_throw(context,
                   "Don't know how to convert GType %s to JavaScript object",
@@ -1008,9 +1008,9 @@ gjs_value_from_g_value_internal(JSContext    *context,
 }
 
 bool
-gjs_value_from_g_value(JSContext    *context,
-                       JS::Value    *value_p,
-                       const GValue *gvalue)
+gjs_value_from_g_value(JSContext             *context,
+                       JS::MutableHandleValue value_p,
+                       const GValue          *gvalue)
 {
     return gjs_value_from_g_value_internal(context, value_p, gvalue, false, NULL, 0);
 }
diff --git a/gi/value.h b/gi/value.h
index 84210fa..f7613f9 100644
--- a/gi/value.h
+++ b/gi/value.h
@@ -36,9 +36,11 @@ bool       gjs_value_to_g_value         (JSContext    *context,
 bool       gjs_value_to_g_value_no_copy (JSContext    *context,
                                          JS::Value     value,
                                          GValue       *gvalue);
-bool       gjs_value_from_g_value       (JSContext    *context,
-                                         JS::Value    *value_p,
-                                         const GValue *gvalue);
+
+bool gjs_value_from_g_value(JSContext             *context,
+                            JS::MutableHandleValue value_p,
+                            const GValue          *gvalue);
+
 GClosure*  gjs_closure_new_marshaled    (JSContext    *context,
                                          JSObject     *callable,
                                          const char   *description);
diff --git a/gjs/byteArray.cpp b/gjs/byteArray.cpp
index 2e051e2..204b5ef 100644
--- a/gjs/byteArray.cpp
+++ b/gjs/byteArray.cpp
@@ -444,16 +444,8 @@ to_string_func(JSContext *context,
         /* optimization, avoids iconv overhead and runs
          * libmozjs hardwired utf8-to-utf16
          */
-        JS::Value retval;
-        bool ok;
-
-        ok = gjs_string_from_utf8(context,
-                                  data,
-                                  priv->array->len,
-                                  &retval);
-        if (ok)
-            argv.rval().set(retval);
-        return ok;
+        return gjs_string_from_utf8(context, data, priv->array->len,
+                                    argv.rval());
     } else {
         bool ok = false;
         gsize bytes_written;
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index 3202667..1b8d72c 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -791,14 +791,13 @@ importer_new_enumerate(JSContext  *context,
     }
 
     case JSENUMERATE_NEXT: {
-        JS::Value element_val;
-
         if (statep.isNull()) /* Iterating prototype */
             return true;
 
         iter = (ImporterIterator*) statep.get().toPrivate();
 
         if (iter->index < iter->elements->len) {
+            JS::RootedValue element_val(context);
             if (!gjs_string_from_utf8(context,
                                          (const char*) g_ptr_array_index(iter->elements,
                                                            iter->index++),
diff --git a/gjs/jsapi-util-error.cpp b/gjs/jsapi-util-error.cpp
index c6849a7..8888b9b 100644
--- a/gjs/jsapi-util-error.cpp
+++ b/gjs/jsapi-util-error.cpp
@@ -49,7 +49,7 @@ gjs_throw_valist(JSContext       *context,
 {
     char *s;
     bool result;
-    JS::Value v_constructor, v_message;
+    JS::Value v_constructor;
     JSObject *err_obj;
 
     s = g_strdup_vprintf(format, args);
@@ -75,6 +75,7 @@ gjs_throw_valist(JSContext       *context,
         return;
     }
 
+    JS::RootedValue v_message(context);
     result = false;
 
     if (!gjs_string_from_utf8(context, s, -1, &v_message)) {
@@ -89,7 +90,7 @@ gjs_throw_valist(JSContext       *context,
     }
 
     /* throw new Error(message) */
-    err_obj = JS_New(context, &v_constructor.toObject(), 1, &v_message);
+    err_obj = JS_New(context, &v_constructor.toObject(), 1, v_message.address());
     JS_SetPendingException(context, JS::ObjectOrNullValue(err_obj));
 
     result = true;
diff --git a/gjs/jsapi-util-string.cpp b/gjs/jsapi-util-string.cpp
index dbab5eb..ebec900 100644
--- a/gjs/jsapi-util-string.cpp
+++ b/gjs/jsapi-util-string.cpp
@@ -65,14 +65,13 @@ gjs_string_to_utf8 (JSContext      *context,
 }
 
 bool
-gjs_string_from_utf8(JSContext  *context,
-                     const char *utf8_string,
-                     gssize      n_bytes,
-                     JS::Value  *value_p)
+gjs_string_from_utf8(JSContext             *context,
+                     const char            *utf8_string,
+                     ssize_t                n_bytes,
+                     JS::MutableHandleValue value_p)
 {
     jschar *u16_string;
     glong u16_string_length;
-    JSString *str;
     GError *error;
 
     /* intentionally using n_bytes even though glib api suggests n_chars; with
@@ -97,10 +96,10 @@ gjs_string_from_utf8(JSContext  *context,
     JS_BeginRequest(context);
 
     /* Avoid a copy - assumes that g_malloc == js_malloc == malloc */
-    str = JS_NewUCString(context, u16_string, u16_string_length);
-
-    if (str && value_p)
-        *value_p = JS::StringValue(str);
+    JS::RootedString str(context,
+                         JS_NewUCString(context, u16_string, u16_string_length));
+    if (str)
+        value_p.setString(str);
 
     JS_EndRequest(context);
     return str != NULL;
@@ -135,10 +134,10 @@ gjs_string_to_filename(JSContext      *context,
 }
 
 bool
-gjs_string_from_filename(JSContext  *context,
-                         const char *filename_string,
-                         gssize      n_bytes,
-                         JS::Value  *value_p)
+gjs_string_from_filename(JSContext             *context,
+                         const char            *filename_string,
+                         ssize_t                n_bytes,
+                         JS::MutableHandleValue value_p)
 {
     gsize written;
     GError *error;
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 2016a86..36f34ab 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -403,17 +403,19 @@ bool        gjs_delete_prop_verbose_stub     (JSContext       *context,
 JSBool      gjs_string_to_utf8               (JSContext       *context,
                                               const JS::Value  string_val,
                                               char           **utf8_string_p);
-bool        gjs_string_from_utf8             (JSContext       *context,
-                                              const char      *utf8_string,
-                                              gssize           n_bytes,
-                                              JS::Value       *value_p);
+bool gjs_string_from_utf8(JSContext             *context,
+                          const char            *utf8_string,
+                          ssize_t                n_bytes,
+                          JS::MutableHandleValue value_p);
+
 JSBool      gjs_string_to_filename           (JSContext       *context,
                                               const JS::Value  string_val,
                                               char           **filename_string_p);
-bool        gjs_string_from_filename         (JSContext       *context,
-                                              const char      *filename_string,
-                                              gssize           n_bytes,
-                                              JS::Value       *value_p);
+bool gjs_string_from_filename(JSContext             *context,
+                              const char            *filename_string,
+                              ssize_t                n_bytes,
+                              JS::MutableHandleValue value_p);
+
 bool        gjs_string_get_uint16_data       (JSContext       *context,
                                               JS::Value        value,
                                               guint16        **data_p,
diff --git a/gjs/runtime.cpp b/gjs/runtime.cpp
index de2e779..97c7804 100644
--- a/gjs/runtime.cpp
+++ b/gjs/runtime.cpp
@@ -58,7 +58,7 @@ gjs_locale_to_upper_case (JSContext *context,
 
     upper_case_utf8 = g_utf8_strup (utf8, -1);
 
-    if (!gjs_string_from_utf8(context, upper_case_utf8, -1, retval.address()))
+    if (!gjs_string_from_utf8(context, upper_case_utf8, -1, retval))
         goto out;
 
     success = true;
@@ -84,7 +84,7 @@ gjs_locale_to_lower_case (JSContext *context,
 
     lower_case_utf8 = g_utf8_strdown (utf8, -1);
 
-    if (!gjs_string_from_utf8(context, lower_case_utf8, -1, retval.address()))
+    if (!gjs_string_from_utf8(context, lower_case_utf8, -1, retval))
         goto out;
 
     success = true;
@@ -138,7 +138,7 @@ gjs_locale_to_unicode (JSContext  *context,
         return false;
     }
 
-    success = gjs_string_from_utf8(context, utf8, -1, retval.address());
+    success = gjs_string_from_utf8(context, utf8, -1, retval);
     g_free (utf8);
 
     return success;
diff --git a/modules/cairo-context.cpp b/modules/cairo-context.cpp
index 128ef7a..b553c8f 100644
--- a/modules/cairo-context.cpp
+++ b/modules/cairo-context.cpp
@@ -968,9 +968,9 @@ context_to_g_argument(JSContext      *context,
 }
 
 static bool
-context_from_g_argument(JSContext  *context,
-                        JS::Value  *value_p,
-                        GArgument  *arg)
+context_from_g_argument(JSContext             *context,
+                        JS::MutableHandleValue value_p,
+                        GIArgument            *arg)
 {
     JSObject *obj;
 
@@ -978,7 +978,7 @@ context_from_g_argument(JSContext  *context,
     if (!obj)
         return false;
 
-    *value_p = JS::ObjectValue(*obj);
+    value_p.setObject(*obj);
     return true;
 }
 
diff --git a/modules/cairo-region.cpp b/modules/cairo-region.cpp
index 67a3651..9324c93 100644
--- a/modules/cairo-region.cpp
+++ b/modules/cairo-region.cpp
@@ -305,9 +305,9 @@ region_to_g_argument(JSContext      *context,
 }
 
 static bool
-region_from_g_argument(JSContext  *context,
-                       JS::Value  *value_p,
-                       GArgument  *arg)
+region_from_g_argument(JSContext             *context,
+                       JS::MutableHandleValue value_p,
+                       GIArgument            *arg)
 {
     JSObject *obj;
 
@@ -315,7 +315,7 @@ region_from_g_argument(JSContext  *context,
     if (!obj)
         return false;
 
-    *value_p = JS::ObjectValue(*obj);
+    value_p.setObject(*obj);
     return true;
 }
 
diff --git a/modules/cairo-surface.cpp b/modules/cairo-surface.cpp
index 2b05528..df28824 100644
--- a/modules/cairo-surface.cpp
+++ b/modules/cairo-surface.cpp
@@ -266,9 +266,9 @@ surface_to_g_argument(JSContext      *context,
 }
 
 static bool
-surface_from_g_argument(JSContext  *context,
-                        JS::Value  *value_p,
-                        GArgument  *arg)
+surface_from_g_argument(JSContext             *context,
+                        JS::MutableHandleValue value_p,
+                        GIArgument            *arg)
 {
     JSObject *obj;
 
@@ -276,7 +276,7 @@ surface_from_g_argument(JSContext  *context,
     if (!obj)
         return false;
 
-    *value_p = JS::ObjectValue(*obj);
+    value_p.setObject(*obj);
     return true;
 }
 
diff --git a/modules/system.cpp b/modules/system.cpp
index bab0667..612088f 100644
--- a/modules/system.cpp
+++ b/modules/system.cpp
@@ -42,19 +42,15 @@ gjs_address_of(JSContext *context,
     JSObject *target_obj;
     bool ret;
     char *pointer_string;
-    JS::Value retval;
 
     if (!gjs_parse_call_args(context, "addressOf", "o", argv, "object", &target_obj))
         return false;
 
     pointer_string = g_strdup_printf("%p", target_obj);
 
-    ret = gjs_string_from_utf8(context, pointer_string, -1, &retval);
-    g_free(pointer_string);
-
-    if (ret)
-        argv.rval().set(retval);
+    ret = gjs_string_from_utf8(context, pointer_string, -1, argv.rval());
 
+    g_free(pointer_string);
     return ret;
 }
 
@@ -156,7 +152,6 @@ gjs_js_define_system_stuff(JSContext  *context,
 {
     GjsContext *gjs_context;
     char *program_name;
-    JS::Value value;
     bool retval;
     JSObject *module;
 
@@ -172,6 +167,7 @@ gjs_js_define_system_stuff(JSContext  *context,
                  "program-name", &program_name,
                  NULL);
 
+    JS::RootedValue value(context);
     if (!gjs_string_from_utf8(context, program_name,
                               -1, &value))
         goto out;
diff --git a/test/gjs-tests.cpp b/test/gjs-tests.cpp
index 0e24ee4..a2141da 100644
--- a/test/gjs-tests.cpp
+++ b/test/gjs-tests.cpp
@@ -100,10 +100,10 @@ gjstest_test_func_gjs_jsapi_util_string_js_string_utf8(void)
 
     const char *utf8_string = "\303\211\303\226 foobar \343\203\237";
     char *utf8_result;
-    JS::Value js_string;
 
     _gjs_unit_test_fixture_begin(&fixture);
     context = fixture.context;
+    JS::RootedValue js_string(context);
     global = gjs_get_global_object(context);
     JSCompartment *oldCompartment = JS_EnterCompartment(context, global);
 


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