Glaring GJS API issues
GNOME has a made JavaScript the preferred programming language for new applications. However, there are some glaring API issues that make Gjs confusing, and bad for normal PEOPLE who value their time. This is the list of the issues I've encountered, roughly sorted by how much I think it will deter normal PEOPLE who value their time from GNOME platform.
This is kind of my personal list, but feel free to edit and comment.
No XML
There's no XML parser besides E4X that's deprecated and going to be removed from SpiderMonkey.
Some properties registered by Gjs clash with perfectly legit property names
The most glaring example is this.parent clash with GtkWidget.parent: Bug 698283. Other ones I found are:
GObject.connect GObject.connect_after GObject.disconnect GObject.emit
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); }
Easier GObject integration
Signals? Properties? GObject names? class_init?
Impossible to create a TreeIter from JavaScript
It's impossible to create custom Gtk.TreeIter from JS (no constructor), so you can't implement a completely custom Gtk.TreeModel in JavaScript.
GtkTreeIter is a simple C structure:
struct GtkTreeIter { gint stamp; gpointer user_data; gpointer user_data2; gpointer user_data3; };
Usage:
int foo(void) { GtkTreeIter iter; get_iter_of_something (&iter); do_something_with_iter (&iter); /* iter is no longer needed, C frees its memory automatically, but it's impossible to make it call a custom function, as C doesn't have C++'s destructors, that's why we can't put references to JavaScript objects into them */ }
Although it's impossible to receive notification when a GtkTreeIter goes out of scope as C has no destructors, I think stamp is enough. JavaScript code will have to maintain an array to map from stamps to actual objects, eg.
_init: function() { this.parent(...); this._items = []; }, getTreeIterOfItem: function(itemStamp) { if (this._items[itemStamp] === undefined) return undefined; return new Gtk.TreeIter(itemStamp); }, getItemByTreeIter: function(iter) { return this._items[iter.stamp]; }
Useless string length arguments
For example, Gtk.TextBuffer.set_text(text, length). Length argument is useless, since JavaScript uses UTF-16 and length expects length of a UTF-8 string.
Binary data uses ByteArray instead of Uint8Array
For example, GFile.load_contents. Uint8Array is now officially recommended.
Useless "success" boolean
Some functions return useless "success" boolean: for example [success, contents, etag_out] = GFile.load_contents(). When C g_file_load_contents returns false, it also sets a GError, so in Gjs the function will always return true (if the C function returns false, an exception is thrown in JavaScript).
The GObject Introspection developers have already introduced "(skip)" mark for such return values, but they won't add it to existing API to avoid backwards incompatibility.
Misc thoughts
- DanWinship on the mailing lists suggested to create an imports.gnome object that behaves like import.gi, but imports fixed, new API while leaving imports.gi intact, preserving compatiability. This won't help to fix the issue with this.parent though.