The GJS documentation is back

Aside

We have once again a set of accurate, up-to-date documentation for GJS. Find it at devdocs.baznga.org!

Many thanks are due to Everaldo Canuto, Patrick Griffis, and Dustin Falgout for helping get the website back online, and to Nuveo for sponsoring the hosting.

In addition, thanks to Patrick’s lead, we have a docker image if you want to run the documentation site yourself.

If you find any inaccuracies in the documentation, please report a bug at this issue tracker.

GJS: What’s next?

In my last post, I went into detail about all the new stuff that GJS brought to GNOME 3.24. Now, it’s time to talk about the near future: what GJS will bring to GNOME 3.26.

Javascript engine

The highest priority is to keep upgrading the Javascript engine. At the time of writing, I’ve got SpiderMonkey 45 almost, but not quite, working, and Mozilla is on the verge of releasing the standalone version of SpiderMonkey 52. If we can get there, then we’ll finally be on a supported release which means we can have a closer collaboration with the Mozilla team. (During the past six months, they’ve been patient with me asking questions about old, unsupported releases, but it’s not fair to ask them to continue doing that.)

I plan to upgrade to 45 but not merge it, and then immediately continue upgrading to 52 on the same branch, then merge it all in at the same time. That way, we won’t have an interregnum where everyone has to build SpiderMonkey 45 in JHBuild and Continuous and the Flatpak SDK. Subscribe to bug 781429 and its offshoots if you want to follow along.

The main language features that this will bring in are: classes (45) and ES7 async/await statements (52). At that point, the only major ES6 feature that we will still be missing is modules.

ES6 Classes

After that is done, I will refactor GJS’s class system (Lang.Class and GObject.Class). I believe this needs to be done before GNOME 3.26. That’s because in SpiderMonkey 45, we gain ES6 classes, and I want to avoid the situation where we have two competing, and possibly incompatible, ways to write classes.

ES6 Modules

Full ES6 module support is still missing in SpiderMonkey 52, but at least some parts of it are implemented. I’ll need to investigate if it’s possible to enable them in GJS already. Although, we will definitely not enable them yet if there’s no way to keep the existing modules working; we don’t want to break everyone’s code.

Developer tools

Next comes a debugger. There are not one, not two, but three existing implementations of a GJS debugger sitting unattended in Bugzilla or a Git branch. None of them will apply to the codebase as is, so my task will be to fix them up, evaluate the merits of each one, and hopefully come up with one patchset to rule them all.

Christian Hergert is planning to add a profiler, so that you can profile your Javascript code with Sysprof, inside Builder.

Documentation

I would very much like to get the GJS documentation browser back online. I hosted it on EC2, but I have run out of free hosting. If you have a server where it can be parked, let me know! (It’s a web app, not static pages, so I can’t just put it on GitHub Pages.) If you want to run the web app locally yourself, you can find instructions here for how I set it up on EC2, on a RHEL 7 box.

Misc.

All that is probably more than I’ll have time for, but here are some of the things that I’d like to get done after that:

  • Update the tutorials on developer.gnome.org to use more modern GJS
  • Better integration with Builder
  • Use structured logging to clean up the “debug topics” mechanism
  • Reduce the list of unreviewed patches in Bugzilla down to 0
  • Find ways to bring in some of the conveniences that Node developers are used to

Chun-wei Fan is working on converting some of the codebase to use C++ smart pointers so that we get the memory leak safety advantages of g_autoptr without losing portability to MSVC.

Build system

The question is inevitable: are we going to switch the build system to Meson? I’m looking forward to it, but no, not until Meson is more mature and some of the open questions about distribution and autobuilding have been answered.

Help!

I think it’s great that once I started contributing, other people soon started contributing too. The 1.48.0 release had way more patches and contributors than 1.46.0, even if you don’t count all the stale patches that I souped up. GNOME’s #javascript IRC channel is starting to be a lively place, compared to how deserted it was last year.

What I’d most like to encourage is for more people to contribute major features so that the above list doesn’t read like a to-do list that’s mostly for me. I’m happy to provide guidance. I think it would be great for GJS to become a more competitive development language for apps using the GNOME technology stack1 and we won’t get there with just me.

Another way you can help is by using the development version of GJS while developing your apps or GNOME Shell, thereby helping to try out the new features. We had some serious bugs up to, or even past, the last minute in GNOME 3.24, and this seems like the best way to prevent that.

Finally, you can help by sharing your experiences with GJS: good and bad. Talk on the mailing list or IRC, or file a bug on bugzilla.gnome.org if there’s something wrong.


