[gjs: 14/16] js: Replace GjsAutoJSChar with JS::UniqueChars



commit d4d7d2e5a288e850acdba30cbe03f9e30501eebf
Author: Philip Chimento <philip chimento gmail com>
Date:   Mon Oct 8 00:47:55 2018 -0700

    js: Replace GjsAutoJSChar with JS::UniqueChars
    
    SpiderMonkey now provides its own unique char* type with the correct free
    function, so we should just use that instead of maintaining our own.

 .clang-format               |  2 ++
 gi/arg.cpp                  | 29 ++++++++++++-----------
 gi/boxed.cpp                | 21 +++++++----------
 gi/fundamental.cpp          | 36 ++++++++++------------------
 gi/gerror.cpp               | 12 +++++-----
 gi/interface.cpp            | 20 +++++-----------
 gi/ns.cpp                   |  4 ++--
 gi/object.cpp               | 57 +++++++++++++++++++++++----------------------
 gi/param.cpp                |  5 ++--
 gi/private.cpp              | 30 ++++++++++++------------
 gi/repo.cpp                 | 19 ++++++---------
 gi/union.cpp                | 28 +++++++---------------
 gi/value.cpp                |  4 ++--
 gjs/byteArray.cpp           | 20 ++++++++--------
 gjs/debugger.cpp            |  2 +-
 gjs/deprecation.cpp         |  6 ++---
 gjs/engine.cpp              | 14 +++++------
 gjs/global.cpp              |  6 ++---
 gjs/importer.cpp            | 24 ++++++++++---------
 gjs/jsapi-util-args.h       | 13 ++++-------
 gjs/jsapi-util-error.cpp    |  7 +++---
 gjs/jsapi-util-string.cpp   | 22 +++++++----------
 gjs/jsapi-util.cpp          | 56 +++++++++++++++++++++-----------------------
 gjs/jsapi-util.h            | 36 ++++++----------------------
 modules/cairo-context.cpp   |  8 +++----
 test/gjs-test-call-args.cpp | 19 +++++++++------
 test/gjs-tests.cpp          |  8 +++----
 27 files changed, 223 insertions(+), 285 deletions(-)
---
diff --git a/.clang-format b/.clang-format
index 44a21ec5..e80eb0c0 100644
--- a/.clang-format
+++ b/.clang-format
@@ -13,6 +13,8 @@ DerivePointerAlignment: false
 ForEachMacros: []
 IndentPPDirectives: AfterHash
 IndentWidth: 4
+MacroBlockBegin: "^JSNATIVE_TEST_FUNC_BEGIN$"
+MacroBlockEnd: "^JSNATIVE_TEST_FUNC_END$"
 PointerAlignment: Left  # Google style allows both, but clang-format doesn't
 SpacesBeforeTrailingComments: 2
 ---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index b0979fbc..fef13070 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -432,10 +432,10 @@ value_to_ghashtable_key(JSContext      *cx,
         else
             str = value.toString();
 
-        GjsAutoJSChar cstr = JS_EncodeStringToUTF8(cx, str);
+        JS::UniqueChars cstr(JS_EncodeStringToUTF8(cx, str));
         if (!cstr)
             return false;
-        *pointer_out = cstr.copy();
+        *pointer_out = g_strdup(cstr.get());
         break;
     }
 
@@ -627,12 +627,12 @@ gjs_array_to_strv(JSContext   *context,
             return false;
         }
 
-        GjsAutoJSChar tmp_result;
+        JS::UniqueChars tmp_result;
         if (!gjs_string_to_utf8(context, elem, &tmp_result)) {
             g_strfreev(result);
             return false;
         }
-        result[i] = tmp_result.copy();
+        result[i] = g_strdup(tmp_result.get());
     }
 
     *arr_p = result;
