From 9f68b106d5cb500c52a9c394fa0ce54e8c2f4341 Mon Sep 17 00:00:00 2001 From: Evan Welsh Date: Wed, 25 Aug 2021 01:28:15 -0700 Subject: 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); + }); +}); -- cgit v1.2.1