I had hoped to have a certain list of “immediate to-do” items finished by now, per my previous blog entry. Instead, I got sidetracked. Royally.
First, I ran into an as-yet-undiagnosed layout bug where the DOM had all the nodes in the right place, but certain XBL bindings were not applying. This caused me so much grief that I set the problem aside after a couple days banging on it alone. Then I had a few Bright Ideas.
To spare people who don’t care (because this is a long blog entry), the rest of this article is in the extended section.
Bright Idea Number One
First, I could use the SAX API’s to trace a document’s source code from beginning to end, and with a DOM TreeWalker, walk the equivalent DOM document from root node to end. Why would I want to do that? Well, if I also have the source code of the document (which I need for SAX), then I can match DOM nodes to source code. Almost completely (there are some minor nits that Mozilla’s SAX implementation doesn’t support yet, but not unsolvable ones).
The result is a new interface for Verbosio (xeINodePositionService.idl)
and a new component (nodePositionService.js). Don’t worry if the JS file looks extremely cluttered and sub-optimal. It’s only a first draft, and can easily go through a couple rounds of code clean-up. Later.
This also ties into my Basic XBL validation blog post a few weeks ago. The code, as it was written, was pretty bloated, and of course untested. That didn’t stop me from having another Bright Idea at just about the same time as the previous one.
Bright Idea Number Two
Instead, I created another interface (xeISourceMap),
for taking these JS strings with known locations and contents, and placing them into a much compacted string internally. Then I evaluate that smaller string in a sandbox, and look for a syntax error. If the source map finds such an error, it translates the error location in the smaller string back to its corresponding location in the original source document. The resulting JS component is jsSourceMap.js.
Reusing code is good for the soul. Even if you don’t have a soul.
With the above components, though, XBL validation reduces to four steps:
- XML well-formedness checking (done via a XML language pack)
- Validation of XBL elements via a recursive algorithm in the XBL language pack component,
Nice, neat, simple. Three adjectives every programmer tries to obtain for their code.
Of these, the second step may also be partially reduced if I write a “validation-purposes-only”
Sure, this sounds like a lot of work just for a XBL validation process. However, thanks to XPCOM, these components are reusable in other contexts, as I pointed out in the “Basic XBL Validation” blog entry.
A break in the gloom and doom
Incidentally, that layout bug I opened the article with? It was for a DOM Inspector-like viewer for XML documents. The right-hand panel (where you get nice things like attributes, text content, etc.) just wasn’t working. I could move nodes in to where they should show, and I could manipulate them, but they didn’t have any renderings or XBL bindings. Major headache, especially since I confirmed repeatedly that my code was working correctly.
I planned on creating a reduced testcase by gutting a copy of Verbosio’s code. I was not looking forward to that at all. Verbosio has a lot of little pieces that fit together, and removing a piece in the wrong order without putting an appropriate bypass patch in would have meant some other bustage. I understand the Verbosio code very well (to date I’ve written all of it), and by and large I think it’s good, solid code that combines to make an application. Ripping Verbosio apart to isolate a bug feels like ripping apart a trunk engine to replace one broken bolt: arduous, time-consuming, and not very pleasant… but ultimately necessary.
I may still gut a Verbosio copy to isolate the bug, but suddenly, I’m not under pressure to do it. What I realized is that I was locked into a particular mental model (“you must use a XUL deck element here”), and that the model wasn’t necessarily true. I was having problems with the deck, but not with ordinary XUL boxes. When I visualized the panels of the deck side-by-side horizontally instead of one-at-a-time, I saw intuitively that it could work, and work much better than a deck. It means the user can see more and do more at a glance than they would with the deck. Win-win situation.
It’s another case of common sense in hindsight in application interface design. So there’s an obscure layout bug that I hit. I have a workaround that is actually easier for the end-user to… well, use in the end. I’m perfectly happy with that.
Now, the funny thing is I wrote most of this code in the last 72 hours. I’m not entirely sure why, but I probably spent a good 40 hours coding and maybe 12 hours (including only four last night) sleeping. I literally went to bed at 7 am this morning, and I’ve only eaten once in 24 hours (dinner about, oh, three hours ago). It’s one of those things I don’t do very often. 🙂