The V8CoverageProvider class is the core implementation of the coverage workflow. It processes raw V8 coverage data, converts it to Istanbul format using AST-based remapping, handles source maps, generates coverage reports, and validates coverage thresholds.
import { V8CoverageProvider } from '@vitest/coverage-v8/provider';Note: The provider is typically instantiated via the getProvider() method of the coverage module, not imported directly.
class V8CoverageProvider extends BaseCoverageProvider<ResolvedCoverageOptions<'v8'>> {
/** Provider identifier */
readonly name: 'v8';
/** Version of the coverage provider package */
version: string;
/**
* Initialize the provider with Vitest context
* @param ctx - Vitest instance
*/
initialize(ctx: Vitest): void;
/**
* Create an empty Istanbul coverage map
* @returns Empty CoverageMap instance
*/
createCoverageMap(): CoverageMap;
/**
* Generate coverage map from collected V8 coverage data
* @param options - Report context with metadata
* @returns Promise resolving to Istanbul CoverageMap
*/
generateCoverage(options: ReportContext): Promise<CoverageMap>;
/**
* Generate coverage reports in configured formats
* @param coverageMap - Istanbul coverage map with coverage data
* @param allTestsRun - Whether all tests were run
* @returns Promise that resolves when reports are generated
*/
generateReports(coverageMap: CoverageMap, allTestsRun?: boolean): Promise<void>;
/**
* Parse a configuration module file using magicast
* @param configFilePath - Path to configuration file
* @returns Promise resolving to proxified module
*/
parseConfigModule(configFilePath: string): Promise<ProxifiedModule<any>>;
}Initializes the provider with the Vitest context and configuration.
/**
* Initialize the provider with Vitest context.
* This method is called by Vitest before tests run. It stores the context
* and performs version compatibility checks.
*
* @param ctx - Vitest instance containing configuration and logger
*
* @example
* import { V8CoverageProvider } from '@vitest/coverage-v8/provider';
*
* const provider = new V8CoverageProvider();
* provider.initialize(vitestContext);
*/
function initialize(ctx: Vitest): void;Behavior:
_initialize method sets up:
Version Check: Warns if running mixed versions of vitest and @vitest/coverage-v8, which may cause bugs.
Creates an empty Istanbul coverage map instance.
/**
* Create an empty Istanbul coverage map.
* Coverage maps store file coverage data in Istanbul format and provide
* methods for merging, filtering, and querying coverage.
*
* @returns Empty CoverageMap instance from istanbul-lib-coverage
*
* @example
* const coverageMap = provider.createCoverageMap();
* coverageMap.merge(otherCoverageMap);
* const files = coverageMap.files(); // Get list of covered files
*/
function createCoverageMap(): CoverageMap;Returns:
Empty Istanbul CoverageMap instance that can be populated with coverage data.
CoverageMap Methods:
files(): Get array of covered file pathsfileCoverageFor(filename): Get coverage for specific filemerge(otherMap): Merge another coverage map into this onefilter(predicate): Filter files based on predicate functionGenerates a complete coverage map from collected V8 coverage data.
/**
* Generate coverage map from collected V8 coverage data.
* This is the main coverage processing method that:
* 1. Reads coverage files from disk
* 2. Merges coverage data from multiple test runs
* 3. Converts V8 coverage to Istanbul format
* 4. Applies source map transformations
* 5. Includes untested files if configured
* 6. Filters results based on include/exclude patterns
*
* @param options - Report context
* @param options.allTestsRun - Indicates whether all tests were run.
* If false, only specific tests were run (e.g., --changed).
* Affects whether untested files are included.
* @returns Promise resolving to Istanbul CoverageMap with complete coverage data
*
* @example
* const coverageMap = await provider.generateCoverage({
* allTestsRun: true
* });
*
* console.log(`Covered ${coverageMap.files().length} files`);
*/
function generateCoverage(options: ReportContext): Promise<CoverageMap>;Parameters:
options.allTestsRun: Boolean indicating if all tests ran (vs. subset of tests)Behavior:
@bcoe/v8-coverage to merge coverage from multiple test runsstartOffset is not lost during mergingistanbul-lib-source-mapsinclude is configured and either all tests ran or cleanOnRerun: false)excludeAfterRemap: true)Processing Flow:
Raw V8 Coverage Files
↓
Merge (handle multiple test runs)
↓
Convert (V8 → Istanbul per project)
↓
Source Map Transform
↓
Merge into CoverageMap
↓
Add Untested Files
↓
Filter & Apply Exclusions
↓
Final CoverageMapPerformance:
processingConcurrency optionMath.min(20, os.availableParallelism?.() ?? os.cpus().length)Returns:
Istanbul CoverageMap containing coverage for all files.
Generates coverage reports in all configured formats.
/**
* Generate coverage reports in configured formats.
* Uses Istanbul reporters to generate coverage reports (text, html, json, lcov, etc.).
* Also validates coverage thresholds if configured.
*
* @param coverageMap - Istanbul coverage map with coverage data
* @param allTestsRun - Optional boolean indicating if all tests were run
* @returns Promise that resolves when all reports are generated
*
* @example
* const coverageMap = await provider.generateCoverage({ allTestsRun: true });
* await provider.generateReports(coverageMap, true);
* // Coverage reports now available in configured directory
*
* @example
* // With custom reporters in vitest config:
* // coverage: {
* // reporter: [['text'], ['html'], ['json', { file: 'coverage.json' }]]
* // }
* await provider.generateReports(coverageMap);
*/
function generateReports(
coverageMap: CoverageMap,
allTestsRun?: boolean
): Promise<void>;Parameters:
coverageMap: Istanbul coverage map with coverage dataallTestsRun: Optional boolean for threshold validationBehavior:
istanbul-reportsskipFull, projectRoot, custom options)Reporter Types:
text: Console output with coverage summaryhtml: HTML coverage report with drill-downjson: Machine-readable JSON coverage datalcov: LCOV format for CI/CD toolsclover: Clover XML formatReporter Options:
skipFull: Skip files with 100% coverageprojectRoot: Root directory for relative paths['html', { subdir: 'html-report' }]Threshold Validation:
If options.thresholds is configured, validates that coverage meets minimum requirements:
Parses a configuration file using magicast for programmatic manipulation.
/**
* Parse a configuration module file using magicast.
* This method is used internally for configuration analysis and manipulation.
*
* @param configFilePath - Absolute path to configuration file
* @returns Promise resolving to proxified module that can be programmatically manipulated
*
* @example
* const configModule = await provider.parseConfigModule('/path/to/vitest.config.ts');
* // Can now analyze or modify the config programmatically
*/
function parseConfigModule(configFilePath: string): Promise<ProxifiedModule<any>>;Behavior:
fs.readFilemagicast.parseModuleUse Case: Used by Vitest's configuration system for analyzing and potentially modifying configuration files programmatically (e.g., for threshold auto-update).
The provider uses ast-v8-to-istanbul for accurate V8 to Istanbul conversion:
Process:
vitest/node.parseAstAsyncAdvantages:
The provider ignores specific code patterns to avoid coverage noise:
Vite SSR Transformations:
__vite_ssr_import_* variables__vite_ssr_exports__ assignments__vite_ssr_export_default__ variables__vite_ssr_import_meta__ assignmentsCJS Imports:
__vite__cjsImport* ternary expressionsIn-Source Tests:
if (import.meta.vitest) blocks (SSR and web modes)Browser Mode:
import.meta.env assignmentsSWC Decorators:
_ts_decorate call expressionsThese patterns are excluded because they're added by the build tool, not user code.
The provider handles complex source map scenarios:
Vue Single File Components:
map.sources array is populatedMissing Source Maps:
Vite Transformations:
When coverage.include is configured, the provider can include untested files:
Process:
getUntestedFiles to find files matching include but not testedResult: Untested files show 0% coverage, making them visible in reports.
interface ReportContext {
/**
* Indicates whether all tests were run.
* False when only specific tests were run (e.g., --changed, single file).
* Affects whether untested files are included in the report.
*/
allTestsRun?: boolean;
}interface CoverageMap {
/**
* Get list of all covered file paths
* @returns Array of absolute file paths
*/
files(): string[];
/**
* Get coverage data for a specific file
* @param filename - Absolute file path
* @returns FileCoverage object with detailed coverage data
*/
fileCoverageFor(filename: string): FileCoverage;
/**
* Merge another coverage map into this one
* @param other - Coverage map to merge
*/
merge(other: CoverageMap): void;
/**
* Filter coverage map based on predicate
* @param predicate - Function that returns true to keep file
*/
filter(predicate: (filename: string) => boolean): void;
}
interface FileCoverage {
/** File path */
path: string;
/** Statement coverage map */
statementMap: Record<string, Range>;
/** Function coverage map */
fnMap: Record<string, FunctionMapping>;
/** Branch coverage map */
branchMap: Record<string, BranchMapping>;
/** Statement execution counts */
s: Record<string, number>;
/** Function execution counts */
f: Record<string, number>;
/** Branch execution counts */
b: Record<string, number[]>;
}/**
* Proxified module from magicast that allows programmatic manipulation
* of JavaScript/TypeScript configuration files
*/
type ProxifiedModule<T = any> = {
exports: T;
// Additional magicast proxy methods
};interface Vitest {
/** Vitest version */
version: string;
/** Logger instance */
logger: {
log: (message: string) => void;
warn: (message: string) => void;
error: (message: string, error?: unknown) => void;
};
/** Vitest configuration */
config: {
root: string;
// ... other config options
};
/** Coverage options (resolved) */
_coverageOptions: ResolvedCoverageOptions<'v8'>;
/** Get root project */
getRootProject(): TestProject;
}interface ResolvedCoverageOptions<T extends 'v8' | 'istanbul'> {
/** Coverage provider type */
provider: T;
/** Enable coverage collection */
enabled: boolean;
/** Glob patterns for files to include */
include?: string[];
/** Glob patterns for files to exclude */
exclude: string[];
/** Directory for coverage reports */
reportsDirectory: string;
/** Reporter configurations */
reporter: CoverageReporterWithOptions[];
/** Clean coverage before running tests */
clean: boolean;
/** Clean coverage on watch mode rerun */
cleanOnRerun: boolean;
/** Skip files with 100% coverage */
skipFull?: boolean;
/** Coverage thresholds */
thresholds?: Record<string, any>;
/** Watermarks for coverage levels */
watermarks?: {
statements?: [number, number];
functions?: [number, number];
branches?: [number, number];
lines?: [number, number];
};
/** Generate report even when tests fail */
reportOnFailure: boolean;
/** Allow coverage of external files */
allowExternal: boolean;
/** Apply exclusions after source map remapping */
excludeAfterRemap?: boolean;
/** Concurrency limit for processing */
processingConcurrency: number;
/** Class method names to ignore */
ignoreClassMethods?: string[];
}The provider processes coverage files concurrently:
processingConcurrencyPromise.allMath.min(20, os.cpus().length)When debug is enabled (via DEBUG=vitest:coverage environment variable):
The provider manages memory carefully:
If AST parsing fails for a file:
If source file doesn't exist:
If source map processing fails:
The provider integrates deeply with Vitest:
Lifecycle Hooks:
initialize - Called when provider is loadedclean - Called before test run to clean old coverageonAfterSuiteRun - Called after each test filegenerateCoverage - Called after all tests completereportCoverage - Called to generate reportsonTestFailure - Called when tests fail (for reportOnFailure option)Vitest APIs Used:
parseAstAsync - Parse source code into ASTBaseCoverageProvider - Base class with common functionalityComplete example showing provider usage:
import { V8CoverageProvider } from '@vitest/coverage-v8/provider';
// 1. Create and initialize provider
const provider = new V8CoverageProvider();
provider.initialize(vitestContext);
// 2. Generate coverage map from collected data
const coverageMap = await provider.generateCoverage({
allTestsRun: true
});
// 3. Generate reports
await provider.generateReports(coverageMap, true);
// Reports are now available in the configured directory
// Default: ./coverage/Typically, you don't use the provider directly. Vitest handles the lifecycle automatically via the coverage module's getProvider() method.