[gjs/gnome-40: 3/30] fundamental: Support converting an empty GValue to a null fundamental




commit 7b0267841ac2a0a228b0bcd21aee0d37d8c5d172
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Fri Apr 9 07:46:21 2021 +0200

    fundamental: Support converting an empty GValue to a null fundamental
    
    An empty GValue of a valid gtype can be safely marshalled to a null
    fundamental pointer, but we did not support this.
    
    Added test
    
    (cherry-picked from commit commit 6580339f)

 gi/fundamental.cpp                    | 29 +++++++++++++++++++----------
 gi/fundamental.h                      |  5 +++--
 gi/value.cpp                          | 10 +++++-----
 installed-tests/js/testFundamental.js | 10 ++++++++++
 4 files changed, 37 insertions(+), 17 deletions(-)
---
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index e443dc7a..41c2fd3a 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -437,22 +437,31 @@ FundamentalPrototype* FundamentalPrototype::for_gtype(JSContext* cx,
     return FundamentalPrototype::for_js(cx, proto);
 }
 
-JSObject* FundamentalInstance::object_for_gvalue(JSContext* cx,
-                                                 const GValue* value,
-                                                 GType gtype) {
+bool FundamentalInstance::object_for_gvalue(
+    JSContext* cx, const GValue* value, GType gtype,
+    JS::MutableHandleObject object_out) {
     auto* proto_priv = FundamentalPrototype::for_gtype(cx, gtype);
-    void* fobj;
+    void* fobj = nullptr;
+
     if (!proto_priv->call_get_value_function(value, &fobj)) {
-        if (G_VALUE_HOLDS(value, gtype) && g_value_fits_pointer(value)) {
-            return FundamentalInstance::object_for_c_ptr(
-                cx, g_value_peek_pointer(value));
+        if (!G_VALUE_HOLDS(value, gtype) || !g_value_fits_pointer(value)) {
+            gjs_throw(cx,
+                      "Failed to convert GValue of type %s to a fundamental %s "
+                      "instance",
+                      G_VALUE_TYPE_NAME(value), g_type_name(gtype));
+            return false;
         }
 
-        gjs_throw(cx, "Failed to convert GValue to a fundamental instance");
-        return nullptr;
+        fobj = g_value_peek_pointer(value);
+    }
+
+    if (!fobj) {
+        object_out.set(nullptr);
+        return true;
     }
 
-    return FundamentalInstance::object_for_c_ptr(cx, fobj);
+    object_out.set(FundamentalInstance::object_for_c_ptr(cx, fobj));
+    return object_out.get() != nullptr;
 }
 
 bool FundamentalBase::to_gvalue(JSContext* cx, JS::HandleObject obj,
diff --git a/gi/fundamental.h b/gi/fundamental.h
index 927f11af..7d2f8de0 100644
--- a/gi/fundamental.h
+++ b/gi/fundamental.h
@@ -173,8 +173,9 @@ class FundamentalInstance
     GJS_JSAPI_RETURN_CONVENTION
     static JSObject* object_for_c_ptr(JSContext* cx, void* gfundamental);
     GJS_JSAPI_RETURN_CONVENTION
-    static JSObject* object_for_gvalue(JSContext* cx, const GValue* gvalue,
-                                       GType gtype);
+    static bool object_for_gvalue(JSContext* cx, const GValue* gvalue,
+                                  GType gtype,
+                                  JS::MutableHandleObject object_out);
 
     static void* copy_ptr(JSContext* cx, GType gtype, void* gfundamental);
 };
diff --git a/gi/value.cpp b/gi/value.cpp
index fea7f9da..5447dc96 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -1018,12 +1018,12 @@ gjs_value_from_g_value_internal(JSContext             *context,
     } else if (G_TYPE_IS_INSTANTIATABLE(gtype)) {
         /* The gtype is none of the above, it should be a custom
            fundamental type. */
-        JSObject* obj =
-            FundamentalInstance::object_for_gvalue(context, gvalue, gtype);
-        if (obj == NULL)
+        JS::RootedObject obj(context);
+        if (!FundamentalInstance::object_for_gvalue(context, gvalue, gtype,
+                                                    &obj))
             return false;
-        else
-            value_p.setObject(*obj);
+
+        value_p.setObjectOrNull(obj);
     } else {
         gjs_throw(context,
                   "Don't know how to convert GType %s to JavaScript object",
diff --git a/installed-tests/js/testFundamental.js b/installed-tests/js/testFundamental.js
index 3274cf6c..8093773c 100644
--- a/installed-tests/js/testFundamental.js
+++ b/installed-tests/js/testFundamental.js
@@ -47,4 +47,14 @@ describe('Fundamental type support', function () {
         expect(() => obj.emit('test-fundamental-value-funcs', fund)).toThrowError(
             /conversion to a GValue/);
     }).pend('https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/268');
+
+    it('can marshal to a null value', function () {
+        const v = new GObject.Value();
+        expect(v.init(Regress.TestFundamentalObject.$gtype)).toBeNull();
+    });
+
+    it('can marshal to a null value if has no getter function', function () {
+        const v = new GObject.Value();
+        expect(v.init(Regress.TestFundamentalObjectNoGetSetFunc.$gtype)).toBeNull();
+    }).pend('https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/268');
 });


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