JavaScript code coverage

Published · Tagged with internals

Code coverage provides information about whether, and optionally how often certain parts of an application have been executed. It’s commonly used to determine how thoroughly a test suite exercises a particular codebase.

Why is it useful? #

As a JavaScript developer, you may often find yourself in a situation in which code coverage could be useful. For instance:

  • Interested in the quality of your test suite? Refactoring a large legacy project? Code coverage can show you exactly which parts of your codebase is covered.
  • Want to quickly know if a particular part of the codebase is reached? Instead of instrumenting with console.log for printf-style debugging or manually stepping through the code, code coverage can display live information about which parts of your applications have been executed.
  • Or maybe you’re optimizing for speed and would like to know which spots to focus on? Execution counts can point out hot functions and loops.

JavaScript code coverage in V8 #

Earlier this year, we added native support for JavaScript code coverage to V8. The initial release in version 5.9 provided coverage at function granularity (showing which functions have been executed), which was later extended to support coverage at block granularity in v6.2 (likewise, but for individual expressions).

Function granularity (left) and block granularity (right)

For JavaScript developers #

There are currently two primary ways to access coverage information. For JavaScript developers, Chrome DevTools’ Profiler.getBestEffortCoverage().

Behind the scenes #

As stated in the previous section, V8 supports two main modes of code coverage: best-effort and precise coverage. Read on for an overview of their implementation.

Best-effort coverage #

Both best-effort and precise coverage modes heavily reuse other V8 mechanisms, the first of which is called the invocation counter. Each time a function is called through V8’s Ignition interpreter, we collect the source range of the then and else branches and associate them with the parsed IfStatement AST node. The same is done for other relevant language constructs.

After collecting source range collection during parsing, the second aspect is tracking execution counts at runtime. This is done by

Except as otherwise noted, any code samples from the V8 project are licensed under the Creative Commons Attribution 3.0 License. For details, see our site policies.

Follow Lee on X/Twitter - Father, Husband, Serial builder creating AI, crypto, games & web tools. We are friends :) AI Will Come To Life!

Check out: eBank.nz (Art Generator) | Netwrck.com (AI Tools) | Text-Generator.io (AI API) | BitBank.nz (Crypto AI) | ReadingTime (Kids Reading) | RewordGame | BigMultiplayerChess | WebFiddle | How.nz | Helix AI Assistant