diff options
author | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2020-10-09 22:21:20 +0200 |
---|---|---|
committer | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2020-10-14 02:02:35 +0200 |
commit | c20a5168119324d29547eb2013041bbb4a644224 (patch) | |
tree | 99ee4dbceed16203a9b0a917ba403c66be467246 | |
parent | 17217a35238f1001ab2b545b9bddfe4689bf0f38 (diff) | |
download | gjs-c20a5168119324d29547eb2013041bbb4a644224.tar.gz |
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.
-rw-r--r-- | gi/arg-cache.cpp | 4 | ||||
-rw-r--r-- | installed-tests/js/meson.build | 1 | ||||
-rw-r--r-- | installed-tests/js/testGObjectValue.js | 77 |
3 files changed, 81 insertions, 1 deletions
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(); + }); +}); |