BrowserJavascript

Console.log Surprises with Internet Explorer 11 and Edge

Like countless other developers, I decided to monkey-patch console.log to implement the logger of our Angular application. You may or may not like this approach, but it worked flawlessly. The first time it broke was when we deployed it to production today.

What had happened?

After a while, we observed that the application works fine if we ran it after opening the developer tools. Closing the developer tools made the application crash again.

Internet Explorer 8 and 9

A quick research in the internet showed a possible explanation. console.log is meant to be debug code. So the Microsoft developers considered it a good idea to create the console object only if the developer tools are open. Close them, and the entire console object is undefined again.

As a remedy, you can use this polyfill:

if(!window.console) {
  var console = {
    log : function(){},
    warn : function(){},
    error : function(){},
    time : function(){},
    timeEnd : function(){}
  }
}

Excursion: Other browsers

It’s a good idea to always add this polyfill. The console object isn’t part of JavaScript. Instead, it’s an extension of the DOM. Most browsers implement it. Node.js implements it, too. But there’s no obligation to do so. There are a few browsers that don’t. For instance, there’s no console on Blackberry, Opera Mini and UC for Android.

Internet Explorer 10, 11, and Edge

Unfortunately, this polyfill didn’t make any difference.

Since version 10, Internet Explorer always has a console object. If the developer tools are closed, calls to the console object are simply ignored. You can even monkey-patch the methods of the console object:

var JL = require('jsnlog').JL;
console.log = JL().info;

You can even show the source code of console.log, console.error, console.warn and so on:

alert(console.info);

In IE11, this shows a native function if the developer tools are closed and a JavaScript function if they are open. The Edge browser always shows a native method.

Now here’s the catch. You can copy the method to a variable, but you cannot use the variable to call the method. So the traditional approach of Monkey Patching (store the old function, intercept the function by overriding it and call the original code at the end of the overriding function) doesn’t work. Quite the contrary, it results in an exception:

alert(console.info);  // shows "native function"

const original = console.info;
alert(original);      // shows "native function"

console.info("You ain't gonna see me, but never mind"); // silently ignored

original("I'm gonna crash in production!"); // may result in an exception

Wrapping it up

The annoying thing about this bug is that it doesn’t leave any traces. Internet Explorer and Edge assume you don’t need any logs in production. From a performance perspective, that’s a great idea, but other than that, it’s annoying. The error message disappears into Nirvana without further ado.

So either you follow the advice of most experienced JavaScript programmers: avoid Monkey Patching, and use a dedicated logger class instead. Or you redirect the console messages without logging them redundantly to the console object of the developer tools. That’s what we did: Now every log message is sent to the server, using the awesome JSNLog library.


4 thoughts on “Console.log Surprises with Internet Explorer 11 and Edge

  1. The most interesting question would be though: Why did you only find it in production and not in your test environment?

    1. Well, that’s simple: we developers are both trained to avoid Internet Explorer (because of its mediocre developer tools) and to always keep the developer tools open. I know that’s not the way it should be, nor is it what a professional software developer should do, but using IE with the dev tools closed doesn’t come easy to me :).

  2. Awesome analysis!!! I think you meant to say “but you ***can’t*** use the variable to call the method.” This problem was vexing me for 24 hours. Sadly, IE doesn’t really point to the problem, it just throws a random exception and, since my logging was in an asynchronous method, it was pretty hard to track down. What made it more frustrating is that I didn’t even know what phrase to google to get the answer. After I figured out that assigning console.log to a temporary variable didn’t work, I wanted to know “why?” Now, with my search terms being “console.log native code in edge” – your page was the result. What a day-night-day of frustration. The old “works in Chrome” thing… Oh IE/Edge – I hate you so! 🙂

    1. Oops – a small typo, obscuring the intent of the entire article… thanks for pointing this out!

Leave a Reply

Your email address will not be published.