Tuesday, April 28th, 2009

vice-versa: the noble act of getting the best of all browsers

Category: JavaScript

<p>Andrea Giammarchi has a vision to have the best of all browsers available to him in JavaScript land. He has created vice versa as a project to explore this ideal and incredibly hard vision to attain:

Studying the DOM, which is notoriously a mess, I often “travel” between the MDC and the MSDN to solve a specific trouble which could cause a lot of headaches because of “some” missed W3C implementation. At the same time, bearing in mind that the most used browser is the one with the slowest JavaScript engine, I always try to find out solutions able to complete a task without killing performances. In most of the cases, I simply realized that since other browsers are fast and more powerful, it makes sense to bring some not standard functionality inside these browsers rather than implement, when it is possible, a missed functionality in Internet Explorer. As basic example, to convert an XML document into a string, we would like to use an XMLSerializer instance, but what is that wrong with Microsoft xml attribute shortcut?

javascript
< view plain text >
  1. // other browsers way
  2. var xmls = new XMLSerializer;
  3. var string = xmls.serializeToString(myXMLDocument);
  4.  
  5. // Internet Explorer way
  6. var string = myXMLDocument.xml;

Moreover, document.evaluate is amazing stuff, but the most common call to this function is this one:

javascript
< view plain text >
  1. var xpresult = document.evaluate(XPathSelector, myXMLDocument, null, 0 /* as ANY_TYPE */, null);

In internet explorer we have a slightly different function: selectNodes

javascript
< view plain text >
  1. var xpresult = myXMLDocument.selectNodes(XPathSelector);

The main difference is number of character used to call the standard method rather than IE one, with a completely equal result during iteration where IE nextNode has the same meaning of other browsers iterateNext. Again, if we are in Internet Explorer we can rely in the most ugly property we have ever seen since first JScript implementation over the DOM: document.all. Now, why on earth we love YUICompressor plus gzipminiaturization” but we prefer a meaningless syntax like this:

javascript
< view plain text >
  1. document.getElementsByTagName("*")

rather than

javascript
< view plain text >
  1. document.all

I would love to see us in a world where standards weren’t the only way to innovate deeply in the browser, cross browser. We have add-ons in most browsers, but creating multiple versions is a pain. I was excited about Gears as a way to do cross browser work, and maybe if a Gears-like system that allowed many people to write services, we could go further.

Update

Andrea has also just posted on the vice versa selector performance where it does quite well in slickspeed on FFx 3.

Related Content:

10 Comments »

Comments feed TrackBack URI

I’m bothered less by the various JS and DOM API differences than I am by the CSS issues. For all but the most compute-intensive applications, few of these issues are real show-stoppers. There’s typically some acceptable work-around.

The CSS issues, on the other hand, are much harder to deal with. I’m thinking specifically of rounded-borders and some of the more nuanced selector support that’s missing in IE.

On the bright side, it seems like the developer community as a whole is more willing to let IE users just suffer, rather than waste time fixing problems that MSFT should have addressed years ago. E.g. “If IE doesn’t support rounded borders, so be it – IE users don’t get to see rounded borders.” That sort of thing.

Comment by broofa — April 28, 2009

Dion, thanks for the entry :-)
I would like to add that in the repository there is a TaskSpeed dedicated file which is the closest in performances to PureDom baseline. Finally, with FireFox 3.0 the SlickSpeed test performs faster than Sly, Sizzle, and others (experimental selector thou) :-)

Comment by WebReflection — April 28, 2009

hmm.. I’m not sure about idea.
I’m more after philosophy that Dean Edwards reflected a while ago in base2 – it tries to bring one standard of choice to all platforms not all standards to all platforms.

Comment by medikoo — April 28, 2009

