Report bundler-eliminated (tree-shaken) functions as uncovered - #27
Merged
NullVoxPopuli merged 1 commit intoAug 7, 2026
Merged
NullVoxPopuli merged 1 commit into
NullVoxPopuli merged 1 commit into
Conversation
An unexported, unreferenced function is tree-shaken by rollup/vite: no compiled code exists, so V8 never sees it, the source map has no segments for its lines, and v8-to-istanbul defaults those lines to covered — a false positive (second report on issue NullVoxPopuli#22, where an unusedTestFunction in a service and a top-level unusedNonClassFunction in a component both showed as 100% covered). The report step now records which original-source lines have at least one mapping segment in any bundle's source map, parses each reported original file with acorn, and collects function-like declaration spans (function/class declarations, function/arrow variable initializers). A span with no mapped lines anywhere was eliminated from the build; its statement counts are zeroed and an uncovered function entry is added. Spans with even one mapped line are left to the existing V8-data and synthetic-method paths. To make original .gjs/.gts app files parseable by acorn, template tags are blanked to an offset-preserving "0" placeholder and decorators are blanked to spaces; any file that still fails to parse is skipped rather than guessed at. The vite-app-using-v2-addon-js scenario now contains both shapes from the issue report — unusedTestFunction in app/services/store.js and unusedNonClassFunction in app/components/counter.gjs — with regression assertions that they are reported as uncovered. Fixes the remaining false positives from NullVoxPopuli#22 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
NullVoxPopuli
approved these changes
Aug 7, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the remaining false positives from #22 (jagthedrummer's follow-up comments:
unusedTestFunctionin the store service and a top-levelunusedNonClassFunctionin a component both still showed as covered).Root cause
Both functions are unexported and unreferenced, so rollup/vite tree-shakes them out of the build entirely — the bundles are byte-identical with or without them (the names only survive in
.mapsourcesContent). With no compiled code, V8 never sees them, the source map has no segments for their lines, and v8-to-istanbul defaults unmapped original lines to covered. Not platform-specific this time — reproduced on Linux with the exact shapes from the screenshots.Fix
While processing each bundle, the report now records which original-source lines have at least one source-map segment. After merging, each reported original file is parsed with acorn and function-like declaration spans are collected (function/class declarations, function/arrow variable initializers). A span with no mapped lines in any bundle was eliminated by the bundler: its statement counts are zeroed and an uncovered function entry is added. A span with even one mapped line is left alone — the bundle kept it, so real V8 data (or the synthetic-method pass) already decides its coverage.
To parse original
.gjs/.gtsfiles,<template>…</template>spans are blanked to an offset-preserving0placeholder and decorators (@tracked,@action('x'), …) are blanked to spaces — parse-validity is all that matters. Files that still fail to parse are skipped rather than guessed at.Scenario changes
vite-app-using-v2-addon-jsnow contains both shapes from the issue report, replicated from the screenshots:app/services/store.js—unusedTestFunction()(unexported, never called)app/components/counter.gjs—unusedNonClassFunction()(top-level, outside the class)Before this fix both reported 100% covered; now store.js reports 0/1 functions with its lines uncovered, and counter.gjs reports the function uncovered alongside the two never-called class methods. Regression assertions added for both, plus the store.js entry itself.
All 22 tests across the three scenarios pass, lint clean.
🤖 Generated with Claude Code