Why XBL Sucks

Good news is never as interesting or as powerful as bad news. So while the majority of this document will be laying into XBL and its Mozilla implementation, I'd like to issue one caveat up front: XBL is, fundamentally, a Good Idea.

Unfortunately, its goodness is mostly in the idea itself, and little else. But it is a good idea to discretely and in an object-oriented fashion design more powerful widgets, composited out of the existing widgets and event system. It is a very powerful approach, which is why despite the righteous thrashing I'm about to deliver the technology, I still like it enough to extract the core idea and re-create it in a more usable form.

Issues With The XBL Specification

By "the XBL specification" I mean the XML files that make up the XBL specification, not the internal implementation.

First up... XBL is specified in XML. Because it embeds Javascript functions inside of XML wrappers it at least avoids the issues I raised with XUL Templates using too much XML; nobody is pretending the XML can do it all. But I do have to ask what is gained from XML.

I emphasize that because when examining the benefits of using XML there are two types of benefits that must be examined distinctly. First, there are the benefits of the XML syntax, and secondly, there are the benefits that accrue from standardizing on anything at all, not just XML.

XML does have some unique benefits:

  1. Cross-platform: Everybody can parse XML. Parsing XML is only the beginning, but it is a good beginning.
  2. Namespaces: XML provides a clean namespace mechanism, allowing the embedding of multiple distinct types of content in one document.
  3. Entities: A defined text-variable substitution system, though in my opinion the benefits of this are often oversold. It is often used for internationalization in Mozilla but a simple lookup scheme is inadequate to that task.
  4. Associated Technologies: Like XSL and of course DOM.

The question is, how much does XBL benefit from these technologies? And my answer is that in practice, very little.

Entities, as I said in the entry, really aren't that useful; I think they are used for I18N simply because they are there and they "should" be used, not because they are a good solution. Namespaces are mostly used to confuse XBL writers about what namespace they are currently in (and while I'm not supposed to get into implementation details yet I can't resist another crack about the silent failure that occurs if you type <label> instead of <xul:label> in the content section...). Sure, in theory they could embed SVG documents or do other theoretical things, but at the moment that is pure theory and it isn't by any means the only way to do it. (Remember that the "XML data model" and "XML character data" (a serialized data model) are two seperate things, and it is the data model that enables arbitrary embedding, not the character data.) And what use is an XSL transform of an XBL file going to conceivably be? Other than the content tag it is mostly JavaScript anyhow.

XBL's benefits come not from standardization on XML, but on standarization period. By standardizing on XML, you get some degree of cross-platform compatibility and the other benefits of XML.... But you also inherit XML's flaws. And XML flaw number one, of course, is that it makes an absolutely crappy programming language to write in.

The problem with XML as a programming language is that syntax is a very important aspect of a programming language; there is only syntax, semantics, and library. By trying to jam a language into XML, you're choosing a meta-syntax not designed for programming languages, and you still have to create a syntax on top of it! There are some projects that use XML as a base language and allow you to edit any of several transformations of the base XML data; they have to provide the latter to have any hope because pure XML is unusable as a programming language. XUL made some of that error in the template language and see my rant for how well that turned out... it isn't all the XML choice but it plays a big role.

But wait, you say, the XML portion of XBL isn't a programming language, it's a data specification language that happens to hold code chunks in it. And I tell you, that too is code, only it is written in a non-Turing Complete language. Proof by construction: With Javascript, a Turing Complete language, I was able to express things there is simply no good way to express in stock XBL, without directly modifying Mozilla code. For instance, I added a "defaults" attribute that allows an XBLinJS widget to specify a default value for something, such as an inherited value. In XBL, this would probably be a <defaults> tag under <implementation>, containing a series of <default name='name' value='value'> tags. Nor is this the only code-based refinement I've been able to add to what would be "data" in XBL via Javascript code.

Code is data, data is code. XBL makes it impossible to manipulate the portions of the code expressed as XBL tags. Javascript makes it easy. XML is such a horrible programming language, you'd think they designed it for something else entirely, like document storage. XBL freezes contained code into XML ice, to be extracted only with great pain, with tools that Mozilla doesn't even provide anyway.

Problems With The Implementation

The problems with the implementation as it now exists in Mozilla (circa 1.7) strongly echo my complaints about XUL templates: Failures of all kinds are silent. Trying to do something clever will randomly segfault the browser, again with no explanation.

