Javascript and the pitfalls of weak typing

've had a bit of free time of late, due to the sleepless nights that my newborn son is assisting, and for some reason or another, I decided to write an extension for KomodoEdit that worked along the same lines as an addin for Visual Studio called CopySourceAsHtml.

The problem

Anyhoo, I had a bug that I couldn't figure out - in my HTML writing function, all my line delimiters were being converted to  . That is, whenever \r\n or \n were encountered, the function was supposed to close any open spans and insert a break element, but a   was being inserted instead.

The code responsible:

var c = text[i];
var s = styles[i]

if (s == 0) {
    //Is whitespace of some sort
    if (s == " ") {
        sb.push(" ");
    }
    else if (c == "\t") {
        sb.push("    "); //tab
    }
    else if (c == "\r") {
        continue;
    }
    else {
        // \n
        if (innerSpanOpen == true) {
            sb.push("</span>"); //close inner span
            innerSpanOpen = false;
        }
sb.push("</span>"); //close line newRow = true; } }

You're (as in me) doing it wrong

The ultimate root of the error was me using undescriptive variable names, as it made confusion far too easy, so c has now been refactored to character and s to style. But my lack of understanding of Javascript also played a key part. The error stems from this line in particular:

if (s == " ") {

This is a typo/logical error. It was 4am in the morning when I was writing this, so probably the latter. I of course, wanted to check if the character was a space, not the style, which is an integer, but the reason that it was always returning true is an interesting one for me, because it was always returning true when s/style was 0, when compared to a string consisting of a space.

Dynamic types, weakly held

So, it turns out that in Javascript 0 == " ". This confused me, as I couldn't see how that worked (did I mention my background is 99% strongly typed languages?), so after some digging through the Mozilla Javascript reference I came across this:

When comparing a number and a string, the string is converted to a number value. JavaScript attempts to convert the string numeric literal to a Number type value. First, a mathematical value is derived from the string numeric literal.

The Javascript reference shed no further light on how a mathematical value was derived, so I downloaded ECMA-262, the ECMAScript spec, and presto:

The conversion of a string to a number value is similar overall to the determination of the number value for a numeric literal (see 7.8.3), but some of the details are different, so the process for converting a string numeric literal to a value of Number type is given here in full. This value is determined in two steps: first, a mathematical value (MV) is derived from the string numeric literal; second, this mathematical value is rounded as described below.

The MV of StringNumericLiteral ::: [empty] is 0. The MV of StringNumericLiteral ::: StrWhiteSpace is 0.

So there we go. 0 == " " in Javascript because it does. On the plus side, I hadn't even realised that Javascript had a === operator, so I'll be using that a bit more often.

It's worth noting that this code would've caused mysterious errors in most type systems. In a strongly typed language like Python, the error would have manifested as a lack of generation of non-breaking spaces, as the condition would've always evaluated to False.

Published: 30th June, 2008