[1] In that regard I’d love to prove wrong Michael Catanzaro’s opinion about using GJS: “there’s no way to change the reality that JavaScript is a terrible language. It has close to zero redeeming features, and many confusing ones.” There is a way! In my opinion ES6 and ES7 have gone a long way towards filling in those potholes. To name just a few, arrow functions mean you can almost always stop caring about the pitfall of what this refers to, and the prospect of doing asynchronous I/O with Promises instead of callbacks actually makes me want to use JS. Of course, in-browser JS is still a terrible language because it has to support the lowest common denominator of Javascripts so that people who haven’t upgraded their browser since Internet Explorer 8 can still visit your website, and that’s why modern web developers preprocess and transpile it to high heaven. But we don’t have to care about all those browser users!

Javascript news from GNOME 3.24

Welcome back to the latest news on GJS, the Javascript engine that powers GNOME Shell, Endless OS, Polari, GNOME Documents, and many other apps.

GNOME 3.24 has been released for about three weeks now, and with it went GJS 1.48.0. Here’s what’s new!

Javascript upgrade!

First of all, we have a more modern Javascript engine. GJS is based on Mozilla’s SpiderMonkey, the same Javascript engine that runs in the Firefox browser. Back in GNOME 3.22, GJS was based on version 24, which was released in September 2013. Now we’ve moved to version 38, which although still old, was released almost two years later in May 2015.

(The number of each SpiderMonkey release increases by 7 each time, because they make a standalone SpiderMonkey release for each Extended Support Release of Firefox, which is one out of every 7. That’s why you might also hear them referred to as “ESR 38”, etc.)

This brings a lot of new Javascript language features with it. Here are some of the ones I’m most excited about.

Promises

Promises allow you to do asynchronous operations (like reading files, or waiting, or fetching things from the network) in a much more intuitive way. With Promises, the code reads from top to bottom as if it were synchronous, instead of from nested level to nested level (often called “callback hell“.)

Here’s an example, a Promises version of examples/gio-cat.js that’s included in GJS’s source distribution:

This is much longer than the original program, but only the lower part of the program is actually the equivalent of the old callback-based code. The top part would ideally be provided by GJS itself. I’m still figuring out what is the best API for wrapPromise but it’s definitely a candidate for including in a future version of GJS.

This code calls loadContents, prints the contents, and exits the main loop. If an exception is thrown anywhere in the chain before .catch, then the function provided to the catch call will log the error message. In any case, no matter whether the operation succeeded or not, the last then call will make sure the main loop exits.

Template literals

Template literals will change your life if you work with text in your GJS program. They are regular strings in backticks, with interpolation. Say goodbye to this:

const Format = imports.format;
String.prototype.format = Format.format;
log("%s, %s!".format(greeting, name));

Also say goodbye to this:

log(greeting + ", " + name + "!");

Instead, from now on you’ll do this:

log(`${greeting}, ${name}!`);

It’s a lot more readable and intuitive.

Template literals can also cover more than one line, and they do real interpolation of expressions too, not just variable names:

const CSS = `
label {
    font-size: ${fontdesc.get_size()};
}`;

You can also “tag” templates which is out of scope of this blog post, but there is one built-in tag which serves the same purpose as r'' string literals do in Python:

String.raw`I'm writing some \LaTeX\ code here
and I \textbf{don't} want to deal with escaping it:
\[ E = mc^2 \]`

Generators

Generators are a great addition to the Javascript toolbox. They were actually already available in GJS, but only in Mozilla’s nonstandard extension form. They are introduced with the function* keyword instead of function, and they work a lot like Python’s generators. Here’s an example, implementing the xrange() function similar to the one in Python using a generator:

function* xrange(limit) {
    for(let count = 0; count < limit; count++)
        yield count;
}

The yield statement returns control back to the caller, while preserving the state of the generator until the next call. You can get all the values one by one, calling a generator’s next() method, but for...of loops will also deal with generators:

for (let ix of xrange(5))
    print(`Counting from 0 to 4: ${ix}`);

If you want to empty a generator into an array, you can also use the spread operator: [...xrange(5)] will give you an array of numbers from 0 to 4.

Here’s a more complicated example showing the yield* statement which allows you to compose more than one generator:

This code prints looks at the directory that it’s given, and prints all the files in it that are not themselves directories (the “leaf nodes”.) If one of the files is a directory, it will descend into that directory and repeat the process, thanks to yield*.

Want to know more?

Since there’s a lot more than I can cover in a comfortably readable blog post, I made a slide deck. I tried to put it together in such a way that you can use it as reference material.

