Saturday, February 10, 2007

Why I May Never be Good at Scripting

In an effort to highlight my extreme ignorance I'll point out a recent bug I raised in the excellent Mochikit framework. In the end I came to the conclusion that Javascript libraries, while they can handle a great deal of incompatibilities between browsers, can't do it all.

I wrote the following Javascript:listMin([10,9,8,7,]);

This finds the minimum value in the list. In IE the result is undefined, in Firefox it is 7 and in Safari it's a syntax error. As I've found out, an array in Javascript as written above does a different thing in Firefox (an array containing 10, 9, 8, 7), IE (an array containing 10, 9, 8, 7, null) and Safari (syntax error). Checking this code against the specification (using something like JSLint) shows that the above code is really a syntax error (the extra comma after 7).

Part of the problem is that when comparing values in Mochikit a null or undefined is less than any other value. My expectation is either an exception or trying to make all browsers work the same way (not possible in Safari of course).

Now the result of these arrays were being passed around, in a functional way (which is part of why I liked Mochikit), and a more typical example is the second one given in the bug report:
map(function(x) {
if (!isUndefined(x)) return x[0];
}, [[10,10],[9,9],[8,8],[7,7],]).length;


Again, IE is creating an extra null object and returns 5 and it returns 4 in Firefox. The actual code using this was getting an exception in IE but not in Firefox because it was trying to treat a null object like an Array.

This is perhaps an example too, where functional passing style was more difficult to debug than if it was in a loop. But then you'd expect arrays to work the same (or at least I did) and that types are maintained (null not being an Array).

Now I'm generating code and allowing commas after each element in a list is a pretty familiar concept in heaps of languages. I can see why Firefox allowed this behaviour. I can also understand Safari following the specification. IE's behaviour though, doesn't make sense to me at all. It seems to have been purposefully created to cause problems.

All of this conspired to take many hours trying to debug code from a very lower level in several libraries, all the way back up to the highest where the arrays were being created.

A good API prevents these kinds of things from being processed - fail fast. I like Safari's behaviour the most - it would've saved me the most time (of course I was on a Windows machine so no help there).

No comments: