Thursday, July 16, 2009

Learning to Love Jetpack, Part 1

I've been having a torrid on-again/off-again love affair with Mozilla Jetpack for the past several weeks, and I have to say, it's been a bit exhausting at times. But try as I may to walk away, I keep coming back for more. I guess fools rush in where less impetuous web developers fear to tread.

It should be said up front that Jetpack is quite immature at this point (having been announced only a couple months ago) and there's a new release almost every week. Putting it through its paces feels a bit like driving a concept car. It's fun, it's exciting, it'll amaze your friends. But is it ready for production?

The basic concept is compelling: Make it possible to develop JavaScript-based Firefox extensions that have special security privileges (the ability to do cross-site AJAX, for example) combined with the ability to vulture page objects at load time, a la Greasemonkey. The goal is to let mere mortals write Firefox add-ons without having to get mired in the XPCOM morass. (If you've ever tried to write a Firefox extension, you know what I'm hinting at. If not, you can get a good whiff here.)

What can you do with Jetpack? Right now, not a lot, other than peek and poke the DOM as a page loads. True, the MozLabs crew recently added audio-recording support, and there's a persistence API that doesn't rely on cookies. Plus you can iterate through tabs, put stuff in the status bar, and create toaster popup notifications. (Woo hoo.) But still, not a lot. You can do most of this kind of stuff with Greasemonkey.

That'll all change soon, though, as Jetpack's APIs expose more and more XPCOM internals. Be clear, a year from now, no one will be mentioning Greasemonkey and Jetpack in the same breath.

Even now, though, Greasemonkey and Jetpack are pretty far apart, under the covers. One difference is the runtime scope. Jetpack runs "above" all open tabs. This is quite handy, because it means you can easily enumerate and manipulate all open tabs (I'll provide some source code for this in a later post), something that's all but impossible to do in Greasemonkey.

Another nice thing about Jetpack is that it comes preloaded with jQuery. You don't have to do anything special to access jQuery methods; just start using them.

There's some built-in support (convenience methods) for the Twitter API, which is kind of interesting.

And you get an integrated development environment with Bespin, which is pretty nice. That, combined with instant-on loading of scripts (no need to restart Firefox), makes for a rapid dev/test cycle, greatly reducing Rolaids consumption. I'll lead you through the dev workflow in my next post so you can get an idea of what it's like to develop Jetpack scripts.

There are a couple of issues (one of them quite serious) to be aware of, though. First, you can't install and use a Jetpack script without installing Jetpack. In other words you can't just give a script to a friend and say "Here, install this, it's cool." Instead it's "Go to the Mozilla Labs download page, install this week's alpha build of Jetpack, along with Firebug 1.4, and pray God my script still works on your machine next week."

The MozLabs guys say that eventually, Firefox may come with embedded Jetpack support so that no one need proactively do a Jetpack install before being able to use Jetpack scripts. That would be a Very Good Thing, except for one potentially nasty issue.

The nastiness has to do with the way Jetpack facilitates memory leakage. Simply put, it's extraordinarily easy to write scripts that eventually cause Firefox to hang. One can argue that adhering to best practices will prevent this (which is true), but I think that if the Jetpack agenda truly does revolve around getting mere mortals (people with modest JavaScript skills) to participate en masse in creating Firefox extensions, the potential exists for disaster. You're inevitably going to have large numbers of amateur programmers getting into trouble with memory leakage, and that's not going to do anything good to Firefox's already poor reputation for memory leakage nor to Jetpack's reputation.

As I see it, the problem is really twofold. Fold Number One has to do with the way XPConnect works. (XPConnect is the bridging technology that allows JavaScript to interoperate with XPCOM objects written in C++.) Without going into gory detail, C++ and JavaScript have different memory management models. One is a world of reference counting, the other is a mark-and-sweep world similar to Java. When you wrap a C++ object in such a way that it's usable from JavaScript, you're entering a whole new universe of memleak possibilities. This is the domain where Jetpack lives.

The second aspect of the problem is that the kinds of capabilities that attract programmers to something like Greasemonkey or Jetpack tend to draw on programming patterns that are inherently dangerous from a memleak point of view, chief among them the Observer pattern. Sometimes I think the Observer pattern is actually better termed The Cyclic Reference Memleak pattern, because you're basically creating objects and/or wrappers that maintain references to each other. It's a great way to generate memory leaks.

Again, any competent developer (myself not included) will understand the importance of best practices here, and staying out of trouble is not rocket science. But to expect the average script kiddie to know or care about memleak mitigation is like expecting the average McDonalds customer to know how to make a roux.

In any case, Jetpack is an interesting beast and I continue to be fascinated by (and infatuated with) it -- enough so, that I intend to devote at least a couple more blog posts to it. Check back here in a day or two. We'll have some fun.