JavaScript Timer and Stack Trace Debugging

Today I had to work on a webpage with a large amount of JavaScript timers running and I had to find a bug which one of them caused. Unfortunatly the timeline in the Google Chrome developer tools only showed the order of the timer execution together with the timer ID. That IDs are created by each JavaScript setInterval() and setTimeout call. But just the ID doesn’t help much. So I rewrote the prototype of both the setTimeout and setInterval functions:

<script type="text/javascript">

window._oldTimeOut = window.setTimeout;
window.setTimeout = function(execute, timeout) {
  var id = window._oldTimeOut(execute, timeout);
  console.debug("created timer with id:", id, arguments.callee.caller.toString());
  console.debug('execute',execute.toString());
  return id;
};

window._oldInterval = window.setInterval;
window.setInterval = function(execute, timeout) {
  var id = window._oldInterval(execute, timeout);
  console.debug("created interval with id:", id, arguments.callee.caller.toString());
  console.debug('execute',execute.toString());
  return id;
};

</script>

This gave me at least a hint where the sourcecode lines of the timer-executed code can be found. Also very helpful is a stack trace (aka call stack) at the current code position to find out which other function was calling the current one. I found a pretty old but still working code snippet on http://helephant.com/2007/05/diy-javascript-stack-trace/ and added it to my timer debugging:

<script type="text/javascript">

Function.prototype.trace = function() {
 var trace = [];
 var current = this;
 while(current) {
 trace.push(current.signature());
  current = current.caller;
 }
 return trace;
};

Function.prototype.signature = function() {
 var signature = {
  name: this.getName(),
  params: [],
  toString: function() {
   var params = this.params.length > 0 ?  "'" + this.params.join("', '") + "'" : "";
   return this.name + "(" + params + ")";
  }
 };
 if(this.arguments) {
  for(var x=0; x<this.arguments.length; x++)
   signature.params.push(this.arguments[x]);
 }
 return signature;
};

Function.prototype.getName = function() {
 if(this.name)
  return this.name;
 var definition = this.toString().split("\n")[0];
 var exp = /^function ([^\s(]+).+/;
 if(exp.test(definition))
  return definition.split("\n")[0].replace(exp, "$1") || "anonymous";
 return "anonymous";
};

window._oldTimeOut = window.setTimeout;
window.setTimeout = function(execute, timeout) {
 var id = window._oldTimeOut(execute, timeout);
 console.debug("created timer with id:", id);
 console.debug('execute',execute.toString());
 console.debug("stacktrace", arguments.callee.trace());
 return id;
};

window._oldInterval = window.setInterval;
window.setInterval = function(execute, timeout) {
 var id = window._oldInterval(execute, timeout);
 console.debug("created interval with id:", id);
 console.debug('execute',execute.toString());
 console.debug("stacktrace", arguments.callee.trace());
 return id;
};

</script>

Be sure to add that script tag at the very top of your JavaScript execution (as the first element of your <head> tag for example).

Tags:

Find UTF-8 byte order marks

In a templating application I just ran into ugly “” characters a the beginning of the text. This is caused by the byte order mark with the hex characters 0xEFBBBF. As it was not the only one file that contained the BOM I ran a search:

find . -iname '*.css' -o -iname '*.html' -o -iname '*.js' -o -iname '*.pm' -o -iname '*.pl' -o -iname '*.xml' | xargs grep -rl $'\xEF\xBB\xBF'

To remove the BOM I followed the suggested way by http://stackoverflow.com/questions/204765/elegant-way-to-search-for-utf-8-files-with-bom using sed:

find . -iname '*.css' -o -iname '*.html' -o -iname '*.js' -o -iname '*.pm' -o -iname '*.pl' -o -iname '*.xml' -exec sed 's/^\xEF\xBB\xBF//' -i.bak {} \; -exec rm {}.bak \;

Tada, no more ugly BOMs!

Optimize all PNG images recursively

Windows batch file syntax sometimes is a pain compared to UNIX bash/sh. Using optipng I wanted to shrink all the PNG images in a directory and inside its subdirectories as well. Notice that I had to write the command into a .bat batch file, it did not work directly from the command line:

FOR /F "tokens=*" %%G IN ('dir /s /b *.png') DO optipng -nc -nb -o7 -full %%G

The optipng params -nc and -nb prevent any color and color depth changes of the png files. Those may change the appearance, for example in the evil Internet Explorer. -o7 means the best and slowest optimization and -full does a full scan of the IDAT part. Using UNIX the same job may look like:

find . -name *.png | xargs optipng -nc -nb -o7 -full