0
# Code Instrumentation
1
2
Core instrumentation functionality for transforming JavaScript code with coverage tracking capabilities. The instrumenter adds counters for statements, branches, and functions while preserving original code semantics.
3
4
## Capabilities
5
6
### Create Instrumenter
7
8
Creates a new instrumenter instance with configurable options for different instrumentation scenarios.
9
10
```javascript { .api }
11
/**
12
* Creates a new instrumenter with the supplied options
13
* @param opts - Instrumenter configuration options
14
* @returns New Instrumenter instance
15
*/
16
function createInstrumenter(opts?: InstrumenterOptions): Instrumenter;
17
18
interface InstrumenterOptions {
19
/** Name of global coverage variable (default: "__coverage__") */
20
coverageVariable?: string;
21
/** Report boolean value of logical expressions (default: false) */
22
reportLogic?: boolean;
23
/** Preserve comments in output (default: false) */
24
preserveComments?: boolean;
25
/** Generate compact code (default: true) */
26
compact?: boolean;
27
/** Set to true to instrument ES6 modules (default: false) */
28
esModules?: boolean;
29
/** Set to true to allow return statements outside of functions (default: false) */
30
autoWrap?: boolean;
31
/** Set to true to produce a source map for the instrumented code (default: false) */
32
produceSourceMap?: boolean;
33
/** Set to array of class method names to ignore for coverage (default: []) */
34
ignoreClassMethods?: string[];
35
/** Callback function called when a source map URL is found (default: null) */
36
sourceMapUrlCallback?: (filename: string, url: string) => void;
37
/** Turn debugging on (default: false) */
38
debug?: boolean;
39
/** Set babel parser plugins (default: from @istanbuljs/schema) */
40
parserPlugins?: string[];
41
/** The global coverage variable scope (default: "this") */
42
coverageGlobalScope?: string;
43
/** Use an evaluated function to find coverageGlobalScope (default: true) */
44
coverageGlobalScopeFunc?: boolean;
45
/** Set babel generator options */
46
generatorOpts?: object;
47
}
48
```
49
50
**Usage Examples:**
51
52
```javascript
53
const { createInstrumenter } = require("istanbul-lib-instrument");
54
55
// Basic instrumenter
56
const instrumenter = createInstrumenter();
57
58
// Instrumenter with custom options
59
const customInstrumenter = createInstrumenter({
60
coverageVariable: "__cov__",
61
esModules: true,
62
preserveComments: true,
63
produceSourceMap: true
64
});
65
66
// Instrumenter for browser environments
67
const browserInstrumenter = createInstrumenter({
68
coverageGlobalScope: "window",
69
compact: true,
70
reportLogic: true
71
});
72
```
73
74
### Instrumenter Class
75
76
Main instrumenter class providing synchronous and asynchronous instrumentation methods.
77
78
```javascript { .api }
79
class Instrumenter {
80
constructor(opts?: InstrumenterOptions);
81
}
82
```
83
84
### Synchronous Instrumentation
85
86
Transform code synchronously and track coverage against the supplied filename. Throws if invalid code is passed.
87
88
```javascript { .api }
89
/**
90
* Instrument the supplied code and track coverage against the supplied filename
91
* @param code - The code to instrument
92
* @param filename - The filename against which to track coverage
93
* @param inputSourceMap - Source map that maps uninstrumented code back to original form
94
* @returns The instrumented code
95
* @throws Error if invalid code is passed
96
*/
97
instrumentSync(code: string, filename: string, inputSourceMap?: object): string;
98
```
99
100
**Usage Examples:**
101
102
```javascript
103
const { createInstrumenter } = require("istanbul-lib-instrument");
104
105
const instrumenter = createInstrumenter();
106
107
// Basic instrumentation
108
const code = `
109
function calculateTax(price, rate) {
110
if (price > 0 && rate > 0) {
111
return price * rate;
112
}
113
return 0;
114
}
115
`;
116
117
const instrumentedCode = instrumenter.instrumentSync(code, 'tax-calculator.js');
118
119
// Instrumentation with source map
120
const sourceMap = { /* source map object */ };
121
const instrumentedWithMap = instrumenter.instrumentSync(
122
code,
123
'tax-calculator.js',
124
sourceMap
125
);
126
```
127
128
### Asynchronous Instrumentation
129
130
Callback-style instrument method that calls back with an error instead of throwing. Note that the callback is called synchronously.
131
132
```javascript { .api }
133
/**
134
* Callback-style instrument method that calls back with an error
135
* @param code - The code to instrument
136
* @param filename - The filename against which to track coverage
137
* @param callback - The callback function
138
* @param inputSourceMap - Source map that maps uninstrumented code back to original form
139
*/
140
instrument(
141
code: string,
142
filename: string,
143
callback: (err: Error | null, result?: string) => void,
144
inputSourceMap?: object
145
): void;
146
147
// Alternative signature with filename optional
148
instrument(
149
code: string,
150
callback: (err: Error | null, result?: string) => void,
151
inputSourceMap?: object
152
): void;
153
```
154
155
**Usage Examples:**
156
157
```javascript
158
const { createInstrumenter } = require("istanbul-lib-instrument");
159
160
const instrumenter = createInstrumenter();
161
162
// Callback-style instrumentation
163
instrumenter.instrument(code, 'calculator.js', (err, instrumentedCode) => {
164
if (err) {
165
console.error('Instrumentation failed:', err);
166
return;
167
}
168
console.log('Instrumented code:', instrumentedCode);
169
});
170
171
// With filename as optional parameter
172
instrumenter.instrument(code, (err, instrumentedCode) => {
173
if (err) {
174
console.error('Instrumentation failed:', err);
175
return;
176
}
177
// filename will be auto-generated
178
console.log('Instrumented code:', instrumentedCode);
179
});
180
```
181
182
### Coverage Data Access
183
184
Retrieve coverage information for the last instrumented file.
185
186
```javascript { .api }
187
/**
188
* Returns the file coverage object for the last file instrumented
189
* @returns The file coverage object with statement, branch, and function tracking
190
*/
191
lastFileCoverage(): object;
192
193
/**
194
* Returns the source map produced for the last file instrumented
195
* @returns The source map object or null if no source map was produced
196
*/
197
lastSourceMap(): object | null;
198
```
199
200
**Usage Examples:**
201
202
```javascript
203
const { createInstrumenter } = require("istanbul-lib-instrument");
204
205
const instrumenter = createInstrumenter({ produceSourceMap: true });
206
207
// Instrument code
208
const instrumentedCode = instrumenter.instrumentSync(code, 'example.js');
209
210
// Get coverage data structure
211
const coverage = instrumenter.lastFileCoverage();
212
console.log('Statement map:', coverage.statementMap);
213
console.log('Function map:', coverage.fnMap);
214
console.log('Branch map:', coverage.branchMap);
215
216
// Get source map if produced
217
const sourceMap = instrumenter.lastSourceMap();
218
if (sourceMap) {
219
console.log('Source map version:', sourceMap.version);
220
console.log('Source map mappings:', sourceMap.mappings);
221
}
222
```
223
224
## Configuration Options Details
225
226
### Coverage Variable Options
227
228
- **coverageVariable**: Name of the global variable where coverage data is stored
229
- **coverageGlobalScope**: The scope where the coverage variable is attached ("this", "window", "global")
230
- **coverageGlobalScopeFunc**: Whether to use an evaluated function to determine the scope
231
232
### Code Generation Options
233
234
- **compact**: Generate compact code without unnecessary whitespace
235
- **preserveComments**: Keep comments in the instrumented output
236
- **generatorOpts**: Pass-through options to Babel's code generator
237
238
### Module System Options
239
240
- **esModules**: Enable ES6 module instrumentation (required for `import`/`export`)
241
- **autoWrap**: Allow `return` statements outside functions (useful for module-level returns)
242
243
### Advanced Options
244
245
- **reportLogic**: Track boolean evaluation in logical expressions (&&, ||)
246
- **ignoreClassMethods**: Array of method names to skip instrumentation on classes
247
- **parserPlugins**: Babel parser plugins for advanced syntax support
248
- **produceSourceMap**: Generate source maps for debugging instrumented code
249
- **sourceMapUrlCallback**: Custom handling of source map URLs found in code
250
251
## Error Handling
252
253
The instrumenter can throw errors in several scenarios:
254
255
- **Invalid Code**: Syntax errors in the input JavaScript code
256
- **Parser Configuration**: Invalid parser plugin configurations
257
- **File System**: Issues accessing files when source maps are involved
258
259
```javascript
260
const { createInstrumenter } = require("istanbul-lib-instrument");
261
262
const instrumenter = createInstrumenter();
263
264
try {
265
const result = instrumenter.instrumentSync('invalid javascript code {', 'test.js');
266
} catch (error) {
267
console.error('Instrumentation failed:', error.message);
268
// Handle parsing or transformation errors
269
}
270
271
// For callback style, errors are passed to callback
272
instrumenter.instrument('invalid code', 'test.js', (err, result) => {
273
if (err) {
274
console.error('Instrumentation failed:', err.message);
275
return;
276
}
277
// Process result
278
});
279
```