1 |
|
2 | import {createRequire as __cjsCompatRequire} from 'module';
|
3 | const require = __cjsCompatRequire(import.meta.url);
|
4 |
|
5 |
|
6 |
|
7 | import { decode, encode } from "@jridgewell/sourcemap-codec";
|
8 | import mapHelpers from "convert-source-map";
|
9 |
|
10 |
|
11 | function compareSegments(a, b) {
|
12 | return a.position - b.position;
|
13 | }
|
14 | function offsetSegment(startOfLinePositions, marker, offset) {
|
15 | if (offset === 0) {
|
16 | return marker;
|
17 | }
|
18 | let line = marker.line;
|
19 | const position = marker.position + offset;
|
20 | while (line < startOfLinePositions.length - 1 && startOfLinePositions[line + 1] <= position) {
|
21 | line++;
|
22 | }
|
23 | while (line > 0 && startOfLinePositions[line] > position) {
|
24 | line--;
|
25 | }
|
26 | const column = position - startOfLinePositions[line];
|
27 | return { line, column, position, next: void 0 };
|
28 | }
|
29 |
|
30 |
|
31 | function removeSourceMapComments(contents) {
|
32 | return mapHelpers.removeMapFileComments(mapHelpers.removeComments(contents)).replace(/\n\n$/, "\n");
|
33 | }
|
34 | var SourceFile = class {
|
35 | constructor(sourcePath, contents, rawMap, sources, fs) {
|
36 | this.sourcePath = sourcePath;
|
37 | this.contents = contents;
|
38 | this.rawMap = rawMap;
|
39 | this.sources = sources;
|
40 | this.fs = fs;
|
41 | this.contents = removeSourceMapComments(contents);
|
42 | this.startOfLinePositions = computeStartOfLinePositions(this.contents);
|
43 | this.flattenedMappings = this.flattenMappings();
|
44 | }
|
45 | renderFlattenedSourceMap() {
|
46 | const sources = new IndexedMap();
|
47 | const names = new IndexedSet();
|
48 | const mappings = [];
|
49 | const sourcePathDir = this.fs.dirname(this.sourcePath);
|
50 | const relativeSourcePathCache = new Cache((input) => this.fs.relative(sourcePathDir, input));
|
51 | for (const mapping of this.flattenedMappings) {
|
52 | const sourceIndex = sources.set(relativeSourcePathCache.get(mapping.originalSource.sourcePath), mapping.originalSource.contents);
|
53 | const mappingArray = [
|
54 | mapping.generatedSegment.column,
|
55 | sourceIndex,
|
56 | mapping.originalSegment.line,
|
57 | mapping.originalSegment.column
|
58 | ];
|
59 | if (mapping.name !== void 0) {
|
60 | const nameIndex = names.add(mapping.name);
|
61 | mappingArray.push(nameIndex);
|
62 | }
|
63 | const line = mapping.generatedSegment.line;
|
64 | while (line >= mappings.length) {
|
65 | mappings.push([]);
|
66 | }
|
67 | mappings[line].push(mappingArray);
|
68 | }
|
69 | const sourceMap = {
|
70 | version: 3,
|
71 | file: this.fs.relative(sourcePathDir, this.sourcePath),
|
72 | sources: sources.keys,
|
73 | names: names.values,
|
74 | mappings: encode(mappings),
|
75 | sourcesContent: sources.values
|
76 | };
|
77 | return sourceMap;
|
78 | }
|
79 | getOriginalLocation(line, column) {
|
80 | if (this.flattenedMappings.length === 0) {
|
81 | return null;
|
82 | }
|
83 | let position;
|
84 | if (line < this.startOfLinePositions.length) {
|
85 | position = this.startOfLinePositions[line] + column;
|
86 | } else {
|
87 | position = this.contents.length;
|
88 | }
|
89 | const locationSegment = { line, column, position, next: void 0 };
|
90 | let mappingIndex = findLastMappingIndexBefore(this.flattenedMappings, locationSegment, false, 0);
|
91 | if (mappingIndex < 0) {
|
92 | mappingIndex = 0;
|
93 | }
|
94 | const { originalSegment, originalSource, generatedSegment } = this.flattenedMappings[mappingIndex];
|
95 | const offset = locationSegment.position - generatedSegment.position;
|
96 | const offsetOriginalSegment = offsetSegment(originalSource.startOfLinePositions, originalSegment, offset);
|
97 | return {
|
98 | file: originalSource.sourcePath,
|
99 | line: offsetOriginalSegment.line,
|
100 | column: offsetOriginalSegment.column
|
101 | };
|
102 | }
|
103 | flattenMappings() {
|
104 | const mappings = parseMappings(this.rawMap && this.rawMap.map, this.sources, this.startOfLinePositions);
|
105 | ensureOriginalSegmentLinks(mappings);
|
106 | const flattenedMappings = [];
|
107 | for (let mappingIndex = 0; mappingIndex < mappings.length; mappingIndex++) {
|
108 | const aToBmapping = mappings[mappingIndex];
|
109 | const bSource = aToBmapping.originalSource;
|
110 | if (bSource.flattenedMappings.length === 0) {
|
111 | flattenedMappings.push(aToBmapping);
|
112 | continue;
|
113 | }
|
114 | const incomingStart = aToBmapping.originalSegment;
|
115 | const incomingEnd = incomingStart.next;
|
116 | let outgoingStartIndex = findLastMappingIndexBefore(bSource.flattenedMappings, incomingStart, false, 0);
|
117 | if (outgoingStartIndex < 0) {
|
118 | outgoingStartIndex = 0;
|
119 | }
|
120 | const outgoingEndIndex = incomingEnd !== void 0 ? findLastMappingIndexBefore(bSource.flattenedMappings, incomingEnd, true, outgoingStartIndex) : bSource.flattenedMappings.length - 1;
|
121 | for (let bToCmappingIndex = outgoingStartIndex; bToCmappingIndex <= outgoingEndIndex; bToCmappingIndex++) {
|
122 | const bToCmapping = bSource.flattenedMappings[bToCmappingIndex];
|
123 | flattenedMappings.push(mergeMappings(this, aToBmapping, bToCmapping));
|
124 | }
|
125 | }
|
126 | return flattenedMappings;
|
127 | }
|
128 | };
|
129 | function findLastMappingIndexBefore(mappings, marker, exclusive, lowerIndex) {
|
130 | let upperIndex = mappings.length - 1;
|
131 | const test = exclusive ? -1 : 0;
|
132 | if (compareSegments(mappings[lowerIndex].generatedSegment, marker) > test) {
|
133 | return -1;
|
134 | }
|
135 | let matchingIndex = -1;
|
136 | while (lowerIndex <= upperIndex) {
|
137 | const index = upperIndex + lowerIndex >> 1;
|
138 | if (compareSegments(mappings[index].generatedSegment, marker) <= test) {
|
139 | matchingIndex = index;
|
140 | lowerIndex = index + 1;
|
141 | } else {
|
142 | upperIndex = index - 1;
|
143 | }
|
144 | }
|
145 | return matchingIndex;
|
146 | }
|
147 | function mergeMappings(generatedSource, ab, bc) {
|
148 | const name = bc.name || ab.name;
|
149 | const diff = compareSegments(bc.generatedSegment, ab.originalSegment);
|
150 | if (diff > 0) {
|
151 | return {
|
152 | name,
|
153 | generatedSegment: offsetSegment(generatedSource.startOfLinePositions, ab.generatedSegment, diff),
|
154 | originalSource: bc.originalSource,
|
155 | originalSegment: bc.originalSegment
|
156 | };
|
157 | } else {
|
158 | return {
|
159 | name,
|
160 | generatedSegment: ab.generatedSegment,
|
161 | originalSource: bc.originalSource,
|
162 | originalSegment: offsetSegment(bc.originalSource.startOfLinePositions, bc.originalSegment, -diff)
|
163 | };
|
164 | }
|
165 | }
|
166 | function parseMappings(rawMap, sources, generatedSourceStartOfLinePositions) {
|
167 | if (rawMap === null) {
|
168 | return [];
|
169 | }
|
170 | const rawMappings = decode(rawMap.mappings);
|
171 | if (rawMappings === null) {
|
172 | return [];
|
173 | }
|
174 | const mappings = [];
|
175 | for (let generatedLine = 0; generatedLine < rawMappings.length; generatedLine++) {
|
176 | const generatedLineMappings = rawMappings[generatedLine];
|
177 | for (const rawMapping of generatedLineMappings) {
|
178 | if (rawMapping.length >= 4) {
|
179 | const originalSource = sources[rawMapping[1]];
|
180 | if (originalSource === null || originalSource === void 0) {
|
181 | continue;
|
182 | }
|
183 | const generatedColumn = rawMapping[0];
|
184 | const name = rawMapping.length === 5 ? rawMap.names[rawMapping[4]] : void 0;
|
185 | const line = rawMapping[2];
|
186 | const column = rawMapping[3];
|
187 | const generatedSegment = {
|
188 | line: generatedLine,
|
189 | column: generatedColumn,
|
190 | position: generatedSourceStartOfLinePositions[generatedLine] + generatedColumn,
|
191 | next: void 0
|
192 | };
|
193 | const originalSegment = {
|
194 | line,
|
195 | column,
|
196 | position: originalSource.startOfLinePositions[line] + column,
|
197 | next: void 0
|
198 | };
|
199 | mappings.push({ name, generatedSegment, originalSegment, originalSource });
|
200 | }
|
201 | }
|
202 | }
|
203 | return mappings;
|
204 | }
|
205 | function extractOriginalSegments(mappings) {
|
206 | const originalSegments = new Map();
|
207 | for (const mapping of mappings) {
|
208 | const originalSource = mapping.originalSource;
|
209 | if (!originalSegments.has(originalSource)) {
|
210 | originalSegments.set(originalSource, []);
|
211 | }
|
212 | const segments = originalSegments.get(originalSource);
|
213 | segments.push(mapping.originalSegment);
|
214 | }
|
215 | originalSegments.forEach((segmentMarkers) => segmentMarkers.sort(compareSegments));
|
216 | return originalSegments;
|
217 | }
|
218 | function ensureOriginalSegmentLinks(mappings) {
|
219 | const segmentsBySource = extractOriginalSegments(mappings);
|
220 | segmentsBySource.forEach((markers) => {
|
221 | for (let i = 0; i < markers.length - 1; i++) {
|
222 | markers[i].next = markers[i + 1];
|
223 | }
|
224 | });
|
225 | }
|
226 | function computeStartOfLinePositions(str) {
|
227 | const NEWLINE_MARKER_OFFSET = 1;
|
228 | const lineLengths = computeLineLengths(str);
|
229 | const startPositions = [0];
|
230 | for (let i = 0; i < lineLengths.length - 1; i++) {
|
231 | startPositions.push(startPositions[i] + lineLengths[i] + NEWLINE_MARKER_OFFSET);
|
232 | }
|
233 | return startPositions;
|
234 | }
|
235 | function computeLineLengths(str) {
|
236 | return str.split(/\n/).map((s) => s.length);
|
237 | }
|
238 | var IndexedMap = class {
|
239 | constructor() {
|
240 | this.map = new Map();
|
241 | this.keys = [];
|
242 | this.values = [];
|
243 | }
|
244 | set(key, value) {
|
245 | if (this.map.has(key)) {
|
246 | return this.map.get(key);
|
247 | }
|
248 | const index = this.values.push(value) - 1;
|
249 | this.keys.push(key);
|
250 | this.map.set(key, index);
|
251 | return index;
|
252 | }
|
253 | };
|
254 | var IndexedSet = class {
|
255 | constructor() {
|
256 | this.map = new Map();
|
257 | this.values = [];
|
258 | }
|
259 | add(value) {
|
260 | if (this.map.has(value)) {
|
261 | return this.map.get(value);
|
262 | }
|
263 | const index = this.values.push(value) - 1;
|
264 | this.map.set(value, index);
|
265 | return index;
|
266 | }
|
267 | };
|
268 | var Cache = class {
|
269 | constructor(computeFn) {
|
270 | this.computeFn = computeFn;
|
271 | this.map = new Map();
|
272 | }
|
273 | get(input) {
|
274 | if (!this.map.has(input)) {
|
275 | this.map.set(input, this.computeFn(input));
|
276 | }
|
277 | return this.map.get(input);
|
278 | }
|
279 | };
|
280 |
|
281 |
|
282 | import mapHelpers2 from "convert-source-map";
|
283 |
|
284 |
|
285 | var ContentOrigin;
|
286 | (function(ContentOrigin2) {
|
287 | ContentOrigin2[ContentOrigin2["Provided"] = 0] = "Provided";
|
288 | ContentOrigin2[ContentOrigin2["Inline"] = 1] = "Inline";
|
289 | ContentOrigin2[ContentOrigin2["FileSystem"] = 2] = "FileSystem";
|
290 | })(ContentOrigin || (ContentOrigin = {}));
|
291 |
|
292 |
|
293 | var SCHEME_MATCHER = /^([a-z][a-z0-9.-]*):\/\//i;
|
294 | var SourceFileLoader = class {
|
295 | constructor(fs, logger, schemeMap) {
|
296 | this.fs = fs;
|
297 | this.logger = logger;
|
298 | this.schemeMap = schemeMap;
|
299 | this.currentPaths = [];
|
300 | }
|
301 | loadSourceFile(sourcePath, contents = null, mapAndPath = null) {
|
302 | const contentsOrigin = contents !== null ? ContentOrigin.Provided : ContentOrigin.FileSystem;
|
303 | const sourceMapInfo = mapAndPath && { origin: ContentOrigin.Provided, ...mapAndPath };
|
304 | return this.loadSourceFileInternal(sourcePath, contents, contentsOrigin, sourceMapInfo);
|
305 | }
|
306 | loadSourceFileInternal(sourcePath, contents, sourceOrigin, sourceMapInfo) {
|
307 | const previousPaths = this.currentPaths.slice();
|
308 | try {
|
309 | if (contents === null) {
|
310 | if (!this.fs.exists(sourcePath)) {
|
311 | return null;
|
312 | }
|
313 | contents = this.readSourceFile(sourcePath);
|
314 | }
|
315 | if (sourceMapInfo === null) {
|
316 | sourceMapInfo = this.loadSourceMap(sourcePath, contents, sourceOrigin);
|
317 | }
|
318 | let sources = [];
|
319 | if (sourceMapInfo !== null) {
|
320 | const basePath = sourceMapInfo.mapPath || sourcePath;
|
321 | sources = this.processSources(basePath, sourceMapInfo);
|
322 | }
|
323 | return new SourceFile(sourcePath, contents, sourceMapInfo, sources, this.fs);
|
324 | } catch (e) {
|
325 | this.logger.warn(`Unable to fully load ${sourcePath} for source-map flattening: ${e.message}`);
|
326 | return null;
|
327 | } finally {
|
328 | this.currentPaths = previousPaths;
|
329 | }
|
330 | }
|
331 | loadSourceMap(sourcePath, sourceContents, sourceOrigin) {
|
332 | const lastLine = this.getLastNonEmptyLine(sourceContents);
|
333 | const inline = mapHelpers2.commentRegex.exec(lastLine);
|
334 | if (inline !== null) {
|
335 | return {
|
336 | map: mapHelpers2.fromComment(inline.pop()).sourcemap,
|
337 | mapPath: null,
|
338 | origin: ContentOrigin.Inline
|
339 | };
|
340 | }
|
341 | if (sourceOrigin === ContentOrigin.Inline) {
|
342 | return null;
|
343 | }
|
344 | const external = mapHelpers2.mapFileCommentRegex.exec(lastLine);
|
345 | if (external) {
|
346 | try {
|
347 | const fileName = external[1] || external[2];
|
348 | const externalMapPath = this.fs.resolve(this.fs.dirname(sourcePath), fileName);
|
349 | return {
|
350 | map: this.readRawSourceMap(externalMapPath),
|
351 | mapPath: externalMapPath,
|
352 | origin: ContentOrigin.FileSystem
|
353 | };
|
354 | } catch (e) {
|
355 | this.logger.warn(`Unable to fully load ${sourcePath} for source-map flattening: ${e.message}`);
|
356 | return null;
|
357 | }
|
358 | }
|
359 | const impliedMapPath = this.fs.resolve(sourcePath + ".map");
|
360 | if (this.fs.exists(impliedMapPath)) {
|
361 | return {
|
362 | map: this.readRawSourceMap(impliedMapPath),
|
363 | mapPath: impliedMapPath,
|
364 | origin: ContentOrigin.FileSystem
|
365 | };
|
366 | }
|
367 | return null;
|
368 | }
|
369 | processSources(basePath, { map, origin: sourceMapOrigin }) {
|
370 | const sourceRoot = this.fs.resolve(this.fs.dirname(basePath), this.replaceSchemeWithPath(map.sourceRoot || ""));
|
371 | return map.sources.map((source, index) => {
|
372 | const path = this.fs.resolve(sourceRoot, this.replaceSchemeWithPath(source));
|
373 | const content = map.sourcesContent && map.sourcesContent[index] || null;
|
374 | const sourceOrigin = content !== null && sourceMapOrigin !== ContentOrigin.Provided ? ContentOrigin.Inline : ContentOrigin.FileSystem;
|
375 | return this.loadSourceFileInternal(path, content, sourceOrigin, null);
|
376 | });
|
377 | }
|
378 | readSourceFile(sourcePath) {
|
379 | this.trackPath(sourcePath);
|
380 | return this.fs.readFile(sourcePath);
|
381 | }
|
382 | readRawSourceMap(mapPath) {
|
383 | this.trackPath(mapPath);
|
384 | return JSON.parse(this.fs.readFile(mapPath));
|
385 | }
|
386 | trackPath(path) {
|
387 | if (this.currentPaths.includes(path)) {
|
388 | throw new Error(`Circular source file mapping dependency: ${this.currentPaths.join(" -> ")} -> ${path}`);
|
389 | }
|
390 | this.currentPaths.push(path);
|
391 | }
|
392 | getLastNonEmptyLine(contents) {
|
393 | let trailingWhitespaceIndex = contents.length - 1;
|
394 | while (trailingWhitespaceIndex > 0 && (contents[trailingWhitespaceIndex] === "\n" || contents[trailingWhitespaceIndex] === "\r")) {
|
395 | trailingWhitespaceIndex--;
|
396 | }
|
397 | let lastRealLineIndex = contents.lastIndexOf("\n", trailingWhitespaceIndex - 1);
|
398 | if (lastRealLineIndex === -1) {
|
399 | lastRealLineIndex = 0;
|
400 | }
|
401 | return contents.slice(lastRealLineIndex + 1);
|
402 | }
|
403 | replaceSchemeWithPath(path) {
|
404 | return path.replace(SCHEME_MATCHER, (_, scheme) => this.schemeMap[scheme.toLowerCase()] || "");
|
405 | }
|
406 | };
|
407 |
|
408 | export {
|
409 | SourceFile,
|
410 | SourceFileLoader
|
411 | };
|
412 |
|
413 |
|
414 |
|
415 |
|
416 |
|
417 |
|
418 |
|
419 |
|