Stupid JavaScript debugging tricks: Abusing the conditional breakpoint


Your favorite JavaScript debugger may very well have a conditional breakpoint facility, and if it does, you can abuse it to do things unrelated to conditional breakpoints.

Since conditional breakpoints are based on evaluating an expression, you can use an expression with side effects, like, say, logging.

Breakpoint Condition

When the breakpoint location is reached, the expression is evaluated and the breakpoint is hit only if the expression is true or has changed.

Condition:
console.log("click received")
ⵙ Is true
ⵔ Has changed

OK Cancel

The console.log function returns undefined, so the condition is never true, but that's okay, because we're executing the expression for its side effect of printing a string to the console.

Here, we just logged a hard-coded string, but you can log any expression you want. For example, you could use

console.log("current selection is " + this.currentSelection)

Or even more fun:

console.log(getStack())

where you've defined

function getStack() { try { throw new Error(); } catch (e) { return e.stack; } }

What, you didn't define that function? No problem. Just evaluate it in your immediate window and boom, now it's defined.

Now, printing an entire stack trace may be excessive. So store it in your object for future inspection. For example, you might do this in a constructor so that you have a stack trace of how your object got created. That way, when you have a transaction that failed to complete, you can look at the cached stack trace to see how the transaction got started.

(this._stack = getStack()) === 42

The extra === 42 at the end is to ensure that the value of the expression is falsy.

Anyway, just a few quick tips for JavaScript debugging. I didn't come up with these ideas, but I'm sharing them.

Comments (22)
  1. Mr Cranky says:

    Well, not being a Javascripter, I falsely assumed "falsy" was a possible typo or coinage.  The truthiness of that turned out to be falsy.

  2. John Ludlow says:

    @Mr Cranky the idea of values being falsy exists outside JavaScript. C++, for example, has nulls that can (kinda, sorta) be considered false.

  3. Dan Bugglin says:

    Chrome allows you to edit JavaScript inline, so in some cases you may find you can just add code inline.

    If you map urls to local disk files properly in the Dev Tools settings you can even Ctrl+S to save your changes back to disk.

    I think there are cases where inline edit doesn't take effect on existing running code, so good trick still!

  4. Adam Rosenfield says:

    My computer doesn't have a font with Tifinagh glyphs in it, so I just see boxes for those TIFINAGH LETTER YAS and TIFINAGH LETTER YAR.  Why not use ◉ (FISHEYE) and ◯ (LARGE CIRCLE) or similar instead?  Or, just raw HTML input elements, as you have in the past?

    [I stopped using raw HTML elements because they interfered with forms on the page. Will investigate the alternate glyphs. -Raymond]
  5. GrumpyOldMan says:

    @Adam Rosenfield: Why not write your own blog that out of the goodness of your heart shares incredibly useful information to a wide audience?

  6. bzakharin says:

    I assume a lot of this can be useful in other debuggers too. Not declaring new functions, but logging results or changing random values

  7. Adam Rosenfield says:

    @GrumpyOldMan: My tone there probably came across there as too harsh.  I like to nitpick about Unicode (as Raymond may or may not have noticed over the years).

    @Raymond: Thanks as always for your non-stop blog posts.  I'm always amazed at your ability to construct faithful representations of windows, dialog boxes, etc. out of HTML+CSS, even when there's the occasional glitch like using characters not contained in some system default fonts.  I've always wondered how much time you spend making those, since I know if I tried to make those, I'd spend a lot of time agonizing over every pixel.  (Then again, I've had a lot less practice than you've had.)

  8. Torkell says:

    Executing code in breakpoint conditions is a useful little trick. I've often ended up using that with Java to log object state, particularly when the traditional method of an unconditional breakpoint would break things (by making other parts of the program - or indeed other programs on the far end of a network connection - complain about timeouts).

  9. Stuart Langridge says:

    Raymond, thank you for this rather neat trick; I'd never thought of this, and shall put it to use. Would that I could offer Win32 tips that you don't know in return!

  10. Vilx- says:

    Tiny additional trick for the stacktrace - there's also "console.trace()" method in modern browsers, which prints out a neatly formatted stack trace. It might not be useful for including in end-user code due to browser compatibility issues, but on your own development machine it's a lot easier to type (and remember) than the "new Error()" thing. :)

  11. Simon says:

    I was intrigued to discover some years back that the remote debugging APIs built into the Java runtime were well documented public interfaces. And while they're obviously intended for building debugger apps, IDE integration, etc, it's actually a pretty useful mechanism for logging code that doesn't contain logging, or which would produce too much of it to be useful. I had a little program that set up one breakpoint at the top of a complex block of code, which when triggered, activated several other breakpoints which did nothing but log the internal state. Obscure, but surprisingly useful˙

  12. cheong00 says:

    [I stopped using raw HTML elements because they interfered with forms on the page. Will investigate the alternate glyphs. -Raymond]

    Maybe adding:

      jQuery(document).ready(function() { jQuery("INPUT[type=radio]").appendTo(jQuery("BODY"); })

    will do the trick to move these radio buttons out of the forms and prevent it interfere with submission.

    I see jQuery-1.5.2 here. Use full form instead of "dollar sign" because I'm not sure if it'll interfere with other library.

    [That doesn't work with my workflow because I don't write these articles directly on the Web site. My authoring system doesn't run script and doesn't come with jQuery. -Raymond]
  13. cheong00 says:

    Oops, one missing ")" after the "BODY", and the line should end with semicolon.

  14. cheong00 says:

    One more thing, to make it stay into place while viewing, maybe it's better to move to out on handler of jQuery("#aspnetForm").submit()

  15. Neil says:

    Surely that's a solved problem, otherwise the search and translate widgets wouldn't work.

  16. Neil says:

    Oh, and why not use the `void` operator to make any expression falsy?

  17. Petr Kadlec says:

    I (mis)used conditional breakpoints in the same way when debugging C# code. However, new Visual Studio does not allow that anymore it seems.

  18. Andrey Roenko says:

    > (this._stack = getStack()) === 42

    I believe comma or void operators would be better.

    this._stack = getStack(), false

    void (this._stack = getStack())

  19. Josh says:

    FYI there's no need for the try/throw/catch in getStack.

       return new Error().stack;

    Will suffice.

  20. Mark says:

    I wish the Visual Studio C++ debugger could do that! (Though edit and continue is just as good I guess.)

  21. Mark says:

    Did notepadconf actually take place?

  22. Tim says:

    "Oh, and why not use the `void` operator to make any expression falsy?"

    Came here to say this. Most people who use JavaScript don't know about the void operator.

Comments are closed.

Skip to main content