Aardwolf

Aardwolf is a remote JavaScript debugger for iPhone / Android / WindowsPhone 7 / BlackBerry OS 6+. It is written in JavaScript.

This is experimental software. Although it has been successfully tested with a JavaScript project consisting of more than 20.000 lines of code, it should not be considered a finished product. The edges are more than just a bit rough: the UI is clunky, you set breakpoints by entering JavaScript arrays into a text field, and it breaks completely if you don’t do everything just right.

If you’re careful, though, you get to play with the following features:

  • breakpoints
  • code evaluation at breakpoint
  • “break on next” breakpoints
  • step/continue execution control
  • exception reporting (also in async calls)
  • JavaScript console remoting
  • call stack listing

If you want to try it out, you can get the code on GitHub.

Sit back, relax, and watch this

Here’s a poorly made video with no sound showing it in action. The window on the left is Firefox running the Aardwolf UI and the window on the right is an instance of the Android emulator.

Please note that because WebKit does not redraw the page until the end of the runloop, the Google home page is still visible at the beginning of the video while another script is already running in the browser!

Try debugging the example script from the video

  • Begin by installing node.js and either Mercurial or Git
  • Get the Aardwolf source code
    using Mercurial: hg clone https://bitbucket.org/lexandera/aardwolf
    using Git: git clone git://github.com/lexandera/Aardwolf.git
  • Create the file config/config.local.js and paste into it the following lines:

var config = require('../config/config.defaults.js');
config.serverHost = 'ip-or-hostname-of-your-computer';

  • Start the server by running “node app.js
  • After the server starts up, open http://localhost:8000 in your desktop browser. The debugger UI should appear.
  • Open http://ip-or-hostname-of-your-computer:8500/calc.html on your phone and wait for the page to load. The line “Mobile device connected.” should appear in the UI’s output pane.
  • You’re now debugging the “calculator” example script.

If you’re having problems opening the example, make sure that access to the port 8500 on your computer is not blocked by a firewall and that the address you entered into the config file can really be accessed from your phone. This is where your phone will load the samples from, so it must work. You will get best results by connecting both you computer and your phone to the same WiFi network.

Debugging your own code

The procedure is the same as above, except:

  • Put the following in your config/config.local.js file:

var config = require('../config/config.defaults.js');
config.serverHost = 'ip-or-hostname-of-your-computer';
config.jsFileServerBaseDir = '/path/to/www/root';

Start or restart the server for changes to take effect.

  • In your HTML page include the aardwolf.js debug library as the very first JS file and change the paths of included files to point to the files modified by Aardwolf:

<script src="http://ip-or-hostname-of-your-computer:8500/aardwolf.js" type="text/javascript"></script>
<script src="http://ip-or-hostname-of-your-computer:8500/some-script.js" type="text/javascript"></script>
<script src="http://ip-or-hostname-of-your-computer:8500/dirname/some-other-script.js" type="text/javascript"></script>

  • Reload the debugger UI first, then reload the page you just modified. The line “Mobile device connected.” should appear in the UI’s output pane.
  • You should now be able to evaluate code remotely, set breakpoints, etc.

Debugging processed or minified code

If you wish to debug code which gets concatenated into a single file, minified, or transformed in some other way, you can still use Aardwolf, but you’ll need to make a minor change in the part of your application which reads the code before it gets transformed.

It is important that Aardwolf can access source files before they are processed. Therefore you will need to set it up just as described in the previous section, with the ‘-d’ parameter pointing to the directory containing unprocessed files, then change the processing code in you application so it reads files served by Aardwolf instead of reading them straight from the filesystem.

For example, if your code looks something like this:

jscode += readFile('some-script.js');
jscode += readFile('some-other-script.js');

you would need to change it to something like this:

jscode += readFile('http://aardwolf-host:8500/aardwolf.js'); /* Don't forget to include this! */
jscode += readFile('http://aardwolf-host:8500/some-script.js');
jscode += readFile('http://aardwolf-host:8500/some-other-script.js');

In most languages, making the modification should be pretty straightforward. PHP’s file_get_contents($url) and Clojure’s (slurp url) will handle the change from local paths to URLs transparently. In Scala you can use io.Source.fromURL(url).mkString, Ruby has the ‘OpenURI’ module and in NodeJS you should be able to read remote files using the ‘request’ module.

Now you should be ready to debug processed code. And since Aardwolf has access to the original files, its UI will display the original, unprocessed code for easier debugging.

How it works (and I’m using the term “works” very loosely here)

Breaking code execution and evaluating code at that point is enabled by code rewriting. Aardwolf’s server contains a rather simple code rewriter which inserts debug hooks in front of every statement in the source code. These debug statements look like this:


Aardwolf.updatePosition(
    "/calc.js", // File path
    7,          // Line number
    false,      // Is current line a "debugger;" statement?
    function(aardwolfEval) {       // This closure captures the current scope and makes it
        return eval(aardwolfEval); // possible to pass it into another function.
    }
);

The first two parameters – file path and line number – should be self explanatory. Every time Aardwolf.updatePosition() is called, the given file and line number are checked against a list of breakpoints, and if a match is found, script execution is halted by performing a synchronous XMLHttpRequest to the server.

The third parameter signals whether the current line contains a “debugger;” statement. If it does, we must break execution even if there is no breakpoint set on that line.

Finally, the last parameter is a closure which captures the scope it’s defined in and allows us to pass it around. When a string is passed to this function for evaluation, it will be eval’d in the same scope where this closure was defined, thus enabling us to evaluate code at the point where script execution was halted.

Pretty simple and straightforward, right?

Misc

Fork me on GitHub

2 Responses to “Aardwolf”

  1. Useful Coding Tools and JavaScript Libraries For Web Developers | Smashing Magazine

    [...] Aardwolf: Remote JavaScript DebuggerMobile browsers are becoming more powerful day-by-day and you can do almost everything you do on your desktop browser. One of the major concerns for the developers is the lack of developer tools. The reasons are quite obvious — real estate needed to show the debugger, non-developer friendly environment. The solution to this problem is remote debugging. You can use JSConsole for this purpose but when it comes to JavaScript debugging, Aardwolf is a better choice. Aardwolf is a JavaScript debugger for iPhone / Android / WindowsPhone 7 / BlackBerry OS 6+. (via Varun Kumar) [...]

  2. weinre: el Firebug para móviles

    [...] weinre no permite depurar javascript línea a línea. Existen alternativas que sí permiten depurar javascript de forma remota, pero son bastante más intrusivas y complicadas de [...]