Generates and consumes source maps for debugging tools that map minified code back to original source code
npx @tessl/cli install tessl/npm-source-map@0.7.0Source Map is a comprehensive JavaScript library for generating and consuming source maps, which are essential debugging tools that map minified or compiled code back to original source code. It provides both high-level APIs for building source maps incrementally during code generation and low-level APIs for direct manipulation and consumption of source map data.
npm install source-mapES Modules:
import { SourceMapGenerator, SourceMapConsumer, SourceNode } from "source-map";CommonJS:
const { SourceMapGenerator, SourceMapConsumer, SourceNode } = require("source-map");import { SourceMapConsumer } from "source-map";
const rawSourceMap = {
version: 3,
file: "min.js",
names: ["bar", "baz", "n"],
sources: ["one.js", "two.js"],
sourceRoot: "http://example.com/www/js/",
mappings: "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUGE,GAClB,OAAOA"
};
// Use the auto-cleanup wrapper (recommended)
const result = await SourceMapConsumer.with(rawSourceMap, null, consumer => {
// Find original position for generated code
const originalPos = consumer.originalPositionFor({
line: 2,
column: 28
});
// Returns: { source: 'http://example.com/www/js/two.js', line: 2, column: 10, name: 'n' }
return originalPos;
});import { SourceMapGenerator } from "source-map";
const map = new SourceMapGenerator({
file: "source-mapped.js"
});
map.addMapping({
generated: { line: 10, column: 35 },
source: "foo.js",
original: { line: 33, column: 2 },
name: "christopher"
});
console.log(map.toString());
// Outputs complete source map JSONimport { SourceNode } from "source-map";
const node = new SourceNode(1, 0, "math.js", [
"function add(a, b) {\n",
new SourceNode(2, 2, "math.js", "return a + b;\n"),
"}"
]);
const result = node.toStringWithSourceMap({
file: "compiled.js"
});
console.log(result.code); // Generated JavaScript
console.log(result.map.toString()); // Source map JSONSource maps support an optional x_google_ignoreList field for marking third-party sources:
const sourceMapWithIgnoreList = {
version: 3,
sources: ["app.js", "vendor.js", "node_modules/lib.js"],
names: [],
mappings: "...",
x_google_ignoreList: [1, 2] // Mark vendor.js and lib.js as third-party
};Source Map is built around three main components:
The library supports both regular source maps and indexed source maps for large applications, with WASM-accelerated performance for fast position lookups in browser environments.
When using in browsers, initialize WASM before creating consumers:
import { SourceMapConsumer } from "source-map";
// Required for browser usage
SourceMapConsumer.initialize({
"lib/mappings.wasm": "https://unpkg.com/source-map@0.7.6/lib/mappings.wasm"
});
// Now safe to use SourceMapConsumerSource map operations can fail for various reasons. Handle errors appropriately:
try {
const consumer = await new SourceMapConsumer(rawSourceMap);
// Use consumer safely
consumer.destroy();
} catch (error) {
if (error.message.includes("Unsupported version")) {
console.error("Source map version not supported (only v3 supported)");
} else if (error.message.includes("lib/mappings.wasm")) {
console.error("WASM not initialized for browser usage");
} else if (error.message.includes("Invalid mapping")) {
console.error("Source map contains invalid mapping data");
} else {
console.error("Failed to parse source map:", error.message);
}
}Common error scenarios:
SourceMapConsumer.initialize()Source map operations can be expensive for large files. Consider these optimizations:
SourceMapConsumer.with() for automatic resource cleanup// Good: Batch operations within consumer lifecycle
const results = await SourceMapConsumer.with(sourceMap, null, (consumer) => {
return sourcePositions.map(pos => consumer.originalPositionFor(pos));
});
// Avoid: Creating multiple consumers for the same map
// This creates unnecessary overheadCreate source maps incrementally during code generation with full control over mappings and source content.
class SourceMapGenerator {
constructor(args?: StartOfSourceMap);
static fromSourceMap(sourceMapConsumer: SourceMapConsumer): SourceMapGenerator;
addMapping(mapping: Mapping): void;
setSourceContent(sourceFile: string, sourceContent: string): void;
applySourceMap(
sourceMapConsumer: SourceMapConsumer,
sourceFile?: string,
sourceMapPath?: string
): void;
toString(): string;
toJSON(): RawSourceMap;
}
interface StartOfSourceMap {
file?: string;
sourceRoot?: string;
skipValidation?: boolean;
}
interface Mapping {
generated: Position;
original: Position;
source: string;
name?: string;
}Read and query existing source maps with bidirectional position mapping and source content access.
interface SourceMapConsumerConstructor {
new (
rawSourceMap: RawSourceMap | RawIndexMap | string,
sourceMapUrl?: SourceMapUrl
): Promise<BasicSourceMapConsumer | IndexedSourceMapConsumer>;
// Static constants
readonly GENERATED_ORDER: 1;
readonly ORIGINAL_ORDER: 2;
readonly GREATEST_LOWER_BOUND: 1;
readonly LEAST_UPPER_BOUND: 2;
initialize(mappings: SourceMappings): void;
fromSourceMap(
sourceMap: SourceMapGenerator,
sourceMapUrl?: SourceMapUrl
): Promise<BasicSourceMapConsumer>;
with<T>(
rawSourceMap: RawSourceMap | RawIndexMap | string,
sourceMapUrl: SourceMapUrl | null | undefined,
callback: (consumer: BasicSourceMapConsumer | IndexedSourceMapConsumer) => Promise<T> | T
): Promise<T>;
}
interface SourceMapConsumer {
computeColumnSpans(): void;
originalPositionFor(
generatedPosition: Position & { bias?: number }
): NullableMappedPosition;
generatedPositionFor(
originalPosition: MappedPosition & { bias?: number }
): NullablePosition;
allGeneratedPositionsFor(
originalPosition: MappedPosition
): NullablePosition[];
hasContentsOfAllSources(): boolean;
sourceContentFor(source: string, returnNullOnMissing?: boolean): string | null;
eachMapping(
callback: (mapping: MappingItem) => void,
context?: any,
order?: number
): void;
destroy(): void;
}Build source maps through code concatenation and manipulation with a high-level fluent API.
class SourceNode {
constructor(
line?: number | null,
column?: number | null,
source?: string | null,
chunks?: Array<string | SourceNode> | SourceNode | string,
name?: string
);
static fromStringWithSourceMap(
code: string,
sourceMapConsumer: SourceMapConsumer,
relativePath?: string
): SourceNode;
add(chunk: Array<string | SourceNode> | SourceNode | string): SourceNode;
prepend(chunk: Array<string | SourceNode> | SourceNode | string): SourceNode;
setSourceContent(sourceFile: string, sourceContent: string): void;
walk(fn: (chunk: string, mapping: MappedPosition) => void): void;
walkSourceContents(fn: (file: string, content: string) => void): void;
join(sep: string): SourceNode;
replaceRight(pattern: string, replacement: string): SourceNode;
toString(): string;
toStringWithSourceMap(startOfSourceMap?: StartOfSourceMap): CodeWithSourceMap;
}type SourceMapUrl = string;
interface Position {
line: number;
column: number;
}
interface NullablePosition {
line: number | null;
column: number | null;
lastColumn: number | null;
}
interface MappedPosition {
source: string;
line: number;
column: number;
name?: string;
}
interface NullableMappedPosition {
source: string | null;
line: number | null;
column: number | null;
name: string | null;
}
interface RawSourceMap {
version: number;
sources: string[];
names: string[];
sourceRoot?: string;
sourcesContent?: string[];
mappings: string;
file: string;
x_google_ignoreList?: number[];
}
interface RawIndexMap extends StartOfSourceMap {
version: number;
sections: RawSection[];
}
interface RawSection {
offset: Position;
map: RawSourceMap;
}
interface MappingItem {
source: string;
generatedLine: number;
generatedColumn: number;
lastGeneratedColumn: number | null;
originalLine: number;
originalColumn: number;
name: string;
}
interface CodeWithSourceMap {
code: string;
map: SourceMapGenerator;
}
interface SourceMappings {
"lib/mappings.wasm": SourceMapUrl | ArrayBuffer;
}