Goals and Update

I'm overdue for an update; first semester of my final year of study is finished, and exams are over. Final marks aren't due for a while longer though. So, now i'm able to dedicate a fairly large chunk of time to my GSoC project - investigate the benefits of using Rust in GSJ.


As my project progresses I'm able to identify some possible outcomes and/or goal extensions;

  • a custom mozjs (SpiderMonkey) binding which implements only what is needed
  • using the rust-mozjs binding from the Mozilla Servo project as a base for a possible full rewrite
  • GJS remians as C++, but uses anything learned from the Rusting attempt, eg, use of move semantics via unique_ptr


Any of these outcomes could have benefits, and not just for GJS; as I document my trails and tribulations hopefully this information is useful for others.

The outcome I hope for is to use rust-mozjs bindings to start with and implement some of GJS using this. The bindings provide a nice existing base with much of the hard work already done. The one downside to this (but one that is hopefully small) is that the upstream development of rust-mozjs is happening on the mozjs tip which is at this time, version 55 - not a huge issue but there could be some possible headaches as mozjs gets refactored along the way. The only issues I've had so far is the renaming and namespacing of a few things I found in the downgrade from version 55 to 52, smooth sailing otherwise. GitHub link

There are some downsides to using the rust-mozjs bindings, however; much of the current implementation is unsafe and will require some very diligent checking to ensure that the unsafe blocks don't break Rusts safety guarantees, and it requires the nightly Rust compiler due to the use of feature gated components - that is features in develoment such as NonZero which is a wrapper for raw pointers and is unavilable in stable Rust (this pointer API has also gone through some hefty changes recently and should be stabilized soon).

I would like to skip making a custom mozjs binding if at all possible, but it may be useful to prototype a small set of operations on data structures. I'll probably weigh this against the time required to set up bindgen and utilize it.

And lastly, every adventure is an opportunity to learn. As part of this project I invested in a new book; "Effective Modern C++". So far it's encouraged me to reattempt to grok some parts of C++ I never spent much time with, eg, templates and generics. I like C and C++, they are powerful languages with many applications, but I can never get past C++ feeling like some sort of Dr Seus house. Here is a rather nice blog post that gives a sort of overview of Rust compared to C++, using topics in the previously mentioned book.

NeXT Steps

I now need to work on the bindings for GObject, and learn how Gobject Introspection works, how and what GIR is and how it can be used via Rust.

There are a few projects available already, much of which hasn't been touched in 2years or longer:

  • grust-gen - "Rust code generator for GObject introspection", which as far as I can tell, uses a GIR file to generate Rust bindings to any library for which these are available.
  • gobject-sys - "Rust import crate for GObject ", GObject Rust bindings generated using grust-gen.
  • grust - This one I think is an implementation of grust-gen in Rust; "creates safe Rust bindings from GIR files, as well as generated binding crates for the core GLib, GObject and GIO APIs."

I'm not entirely sure where to go from here. Explanations on what GObject Introspection actually is seem a bit thin on the ground. Is it just a library/program that generates bindings from GIR files? Seriously, if you can offer a good explanation of GObject and Introspection, plus how it all interoperates, please email me.

For example in;

gjs_value_to_g_argument(JSContext      *context,
                        JS::HandleValue value,
                        GITypeInfo     *type_info,
                        const char     *arg_name,
                        GjsArgumentType arg_type,
                        GITransfer      transfer,
                        bool            may_be_null,
                        GArgument      *arg)

what is GITypeInfo really? Is it a layer above GTypeInfo? Is it using the Gobject Introspection library to read GIR info? If you're in the GNOME Foundation, and working on GObject, a great blog post subject would be on the GObject and GI ecosytem + how it all interoperates.

I'm inclined to try using rust-bindgen to generate GObject bindings for Rust, except I'm not sure how to use it from there if something is currently using GI. Consideration must be taken in recognising that Rust is a low-level language, not a secondary layer here - the intention is to replace parts of GJS C++ code with Rust.