crash when destroying a listview with duplicate items
if a listmodel of a listview returns the same object in multiple places, it crashes with a failed assertion when closing the window:
$ flatpak run --socket=wayland --device=dri --command=gjs --filesystem="$(pwd)" org.gnome.Platform//master -m bug2.js
MESA-INTEL: warning: ../src/intel/vulkan/anv_formats.c:763: FINISHME: support YUV colorspace with DRM format modifiers
MESA-INTEL: warning: ../src/intel/vulkan/anv_formats.c:794: FINISHME: support more multi-planar formats with DRM modifiers
(gjs:2): Gjs-CRITICAL **: 23:13:38.823: Attempting to run a JS callback during garbage collection. This is most likely caused by destroying a Clutter actor or GTK widget with ::destroy signal connected, or using the destroy(), dispose(), or remove() vfuncs. Because it would crash the application, it has been blocked.
The offending callback was get_n_items(), a vfunc.
== Stack trace for context 0x558816a71db0 ==
(gjs:2): Gjs-CRITICAL **: 23:13:38.823: Attempting to run a JS callback during garbage collection. This is most likely caused by destroying a Clutter actor or GTK widget with ::destroy signal connected, or using the destroy(), dispose(), or remove() vfuncs. Because it would crash the application, it has been blocked.
The offending callback was get_n_items(), a vfunc.
== Stack trace for context 0x558816a71db0 ==
(gjs:2): Gjs-CRITICAL **: 23:13:38.824: Attempting to run a JS callback during garbage collection. This is most likely caused by destroying a Clutter actor or GTK widget with ::destroy signal connected, or using the destroy(), dispose(), or remove() vfuncs. Because it would crash the application, it has been blocked.
The offending callback was get_n_items(), a vfunc.
== Stack trace for context 0x558816a71db0 ==
(gjs:2): Gjs-CRITICAL **: 23:13:38.824: Attempting to run a JS callback during garbage collection. This is most likely caused by destroying a Clutter actor or GTK widget with ::destroy signal connected, or using the destroy(), dispose(), or remove() vfuncs. Because it would crash the application, it has been blocked.
The offending callback was get_n_items(), a vfunc.
== Stack trace for context 0x558816a71db0 ==
(gjs:2): Gjs-CRITICAL **: 23:13:38.824: Attempting to run a JS callback during garbage collection. This is most likely caused by destroying a Clutter actor or GTK widget with ::destroy signal connected, or using the destroy(), dispose(), or remove() vfuncs. Because it would crash the application, it has been blocked.
The offending callback was get_n_items(), a vfunc.
== Stack trace for context 0x558816a71db0 ==
(gjs:2): Gjs-CRITICAL **: 23:13:38.824: Attempting to run a JS callback during garbage collection. This is most likely caused by destroying a Clutter actor or GTK widget with ::destroy signal connected, or using the destroy(), dispose(), or remove() vfuncs. Because it would crash the application, it has been blocked.
The offending callback was get_n_items(), a vfunc.
== Stack trace for context 0x558816a71db0 ==
(gjs:2): Gjs-CRITICAL **: 23:13:38.824: Attempting to run a JS callback during garbage collection. This is most likely caused by destroying a Clutter actor or GTK widget with ::destroy signal connected, or using the destroy(), dispose(), or remove() vfuncs. Because it would crash the application, it has been blocked.
The offending callback was get_n_items(), a vfunc.
== Stack trace for context 0x558816a71db0 ==
**
Gtk:ERROR:../gtk/gtklistitemmanager.c:1735:gtk_list_item_manager_clear_model: assertion failed: (gtk_rb_tree_get_root (self->items) == NULL)
Bail out! Gtk:ERROR:../gtk/gtklistitemmanager.c:1735:gtk_list_item_manager_clear_model: assertion failed: (gtk_rb_tree_get_root (self->items) == NULL)
$
example code:
import GObject from "gi://GObject";
import Gio from "gi://Gio";
import Gtk from "gi://Gtk?version=4.0";
const ExampleModel = GObject.registerClass({
Implements: [Gio.ListModel],
}, class ExampleModel extends GObject.Object {
item = Gtk.StringObject.new("asdfef");
vfunc_get_item_type() {
return Gtk.StringObject;
}
vfunc_get_n_items() {
return 2;
}
vfunc_get_item(i) {
return i < 2 ? this.item : null;
}
});
const app = new Gtk.Application();
app.connect("activate", (application) => {
const factory = new Gtk.SignalListItemFactory;
factory.connect("bind", (self, item) => item.child = Gtk.Label.new(item.item.string));
new Gtk.ApplicationWindow({
application,
child: Gtk.ListView.new(Gtk.NoSelection.new(new ExampleModel), factory),
}).present();
});
app.run(null);