Tuesday, February 18, 2014

Debugging Dart for Cool People


It's no secret that I am not a fan of IDEs, preferring instead the One True Editor. Having mucked around with the Dart Editor last night, I do envy the debugging ability of the Dart IDE. I have to admit that I have mostly resorted to console printing debugging of late in my Dart code, which is not at all cool. So the question before me is, can I do better debugging without the IDE?

To answer this question thoroughly, I start with a fresh install of Dart. I download archives into ~/Downloads and install things like Dart in ~/local. With that in mind, I grab the latest Dart Editor—I won't use it (much), but bandwidth is cheap and that archive includes the SDK and Dartium in addition to the editor:
$ cd ~/Downloads 
$ wget http://storage.googleapis.com/dart-archive/channels/stable/release/latest/editor/darteditor-linux-x64.zip
$ cd local/
$ rm -rf dart.old
$ mv dart dart.old
$ unzip -dc ~/Downloads/darteditor-linux-x64\ \(5\).zip
Archive:  /home/chris/Downloads/darteditor-linux-x64 (5).zip
   creating: c/dart/
   ...
  inflating: c/dart/editor.properties
  inflating: c/dart/chromium/download_file.dart
  inflating: c/dart/chromium/download_contentshell.sh
  inflating: c/dart/chromium/download_dartium_debug.sh
  inflating: c/dart/DartEditor.ini
I have no idea why “c” is now the top-level directory in the Dart Editor archive. My shell's $PATH expects things in ~/local/dart, so a quick:
$ mv c/dart .
$ rmdir c
And I have the latest version of things ready to roll.

In last night's IDE-generated code, I run pub serve to start the local development HTTP server. Then I fire up ~/local/dart/chromium/chrome. If I were debugging a JavaScript Polymer, I might add a debugger statement to a problem method:
@CustomTag('hello-you')
class HelloYou extends PolymerElement {
  // ...
  feelingLucky() {
    debugger; // THIS WON'T WORK!!!
    var num = new Random().nextInt(colors.length);
    shadowRoot.
      query('h2').
      style.color = colors[num];
  }
}
That does not fly in Dart, however. If I trigger that method, I will get:
Uncaught Error: Class 'HelloYou' has no instance getter 'debugger'.

NoSuchMethodError : method not found: 'debugger'
Receiver: Instance of 'HelloYou'
Arguments: []
This saddens me, if only a little. I realize that the Dart lifestyle is optimized for Dart Editor and, as such, mavericks like myself have to do a little extra work, but still. When I test in Dart, I can mark a single test to run with code (solo_test). It would be nice to do the same when debugging. Since I can't…

I open up the Developer Console and choose the “Sources” tab:



I type the suggested Ctrl+O to open a source file and find hello_you.dart, the backing class behind my <hello-you> Polymer:



In there, I click the line number on which I want to break:



Finally, I trigger the feelingLucky() method in there to find…

Nothing.

The code works just like normal and I am not seeing and debugger / breakpoint kicking in. This is what the dart/chromium/download_dartium_debug.sh script in the Dart Editor archive does. Be warned, it takes a looooong time to do its thing. I run it from the install directory:
$ cd ~/local/dart/chromium 
$ ./download_dartium_debug.sh 
Downloading http://dartlang.org/editor/update/channels/stable/32314/dartium/dartium-linux-x64-debug.zip to dartium-linux-x64-debug.zip.
And then it just sits there. For 10 minutes. My network monitor indicates that I am getting roughly 1 MB/s download speed on this, but it still takes a full 10 minutes before I see:
Download finished.
With that, I have to stop and restart Dartium. Now when I trigger the feelingLucky() method, I get the desired break:



What is nice here is that I am not just using the JavaScript debugger, but a full fledged Dart debugger. It is aware of the variables in my current scope as well as the current call stack:



Just like in the JavaScript debugger, I can click different points in the stack trace to see and interact with the variables that are in scope at those points:



Like any debugger, I can step over, in, and out of the current method. If I step over the random assignment of num, I see the value change in the list of scope variables. Better yet, I can interact with it in the JavaScriptDart Console. In fact, not only can I interact with it, but I can execute arbitrary Dart code here to truly debug my Polymer:



That is awesome. I have editor feature envy no more, because I have the full power of Chrome's debug tool—for Dart.


Day #1,030

2 comments:

  1. Seems that http://dartlang.org/editor/update/channels/stable/32314/dartium/dartium-linux-x64-debug.zip does not exist any more... I havn't found any replacement for the debbuging

    ReplyDelete
    Replies
    1. Yes, this is quite annoying. There hasn't even been activity on the bug, which is disappointing: https://code.google.com/p/dart/issues/detail?id=18977

      Delete