90 lines
2.4 KiB
JavaScript
90 lines
2.4 KiB
JavaScript
import sourceMap from "source-map";
|
|
|
|
/**
|
|
* Build a sourcemap.
|
|
*/
|
|
|
|
export default class SourceMap {
|
|
constructor(opts, code) {
|
|
this._cachedMap = null;
|
|
this._code = code;
|
|
this._opts = opts;
|
|
this._rawMappings = [];
|
|
}
|
|
|
|
/**
|
|
* Get the sourcemap.
|
|
*/
|
|
|
|
get() {
|
|
if (!this._cachedMap) {
|
|
const map = this._cachedMap = new sourceMap.SourceMapGenerator({
|
|
file: this._opts.sourceMapTarget,
|
|
sourceRoot: this._opts.sourceRoot,
|
|
});
|
|
|
|
const code = this._code;
|
|
if (typeof code === "string") {
|
|
map.setSourceContent(this._opts.sourceFileName, code);
|
|
} else if (typeof code === "object") {
|
|
Object.keys(code).forEach((sourceFileName) => {
|
|
map.setSourceContent(sourceFileName, code[sourceFileName]);
|
|
});
|
|
}
|
|
|
|
this._rawMappings.forEach(map.addMapping, map);
|
|
}
|
|
|
|
return this._cachedMap.toJSON();
|
|
}
|
|
|
|
getRawMappings() {
|
|
return this._rawMappings.slice();
|
|
}
|
|
|
|
/**
|
|
* Mark the current generated position with a source position. May also be passed null line/column
|
|
* values to insert a mapping to nothing.
|
|
*/
|
|
|
|
mark(
|
|
generatedLine: number,
|
|
generatedColumn: number,
|
|
line: number,
|
|
column: number,
|
|
identifierName: ?string,
|
|
filename: ?string,
|
|
) {
|
|
// Adding an empty mapping at the start of a generated line just clutters the map.
|
|
if (this._lastGenLine !== generatedLine && line === null) return;
|
|
|
|
// If this mapping points to the same source location as the last one, we can ignore it since
|
|
// the previous one covers it.
|
|
if (this._lastGenLine === generatedLine && this._lastSourceLine === line &&
|
|
this._lastSourceColumn === column) {
|
|
return;
|
|
}
|
|
|
|
this._cachedMap = null;
|
|
this._lastGenLine = generatedLine;
|
|
this._lastSourceLine = line;
|
|
this._lastSourceColumn = column;
|
|
|
|
// We are deliberately not using the `source-map` library here to allow
|
|
// callers to use these mappings without any overhead
|
|
this._rawMappings.push({
|
|
// undefined to allow for more compact json serialization
|
|
name: identifierName || undefined,
|
|
generated: {
|
|
line: generatedLine,
|
|
column: generatedColumn,
|
|
},
|
|
source: line == null ? undefined : filename || this._opts.sourceFileName,
|
|
original: line == null ? undefined : {
|
|
line: line,
|
|
column: column,
|
|
},
|
|
});
|
|
}
|
|
}
|