[gjs: 1/2] object: Use g_object_new_with_properties()



commit dfbb2329b7ce33dd857aa44612da189b1cba005b
Author: Philip Chimento <philip chimento gmail com>
Date:   Mon Jun 4 00:08:18 2018 -0700

    object: Use g_object_new_with_properties()
    
    g_object_newv() is deprecated, and we had deprecation guards around it in
    order to silence the deprecation warning. Since we're going to refactor
    this code, it's probably time to fix this.
    
    We get rid of the awkward clear() function by moving it into the
    destructor of an AutoGValueVector class.
    
    GLib dependency is now 2.54.
    
    Closes: #104

 configure.ac  |  2 +-
 gi/object.cpp | 59 ++++++++++++++++++++++++++---------------------------------
 2 files changed, 27 insertions(+), 34 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index d65bb8cf..37aacc67 100644
--- a/configure.ac
+++ b/configure.ac
@@ -59,7 +59,7 @@ AX_VALGRIND_DFLT([sgcheck], [off])
 AX_VALGRIND_CHECK
 
 # Checks for libraries.
-m4_define(glib_required_version, 2.50.0)
+m4_define(glib_required_version, 2.54.0)
 
 GOBJECT_INTROSPECTION_REQUIRE([1.41.4])
 
diff --git a/gi/object.cpp b/gi/object.cpp
index 1cd86e23..25b54f6d 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -115,6 +115,13 @@ class GjsListLink {
     }
 };
 
+struct AutoGValueVector : public std::vector<GValue> {
+    ~AutoGValueVector() {
+        for (GValue value : *this)
+            g_value_unset(&value);
+    }
+};
+
 using ParamRef = std::unique_ptr<GParamSpec, decltype(&g_param_spec_unref)>;
 using PropertyCache = JS::GCHashMap<JS::Heap<JSString *>, ParamRef,
                                     js::DefaultHasher<JSString *>,
@@ -1030,17 +1037,15 @@ object_instance_resolve(JSContext       *context,
     return true;
 }
 
-/* Set properties from args to constructor (argv[0] is supposed to be
- * a hash)
- * The GParameter elements in the passed-in vector must be unset by the caller,
- * regardless of the return value of this function.
- */
+/* Set properties from args to constructor (args[0] is supposed to be
+ * a hash) */
 static bool
 object_instance_props_to_g_parameters(JSContext                  *context,
                                       JSObject                   *obj,
                                       const JS::HandleValueArray& args,
                                       ObjectInstance             *proto_priv,
-                                      std::vector<GParameter>&    gparams)
+                                      std::vector<const char *>  *names,
+                                      AutoGValueVector           *values)
 {
     size_t ix, length;
 
@@ -1062,8 +1067,7 @@ object_instance_props_to_g_parameters(JSContext                  *context,
     }
 
     for (ix = 0, length = ids.length(); ix < length; ix++) {
-        GjsAutoJSChar name;
-        GParameter gparam = { NULL, { 0, }};
+        GValue gvalue = G_VALUE_INIT;
 
         /* ids[ix] is reachable because props is rooted, but require_property
          * doesn't know that */
@@ -1092,14 +1096,14 @@ object_instance_props_to_g_parameters(JSContext                  *context,
                                                    param_spec->name);
             /* prevent setting the prop even in JS */
 
-        gparam.name = param_spec->name;
-        g_value_init(&gparam.value, G_PARAM_SPEC_VALUE_TYPE(param_spec));
-        if (!gjs_value_to_g_value(context, value, &gparam.value)) {
-            g_value_unset(&gparam.value);
+        g_value_init(&gvalue, G_PARAM_SPEC_VALUE_TYPE(param_spec));
+        if (!gjs_value_to_g_value(context, value, &gvalue)) {
+            g_value_unset(&gvalue);
             return false;
         }
 
-        gparams.push_back(gparam);
+        names->push_back(param_spec->name);  /* owned by GParamSpec in cache */
+        values->push_back(gvalue);
     }
 
     return true;
@@ -1563,13 +1567,6 @@ disassociate_js_gobject(ObjectInstance *priv)
     priv->keep_alive = nullptr;
 }
 
-static void
-clear_g_params(std::vector<GParameter>& params)
-{
-    for (GParameter param : params)
-        g_value_unset(&param.value);
-}
-
 static bool
 object_instance_init (JSContext                  *context,
                       JS::MutableHandleObject     object,
@@ -1577,21 +1574,19 @@ object_instance_init (JSContext                  *context,
 {
     ObjectInstance *priv;
     GType gtype;
-    std::vector<GParameter> params;
     GTypeQuery query;
-    GObject *gobj;
 
     priv = (ObjectInstance *) JS_GetPrivate(object);
 
     gtype = priv->gtype;
     g_assert(gtype != G_TYPE_NONE);
 
+    std::vector<const char *> names;
+    AutoGValueVector values;
     if (!object_instance_props_to_g_parameters(context, object, args,
                                                proto_priv_from_js(context, object),
-                                               params)) {
-        clear_g_params(params);
+                                               &names, &values))
         return false;
-    }
 
     /* Mark this object in the construction stack, it
        will be popped in gjs_object_custom_init() later
@@ -1601,17 +1596,15 @@ object_instance_init (JSContext                  *context,
         object_init_list.emplace(context, object);
     }
 
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-    gobj = (GObject*) g_object_newv(gtype, params.size(), params.data());
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-    clear_g_params(params);
+    g_assert(names.size() == values.size());
+    GObject *gobj = g_object_new_with_properties(gtype, values.size(),
+                                                 names.data(), values.data());
 
     ObjectInstance *other_priv = get_object_qdata(gobj);
     if (other_priv && other_priv->keep_alive != object.get()) {
-        /* g_object_newv returned an object that's already tracked by a JS
-         * object. Let's assume this is a singleton like IBus.IBus and return
-         * the existing JS wrapper object.
+        /* g_object_new_with_properties() returned an object that's already
+         * tracked by a JS object. Let's assume this is a singleton like
+         * IBus.IBus and return the existing JS wrapper object.
          *
          * 'object' has a value that was originally created by
          * JS_NewObjectForConstructor in GJS_NATIVE_CONSTRUCTOR_PRELUDE, but


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