You can't apply any testing technologies like JSUnit because the XBL is too deeply embedded and critical parts are out of your control, such as the rendering order. (Really, I tried, I did, but without semaphores in JS it can't be done, even with document.loadBindingDocument. You can create the XBL nodes, but I had an XBL widget that would not render synchronously for reasons I never could figure out, and as a result it was unavailable for testing, no matter what I did, because having the XBL widget rendered is a pre-requisite for testing its methods; see below.)

Debugging is possible with Venkman, unlike XUL templates, but it is difficult because the thread of execution jumps in and out of Javascript you control and XML you don't.

Creating XBL widgets that dynamically add other XBL widgets as their children has to be kludged at best, and crashes the browser at worst. You can create a DOM node with document.createElement that will become an XBL widget when the node is rendered on the screen, but until the node is rendered on the screen, it is just a normal DOM node. That is to say, if you have an XBL widget that defines a "turnRed" method, this won't work: node = document.createElement("redableThing"); node.turnRed(), even if you add it to the document first. Thanks to the wonders of the Javascript threading non-model, there's no way to ask for a render (that I can see) and you're stuck with the whims of the browser.

This turns out to be a major impediment to making powerful dynamic interfaces that react to the data; XBL can only be used safely one "layer" deep, dangerously "two" layers deep, and basically not at all any deeper. When do I want to do this? Well, in my app, I want to create an interface to edit an arbitrary object, based on its metadata. Having drunk the XBL Kool-Aid (and that metaphor applies rather more than usual), I thought the "grid" that controlled the display of the individual widgets would be an XBL widget that generated other XBL widgets inside of itself in the constructor. Crash. Crash. Crash. Eventually, I created a Javascript object outside of the XBL framework that created XBL objects with the DOM, and that worked swimmingly. As I had to do this more and more often, and each time, it was a pleasure compared to dealing with XBL (no browser segfaults to date, for one thing!), I got to thinking.

How XBL Should Be Done

If I found it so much easier to use JS and the DOM instead of XBL, then why not go all the way?

Instead of standardizing on XBL(XML) + DOM + Javascript, why not just standardize on Javascript + DOM? Much like the end of my XUL template rant, not only can this combination do everything XBL can do, it does it better: It does it more testably, it does it more stably, it does it more debuggably, it does it cross-platform. -Ly. (I guess that isn't a word...)

In fact, it isn't even hard to take an XBL object and convert it to JS + DOM, and writing a base JS class to make this easy doesn't take long (mostly a matter of managing the bindings which is a little tricky, but not too bad). It takes even less time if you just download mine.

If you want "cross-platform" support beyond just browsers, make it easy to embed a JS interpreter into something and provide it a reflection of interface elements through a standard set of DOM nodes. There's no reason a C++ or Java program needs "XML" to read the interface, a Javascript interpreter can run in there as well as an XML parser. (This would be more complicated if XUL only required an XML parser, but to date I haven't seen anything called "XUL" that doesn't already have an embedded language in it, so by dropping the XML requirement we are strictly lowering the requirements in the client app that wishes to use XUL.)

Javascript does have a couple of differences from XBL that I can't work around, but they are annoyances at worst, and in some situations can be big wins. First, XBL widgets automatically call all superclass constructors before the leaf constructor. In Javascript, you have to call them manually. However, that is sometimes a good thing, too, and in XBL you have to go out of your way to avoid this if it is an issue. The flip side too is that subwidgets can extend non-constructor methods and there is a way to call the superclass methods, which I never did figure out how to do in XBL. (I always had to go with a template pattern, sometimes in highly inappropriate ways, to work around this.)

Second, you lose entity support, but it isn't too hard to create a lookup table, and if you like, you can create a more sophisticated system like Perl's Locale::MakeText, so this too can also be a big win under some circumstances.

And in return you get the full power of Javascript, of course. Instead of XML attribute specification, for instance, I use Javascript objects. The JS equivalent of att1="val1" att2="val2" is {att1: "val1, att2: "val2"}... of course, what's the XML equivalent of {name: (this.parent ? this.parent.name + ": subwidget" : "widget") + " #" + WIDGET_COUNT++}?

(As I write this, I am looking into supporting XML fragments via the parsers that IE and Mozilla expose, and yet, almost immediately as I converted my existing XBL widgets over I was using features that didn't translate and made my system clean; since I've turned my code into an open source project I may just wait for someone who cares to add that feature; as I don't care I'm not sure I could do it right.)

In conclusion, even as I don't like the XBL implementation in Mozilla one bit, I like the idea well enough to re-implement it. Certainly it is stronger than XUL templates, in my opinion.

Jerf.org : Programs & Resources : Why XBL (And Its Implementation) Suck

 

Current Section Links

 

Search Jerf.org
Google

Search WWW
Search jerf.org