[gjs] Value: add Gjs::AutoGValue and use this to handle lifetime of GValues
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] Value: add Gjs::AutoGValue and use this to handle lifetime of GValues
- Date: Wed, 19 May 2021 05:12:30 +0000 (UTC)
commit e6950f8d6a1336d02aa348aa1391bf3db6924110
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Fri May 14 18:06:01 2021 +0200
Value: add Gjs::AutoGValue and use this to handle lifetime of GValues
Add a simple structure that wraps GValue that allows us handling
lifetime of GValue's in a nicer way and redefine AutoGValueVector
with it transparently.
In this way the allocated data keeps being structured as GValues but we
handle its initializations without errors.
gi/arg-cache.cpp | 3 +--
gi/arg.cpp | 3 +--
gi/object.cpp | 24 ++++++------------------
gi/object.h | 8 +-------
gi/value.cpp | 4 +---
gi/value.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 60 insertions(+), 32 deletions(-)
---
diff --git a/gi/arg-cache.cpp b/gi/arg-cache.cpp
index 53064b36..dfc76557 100644
--- a/gi/arg-cache.cpp
+++ b/gi/arg-cache.cpp
@@ -568,14 +568,13 @@ static bool gjs_marshal_gvalue_in_in(JSContext* cx, GjsArgumentCache*,
}
}
- GValue gvalue = G_VALUE_INIT;
+ Gjs::AutoGValue gvalue;
if (!gjs_value_to_g_value(cx, value, &gvalue))
return false;
gjs_arg_set(arg, g_boxed_copy(G_TYPE_VALUE, &gvalue));
- g_value_unset(&gvalue);
return true;
}
diff --git a/gi/arg.cpp b/gi/arg.cpp
index 85edfc4d..2a82b07b 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -1221,14 +1221,13 @@ static bool value_to_interface_gi_argument(
return true;
}
- GValue gvalue = G_VALUE_INIT;
+ Gjs::AutoGValue gvalue;
if (!gjs_value_to_g_value(cx, value, &gvalue)) {
gjs_arg_unset<void*>(arg);
return false;
}
gjs_arg_set(arg, g_boxed_copy(G_TYPE_VALUE, &gvalue));
- g_value_unset(&gvalue);
return true;
} else if (arg::is_gdk_atom(interface_info)) {
diff --git a/gi/object.cpp b/gi/object.cpp
index 5e27c64b..5eeb651a 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -367,8 +367,6 @@ bool ObjectInstance::prop_getter_impl(JSContext* cx, JS::HandleString name,
return true;
}
- GValue gvalue = { 0, };
-
ObjectPrototype* proto_priv = get_prototype();
GParamSpec *param = proto_priv->find_param_spec_from_id(cx, name);
@@ -388,15 +386,10 @@ bool ObjectInstance::prop_getter_impl(JSContext* cx, JS::HandleString name,
gjs_debug_jsprop(GJS_DEBUG_GOBJECT, "Accessing GObject property %s",
param->name);
- g_value_init(&gvalue, G_PARAM_SPEC_VALUE_TYPE(param));
+ Gjs::AutoGValue gvalue(G_PARAM_SPEC_VALUE_TYPE(param));
g_object_get_property(m_ptr, param->name, &gvalue);
- if (!gjs_value_from_g_value(cx, rval, &gvalue)) {
- g_value_unset(&gvalue);
- return false;
- }
- g_value_unset(&gvalue);
- return true;
+ return gjs_value_from_g_value(cx, rval, &gvalue);
}
[[nodiscard]] static GjsAutoFieldInfo lookup_field_info(GIObjectInfo* info,
@@ -531,15 +524,11 @@ bool ObjectInstance::prop_setter_impl(JSContext* cx, JS::HandleString name,
gjs_debug_jsprop(GJS_DEBUG_GOBJECT, "Setting GObject prop %s",
param_spec->name);
- GValue gvalue = G_VALUE_INIT;
- g_value_init(&gvalue, G_PARAM_SPEC_VALUE_TYPE(param_spec));
- if (!gjs_value_to_g_value(cx, value, &gvalue)) {
- g_value_unset(&gvalue);
+ Gjs::AutoGValue gvalue(G_PARAM_SPEC_VALUE_TYPE(param_spec));
+ if (!gjs_value_to_g_value(cx, value, &gvalue))
return false;
- }
g_object_set_property(m_ptr, param_spec->name, &gvalue);
- g_value_unset(&gvalue);
return true;
}
@@ -1097,9 +1086,8 @@ bool ObjectPrototype::props_to_g_parameters(JSContext* context,
param_spec->name);
/* prevent setting the prop even in JS */
- GValue& gvalue = values->emplace_back();
- gvalue = G_VALUE_INIT;
- g_value_init(&gvalue, G_PARAM_SPEC_VALUE_TYPE(param_spec));
+ Gjs::AutoGValue& gvalue =
+ values->emplace_back(G_PARAM_SPEC_VALUE_TYPE(param_spec));
if (!gjs_value_to_g_value(context, value, &gvalue))
return false;
diff --git a/gi/object.h b/gi/object.h
index 980aff4a..1d5403bd 100644
--- a/gi/object.h
+++ b/gi/object.h
@@ -27,6 +27,7 @@
#include <mozilla/HashFunctions.h> // for HashGeneric, HashNumber
#include <mozilla/Likely.h> // for MOZ_LIKELY
+#include "gi/value.h"
#include "gi/wrapperutils.h"
#include "gjs/jsapi-util-root.h"
#include "gjs/jsapi-util.h"
@@ -63,13 +64,6 @@ class GjsListLink {
[[nodiscard]] size_t size() const;
};
-struct AutoGValueVector : public std::vector<GValue> {
- ~AutoGValueVector() {
- for (GValue value : *this)
- g_value_unset(&value);
- }
-};
-
/*
* ObjectBase:
*
diff --git a/gi/value.cpp b/gi/value.cpp
index f2f3bfc0..df427464 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -539,8 +539,6 @@ gjs_value_to_g_value_internal(JSContext *context,
/* special case GValue */
if (g_type_is_a(gtype, G_TYPE_VALUE)) {
- GValue nested_gvalue = G_VALUE_INIT;
-
/* explicitly handle values that are already GValues
to avoid infinite recursion */
if (value.isObject()) {
@@ -557,11 +555,11 @@ gjs_value_to_g_value_internal(JSContext *context,
}
}
+ Gjs::AutoGValue nested_gvalue;
if (!gjs_value_to_g_value(context, value, &nested_gvalue))
return false;
g_value_set_boxed(gvalue, &nested_gvalue);
- g_value_unset(&nested_gvalue);
return true;
}
diff --git a/gi/value.h b/gi/value.h
index 611cfb1a..8d05ee67 100644
--- a/gi/value.h
+++ b/gi/value.h
@@ -7,12 +7,62 @@
#include <config.h>
+#include <utility> // for move, swap
+#include <vector> // for vector
+
#include <glib-object.h>
#include <js/TypeDecls.h>
#include "gjs/macros.h"
+namespace Gjs {
+struct AutoGValue : GValue {
+ AutoGValue() {
+ static_assert(sizeof(AutoGValue) == sizeof(GValue));
+ *static_cast<GValue*>(this) = G_VALUE_INIT;
+ }
+ explicit AutoGValue(GType gtype) : AutoGValue() {
+ g_value_init(this, gtype);
+ }
+ AutoGValue(AutoGValue const& src) : AutoGValue(G_VALUE_TYPE(&src)) {
+ g_value_copy(&src, this);
+ }
+ AutoGValue& operator=(AutoGValue other) {
+ // We need to cast to GValue here not to make swap to recurse here
+ std::swap(*static_cast<GValue*>(this), *static_cast<GValue*>(&other));
+ return *this;
+ }
+ AutoGValue(AutoGValue&& src) {
+ switch (G_VALUE_TYPE(&src)) {
+ case G_TYPE_NONE:
+ case G_TYPE_CHAR:
+ case G_TYPE_UCHAR:
+ case G_TYPE_BOOLEAN:
+ case G_TYPE_INT:
+ case G_TYPE_UINT:
+ case G_TYPE_LONG:
+ case G_TYPE_ULONG:
+ case G_TYPE_INT64:
+ case G_TYPE_UINT64:
+ case G_TYPE_FLOAT:
+ case G_TYPE_DOUBLE:
+ *static_cast<GValue*>(this) =
+ std::move(static_cast<GValue const&&>(src));
+ break;
+ default:
+ // We can't safely move in complex cases, so let's just copy
+ *static_cast<GValue*>(this) = G_VALUE_INIT;
+ *this = src;
+ g_value_unset(&src);
+ }
+ }
+ ~AutoGValue() { g_value_unset(this); }
+};
+} // namespace Gjs
+
+using AutoGValueVector = std::vector<Gjs::AutoGValue>;
+
GJS_JSAPI_RETURN_CONVENTION
bool gjs_value_to_g_value (JSContext *context,
JS::HandleValue value,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]