Debug JavaScript in Internet Explorer 11 in 7 easy steps
Posted Dec 14, 2020 | 11 min. (2193 words)This article will focus on debugging JavaScript code within Internet Explorer 11’s Developer Tools.
The developer tools built into IE11 make developing and debugging code in the browser relatively straightforward. The browser’s tools boast many of the features of the other more developer-focused browsers such as Chrome and Firefox.
While Microsoft declared the end of support for IE11 by Aug 17th, 2021, with many people still using the browser, it is useful to have some debugging skills to hand.
We’ll be using Raygun Crash Reporting to find the stack trace and the line of code the error occurred on. You can sign up for a free 14-day trial here.
The steps we are going to follow are:
- Sample project introduction
- Analyze a Raygun error report
- Explore the anatomy of Dev Tools
- Add breakpoints to your code
- Step through your code
- Determine the state of your application
- Fix the bug!
So, let’s dive in!
Step 1: Sample Project Introduction
To demonstrate how to debug an application with Internet Explorer’s Developer Tools, I’m going to use a simple Add Person form. This form allows you to enter a first, middle, and last name. On clicking the ‘Save’ button, the form will do a bit of processing, and the data will be sent off to your (imaginary) server.
The code for this form has three functions:
- A click handler
- A capitalize string function
- A save function
var saveButton = document.getElementById('saveButton');
var firstNameField = document.getElementById('firstName');
var middleNameField = document.getElementById('middleName');
var lastNameField = document.getElementById('lastName');
function onSaveButtonClick(){
var firstName = firstNameField.value;
var middleName = middleNameField.value;
var lastName = lastNameField.value;
// capitalise the names
firstName = capitalizeString(firstName);
middleName = capitalizeString(middleName);
lastName = capitalizeString(lastName);
doSave(firstName, middleName, lastName);
}
function capitalizeString(value){
return value.split('')[0].toUpperCase() + value.slice(1);
}
function doSave(firstName, middleName, lastName){
alert(firstName + ' ' + middleName + ' ' + lastName + ' has been saved!');
}
saveButton.addEventListener('click', onSaveButtonClick);
Unfortunately, after shipping this to production late on a Friday evening, you start to see error reports coming into your dashboard. There’s a bug, and you need to fix it, quickly.
Step 2. Analyze the Raygun error report
Error reports that come into Raygun have plenty of info you can use to find and fix the error, so let’s have a look at what we’re dealing with.
The information you will need to debug the error is located in the Stacktrace module.
The Message part of the Stacktrace is a short overview of what is wrong. In this case, the toUpperCase
method is being called on an undefined value.
The Stacktrace tells you where the error occurred and the sequence of function calls that led there. As you can see in the screenshot above, the error happened in the capitalizeString
function on line 20 of the index.js
file.
Knowing which line triggered the error means you can jump straight to the place where the error occurred and start digging into what has caused the problem.
Step 3: Exploring the anatomy of the Developer Tools
The first step is to launch the app in Internet Explorer and open up the Developer Tools. You can do this with the keyboard using the F12 key or by selecting “F12 Developer Tools” in the “Tools” menu.
The Developer Tools will now be open inside the browser tab, and the DOM Explorer tab will be active. Change to the Console tab by clicking its name. The Console tab allows you to execute arbitrary JavaScript code at any time or to view any outputs from console.log
calls.
Try entering alert('Hello!');
and hitting Enter — you should see the alert appear straight away.
The Console tab is a valuable debugging tool as you can use it as a scratchpad for trying out code and evaluating variables as you diagnose your problem.
To debug the code, you first need to navigate through your source code in the Developer Tools. You do this in the Debugger tab.
You can access a tree view of all the source files loaded into the page by clicking the button at the top left of the tab. You can navigate the files here as you would in an IDE, as the contents are displayed in the central pane.
If you have a lot of files, you can search them by typing the name of the file into the textbox at the top of the file browser.
In the app, you know the problem lies in the index.js
file, so select it from the file list to view its contents.
Step 4: Add breakpoints to your code
Now you can view your code, we want to be able to step through it a line at a time to see where things go wrong. To do this, we use breakpoints. Breakpoints are markers at specific points in the code that stop execution so you can inspect the state of the code at that point in time, and continue execution line-by-line.
There are a few different ways to add breakpoints which I’ll go over below.
Line breakpoints
The most common way to add a breakpoint is to find the specific line you want to stop on and add it there. Navigate to the file and line you are interested in and click the line number. A red marker will be added on that line and execution will stop every time it hits this line of code. In the screenshot below it will stop on Line 7 of index.js
.
Event breakpoints
You can force execution to break when a specific event (or set of events) happen on the page. In the right-side debugging pane, next to Call stack, you can select the “Breakpoints” tab. Then, click the “Add event breakpoint” button and select the event you want to break on from the list. You can optionally add a condition expression to prevent execution from being stopped every time.
Programmatic breakpoint
You can also add breakpoints programmatically, which can be useful if you don’t want to search through your code in Developer Tools when you have it handy in your IDE. You can also use this approach to conditionally introduce breakpoints, for example, at specific iterations of loops, or if the code runs on page load and there’s no time to add the breakpoint manually.
To do this, you add the debugger;
statement at the position you want to break the execution. The code below will have the same effect as the Line Breakpoint above.
Error breakpoint
Developer Tools has a handy feature that will stop execution when it hits an exception in your code, allowing you to examine what’s going on at the time of the error. You can even choose to stop on exceptions that are already handled by a try/catch statement.
To enable this feature, click the stop sign icon with the pause symbol within it and choose the option you would like from the list. It will be blue when enabled.
Step 5: Step through your code
Now that we know how to break into our code, we now want to step through each line so we can figure out what’s going wrong. First, put a breakpoint on Line 7 — just inside the Add button’s click handler so we can start at the beginning.
In the previous section, we inferred from the Raygun error report that the error came from the capitalizeString
method. This method is called three times, so, which instance is the culprit? You can look a little closer at the Stacktrace and see that it was the call that came from Line 13, which caused the error. You know that line 13 relates to the Middle Name value. Therefore, you should focus your effort on reproducing the error by crafting your input correctly.
With this extra knowledge, you can fill in the First and Last Name fields but leave the Middle Name blank to see if this triggers the error.
Hit the Save button. From here, the Source tab will open where you can see the breakpoint activated. You can now start to step through the code. To do this, you use the four buttons in the debugging pane.
- The first pauses or resumes execution of your code and continues until the next breakpoint
- The second steps over the current line, moving us on to the next line
- The third steps into the next function call that is on that line
- The fourth button steps out of the current function call, back up the call stack one level
You’re going to use these to step all the way to your capitalizeString function. So from Line 7, use the “Step over” button until we get to Line 13. The active line is shown with a yellow background and an orange arrow pointing at it.
You can now use the “Step into” button to move into the call to the capitalizeString
function.
Navigating the call stack
When you’re moving through the code like this, you might want to jump back to a parent function to check what was happening at that point. To do this, use the Call stack section, which lists all the functions that have been passed through to get to this point in your code — exactly the same as the Callstack shown in the Raygun error report.
You can click on an item in this list and you will be moved back to that function. Bear in mind that the current position in the execution doesn’t change, so using the Step Over buttons will continue from the top of the call stack.
Step 6: Determine the state of your application
Now you’ve navigated to where your error happened, we need to examine the state of the application and figure out what’s causing the error.
There are a few options for figuring out what values variables contain and evaluating expressions before the code moves on. We’ll look at each in turn.
Mouse hover
The simplest way to determine the value of a variable is to hover the mouse over it and a tooltip will pop-up with the value. You can even select a group of expressions and hover over this to get the output of the expression.
Watches
You can add expressions to the Watches panel which displays the current value of the expression as you move through the code. This is handy to keep track of how more complex expressions change over time.
You add these by either clicking the button at the top of the panel, clicking the “Add Watch” text at the bottom, or by selecting an expression, right-clicking, and choosing “Add Watch”.
Scope
The Watches panel also displays a list of variables currently within scope and their associated values. This is similar to manually added watches, but these are generated automatically by the Developer Tools. This section is useful for identifying local variables and saves you explicitly adding them to the Watch list.
Event Tracepoint
A feature unique to IE 11’s Developer Tools is the Event Tracepoint, which allows you to define an expression to evaluate and output to the console whenever a selected event occurs. For example, you could output the current datetime when a mouse event happens.
To add an Event Tracepoint, click the button from the Breakpoints section. From the window that opens, select the event you want to trace and then enter the expression to output.
Console
Finally, the Console tab is an excellent tool for checking expression values and experimenting with code. Just switch back to the Console tab, type some code, and hit enter. Developer Tools will execute the code within the context and scope of the current breakpoint.
Step 7: Fix the Bug
Switch over to the Console tab, and let’s start to break down the line that caused the error so you can fix it using the Console tab
First, check the output of the value.split('')
call (which is intended to grab the first character and then call the toUpperCase
function on it).
Executing the expression in the Console shows it returns an empty array — this is where the error comes from! Since it returns an empty array and we try to call toUpperCase
on the first item in the array (undefined, since there are no items in the array at all), it results in an error.
You can verify this by entering the full expression into the Console. To fix this problem, you need to check to see if the string is empty or undefined before parsing it. If it is, you need to return an empty string back without doing any processing.
function capitalizeString(value){
if(!value || value.length === 0){
return '';
}
return value.split('')[0].toUpperCase() + value.slice(1);
}
Summary
That wraps up this quick intro to debugging JavaScript in Internet Explorer 11’s Developer Tools. These developer tools are a welcome leap forward in the developer experience in past versions of Internet Explorer, and are very complete when compared with other browsers’ offerings, even including a few unique features of their own.
If you’d like to learn more, we wrote a whole guide on JavaScript debugging in major browsers. Debug JavaScript using the same process as above in: