A list of useful, not-obvious hacks to get the most out of your browser’s1 debugger. Assumes an intermediate-level-or-higher understanding of the developer tools.
Advanced Conditional Breakpoints
By using expressions that have side effects in places you wouldn’t expect, we can squeeze more functionality out of basic features like conditional breakpoints.
Logpoints / Tracepoints
For example, we can console.log in breakpoints.
Logpoints are breakpoints that log to the console without
pausing execution. While Microsoft Edge has had logpoints
built-in for a while and Chrome just added them in v73,
Firefox does not. But, we can use conditional breakpoints to
simulate them in any browser.
Use console.count instead of
console.log if you also want a running count of
how many times the line is executed.
UPDATE (May 2020): All the major browsers now directly support logpoints/tracepoints (Chrome Logpoints, Edge Tracepoints, Firefox Logpoints)
Watch Pane
You can also use console.log in the watch pane.
For example, to dump a snapshot of
localStorage everytime your application pauses
in the debugger, you can create a
console.table(localStorage) watch:
Or to execute an expression after DOM mutation, set a DOM
mutation breakpoint (in the Element Inspector):
And then add your watch expression, e.g. to record a
snapshot of the DOM:
(window.doms = window.doms ||
[]).push(document.documentElement.outerHTML). Now, after any DOM subtree modification, the debugger
will pause execution and the new DOM snapshot will be at the
end of the window.doms array. (There is no way
to create a DOM mutation breakpoint that doesn’t pause
execution.)
Tracing Callstacks
Let’s say you have a function that shows a loading spinner
and a function that hides it, but somewhere in your code
you’re calling the show method without a matching hide call.
How can you find the source of the unpaired show call? Use
console.trace in a conditional breakpoint in
the show method, run your code, find the last stack trace
for the show method and click the caller to go to the code:
Changing Program Behavior
By using expressions that have side effects on program behavior, we can change program behavior on the fly, right in the browser.
For example, you can override the param to the
getPerson function, id. Since
id=1 evaluates to true, this conditional
breakpoint would pause the debugger. To prevent that, append
, false to the expression.
Quick and Dirty Performance Profiling
You shouldn’t muddy your performance profiling with things
like conditional breakpoint evaluation time, but if you want a
quick and dirty measurement of how long something takes to
run, you can use the console timing API in conditional
breakpoints. In your starting point set a breakpoint with the
condition console.time('label') and at
the end point set a breakpoint with the condition
console.timeEnd('label'). Everytime the
thing you’re measuring runs, the browser will log to the
console how long it takes.
Using Function Arity
Break on Number of Arguments
Only pause when the current function is called with 3
arguments: arguments.callee.length === 3
Useful when you have an overloaded function that has optional parameters.
Break on Function Arity Mismatch
Only pause when the current function is called with the
wrong number of arguments:
(arguments.callee.length) != arguments.length
Useful when finding bugs in function call sites.
Using Time
Skip Page Load
Don’t pause until 5 seconds after page load:
performance.now() > 5000
Useful when you want to set a breakpoint but you’re only interested in pausing execution after initial page load.
Skip N Seconds
Don’t pause execution if the breakpoint is hit in the next 5
seconds, but pause anytime after:
window.baseline = window.baseline || Date.now(),
(Date.now() - window.baseline) > 5000
Reset the counter from the console anytime you’d like:
window.baseline = Date.now()
Using CSS
Pause based on computed CSS values, e.g. only pause execution
when the document body has a red background color:
window.getComputedStyle(document.body).backgroundColor ===
"rgb(255,0,0)"
Even Calls Only
Only pause every other time the line is executed:
window.counter = (window.counter || 0) + 1, window.counter
% 2 === 0
Break on Sample
Only break on a random sample of executions of the line, e.g.
only break 1 out of every 10 times the line is executed:
Math.random() < 0.1