[gjs] js: Use correct autoptr in gjs_string_to_filename()



commit 9ddca8b4fa2c42205d578d9ee782586d5b492618
Author: Philip Chimento <philip endlessm com>
Date:   Thu Jul 13 10:43:45 2017 -0700

    js: Use correct autoptr in gjs_string_to_filename()
    
    The return value of g_filename_from_utf8() (must be freed with g_free())
    was getting assigned to a GjsAutoJSChar (which would be freed with
    JS_free()). Instead gjs_string_to_filename() must have a GjsAutoChar
    output parameter.
    
    This requires changing gjs_parse_call_args() as well. We improve it by
    allowing to pass in autoptrs for 's' or 'F' args instead of char**.
    
    Fixes a few minor memory leaks, mostly in error paths in Cairo functions.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=785040

 gi/arg.cpp                      |   43 ++++++++++++++++++-------------
 gi/object.cpp                   |   39 +++++++++-------------------
 gjs/coverage.cpp                |    7 +---
 gjs/jsapi-util-args.h           |   45 +++++++++++++++++----------------
 gjs/jsapi-util-string.cpp       |    8 ++---
 gjs/jsapi-util.h                |    7 +++--
 gjs/stack.cpp                   |    2 +-
 modules/cairo-context.cpp       |    6 +---
 modules/cairo-image-surface.cpp |    4 +-
 modules/cairo-pdf-surface.cpp   |    7 +---
 modules/cairo-ps-surface.cpp    |    7 +---
 modules/cairo-surface.cpp       |    8 ++---
 modules/cairo-svg-surface.cpp   |    7 +---
 modules/system.cpp              |    3 +-
 test/gjs-test-call-args.cpp     |   52 +++++++++++++++++++++-----------------
 15 files changed, 114 insertions(+), 131 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index c7e92ee..77de076 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -414,24 +414,31 @@ value_to_ghashtable_key(JSContext      *cx,
 
 #undef HANDLE_UNSIGNED_INT
 
-#define HANDLE_STRING(type, lctype)                                   \
-    case GI_TYPE_TAG_##type: {                                        \
-        GjsAutoJSChar cstr(cx);                                       \
-        JS::RootedValue str_val(cx, value);                           \
-        if (!str_val.isString()) {                                    \
-            JS::RootedString str(cx, JS::ToString(cx, str_val));      \
-            str_val.setString(str);                                   \
-        }                                                             \
-        if (!gjs_string_to_##lctype(cx, str_val, &cstr))              \
-            return false;                                             \
-        *pointer_out = cstr.copy();                                   \
-        break;                                                        \
+    case GI_TYPE_TAG_FILENAME: {
+        GjsAutoChar cstr;
+        JS::RootedValue str_val(cx, value);
+        if (!str_val.isString()) {
+            JS::RootedString str(cx, JS::ToString(cx, str_val));
+            str_val.setString(str);
+        }
+        if (!gjs_string_to_filename(cx, str_val, &cstr))
+            return false;
+        *pointer_out = cstr.release();
+        break;
     }
 
-    HANDLE_STRING(FILENAME, filename);
-    HANDLE_STRING(UTF8, utf8);
-
-#undef HANDLE_STRING
+    case GI_TYPE_TAG_UTF8: {
+        GjsAutoJSChar cstr(cx);
+        JS::RootedValue str_val(cx, value);
+        if (!str_val.isString()) {
+            JS::RootedString str(cx, JS::ToString(cx, str_val));
+            str_val.setString(str);
+        }
+        if (!gjs_string_to_utf8(cx, str_val, &cstr))
+            return false;
+        *pointer_out = cstr.copy();
+        break;
+    }
 
     case GI_TYPE_TAG_FLOAT:
     case GI_TYPE_TAG_DOUBLE:
@@ -1467,9 +1474,9 @@ gjs_value_to_g_argument(JSContext      *context,
         if (value.isNull()) {
             arg->v_pointer = NULL;
         } else if (value.isString()) {
-            GjsAutoJSChar filename_str(context);
+            GjsAutoChar filename_str;
             if (gjs_string_to_filename(context, value, &filename_str))
-                arg->v_pointer = filename_str.copy();
+                arg->v_pointer = filename_str.release();
             else
                 wrong = true;
         } else {
diff --git a/gi/object.cpp b/gi/object.cpp
index 3d2b350..2bf51db 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -2137,7 +2137,7 @@ static void
 find_vfunc_info (JSContext *context,
                  GType implementor_gtype,
                  GIBaseInfo *vfunc_info,
-                 gchar *vfunc_name,
+                 const char   *vfunc_name,
                  gpointer *implementor_vtable_ret,
                  GIFieldInfo **field_info_ret)
 {
@@ -2214,7 +2214,7 @@ gjs_hook_up_vfunc(JSContext *cx,
                   JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    gchar *name;
+    GjsAutoJSChar name(cx);
     JS::RootedObject object(cx), function(cx);
     ObjectInstance *priv;
     GType gtype, info_gtype;
@@ -2279,9 +2279,8 @@ gjs_hook_up_vfunc(JSContext *cx,
     }
 
     if (!vfunc) {
-        gjs_throw(cx, "Could not find definition of virtual function %s", name);
-
-        g_free(name);
+        gjs_throw(cx, "Could not find definition of virtual function %s",
+                  name.get());
         return false;
     }
 
@@ -2315,7 +2314,6 @@ gjs_hook_up_vfunc(JSContext *cx,
     }
 
     g_base_info_unref(vfunc);
-    g_free(name);
     return true;
 }
 
@@ -2460,7 +2458,7 @@ gjs_override_property(JSContext *cx,
                       JS::Value *vp)
 {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-    gchar *name = NULL;
+    GjsAutoJSChar name(cx);
     JS::RootedObject type(cx);
     GParamSpec *pspec;
     GParamSpec *new_pspec;
@@ -2473,7 +2471,6 @@ gjs_override_property(JSContext *cx,
 
     if ((gtype = gjs_gtype_get_actual_gtype(cx, type)) == G_TYPE_INVALID) {
         gjs_throw(cx, "Invalid parameter type was not a GType");
-        g_clear_pointer(&name, g_free);
         return false;
     }
 
@@ -2489,14 +2486,12 @@ gjs_override_property(JSContext *cx,
     }
 
     if (pspec == NULL) {
-        gjs_throw(cx, "No such property '%s' to override on type '%s'", name,
-                  g_type_name(gtype));
-        g_clear_pointer(&name, g_free);
+        gjs_throw(cx, "No such property '%s' to override on type '%s'",
+                  name.get(), g_type_name(gtype));
         return false;
     }
 
     new_pspec = g_param_spec_override(name, pspec);
-    g_clear_pointer(&name, g_free);
 
     g_param_spec_set_qdata(new_pspec, gjs_is_custom_property_quark(), GINT_TO_POINTER(1));
 
@@ -2724,7 +2719,7 @@ gjs_register_interface(JSContext *cx,
                        JS::Value *vp)
 {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-    char *name = NULL;
+    GjsAutoJSChar name(cx);
     guint32 i, n_interfaces, n_properties;
     GType *iface_types;
     GType interface_type;
@@ -2751,29 +2746,23 @@ gjs_register_interface(JSContext *cx,
         return false;
 
     if (!validate_interfaces_and_properties_args(cx, interfaces, properties,
-                                                 &n_interfaces, &n_properties)) {
-        g_clear_pointer(&name, g_free);
+                                                 &n_interfaces, &n_properties))
         return false;
-    }
 
     iface_types = (GType *) g_alloca(sizeof(GType) * n_interfaces);
 
     /* We do interface addition in two passes so that any failure
        is caught early, before registering the GType (which we can't undo) */
-    if (!get_interface_gtypes(cx, interfaces, n_interfaces, iface_types)) {
-        g_clear_pointer(&name, g_free);
+    if (!get_interface_gtypes(cx, interfaces, n_interfaces, iface_types))
         return false;
-    }
 
     if (g_type_from_name(name) != G_TYPE_INVALID) {
-        gjs_throw(cx, "Type name %s is already registered", name);
-        g_clear_pointer(&name, g_free);
+        gjs_throw(cx, "Type name %s is already registered", name.get());
         return false;
     }
 
     interface_type = g_type_register_static(G_TYPE_INTERFACE, name, &type_info,
                                             (GTypeFlags) 0);
-    g_clear_pointer(&name, g_free);
 
     g_type_set_qdata(interface_type, gjs_is_custom_type_quark(), GINT_TO_POINTER(1));
 
@@ -2801,7 +2790,7 @@ gjs_register_type(JSContext *cx,
                   JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    gchar *name;
+    GjsAutoJSChar name(cx);
     GType instance_type, parent_type;
     GTypeQuery query;
     ObjectInstance *parent_priv;
@@ -2850,7 +2839,7 @@ gjs_register_type(JSContext *cx,
         return false;
 
     if (g_type_from_name(name) != G_TYPE_INVALID) {
-        gjs_throw (cx, "Type name %s is already registered", name);
+        gjs_throw(cx, "Type name %s is already registered", name.get());
         return false;
     }
 
@@ -2873,8 +2862,6 @@ gjs_register_type(JSContext *cx,
     instance_type = g_type_register_static(parent_type, name, &type_info,
                                            (GTypeFlags) 0);
 
-    g_free(name);
-
     g_type_set_qdata (instance_type, gjs_is_custom_type_quark(), GINT_TO_POINTER (1));
 
     if (!save_properties_for_class_init(cx, properties, n_properties, instance_type))
diff --git a/gjs/coverage.cpp b/gjs/coverage.cpp
index 3281ff3..2c74359 100644
--- a/gjs/coverage.cpp
+++ b/gjs/coverage.cpp
@@ -1363,17 +1363,14 @@ coverage_log(JSContext *context,
 static GFile *
 get_file_from_call_args_filename(JSContext    *context,
                                  JS::CallArgs &args) {
-    char *filename = NULL;
+    GjsAutoJSChar filename(context);
 
     if (!gjs_parse_call_args(context, "getFileContents", args, "s",
                              "filename", &filename))
         return NULL;
 
     /* path could be a resource, so use g_file_new_for_commandline_arg. */
-    GFile *file = g_file_new_for_commandline_arg(filename);
-
-    g_free(filename);
-    return file;
+    return g_file_new_for_commandline_arg(filename);
 }
 
 static bool
diff --git a/gjs/jsapi-util-args.h b/gjs/jsapi-util-args.h
index d0baa12..520ac8f 100644
--- a/gjs/jsapi-util-args.h
+++ b/gjs/jsapi-util-args.h
@@ -91,26 +91,34 @@ assign(JSContext      *cx,
        char            c,
        bool            nullable,
        JS::HandleValue value,
-       char          **ref)
+       GjsAutoJSChar  *ref)
 {
-    if (nullable && (c == 's' || c == 'F') && value.isNull()) {
-        *ref = NULL;
+    if (c != 's')
+        throw g_strdup_printf("Wrong type for %c, got GjsAutoJSChar*", c);
+    if (nullable && value.isNull()) {
+        ref->reset(cx, nullptr);
         return;
     }
+    if (!gjs_string_to_utf8(cx, value, ref))
+        throw g_strdup("Couldn't convert to string");
+}
 
-    GjsAutoJSChar tmp_ref(cx);
-
-    if (c == 's') {
-        if (!gjs_string_to_utf8(cx, value, &tmp_ref))
-            throw g_strdup("Couldn't convert to string");
-    } else if (c == 'F') {
-        if (!gjs_string_to_filename(cx, value, &tmp_ref))
-            throw g_strdup("Couldn't convert to filename");
-    } else {
-        throw g_strdup_printf("Wrong type for %c, got char**", c);
+GJS_ALWAYS_INLINE
+static inline void
+assign(JSContext      *cx,
+       char            c,
+       bool            nullable,
+       JS::HandleValue value,
+       GjsAutoChar    *ref)
+{
+    if (c != 'F')
+        throw g_strdup_printf("Wrong type for %c, got GjsAutoChar*", c);
+    if (nullable && value.isNull()) {
+        ref->release();
+        return;
     }
-
-    *ref = tmp_ref.copy();
+    if (!gjs_string_to_filename(cx, value, ref))
+        throw g_strdup("Couldn't convert to filename");
 }
 
 GJS_ALWAYS_INLINE
@@ -222,13 +230,6 @@ free_if_necessary(JS::MutableHandleObject param_ref)
     param_ref.set(NULL);
 }
 
-GJS_ALWAYS_INLINE
-static inline void
-free_if_necessary(char **param_ref)
-{
-    g_free(*param_ref);
-}
-
 template<typename T>
 static bool
 parse_call_args_helper(JSContext    *cx,
diff --git a/gjs/jsapi-util-string.cpp b/gjs/jsapi-util-string.cpp
index bc8cb74..53f32f5 100644
--- a/gjs/jsapi-util-string.cpp
+++ b/gjs/jsapi-util-string.cpp
@@ -93,11 +93,10 @@ gjs_string_from_utf8(JSContext             *context,
 bool
 gjs_string_to_filename(JSContext      *context,
                        const JS::Value filename_val,
-                       GjsAutoJSChar  *filename_string_p)
+                       GjsAutoChar    *filename_string)
 {
     GError *error;
     GjsAutoJSChar tmp(context);
-    char *filename_string;
 
     /* gjs_string_to_filename verifies that filename_val is a string */
 
@@ -107,13 +106,12 @@ gjs_string_to_filename(JSContext      *context,
     }
 
     error = NULL;
-    filename_string = g_filename_from_utf8(tmp, -1, NULL, NULL, &error);
-    if (!filename_string) {
+    *filename_string = g_filename_from_utf8(tmp, -1, NULL, NULL, &error);
+    if (!*filename_string) {
         gjs_throw_g_error(context, error);
         return false;
     }
 
-    filename_string_p->reset(context, filename_string);
     return true;
 }
 
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index e30c742..fe5b524 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -215,9 +215,10 @@ bool gjs_string_from_utf8(JSContext             *context,
                           ssize_t                n_bytes,
                           JS::MutableHandleValue value_p);
 
-bool        gjs_string_to_filename           (JSContext       *context,
-                                              const JS::Value  string_val,
-                                              GjsAutoJSChar   *filename_string_p);
+bool gjs_string_to_filename(JSContext       *cx,
+                            const JS::Value  string_val,
+                            GjsAutoChar     *filename_string);
+
 bool gjs_string_from_filename(JSContext             *context,
                               const char            *filename_string,
                               ssize_t                n_bytes,
diff --git a/gjs/stack.cpp b/gjs/stack.cpp
index 0096393..2d3a7cb 100644
--- a/gjs/stack.cpp
+++ b/gjs/stack.cpp
@@ -89,7 +89,7 @@ gjs_context_print_stack_stderr(GjsContext *context)
 {
     JSContext *cx = (JSContext*) gjs_context_get_native_context(context);
     JS::RootedValue v_stack(cx);
-    GjsAutoJSChar stack(cx);
+    GjsAutoChar stack;
 
     g_printerr("== Stack trace for context %p ==\n", context);
 
diff --git a/modules/cairo-context.cpp b/modules/cairo-context.cpp
index 5f34d21..7d6263b 100644
--- a/modules/cairo-context.cpp
+++ b/modules/cairo-context.cpp
@@ -656,7 +656,7 @@ showText_func(JSContext *context,
               JS::Value *vp)
 {
     GJS_GET_PRIV(context, argc, vp, argv, obj, GjsCairoContext, priv);
-    char *utf8;
+    GjsAutoJSChar utf8(context);
     cairo_t *cr = priv ? priv->cr : NULL;
 
     if (!gjs_parse_call_args(context, "showText", argv, "s",
@@ -664,7 +664,6 @@ showText_func(JSContext *context,
         return false;
 
     cairo_show_text(cr, utf8);
-    g_free(utf8);
 
     if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
         return false;
@@ -680,7 +679,7 @@ selectFontFace_func(JSContext *context,
                     JS::Value *vp)
 {
     GJS_GET_PRIV(context, argc, vp, argv, obj, GjsCairoContext, priv);
-    char *family;
+    GjsAutoJSChar family(context);
     cairo_font_slant_t slant;
     cairo_font_weight_t weight;
     cairo_t *cr = priv ? priv->cr : NULL;
@@ -692,7 +691,6 @@ selectFontFace_func(JSContext *context,
         return false;
 
     cairo_select_font_face(cr, family, slant, weight);
-    g_free(family);
 
     if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
         return false;
diff --git a/modules/cairo-image-surface.cpp b/modules/cairo-image-surface.cpp
index 8aaa640..85942f9 100644
--- a/modules/cairo-image-surface.cpp
+++ b/modules/cairo-image-surface.cpp
@@ -79,10 +79,10 @@ createFromPNG_func(JSContext *context,
                    JS::Value *vp)
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
-    char *filename = nullptr;
+    GjsAutoChar filename;
     cairo_surface_t *surface;
 
-    if (!gjs_parse_call_args(context, "createFromPNG", argv, "s",
+    if (!gjs_parse_call_args(context, "createFromPNG", argv, "F",
                              "filename", &filename))
         return false;
 
diff --git a/modules/cairo-pdf-surface.cpp b/modules/cairo-pdf-surface.cpp
index 56c89a1..1c97d73 100644
--- a/modules/cairo-pdf-surface.cpp
+++ b/modules/cairo-pdf-surface.cpp
@@ -39,7 +39,7 @@ GJS_DEFINE_PROTO_WITH_PARENT("PDFSurface", cairo_pdf_surface,
 GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_pdf_surface)
 {
     GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_pdf_surface)
-    char *filename = nullptr;
+    GjsAutoChar filename;
     double width, height;
     cairo_surface_t *surface;
 
@@ -54,14 +54,11 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_pdf_surface)
     surface = cairo_pdf_surface_create(filename, width, height);
 
     if (!gjs_cairo_check_status(context, cairo_surface_status(surface),
-                                "surface")) {
-        g_free(filename);
+                                "surface"))
         return false;
-    }
 
     gjs_cairo_surface_construct(context, object, surface);
     cairo_surface_destroy(surface);
-    g_free(filename);
 
     GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_pdf_surface);
 
diff --git a/modules/cairo-ps-surface.cpp b/modules/cairo-ps-surface.cpp
index 4b930ae..833dc8d 100644
--- a/modules/cairo-ps-surface.cpp
+++ b/modules/cairo-ps-surface.cpp
@@ -39,7 +39,7 @@ GJS_DEFINE_PROTO_WITH_PARENT("PSSurface", cairo_ps_surface, cairo_surface,
 GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_ps_surface)
 {
     GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_ps_surface)
-    char *filename = nullptr;
+    GjsAutoChar filename;
     double width, height;
     cairo_surface_t *surface;
 
@@ -54,14 +54,11 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_ps_surface)
     surface = cairo_ps_surface_create(filename, width, height);
 
     if (!gjs_cairo_check_status(context, cairo_surface_status(surface),
-                                "surface")) {
-        g_free(filename);
+                                "surface"))
         return false;
-    }
 
     gjs_cairo_surface_construct(context, object, surface);
     cairo_surface_destroy(surface);
-    g_free(filename);
 
     GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_ps_surface);
 
diff --git a/modules/cairo-surface.cpp b/modules/cairo-surface.cpp
index 34803d1..af783f9 100644
--- a/modules/cairo-surface.cpp
+++ b/modules/cairo-surface.cpp
@@ -66,7 +66,7 @@ writeToPNG_func(JSContext *context,
                 JS::Value *vp)
 {
     GJS_GET_THIS(context, argc, vp, argv, obj);
-    char *filename = nullptr;
+    GjsAutoChar filename;
     cairo_surface_t *surface;
 
     if (!gjs_parse_call_args(context, "writeToPNG", argv, "F",
@@ -74,12 +74,10 @@ writeToPNG_func(JSContext *context,
         return false;
 
     surface = gjs_cairo_surface_get_surface(context, obj);
-    if (!surface) {
-        g_free(filename);
+    if (!surface)
         return false;
-    }
+
     cairo_surface_write_to_png(surface, filename);
-    g_free(filename);
     if (!gjs_cairo_check_status(context, cairo_surface_status(surface),
                                 "surface"))
         return false;
diff --git a/modules/cairo-svg-surface.cpp b/modules/cairo-svg-surface.cpp
index 4fb32b6..52e4645 100644
--- a/modules/cairo-svg-surface.cpp
+++ b/modules/cairo-svg-surface.cpp
@@ -39,7 +39,7 @@ GJS_DEFINE_PROTO_WITH_PARENT("SVGSurface", cairo_svg_surface,
 GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_svg_surface)
 {
     GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_svg_surface)
-    char *filename = nullptr;
+    GjsAutoChar filename;
     double width, height;
     cairo_surface_t *surface;
 
@@ -54,14 +54,11 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_svg_surface)
     surface = cairo_svg_surface_create(filename, width, height);
 
     if (!gjs_cairo_check_status(context, cairo_surface_status(surface),
-                                "surface")) {
-        g_free(filename);
+                                "surface"))
         return false;
-    }
 
     gjs_cairo_surface_construct(context, object, surface);
     cairo_surface_destroy(surface);
-    g_free(filename);
 
     GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_svg_surface);
 
diff --git a/modules/system.cpp b/modules/system.cpp
index 81b7ae3..368a7cf 100644
--- a/modules/system.cpp
+++ b/modules/system.cpp
@@ -105,7 +105,7 @@ gjs_dump_heap(JSContext *cx,
               JS::Value *vp)
 {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-    char *filename = nullptr;
+    GjsAutoChar filename;
 
     if (!gjs_parse_call_args(cx, "dumpHeap", args, "|F", "filename", &filename))
         return false;
@@ -114,7 +114,6 @@ gjs_dump_heap(JSContext *cx,
         FILE *fp = fopen(filename, "a");
         js::DumpHeap(cx, fp, js::IgnoreNurseryObjects);
         fclose(fp);
-        g_free(filename);
     } else {
         js::DumpHeap(cx, stdout, js::IgnoreNurseryObjects);
     }
diff --git a/test/gjs-test-call-args.cpp b/test/gjs-test-call-args.cpp
index 601a14f..49563ee 100644
--- a/test/gjs-test-call-args.cpp
+++ b/test/gjs-test-call-args.cpp
@@ -85,7 +85,8 @@ JSNATIVE_TEST_FUNC_END
 
 JSNATIVE_TEST_FUNC_BEGIN(one_of_each_type)
     bool boolval;
-    char *strval, *fileval;
+    GjsAutoJSChar strval(cx);
+    GjsAutoChar fileval;
     int intval;
     unsigned uintval;
     int64_t int64val;
@@ -108,8 +109,6 @@ JSNATIVE_TEST_FUNC_BEGIN(one_of_each_type)
     g_assert_cmpint(int64val, ==, 1);
     g_assert_cmpfloat(dblval, ==, 1.0);
     g_assert_nonnull(objval);
-    g_free(strval);
-    g_free(fileval);
 JSNATIVE_TEST_FUNC_END
 
 JSNATIVE_TEST_FUNC_BEGIN(optional_args_all)
@@ -156,7 +155,8 @@ JSNATIVE_TEST_FUNC_BEGIN(signed_enum_arg)
 JSNATIVE_TEST_FUNC_END
 
 JSNATIVE_TEST_FUNC_BEGIN(one_of_each_nullable_type)
-    char *strval, *fileval;
+    GjsAutoJSChar strval(cx);
+    GjsAutoChar fileval;
     JS::RootedObject objval(cx);
     retval = gjs_parse_call_args(cx, "oneOfEachNullableType", args, "?s?F?o",
                                  "strval", &strval,
@@ -168,18 +168,14 @@ JSNATIVE_TEST_FUNC_BEGIN(one_of_each_nullable_type)
 JSNATIVE_TEST_FUNC_END
 
 JSNATIVE_TEST_FUNC_BEGIN(unwind_free_test)
-    char *strval, *fileval;
     int intval;
     unsigned uval;
     JS::RootedObject objval(cx);
-    retval = gjs_parse_call_args(cx, "unwindFreeTest", args, "sFoiu",
-                                 "strval", &strval,
-                                 "fileval", &fileval,
+    retval = gjs_parse_call_args(cx, "unwindFreeTest", args, "oiu",
                                  "objval", &objval,
                                  "intval", &intval,
                                  "error", &uval);
     g_assert_null(objval);
-    /* Sadly, we cannot assert that strval and fileval have been freed */
 JSNATIVE_TEST_FUNC_END
 
 #define JSNATIVE_BAD_NULLABLE_TEST_FUNC(type, fmt)                 \
@@ -210,16 +206,22 @@ JSNATIVE_BAD_TYPE_TEST_FUNC(int, "u");
 JSNATIVE_BAD_TYPE_TEST_FUNC(unsigned, "t");
 JSNATIVE_BAD_TYPE_TEST_FUNC(int64_t, "f");
 JSNATIVE_BAD_TYPE_TEST_FUNC(double, "b");
-typedef char *charptr;
-JSNATIVE_BAD_TYPE_TEST_FUNC(charptr, "i");
+JSNATIVE_BAD_TYPE_TEST_FUNC(GjsAutoChar, "i");
 
 #undef JSNATIVE_BAD_TYPE_TEST_FUNC
 
-JSNATIVE_TEST_FUNC_BEGIN(object_invalid_type)
-    JS::RootedObject val(cx);
-    retval = gjs_parse_call_args(cx, "objectInvalidType", args, "i",
-                                 "val", &val);
-JSNATIVE_TEST_FUNC_END
+#define JSNATIVE_CONSTRUCTED_BAD_TYPE_TEST_FUNC(type, ch)                \
+    JSNATIVE_TEST_FUNC_BEGIN(type##_invalid_type)                        \
+        type val(cx);                                                    \
+        retval = gjs_parse_call_args(cx, #type "InvalidType", args, ch,  \
+                                     "val", &val);                       \
+    JSNATIVE_TEST_FUNC_END
+
+using JS::RootedObject;
+JSNATIVE_CONSTRUCTED_BAD_TYPE_TEST_FUNC(GjsAutoJSChar, "i");
+JSNATIVE_CONSTRUCTED_BAD_TYPE_TEST_FUNC(RootedObject, "i");
+
+#undef JSNATIVE_CONSTRUCTED_BAD_TYPE_TEST_FUNC
 
 static JSFunctionSpec native_test_funcs[] = {
     JS_FS("noArgs", no_args, 0, 0),
@@ -247,8 +249,9 @@ static JSFunctionSpec native_test_funcs[] = {
     JS_FS("unsignedInvalidType", unsigned_invalid_type, 0, 0),
     JS_FS("int64_tInvalidType", int64_t_invalid_type, 0, 0),
     JS_FS("doubleInvalidType", double_invalid_type, 0, 0),
-    JS_FS("charptrInvalidType", charptr_invalid_type, 0, 0),
-    JS_FS("objectInvalidType", object_invalid_type, 0, 0),
+    JS_FS("GjsAutoCharInvalidType", GjsAutoChar_invalid_type, 0, 0),
+    JS_FS("GjsAutoJSCharInvalidType", GjsAutoJSChar_invalid_type, 0, 0),
+    JS_FS("RootedObjectInvalidType", RootedObject_invalid_type, 0, 0),
     JS_FS_END
 };
 
@@ -347,7 +350,7 @@ gjs_test_add_tests_for_parse_call_args(void)
     ADD_CALL_ARGS_TEST("passing-all-arguments-when-all-optional",
                        "onlyOptionalArgs(1, 1)");
     ADD_CALL_ARGS_TEST_XFAIL("allocated-args-are-freed-on-error",
-                             "unwindFreeTest('', '', {}, 1, -1)"
+                             "unwindFreeTest({}, 1, -1)"
                              "//*Value * is out of range");
     ADD_CALL_ARGS_TEST_XFAIL("nullable-bool-is-invalid",
                              "boolInvalidNullable(true)"
@@ -379,11 +382,14 @@ gjs_test_add_tests_for_parse_call_args(void)
     ADD_CALL_ARGS_TEST_XFAIL("invalid-double-type",
                              "doubleInvalidType(false)"
                              "//*Wrong type for b, got double?");
-    ADD_CALL_ARGS_TEST_XFAIL("invalid-string-type",
-                             "charptrInvalidType(1)"
-                             "//*Wrong type for i, got char??");
+    ADD_CALL_ARGS_TEST_XFAIL("invalid-autochar-type",
+                             "GjsAutoCharInvalidType(1)"
+                             "//*Wrong type for i, got GjsAutoChar?");
+    ADD_CALL_ARGS_TEST_XFAIL("invalid-autojschar-type",
+                             "GjsAutoJSCharInvalidType(1)"
+                             "//*Wrong type for i, got GjsAutoJSChar?");
     ADD_CALL_ARGS_TEST_XFAIL("invalid-object-type",
-                             "objectInvalidType(1)"
+                             "RootedObjectInvalidType(1)"
                              "//*Wrong type for i, got JS::MutableHandleObject");
     ADD_CALL_ARGS_TEST_XFAIL("invalid-boolean",
                              "boolArgNoAssert({})//*Not a boolean");


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