Hive LMS: Solving bugs I didn’t know I had!

This has been a very eventful week and a very successful one as far as my programming career goes. Besides the post I put up a few days ago, Hive LMS: Knowing when it’s time to toss code out!, I also stumbled on to a bug that turned out not to be a bug and figured I should share.

So the background of this post in true TL;DR fashion: JavaScript has a bug that returns OBJECT when checking the type of something that is NULL. For the full explanation of this and to get caught up to speed on what I’m talking about so far you should read Dr. Axel Rauschmayer’s post The history of “typeof null”.

What happened this week though when I stumbled on this tidbit of knowledge is I panicked! First, I wrote a custom function that I have been using pretty heavily called empty that replies on checking a variables type and second, I had started writing a strip tag (html entity stripper) that was going to rely on checking types. Since the strip tag function was nowhere near completion my main concern really was my empty function biting me with a zero day or some other crippling bug. At the time I’m writing this post (June 2017) the Hive LMS project is really nowhere near a stage that this should concern me with zero days and crippling bugs but as I learned in Hive LMS: Knowing when it’s time to toss code out!, fixing mistakes and rewriting code can cost you a lot of time and time is something I don’t have a lot of at the moment.

Jumping back in the story for just a second I had at this point read Eric Corry’s The madness of parsing real world JavaScript Regexps and checked out Mathias Bynens’ Robust HTML entity encoder/decoder AKA he, for use in my string tags function; which by the way I think I’m going to call sanitize but that’s another story altogether.

As I started to dig into the code and see how I could potentially catch this type bug it hit me: I opted not to use JavaScript’s built-in type checker in the first place. This decision mostly was because I never used it before and felt I wanted a more controlled approach that I understood. This led me to using the following function I found on Stack Overflow somewhere; quite possibly was in someones comment:

This little gem gets the variables type by looking at it as a string and not relying on the built in typeof that checks the bits. This means when something is null the function literally sees and returns the string null converted to uppercase with toUpperCase to make things easier to see in the code.

Explain this typeOf function to me in more detail:

So lets break this little function into it’s parts. First we make an empty object and invoke its toString method:

({}).toString

This by itself will do nothing but give us a function reference. If we run this code in the developer console we get:

function toString() { [native code] }

That by itself is not helpful at all because its missing the next step:

({}).toString.call( what we’re check goes here )

By adding the call method and sending in what we’re checking we’re telling the computer to ignore the empty object and instead toString whatever we gave it. The call method is related to the apply method and similar but different than bind. Essentially call and apply are immediately invoked where bind is meant for things that will be invoked later. Please see the links to the Mozilla Developers Network manual pages for a more in-depth explanation about the differences here. With the code in its current state we can expect a string back that looks like:

[object Type Name Of What You Passed In]

Type Name Of What You Passed In could be String, Null, Number, and so on where the first letter will always be capitalized. Why capitalized? I don’t really know its just built in JavaScript and as you’ll see in a minute doesn’t really matter. Now lets add JavaScript’s built in match method and provide a simple regular expression to pull this string apart:

({}).toString.call( what we’re check goes here ).match(/\s([^\]]+)/)

Running this in developers console well testing an array will give you the following:

[” Array”, “Array”, index: 7, input: “[object Array]”]

Now we just add on the last little tweaks. First we want the second match all the time so we don’t have to deal with striping the space so we grab index 1; remember array indexes start at 0 in JavaScript. Next we turn the whole string to uppercase. We could have chosen to make it all lowercase but I figured having it all uppercase makes it easier to see whats going on when we need to compare the returned result of this function to something in our own code:

({}).toString.call( what we’re check goes here ).match(/\s([^\]]+)/)[1].toUpperCase();

And there you have it. A step by step explanation of what this magical looking function is actually doing.

 

This then meant I only needed to add one line of code to my empty function to catch this bug. You can see the change on line 55 in the code below and a comment I added on line 54 explaining what is happening:

So there you have it! I solved a bug I thought I had by avoiding the bug unknowingly in the first place.

Leave a Reply