0
# Source Map Consumption
1
2
The SourceMapConsumer classes provide functionality for reading and querying existing source maps. This enables bidirectional position mapping, source content access, and mapping iteration for debugging tools, development servers, and error reporting systems.
3
4
## Capabilities
5
6
### SourceMapConsumer Constructor
7
8
Creates consumers for both regular and indexed source maps with automatic type detection.
9
10
```typescript { .api }
11
/**
12
* Creates a new SourceMapConsumer from raw source map data
13
* @param rawSourceMap - Raw source map object, indexed map, or JSON string
14
* @param sourceMapUrl - Optional URL of the source map for resolving relative paths
15
* @returns Promise resolving to BasicSourceMapConsumer or IndexedSourceMapConsumer
16
*/
17
interface SourceMapConsumerConstructor {
18
new (
19
rawSourceMap: RawSourceMap | RawIndexMap | string,
20
sourceMapUrl?: SourceMapUrl
21
): Promise<BasicSourceMapConsumer | IndexedSourceMapConsumer>;
22
23
/**
24
* Initialize WASM for browser usage (required before creating consumers)
25
* @param mappings - Object containing WASM file URL or ArrayBuffer
26
*/
27
initialize(mappings: SourceMappings): void;
28
29
/**
30
* Create a BasicSourceMapConsumer from a SourceMapGenerator
31
* @param sourceMap - The source map generator to consume
32
* @param sourceMapUrl - Optional URL for resolving relative paths
33
*/
34
fromSourceMap(
35
sourceMap: SourceMapGenerator,
36
sourceMapUrl?: SourceMapUrl
37
): Promise<BasicSourceMapConsumer>;
38
39
/**
40
* Auto-cleanup wrapper that ensures destroy() is called
41
* @param rawSourceMap - Raw source map data
42
* @param sourceMapUrl - Optional source map URL
43
* @param callback - Function to execute with the consumer
44
*/
45
with<T>(
46
rawSourceMap: RawSourceMap | RawIndexMap | string,
47
sourceMapUrl: SourceMapUrl | null | undefined,
48
callback: (consumer: BasicSourceMapConsumer | IndexedSourceMapConsumer) => Promise<T> | T
49
): Promise<T>;
50
}
51
52
interface SourceMappings {
53
"lib/mappings.wasm": SourceMapUrl | ArrayBuffer;
54
}
55
56
type SourceMapUrl = string;
57
```
58
59
**Usage Examples:**
60
61
```typescript
62
import { SourceMapConsumer } from "source-map";
63
64
// Browser initialization (required)
65
SourceMapConsumer.initialize({
66
"lib/mappings.wasm": "https://unpkg.com/source-map@0.7.6/lib/mappings.wasm"
67
});
68
69
// Create consumer (auto-detects regular vs indexed)
70
const consumer = await new SourceMapConsumer(rawSourceMap);
71
72
// Recommended: Use auto-cleanup wrapper
73
const result = await SourceMapConsumer.with(rawSourceMap, null, async (consumer) => {
74
const originalPos = consumer.originalPositionFor({ line: 1, column: 12 });
75
return originalPos;
76
// consumer.destroy() called automatically
77
});
78
```
79
80
### Basic Source Map Consumer
81
82
Handles regular source maps with full position mapping and source content access.
83
84
```typescript { .api }
85
interface BasicSourceMapConsumer extends SourceMapConsumer {
86
/** Generated file name */
87
readonly file: string;
88
/** Source root URL */
89
readonly sourceRoot: string;
90
/** Array of absolute source URLs */
91
readonly sources: string[];
92
/** Array of source file contents */
93
readonly sourcesContent: string[];
94
}
95
96
interface BasicSourceMapConsumerConstructor {
97
new (rawSourceMap: RawSourceMap | string): Promise<BasicSourceMapConsumer>;
98
fromSourceMap(sourceMap: SourceMapGenerator): Promise<BasicSourceMapConsumer>;
99
}
100
```
101
102
### Indexed Source Map Consumer
103
104
Handles indexed source maps containing multiple sections for large applications.
105
106
```typescript { .api }
107
interface IndexedSourceMapConsumer extends SourceMapConsumer {
108
/** Combined sources from all sections */
109
readonly sources: string[];
110
}
111
112
interface IndexedSourceMapConsumerConstructor {
113
new (rawSourceMap: RawIndexMap | string): Promise<IndexedSourceMapConsumer>;
114
}
115
```
116
117
### Position Mapping
118
119
Map between generated and original code positions bidirectionally.
120
121
```typescript { .api }
122
/**
123
* Returns the original source, line, and column information for the generated
124
* source's line and column positions provided
125
* @param generatedPosition - Position in generated code with optional bias
126
* @returns Original position information (values can be null if not found)
127
*/
128
originalPositionFor(
129
generatedPosition: Position & { bias?: number }
130
): NullableMappedPosition;
131
132
/**
133
* Returns the generated line and column information for the original source,
134
* line, and column positions provided
135
* @param originalPosition - Position in original code with optional bias
136
* @returns Generated position information (values can be null if not found)
137
*/
138
generatedPositionFor(
139
originalPosition: MappedPosition & { bias?: number }
140
): NullablePosition;
141
142
/**
143
* Returns all generated line and column information for the original source,
144
* line, and column provided
145
* @param originalPosition - Position in original code
146
* @returns Array of all corresponding generated positions
147
*/
148
allGeneratedPositionsFor(
149
originalPosition: MappedPosition
150
): NullablePosition[];
151
152
interface Position {
153
line: number; // 1-based line number
154
column: number; // 0-based column number
155
}
156
157
interface MappedPosition {
158
source: string; // Original source file name
159
line: number; // 1-based line number
160
column: number; // 0-based column number
161
name?: string; // Optional original identifier name
162
}
163
164
interface NullablePosition {
165
line: number | null;
166
column: number | null;
167
lastColumn: number | null;
168
}
169
170
interface NullableMappedPosition {
171
source: string | null;
172
line: number | null;
173
column: number | null;
174
name: string | null;
175
}
176
```
177
178
**Usage Examples:**
179
180
```typescript
181
// Find original position for generated code
182
const originalPos = consumer.originalPositionFor({
183
line: 1, // Generated line (1-based)
184
column: 28 // Generated column (0-based)
185
});
186
console.log(originalPos);
187
// { source: 'math.js', line: 15, column: 4, name: 'add' }
188
189
// Find generated position for original code
190
const generatedPos = consumer.generatedPositionFor({
191
source: 'math.js',
192
line: 15,
193
column: 4
194
});
195
console.log(generatedPos);
196
// { line: 1, column: 28, lastColumn: 32 }
197
198
// Get all generated positions for original
199
const allPositions = consumer.allGeneratedPositionsFor({
200
source: 'utils.js',
201
line: 10,
202
column: 0
203
});
204
console.log(allPositions);
205
// [{ line: 5, column: 12, lastColumn: null }, { line: 8, column: 0, lastColumn: null }]
206
```
207
208
### Search Bias Constants
209
210
Control position lookup behavior when exact matches aren't found.
211
212
```typescript { .api }
213
// Static constants on SourceMapConsumer
214
static readonly GREATEST_LOWER_BOUND: 1; // Find closest smaller element
215
static readonly LEAST_UPPER_BOUND: 2; // Find closest larger element
216
217
// Iteration order constants
218
static readonly GENERATED_ORDER: 1; // Sort by generated position
219
static readonly ORIGINAL_ORDER: 2; // Sort by original position
220
```
221
222
**Usage:**
223
224
```typescript
225
// Use bias for fuzzy position matching
226
const originalPos = consumer.originalPositionFor({
227
line: 1,
228
column: 15,
229
bias: SourceMapConsumer.GREATEST_LOWER_BOUND // Find closest match <= position
230
});
231
```
232
233
### Source Content Access
234
235
Access original source file contents embedded in the source map.
236
237
```typescript { .api }
238
/**
239
* Return true if we have the source content for every source in the source
240
* map, false otherwise
241
*/
242
hasContentsOfAllSources(): boolean;
243
244
/**
245
* Returns the original source content. The only argument is the url of the
246
* original source file. Returns null if no original source content is available
247
* @param source - Source file name/URL
248
* @param returnNullOnMissing - If true, return null instead of throwing error
249
*/
250
sourceContentFor(source: string, returnNullOnMissing?: boolean): string | null;
251
```
252
253
**Usage:**
254
255
```typescript
256
// Check if all source content is available
257
if (consumer.hasContentsOfAllSources()) {
258
console.log("All source content is embedded");
259
}
260
261
// Get content for specific source
262
const content = consumer.sourceContentFor("math.js");
263
if (content) {
264
console.log("Source content:", content);
265
} else {
266
console.log("No content available for math.js");
267
}
268
269
// Safe content access without exceptions
270
const safeContent = consumer.sourceContentFor("missing.js", true);
271
console.log(safeContent); // null if not found
272
```
273
274
### Mapping Iteration
275
276
Iterate over all mappings in the source map with different ordering options.
277
278
```typescript { .api }
279
/**
280
* Iterate over each mapping between an original source/line/column and a
281
* generated line/column in this source map
282
* @param callback - Function called with each mapping
283
* @param context - Optional context object for callback
284
* @param order - Iteration order (GENERATED_ORDER or ORIGINAL_ORDER)
285
*/
286
eachMapping(
287
callback: (mapping: MappingItem) => void,
288
context?: any,
289
order?: number
290
): void;
291
292
293
interface MappingItem {
294
source: string;
295
generatedLine: number;
296
generatedColumn: number;
297
lastGeneratedColumn: number | null;
298
originalLine: number;
299
originalColumn: number;
300
name: string;
301
}
302
```
303
304
**Usage:**
305
306
```typescript
307
// Iterate in generated code order
308
consumer.eachMapping((mapping) => {
309
console.log(`Generated ${mapping.generatedLine}:${mapping.generatedColumn} -> ` +
310
`Original ${mapping.source}:${mapping.originalLine}:${mapping.originalColumn}`);
311
}, null, SourceMapConsumer.GENERATED_ORDER);
312
313
// Iterate in original source order
314
consumer.eachMapping((mapping) => {
315
console.log(`${mapping.source}:${mapping.originalLine}:${mapping.originalColumn} -> ` +
316
`${mapping.generatedLine}:${mapping.generatedColumn}`);
317
}, null, SourceMapConsumer.ORIGINAL_ORDER);
318
319
// Use context object
320
const stats = { totalMappings: 0, sources: new Set() };
321
consumer.eachMapping(function(mapping) {
322
this.totalMappings++;
323
this.sources.add(mapping.source);
324
}, stats);
325
console.log(`Found ${stats.totalMappings} mappings across ${stats.sources.size} sources`);
326
```
327
328
### Column Spans
329
330
Calculate ending column positions for mappings.
331
332
```typescript { .api }
333
/**
334
* Compute the last column for each generated mapping. The last column is
335
* inclusive.
336
*/
337
computeColumnSpans(): void;
338
```
339
340
**Usage:**
341
342
```typescript
343
// Calculate column spans for better range mapping
344
consumer.computeColumnSpans();
345
346
// Now lastColumn will be populated in position results
347
const pos = consumer.originalPositionFor({ line: 1, column: 0 });
348
console.log(`Mapping spans from column ${pos.column} to ${pos.lastColumn}`);
349
```
350
351
### Resource Management
352
353
Properly clean up WASM resources to prevent memory leaks.
354
355
```typescript { .api }
356
/**
357
* Free this source map consumer's associated wasm data that is manually-managed.
358
* Alternatively, you can use SourceMapConsumer.with to avoid needing to remember to call destroy.
359
*/
360
destroy(): void;
361
```
362
363
**Usage:**
364
365
```typescript
366
// Manual cleanup (not recommended)
367
const consumer = await new SourceMapConsumer(rawSourceMap);
368
try {
369
// Use consumer
370
const pos = consumer.originalPositionFor({ line: 1, column: 0 });
371
} finally {
372
consumer.destroy(); // Required to prevent memory leaks
373
}
374
375
// Recommended: automatic cleanup
376
const result = await SourceMapConsumer.with(rawSourceMap, null, (consumer) => {
377
return consumer.originalPositionFor({ line: 1, column: 0 });
378
// destroy() called automatically
379
});
380
```
381
382
## Data Types
383
384
```typescript { .api }
385
interface RawSourceMap {
386
version: number;
387
sources: string[];
388
names: string[];
389
sourceRoot?: string;
390
sourcesContent?: string[];
391
mappings: string;
392
file: string;
393
x_google_ignoreList?: number[]; // Indices of third-party sources to ignore in Chrome DevTools
394
}
395
396
interface RawIndexMap {
397
version: number;
398
sections: RawSection[];
399
file?: string;
400
sourceRoot?: string;
401
}
402
403
interface RawSection {
404
offset: Position;
405
map: RawSourceMap;
406
}
407
```
408
409
## Error Handling
410
411
Source map consumption can fail for various reasons:
412
413
- **Unsupported version**: Only version 3 source maps are supported
414
- **Invalid format**: Malformed JSON or missing required fields
415
- **WASM not initialized**: Browser usage requires `SourceMapConsumer.initialize()`
416
- **Source not found**: Requested source file not present in source map
417
- **Invalid positions**: Line/column values outside valid ranges
418
419
```typescript
420
try {
421
const consumer = await new SourceMapConsumer(malformedSourceMap);
422
} catch (error) {
423
if (error.message.includes("Unsupported version")) {
424
console.error("Source map version not supported");
425
} else if (error.message.includes("lib/mappings.wasm")) {
426
console.error("WASM not initialized for browser usage");
427
}
428
}
429
```