Core istanbul API for JS code coverage instrumentation and analysis
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Utility functionality for extracting existing coverage data from already instrumented JavaScript code. This enables coverage analysis of pre-instrumented files and recovery of coverage metadata.
Extracts coverage data from JavaScript code that has already been instrumented with coverage tracking.
/**
* Reads existing coverage data from already instrumented code
* @param code - The instrumented code (string) or parsed AST object
* @returns Coverage data object if found, null if no coverage data exists
*/
function readInitialCoverage(code: string | object): CoverageData | null;
interface CoverageData {
/** File path that the coverage data tracks */
path: string;
/** Hash of the original source code */
hash: string;
/** Global coverage variable name */
gcv: string;
/** The actual coverage tracking data structure */
coverageData: object;
}Usage Examples:
const { readInitialCoverage } = require("istanbul-lib-instrument");
// Read coverage from instrumented code string
const instrumentedCode = `
var cov_1a2b3c = function () {
var path = '/path/to/original/file.js';
var hash = 'abc123def456';
var gcv = '__coverage__';
var coverageData = {
path: '/path/to/original/file.js',
statementMap: { /* ... */ },
fnMap: { /* ... */ },
branchMap: { /* ... */ },
s: {},
f: {},
b: {}
};
return coverageData;
}();
function add(a, b) {
cov_1a2b3c.s[0]++;
return a + b;
}
`;
const coverage = readInitialCoverage(instrumentedCode);
if (coverage) {
console.log('Original file path:', coverage.path);
console.log('Source hash:', coverage.hash);
console.log('Coverage variable:', coverage.gcv);
console.log('Statement map:', coverage.coverageData.statementMap);
}Reading coverage data from pre-parsed AST objects instead of code strings.
// Reading from Babel AST
const { parseSync } = require("@babel/core");
const { readInitialCoverage } = require("istanbul-lib-instrument");
const ast = parseSync(instrumentedCode, {
sourceType: 'script',
plugins: ['jsx', 'typescript']
});
const coverage = readInitialCoverage(ast);Usage Examples:
const { parseSync } = require("@babel/core");
const { readInitialCoverage } = require("istanbul-lib-instrument");
// Parse instrumented code to AST
const instrumentedCode = '/* instrumented code */';
const ast = parseSync(instrumentedCode, {
sourceType: 'unambiguous',
allowImportExportEverywhere: true,
allowReturnOutsideFunction: true
});
// Extract coverage from AST
const coverage = readInitialCoverage(ast);
if (coverage) {
console.log('Found coverage data for:', coverage.path);
// Access detailed coverage information
const { coverageData } = coverage;
console.log('Functions tracked:', Object.keys(coverageData.fnMap).length);
console.log('Statements tracked:', Object.keys(coverageData.statementMap).length);
console.log('Branches tracked:', Object.keys(coverageData.branchMap).length);
}Understanding the structure of returned coverage data for analysis and reporting.
interface DetailedCoverageData {
/** File path being tracked */
path: string;
/** Statement location mapping */
statementMap: { [key: string]: Location };
/** Function location mapping */
fnMap: { [key: string]: FunctionMapping };
/** Branch location mapping */
branchMap: { [key: string]: BranchMapping };
/** Statement execution counts */
s: { [key: string]: number };
/** Function execution counts */
f: { [key: string]: number };
/** Branch execution counts */
b: { [key: string]: number[] };
}
interface Location {
start: { line: number; column: number };
end: { line: number; column: number };
}
interface FunctionMapping {
name: string;
decl: Location;
loc: Location;
line: number;
}
interface BranchMapping {
loc: Location;
type: 'if' | 'switch' | 'cond-expr' | 'logical-expr';
locations: Location[];
line: number;
}Usage Examples:
const { readInitialCoverage } = require("istanbul-lib-instrument");
function analyzeCoverage(instrumentedCode) {
const coverage = readInitialCoverage(instrumentedCode);
if (!coverage) {
console.log('No coverage data found');
return;
}
const { coverageData } = coverage;
// Analyze statement coverage
const statements = Object.keys(coverageData.statementMap);
const executedStatements = statements.filter(id => coverageData.s[id] > 0);
console.log(`Statement coverage: ${executedStatements.length}/${statements.length}`);
// Analyze function coverage
const functions = Object.keys(coverageData.fnMap);
const executedFunctions = functions.filter(id => coverageData.f[id] > 0);
console.log(`Function coverage: ${executedFunctions.length}/${functions.length}`);
// Analyze branch coverage
const branches = Object.keys(coverageData.branchMap);
let totalBranches = 0;
let executedBranches = 0;
branches.forEach(branchId => {
const branchData = coverageData.b[branchId];
totalBranches += branchData.length;
executedBranches += branchData.filter(count => count > 0).length;
});
console.log(`Branch coverage: ${executedBranches}/${totalBranches}`);
}Handling cases where coverage data is missing, malformed, or partially available.
function safeCoverageReading(code) {
try {
const coverage = readInitialCoverage(code);
if (!coverage) {
console.log('No coverage data found in code');
return null;
}
// Validate coverage data structure
if (!coverage.coverageData || !coverage.path) {
console.warn('Incomplete coverage data structure');
return null;
}
return coverage;
} catch (error) {
console.error('Failed to read coverage data:', error.message);
return null;
}
}Usage Examples:
const { readInitialCoverage } = require("istanbul-lib-instrument");
const fs = require('fs');
// Read coverage from multiple files
function analyzeCoverageFiles(filePaths) {
const results = [];
for (const filePath of filePaths) {
try {
const code = fs.readFileSync(filePath, 'utf8');
const coverage = readInitialCoverage(code);
if (coverage) {
results.push({
file: filePath,
originalPath: coverage.path,
hash: coverage.hash,
hasStatements: Object.keys(coverage.coverageData.statementMap).length > 0,
hasFunctions: Object.keys(coverage.coverageData.fnMap).length > 0,
hasBranches: Object.keys(coverage.coverageData.branchMap).length > 0
});
}
} catch (error) {
console.warn(`Failed to analyze ${filePath}:`, error.message);
}
}
return results;
}
// Usage
const coverageFiles = [
'dist/instrumented/app.js',
'dist/instrumented/utils.js',
'dist/instrumented/components.js'
];
const analysis = analyzeCoverageFiles(coverageFiles);
analysis.forEach(result => {
console.log(`${result.file} -> ${result.originalPath}`);
console.log(` Hash: ${result.hash}`);
console.log(` Coverage types: ${[
result.hasStatements && 'statements',
result.hasFunctions && 'functions',
result.hasBranches && 'branches'
].filter(Boolean).join(', ')}`);
});Analyzing code that was instrumented in a previous build step or by a different tool.
const { readInitialCoverage } = require("istanbul-lib-instrument");
// Check if code is already instrumented before re-instrumenting
function isAlreadyInstrumented(code) {
const coverage = readInitialCoverage(code);
return coverage !== null;
}
// Extract original file path from instrumented code
function getOriginalPath(instrumentedCode) {
const coverage = readInitialCoverage(instrumentedCode);
return coverage ? coverage.path : null;
}Recovering coverage data from build artifacts or distributed code.
// Recover coverage metadata from production builds
function recoverCoverageMetadata(buildArtifacts) {
const metadata = [];
for (const artifact of buildArtifacts) {
const coverage = readInitialCoverage(artifact.code);
if (coverage) {
metadata.push({
buildFile: artifact.path,
originalFile: coverage.path,
sourceHash: coverage.hash,
instrumentationVariable: coverage.gcv
});
}
}
return metadata;
}Integration with development tools that need to understand existing coverage instrumentation.
// IDE or editor plugin to detect instrumented files
function detectInstrumentedFiles(projectFiles) {
return projectFiles
.map(filePath => {
const code = fs.readFileSync(filePath, 'utf8');
const coverage = readInitialCoverage(code);
return {
path: filePath,
isInstrumented: coverage !== null,
originalSource: coverage ? coverage.path : filePath,
coverageVariable: coverage ? coverage.gcv : null
};
})
.filter(file => file.isInstrumented);
}