For more information on all of these cool things, I highly recommend this “ES6 Explained” series of posts from the Mozilla Hacks blog. Some of these features, such as classes and modules, are still to come in GJS.

Maintainer life

The Javascript engine upgrade was the major feature, but I also spent some time on making things easier for myself as the maintainer. A well-tended garden will hopefully attract more gardeners. Happily, some other people joined in for this part.

I cleaned up the build system, using more modern and concise Autotools code. I also spent some time cleaning up compiler warnings, both on GCC and Clang. Now the build and test runs are faster, and the cleaner output makes it much easier to see when something goes wrong. I also made sure that GJS builds on macOS, or at least it did until my Apple hardware broke down. Chun-wei Fan made some improvements that ensure GJS builds on Windows with MSVC. Claudio André implemented continuous integration in a Docker container, with the intention to run it on Travis CI, but sadly we do not have permission to flip the bit to get Travis to build it.

Having written Jasmine GJS in order to bring some of that convenient unit testing technology from the Node world into GJS applications, I also wanted to use it for writing GJS’s own unit tests. I couldn’t use it directly because that would have been a circular dependency, of course, but I embedded a copy of upstream Jasmine plus a very stripped-down version of Jasmine GJS, and called it “Minijasmine”. It’s now a lot easier, and dare I say less of a drag, to write unit tests for GJS. Accordingly, we’ll now try to cover every bug fix with a regression test.

And I worked on getting the bug tracker down to a less daunting number of bugs. It was fun to make the bug chart in my last post, so here’s another one: this is the number of open bugs during the release cycle from 1.46.0 to 1.48.0.

Graphical report results

You can definitely see that November Bug Squash Month had an effect

Unfortunately the chart will not look like this again next time around. The big drop was me closing all the obsolete or already-fixed bugs during November Bug Squash Month. We are down from about 160 to about 100 bugs, but those were all the easy ones; there are only hard ones left now.

Thanks

Thanks to everyone who participated to bring GJS to GNOME 3.24: Chun-wei Fan, Claudio André, Florian Müllner, Alexander Larsson, Iain Lane, Jonh Wendell, and Lionel Landwerlin.

As well, this release incorporated a lot of patches that people contributed a long time ago, even up to 8 years, that for various reasons had not been reviewed yet. (Many from emeritus GJS maintainers!) Thanks to those people for participating in the past, and I’m glad we were able to finally bring your contributions into the project: Giovanni Campagna, Jasper St. Pierre, Sam Spilsbury, Havoc Pennington, Joe Shaw, Paolo Borelli, Shawn Walker, and Tim Lunn.

Luke Jones and Hussam Al-Tayeb identified a serious memory leak right before the final 1.48.0 release and without their contribution, it would have been a different and much sadder story. As it was, 1.48.0 still contained another serious bug that made GNOME Shell quite unusable for an unlucky few people. Thanks to Georges Stavracas for rewriting a happy ending for 1.48.2.

Special thanks to Cosimo Cecchi, for reviewing almost every single line of the code I wrote for this release: about 20000 lines, many of them boring and repetitive.

Thanks also to my employer Endless which sponsored most of the Javascript engine upgrade, and a good chunk of miscellaneous bug fixing time.

Looking forward

My next post will be about what’s to come in GJS for GNOME 3.26.

November Bug Squash Month: GJS

Here’s what happened during November Bug Squash Month in GJS.

First off, I didn’t really get on the ball to promote Bug Squash Month and I didn’t take pictures of any bug squashing activity… which I regret. I hope this post can make up for some of that.

During November I finally took the leap and offered to become a maintainer of GJS. My employer Endless has been sponsoring work on bugs 742249 and 751252, porting GJS’s Javascript engine from SpiderMonkey 24 to SpiderMonkey 31. But aside from that I had been getting interested in contributing more to it, and outside of work I did a bunch of maintenance work modernizing the Autotools scripts and getting it to compile without warnings. From there it was a small step to officially volunteering.

With not much of November remaining and a holiday and family visit coming up (life always is more important than bug squashing!) I decided to start out my bug-squashing campaign with what would get me the most results for the time spent: going through GJS’s bug tracker and closing obsolete or invalid bugs. This I managed to do, closing about 1/4 of all open bugs!

Then I made a list of all open bugs with attached patches and intended to review them to see if they still applied and why they hadn’t been committed yet. I got through a few, and had the dubious distinction of fixing up and committing patches from a 7 year old bug yesterday. But as you can see in the list, there are still 54 remaining. A good to-do list for the next Bug Squash Month, or whenever I feel like working on GJS but don’t know what to work on!

