[gjs: 1/5] arg-cache: Use simple boxed marshaller if we're handling a GValue method




commit c20a5168119324d29547eb2013041bbb4a644224
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Fri Oct 9 22:21:20 2020 +0200

    arg-cache: Use simple boxed marshaller if we're handling a GValue method
    
    If our argument is a GValue and it's marked as the instance parameter,
    then it means we're calling a g_value_* function, and as per this we
    should not pass a temporary value but we can just pass the object we've
    initialized locally.

 gi/arg-cache.cpp                       |  4 +-
 installed-tests/js/meson.build         |  1 +
 installed-tests/js/testGObjectValue.js | 77 ++++++++++++++++++++++++++++++++++
 3 files changed, 81 insertions(+), 1 deletion(-)
---
diff --git a/gi/arg-cache.cpp b/gi/arg-cache.cpp
index c053865e..cb5d660d 100644
--- a/gi/arg-cache.cpp
+++ b/gi/arg-cache.cpp
@@ -1363,7 +1363,9 @@ static bool gjs_arg_cache_build_interface_in_arg(JSContext* cx,
             // marshallers know not to copy stuff if we don't need to.
 
             if (gtype == G_TYPE_VALUE) {
-                if (self->transfer == GI_TRANSFER_NOTHING && !is_instance_param)
+                if (self->arg_pos == GjsArgumentCache::INSTANCE_PARAM)
+                    self->marshallers = &boxed_in_marshallers;
+                else if (self->transfer == GI_TRANSFER_NOTHING && !is_instance_param)
                     self->marshallers = &gvalue_in_transfer_none_marshallers;
                 else
                     self->marshallers = &gvalue_in_marshallers;
diff --git a/installed-tests/js/meson.build b/installed-tests/js/meson.build
index bd80555b..3ea141e0 100644
--- a/installed-tests/js/meson.build
+++ b/installed-tests/js/meson.build
@@ -100,6 +100,7 @@ jasmine_tests = [
     'GObject',
     'GObjectClass',
     'GObjectInterface',
+    'GObjectValue',
     'GTypeClass',
     'Importer',
     'Introspection',
diff --git a/installed-tests/js/testGObjectValue.js b/installed-tests/js/testGObjectValue.js
new file mode 100644
index 00000000..4e5d03ce
--- /dev/null
+++ b/installed-tests/js/testGObjectValue.js
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+// SPDX-FileCopyrightText: 2020 Marco Trevisan <marco trevisan canonical com>
+
+const {GLib, GObject} = imports.gi;
+
+GObject.TYPE_SCHAR = GObject.TYPE_CHAR;
+
+const SIGNED_TYPES = ['schar', 'int', 'int64', 'long'];
+const UNSIGNED_TYPES = ['char', 'uchar', 'uint', 'uint64', 'ulong'];
+const FLOATING_TYPES = ['double', 'float'];
+const SPECIFIC_TYPES = ['gtype', 'boolean', 'string', 'variant'];
+const ALL_TYPES = [...SIGNED_TYPES, ...UNSIGNED_TYPES, ...FLOATING_TYPES, ...SPECIFIC_TYPES];
+
+describe('GObject value (GValue)', function () {
+    let v;
+    beforeEach(function () {
+        v = new GObject.Value();
+    });
+
+    function getDefaultContentByType(type) {
+        if (SIGNED_TYPES.includes(type))
+            return -((Math.random() * 100 | 0) + 1);
+        if (UNSIGNED_TYPES.includes(type))
+            return -getDefaultContentByType('int') + 2;
+        if (FLOATING_TYPES.includes(type))
+            return getDefaultContentByType('uint') + 0.5;
+        if (type === 'string')
+            return `Hello GValue! ${getDefaultContentByType('uint')}`;
+        if (type === 'boolean')
+            return !!(getDefaultContentByType('int') % 2);
+        if (type === 'gtype') {
+            const other = ALL_TYPES[Math.random() * ALL_TYPES.length | 0];
+            return GObject[`TYPE_${other.toUpperCase()}`];
+        }
+        if (type === 'variant') {
+            return new GLib.Variant('a{sv}', {
+                pasta: new GLib.Variant('s', 'Carbonara (con guanciale)'),
+                pizza: new GLib.Variant('s', 'Verace'),
+                randomString: new GLib.Variant('s', getDefaultContentByType('string')),
+            });
+        }
+
+        throw new Error(`No default content set for type ${type}`);
+    }
+
+    ALL_TYPES.forEach(type => {
+        const gtype = GObject[`TYPE_${type.toUpperCase()}`];
+        it(`initializes ${type}`, function () {
+            v.init(gtype);
+        });
+
+        it(`${type} is compatible with itself`, function () {
+            expect(GObject.Value.type_compatible(gtype, gtype)).toBeTruthy();
+        });
+
+        it(`${type} is transformable to itself`, function () {
+            expect(GObject.Value.type_transformable(gtype, gtype)).toBeTruthy();
+        });
+
+        describe('initialized', function () {
+            let randomContent;
+            beforeEach(function () {
+                v.init(gtype);
+                randomContent = getDefaultContentByType(type);
+            });
+
+            it(`sets and gets ${type}`, function () {
+                v[`set_${type}`](randomContent);
+                expect(v[`get_${type}`]()).toEqual(randomContent);
+            });
+        });
+    });
+
+    afterEach(function () {
+        v.unset();
+    });
+});


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