Praise be to Joe Hewitt, whose CSS-to-XPath script I was able to adapt for this patch. I'm a regular expression doofus, so otherwise I'd have been dead in the water.
For a while I've had the idea of translating CSS strings to XPath strings to speed up the $$ function (which, while handy, is horribly slow), but I couldn't justify writing all that code just for Firefox. But XPath support has made it into WebKit nightly builds, which means the next major version of Safari will probably get XPath. And Opera 9 supports it, too, leaving IE as the only member of the big 4 that will not. (I can always dream of IE8).
This patch introduces a new method for String.prototype so that you can do "li#main".toXPath() and it'll return //li[@id='main']. It also tests for document.evaluate and, if successful, re-defines $$ and document.getElementsByClassName to use XPath. Browsers that do not support XPath will keep the ordinary versions (which, while a little slow, are still perfectly fine), so this doesn't break compatibility with any browser.
What's the point of all this? A performance increase that's at least sixfold and usually much greater. To use getElementsByClassName as an example: since it fetches all tags on the page and loops through them, the time it takes to execute rises linearly with the number of elements on the page, not the number of elements you're requesting.
This means that XPath really kicks ass in situations where there's a really big haystack and a really small needle. In informal testing I've had XPath beat the ordinary $$ function by a factor of 20 on large pages.
Attached is xpath.js, which can be dropped into an existing Prototype install without modifying any files. (I'll work on testcases soon. I swear.) I've tried to make the code footprint as light as possible, but the String.prototype.toXPath method is somewhat bulky out of necessity.