Spaces:
Running
Running
import { SetArray, put } from '@jridgewell/set-array'; | |
import { encode } from '@jridgewell/sourcemap-codec'; | |
import { TraceMap, decodedMappings } from '@jridgewell/trace-mapping'; | |
const COLUMN = 0; | |
const SOURCES_INDEX = 1; | |
const SOURCE_LINE = 2; | |
const SOURCE_COLUMN = 3; | |
const NAMES_INDEX = 4; | |
const NO_NAME = -1; | |
/** | |
* A low-level API to associate a generated position with an original source position. Line and | |
* column here are 0-based, unlike `addMapping`. | |
*/ | |
let addSegment; | |
/** | |
* A high-level API to associate a generated position with an original source position. Line is | |
* 1-based, but column is 0-based, due to legacy behavior in `source-map` library. | |
*/ | |
let addMapping; | |
/** | |
* Same as `addSegment`, but will only add the segment if it generates useful information in the | |
* resulting map. This only works correctly if segments are added **in order**, meaning you should | |
* not add a segment with a lower generated line/column than one that came before. | |
*/ | |
let maybeAddSegment; | |
/** | |
* Same as `addMapping`, but will only add the mapping if it generates useful information in the | |
* resulting map. This only works correctly if mappings are added **in order**, meaning you should | |
* not add a mapping with a lower generated line/column than one that came before. | |
*/ | |
let maybeAddMapping; | |
/** | |
* Adds/removes the content of the source file to the source map. | |
*/ | |
let setSourceContent; | |
/** | |
* Returns a sourcemap object (with decoded mappings) suitable for passing to a library that expects | |
* a sourcemap, or to JSON.stringify. | |
*/ | |
let toDecodedMap; | |
/** | |
* Returns a sourcemap object (with encoded mappings) suitable for passing to a library that expects | |
* a sourcemap, or to JSON.stringify. | |
*/ | |
let toEncodedMap; | |
/** | |
* Constructs a new GenMapping, using the already present mappings of the input. | |
*/ | |
let fromMap; | |
/** | |
* Returns an array of high-level mapping objects for every recorded segment, which could then be | |
* passed to the `source-map` library. | |
*/ | |
let allMappings; | |
// This split declaration is only so that terser can elminiate the static initialization block. | |
let addSegmentInternal; | |
/** | |
* Provides the state to generate a sourcemap. | |
*/ | |
class GenMapping { | |
constructor({ file, sourceRoot } = {}) { | |
this._names = new SetArray(); | |
this._sources = new SetArray(); | |
this._sourcesContent = []; | |
this._mappings = []; | |
this.file = file; | |
this.sourceRoot = sourceRoot; | |
} | |
} | |
(() => { | |
addSegment = (map, genLine, genColumn, source, sourceLine, sourceColumn, name, content) => { | |
return addSegmentInternal(false, map, genLine, genColumn, source, sourceLine, sourceColumn, name, content); | |
}; | |
maybeAddSegment = (map, genLine, genColumn, source, sourceLine, sourceColumn, name, content) => { | |
return addSegmentInternal(true, map, genLine, genColumn, source, sourceLine, sourceColumn, name, content); | |
}; | |
addMapping = (map, mapping) => { | |
return addMappingInternal(false, map, mapping); | |
}; | |
maybeAddMapping = (map, mapping) => { | |
return addMappingInternal(true, map, mapping); | |
}; | |
setSourceContent = (map, source, content) => { | |
const { _sources: sources, _sourcesContent: sourcesContent } = map; | |
sourcesContent[put(sources, source)] = content; | |
}; | |
toDecodedMap = (map) => { | |
const { file, sourceRoot, _mappings: mappings, _sources: sources, _sourcesContent: sourcesContent, _names: names, } = map; | |
removeEmptyFinalLines(mappings); | |
return { | |
version: 3, | |
file: file || undefined, | |
names: names.array, | |
sourceRoot: sourceRoot || undefined, | |
sources: sources.array, | |
sourcesContent, | |
mappings, | |
}; | |
}; | |
toEncodedMap = (map) => { | |
const decoded = toDecodedMap(map); | |
return Object.assign(Object.assign({}, decoded), { mappings: encode(decoded.mappings) }); | |
}; | |
allMappings = (map) => { | |
const out = []; | |
const { _mappings: mappings, _sources: sources, _names: names } = map; | |
for (let i = 0; i < mappings.length; i++) { | |
const line = mappings[i]; | |
for (let j = 0; j < line.length; j++) { | |
const seg = line[j]; | |
const generated = { line: i + 1, column: seg[COLUMN] }; | |
let source = undefined; | |
let original = undefined; | |
let name = undefined; | |
if (seg.length !== 1) { | |
source = sources.array[seg[SOURCES_INDEX]]; | |
original = { line: seg[SOURCE_LINE] + 1, column: seg[SOURCE_COLUMN] }; | |
if (seg.length === 5) | |
name = names.array[seg[NAMES_INDEX]]; | |
} | |
out.push({ generated, source, original, name }); | |
} | |
} | |
return out; | |
}; | |
fromMap = (input) => { | |
const map = new TraceMap(input); | |
const gen = new GenMapping({ file: map.file, sourceRoot: map.sourceRoot }); | |
putAll(gen._names, map.names); | |
putAll(gen._sources, map.sources); | |
gen._sourcesContent = map.sourcesContent || map.sources.map(() => null); | |
gen._mappings = decodedMappings(map); | |
return gen; | |
}; | |
// Internal helpers | |
addSegmentInternal = (skipable, map, genLine, genColumn, source, sourceLine, sourceColumn, name, content) => { | |
const { _mappings: mappings, _sources: sources, _sourcesContent: sourcesContent, _names: names, } = map; | |
const line = getLine(mappings, genLine); | |
const index = getColumnIndex(line, genColumn); | |
if (!source) { | |
if (skipable && skipSourceless(line, index)) | |
return; | |
return insert(line, index, [genColumn]); | |
} | |
const sourcesIndex = put(sources, source); | |
const namesIndex = name ? put(names, name) : NO_NAME; | |
if (sourcesIndex === sourcesContent.length) | |
sourcesContent[sourcesIndex] = content !== null && content !== void 0 ? content : null; | |
if (skipable && skipSource(line, index, sourcesIndex, sourceLine, sourceColumn, namesIndex)) { | |
return; | |
} | |
return insert(line, index, name | |
? [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex] | |
: [genColumn, sourcesIndex, sourceLine, sourceColumn]); | |
}; | |
})(); | |
function getLine(mappings, index) { | |
for (let i = mappings.length; i <= index; i++) { | |
mappings[i] = []; | |
} | |
return mappings[index]; | |
} | |
function getColumnIndex(line, genColumn) { | |
let index = line.length; | |
for (let i = index - 1; i >= 0; index = i--) { | |
const current = line[i]; | |
if (genColumn >= current[COLUMN]) | |
break; | |
} | |
return index; | |
} | |
function insert(array, index, value) { | |
for (let i = array.length; i > index; i--) { | |
array[i] = array[i - 1]; | |
} | |
array[index] = value; | |
} | |
function removeEmptyFinalLines(mappings) { | |
const { length } = mappings; | |
let len = length; | |
for (let i = len - 1; i >= 0; len = i, i--) { | |
if (mappings[i].length > 0) | |
break; | |
} | |
if (len < length) | |
mappings.length = len; | |
} | |
function putAll(strarr, array) { | |
for (let i = 0; i < array.length; i++) | |
put(strarr, array[i]); | |
} | |
function skipSourceless(line, index) { | |
// The start of a line is already sourceless, so adding a sourceless segment to the beginning | |
// doesn't generate any useful information. | |
if (index === 0) | |
return true; | |
const prev = line[index - 1]; | |
// If the previous segment is also sourceless, then adding another sourceless segment doesn't | |
// genrate any new information. Else, this segment will end the source/named segment and point to | |
// a sourceless position, which is useful. | |
return prev.length === 1; | |
} | |
function skipSource(line, index, sourcesIndex, sourceLine, sourceColumn, namesIndex) { | |
// A source/named segment at the start of a line gives position at that genColumn | |
if (index === 0) | |
return false; | |
const prev = line[index - 1]; | |
// If the previous segment is sourceless, then we're transitioning to a source. | |
if (prev.length === 1) | |
return false; | |
// If the previous segment maps to the exact same source position, then this segment doesn't | |
// provide any new position information. | |
return (sourcesIndex === prev[SOURCES_INDEX] && | |
sourceLine === prev[SOURCE_LINE] && | |
sourceColumn === prev[SOURCE_COLUMN] && | |
namesIndex === (prev.length === 5 ? prev[NAMES_INDEX] : NO_NAME)); | |
} | |
function addMappingInternal(skipable, map, mapping) { | |
const { generated, source, original, name, content } = mapping; | |
if (!source) { | |
return addSegmentInternal(skipable, map, generated.line - 1, generated.column, null, null, null, null, null); | |
} | |
const s = source; | |
return addSegmentInternal(skipable, map, generated.line - 1, generated.column, s, original.line - 1, original.column, name, content); | |
} | |
export { GenMapping, addMapping, addSegment, allMappings, fromMap, maybeAddMapping, maybeAddSegment, setSourceContent, toDecodedMap, toEncodedMap }; | |
//# sourceMappingURL=gen-mapping.mjs.map | |