Open romgrk opened 6 years ago
Hey, this repo is being developed by myself and a few others. Progress is slow but I think there's been great progress since I forked from creationix/node-gir
Before I decided to fork node-gir I gave WebReflection/node-gtk
a spin. I remember it was unable to compile and I had limited knowledge of V8 and GI at the time. I ended up building off node-gir for a variety of reasons, mostly, I could understand the code more easily. I'm sure most of that has changed with the work you've put into your fork in the mean time.
I think the reason for so many node<->gi libs on NPM is because people fork the earlier attempts to dive in only to realize GIR is tricky and lacks docs. Most of the npm packages out there are abandoned. I'd love to focus efforts to avoid this!
Currently, i'm pretty happy with what we've got going in node-gir. How do you feel about node-gtk in comparison to the code base here?
Well I regret to not have given more time to investigate before continuing working on node-gtk (had already worked on it 2 years ago), I recently pushed a lot to get things working.
Node-gir codebase seems more organised, and more C++-y (not sure if it's a good thing, but it looks cleaner usually). Node-gtk has all the functions under the same namespace, although each file's purpose is clearly defined.
For the rest, node-gtk codebase seems more advanced from what I can see. The original author (Jasper St-Pierre) did an excellent job laying out how things would be linked together. Memory management is excellent. Here is a few things that I haven't seen when searching this code base:
Object->SetAlignedPointerInInternalField
as a mean to attach an arbitrary pointer to a JS object. In conjunction with Persistent<Object>->SetWeak
, you can free resources when a JS object is GC'ed.gobject_set_qdata
as a mean to attach an arbitrary pointer to a GObject
. In conjunction with g_object_add_toggle_ref
which calls a notify function when there is a single ref left, you can free the Persistent<Object>
if the resources are not needed anymore. (see https://github.com/romgrk/node-gtk/blob/master/src/gobject.cc#L108-L116 to get a sense of how this works)From the points on the README:
Conversion between a v8 value and a GValue/GArgument is veeeery buggy (but everything needs it so most things are buggy)
: Got everything working recently (C Arrays, GArrays, GList, GHashTable, ...). Even if we don't merge, feel free to steal code from GIArgumentToV8 and FreeGIArgument, good chunks of it were copied from PyGObject anyway.Structs and boxed types are still being implemented
: Those are working well on node-gtk (again, using Object->SetAlignedPointerInInternalField
). There are some adjustments to make for Unions; they are usable, but the API is rough (like a direct .__proto__
set... :/ ).out arguments are currently buggy.
: got OUT
and INOUT
arguments working recently (god these were hard!)Interface methods are inherited
: node-gtk doesn't do anything with interfaces yet. Haven't understood yet how these are used by the GLib framework.Support for signals using .connect('signal', callback)
: we got this also, but under a more NodeJS-y API: https://github.com/romgrk/node-gtk/blob/master/lib/index.js#L46-L94 (I'd encourage you to steal it as well)I think the reason for so many node<->gi libs on NPM is because people fork the earlier attempts to dive in only to realize GIR is tricky and lacks docs. Most of the npm packages out there are abandoned. I'd love to focus efforts to avoid this!
So true! GIR docs are often a pain in the ass. The many times I've found myself stuck on some tricky aspect, the most efficient way to solve it would be to go on Gnome's IRC #introspection channel and ask for guidance. When you can get some, it's usually good.
Would you mind commenting on how you feel about your own codebase compared to node-gtk?
Last thing, even if we continue developping both projects in parallel, don't hesitate to ping me on github issues if you need help. I've spent sooooo many time understanding GIR, I'd be happy to share what I've learnt :) (and not feel that I've wasted my life, LOL!)
I have had a little look at node-gtk and it looks very clean.
Memory management is excellent This is great to hear, it's something node-gir has trouble with.
I probably need to update the README in node-gir, we've actually got support for structs and boxed types now for example.
feel free to steal code from GIArgumentToV8 and FreeGIArgument
The type conversion code from node-gtk
looks much neater than node-gir
. I've found there are 100 million edge cases in GI for this and it shows in the code bases for all GI bindings, I almost don't believe node-gtk
works haha! but if it does then that's very impressive!
good chunks of it were copied from PyGObject anyway
this could be a show stopper for me. PyGObject is LGPL licensed currently. This license (for right or wrong reasons) worries many companies/developers who are less familiar with open source licenses. I feel strongly that node-gir
should be and remain MIT or Apache licensed. Copying code from an LGPL codebase would mean the licenses are incompatible.
signals using .connect('signal', callback): we got this also, but under a more NodeJS-y API
I had this debate early on when forking node-gir
. It didn't really support signals originally. I went with the API that I did to closely match gjs
(and maybe seed, can't remember). I would very much like to add a gjs
compat mode to node-gir
including a runtime polyfill for all the gjs
specific APIs to help users port (maybe without change) their gjs
code to node-gir
. As a result, the only real difference i'm consciously making is camelCase
naming in node-gir
instead of the snake_case
ing that gjs
uses, hopefully the compat mode would just change the naming convention. This is also inline with the language binding development best practices that GNOME include in their docs.
node-gir
and a imagine node-gtk
is designed to be a low level library to offer pure bindings to nodejs land with all the imperfections that come with it. Library authors can then build the nice abstractions on top.
I'm keen to hear some of your ideas for the long term goals of node-gtk
. I think we'll likely share many and differ on some. Perhaps we should setup a call?
Good point about the license. Node-gtk was originally under LGPL, but Jasper changed the license for MIT (which I also prefer). There were already chunks of code that clearly originated from PyGObject (identical comments) when I forked, so I guessed wrongly it was ok to keep copying code from there. I'll definitely look into it, there's not so much to do to remove PyGObject code.
I had this debate early on when forking node-gir. It didn't really support signals originally. I went with the API that I did to closely match gjs
We also have the API that matches gjs
, the NodeJS-y .on()/.off()
is built on top of it, to follow binding guidelines. Also, I must say that compatibility with gjs
was never a goal for me, but now that you mention it it's true that it could be nice to have it.
I'm very bad with calls, and english isn't my native language so I still struggle to compose sentences on the fly. If you'd like to chat on hangouts my email is cm9tZ3JrLmNjQGdtYWlsLmNvbQ== (base64), let me know when you'd be available!
I'd be happy to share what I've learnt :) (and not feel that I've wasted my life, LOL!)
While I lack knowledge in anything GIR or low level NodeJS, I think your knowledge would be greatly appreciated in updating the documentation in the GNOME wikis.
I wish there was more I could do than just sit on my hands and watch the project follow through, but I am very much looking forward to this getting more mature, as the current solution to integrate NodeJS libraries into GJS / GNOME apps is rather... hacky.
I can only 👀 over the project and get hyped!
@SolarLiner, if you are interested in learning GIR and low-level NodeJS, I have some really great resources I can share that have helped me out a ton.
@romgrk and @Place1, is node-gtk or node-gir more stable? And which repo should we focus on?
I'm not sure. I would say node-gtk, but I'm obviously biased here. Here are some observations:
node-gir is easier to understand, but certain implementation details are not optimal. E.g. the fact there is no memory management for objects, combined with the fact that linking a GObject with a JSObject is done through a for-loop that iterates all existing objects (O(n)) means the longer an application runs, the less efficient it becomes. (node-gtk is O(1) for retrieving a JS object from a GObject, or the opposite also)
Overall, node-gir also tends to implement it's own mechanisms instead of using native GLib mechanisms. E.g. to link a FunctionTemplate to a GType, it implements its own PersistentObjectStore
, where GLib already offers g_type_set_qdata/g_type_get_qdata.
node-gtk was designed from the start with memory management concerns in mind. It uses V8's weak references to dispose resources when JS objects are GC'ed, and uses GObject toggle-notify callbacks to dispose of unused JSObjects. node-gtk also already has support for OUT and INOUT arguments, and supports more types (container data structures: Arrays, GList, GSList, GHashTable). node-gtk doesn't support methods on interfaces, but node-gir does. Overall, understanding node-gtk requires more knowledge of V8 and GLib internals. The bus factor of node-gtk is probably 1 (2 counting the original author, but he doesn't have time to work on it anymore).
Note that the above observations are done with all due respect to node-gir maintainers, and frankly most credit for node-gtk goes to the original author of it, I've been merely patching the missing holes.
The comments on node-gir are mostly accurate and I agree, although most of these are easily fixed. For example it'd be fairly easy to improve GObject lookup via a map or the GLib features which you mentioned - no need to do any large re-structuring of the codebase.
Supporting more types such as Arrays, GList, etc, is just a matter of implementing them. Considering you've done this in node-gtk I assume it'd be quite easy for node-gir to just pull that code in. Similarly, OUT and INOUT arguments could be modeled after node-gtk.
The memory management of node-gtk (from what you've said) does sound better than node-gir. It's definitely something that is slowly being improved but I don't think the comment
there is no memory management for objects Is completely accurate. All node-gir requires is a destructor implementation for the
Nan::ObjectWrap
object and struct wrappers to free the wrapped object. It's not a large change and probably doesn't warrent the enphasis it received in your comment. But I do agree that it's not done :smile:
All in all, I'd like some time to explore both codebases more and make the afore mentioned changes. node-gir is somewhat of a pet project of mine so I don't particularly want to just up and abandon it. I'm sure @romgrk feels the same way about node-gtk :smile:
@romgrk does node-gtk support the entire Glib ecosystem?
node-gir is somewhat of a pet project of mine so I don't particularly want to just up and abandon it. I'm sure @romgrk feels the same way about node-gtk 
Thats exactly my feeling about node-gtk! It's been my learning project for C++ so I'm quite attached to it. :) (tbh, I had already had the feeling that it would be one reason that could prevent the merge)
The comments @Place1 made about the improvements are also accurate, from what I've seen no large re-structuring should be required. node-gir is in a good state, and some parts of node-gtk can be ported into node-gir. (Maybe not the OUT/INOUT arguments though, node-gtk uses libffi instead of g_function_info_invoke/g_callable_info_invoke)
@romgrk does node-gtk support the entire Glib ecosystem?
node-gtk is more advanced overall, but is still missing some parts, namely: interface methods, vfunc methods and the signal callbacks don't use GIR annotations currently, we just use the passed arguments as-is, which means some arguments are not exactly what they should be.
E.g. widget.on('key-press-event', (widget, event) => { /* event is of type GdkEvent, but it should be GdkEventKey, so the user needs to adjust the prototype to use the event */ })
.
All types supported by GLib are implemented, but the implementation is recent and there's likely edge cases that aren't handled yet. I've been building the test suite but it's not complete enough to confidently say "we support everything".
Those are things that I hope to implement soon, I'm trying to get a usable 1.0 out.
(wow, I just thought about this. You know what this whole node-gtk vs node-gir reminds me of? The seed vs gjs fight :P)
Yeah, well seed and GJS will soon become irrelevant :)
Despite not working on Linux / GTK+ professionally anymore, I can also help answer any GIR questions you might have.
Hey! I'm the maintainer of https://github.com/romgrk/node-gtk (I've recently taken over the npm
node-gtk
package, which was originally owned by WebReflection/node-gtk). So I stumbled upon this fork of node-gir and I was wondering, what is the state of this? I've been suprised by the number of node<->Gtk bindings package on NPM, and I'm wondering if there isn't a way to focus our efforts into bringing high-quality bindings by combining our efforts. Let me know what you think.