Skip to content

fix(coverage): don't mark lines uncovered when zero-count range only partially overlaps#32601

Merged
bartlomieju merged 4 commits intomainfrom
fix/coverage-finally-block
Mar 15, 2026
Merged

fix(coverage): don't mark lines uncovered when zero-count range only partially overlaps#32601
bartlomieju merged 4 commits intomainfrom
fix/coverage-finally-block

Conversation

@bartlomieju
Copy link
Copy Markdown
Member

Summary

Fixes #13781finally blocks (and if condition lines) were incorrectly marked as uncovered when all branches in try/catch had return statements.

Root cause

The coverage line count algorithm has two phases:

  1. Phase 1: Find the innermost V8 range that fully encloses each line → use its count
  2. Phase 2: Reset count to 0 if any zero-count range merely overlaps the line (even partially)

For try/catch/finally with returns, V8 emits a tiny zero-count range (often just 1 character) representing the unreachable sequential path between catch's return and the finally keyword. Phase 2's partial-overlap check let this tiny range incorrectly zero out the finally { line — even though Phase 1 correctly found a larger enclosing range with count > 0.

The same bug affected if (cond) { lines where the false-branch zero-count range partially overlapped the condition line.

Fix

Phase 2 now uses the same full-enclosure criterion as Phase 1, and only overrides when the zero-count range is more specific (smaller) than the best range found in Phase 1.

Test plan

🤖 Generated with Claude Code

bartlomieju and others added 3 commits March 9, 2026 22:02
…partially overlaps

The coverage line count algorithm had two phases: Phase 1 found the
innermost range fully enclosing each line, and Phase 2 reset the count
to zero if any zero-count range merely *overlapped* (even partially)
the line. This caused lines like `if (cond) {` and `finally {` to be
falsely marked uncovered when a tiny zero-count range (e.g. the
unreachable gap between catch's return and finally) partially overlapped
them.

Fix Phase 2 to require the same full-enclosure criterion as Phase 1,
and only override when the zero-count range is more specific (smaller)
than the best range found in Phase 1.

Fixes #13781

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update the Phase 2 zero-count override to require the range reaches at
least one edge of the line. A zero-count range floating in the middle
(not touching start or end) is a V8 artifact (e.g. catch/finally gap)
and should not zero out the line. Update test expectations for
console.log with uncalled arrow fn — the line IS executed so marking it
covered is more correct.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Member

@nathanwhit nathanwhit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bartlomieju bartlomieju merged commit ad32e93 into main Mar 15, 2026
112 checks passed
@bartlomieju bartlomieju deleted the fix/coverage-finally-block branch March 15, 2026 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

deno coverage doesn't mark finally if try/catch have return statements

2 participants