[gjs: 15/18] js: Remove most goto error handling



commit 46580c00e143a46d75476a686f73200ed4ee8f84
Author: Philip Chimento <philip chimento gmail com>
Date:   Mon Dec 2 21:54:15 2019 -0800

    js: Remove most goto error handling
    
    This is C++, we have RAII, so while "goto out" is a good pattern in C if
    you are not using g_autoptr, it's not a good pattern in our code. This
    removes most goto error handling in favour of RAII or splitting
    non-cleanup parts out to a second function. There are still a few
    instances of it left, that will require more extensive refactoring.

 gi/arg.cpp            | 223 +++++++++++++++++++++++---------------------------
 gi/boxed.cpp          |  47 +++--------
 gi/repo.cpp           |  35 ++++----
 gjs/console.cpp       |  46 ++++++-----
 gjs/context-private.h |  15 +++-
 gjs/context.cpp       |  12 +--
 gjs/importer.cpp      |  65 +++++++--------
 gjs/jsapi-util.cpp    |  11 ++-
 8 files changed, 209 insertions(+), 245 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index aa3efc41..3c4e194e 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -491,7 +491,6 @@ gjs_object_to_g_hash(JSContext   *context,
                      GITransfer   transfer,
                      GHashTable **hash_p)
 {
-    GHashTable *result = NULL;
     size_t id_ix, id_len;
 
     g_assert(hash_value.isObjectOrNull());
@@ -516,7 +515,8 @@ gjs_object_to_g_hash(JSContext   *context,
     if (!JS_Enumerate(context, props, &ids))
         return false;
 
-    result = create_hash_table_for_key_type(key_param_info);
+    GjsAutoPointer<GHashTable, GHashTable, g_hash_table_destroy> result =
+        create_hash_table_for_key_type(key_param_info);
 
     JS::RootedValue key_js(context), val_js(context);
     JS::RootedId cur_id(context);
@@ -525,23 +525,16 @@ gjs_object_to_g_hash(JSContext   *context,
         gpointer key_ptr, val_ptr;
         GIArgument val_arg = { 0 };
 
-        if (!JS_IdToValue(context, cur_id, &key_js))
-            goto free_hash_and_fail;
-
-        /* Type check key type. */
-        if (!value_to_ghashtable_key(context, key_js, key_param_info, &key_ptr))
-            goto free_hash_and_fail;
-
-        if (!JS_GetPropertyById(context, props, cur_id, &val_js))
-            goto free_hash_and_fail;
-
-        /* Type check and convert value to a c type */
-        if (!gjs_value_to_g_argument(context, val_js, val_param_info, NULL,
-                                     GJS_ARGUMENT_HASH_ELEMENT,
-                                     transfer,
-                                     true /* allow null */,
-                                     &val_arg))
-            goto free_hash_and_fail;
+        if (!JS_IdToValue(context, cur_id, &key_js) ||
+            // Type check key type.
+            !value_to_ghashtable_key(context, key_js, key_param_info,
+                                     &key_ptr) ||
+            !JS_GetPropertyById(context, props, cur_id, &val_js) ||
+            // Type check and convert value to a C type
+            !gjs_value_to_g_argument(context, val_js, val_param_info, nullptr,
+                                     GJS_ARGUMENT_HASH_ELEMENT, transfer,
+                                     true /* allow null */, &val_arg))
+            return false;
 
         GITypeTag val_type = g_type_info_get_tag(val_param_info);
         /* Use heap-allocated values for types that don't fit in a pointer */
@@ -569,12 +562,8 @@ gjs_object_to_g_hash(JSContext   *context,
         g_hash_table_insert(result, key_ptr, val_ptr);
     }
 
-    *hash_p = result;
+    *hash_p = result.release();
     return true;
-
- free_hash_and_fail:
-    g_hash_table_destroy(result);
-    return false;
 }
 
 bool
@@ -1336,8 +1325,6 @@ gjs_array_to_explicit_array_internal(JSContext       *context,
                                      gpointer        *contents,
                                      gsize           *length_p)
 {
-    bool ret = false;
-    GITypeInfo *param_info;
     bool found_length;
 
     gjs_debug_marshal(
@@ -1345,12 +1332,11 @@ gjs_array_to_explicit_array_internal(JSContext       *context,
         "Converting argument '%s' JS value %s to C array, transfer %d",
         arg_name, gjs_debug_value(value).c_str(), transfer);
 
-    param_info = g_type_info_get_param_type(type_info, 0);
+    GjsAutoTypeInfo param_info = g_type_info_get_param_type(type_info, 0);
 
     if ((value.isNull() && !may_be_null) ||
         (!value.isString() && !value.isObjectOrNull())) {
         throw_invalid_argument(context, value, param_info, arg_name, arg_type);
-        g_base_info_unref((GIBaseInfo*) param_info);
         return false;
     }
 
@@ -1361,7 +1347,7 @@ gjs_array_to_explicit_array_internal(JSContext       *context,
         /* Allow strings as int8/uint8/int16/uint16 arrays */
         JS::RootedString str(context, value.toString());
         if (!gjs_string_to_intarray(context, str, param_info, contents, length_p))
-            goto out;
+            return false;
     } else {
         JS::RootedObject array_obj(context, &value.toObject());
         const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
@@ -1377,7 +1363,7 @@ gjs_array_to_explicit_array_internal(JSContext       *context,
 
             if (!gjs_object_require_converted_property(
                     context, array_obj, nullptr, atoms.length(), &length)) {
-                goto out;
+                return false;
             } else {
                 if (!gjs_array_to_array(context,
                                         value,
@@ -1385,21 +1371,17 @@ gjs_array_to_explicit_array_internal(JSContext       *context,
                                         transfer,
                                         param_info,
                                         contents))
-                    goto out;
+                    return false;
 
                 *length_p = length;
             }
         } else {
             throw_invalid_argument(context, value, param_info, arg_name, arg_type);
-            goto out;
+            return false;
         }
     }
 
-    ret = true;
- out:
-    g_base_info_unref((GIBaseInfo*) param_info);
-
-    return ret;
+    return true;
 }
 
 GJS_USE
@@ -2834,12 +2816,11 @@ gjs_value_from_g_argument (JSContext             *context,
 
     case GI_TYPE_TAG_INTERFACE:
         {
-            JS::RootedValue value(context);
-            GIBaseInfo* interface_info;
             GIInfoType interface_type;
             GType gtype;
 
-            interface_info = g_type_info_get_interface(type_info);
+            GjsAutoBaseInfo interface_info =
+                g_type_info_get_interface(type_info);
             g_assert(interface_info != NULL);
 
             interface_type = g_base_info_get_type(interface_info);
@@ -2848,7 +2829,7 @@ gjs_value_from_g_argument (JSContext             *context,
                 gjs_throw(context,
                           "Unable to resolve arg type '%s'",
                           g_base_info_get_name(interface_info));
-                goto out;
+                return false;
             }
 
             /* Enum/Flags are aren't pointer types, unlike the other interface subtypes */
@@ -2856,52 +2837,51 @@ gjs_value_from_g_argument (JSContext             *context,
                 int64_t value_int64 =
                     _gjs_enum_from_int(interface_info, arg->v_int);
 
-                if (_gjs_enum_value_is_valid(context, (GIEnumInfo *)interface_info, value_int64)) {
-                    value = JS::NumberValue(value_int64);
-                }
+                if (!_gjs_enum_value_is_valid(context, interface_info,
+                                              value_int64))
+                    return false;
+
+                value_p.setNumber(static_cast<double>(value_int64));
+                return true;
+            }
 
-                goto out;
-            } else if (interface_type == GI_INFO_TYPE_FLAGS) {
+            if (interface_type == GI_INFO_TYPE_FLAGS) {
                 int64_t value_int64 =
                     _gjs_enum_from_int(interface_info, arg->v_int);
 
                 gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo*)interface_info);
-                if (_gjs_flags_value_is_valid(context, gtype, value_int64)) {
-                    value = JS::NumberValue(value_int64);
-                }
+                if (!_gjs_flags_value_is_valid(context, gtype, value_int64))
+                    return false;
 
-                goto out;
-            } else if (interface_type == GI_INFO_TYPE_STRUCT &&
-                       g_struct_info_is_foreign((GIStructInfo*)interface_info)) {
-                bool ret;
-                ret = gjs_struct_foreign_convert_from_g_argument(context, value_p, interface_info, arg);
-                g_base_info_unref(interface_info);
-                return ret;
+                value_p.setNumber(static_cast<double>(value_int64));
+                return true;
+            }
+
+            if (interface_type == GI_INFO_TYPE_STRUCT &&
+                g_struct_info_is_foreign((GIStructInfo*)interface_info)) {
+                return gjs_struct_foreign_convert_from_g_argument(
+                    context, value_p, interface_info, arg);
             }
 
             /* Everything else is a pointer type, NULL is the easy case */
             if (arg->v_pointer == NULL) {
-                value = JS::NullValue();
-                goto out;
+                value_p.setNull();
+                return true;
             }
 
             if (interface_type == GI_INFO_TYPE_STRUCT &&
                 g_struct_info_is_gtype_struct((GIStructInfo*)interface_info)) {
-                bool ret;
-
                 /* XXX: here we make the implicit assumption that GTypeClass is the same
                    as GTypeInterface. This is true for the GType field, which is what we
                    use, but not for the rest of the structure!
                 */
                 gtype = G_TYPE_FROM_CLASS(arg->v_pointer);
 
-                if (g_type_is_a(gtype, G_TYPE_INTERFACE))
-                    ret = gjs_lookup_interface_constructor(context, gtype, value_p);
-                else
-                    ret = gjs_lookup_object_constructor(context, gtype, value_p);
-
-                g_base_info_unref(interface_info);
-                return ret;
+                if (g_type_is_a(gtype, G_TYPE_INTERFACE)) {
+                    return gjs_lookup_interface_constructor(context, gtype,
+                                                            value_p);
+                }
+                return gjs_lookup_object_constructor(context, gtype, value_p);
             }
 
             gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo*)interface_info);
@@ -2915,20 +2895,18 @@ gjs_value_from_g_argument (JSContext             *context,
 
             /* Test GValue and GError before Struct, or it will be handled as the latter */
             if (g_type_is_a(gtype, G_TYPE_VALUE)) {
-                if (!gjs_value_from_g_value(context, &value, (const GValue *) arg->v_pointer))
-                    value = JS::UndefinedValue(); /* Make sure error is flagged */
-
-                goto out;
+                return gjs_value_from_g_value(
+                    context, value_p,
+                    static_cast<const GValue*>(arg->v_pointer));
             }
+
             if (g_type_is_a(gtype, G_TYPE_ERROR)) {
                 JSObject* obj = ErrorInstance::object_for_c_ptr(
                     context, static_cast<GError*>(arg->v_pointer));
-                if (obj)
-                    value = JS::ObjectValue(*obj);
-                else
-                    value = JS::UndefinedValue();
-
-                goto out;
+                if (!obj)
+                    return false;
+                value_p.setObject(*obj);
+                return true;
             }
 
             if (interface_type == GI_INFO_TYPE_STRUCT || interface_type == GI_INFO_TYPE_BOXED) {
@@ -2943,12 +2921,10 @@ gjs_value_from_g_argument (JSContext             *context,
                             nullptr);
 
                     g_base_info_unref(atom_name_fun);
-                    g_base_info_unref(interface_info);
 
                     if (strcmp("NONE", atom_name_ret.v_string) == 0) {
                         g_free(atom_name_ret.v_string);
-                        value = JS::NullValue();
-
+                        value_p.setNull();
                         return true;
                     }
 
@@ -2968,60 +2944,72 @@ gjs_value_from_g_argument (JSContext             *context,
                         context, interface_info, arg->v_pointer,
                         BoxedInstance::NoCopy());
 
-                if (obj)
-                    value = JS::ObjectValue(*obj);
+                if (!obj)
+                    return false;
+
+                value_p.setObject(*obj);
+                return true;
+            }
 
-                goto out;
-            } else if (interface_type == GI_INFO_TYPE_UNION) {
+            if (interface_type == GI_INFO_TYPE_UNION) {
                 JSObject *obj;
                 obj = gjs_union_from_c_union(context, (GIUnionInfo *)interface_info, arg->v_pointer);
-                if (obj)
-                        value = JS::ObjectValue(*obj);
+                if (!obj)
+                    return false;
 
-                goto out;
+                value_p.setObject(*obj);
+                return true;
             }
 
             if (g_type_is_a(gtype, G_TYPE_OBJECT)) {
                 // arg->v_pointer == nullptr is already handled above
                 JSObject* obj = ObjectInstance::wrapper_from_gobject(
                     context, G_OBJECT(arg->v_pointer));
-                if (obj)
-                    value = JS::ObjectValue(*obj);
-            } else if (g_type_is_a(gtype, G_TYPE_BOXED) ||
-                       g_type_is_a(gtype, G_TYPE_ENUM) ||
-                       g_type_is_a(gtype, G_TYPE_FLAGS)) {
+                if (!obj)
+                    return false;
+                value_p.setObject(*obj);
+                return true;
+            }
+
+            if (g_type_is_a(gtype, G_TYPE_BOXED) ||
+                g_type_is_a(gtype, G_TYPE_ENUM) ||
+                g_type_is_a(gtype, G_TYPE_FLAGS)) {
                 /* Should have been handled above */
                 gjs_throw(context,
                           "Type %s registered for unexpected interface_type %d",
                           g_type_name(gtype),
                           interface_type);
                 return false;
-            } else if (g_type_is_a(gtype, G_TYPE_PARAM)) {
+            }
+
+            if (g_type_is_a(gtype, G_TYPE_PARAM)) {
                 JSObject *obj;
                 obj = gjs_param_from_g_param(context, G_PARAM_SPEC(arg->v_pointer));
-                if (obj)
-                    value = JS::ObjectValue(*obj);
-            } else if (gtype == G_TYPE_NONE) {
+                if (!obj)
+                    return false;
+                value_p.setObject(*obj);
+                return true;
+            }
+
+            if (gtype == G_TYPE_NONE) {
                 gjs_throw(context, "Unexpected unregistered type packing GArgument into JS::Value");
-            } else if (G_TYPE_IS_INSTANTIATABLE(gtype) || G_TYPE_IS_INTERFACE(gtype)) {
+                return false;
+            }
+
+            if (G_TYPE_IS_INSTANTIATABLE(gtype) || G_TYPE_IS_INTERFACE(gtype)) {
                 JSObject* obj = FundamentalInstance::object_for_c_ptr(
                     context, arg->v_pointer);
-                if (obj)
-                    value = JS::ObjectValue(*obj);
-            } else {
-                gjs_throw(context, "Unhandled GType %s packing GArgument into JS::Value",
-                          g_type_name(gtype));
+                if (!obj)
+                    return false;
+                value_p.setObject(*obj);
+                return true;
             }
 
-         out:
-            g_base_info_unref( (GIBaseInfo*) interface_info);
-
-            if (value.isUndefined())
-                return false;
-
-            value_p.set(value);
+            gjs_throw(context,
+                      "Unhandled GType %s packing GArgument into JS::Value",
+                      g_type_name(gtype));
+            return false;
         }
-        break;
 
     case GI_TYPE_TAG_ARRAY:
         if (arg->v_pointer == NULL) {
@@ -3226,11 +3214,11 @@ gjs_g_arg_release_internal(JSContext  *context,
 
     case GI_TYPE_TAG_INTERFACE:
         {
-            GIBaseInfo* interface_info;
             GIInfoType interface_type;
             GType gtype;
 
-            interface_info = g_type_info_get_interface(type_info);
+            GjsAutoBaseInfo interface_info =
+                g_type_info_get_interface(type_info);
             g_assert(interface_info != NULL);
 
             interface_type = g_base_info_get_type(interface_info);
@@ -3241,11 +3229,11 @@ gjs_g_arg_release_internal(JSContext  *context,
                         transfer, interface_info, arg);
 
             if (interface_type == GI_INFO_TYPE_ENUM || interface_type == GI_INFO_TYPE_FLAGS)
-                goto out;
+                return true;
 
             /* Anything else is a pointer */
             if (arg->v_pointer == NULL)
-                goto out;
+                return true;
 
             gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo*)interface_info);
             if (G_TYPE_IS_INSTANTIATABLE(gtype) ||
@@ -3295,13 +3283,10 @@ gjs_g_arg_release_internal(JSContext  *context,
             } else {
                 gjs_throw(context, "Unhandled GType %s releasing GArgument",
                           g_type_name(gtype));
-                failed = true;
+                return false;
             }
-
-        out:
-            g_base_info_unref( (GIBaseInfo*) interface_info);
         }
-        break;
+            return true;
 
     case GI_TYPE_TAG_GLIST:
         if (transfer != GI_TRANSFER_CONTAINER) {
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index d37603ba..97df571d 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -600,30 +600,18 @@ bool BoxedInstance::set_nested_interface_object(JSContext* context,
 bool BoxedInstance::field_setter_impl(JSContext* context,
                                       GIFieldInfo* field_info,
                                       JS::HandleValue value) {
-    GITypeInfo *type_info;
     GArgument arg;
-    bool success = false;
-    bool need_release = false;
-
-    type_info = g_field_info_get_type (field_info);
+    GjsAutoTypeInfo type_info = g_field_info_get_type(field_info);
 
     if (!g_type_info_is_pointer (type_info) &&
         g_type_info_get_tag (type_info) == GI_TYPE_TAG_INTERFACE) {
+        GjsAutoBaseInfo interface_info = g_type_info_get_interface(type_info);
 
-        GIBaseInfo *interface_info = g_type_info_get_interface(type_info);
-
-        if (g_base_info_get_type (interface_info) == GI_INFO_TYPE_STRUCT ||
-            g_base_info_get_type (interface_info) == GI_INFO_TYPE_BOXED) {
-            success = set_nested_interface_object(context, field_info,
-                                                  interface_info, value);
-
-            g_base_info_unref ((GIBaseInfo *)interface_info);
-
-            goto out;
+        if (interface_info.type() == GI_INFO_TYPE_STRUCT ||
+            interface_info.type() == GI_INFO_TYPE_BOXED) {
+            return set_nested_interface_object(context, field_info,
+                                               interface_info, value);
         }
-
-        g_base_info_unref ((GIBaseInfo *)interface_info);
-
     }
 
     if (!gjs_value_to_g_argument(context, value,
@@ -632,28 +620,19 @@ bool BoxedInstance::field_setter_impl(JSContext* context,
                                  GJS_ARGUMENT_FIELD,
                                  GI_TRANSFER_NOTHING,
                                  true, &arg))
-        goto out;
-
-    need_release = true;
+        return false;
 
+    bool success = true;
     if (!g_field_info_set_field(field_info, m_ptr, &arg)) {
         gjs_throw(context, "Writing field %s.%s is not supported", name(),
                   g_base_info_get_name(field_info));
-        goto out;
-    }
-
-    success = true;
-
-out:
-    if (need_release) {
-        JS::AutoSaveExceptionState saved_exc(context);
-        if (!gjs_g_argument_release(context, GI_TRANSFER_NOTHING, type_info,
-                                    &arg))
-            gjs_log_exception(context);
-        saved_exc.restore();
+        success = false;
     }
 
-    g_base_info_unref ((GIBaseInfo *)type_info);
+    JS::AutoSaveExceptionState saved_exc(context);
+    if (!gjs_g_argument_release(context, GI_TRANSFER_NOTHING, type_info, &arg))
+        gjs_log_exception(context);
+    saved_exc.restore();
 
     return success;
 }
diff --git a/gi/repo.cpp b/gi/repo.cpp
index 75ce4cee..90d22329 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -307,6 +307,20 @@ gjs_define_repo(JSContext              *cx,
     return true;
 }
 
+GJS_JSAPI_RETURN_CONVENTION
+static bool gjs_value_from_constant_info(JSContext* cx, GIConstantInfo* info,
+                                         JS::MutableHandleValue value) {
+    GIArgument garg;
+    g_constant_info_get_value(info, &garg);
+
+    GjsAutoTypeInfo type_info = g_constant_info_get_type(info);
+
+    bool ok = gjs_value_from_g_argument(cx, value, type_info, &garg, true);
+
+    g_constant_info_free_value(info, &garg);
+    return ok;
+}
+
 GJS_JSAPI_RETURN_CONVENTION
 static bool
 gjs_define_constant(JSContext       *context,
@@ -314,28 +328,15 @@ gjs_define_constant(JSContext       *context,
                     GIConstantInfo  *info)
 {
     JS::RootedValue value(context);
-    GArgument garg = { 0, };
-    GITypeInfo *type_info;
     const char *name;
-    bool ret = false;
-
-    type_info = g_constant_info_get_type(info);
-    g_constant_info_get_value(info, &garg);
 
-    if (!gjs_value_from_g_argument(context, &value, type_info, &garg, true))
-        goto out;
+    if (!gjs_value_from_constant_info(context, info, &value))
+        return false;
 
     name = g_base_info_get_name((GIBaseInfo*) info);
 
-    if (JS_DefineProperty(context, in_object,
-                          name, value,
-                          GJS_MODULE_PROP_FLAGS))
-        ret = true;
-
- out:
-    g_constant_info_free_value (info, &garg);
-    g_base_info_unref((GIBaseInfo*) type_info);
-    return ret;
+    return JS_DefineProperty(context, in_object, name, value,
+                             GJS_MODULE_PROP_FLAGS);
 }
 
 #if GJS_VERBOSE_ENABLE_GI_USAGE
diff --git a/gjs/console.cpp b/gjs/console.cpp
index 3f9d9eb2..a42a37a3 100644
--- a/gjs/console.cpp
+++ b/gjs/console.cpp
@@ -186,6 +186,29 @@ check_script_args_for_stray_gjs_args(int           argc,
     g_strfreev(argv_copy);
 }
 
+int define_argv_and_eval_script(GjsContext* js_context, int argc,
+                                char* const* argv, const char* script,
+                                size_t len, const char* filename) {
+    GError* error = nullptr;
+
+    /* prepare command line arguments */
+    if (!gjs_context_define_string_array(
+            js_context, "ARGV", argc, const_cast<const char**>(argv), &error)) {
+        g_critical("Failed to define ARGV: %s", error->message);
+        g_clear_error(&error);
+        return 1;
+    }
+
+    /* evaluate the script */
+    int code;
+    if (!gjs_context_eval(js_context, script, len, filename, &code, &error)) {
+        if (!g_error_matches(error, GJS_ERROR, GJS_ERROR_SYSTEM_EXIT))
+            g_critical("%s\n", error->message);
+        g_clear_error(&error);
+    }
+    return code;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -197,7 +220,7 @@ main(int argc, char **argv)
     const char *filename;
     const char *program_name;
     gsize len;
-    int code, gjs_argc = argc, script_argc, ix;
+    int gjs_argc = argc, script_argc, ix;
     char **argv_copy = g_strdupv(argv), **argv_copy_addr = argv_copy;
     char **gjs_argv, **gjs_argv_addr;
     char * const *script_argv;
@@ -354,31 +377,14 @@ main(int argc, char **argv)
         tracefd = -1;
     }
 
-    /* prepare command line arguments */
-    if (!gjs_context_define_string_array(js_context, "ARGV",
-                                         script_argc, (const char **) script_argv,
-                                         &error)) {
-        code = 1;
-        g_printerr("Failed to defined ARGV: %s", error->message);
-        g_clear_error(&error);
-        goto out;
-    }
-
     /* If we're debugging, set up the debugger. It will break on the first
      * frame. */
     if (debugging)
         gjs_context_setup_debugger_console(js_context);
 
-    /* evaluate the script */
-    if (!gjs_context_eval(js_context, script, len,
-                          filename, &code, &error)) {
-        if (!g_error_matches(error, GJS_ERROR, GJS_ERROR_SYSTEM_EXIT))
-            g_printerr("%s\n", error->message);
-        g_clear_error(&error);
-        goto out;
-    }
+    int code = define_argv_and_eval_script(js_context, script_argc, script_argv,
+                                           script, len, filename);
 
- out:
     g_strfreev(gjs_argv_addr);
 
     /* Probably doesn't make sense to write statistics on failure */
diff --git a/gjs/context-private.h b/gjs/context-private.h
index cb8f9f7a..35625d07 100644
--- a/gjs/context-private.h
+++ b/gjs/context-private.h
@@ -128,10 +128,17 @@ class GjsContextPrivate {
     static gboolean trigger_gc_if_needed(void* data);
     static gboolean drain_job_queue_idle_handler(void* data);
     void warn_about_unhandled_promise_rejections(void);
-    void reset_exit(void) {
-        m_should_exit = false;
-        m_exit_code = 0;
-    }
+
+    class AutoResetExit {
+        GjsContextPrivate* m_self;
+
+     public:
+        explicit AutoResetExit(GjsContextPrivate* self) { m_self = self; }
+        ~AutoResetExit() {
+            m_self->m_should_exit = false;
+            m_self->m_exit_code = 0;
+        }
+    };
 
  public:
     /* Retrieving a GjsContextPrivate from JSContext or GjsContext */
diff --git a/gjs/context.cpp b/gjs/context.cpp
index ce38ebd5..f55d8a44 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -871,7 +871,7 @@ gjs_context_eval(GjsContext   *js_context,
 bool GjsContextPrivate::eval(const char* script, ssize_t script_len,
                              const char* filename, int* exit_status_p,
                              GError** error) {
-    bool ret = false;
+    AutoResetExit reset(this);
 
     bool auto_profile = m_should_profile;
     if (auto_profile &&
@@ -906,7 +906,7 @@ bool GjsContextPrivate::eval(const char* script, ssize_t script_len,
             *exit_status_p = code;
             g_set_error(error, GJS_ERROR, GJS_ERROR_SYSTEM_EXIT,
                         "Exit with code %d", code);
-            goto out;  /* Don't log anything */
+            return false;  // Don't log anything
         }
 
         if (!JS_IsExceptionPending(m_cx)) {
@@ -923,7 +923,7 @@ bool GjsContextPrivate::eval(const char* script, ssize_t script_len,
         gjs_log_exception(m_cx);
         /* No exit code from script, but we don't want to exit(0) */
         *exit_status_p = 1;
-        goto out;
+        return false;
     }
 
     if (exit_status_p) {
@@ -938,11 +938,7 @@ bool GjsContextPrivate::eval(const char* script, ssize_t script_len,
         }
     }
 
-    ret = true;
-
- out:
-    reset_exit();
-    return ret;
+    return true;
 }
 
 bool
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index 300044e6..9c650f27 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -308,16 +308,15 @@ import_module_init(JSContext       *context,
                    GFile           *file,
                    JS::HandleObject module_obj)
 {
-    bool ret = false;
-    char *script = NULL;
-    char *full_path = NULL;
     gsize script_len = 0;
     GError *error = NULL;
 
     GjsContextPrivate* gjs = GjsContextPrivate::from_cx(context);
     JS::RootedValue ignored(context);
 
-    if (!(g_file_load_contents(file, NULL, &script, &script_len, NULL, &error))) {
+    char* script_unowned;
+    if (!(g_file_load_contents(file, nullptr, &script_unowned, &script_len,
+                               nullptr, &error))) {
         if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY) &&
             !g_error_matches(error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY) &&
             !g_error_matches(error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
@@ -325,23 +324,16 @@ import_module_init(JSContext       *context,
         else
             g_error_free(error);
 
-        goto out;
+        return false;
     }
 
+    GjsAutoChar script = script_unowned;
     g_assert(script != NULL);
 
-    full_path = g_file_get_parse_name (file);
-
-    if (!gjs->eval_with_scope(module_obj, script, script_len, full_path,
-                              &ignored))
-        goto out;
-
-    ret = true;
+    GjsAutoChar full_path = g_file_get_parse_name(file);
 
- out:
-    g_free(script);
-    g_free(full_path);
-    return ret;
+    return gjs->eval_with_scope(module_obj, script, script_len, full_path,
+                                &ignored);
 }
 
 GJS_JSAPI_RETURN_CONVENTION
@@ -442,6 +434,22 @@ import_symbol_from_init_js(JSContext       *cx,
     return true;
 }
 
+GJS_JSAPI_RETURN_CONVENTION
+static bool attempt_import(JSContext* cx, JS::HandleObject obj,
+                           JS::HandleId module_id, const char* module_name,
+                           GFile* file) {
+    JS::RootedObject module_obj(
+        cx, gjs_module_import(cx, obj, module_id, module_name, file));
+    if (!module_obj)
+        return false;
+
+    GjsAutoChar full_path = g_file_get_parse_name(file);
+
+    return define_meta_properties(cx, module_obj, full_path, module_name,
+                                  obj) &&
+           seal_import(cx, obj, module_id, module_name);
+}
+
 GJS_JSAPI_RETURN_CONVENTION
 static bool
 import_file_on_module(JSContext       *context,
@@ -450,29 +458,12 @@ import_file_on_module(JSContext       *context,
                       const char      *name,
                       GFile           *file)
 {
-    bool retval = false;
-    char *full_path = NULL;
-
-    JS::RootedObject module_obj(context,
-        gjs_module_import(context, obj, id, name, file));
-    if (!module_obj)
-        goto out;
-
-    full_path = g_file_get_parse_name (file);
-    if (!define_meta_properties(context, module_obj, full_path, name, obj))
-        goto out;
-
-    if (!seal_import(context, obj, id, name))
-        goto out;
-
-    retval = true;
-
- out:
-    if (!retval)
+    if (!attempt_import(context, obj, id, name, file)) {
         cancel_import(context, obj, name);
+        return false;
+    }
 
-    g_free (full_path);
-    return retval;
+    return true;
 }
 
 GJS_JSAPI_RETURN_CONVENTION
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index d76dec55..62d824d0 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -520,31 +520,30 @@ static void
 _linux_get_self_process_size (gulong *vm_size,
                               gulong *rss_size)
 {
-    char *contents;
     char *iter;
     gsize len;
     int i;
 
     *vm_size = *rss_size = 0;
 
-    if (!g_file_get_contents ("/proc/self/stat", &contents, &len, NULL))
+    char* contents_unowned;
+    if (!g_file_get_contents("/proc/self/stat", &contents_unowned, &len,
+                             nullptr))
         return;
 
+    GjsAutoChar contents = contents_unowned;
     iter = contents;
     /* See "man proc" for where this 22 comes from */
     for (i = 0; i < 22; i++) {
         iter = strchr (iter, ' ');
         if (!iter)
-            goto out;
+            return;
         iter++;
     }
     sscanf (iter, " %lu", vm_size);
     iter = strchr (iter, ' ');
     if (iter)
         sscanf (iter, " %lu", rss_size);
-
- out:
-    g_free (contents);
 }
 
 static gulong linux_rss_trigger;


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