0
# Coverage Data Reading
1
2
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.
3
4
## Capabilities
5
6
### Read Initial Coverage
7
8
Extracts coverage data from JavaScript code that has already been instrumented with coverage tracking.
9
10
```javascript { .api }
11
/**
12
* Reads existing coverage data from already instrumented code
13
* @param code - The instrumented code (string) or parsed AST object
14
* @returns Coverage data object if found, null if no coverage data exists
15
*/
16
function readInitialCoverage(code: string | object): CoverageData | null;
17
18
interface CoverageData {
19
/** File path that the coverage data tracks */
20
path: string;
21
/** Hash of the original source code */
22
hash: string;
23
/** Global coverage variable name */
24
gcv: string;
25
/** The actual coverage tracking data structure */
26
coverageData: object;
27
}
28
```
29
30
**Usage Examples:**
31
32
```javascript
33
const { readInitialCoverage } = require("istanbul-lib-instrument");
34
35
// Read coverage from instrumented code string
36
const instrumentedCode = `
37
var cov_1a2b3c = function () {
38
var path = '/path/to/original/file.js';
39
var hash = 'abc123def456';
40
var gcv = '__coverage__';
41
var coverageData = {
42
path: '/path/to/original/file.js',
43
statementMap: { /* ... */ },
44
fnMap: { /* ... */ },
45
branchMap: { /* ... */ },
46
s: {},
47
f: {},
48
b: {}
49
};
50
return coverageData;
51
}();
52
53
function add(a, b) {
54
cov_1a2b3c.s[0]++;
55
return a + b;
56
}
57
`;
58
59
const coverage = readInitialCoverage(instrumentedCode);
60
if (coverage) {
61
console.log('Original file path:', coverage.path);
62
console.log('Source hash:', coverage.hash);
63
console.log('Coverage variable:', coverage.gcv);
64
console.log('Statement map:', coverage.coverageData.statementMap);
65
}
66
```
67
68
### AST-based Coverage Reading
69
70
Reading coverage data from pre-parsed AST objects instead of code strings.
71
72
```javascript { .api }
73
// Reading from Babel AST
74
const { parseSync } = require("@babel/core");
75
const { readInitialCoverage } = require("istanbul-lib-instrument");
76
77
const ast = parseSync(instrumentedCode, {
78
sourceType: 'script',
79
plugins: ['jsx', 'typescript']
80
});
81
82
const coverage = readInitialCoverage(ast);
83
```
84
85
**Usage Examples:**
86
87
```javascript
88
const { parseSync } = require("@babel/core");
89
const { readInitialCoverage } = require("istanbul-lib-instrument");
90
91
// Parse instrumented code to AST
92
const instrumentedCode = '/* instrumented code */';
93
const ast = parseSync(instrumentedCode, {
94
sourceType: 'unambiguous',
95
allowImportExportEverywhere: true,
96
allowReturnOutsideFunction: true
97
});
98
99
// Extract coverage from AST
100
const coverage = readInitialCoverage(ast);
101
if (coverage) {
102
console.log('Found coverage data for:', coverage.path);
103
104
// Access detailed coverage information
105
const { coverageData } = coverage;
106
console.log('Functions tracked:', Object.keys(coverageData.fnMap).length);
107
console.log('Statements tracked:', Object.keys(coverageData.statementMap).length);
108
console.log('Branches tracked:', Object.keys(coverageData.branchMap).length);
109
}
110
```
111
112
### Coverage Data Structure
113
114
Understanding the structure of returned coverage data for analysis and reporting.
115
116
```javascript { .api }
117
interface DetailedCoverageData {
118
/** File path being tracked */
119
path: string;
120
/** Statement location mapping */
121
statementMap: { [key: string]: Location };
122
/** Function location mapping */
123
fnMap: { [key: string]: FunctionMapping };
124
/** Branch location mapping */
125
branchMap: { [key: string]: BranchMapping };
126
/** Statement execution counts */
127
s: { [key: string]: number };
128
/** Function execution counts */
129
f: { [key: string]: number };
130
/** Branch execution counts */
131
b: { [key: string]: number[] };
132
}
133
134
interface Location {
135
start: { line: number; column: number };
136
end: { line: number; column: number };
137
}
138
139
interface FunctionMapping {
140
name: string;
141
decl: Location;
142
loc: Location;
143
line: number;
144
}
145
146
interface BranchMapping {
147
loc: Location;
148
type: 'if' | 'switch' | 'cond-expr' | 'logical-expr';
149
locations: Location[];
150
line: number;
151
}
152
```
153
154
**Usage Examples:**
155
156
```javascript
157
const { readInitialCoverage } = require("istanbul-lib-instrument");
158
159
function analyzeCoverage(instrumentedCode) {
160
const coverage = readInitialCoverage(instrumentedCode);
161
162
if (!coverage) {
163
console.log('No coverage data found');
164
return;
165
}
166
167
const { coverageData } = coverage;
168
169
// Analyze statement coverage
170
const statements = Object.keys(coverageData.statementMap);
171
const executedStatements = statements.filter(id => coverageData.s[id] > 0);
172
console.log(`Statement coverage: ${executedStatements.length}/${statements.length}`);
173
174
// Analyze function coverage
175
const functions = Object.keys(coverageData.fnMap);
176
const executedFunctions = functions.filter(id => coverageData.f[id] > 0);
177
console.log(`Function coverage: ${executedFunctions.length}/${functions.length}`);
178
179
// Analyze branch coverage
180
const branches = Object.keys(coverageData.branchMap);
181
let totalBranches = 0;
182
let executedBranches = 0;
183
184
branches.forEach(branchId => {
185
const branchData = coverageData.b[branchId];
186
totalBranches += branchData.length;
187
executedBranches += branchData.filter(count => count > 0).length;
188
});
189
190
console.log(`Branch coverage: ${executedBranches}/${totalBranches}`);
191
}
192
```
193
194
### Error Handling and Validation
195
196
Handling cases where coverage data is missing, malformed, or partially available.
197
198
```javascript { .api }
199
function safeCoverageReading(code) {
200
try {
201
const coverage = readInitialCoverage(code);
202
203
if (!coverage) {
204
console.log('No coverage data found in code');
205
return null;
206
}
207
208
// Validate coverage data structure
209
if (!coverage.coverageData || !coverage.path) {
210
console.warn('Incomplete coverage data structure');
211
return null;
212
}
213
214
return coverage;
215
216
} catch (error) {
217
console.error('Failed to read coverage data:', error.message);
218
return null;
219
}
220
}
221
```
222
223
**Usage Examples:**
224
225
```javascript
226
const { readInitialCoverage } = require("istanbul-lib-instrument");
227
const fs = require('fs');
228
229
// Read coverage from multiple files
230
function analyzeCoverageFiles(filePaths) {
231
const results = [];
232
233
for (const filePath of filePaths) {
234
try {
235
const code = fs.readFileSync(filePath, 'utf8');
236
const coverage = readInitialCoverage(code);
237
238
if (coverage) {
239
results.push({
240
file: filePath,
241
originalPath: coverage.path,
242
hash: coverage.hash,
243
hasStatements: Object.keys(coverage.coverageData.statementMap).length > 0,
244
hasFunctions: Object.keys(coverage.coverageData.fnMap).length > 0,
245
hasBranches: Object.keys(coverage.coverageData.branchMap).length > 0
246
});
247
}
248
} catch (error) {
249
console.warn(`Failed to analyze ${filePath}:`, error.message);
250
}
251
}
252
253
return results;
254
}
255
256
// Usage
257
const coverageFiles = [
258
'dist/instrumented/app.js',
259
'dist/instrumented/utils.js',
260
'dist/instrumented/components.js'
261
];
262
263
const analysis = analyzeCoverageFiles(coverageFiles);
264
analysis.forEach(result => {
265
console.log(`${result.file} -> ${result.originalPath}`);
266
console.log(` Hash: ${result.hash}`);
267
console.log(` Coverage types: ${[
268
result.hasStatements && 'statements',
269
result.hasFunctions && 'functions',
270
result.hasBranches && 'branches'
271
].filter(Boolean).join(', ')}`);
272
});
273
```
274
275
## Use Cases
276
277
### Pre-Instrumented Code Analysis
278
279
Analyzing code that was instrumented in a previous build step or by a different tool.
280
281
```javascript
282
const { readInitialCoverage } = require("istanbul-lib-instrument");
283
284
// Check if code is already instrumented before re-instrumenting
285
function isAlreadyInstrumented(code) {
286
const coverage = readInitialCoverage(code);
287
return coverage !== null;
288
}
289
290
// Extract original file path from instrumented code
291
function getOriginalPath(instrumentedCode) {
292
const coverage = readInitialCoverage(instrumentedCode);
293
return coverage ? coverage.path : null;
294
}
295
```
296
297
### Coverage Data Recovery
298
299
Recovering coverage data from build artifacts or distributed code.
300
301
```javascript
302
// Recover coverage metadata from production builds
303
function recoverCoverageMetadata(buildArtifacts) {
304
const metadata = [];
305
306
for (const artifact of buildArtifacts) {
307
const coverage = readInitialCoverage(artifact.code);
308
if (coverage) {
309
metadata.push({
310
buildFile: artifact.path,
311
originalFile: coverage.path,
312
sourceHash: coverage.hash,
313
instrumentationVariable: coverage.gcv
314
});
315
}
316
}
317
318
return metadata;
319
}
320
```
321
322
### Development Tool Integration
323
324
Integration with development tools that need to understand existing coverage instrumentation.
325
326
```javascript
327
// IDE or editor plugin to detect instrumented files
328
function detectInstrumentedFiles(projectFiles) {
329
return projectFiles
330
.map(filePath => {
331
const code = fs.readFileSync(filePath, 'utf8');
332
const coverage = readInitialCoverage(code);
333
334
return {
335
path: filePath,
336
isInstrumented: coverage !== null,
337
originalSource: coverage ? coverage.path : filePath,
338
coverageVariable: coverage ? coverage.gcv : null
339
};
340
})
341
.filter(file => file.isInstrumented);
342
}
343
```