Links

pmuellr is Patrick Mueller

other pmuellr thangs: home page, twitter, flickr, github

Thursday, June 04, 2009

debugger friendly

(this is a bit of a followup to my previous blog post - "debugging")

Hit a milestone yesterday, submitting my first patch to WebKit, in support of "Bug 25474: Show the filename and first line for '(program)' in the Profiler/Debugger". The patch provides the same support that Firefox provides to allow JavaScript eval() invocations and Function() constructor invocations to name the code they are injecting into the environment, by adding a comment to the source interpreted:

//@ sourceURL=some-url-goes-here

Presumably some-url-goes-here is replaced in your source by some kind of moniker that will be useful to you.

Why is this useful? Here's what your "list of scripts" looks like when developing a Dojo app, without this support: [link]; here's what it looks like with this support: [link]. A little more useful.

Last month, another interesting feature for debugging was added to WebKit - the ability to 'name' anonymous functions, after they've been created. A full description of this, and the value it provides, was written up a blog entry "Building a Better JavaScript Profiler with WebKit". In a nutshell, you can add a property displayName to a function which will be used as it's name in the debugger and profiler if the function doesn't otherwise have a name.

Quick notes:

  • the sourceURL feature is not yet committed to WebKit, and even if/when it is, would only be available in WebKit nightlies.
  • the displayName feature is only available in WebKit nightlies right now.
  • the sourceURL feature does not currently work with the WebKit profiler, just the debugger.
  • the displayName feature works in the WebKit profiler and debugger.
  • Firefox supports (and invented!) the sourceURL feature, but AFAIK does not support the displayName feature.
  • Dojo currently has support for sourceURL feature, but only if you're running in a Mozilla-based browser - chime in here for WebKit support.
  • Dojo has no support for the displayName feature - chime in here on that issue.

enhanced object display

Here's what I'm going to look into next:

In the WebKit bug, "Bug 25724: Incorrect collection output for Javascript console evaluation", the reporter claims that the output when displaying the result of a jQuery function invocation is incorrect. Incorrect isn't fair; it's better to say that it's not what the user expected, but then, as jjb mentions in comment #6, "we can't read [the user's] mind".

It's certainly true that the current output isn't useful, and it's certainly the case that the developer of a debugger can't read a user's mind, so the obvious answer is to let the user decide how to see their output. In Smalltalk, the debugger would call debugPrintOn: instead of the more typical printOn: method (printOn: being analogous to toString in Java or JavaScript). This allowed developers to provide a debug-friendly version of the human-readable representation of an object, without impacting runtime code. JavaScript debuggers should do the same thing.

The other bit that needs to be done is to somehow augment the "properties" that you see associated with an object in the debugger. Literally what you see in the debugger is the implementation goop of an object. Not terribly useful, especially if values associated with objects are computed lazily, via a function invocation. Seeing a function instead of perhaps the lazily computed value provides little value (though it is obviously much safer!).

What I'd like to do is provide an optional method on a function which can be called to obtain "debug properties". For instance, the debug properties for a jQuery object might return the array of matching DOM elements. DOM elements themselves might return, instead of the goop currently returned, their parent DOM object, their children, and their next/previous siblings. These DOM element's might have a "debug toString" that actually showed the HTML representation of the node (which the debuggers already support in some cases).

Of course feel free to post additional ideas on this to the existing but report.

soundpoints

Here's something I did back in the Smalltalk days; would be fun to do this for JavaScript as well:

We all know what breakpoints are, but I extended the concept in Smalltalk with soundpoints (stole the idea from somewhere). Instead of having the debugger pause the execution of the program when a breakpoint is reached, the debugger would play a sound when a soundpoint is reached. The nice thing about this capability is that you get some feedback without having to stop your program. You can set soundpoints to let you know when you venture into code you're not expecting to venture into (some kind of beep/boop), or set a very short blip sound for a soundpoint you expect to hit a lot - giving you a kind of geiger counter. Since WebKit already has programmatic support for playing audio, the "hard" part of this is already done. What's needed is to integrate into the debugger framework. OK, that is the hard part.

As sort of a side issue, when I did this in Smalltalk, I was able to do this with user-land code; I didn't need to be some kind of core developer to get the function added. That's not true today in WebKit. You need to modify existing WebKit code to add functionality like this; there's no simple way of me just adding it to my environment. That would be a nice thing then also, having a way of extending the debugging environment through plugins or equivalent. See "Bug 24273: Inspector Plugins or Extend Capability". Also note that I believe FireFox has or will have the ability to extend FireBug via plugins. I think it's too much to ask to have portable plugins, at this point, but something to think about.

what else

What else can we do beyond all that? What are your frustrations with JavaScript debugging?

2 comments:

Unknown said...

When we built the Smalltalk debugger - we added the ability to do conditional breakpoints. The simplest manner to do this was to allow the execution of some Smalltalk code (a doit) that would return true or false indicating if execution should stop at this breakpoint. This was very handy for some tricky bugs.

Of course - since you're running a doit - then anything can happen, including side-effects. So it became possible to use debugger breakpoints to extend the environment.

The key technologies here:
a) Ability to inject arbitrary "bits" of code in the context of your application.
b) Debugger hook that supports conditional breakpoints using (a) to trigger the condition

Patrick Mueller said...

I believe this is how I implemented my "soundpoints". Thanks for the reminder.