GNOME Bugzilla – Bug 698283
this.parent clashes with GtkWidget.parent
Last modified: 2014-02-24 16:02:07 UTC
For example: const MyWidget = new Lang.Class({ Name: 'MyWidget', Extends: Gtk.Grid }); let grid = new Gtk.Grid(); let widget = new MyWidget(); print(widget.parent); Prints: function _parent() { if (!this.__caller__) { throw new TypeError("The method 'parent' cannot be called"); } var caller = this.__caller__; var name = caller._name; var parent = caller._owner.__super__; var previous = parent ? parent.prototype[name] : undefined; if (!previous) { throw new TypeError("The method '" + name + "' is not on the superclass"); } return previous.apply(this, arguments); }
Yes, this is expected, because if you subclass your widget you want to be able to chain-up, and having parent resolve differently based on the scope you're in is not really feasible. So just use widget.get_parent().
Maybe just rename this.parent to this.Parent (with big P) or this.Super, so it won't clash with property naming conventions at all?
I don't think we can do that, at this point: there are too many uses of .parent() meaning the superclass in existing gjs code.
s/this.parent/this.Super/g could help. I think most if not all applications using Gjs still are developed by GNOME developers (because of lack of documentation), maybe there is still a chance to break compatibility? Or maybe make a copy of Lang.Class (Oop.Class?) with fixed API for use in new applications?
Created attachment 241900 [details] [review] Rename this.parent to this.super for API version 2 Patch that renames this.parent to this.Super for API version 2. Depends on API version support in https://bugzilla.gnome.org/show_bug.cgi?id=698360
Really, I don't understand all the noise on this bug. Yes, Gtk.Widget.parent cannot be used, and you need Gtk.Widget.get_parent() So? It's definitely not worth a new major revision of the gjs API (or worse, a copy of the whole lang module). Also, it would cause sed pain on every shell extension out there, like we didn't break API enough for them... If it were for me, this would be wontfix.
I didn't see that in practice, but what if a function is named 'parent'? There's no another alias for it, so it becomes completely inaccessible. Also there are GObject.connect, GObject.disconnect, GObject.connect_after, GObject.emit. They too clash with valid method names (GSocket.connect?) (these deserve another bug). There are lots of other issues like these, I even made a list of them: https://live.gnome.org/NikitaChuraev/GlaringGjsApiIssues I understand that many of the issues listed there are small, insignificant and can be easily worked around (eg. rename GSocket.connect to GSocket._connect or something like this), but combined they contribute to the feeling of clumsiness of Gjs platform. It just doesn't feel right. These are really basic thing: loading from file, adding text to GtkTextView, connecting via a socket. Is that really not possible to fix these issues now? I've heard that Gjs documentation is coming, IDE, lowering the bar significantly for new developers, and then it'll be even harder to fix. Suggestions for both issues: maybe move Lang.Class into Oop.Class or another place and make Lang.Class a simple compatibility shim? It'll break MyClass instanceof Lang.Class, but I don't think anyone does that at this point. function Class(params) { let newClass = new Oop.Class(params); if (newClass.prototype.parent === undefined) newClass.prototype.parent = Oop._super; return newClass; } As for GObject.connect and others, mark them as deprecated without removing them and replace them with external methods (as in C): GObject.connect GObject.connect_after GObject.disconnect GObject.emit
You can use My.Foo.prototype.parent.call(obj, args...); if you have an hypothetical method called "parent". And you can use GObject.Object.prototype.connect.call(...) if .connect is Gio.Socket.prototype.connect. I agree that GObject.signal_connect() / GObject.signal_disconnect() / GObject.signal_emit() are useful, to avoid the long incantation, because .connect() as a method is more likely than .parent(). Easy to do in a backward compatible way with overrides, patch coming.
Created attachment 241931 [details] [review] Allow using GObject.signal_* functions in place of Object methods GObject.Object.connect() and friends might be unavailable because shadowed by another method in the prototype chain (such as g_socket_connect()). In that case, it is nice to use the C equivalents, which are GObject.signal_connect(), GObject.signal_handler_disconnect() and GObject.signal_emit_by_name().
Created attachment 241932 [details] [review] Implement GObject.prototype.disconnect in JS Because GObject.signal_handler_disconnect() is introspectable now.
Both my patches are depending on bug 698382 for g_signal_handler_disconnect().
Uhm... this patches have been waiting for one year, maybe it's time for a review?
Review of attachment 241931 [details] [review]: I don't like this. I'd prefer to see GObject.Object.prototype.connect.call(obj, Lang.bind(...));
Review of attachment 241932 [details] [review]: OK. Is there a reason we can't do the same for connect? The custom value marshalling?
Review of attachment 241900 [details] [review]: No.
(In reply to comment #13) > Review of attachment 241931 [details] [review]: > > I don't like this. I'd prefer to see GObject.Object.prototype.connect.call(obj, > Lang.bind(...)); So we should bind automatically? And to what? (In reply to comment #14) > Review of attachment 241932 [details] [review]: > > OK. Is there a reason we can't do the same for connect? The custom value > marshalling? Yes. Generic GClosure marshalling doesn't use GSignal type information (or GIRepository type information, which we should start using...), so it's less accurate.
(In reply to comment #16) > So we should bind automatically? And to what? What? No, I meant users should call GObject.prototype.connect.call(obj, foo); themselves, just like they need to do for any other "conflicted" method. > (In reply to comment #14) > Yes. Generic GClosure marshalling doesn't use GSignal type information (or > GIRepository type information, which we should start using...), so it's less > accurate. OK. It would be better if we could just do connect(GjsPrivate.create_signal_marshaller(obj, signalName, myFunction)); instead, but I won't budge on it.
(In reply to comment #17) > (In reply to comment #16) > > So we should bind automatically? And to what? > > What? No, I meant users should call GObject.prototype.connect.call(obj, foo); > themselves, just like they need to do for any other "conflicted" method. Well, yes, but "connect" is a fairly common name, and g_signal_connect() is already part of the C API...
I pushed the code cleanup for disconnect(), but I understand we're not going to touch connect() and emit(). Prototypes exists, and people can patch GObject in their apps if they want. Attachment 241932 [details] pushed as 9a54db2 - Implement GObject.prototype.disconnect in JS