[gjs/ewlsh/fix-closures] Test memory handling
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/ewlsh/fix-closures] Test memory handling
- Date: Sat, 15 Jan 2022 23:31:19 +0000 (UTC)
commit 2bbf75fbcf78178a555bffdcbab3a14e07c64d82
Author: Evan Welsh <contact evanwelsh com>
Date: Sat Jan 15 15:30:55 2022 -0800
Test memory handling
gi/closure.h | 42 ++++++++++++++++++++++++++++--------------
gi/object.cpp | 2 +-
gi/private.cpp | 24 ++++++++++++++++++++----
3 files changed, 49 insertions(+), 19 deletions(-)
---
diff --git a/gi/closure.h b/gi/closure.h
index 551939d5..778d856d 100644
--- a/gi/closure.h
+++ b/gi/closure.h
@@ -71,25 +71,14 @@ class Closure : public GClosure {
[[nodiscard]] static Closure* create_marshaled(JSContext* cx,
JSFunction* callable,
- const char* description) {
- auto* self = new Closure(cx, callable, true /* root */, description);
+ const char* description,
+ bool root = true) {
+ auto* self = new Closure(cx, callable, root, description);
self->add_finalize_notifier<Closure>();
g_closure_set_marshal(self, marshal_cb);
return self;
}
- [[nodiscard]] static Closure* create_for_signal(JSContext* cx,
- JSFunction* callable,
- const char* description,
- unsigned signal_id) {
- auto* self = new Closure(cx, callable, false /* root */, description);
- self->add_finalize_notifier<Closure>();
- SignalClosureMeta* meta = new SignalClosureMeta();
- meta->signal_id = signal_id;
- g_closure_set_meta_marshal(self, meta, marshal_cb);
- return self;
- }
-
constexpr JSFunction* callable() const { return m_func; }
[[nodiscard]] constexpr JSContext* context() const { return m_cx; }
[[nodiscard]] constexpr bool is_valid() const { return !!m_cx; }
@@ -111,6 +100,7 @@ class Closure : public GClosure {
m_cx = nullptr;
}
+ protected:
static void marshal_cb(GClosure* closure, GValue* ret, unsigned n_params,
const GValue* params, void* hint, void* data) {
for_gclosure(closure)->marshal(ret, n_params, params, hint, data);
@@ -134,6 +124,30 @@ class Closure : public GClosure {
GjsMaybeOwned<JSFunction*> m_func;
};
+class SignalClosure : public Closure {
+ protected:
+ SignalClosureMeta m_meta;
+
+ SignalClosure(JSContext* cx, JSFunction* func, const char* description,
+ unsigned signal_id)
+ : Closure(cx, func, false, description) {
+ m_meta.signal_id = signal_id;
+
+ g_closure_set_meta_marshal(this, &m_meta, marshal_cb);
+ }
+
+ public:
+ [[nodiscard]] static SignalClosure* create(JSContext* cx,
+ JSFunction* callable,
+ const char* description,
+ unsigned signal_id) {
+ auto* self = new SignalClosure(cx, callable, description, signal_id);
+
+ self->add_finalize_notifier<SignalClosure>();
+ return self;
+ }
+};
+
} // namespace Gjs
#endif // GI_CLOSURE_H_
diff --git a/gi/object.cpp b/gi/object.cpp
index d1880966..80a5acac 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -2141,7 +2141,7 @@ ObjectInstance::connect_impl(JSContext *context,
return false;
}
- GClosure* closure = Gjs::Closure::create_for_signal(
+ GClosure* closure = Gjs::SignalClosure::create(
context, JS_GetObjectFunction(callback), "signal callback", signal_id);
if (closure == NULL)
return false;
diff --git a/gi/private.cpp b/gi/private.cpp
index 1fc13935..c8aac9d0 100644
--- a/gi/private.cpp
+++ b/gi/private.cpp
@@ -278,11 +278,26 @@ static bool gjs_create_closure(JSContext* cx, unsigned argc, JS::Value* vp) {
JS::RootedFunction func(cx, JS_GetObjectFunction(callable));
Gjs::Closure* closure =
- Gjs::Closure::create_marshaled(cx, func, "custom callback");
+ Gjs::Closure::create_marshaled(cx, func, "custom callback", false);
if (closure == nullptr)
return false;
- return gjs_value_from_closure(cx, closure, args.rval());
+ g_closure_ref(closure);
+ g_closure_sink(closure);
+
+ GjsAutoStructInfo info =
+ g_irepository_find_by_gtype(nullptr, G_TYPE_CLOSURE);
+ g_assert(info);
+
+ JS::RootedObject boxed(cx,
+ BoxedInstance::new_for_c_struct(cx, info, closure));
+ g_closure_unref(closure);
+
+ if (!boxed)
+ return false;
+
+ args.rval().setObject(*boxed);
+ return true;
}
GJS_JSAPI_RETURN_CONVENTION
@@ -314,7 +329,7 @@ static bool gjs_create_signal_closure(JSContext* cx, unsigned argc,
JS::RootedFunction func(cx, JS_GetObjectFunction(callable));
- Gjs::Closure* closure = Gjs::Closure::create_for_signal(
+ Gjs::Closure* closure = Gjs::SignalClosure::create(
cx, func, "custom signal callback", signal_id);
if (closure == nullptr)
@@ -376,7 +391,7 @@ static bool gjs_invoke_closure(JSContext* cx, unsigned argc, JS::Value* vp) {
}
if (return_type) {
- GValue return_value = {0};
+ Gjs::AutoGValue return_value;
GType return_gtype;
if (!gjs_gtype_get_actual_gtype(cx, return_type, &return_gtype))
return false;
@@ -387,6 +402,7 @@ static bool gjs_invoke_closure(JSContext* cx, unsigned argc, JS::Value* vp) {
g_value_init(&return_value, return_gtype);
g_closure_invoke(gjs_closure, &return_value, param_values.size(),
param_values.data(), nullptr);
+
return gjs_value_from_g_value(cx, args.rval(), &return_value);
}
g_closure_invoke(gjs_closure, nullptr, param_values.size(),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]