From 8a7566a87a89ba46c38d868f4cdd807568315131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 6 Dec 2017 13:24:28 -0500 Subject: [PATCH 1/3] object: Show error when using proto functions (connect*, emit) on destroyed object We also need to ensure that these proto functions are used properly. --- gi/object.cpp | 21 +++++++++++++ .../js/testGObjectDestructionAccess.js | 30 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/gi/object.cpp b/gi/object.cpp index 64a9a8672..d2aabaa3c 100644 --- a/gi/object.cpp +++ b/gi/object.cpp @@ -1668,6 +1668,16 @@ real_connect_func(JSContext *context, priv->info ? g_base_info_get_name( (GIBaseInfo*) priv->info) : g_type_name(priv->gtype)); return false; } + if (priv->g_object_finalized) { + g_critical("Object %s.%s (%p), has been already deallocated - impossible to connect to signal. " + "This might be caused by the fact that the object has been destroyed from C " + "code using something such as destroy(), dispose(), or remove() vfuncs", + priv->info ? g_base_info_get_namespace( (GIBaseInfo*) priv->info) : "", + priv->info ? g_base_info_get_name( (GIBaseInfo*) priv->info) : g_type_name(priv->gtype), + priv->gobj); + gjs_dumpstack(); + return true; + } if (argc != 2 || !argv[0].isString() || !JS::IsCallable(&argv[1].toObject())) { gjs_throw(context, "connect() takes two args, the signal name and the callback"); @@ -1751,6 +1761,17 @@ emit_func(JSContext *context, return false; } + if (priv->g_object_finalized) { + g_critical("Object %s.%s (%p), has been already deallocated - impossible to emit signal. " + "This might be caused by the fact that the object has been destroyed from C " + "code using something such as destroy(), dispose(), or remove() vfuncs", + priv->info ? g_base_info_get_namespace( (GIBaseInfo*) priv->info) : "", + priv->info ? g_base_info_get_name( (GIBaseInfo*) priv->info) : g_type_name(priv->gtype), + priv->gobj); + gjs_dumpstack(); + return true; + } + if (argc < 1 || !argv[0].isString()) { gjs_throw(context, "emit() first arg is the signal name"); return false; diff --git a/installed-tests/js/testGObjectDestructionAccess.js b/installed-tests/js/testGObjectDestructionAccess.js index 3e30e6e48..22c01b0f0 100644 --- a/installed-tests/js/testGObjectDestructionAccess.js +++ b/installed-tests/js/testGObjectDestructionAccess.js @@ -55,4 +55,34 @@ describe('Access to destroyed GObject', () => { GLib.test_assert_expected_messages_internal('Gjs', 'testGObjectDestructionAccess.js', 0, 'testExceptionInDestroyedObjectMethodSet'); }); + + it('Proto function connect', () => { + GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_CRITICAL, + 'Object Gtk.Window (0x*'); + + destroyedWindow.connect('foo-signal', () => {}); + + GLib.test_assert_expected_messages_internal('Gjs', 'testGObjectDestructionAccess.js', 0, + 'testExceptionInDestroyedObjectConnect'); + }); + + it('Proto function connect_after', () => { + GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_CRITICAL, + 'Object Gtk.Window (0x*'); + + destroyedWindow.connect_after('foo-signal', () => {}); + + GLib.test_assert_expected_messages_internal('Gjs', 'testGObjectDestructionAccess.js', 0, + 'testExceptionInDestroyedObjectConnectAfter'); + }); + + it('Proto function emit', () => { + GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_CRITICAL, + 'Object Gtk.Window (0x*'); + + destroyedWindow.emit('foo-signal'); + + GLib.test_assert_expected_messages_internal('Gjs', 'testGObjectDestructionAccess.js', 0, + 'testExceptionInDestroyedObjectEmit'); + }); }); -- GitLab From 29cd1f2eb6ce2cea219d63a4e952d728a78f3b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 6 Dec 2017 13:26:50 -0500 Subject: [PATCH 2/3] object: make clear in toString() proto method when the object is finalized --- gi/object.cpp | 4 +++- .../js/testGObjectDestructionAccess.js | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/gi/object.cpp b/gi/object.cpp index d2aabaa3c..a0fc16a97 100644 --- a/gi/object.cpp +++ b/gi/object.cpp @@ -1862,7 +1862,9 @@ to_string_func(JSContext *context, return false; /* wrong class passed in */ } - return _gjs_proxy_to_string_func(context, obj, "object", + return _gjs_proxy_to_string_func(context, obj, + (priv->g_object_finalized) ? + "object (FINALIZED)" : "object", (GIBaseInfo*)priv->info, priv->gtype, priv->gobj, rec.rval()); } diff --git a/installed-tests/js/testGObjectDestructionAccess.js b/installed-tests/js/testGObjectDestructionAccess.js index 22c01b0f0..e479ff9ab 100644 --- a/installed-tests/js/testGObjectDestructionAccess.js +++ b/installed-tests/js/testGObjectDestructionAccess.js @@ -85,4 +85,21 @@ describe('Access to destroyed GObject', () => { GLib.test_assert_expected_messages_internal('Gjs', 'testGObjectDestructionAccess.js', 0, 'testExceptionInDestroyedObjectEmit'); }); + + it('Proto function toString', () => { + expect(destroyedWindow.toString()).toMatch( + /\[object \(FINALIZED\) instance proxy GIName:Gtk.Window jsobj@0x[a-f0-9]+ native@0x[a-f0-9]+\]/); + }); + + it('Porto function toString before/after', () => { + var validWindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL}); + + expect(validWindow.toString()).toMatch( + /\[object instance proxy GIName:Gtk.Window jsobj@0x[a-f0-9]+ native@0x[a-f0-9]+\]/); + + validWindow.destroy(); + + expect(validWindow.toString()).toMatch( + /\[object \(FINALIZED\) instance proxy GIName:Gtk.Window jsobj@0x[a-f0-9]+ native@0x[a-f0-9]+\]/); + }); }); -- GitLab From e49dbabae1b964464259e90df8bbb2ac1ddc8dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 7 Dec 2017 14:07:30 -0500 Subject: [PATCH 3/3] proxyutils: remove trailing spaces --- gi/proxyutils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gi/proxyutils.cpp b/gi/proxyutils.cpp index 3894ec838..d90aa4d01 100644 --- a/gi/proxyutils.cpp +++ b/gi/proxyutils.cpp @@ -63,7 +63,7 @@ _gjs_proxy_to_string_func(JSContext *context, g_string_append_printf(buf, " jsobj@%p", this_obj); if (native_address != NULL) g_string_append_printf(buf, " native@%p", native_address); - + g_string_append_c(buf, ']'); if (!gjs_string_from_utf8(context, buf->str, rval)) -- GitLab