[gjs/ewlsh/fix-int64-conversion: 11/11] gi: Convert GJS values to 64-bit GValue integers




commit 9f68b106d5cb500c52a9c394fa0ce54e8c2f4341
Author: Evan Welsh <contact evanwelsh com>
Date:   Wed Aug 25 01:28:15 2021 -0700

    gi: Convert GJS values to 64-bit GValue integers
    
    Previously we relied on g_value_type_transformable to transform JS
    numbers to uint64 and int64 values, this coerced the values into
    ints and broke setting values larger than GLib.MAXINT32 during
    construction.
    
    Fixes #92

 gi/value.cpp                           | 17 ++++++++++++++++-
 installed-tests/js/testGObjectClass.js | 31 +++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 1 deletion(-)
---
diff --git a/gi/value.cpp b/gi/value.cpp
index ec64f0ac..4ba2160d 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -423,6 +423,13 @@ gjs_value_to_g_value_internal(JSContext      *context,
         } else {
             return throw_expect_type(context, value, "integer");
         }
+    } else if (gtype == G_TYPE_INT64) {
+        gint64 i;
+        if (Gjs::js_value_to_c(context, value, &i)) {
+            g_value_set_int64(gvalue, i);
+        } else {
+            return throw_expect_type(context, value, "64-bit integer");
+        }
     } else if (gtype == G_TYPE_DOUBLE) {
         gdouble d;
         if (Gjs::js_value_to_c(context, value, &d)) {
@@ -446,10 +453,18 @@ gjs_value_to_g_value_internal(JSContext      *context,
         } else {
             return throw_expect_type(context, value, "unsigned integer");
         }
+    } else if (gtype == G_TYPE_UINT64) {
+        guint64 i;
+        if (Gjs::js_value_to_c(context, value, &i)) {
+            g_value_set_uint64(gvalue, i);
+        } else {
+            return throw_expect_type(context, value, "unsigned 64-bit integer");
+        }
     } else if (gtype == G_TYPE_BOOLEAN) {
         /* JS::ToBoolean() can't fail */
         g_value_set_boolean(gvalue, JS::ToBoolean(value));
-    } else if (g_type_is_a(gtype, G_TYPE_OBJECT) || g_type_is_a(gtype, G_TYPE_INTERFACE)) {
+    } else if (g_type_is_a(gtype, G_TYPE_OBJECT) ||
+               g_type_is_a(gtype, G_TYPE_INTERFACE)) {
         GObject *gobj;
 
         gobj = NULL;
diff --git a/installed-tests/js/testGObjectClass.js b/installed-tests/js/testGObjectClass.js
index 4b611aed..0b46d417 100644
--- a/installed-tests/js/testGObjectClass.js
+++ b/installed-tests/js/testGObjectClass.js
@@ -1293,3 +1293,34 @@ describe('GObject class with JSObject signals', function () {
     });
 });
 
+describe('GObject class with int64 properties', function () {
+    const MyInt64Class = GObject.registerClass(class MyInt64Class extends GObject.Object {
+        static [GObject.properties] = {
+            'int64': GObject.ParamSpec.int64('int64', 'int64', 'int64',
+                GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE | GObject.ParamFlags.CONSTRUCT,
+                // GLib.MAXINT64 exceeds JS' ability to safely represent an integer
+                GLib.MININT32 * 2, GLib.MAXINT32 * 2, 0),
+        };
+    });
+
+    it('can set an int64 property', function () {
+        const instance = new MyInt64Class({
+            int64: GLib.MAXINT32,
+        });
+
+        expect(instance.int64).toBe(GLib.MAXINT32);
+
+        instance.int64 = GLib.MAXINT32 + 1;
+
+        expect(instance.int64).toBe(GLib.MAXINT32 + 1);
+    });
+
+
+    it('can construct with int64 property', function () {
+        const instance = new MyInt64Class({
+            int64: GLib.MAXINT32 + 1,
+        });
+
+        expect(instance.int64).toBe(GLib.MAXINT32 + 1);
+    });
+});


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