@@ -653,11 +653,11 @@ gjs_string_to_intarray(JSContext       *context,
     element_type = g_type_info_get_tag(param_info);
 
     if (element_type == GI_TYPE_TAG_INT8 || element_type == GI_TYPE_TAG_UINT8) {
-        GjsAutoJSChar result = JS_EncodeStringToUTF8(context, str);
+        JS::UniqueChars result(JS_EncodeStringToUTF8(context, str));
         if (!result)
             return false;
-        *length = strlen(result);
-        *arr_p = result.copy();
+        *length = strlen(result.get());
+        *arr_p = g_strdup(result.get());
         return true;
     }
 
@@ -1517,9 +1517,9 @@ gjs_value_to_g_argument(JSContext      *context,
             arg->v_pointer = NULL;
         } else if (value.isString()) {
             JS::RootedString str(context, value.toString());
-            GjsAutoJSChar utf8_str = JS_EncodeStringToUTF8(context, str);
+            JS::UniqueChars utf8_str(JS_EncodeStringToUTF8(context, str));
             if (utf8_str)
-                arg->v_pointer = utf8_str.copy();
+                arg->v_pointer = g_strdup(utf8_str.get());
             else
                 wrong = true;
         } else {
@@ -1619,15 +1619,15 @@ gjs_value_to_g_argument(JSContext      *context,
                     intern_gdk_atom("NONE", arg);
                 } else {
                     JS::RootedString str(context, value.toString());
-                    GjsAutoJSChar atom_name = JS_EncodeStringToUTF8(context, str);
+                    JS::UniqueChars name(JS_EncodeStringToUTF8(context, str));
 
-                    if (!atom_name) {
+                    if (!name) {
                         wrong = true;
                         g_base_info_unref(interface_info);
                         break;
                     }
 
-                    intern_gdk_atom(atom_name, arg);
+                    intern_gdk_atom(name.get(), arg);
                 }
             } else if (expect_object != value.isObjectOrNull()) {
                 wrong = true;
@@ -2610,7 +2610,7 @@ gjs_object_from_g_hash (JSContext             *context,
         if (!keystr)
             return false;
 
-        GjsAutoJSChar keyutf8 = JS_EncodeStringToUTF8(context, keystr);
+        JS::UniqueChars keyutf8(JS_EncodeStringToUTF8(context, keystr));
         if (!keyutf8)
             return false;
 
@@ -2619,7 +2619,8 @@ gjs_object_from_g_hash (JSContext             *context,
                                        true))
             return false;
 
-        if (!JS_DefineProperty(context, obj, keyutf8, valjs, JSPROP_ENUMERATE))
+        if (!JS_DefineProperty(context, obj, keyutf8.get(), valjs,
+                               JSPROP_ENUMERATE))
             return false;
     }
 
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 66a79c22..f8822b39 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -134,14 +134,15 @@ boxed_resolve(JSContext       *context,
         return true;
     }
 
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     if (!gjs_get_string_id(context, id, &name)) {
         *resolved = false;
         return true;
     }
 
     /* We are the prototype, so look for methods and other class properties */
-    GIFunctionInfo *method_info = g_struct_info_find_method(priv->info, name);
+    GjsAutoFunctionInfo method_info =
+        g_struct_info_find_method(priv->info, name.get());
     if (!method_info) {
         *resolved = false;
         return true;
@@ -151,26 +152,21 @@ boxed_resolve(JSContext       *context,
 #endif
 
     if (g_function_info_get_flags(method_info) & GI_FUNCTION_IS_METHOD) {
-        const char *method_name = g_base_info_get_name(method_info);
-
         gjs_debug(GJS_DEBUG_GBOXED,
                   "Defining method %s in prototype for %s.%s",
-                  method_name,
+                  method_info.name(),
                   g_base_info_get_namespace( (GIBaseInfo*) priv->info),
                   g_base_info_get_name( (GIBaseInfo*) priv->info));
 
         /* obj is the Boxed prototype */
-        if (!gjs_define_function(context, obj, priv->gtype, method_info)) {
-            g_base_info_unref( (GIBaseInfo*) method_info);
+        if (!gjs_define_function(context, obj, priv->gtype, method_info))
             return false;
-        }
 
         *resolved = true;
     } else {
         *resolved = false;
     }
 
-    g_base_info_unref(method_info);
     return true;
 }
 
@@ -265,13 +261,12 @@ boxed_init_from_props(JSContext   *context,
 
     JS::RootedValue value(context);
     for (ix = 0, length = ids.length(); ix < length; ix++) {
-        GIFieldInfo *field_info;
-        GjsAutoJSChar name;
-
+        JS::UniqueChars name;
         if (!gjs_get_string_id(context, ids[ix], &name))
             return false;
 
-        field_info = (GIFieldInfo *) g_hash_table_lookup(priv->field_map, name);
+        auto* field_info = static_cast<GIFieldInfo*>(
+            g_hash_table_lookup(priv->field_map, name.get()));
         if (field_info == NULL) {
             gjs_throw(context, "No field %s on boxed type %s",
                       name.get(), g_base_info_get_name((GIBaseInfo *)priv->info));
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index a8706e9e..6769b188 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -307,7 +307,7 @@ fundamental_instance_resolve(JSContext       *context,
         return true;
     }
 
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     if (!gjs_get_string_id(context, id, &name)) {
         *resolved = false;
         return true; /* not resolved, but no error */
@@ -315,55 +315,43 @@ fundamental_instance_resolve(JSContext       *context,
 
     /* We are the prototype, so look for methods and other class properties */
     Fundamental *proto_priv = (Fundamental *) priv;
-    GIFunctionInfo *method_info;
-
-    method_info = g_object_info_find_method((GIStructInfo*) proto_priv->info,
-                                            name);
-
-    if (method_info != NULL) {
-        const char *method_name;
+    GjsAutoFunctionInfo method_info =
+        g_object_info_find_method(proto_priv->info, name.get());
 
+    if (method_info) {
 #if GJS_VERBOSE_ENABLE_GI_USAGE
-        _gjs_log_info_usage((GIBaseInfo *) method_info);
+        _gjs_log_info_usage(method_info);
 #endif
         if (g_function_info_get_flags (method_info) & GI_FUNCTION_IS_METHOD) {
-            method_name = g_base_info_get_name((GIBaseInfo *) method_info);
-
             /* we do not define deprecated methods in the prototype */
-            if (g_base_info_is_deprecated((GIBaseInfo *) method_info)) {
+            if (g_base_info_is_deprecated(method_info)) {
                 gjs_debug(GJS_DEBUG_GFUNDAMENTAL,
                           "Ignoring definition of deprecated method %s in prototype %s.%s",
-                          method_name,
+                          method_info.name(),
                           g_base_info_get_namespace((GIBaseInfo *) proto_priv->info),
                           g_base_info_get_name((GIBaseInfo *) proto_priv->info));
-                g_base_info_unref((GIBaseInfo *) method_info);
                 *resolved = false;
                 return true;
             }
 
             gjs_debug(GJS_DEBUG_GFUNDAMENTAL,
                       "Defining method %s in prototype for %s.%s",
-                      method_name,
+                      method_info.name(),
                       g_base_info_get_namespace((GIBaseInfo *) proto_priv->info),
                       g_base_info_get_name((GIBaseInfo *) proto_priv->info));
 
-            if (gjs_define_function(context, obj, proto_priv->gtype,
-                                    method_info) == NULL) {
-                g_base_info_unref((GIBaseInfo *) method_info);
+            if (!gjs_define_function(context, obj, proto_priv->gtype,
+                                     method_info))
                 return false;
-            }
 
             *resolved = true;
         }
-
-        g_base_info_unref((GIBaseInfo *) method_info);
     } else {
         *resolved = false;
     }
 
-    bool status =
-        fundamental_instance_resolve_interface(context, obj, resolved,
-                                               proto_priv, name);
+    bool status = fundamental_instance_resolve_interface(
+        context, obj, resolved, proto_priv, name.get());
     return status;
 }
 
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index b25cf598..28ac547f 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -97,7 +97,7 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(error)
     priv->domain = proto_priv->domain;
 
     JS::RootedObject params_obj(context, &argv[0].toObject());
-    GjsAutoJSChar message;
+    JS::UniqueChars message;
     if (!gjs_object_require_property(context, params_obj,
                                      "GError constructor",
                                      GJS_STRING_MESSAGE, &message))
@@ -108,7 +108,7 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(error)
                                      GJS_STRING_CODE, &code))
         return false;
 
-    priv->gerror = g_error_new_literal(priv->domain, code, message);
+    priv->gerror = g_error_new_literal(priv->domain, code, message.get());
 
     /* We assume this error will be thrown in the same line as the constructor */
     define_error_properties(context, object);
@@ -579,7 +579,7 @@ gjs_gerror_make_from_error(JSContext       *cx,
     if (!gjs_object_get_property(cx, obj, GJS_STRING_NAME, &v_name))
         return nullptr;
 
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     if (!gjs_string_to_utf8(cx, v_name, &name))
         return nullptr;
 
@@ -587,19 +587,19 @@ gjs_gerror_make_from_error(JSContext       *cx,
     if (!gjs_object_get_property(cx, obj, GJS_STRING_MESSAGE, &v_message))
         return nullptr;
 
-    GjsAutoJSChar message;
+    JS::UniqueChars message;
     if (!gjs_string_to_utf8(cx, v_message, &message))
         return nullptr;
 
     GjsAutoTypeClass<GEnumClass> klass(GJS_TYPE_JS_ERROR);
-    const GEnumValue *value = g_enum_get_value_by_name(klass, name);
+    const GEnumValue *value = g_enum_get_value_by_name(klass, name.get());
     int code;
     if (value)
         code = value->value;
     else
         code = GJS_JS_ERROR_ERROR;
 
-    return g_error_new_literal(GJS_JS_ERROR, code, message);
+    return g_error_new_literal(GJS_JS_ERROR, code, message.get());
 }
 
 /*
diff --git a/gi/interface.cpp b/gi/interface.cpp
index 88eeee63..ac7467da 100644
--- a/gi/interface.cpp
+++ b/gi/interface.cpp
@@ -112,10 +112,7 @@ interface_resolve(JSContext       *context,
                   JS::HandleId     id,
                   bool            *resolved)
 {
-    Interface *priv;
-    GIFunctionInfo *method_info;
-
-    priv = priv_from_js(context, obj);
+    Interface* priv = priv_from_js(context, obj);
 
     if (priv == nullptr)
         return false;
@@ -128,29 +125,24 @@ interface_resolve(JSContext       *context,
         return true;
     }
 
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     if (!gjs_get_string_id(context, id, &name)) {
         *resolved = false;
         return true;
     }
 
-    method_info = g_interface_info_find_method((GIInterfaceInfo*) priv->info, name);
+    GjsAutoFunctionInfo method_info =
+        g_interface_info_find_method(priv->info, name.get());
 
-    if (method_info != NULL) {
+    if (method_info) {
         if (g_function_info_get_flags (method_info) & GI_FUNCTION_IS_METHOD) {
-            if (gjs_define_function(context, obj,
-                                    priv->gtype,
-                                    (GICallableInfo*)method_info) == NULL) {
-                g_base_info_unref((GIBaseInfo*)method_info);
+            if (!gjs_define_function(context, obj, priv->gtype, method_info))
                 return false;
-            }
 
             *resolved = true;
         } else {
             *resolved = false;
         }
-
-        g_base_info_unref((GIBaseInfo*)method_info);
     } else {
         *resolved = false;
     }
diff --git a/gi/ns.cpp b/gi/ns.cpp
index 04ae2b33..9ff190f8 100644
--- a/gi/ns.cpp
+++ b/gi/ns.cpp
@@ -77,14 +77,14 @@ ns_resolve(JSContext       *context,
         return true;
     }
 
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     if (!gjs_get_string_id(context, id, &name)) {
         *resolved = false;
         return true;  /* not resolved, but no error */
     }
 
     GjsAutoBaseInfo info =
-        g_irepository_find_by_name(nullptr, priv->gi_namespace, name);
+        g_irepository_find_by_name(nullptr, priv->gi_namespace, name.get());
     if (!info) {
         *resolved = false; /* No property defined, but no error either */
         return true;
diff --git a/gi/object.cpp b/gi/object.cpp
index c276adba..3626c2d6 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -279,17 +279,17 @@ GParamSpec* ObjectPrototype::find_param_spec_from_id(JSContext* cx,
     if (entry)
         return entry->value();
 
-    GjsAutoJSChar js_prop_name;
+    JS::UniqueChars js_prop_name;
     if (!gjs_string_to_utf8(cx, JS::StringValue(key), &js_prop_name))
         return nullptr;
 
-    GjsAutoChar gname = gjs_hyphen_from_camel(js_prop_name);
+    GjsAutoChar gname = gjs_hyphen_from_camel(js_prop_name.get());
     GjsAutoTypeClass<GObjectClass> gobj_class(m_gtype);
     GParamSpec* pspec = g_object_class_find_property(gobj_class, gname);
     GjsAutoParam param_spec(pspec, GjsAutoParam::TakeOwnership());
 
     if (!param_spec) {
-        _gjs_proxy_throw_nonexistent_field(cx, m_gtype, js_prop_name);
+        _gjs_proxy_throw_nonexistent_field(cx, m_gtype, js_prop_name.get());
         return nullptr;
     }
 
@@ -426,14 +426,14 @@ GIFieldInfo* ObjectPrototype::find_field_info_from_id(JSContext* cx,
     if (entry)
         return entry->value().get();
 
-    GjsAutoJSChar js_prop_name;
+    JS::UniqueChars js_prop_name;
     if (!gjs_string_to_utf8(cx, JS::StringValue(key), &js_prop_name))
         return nullptr;
 
-    GjsAutoFieldInfo field = lookup_field_info(m_info, js_prop_name);
+    GjsAutoFieldInfo field = lookup_field_info(m_info, js_prop_name.get());
 
     if (!field) {
-        _gjs_proxy_throw_nonexistent_field(cx, m_gtype, js_prop_name);
+        _gjs_proxy_throw_nonexistent_field(cx, m_gtype, js_prop_name.get());
         return nullptr;
     }
 
@@ -837,7 +837,7 @@ bool ObjectPrototype::resolve_impl(JSContext* context, JS::HandleObject obj,
                                    JS::HandleId id, bool* resolved) {
     debug_jsprop("Resolve hook", id, obj);
 
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     if (!gjs_get_string_id(context, id, &name)) {
         *resolved = false;
         return true;  /* not resolved, but no error */
@@ -847,10 +847,10 @@ bool ObjectPrototype::resolve_impl(JSContext* context, JS::HandleObject obj,
      * we need to look at exposing interfaces. Look up our interfaces through
      * GType data, and then hope that *those* are introspectable. */
     if (is_custom_js_class())
-        return resolve_no_info(context, obj, id, resolved, name,
+        return resolve_no_info(context, obj, id, resolved, name.get(),
                                ConsiderMethodsAndProperties);
 
-    if (g_str_has_prefix (name, "vfunc_")) {
+    if (g_str_has_prefix(name.get(), "vfunc_")) {
         /* The only time we find a vfunc info is when we're the base
          * class that defined the vfunc. If we let regular prototype
          * chaining resolve this, we'd have the implementation for the base's
@@ -887,10 +887,11 @@ bool ObjectPrototype::resolve_impl(JSContext* context, JS::HandleObject obj,
          * method resolution. */
     }
 
-    if (is_gobject_property_name(m_info, name))
-        return lazy_define_gobject_property(context, obj, id, resolved, name);
+    if (is_gobject_property_name(m_info, name.get()))
+        return lazy_define_gobject_property(context, obj, id, resolved,
+                                            name.get());
 
-    GjsAutoFieldInfo field_info = lookup_field_info(m_info, name);
+    GjsAutoFieldInfo field_info = lookup_field_info(m_info, name.get());
     if (field_info) {
         bool found = false;
         if (!JS_AlreadyHasOwnPropertyById(context, obj, id, &found))
@@ -907,10 +908,10 @@ bool ObjectPrototype::resolve_impl(JSContext* context, JS::HandleObject obj,
             flags |= JSPROP_READONLY;
 
         JS::RootedValue private_id(context, JS::StringValue(JSID_TO_STRING(id)));
-        if (!gjs_define_property_dynamic(context, obj, name, "gobject_field",
-                                         &ObjectBase::field_getter,
-                                         &ObjectBase::field_setter, private_id,
-                                         flags))
+        if (!gjs_define_property_dynamic(
+                context, obj, name.get(), "gobject_field",
+                &ObjectBase::field_getter, &ObjectBase::field_setter,
+                private_id, flags))
             return false;
 
         *resolved = true;
@@ -929,7 +930,7 @@ bool ObjectPrototype::resolve_impl(JSContext* context, JS::HandleObject obj,
      */
 
     GjsAutoFunctionInfo method_info =
-        g_object_info_find_method_using_interfaces(m_info, name, nullptr);
+        g_object_info_find_method_using_interfaces(m_info, name.get(), nullptr);
 
     /**
      * Search through any interfaces implemented by the GType;
@@ -937,7 +938,7 @@ bool ObjectPrototype::resolve_impl(JSContext* context, JS::HandleObject obj,
      * https://bugzilla.gnome.org/show_bug.cgi?id=632922
      */
     if (!method_info)
-        return resolve_no_info(context, obj, id, resolved, name,
+        return resolve_no_info(context, obj, id, resolved, name.get(),
                                ConsiderOnlyMethods);
 
 #if GJS_VERBOSE_ENABLE_GI_USAGE
@@ -1876,7 +1877,7 @@ ObjectInstance::connect_impl(JSContext          *context,
     if (!check_gobject_disposed("connect to any signal on"))
         return true;
 
-    GjsAutoJSChar signal_name;
+    JS::UniqueChars signal_name;
     JS::RootedObject callback(context);
     if (!gjs_parse_call_args(context, after ? "connect_after" : "connect", args, "so",
                              "signal name", &signal_name,
@@ -1888,8 +1889,8 @@ ObjectInstance::connect_impl(JSContext          *context,
         return false;
     }
 
-    if (!g_signal_parse_name(signal_name, gtype(), &signal_id, &signal_detail,
-                             true)) {
+    if (!g_signal_parse_name(signal_name.get(), gtype(), &signal_id,
+                             &signal_detail, true)) {
         gjs_throw(context, "No signal '%s' on object '%s'",
                   signal_name.get(), type_name());
         return false;
@@ -1940,13 +1941,13 @@ ObjectInstance::emit_impl(JSContext          *context,
     if (!check_gobject_disposed("emit any signal on"))
         return true;
 
-    GjsAutoJSChar signal_name;
+    JS::UniqueChars signal_name;
     if (!gjs_parse_call_args(context, "emit", argv, "!s",
                              "signal name", &signal_name))
         return false;
 
-    if (!g_signal_parse_name(signal_name, gtype(), &signal_id, &signal_detail,
-                             false)) {
+    if (!g_signal_parse_name(signal_name.get(), gtype(), &signal_id,
+                             &signal_detail, false)) {
         gjs_throw(context, "No signal '%s' on object '%s'",
                   signal_name.get(), type_name());
         return false;
@@ -2437,7 +2438,7 @@ bool ObjectBase::hook_up_vfunc(JSContext* cx, unsigned argc, JS::Value* vp) {
 bool ObjectPrototype::hook_up_vfunc_impl(JSContext* cx,
                                          const JS::CallArgs& args,
                                          JS::HandleObject prototype) {
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     JS::RootedObject function(cx);
     if (!gjs_parse_call_args(cx, "hook_up_vfunc", args, "so",
                              "name", &name,
@@ -2459,7 +2460,7 @@ bool ObjectPrototype::hook_up_vfunc_impl(JSContext* cx,
      * This is awful, so abort now. */
     g_assert(info != NULL);
 
-    GjsAutoVFuncInfo vfunc = find_vfunc_on_parents(info, name, nullptr);
+    GjsAutoVFuncInfo vfunc = find_vfunc_on_parents(info, name.get(), nullptr);
 
     if (!vfunc) {
         guint i, n_interfaces;
@@ -2474,7 +2475,7 @@ bool ObjectPrototype::hook_up_vfunc_impl(JSContext* cx,
             /* The interface doesn't have to exist -- it could be private
              * or dynamic. */
             if (interface) {
-                vfunc = g_interface_info_find_vfunc(interface, name);
+                vfunc = g_interface_info_find_vfunc(interface, name.get());
 
                 if (vfunc)
                     break;
@@ -2492,7 +2493,7 @@ bool ObjectPrototype::hook_up_vfunc_impl(JSContext* cx,
 
     void *implementor_vtable;
     GjsAutoFieldInfo field_info;
-    if (!find_vfunc_info(cx, m_gtype, vfunc, name, &implementor_vtable,
+    if (!find_vfunc_info(cx, m_gtype, vfunc, name.get(), &implementor_vtable,
                          &field_info))
         return false;
 
diff --git a/gi/param.cpp b/gi/param.cpp
index 20bdf324..ae998fb8 100644
--- a/gi/param.cpp
+++ b/gi/param.cpp
@@ -62,14 +62,15 @@ param_resolve(JSContext       *context,
         return true;
     }
 
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     if (!gjs_get_string_id(context, id, &name)) {
         *resolved = false;
         return true; /* not resolved, but no error */
     }
 
     GjsAutoObjectInfo info = g_irepository_find_by_gtype(nullptr, G_TYPE_PARAM);
-    GjsAutoFunctionInfo method_info = g_object_info_find_method(info, name);
+    GjsAutoFunctionInfo method_info =
+        g_object_info_find_method(info, name.get());
 
     if (!method_info) {
         *resolved = false;
diff --git a/gi/private.cpp b/gi/private.cpp
index 7a852ddc..097b8a6f 100644
--- a/gi/private.cpp
+++ b/gi/private.cpp
@@ -43,7 +43,7 @@
 
 static bool gjs_override_property(JSContext* cx, unsigned argc, JS::Value* vp) {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     JS::RootedObject type(cx);
 
     if (!gjs_parse_call_args(cx, "override_property", args, "so", "name", &name,
@@ -60,11 +60,11 @@ static bool gjs_override_property(JSContext* cx, unsigned argc, JS::Value* vp) {
     if (g_type_is_a(gtype, G_TYPE_INTERFACE)) {
         auto* interface_type =
             static_cast<GTypeInterface*>(g_type_default_interface_ref(gtype));
-        pspec = g_object_interface_find_property(interface_type, name);
+        pspec = g_object_interface_find_property(interface_type, name.get());
         g_type_default_interface_unref(interface_type);
     } else {
         GjsAutoTypeClass<GObjectClass> class_type(gtype);
-        pspec = g_object_class_find_property(class_type, name);
+        pspec = g_object_class_find_property(class_type, name.get());
     }
 
     if (!pspec) {
@@ -73,7 +73,7 @@ static bool gjs_override_property(JSContext* cx, unsigned argc, JS::Value* vp) {
         return false;
     }
 
-    GjsAutoParam new_pspec = g_param_spec_override(name, pspec);
+    GjsAutoParam new_pspec = g_param_spec_override(name.get(), pspec);
 
     g_param_spec_set_qdata(new_pspec, ObjectBase::custom_property_quark(),
                            GINT_TO_POINTER(1));
@@ -176,7 +176,7 @@ static bool gjs_register_interface(JSContext* cx, unsigned argc,
                                    JS::Value* vp) {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
 
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     JS::RootedObject interfaces(cx), properties(cx);
     if (!gjs_parse_call_args(cx, "register_interface", args, "soo", "name",
                              &name, "interfaces", &interfaces, "properties",
@@ -195,14 +195,14 @@ static bool gjs_register_interface(JSContext* cx, unsigned argc,
     if (!get_interface_gtypes(cx, interfaces, n_interfaces, iface_types))
         return false;
 
-    if (g_type_from_name(name) != G_TYPE_INVALID) {
+    if (g_type_from_name(name.get()) != G_TYPE_INVALID) {
         gjs_throw(cx, "Type name %s is already registered", name.get());
         return false;
     }
 
     GTypeInfo type_info = gjs_gobject_interface_info;
-    GType interface_type = g_type_register_static(G_TYPE_INTERFACE, name,
-        &type_info, GTypeFlags(0));
+    GType interface_type = g_type_register_static(G_TYPE_INTERFACE, name.get(),
+                                                  &type_info, GTypeFlags(0));
 
     g_type_set_qdata(interface_type, ObjectBase::custom_type_quark(),
                      GINT_TO_POINTER(1));
@@ -239,7 +239,7 @@ static bool gjs_register_type(JSContext* cx, unsigned argc, JS::Value* vp) {
 
     JSAutoRequest ar(cx);
 
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     JS::RootedObject parent(cx), interfaces(cx), properties(cx);
     if (!gjs_parse_call_args(cx, "register_type", argv, "osoo", "parent",
                              &parent, "name", &name, "interfaces", &interfaces,
@@ -265,7 +265,7 @@ static bool gjs_register_type(JSContext* cx, unsigned argc, JS::Value* vp) {
     if (!get_interface_gtypes(cx, interfaces, n_interfaces, iface_types))
         return false;
 
-    if (g_type_from_name(name) != G_TYPE_INVALID) {
+    if (g_type_from_name(name.get()) != G_TYPE_INVALID) {
         gjs_throw(cx, "Type name %s is already registered", name.get());
         return false;
     }
@@ -286,8 +286,8 @@ static bool gjs_register_type(JSContext* cx, unsigned argc, JS::Value* vp) {
     type_info.class_size = query.class_size;
     type_info.instance_size = query.instance_size;
 
-    GType instance_type = g_type_register_static(parent_priv->gtype(), name,
-                                                 &type_info, GTypeFlags(0));
+    GType instance_type = g_type_register_static(
+        parent_priv->gtype(), name.get(), &type_info, GTypeFlags(0));
 
     g_type_set_qdata(instance_type, ObjectBase::custom_type_quark(),
                      GINT_TO_POINTER(1));
@@ -318,7 +318,7 @@ static bool gjs_signal_new(JSContext* cx, unsigned argc, JS::Value* vp) {
 
     JSAutoRequest ar(cx);
 
-    GjsAutoJSChar signal_name;
+    JS::UniqueChars signal_name;
     int32_t flags, accumulator_enum;
     JS::RootedObject gtype_obj(cx), return_gtype_obj(cx), params_obj(cx);
     if (!gjs_parse_call_args(cx, "signal_new", args, "osiioo", "gtype",
@@ -375,8 +375,8 @@ static bool gjs_signal_new(JSContext* cx, unsigned argc, JS::Value* vp) {
     GType gtype = gjs_gtype_get_actual_gtype(cx, gtype_obj);
 
     unsigned signal_id = g_signal_newv(
-        signal_name, gtype, GSignalFlags(flags), nullptr, /* class closure */
-        accumulator, nullptr,                             /* accu_data */
+        signal_name.get(), gtype, GSignalFlags(flags),
+        /* class closure */ nullptr, accumulator, /* accu_data */ nullptr,
         g_cclosure_marshal_generic, return_type, n_parameters, params);
 
     // FIXME: what if ID is greater than int32 max?
diff --git a/gi/repo.cpp b/gi/repo.cpp
index 90f9d37d..79d54b3a 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -57,12 +57,8 @@ GJS_DEFINE_PRIV_FROM_JS(Repo, gjs_repo_class)
 static bool lookup_override_function(JSContext *, JS::HandleId,
                                      JS::MutableHandleValue);
 
-static bool
-get_version_for_ns (JSContext       *context,
-                    JS::HandleObject repo_obj,
-                    JS::HandleId     ns_id,
-                    GjsAutoJSChar   *version)
-{
+static bool get_version_for_ns(JSContext* context, JS::HandleObject repo_obj,
+                               JS::HandleId ns_id, JS::UniqueChars* version) {
     JS::RootedObject versions(context);
     bool found;
 
@@ -90,7 +86,7 @@ resolve_namespace_object(JSContext       *context,
 
     JSAutoRequest ar(context);
 
-    GjsAutoJSChar version;
+    JS::UniqueChars version;
     if (!get_version_for_ns(context, repo_obj, ns_id, &version))
         return false;
 
@@ -107,8 +103,8 @@ resolve_namespace_object(JSContext       *context,
     g_list_free_full(versions, g_free);
 
     error = NULL;
-    g_irepository_require(nullptr, ns_name, version, (GIRepositoryLoadFlags)0,
-                          &error);
+    g_irepository_require(nullptr, ns_name, version.get(),
+                          GIRepositoryLoadFlags(0), &error);
     if (error != NULL) {
         gjs_throw(context,
                   "Requiring %s, version %s: %s",
@@ -184,15 +180,14 @@ repo_resolve(JSContext       *context,
         return true;
     }
 
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     if (!gjs_get_string_id(context, id, &name)) {
         *resolved = false;
         return true;
     }
 
-    if (!resolve_namespace_object(context, obj, id, name)) {
+    if (!resolve_namespace_object(context, obj, id, name.get()))
         return false;
-    }
 
     *resolved = true;
     return true;
diff --git a/gi/union.cpp b/gi/union.cpp
index fd7bea20..853c908a 100644
--- a/gi/union.cpp
+++ b/gi/union.cpp
@@ -79,47 +79,37 @@ union_resolve(JSContext       *context,
         return true;
     }
 
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     if (!gjs_get_string_id(context, id, &name)) {
         *resolved = false;
         return true; /* not resolved, but no error */
     }
 
     /* We are the prototype, so look for methods and other class properties */
-    GIFunctionInfo *method_info;
-
-    method_info = g_union_info_find_method((GIUnionInfo*) priv->info,
-                                           name);
-
-    if (method_info != NULL) {
-        const char *method_name;
+    GjsAutoFunctionInfo method_info =
+        g_union_info_find_method(priv->info, name.get());
 
+    if (method_info) {
 #if GJS_VERBOSE_ENABLE_GI_USAGE
-        _gjs_log_info_usage((GIBaseInfo*) method_info);
+        _gjs_log_info_usage(method_info);
 #endif
         if (g_function_info_get_flags (method_info) & GI_FUNCTION_IS_METHOD) {
-            method_name = g_base_info_get_name( (GIBaseInfo*) method_info);
-
             gjs_debug(GJS_DEBUG_GBOXED,
                       "Defining method %s in prototype for %s.%s",
-                      method_name,
+                      method_info.name(),
                       g_base_info_get_namespace( (GIBaseInfo*) priv->info),
                       g_base_info_get_name( (GIBaseInfo*) priv->info));
 
             /* obj is union proto */
-            if (gjs_define_function(context, obj,
-                                    g_registered_type_info_get_g_type(priv->info),
-                                    method_info) == NULL) {
-                g_base_info_unref( (GIBaseInfo*) method_info);
+            if (!gjs_define_function(
+                    context, obj, g_registered_type_info_get_g_type(priv->info),
+                    method_info))
                 return false;
-            }
 
             *resolved = true; /* we defined the prop in object_proto */
         } else {
             *resolved = false;
         }
-
-        g_base_info_unref( (GIBaseInfo*) method_info);
     } else {
         *resolved = false;
     }
diff --git a/gi/value.cpp b/gi/value.cpp
index 04104373..867ab7df 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -393,11 +393,11 @@ gjs_value_to_g_value_internal(JSContext      *context,
             g_value_set_string(gvalue, NULL);
         } else if (value.isString()) {
             JS::RootedString str(context, value.toString());
-            GjsAutoJSChar utf8_string = JS_EncodeStringToUTF8(context, str);
+            JS::UniqueChars utf8_string(JS_EncodeStringToUTF8(context, str));
             if (!utf8_string)
                 return false;
 
-            g_value_take_string(gvalue, utf8_string.copy());
+            g_value_set_string(gvalue, utf8_string.get());
         } else {
             return throw_expect_type(context, value, "string");
         }
diff --git a/gjs/byteArray.cpp b/gjs/byteArray.cpp
index 5d13ebed..1b77311b 100644
--- a/gjs/byteArray.cpp
+++ b/gjs/byteArray.cpp
@@ -115,14 +115,14 @@ static bool to_string_impl(JSContext* context, JS::HandleObject byte_array,
 
 static bool to_string_func(JSContext* cx, unsigned argc, JS::Value* vp) {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-    GjsAutoJSChar encoding;
+    JS::UniqueChars encoding;
     JS::RootedObject byte_array(cx);
 
     if (!gjs_parse_call_args(cx, "toString", args, "o|s", "byteArray",
                              &byte_array, "encoding", &encoding))
         return false;
 
-    return to_string_impl(cx, byte_array, encoding, args.rval());
+    return to_string_impl(cx, byte_array, encoding.get(), args.rval());
 }
 
 /* Workaround to keep existing code compatible. This function is tacked onto
@@ -131,7 +131,7 @@ static bool to_string_func(JSContext* cx, unsigned argc, JS::Value* vp) {
 static bool instance_to_string_func(JSContext* cx, unsigned argc,
                                     JS::Value* vp) {
     GJS_GET_THIS(cx, argc, vp, args, this_obj);
-    GjsAutoJSChar encoding;
+    JS::UniqueChars encoding;
 
     _gjs_warn_deprecated_once_per_callsite(
         cx, GjsDeprecationMessageId::ByteArrayInstanceToString);
@@ -139,7 +139,7 @@ static bool instance_to_string_func(JSContext* cx, unsigned argc,
     if (!gjs_parse_call_args(cx, "toString", args, "|s", "encoding", &encoding))
         return false;
 
-    return to_string_impl(cx, this_obj, encoding, args.rval());
+    return to_string_impl(cx, this_obj, encoding.get(), args.rval());
 }
 
 static bool
@@ -173,8 +173,8 @@ from_string_func(JSContext *context,
                  JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    GjsAutoJSChar encoding;
-    GjsAutoJSChar utf8;
+    JS::UniqueChars encoding;
+    JS::UniqueChars utf8;
     bool encoding_is_utf8;
     JS::RootedObject obj(context), array_buffer(context);
 
@@ -188,7 +188,7 @@ from_string_func(JSContext *context,
          * doesn't matter much though. encoding_is_utf8 is
          * just an optimization anyway.
          */
-        encoding_is_utf8 = (strcmp(encoding, "UTF-8") == 0);
+        encoding_is_utf8 = (strcmp(encoding.get(), "UTF-8") == 0);
     } else {
         encoding_is_utf8 = true;
     }
@@ -197,7 +197,7 @@ from_string_func(JSContext *context,
         /* optimization? avoids iconv overhead and runs
          * libmozjs hardwired utf16-to-utf8.
          */
-        size_t len = strlen(utf8);
+        size_t len = strlen(utf8.get());
         array_buffer =
             JS_NewArrayBufferWithContents(context, len, utf8.release());
     } else {
@@ -219,7 +219,7 @@ from_string_func(JSContext *context,
                     return false;
 
                 encoded = g_convert((char *) chars, len,
-                                    encoding,  /* to_encoding */
+                                    encoding.get(),  // to_encoding
                                     "LATIN1",  /* from_encoding */
                                     NULL,  /* bytes read */
                                     &bytes_written, &error);
@@ -230,7 +230,7 @@ from_string_func(JSContext *context,
                     return false;
 
                 encoded = g_convert((char *) chars, len * 2,
-                                    encoding,  /* to_encoding */
+                                    encoding.get(),  // to_encoding
                                     "UTF-16",  /* from_encoding */
                                     NULL,  /* bytes read */
                                     &bytes_written, &error);
diff --git a/gjs/debugger.cpp b/gjs/debugger.cpp
index 84530ae7..5203e911 100644
--- a/gjs/debugger.cpp
+++ b/gjs/debugger.cpp
@@ -52,7 +52,7 @@ static bool do_readline(JSContext* cx, unsigned argc, JS::Value* vp) {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
     JSAutoRequest ar(cx);
 
-    GjsAutoJSChar prompt;
+    JS::UniqueChars prompt;
     if (!gjs_parse_call_args(cx, "readline", args, "|s", "prompt", &prompt))
         return false;
 
diff --git a/gjs/deprecation.cpp b/gjs/deprecation.cpp
index de3c0080..82f275a0 100644
--- a/gjs/deprecation.cpp
+++ b/gjs/deprecation.cpp
@@ -78,7 +78,7 @@ static char* get_callsite(JSContext* cx) {
     if (!frame_string)
         return nullptr;
 
-    GjsAutoJSChar frame_utf8;
+    JS::UniqueChars frame_utf8;
     if (!gjs_string_to_utf8(cx, JS::StringValue(frame_string), &frame_utf8))
         return nullptr;
     return frame_utf8.release();
@@ -89,8 +89,8 @@ static char* get_callsite(JSContext* cx) {
  * stdout or stderr. Do not use this function during GC, for example. */
 void _gjs_warn_deprecated_once_per_callsite(JSContext* cx,
                                             const GjsDeprecationMessageId id) {
-    GjsAutoJSChar callsite = get_callsite(cx);
-    DeprecationEntry entry(id, callsite);
+    JS::UniqueChars callsite(get_callsite(cx));
+    DeprecationEntry entry(id, callsite.get());
     if (!logged_messages.count(entry)) {
         JS::UniqueChars stack_dump = JS::FormatStackDump(cx, nullptr, false,
             false, false);
diff --git a/gjs/engine.cpp b/gjs/engine.cpp
index a22199b3..4629748a 100644
--- a/gjs/engine.cpp
+++ b/gjs/engine.cpp
@@ -48,11 +48,11 @@ gjs_locale_to_upper_case (JSContext *context,
                           JS::HandleString src,
                           JS::MutableHandleValue retval)
 {
-    GjsAutoJSChar utf8 = JS_EncodeStringToUTF8(context, src);
+    JS::UniqueChars utf8(JS_EncodeStringToUTF8(context, src));
     if (!utf8)
         return false;
 
-    GjsAutoChar upper_case_utf8 = g_utf8_strup(utf8, -1);
+    GjsAutoChar upper_case_utf8 = g_utf8_strup(utf8.get(), -1);
     return gjs_string_from_utf8(context, upper_case_utf8, retval);
 }
 
@@ -61,11 +61,11 @@ gjs_locale_to_lower_case (JSContext *context,
                           JS::HandleString src,
                           JS::MutableHandleValue retval)
 {
-    GjsAutoJSChar utf8 = JS_EncodeStringToUTF8(context, src);
+    JS::UniqueChars utf8(JS_EncodeStringToUTF8(context, src));
     if (!utf8)
         return false;
 
-    GjsAutoChar lower_case_utf8 = g_utf8_strdown(utf8, -1);
+    GjsAutoChar lower_case_utf8 = g_utf8_strdown(utf8.get(), -1);
     return gjs_string_from_utf8(context, lower_case_utf8, retval);
 }
 
@@ -75,15 +75,15 @@ gjs_locale_compare (JSContext *context,
                     JS::HandleString src_2,
                     JS::MutableHandleValue retval)
 {
-    GjsAutoJSChar utf8_1 = JS_EncodeStringToUTF8(context, src_1);
+    JS::UniqueChars utf8_1(JS_EncodeStringToUTF8(context, src_1));
     if (!utf8_1)
         return false;
 
-    GjsAutoJSChar utf8_2 = JS_EncodeStringToUTF8(context, src_2);
+    JS::UniqueChars utf8_2(JS_EncodeStringToUTF8(context, src_2));
     if (!utf8_2)
         return false;
 
-    retval.setInt32(g_utf8_collate(utf8_1, utf8_2));
+    retval.setInt32(g_utf8_collate(utf8_1.get(), utf8_2.get()));
 
     return true;
 }
diff --git a/gjs/global.cpp b/gjs/global.cpp
index 02712e16..2ea9b6df 100644
--- a/gjs/global.cpp
+++ b/gjs/global.cpp
@@ -88,7 +88,7 @@ gjs_log(JSContext *cx,
         return true;
     }
 
-    GjsAutoJSChar s = JS_EncodeStringToUTF8(cx, jstr);
+    JS::UniqueChars s(JS_EncodeStringToUTF8(cx, jstr));
     if (!s)
         return false;
 
@@ -147,13 +147,13 @@ gjs_print_parse_args(JSContext    *cx,
         exc_state.restore();
 
         if (jstr) {
-            GjsAutoJSChar s = JS_EncodeStringToUTF8(cx, jstr);
+            JS::UniqueChars s(JS_EncodeStringToUTF8(cx, jstr));
             if (!s) {
                 g_string_free(str, true);
                 return false;
             }
 
-            g_string_append(str, s);
+            g_string_append(str, s.get());
             if (n < (argv.length()-1))
                 g_string_append_c(str, ' ');
         } else {
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index ce4cd9d7..6f5a7daf 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -81,7 +81,7 @@ importer_to_string(JSContext *cx,
     if (module_path.isNull()) {
         output = g_strdup_printf("[%s root]", klass->name);
     } else {
-        GjsAutoJSChar path;
+        JS::UniqueChars path;
         if (!gjs_string_to_utf8(cx, module_path, &path))
             return false;
         output = g_strdup_printf("[%s %s]", klass->name, path.get());
@@ -142,7 +142,7 @@ define_meta_properties(JSContext       *context,
         if (parent_module_path.isNull()) {
             module_path_buf = g_strdup(module_name);
         } else {
-            GjsAutoJSChar parent_path;
+            JS::UniqueChars parent_path;
             if (!gjs_string_to_utf8(context, parent_module_path, &parent_path))
                 return false;
             module_path_buf = g_strdup_printf("%s.%s", parent_path.get(), module_name);
@@ -503,7 +503,7 @@ do_import(JSContext       *context,
         }
 
         str = elem.toString();
-        GjsAutoJSChar dirname = JS_EncodeStringToUTF8(context, str);
+        JS::UniqueChars dirname(JS_EncodeStringToUTF8(context, str));
         if (!dirname)
             return false;
 
@@ -513,13 +513,14 @@ do_import(JSContext       *context,
 
         /* Try importing __init__.js and loading the symbol from it */
         bool found = false;
-        if (!import_symbol_from_init_js(context, obj, dirname, name, &found))
+        if (!import_symbol_from_init_js(context, obj, dirname.get(), name,
+                                        &found))
             return false;
         if (found)
             return true;
 
         /* Second try importing a directory (a sub-importer) */
-        GjsAutoChar full_path = g_build_filename(dirname, name, nullptr);
+        GjsAutoChar full_path = g_build_filename(dirname.get(), name, nullptr);
         GjsAutoUnref<GFile> gfile = g_file_new_for_commandline_arg(full_path);
 
         if (g_file_query_file_type(gfile, (GFileQueryInfoFlags) 0, NULL) == G_FILE_TYPE_DIRECTORY) {
@@ -539,7 +540,7 @@ do_import(JSContext       *context,
             continue;
 
         /* Third, if it's not a directory, try importing a file */
-        full_path = g_build_filename(dirname, filename.get(), nullptr);
+        full_path = g_build_filename(dirname.get(), filename.get(), nullptr);
         gfile = g_file_new_for_commandline_arg(full_path);
         exists = g_file_query_exists(gfile, NULL);
 
@@ -644,18 +645,19 @@ static bool importer_new_enumerate(JSContext* context, JS::HandleObject object,
         }
 
         str = elem.toString();
-        GjsAutoJSChar dirname = JS_EncodeStringToUTF8(context, str);
+        JS::UniqueChars dirname(JS_EncodeStringToUTF8(context, str));
         if (!dirname)
             return false;
 
-        init_path = g_build_filename(dirname, MODULE_INIT_FILENAME, NULL);
+        init_path =
+            g_build_filename(dirname.get(), MODULE_INIT_FILENAME, nullptr);
 
         load_module_elements(context, object, properties, init_path);
 
         g_free(init_path);
 
         /* new_for_commandline_arg handles resource:/// paths */
-        GjsAutoUnref<GFile> dir = g_file_new_for_commandline_arg(dirname);
+        GjsAutoUnref<GFile> dir = g_file_new_for_commandline_arg(dirname.get());
         GjsAutoUnref<GFileEnumerator> direnum =
             g_file_enumerate_children(dir, "standard::name,standard::type",
                                       G_FILE_QUERY_INFO_NONE, NULL, NULL);
@@ -737,13 +739,13 @@ importer_resolve(JSContext        *context,
 
     JSAutoRequest ar(context);
 
-    GjsAutoJSChar name;
+    JS::UniqueChars name;
     if (!gjs_get_string_id(context, id, &name)) {
         *resolved = false;
         return true;
     }
 
-    if (!do_import(context, obj, priv, id, name))
+    if (!do_import(context, obj, priv, id, name.get()))
         return false;
 
     *resolved = true;
diff --git a/gjs/jsapi-util-args.h b/gjs/jsapi-util-args.h
index b5363ea8..cf12b842 100644
--- a/gjs/jsapi-util-args.h
+++ b/gjs/jsapi-util-args.h
@@ -86,15 +86,10 @@ assign(JSContext              *cx,
 }
 
 GJS_ALWAYS_INLINE
-static inline void
-assign(JSContext      *cx,
-       char            c,
-       bool            nullable,
-       JS::HandleValue value,
-       GjsAutoJSChar  *ref)
-{
+static inline void assign(JSContext* cx, char c, bool nullable,
+                          JS::HandleValue value, JS::UniqueChars* ref) {
     if (c != 's')
-        throw g_strdup_printf("Wrong type for %c, got GjsAutoJSChar*", c);
+        throw g_strdup_printf("Wrong type for %c, got JS::UniqueChars*", c);
     if (nullable && value.isNull()) {
         ref->reset();
         return;
@@ -352,7 +347,7 @@ gjs_parse_call_args(JSContext          *cx,
  * value location pairs.  The currently accepted format specifiers are:
  *
  * b: A boolean (pass a bool *)
- * s: A string, converted into UTF-8 (pass a GjsAutoJSChar *)
+ * s: A string, converted into UTF-8 (pass a JS::UniqueChars*)
  * F: A string, converted into "filename encoding" (i.e. active locale) (pass
  *   a GjsAutoChar *)
  * i: A number, will be converted to a 32-bit int (pass an int32_t * or a
diff --git a/gjs/jsapi-util-error.cpp b/gjs/jsapi-util-error.cpp
index 42d14ae8..5e7c4485 100644
--- a/gjs/jsapi-util-error.cpp
+++ b/gjs/jsapi-util-error.cpp
@@ -213,16 +213,17 @@ gjs_format_stack_trace(JSContext       *cx,
     JS::AutoSaveExceptionState saved_exc(cx);
 
     JS::RootedString stack_trace(cx);
-    GjsAutoJSChar stack_utf8;
+    JS::UniqueChars stack_utf8;
     if (JS::BuildStackString(cx, saved_frame, &stack_trace, 2))
-        stack_utf8 = JS_EncodeStringToUTF8(cx, stack_trace);
+        stack_utf8.reset(JS_EncodeStringToUTF8(cx, stack_trace));
 
     saved_exc.restore();
 
     if (!stack_utf8)
         return nullptr;
 
-    return g_filename_from_utf8(stack_utf8, -1, nullptr, nullptr, nullptr);
+    return g_filename_from_utf8(stack_utf8.get(), -1, nullptr, nullptr,
+                                nullptr);
 }
 
 void
diff --git a/gjs/jsapi-util-string.cpp b/gjs/jsapi-util-string.cpp
index 6ec7c230..5c59d7b0 100644
--- a/gjs/jsapi-util-string.cpp
+++ b/gjs/jsapi-util-string.cpp
@@ -55,11 +55,8 @@ char* gjs_hyphen_to_underscore(const char* str) {
  * Don't use this function if you already have a JS::RootedString, or if you
  * know the value already holds a string; use JS_EncodeStringToUTF8() instead.
  */
-bool
-gjs_string_to_utf8(JSContext      *cx,
-                   const JS::Value value,
-                   GjsAutoJSChar  *utf8_string_p)
-{
+bool gjs_string_to_utf8(JSContext* cx, const JS::Value value,
+                        JS::UniqueChars* utf8_string_p) {
     JSAutoRequest ar(cx);
 
     if (!value.isString()) {
@@ -110,7 +107,7 @@ gjs_string_to_filename(JSContext      *context,
                        GjsAutoChar    *filename_string)
 {
     GError *error;
-    GjsAutoJSChar tmp;
+    JS::UniqueChars tmp;
 
     /* gjs_string_to_filename verifies that filename_val is a string */
 
@@ -120,7 +117,8 @@ gjs_string_to_filename(JSContext      *context,
     }
 
     error = NULL;
-    *filename_string = g_filename_from_utf8(tmp, -1, NULL, NULL, &error);
+    *filename_string =
+        g_filename_from_utf8(tmp.get(), -1, nullptr, nullptr, &error);
     if (!*filename_string)
         return gjs_throw_gerror_message(context, error);
 
@@ -323,11 +321,7 @@ gjs_string_from_ucs4(JSContext             *cx,
  *
  * Returns: true if *name_p is non-%NULL
  **/
-bool
-gjs_get_string_id (JSContext       *context,
-                   jsid             id,
-                   GjsAutoJSChar   *name_p)
-{
+bool gjs_get_string_id(JSContext* context, jsid id, JS::UniqueChars* name_p) {
     JS::RootedValue id_val(context);
 
     if (!JS_IdToValue(context, id, &id_val))
@@ -359,9 +353,9 @@ gjs_unichar_from_string (JSContext *context,
                          JS::Value  value,
                          gunichar  *result)
 {
-    GjsAutoJSChar utf8_str;
+    JS::UniqueChars utf8_str;
     if (gjs_string_to_utf8(context, value, &utf8_str)) {
-        *result = g_utf8_get_char(utf8_str);
+        *result = g_utf8_get_char(utf8_str.get());
         return true;
     }
     return false;
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index 8e5d0ca0..968a1f3d 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -24,22 +24,23 @@
 
 #include <config.h>
 
+#include <math.h>
+#include <string.h>
+
 #include <codecvt>
 #include <locale>
+
 #include "jsapi-wrapper.h"
 #include <js/GCAPI.h>
+#include <js/Printf.h>
 
-#include <util/log.h>
-#include <util/glib.h>
-#include <util/misc.h>
-#include <util/error.h>
-
-#include "jsapi-class.h"
-#include "jsapi-util.h"
-#include "context-private.h"
-
-#include <string.h>
-#include <math.h>
+#include "gjs/context-private.h"
+#include "gjs/jsapi-class.h"
+#include "gjs/jsapi-util.h"
+#include "util/error.h"
+#include "util/glib.h"
+#include "util/log.h"
+#include "util/misc.h"
 
 GQuark
 gjs_util_error_quark (void)
@@ -216,13 +217,10 @@ gjs_object_require_property(JSContext       *cx,
 }
 
 /* Converts JS string value to UTF-8 string. value must be freed with JS_free. */
-bool
-gjs_object_require_property(JSContext       *cx,
-                            JS::HandleObject obj,
-                            const char      *description,
-                            JS::HandleId     property_name,
-                            GjsAutoJSChar   *value)
-{
+bool gjs_object_require_property(JSContext* cx, JS::HandleObject obj,
+                                 const char* description,
+                                 JS::HandleId property_name,
+                                 JS::UniqueChars* value) {
     JS::RootedValue prop_value(cx);
     if (JS_GetPropertyById(cx, obj, property_name, &prop_value) &&
         gjs_string_to_utf8(cx, prop_value, value))
@@ -361,7 +359,7 @@ gjs_string_readable(JSContext       *context,
 
     g_string_append_c(buf, '"');
 
-    GjsAutoJSChar chars = JS_EncodeStringToUTF8(context, string);
+    JS::UniqueChars chars(JS_EncodeStringToUTF8(context, string));
     if (!chars) {
         /* I'm not sure this code will actually ever be reached except in the
          * case of OOM, since JS_EncodeStringToUTF8() seems to happily output
@@ -376,7 +374,7 @@ gjs_string_readable(JSContext       *context,
         g_string_append(buf, escaped);
         g_free(escaped);
     } else {
-        g_string_append(buf, chars);
+        g_string_append(buf, chars.get());
     }
 
     g_string_append_c(buf, '"');
@@ -494,9 +492,9 @@ gjs_log_exception_full(JSContext       *context,
     JS_BeginRequest(context);
     JS::RootedObject exc_obj(context);
     JS::RootedString exc_str(context, JS::ToString(context, exc));
-    GjsAutoJSChar utf8_exception;
+    JS::UniqueChars utf8_exception;
     if (exc_str)
-        utf8_exception = JS_EncodeStringToUTF8(context, exc_str);
+        utf8_exception.reset(JS_EncodeStringToUTF8(context, exc_str));
     if (!utf8_exception)
         JS_ClearPendingException(context);
 
@@ -508,9 +506,9 @@ gjs_log_exception_full(JSContext       *context,
         is_syntax = JS_InstanceOf(context, exc_obj, syntax_error, nullptr);
     }
 
-    GjsAutoJSChar utf8_message;
+    JS::UniqueChars utf8_message;
     if (message)
-        utf8_message = JS_EncodeStringToUTF8(context, message);
+        utf8_message.reset(JS_EncodeStringToUTF8(context, message));
 
     /* We log syntax errors differently, because the stack for those includes
        only the referencing module, but we want to print out the filename and
@@ -526,13 +524,13 @@ gjs_log_exception_full(JSContext       *context,
         gjs_object_get_property(context, exc_obj, GJS_STRING_FILENAME,
                                 &js_fileName);
 
-        GjsAutoJSChar utf8_filename;
+        JS::UniqueChars utf8_filename;
         if (js_fileName.isString()) {
             JS::RootedString str(context, js_fileName.toString());
-            utf8_filename = JS_EncodeStringToUTF8(context, str);
+            utf8_filename.reset(JS_EncodeStringToUTF8(context, str));
         }
         if (!utf8_filename)
-            utf8_filename = JS_strdup(context, "unknown");
+            utf8_filename.reset(JS_strdup(context, "unknown"));
 
         lineNumber = js_lineNumber.toInt32();
 
@@ -545,7 +543,7 @@ gjs_log_exception_full(JSContext       *context,
         }
 
     } else {
-        GjsAutoJSChar utf8_stack;
+        JS::UniqueChars utf8_stack;
         JS::RootedValue stack(context);
 
         if (exc.isObject() &&
@@ -553,7 +551,7 @@ gjs_log_exception_full(JSContext       *context,
                                     &stack) &&
             stack.isString()) {
             JS::RootedString str(context, stack.toString());
-            utf8_stack = JS_EncodeStringToUTF8(context, str);
+            utf8_stack.reset(JS_EncodeStringToUTF8(context, str));
         }
 
         if (message) {
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 65b08bb8..bfd1d079 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -185,24 +185,6 @@ struct GjsJSFreeArgs {
     }
 };
 
-class GjsAutoJSChar : public std::unique_ptr<char, GjsJSFreeArgs> {
-public:
-    GjsAutoJSChar(char *str = nullptr) : unique_ptr(str, GjsJSFreeArgs()) { }
-
-    operator const char*() const {
-        return get();
-    }
-
-    void operator=(char *str) {
-        reset(str);
-    }
-
-    char* copy() const {
-        /* Strings acquired by this should be g_free()'ed */
-        return g_strdup(get());
-    }
-};
-
 G_BEGIN_DECLS
 
 #define GJS_UTIL_ERROR gjs_util_error_quark ()
@@ -288,9 +270,8 @@ bool gjs_call_function_value(JSContext                  *context,
 void gjs_warning_reporter(JSContext     *cx,
                           JSErrorReport *report);
 
-bool        gjs_string_to_utf8               (JSContext       *context,
-                                              const JS::Value  string_val,
-                                              GjsAutoJSChar   *utf8_string_p);
+bool gjs_string_to_utf8(JSContext* cx, const JS::Value string_val,
+                        JS::UniqueChars* utf8_string_p);
 bool gjs_string_from_utf8(JSContext             *context,
                           const char            *utf8_string,
                           JS::MutableHandleValue value_p);
@@ -322,9 +303,7 @@ bool gjs_string_from_ucs4(JSContext             *cx,
                           ssize_t                n_chars,
                           JS::MutableHandleValue value_p);
 
-bool        gjs_get_string_id                (JSContext       *context,
-                                              jsid             id,
-                                              GjsAutoJSChar   *name_p);
+bool gjs_get_string_id(JSContext* cx, jsid id, JS::UniqueChars* name_p);
 jsid        gjs_intern_string_to_id          (JSContext       *context,
                                               const char      *string);
 
@@ -452,11 +431,10 @@ bool gjs_object_require_property(JSContext       *cx,
                                  JS::HandleId     property_name,
                                  int32_t         *value);
 
-bool gjs_object_require_property(JSContext       *cx,
-                                 JS::HandleObject obj,
-                                 const char      *description,
-                                 JS::HandleId     property_name,
-                                 GjsAutoJSChar   *value);
+bool gjs_object_require_property(JSContext* cx, JS::HandleObject obj,
+                                 const char* description,
+                                 JS::HandleId property_name,
+                                 JS::UniqueChars* value);
 
 bool gjs_object_require_property(JSContext              *cx,
                                  JS::HandleObject        obj,
diff --git a/modules/cairo-context.cpp b/modules/cairo-context.cpp
index 8cf30e7b..418126fb 100644
--- a/modules/cairo-context.cpp
+++ b/modules/cairo-context.cpp
@@ -656,14 +656,14 @@ showText_func(JSContext *context,
               JS::Value *vp)
 {
     GJS_GET_PRIV(context, argc, vp, argv, obj, GjsCairoContext, priv);
-    GjsAutoJSChar utf8;
+    JS::UniqueChars utf8;
     cairo_t *cr = priv ? priv->cr : NULL;
 
     if (!gjs_parse_call_args(context, "showText", argv, "s",
                              "utf8", &utf8))
         return false;
 
-    cairo_show_text(cr, utf8);
+    cairo_show_text(cr, utf8.get());
 
     if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
         return false;
@@ -679,7 +679,7 @@ selectFontFace_func(JSContext *context,
                     JS::Value *vp)
 {
     GJS_GET_PRIV(context, argc, vp, argv, obj, GjsCairoContext, priv);
-    GjsAutoJSChar family;
+    JS::UniqueChars family;
     cairo_font_slant_t slant;
     cairo_font_weight_t weight;
     cairo_t *cr = priv ? priv->cr : NULL;
@@ -690,7 +690,7 @@ selectFontFace_func(JSContext *context,
                              "weight", &weight))
         return false;
 
-    cairo_select_font_face(cr, family, slant, weight);
+    cairo_select_font_face(cr, family.get(), slant, weight);
 
     if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
         return false;
diff --git a/test/gjs-test-call-args.cpp b/test/gjs-test-call-args.cpp
index d62d86e6..6a76568b 100644
--- a/test/gjs-test-call-args.cpp
+++ b/test/gjs-test-call-args.cpp
@@ -86,7 +86,7 @@ JSNATIVE_TEST_FUNC_END
 
 JSNATIVE_TEST_FUNC_BEGIN(one_of_each_type)
     bool boolval;
-    GjsAutoJSChar strval;
+    JS::UniqueChars strval;
     GjsAutoChar fileval;
     int intval;
     unsigned uintval;
@@ -103,7 +103,7 @@ JSNATIVE_TEST_FUNC_BEGIN(one_of_each_type)
                                  "dbl", &dblval,
                                  "obj", &objval);
     g_assert_cmpint(boolval, ==, true);
-    g_assert_cmpstr(strval, ==, "foo");
+    g_assert_cmpstr(strval.get(), ==, "foo");
     g_assert_cmpstr(fileval, ==, "foo");
     g_assert_cmpint(intval, ==, 1);
     g_assert_cmpint(uintval, ==, 1);
@@ -156,7 +156,7 @@ JSNATIVE_TEST_FUNC_BEGIN(signed_enum_arg)
 JSNATIVE_TEST_FUNC_END
 
 JSNATIVE_TEST_FUNC_BEGIN(one_of_each_nullable_type)
-    GjsAutoJSChar strval;
+    JS::UniqueChars strval;
     GjsAutoChar fileval;
     JS::RootedObject objval(cx);
     retval = gjs_parse_call_args(cx, "oneOfEachNullableType", args, "?s?F?o",
@@ -208,10 +208,15 @@ JSNATIVE_BAD_TYPE_TEST_FUNC(unsigned, "t");
 JSNATIVE_BAD_TYPE_TEST_FUNC(int64_t, "f");
 JSNATIVE_BAD_TYPE_TEST_FUNC(double, "b");
 JSNATIVE_BAD_TYPE_TEST_FUNC(GjsAutoChar, "i");
-JSNATIVE_BAD_TYPE_TEST_FUNC(GjsAutoJSChar, "i");
 
 #undef JSNATIVE_BAD_TYPE_TEST_FUNC
 
+JSNATIVE_TEST_FUNC_BEGIN(UniqueChars_invalid_type)
+    JS::UniqueChars value;
+    retval = gjs_parse_call_args(cx, "UniqueCharsInvalidType", args, "i",
+                                 "value", &value);
+JSNATIVE_TEST_FUNC_END
+
 JSNATIVE_TEST_FUNC_BEGIN(object_invalid_type)
     JS::RootedObject val(cx);
     retval = gjs_parse_call_args(cx, "objectInvalidType", args, "i",
@@ -245,7 +250,7 @@ static JSFunctionSpec native_test_funcs[] = {
     JS_FN("int64_tInvalidType", int64_t_invalid_type, 0, 0),
     JS_FN("doubleInvalidType", double_invalid_type, 0, 0),
     JS_FN("GjsAutoCharInvalidType", GjsAutoChar_invalid_type, 0, 0),
-    JS_FN("GjsAutoJSCharInvalidType", GjsAutoJSChar_invalid_type, 0, 0),
+    JS_FN("UniqueCharsInvalidType", UniqueChars_invalid_type, 0, 0),
     JS_FN("objectInvalidType", object_invalid_type, 0, 0),
     JS_FS_END};
 
@@ -380,8 +385,8 @@ gjs_test_add_tests_for_parse_call_args(void)
                              "GjsAutoCharInvalidType(1)"
                              "//*Wrong type for i, got GjsAutoChar?");
     ADD_CALL_ARGS_TEST_XFAIL("invalid-autojschar-type",
-                             "GjsAutoJSCharInvalidType(1)"
-                             "//*Wrong type for i, got GjsAutoJSChar?");
+                             "UniqueCharsInvalidType(1)"
+                             "//*Wrong type for i, got JS::UniqueChars?");
     ADD_CALL_ARGS_TEST_XFAIL("invalid-object-type",
                              "objectInvalidType(1)"
                              "//*Wrong type for i, got JS::MutableHandleObject");
diff --git a/test/gjs-tests.cpp b/test/gjs-tests.cpp
index e482c80f..328c61c2 100644
--- a/test/gjs-tests.cpp
+++ b/test/gjs-tests.cpp
@@ -123,9 +123,9 @@ gjstest_test_func_gjs_jsapi_util_string_js_string_utf8(GjsUnitTestFixture *fx,
     g_assert_true(gjs_string_from_utf8(fx->cx, VALID_UTF8_STRING, &js_string));
     g_assert(js_string.isString());
 
-    GjsAutoJSChar utf8_result;
+    JS::UniqueChars utf8_result;
     g_assert(gjs_string_to_utf8(fx->cx, js_string, &utf8_result));
-    g_assert_cmpstr(VALID_UTF8_STRING, ==, utf8_result);
+    g_assert_cmpstr(VALID_UTF8_STRING, ==, utf8_result.get());
 }
 
 static void
@@ -148,10 +148,10 @@ gjstest_test_func_gjs_jsapi_util_error_throw(GjsUnitTestFixture *fx,
 
     g_assert(value.isString());
 
-    GjsAutoJSChar s;
+    JS::UniqueChars s;
     gjs_string_to_utf8(fx->cx, value, &s);
     g_assert_nonnull(s);
-    g_assert_cmpstr(s, ==, "This is an exception 42");
+    g_assert_cmpstr(s.get(), ==, "This is an exception 42");
 
     /* keep this around before we clear it */
     JS::RootedValue previous(fx->cx, exc);


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