[gjs/ewlsh/fix-closures] Test memory handling




commit 77ea2bddf21154d737e678b1309f09249e6d59bc
Author: Evan Welsh <contact evanwelsh com>
Date:   Sat Jan 15 15:27:59 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]