Did you know Bugzilla could generate graphs? I didn’t! Here’s a graph of the total bug count in GJS during November Bug Squash Month:

chart

The clunkiness of this chart kills me though…

My plans now that Bug Squash Month is over are to concentrate on fixing things that make it more pleasant to use and contribute to GJS:

  • Find an active co-maintainer so that we can review each other’s patches (could this be you?)
  • Make ES6 Promises available (this work is also being sponsored by Endless)
  • Rework the test suite to use an embedded copy of Jasmine so that writing automated tests becomes less of a pain
  • Find ways to bring in some of the conveniences that Node developers are used to

I’ve also decided to try an experiment: I’ve just made the Trello board public on which I keep track of what I’m working on and what I’d like to work on. Let me know if this is interesting to you and what features you might like to see on there! (It’s made possible by a Chrome extension, Bug 2 Trello.)

All in all November Bug Squash Month was a success, though next time I will get started earlier in the month. Come join me next time!

gnome_bugsquash_nov_2016

 

Documentation for GJS

In the last days of January I attended the GNOME Developer Experience hackfest, remotely. This was a first for me since I have not attended a hackfest remotely before. It was also a first for the hackfest, that three remote participants signed up, and we had a discussion on desktop-devel-list as to how that should work.

My main project for the three days was to show people the documentation browser I’ve been working on. This got started a while after last year’s edition of the DX hackfest, which I didn’t attend, but the project was born out of a discussion with some people who were there and talked about it last year.

Some background: You can write applications for the GNOME desktop in many different programming languages, including C, Python, Javascript, and Vala; this is made possible through a piece of software called GObject Introspection, which is a bridge between C libraries and many other programming languages. At (yet another) DX hackfest, the one in 2013, GNOME decided to promote Javascript (and the GJS interpreter, which is basically the Javascript engine from Firefox 24 with GObject Introspection on top) as its preferred platform for application development. Not the exclusive platform, you can still develop apps in Python if you want, but there would be a focus on getting new developers started in Javascript, with tutorials and documentation.

Sadly, since then, we haven’t had good API documentation for developing apps in GJS. The best story we had for a long time was to tell people to refer to the C, Python, or Vala API references and mentally make the transition to Javascript, a process I’ve compared to playing a song on the guitar using chord sheets from the internet, but mentally transposing them to a different key as you go along. At one point, Giovanni Campagna generated some static Javascript documentation and hosted it on his website. This eventually got out of date.

So, this was the problem I was hoping to solve. After a short-lived attempt to write my own web app using Semantic UI (a technology I’d still like to check out someday!) I figured, why bother when there was something that would fit the bill perfectly well: DevDocs, an open-source documentation browser that combines all kinds of documentation from elsewhere (mostly web development technologies) and presents them in a unified fashion with a useful but simple and elegant web app.

In the final quarter of 2015 I worked on this on and off, adding some code to the documentation generator g-ir-doc-tool to make its output suitable for DevDocs to input, and some code to a forked version of DevDocs to import the GNOME documentation and make nice metadata and sidebar entries.

Screenshot of Javascript documentation on DevDocs

Here it is in action

At the hackfest I gave a demo (at 6:30 AM, because of the timezone difference!) to the other people there who were working on developer documentation. I got some good feedback from the people who were listening, discussed some of the shortcomings, and we discussed Mathieu Duponchelle’s new documentation tool, Hotdoc, as well. One good outcome was that the GNOME Developer Center now links to my instance of DevDocs (noting that it’s “experimental”.)

To talk about one of the limitations that we discussed at the hackfest: The approach I chose generates all the documentation from one file, the “GIR file,” which is the same approach that g-ir-doc-tool has always taken. This is nice because it’s self-contained, but also incomplete: API references often include separate pages not connected to any API in particular, such as this one. I think using Hotdoc will help overcome this limitation, since Hotdoc is made for combining these sorts of things. I’m also happy not to work with g-ir-doc-tool since all the stuff I added to it was basically bolted on the side, not really useful for anything else, and therefore not likely to be accepted upstream.

I’m now hosting an instance of the GNOME Javascript API documentation on my modified version of DevDocs: try it out at http://docs.ptomato.name:9292/.

During the hackfest I also collaborated with Philip Withnall on some autoconf macros for GJS and GObject Introspection, which I’ll talk about in a following post…

Some of the other stuff that people worked on is summarized on Philip W.’s blog.