medikoo, as I explained in my blog related entry, it is about what is possible to bring “where” without loosing performances.
Since MSDN is a good reference we could see some IE specific behavior as an API and since only other browsers are able to emulate IE behavior there is no reason to make IE faster.
Take jQuery as example, we all like the html method to retrieve or set html, so what’s wrong with the xml attribute to retrieve serialized documents? And what about outerHTML to quickly replace or remove a node? innerText rather than appendChild(document.createTextNode(whatever)) ? and how to retrieve plain text without tags? all this stuff requires a library which 90% of time will privilege recent and powerful browsers and sill penalize Internet Explorer performances …. something already bad compared with every other browser.
I like the DOM way but at the same time I think innerText is not that bad, .xml is short meaningful and fast, the same is for innerHTML the most unstardard and the most used as well, copied by IE … so that is good, the rest is crap? I do not think so, as I do not think that a fast implementation of Mozilla and ECMAScript 5 Array is bad for explorer or other browsers ( Array.slice and Array.forEach compatible with HTMLCOllections as well ) … so that’s the philosophy, performances preserved or good overall performances and some shortcut that could make our code shorter, still standard via getters/setters or DOM/XML prototypes and without penalize the most used browser, IE.
Obviously, if you want to see only attachEvent … well, there’s nothing I can tell you, but addEventListener so far has never been used as intended (third parameter incompatible with IE so not a single library emulate it) and the only reason we like it is for the “this” (plus some extra “magic” stuff a la DOMContentLoaded) but for the “this” we have event.srcElement while rather than use callbacks we can use event.cancleBubble or event.returnValue and in few wods we have a hybrid low level that thanks to recent standard browsers will be still fast (via prototypes) and standard, via DOM native methods inside prototypes. That’s it, less code and more natural behaviors rather than emulated one via some library. Of course a library based on vice–versa will perform in any case generally well, that’s why the TaskSpeed file is almost 1/2 of the DOM based one, but almost that fast as well. Hope you got my points but in any case I was sure about skeptical reactions … is just I have to deal with IE and a truly complex application on daily basis and performances are always cryptic there :)

Comment by WebReflection — April 28, 2009

@Andrea – You have a good start here. I dig the use of the getter/setters.
I have a feeling once you flesh things out you will see that a lot of the slow down in other frameworks can be attributed to the fact that they are fixing lots of bugs you have over looked.
.
For example: Array.slice (native generics like this are only supported in Firefox at the moment)
.
Array.slice – In your for-loop if your nodeList contains an element with the id=’length’ your iteration will fail.
.
Object.defineProperty() is missing support for the descriptors like `writable`, `configurable’ and others. (it can’t be emulated so why a half port that’s inconsistent across browsers)
.
Your String#trim does not follow spec and will produce inconsistent results across browsers that support native trim
.
Also yuck for `if(+”\v1″){(` in your DOM.js
.
IE8 supports document.querySelectorAll and will fail when your Selector engine tries to use native array slice on with a StaticNodeList.
.
There is more, but you get the point. As you begin to create unit tests you will find that more code and branches are needed to create consistent and stable results. You have a good start and keep up the good work.

Comment by jdalton — April 29, 2009

jdalton, thanks for hints … Array.slice should works with every browser over HTMLCollections as well, it is in the test case but I’ll look deeper.
You are right about defineProperty but so far what I have done is a porting of IE8 implementation … btw that method is not usable with IE6 or 7 so it is just a plus which does not cost that much (bytes speaking).
The trim in the nightly check if there is a native one so it should not overwrite it when present, same is for Function bind in nightly.
the IE check is just something easy to change the day that trick will not work anymore … so far, that trick is reliable and extremely compact :-)
slice for IE is not the native one, there is a try catch to avoid problem you described so with IE8 document.query(“tag”).forEach(…) will work, part of the test file.
document.query is using an essential selector based on most used selectors: #id, tagName, .className, tagName.className … that’s it. It is a public static document method that could be easily changed via:
document.query = Sizzle;
or
document.query = Sly.search;
when and if we need a better engine, as long as it returns an Array instance.
You are right in any case, I need to write a lot of tests but I am already using this stuff in a production environment and so far so good, hoping someone will suggest me other IE tricks absent in other browsers or vice-versa ;-)

Comment by WebReflection — April 29, 2009

@Andrea – The problem is not overwriting native methods its that when you add support for methods like defineProperty and slice and trim you aren’t following spec, so browsers that do implement them have the possibility of returning a different result that the ones that have those methods simulated by visa-versa.
.
In your query method you reference ‘slice = Array.prototype.slice’ and not your `Array.slice` method and you aren’t correcting the Array.prototype.slice so I still think you will have issues with it.
.
Having the code in a production environment will help with bug fixes for sure :D.

Comment by jdalton — April 29, 2009

jdalton, try the code since you cannot spot where I correct the slice … it simply works. Why guys don’t you test a little bit before these posts? :)
Also try the test page, there’s almost everything there and compare with whatever browser you want ;)

Comment by WebReflection — April 29, 2009

@Andrea – fair enough :)
I see where you fix it for IE8. Keep up the good work.

Comment by jdalton — April 29, 2009

The idea is backwards, just like those Base libraries. The last thing you want to do is further confuse feature detection.

Comment by DavidMark — July 11, 2009

Leave a comment

You must be logged in to post a comment.