[gjs] Support marshalling arguments that are GVariants



commit 6dca0dde9c2d3a0dfc7b353cf6ad118d6cc48b26
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Tue Mar 29 18:05:25 2011 +0200

    Support marshalling arguments that are GVariants
    
    Initial GVariant support, includes only obtaining a GVariant from
    a method that returns one and passing it around mantaining a correct
    reference count.
    Has some basic unit tests, will add more alongside the JS convenience
    layer.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=622344

 gi/arg.c                       |    5 +++++
 gi/boxed.c                     |   25 ++++++++++++++++++++-----
 gi/value.c                     |   25 +++++++++++++++++++++++--
 test/js/testEverythingBasic.js |   22 ++++++++++++++++++++++
 4 files changed, 70 insertions(+), 7 deletions(-)
---
diff --git a/gi/arg.c b/gi/arg.c
index 0205266..667a177 100644
--- a/gi/arg.c
+++ b/gi/arg.c
@@ -1154,6 +1154,8 @@ gjs_value_to_g_argument(JSContext      *context,
                     if (transfer != GI_TRANSFER_NOTHING) {
                         if (g_type_is_a(gtype, G_TYPE_BOXED))
                             arg->v_pointer = g_boxed_copy (gtype, arg->v_pointer);
+                        else if (g_type_is_a(gtype, G_TYPE_VARIANT))
+                            g_variant_ref (arg->v_pointer);
                         else {
                             gjs_throw(context,
                                       "Can't transfer ownership of a structure type not registered as boxed");
@@ -2519,6 +2521,9 @@ gjs_g_arg_release_internal(JSContext  *context,
             } else if (g_type_is_a(gtype, G_TYPE_BOXED)) {
                 if (transfer != TRANSFER_IN_NOTHING)
                     g_boxed_free(gtype, arg->v_pointer);
+            } else if (g_type_is_a(gtype, G_TYPE_VARIANT)) {
+                if (transfer != TRANSFER_IN_NOTHING)
+                    g_variant_unref (arg->v_pointer);
             } else if (gtype == G_TYPE_NONE) {
                 if (transfer != TRANSFER_IN_NOTHING) {
                     gjs_throw(context, "Don't know how to release GArgument: not an object or boxed type");
diff --git a/gi/boxed.c b/gi/boxed.c
index 11297e9..53a68f8 100644
--- a/gi/boxed.c
+++ b/gi/boxed.c
@@ -503,19 +503,27 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
 
         if (unthreadsafe_template_for_constructor.gboxed == NULL) {
             Boxed *source_priv;
+            GType gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
 
             /* Short-circuit copy-construction in the case where we can use g_boxed_copy */
             if (argc == 1 &&
                 boxed_get_copy_source(context, priv, argv[0], &source_priv)) {
 
-                GType gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
-                if (gtype != G_TYPE_NONE) {
+                if (gtype != G_TYPE_NONE && g_type_is_a (gtype, G_TYPE_BOXED)) {
                     priv->gboxed = g_boxed_copy(gtype, source_priv->gboxed);
                     GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
                     return JS_TRUE;
                 }
             }
 
+            /* Short-circuit construction for GVariants (simply cannot construct here,
+               the constructor should be overridden) */
+            if (g_type_is_a(gtype, G_TYPE_VARIANT)) {
+                gjs_throw(context,
+                          "Can't create instance of GVariant directly, use GVariant.new_*");
+                return JS_FALSE;
+            }
+
             if (!boxed_new(context, object, priv))
                 return JS_FALSE;
 
@@ -548,9 +556,11 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
             GType gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
             JSBool retval;
             
-            if (gtype != G_TYPE_NONE) {
+            if (gtype != G_TYPE_NONE && g_type_is_a (gtype, G_TYPE_BOXED)) {
                 priv->gboxed = g_boxed_copy(gtype,
                                             unthreadsafe_template_for_constructor.gboxed);
+            } else if (g_type_is_a(gtype, G_TYPE_VARIANT)) {
+                priv->gboxed = g_variant_ref_sink (unthreadsafe_template_for_constructor.gboxed);
             } else if (priv->can_allocate_directly) {
                 if (!boxed_new_direct(context, object, priv))
                     return JS_FALSE;
@@ -597,7 +607,12 @@ boxed_finalize(JSContext *context,
             GType gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
             g_assert(gtype != G_TYPE_NONE);
 
-            g_boxed_free(gtype,  priv->gboxed);
+            if (g_type_is_a (gtype, G_TYPE_BOXED))
+                g_boxed_free (gtype,  priv->gboxed);
+            else if (g_type_is_a (gtype, G_TYPE_VARIANT))
+                g_variant_unref (priv->gboxed);
+            else
+                g_assert_not_reached ();
         }
 
         priv->gboxed = NULL;
@@ -1020,7 +1035,7 @@ gjs_lookup_boxed_constructor(JSContext    *context,
 
 JSObject*
 gjs_lookup_boxed_prototype(JSContext    *context,
-                              GIBoxedInfo  *info)
+                           GIBoxedInfo  *info)
 {
     JSObject *ns;
     JSObject *proto;
diff --git a/gi/value.c b/gi/value.c
index 28b8d3d..2de1401 100644
--- a/gi/value.c
+++ b/gi/value.c
@@ -403,6 +403,23 @@ gjs_value_to_g_value_internal(JSContext    *context,
             g_value_set_static_boxed(gvalue, gboxed);
         else
             g_value_set_boxed(gvalue, gboxed);
+    } else if (g_type_is_a(gtype, G_TYPE_VARIANT)) {
+        GVariant *variant = NULL;
+
+        if (JSVAL_IS_NULL(value)) {
+            /* nothing to do */
+        } else if (JSVAL_IS_OBJECT(value)) {
+            JSObject *obj = JSVAL_TO_OBJECT(value);
+            variant = gjs_c_struct_from_boxed(context, obj);
+        } else {
+            gjs_throw(context,
+                      "Wrong type %s; boxed type %s expected",
+                      gjs_get_type_name(value),
+                      g_type_name(gtype));
+            return JS_FALSE;
+        }
+
+        g_value_set_variant (gvalue, variant);
     } else if (g_type_is_a(gtype, G_TYPE_ENUM)) {
         gint64 value_int64;
 
@@ -627,13 +644,17 @@ gjs_value_from_g_value_internal(JSContext    *context,
         gjs_throw(context,
                   "Unable to introspect element-type of container in GValue");
         return JS_FALSE;
-    } else if (g_type_is_a(gtype, G_TYPE_BOXED)) {
+    } else if (g_type_is_a(gtype, G_TYPE_BOXED) ||
+               g_type_is_a(gtype, G_TYPE_VARIANT)) {
         GjsBoxedCreationFlags boxed_flags;
         GIBaseInfo *info;
         void *gboxed;
         JSObject *obj;
 
-        gboxed = g_value_get_boxed(gvalue);
+        if (g_type_is_a(gtype, G_TYPE_BOXED))
+            gboxed = g_value_get_boxed(gvalue);
+        else
+            gboxed = g_value_get_variant(gvalue);
         boxed_flags = GJS_BOXED_CREATION_NONE;
 
         /* The only way to differentiate unions and structs is from
diff --git a/test/js/testEverythingBasic.js b/test/js/testEverythingBasic.js
index f74e4f6..264b216 100644
--- a/test/js/testEverythingBasic.js
+++ b/test/js/testEverythingBasic.js
@@ -7,6 +7,7 @@ if (!('assertEquals' in this)) { /* allow running this test standalone */
 }
 
 // We use Gio to have some objects that we know exist
+const GLib = imports.gi.GLib;
 const Gio = imports.gi.Gio;
 const Lang = imports.lang;
 
@@ -462,4 +463,25 @@ function testStrvInGValue() {
     assertEquals(v[2], "three");
 }
 
+function testVariant() {
+    // Cannot access the variant contents, for now
+    let ivar = Everything.test_gvariant_i();
+    assertEquals('i', ivar.get_type_string());
+    assertTrue(ivar.equal(GLib.Variant.new_int32(1)));
+
+    let svar = Everything.test_gvariant_s();
+    assertEquals('s', String.fromCharCode(svar.classify()));
+    assertEquals('one', svar.get_string()[0]);
+
+    let asvvar = Everything.test_gvariant_asv();
+    assertEquals(2, asvvar.n_children());
+
+    let asvar = Everything.test_gvariant_as();
+    let as = asvar.get_strv();
+    assertEquals('one', as[0]);
+    assertEquals('two', as[1]);
+    assertEquals('three', as[2]);
+    assertEquals(3, as.length);
+}
+
 gjstestRun();



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