[gjs: 1/2] arg-cache: Handle notified callbacks without destroy




commit 918ebe4d0df4cd426465521e1e0c2a3ac80a583d
Author: Florian Müllner <fmuellner gnome org>
Date:   Wed Jul 28 21:46:10 2021 +0200

    arg-cache: Handle notified callbacks without destroy
    
    A scope of "notified" means that a callback may be used until a
    corresponding GDestroyNotify callback is called. If there is no
    such destroy callback, then we can assume that the callback should
    remain valid forever.
    
    An example of this are class methods like gtk_widget_class_install_action().

 gi/arg-cache.cpp               |  7 +++++--
 installed-tests/js/testGtk4.js | 20 ++++++++++++++++++++
 2 files changed, 25 insertions(+), 2 deletions(-)
---
diff --git a/gi/arg-cache.cpp b/gi/arg-cache.cpp
index dd46b88a..f4d8136e 100644
--- a/gi/arg-cache.cpp
+++ b/gi/arg-cache.cpp
@@ -325,9 +325,12 @@ static bool gjs_marshal_callback_in(JSContext* cx, GjsArgumentCache* self,
         gjs_arg_set(&state->in_cvalue(closure_pos), trampoline);
     }
 
-    if (trampoline && self->contents.callback.scope == GI_SCOPE_TYPE_ASYNC) {
+    GIScopeType scope = self->contents.callback.scope;
+    bool keep_forever = scope == GI_SCOPE_TYPE_NOTIFIED &&
+                        !self->has_callback_destroy();
+    if (trampoline && (scope == GI_SCOPE_TYPE_ASYNC || keep_forever)) {
         // Add an extra reference that will be cleared when garbage collecting
-        // async calls
+        // async calls or never for notified callbacks without destroy
         g_closure_ref(trampoline);
     }
     gjs_arg_set(arg, closure);
diff --git a/installed-tests/js/testGtk4.js b/installed-tests/js/testGtk4.js
index a8c3ead6..2d458610 100644
--- a/installed-tests/js/testGtk4.js
+++ b/installed-tests/js/testGtk4.js
@@ -112,6 +112,20 @@ const MyComplexGtkSubclassFromFile = GObject.registerClass({
 const SubclassSubclass = GObject.registerClass(
     class SubclassSubclass extends MyComplexGtkSubclass {});
 
+
+const CustomActionWidget = GObject.registerClass(
+class CustomActionWidget extends Gtk.Widget {
+    static _classInit(klass) {
+        klass = Gtk.Widget._classInit(klass);
+
+        Gtk.Widget.install_action.call(klass,
+            'custom.action',
+            null,
+            widget => (widget.action = 42));
+        return klass;
+    }
+});
+
 function validateTemplate(description, ClassName, pending = false) {
     let suite = pending ? xdescribe : describe;
     suite(description, function () {
@@ -181,4 +195,10 @@ describe('Gtk 4 regressions', function () {
     it('Gdk.Event fundamental type should not crash', function () {
         expect(() => new Gdk.Event()).toThrowError(/Couldn't find a constructor/);
     });
+
+    xit('Actions added via Gtk.WidgetClass.add_action() should not crash', function () {
+        const custom = new CustomActionWidget();
+        custom.activate_action('custom.action', null);
+        expect(custom.action).toEqual(42);
+    }).pend('https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/3796');
 });


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