[gjs/wip/carlosg/arrays-in-signals] WIP: [RFC] value: Introspect element-type in arrays




commit af4edd99dffafbec4ea7bddc7b75bc4b27312908
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Feb 15 23:51:53 2021 +0100

    WIP: [RFC] value: Introspect element-type in arrays
    
    A few things have to combine ATM here:
    - Of all compound types, it has to be an array
    - Of all element-types it has to be a struct/union/boxed
    
    It will succeed then, fail otherwise.
    
    Fixes: https://gitlab.gnome.org/GNOME/gjs/-/issues/377

 gi/value.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 57 insertions(+), 2 deletions(-)
---
diff --git a/gi/value.cpp b/gi/value.cpp
index 26a679f3..4f648e07 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -11,6 +11,7 @@
 #include <glib-object.h>
 #include <glib.h>
 
+#include <js/Array.h>
 #include <js/CharacterEncoding.h>
 #include <js/Conversions.h>
 #include <js/GCVector.h>  // for RootedVector
@@ -840,10 +841,64 @@ gjs_value_from_g_value_internal(JSContext             *context,
             gjs_throw(context, "Failed to convert strv to array");
             return false;
         }
+    } else if (g_type_is_a(gtype, G_TYPE_PTR_ARRAY)) {
+        GIArgInfo *arg_info;
+        GISignalInfo *signal_info;
+        GITypeInfo type_info;
+
+        signal_info = get_signal_info_if_available(signal_query);
+        if (!signal_info) {
+            gjs_throw(context, "Unknown signal.");
+            return false;
+        }
+
+        /* Look for element-type */
+        arg_info = g_callable_info_get_arg(signal_info, arg_n - 1);
+        g_arg_info_load_type(arg_info, &type_info);
+
+        GITypeInfo *element_info = g_type_info_get_param_type (&type_info, 0);
+        GjsAutoBaseInfo interface_info =
+            g_type_info_get_interface(element_info);
+        GType gtype;
+
+        guint i;
+        JS::RootedValueVector elems(context);
+        GPtrArray *ptr_array = (GPtrArray*) g_value_get_boxed (gvalue);
+
+        for (i = 0; i < ptr_array->len; i++) {
+            if (!elems.growBy(1)) {
+                JS_ReportOutOfMemory(context);
+                return false;
+            }
+
+            gtype = g_registered_type_info_get_g_type(interface_info);
+
+            if (g_base_info_get_type(interface_info) == GI_INFO_TYPE_STRUCT ||
+                g_base_info_get_type(interface_info) == GI_INFO_TYPE_UNION ||
+                g_base_info_get_type(interface_info) == GI_INFO_TYPE_BOXED) {
+                GjsAutoBaseInfo info = g_irepository_find_by_gtype(nullptr, gtype);
+                JSObject *obj;
+
+                obj = BoxedInstance::new_for_c_struct(context, info, g_ptr_array_index (ptr_array, i));
+                if (!obj)
+                    return false;
+                elems[i].setObject(*obj);
+            } else {
+                gjs_throw(context,
+                          "Unable to introspect non-boxed array");
+                return false;
+            }
+        }
+
+        JS::RootedObject obj(context, JS::NewArrayObject(context, elems));
+        if (!obj)
+            return false;
+
+        value_p.setObject(*obj);
+        return true;
     } else if (g_type_is_a(gtype, G_TYPE_HASH_TABLE) ||
                g_type_is_a(gtype, G_TYPE_ARRAY) ||
-               g_type_is_a(gtype, G_TYPE_BYTE_ARRAY) ||
-               g_type_is_a(gtype, G_TYPE_PTR_ARRAY)) {
+               g_type_is_a(gtype, G_TYPE_BYTE_ARRAY)) {
         gjs_throw(context,
                   "Unable to introspect element-type of container in GValue");
         return false;


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