source: frontend/node_modules/webpack-sources/lib/helpers/streamChunksOfCombinedSourceMap.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 11.7 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const splitIntoLines = require("./splitIntoLines");
9const streamChunksOfSourceMap = require("./streamChunksOfSourceMap");
10
11/** @typedef {import("../Source").RawSourceMap} RawSourceMap */
12/** @typedef {import("./getGeneratedSourceInfo").GeneratedSourceInfo} GeneratedSourceInfo */
13/** @typedef {import("./streamChunks").OnChunk} onChunk */
14/** @typedef {import("./streamChunks").OnName} OnName */
15/** @typedef {import("./streamChunks").OnSource} OnSource */
16
17/**
18 * @param {string} source source
19 * @param {RawSourceMap} sourceMap source map
20 * @param {string} innerSourceName inner source name
21 * @param {string} innerSource inner source
22 * @param {RawSourceMap} innerSourceMap inner source map
23 * @param {boolean | undefined} removeInnerSource do remove inner source
24 * @param {onChunk} onChunk on chunk
25 * @param {OnSource} onSource on source
26 * @param {OnName} onName on name
27 * @param {boolean} finalSource finalSource
28 * @param {boolean} columns columns
29 * @returns {GeneratedSourceInfo} generated source info
30 */
31const streamChunksOfCombinedSourceMap = (
32 source,
33 sourceMap,
34 innerSourceName,
35 innerSource,
36 innerSourceMap,
37 removeInnerSource,
38 onChunk,
39 onSource,
40 onName,
41 finalSource,
42 columns,
43) => {
44 /** @type {Map<string | null, number>} */
45 const sourceMapping = new Map();
46 /** @type {Map<string, number>} */
47 const nameMapping = new Map();
48 /** @type {number[]} */
49 const sourceIndexMapping = [];
50 /** @type {number[]} */
51 const nameIndexMapping = [];
52 /** @type {string[]} */
53 const nameIndexValueMapping = [];
54 let outerSourceIndex = -2;
55 /** @type {number[]} */
56 const innerSourceIndexMapping = [];
57 /** @type {[string | null, string | undefined][]} */
58 const innerSourceIndexValueMapping = [];
59 /** @type {(string | undefined)[]} */
60 const innerSourceContents = [];
61 /** @type {(null | undefined | string[])[]} */
62 const innerSourceContentLines = [];
63 /** @type {number[]} */
64 const innerNameIndexMapping = [];
65 /** @type {string[]} */
66 const innerNameIndexValueMapping = [];
67 /** @typedef {[number, number, number, number, number] | number[]} MappingsData */
68 /** @type {{ chunks: string[], mappingsData: MappingsData }[]} */
69 const innerSourceMapLineData = [];
70 /**
71 * @param {number} line line
72 * @param {number} column column
73 * @returns {number} result
74 */
75 const findInnerMapping = (line, column) => {
76 if (line > innerSourceMapLineData.length) return -1;
77 const { mappingsData } = innerSourceMapLineData[line - 1];
78 let l = 0;
79 // `mappingsData.length` is always a multiple of 5 (five values pushed
80 // per mapping), so dividing is exact. Coerce the bound to an int32 so
81 // the binary-search loop stays on V8's fast small-int path instead of
82 // comparing an int against a float.
83 let r = (mappingsData.length / 5) | 0;
84 while (l < r) {
85 const m = (l + r) >> 1;
86 if (mappingsData[m * 5] <= column) {
87 l = m + 1;
88 } else {
89 r = m;
90 }
91 }
92 if (l === 0) return -1;
93 return l - 1;
94 };
95 return streamChunksOfSourceMap(
96 source,
97 sourceMap,
98 (
99 chunk,
100 generatedLine,
101 generatedColumn,
102 sourceIndex,
103 originalLine,
104 originalColumn,
105 nameIndex,
106 ) => {
107 // Check if this is a mapping to the inner source
108 if (sourceIndex === outerSourceIndex) {
109 // Check if there is a mapping in the inner source
110 const idx = findInnerMapping(originalLine, originalColumn);
111 if (idx !== -1) {
112 const { chunks, mappingsData } =
113 innerSourceMapLineData[originalLine - 1];
114 const mi = idx * 5;
115 const innerSourceIndex = mappingsData[mi + 1];
116 const innerOriginalLine = mappingsData[mi + 2];
117 let innerOriginalColumn = mappingsData[mi + 3];
118 let innerNameIndex = mappingsData[mi + 4];
119 if (innerSourceIndex >= 0) {
120 // Check for an identity mapping
121 // where we are allowed to adjust the original column
122 const innerChunk = chunks[idx];
123 const innerGeneratedColumn = mappingsData[mi];
124 const locationInChunk = originalColumn - innerGeneratedColumn;
125 if (locationInChunk > 0) {
126 let originalSourceLines =
127 innerSourceIndex < innerSourceContentLines.length
128 ? innerSourceContentLines[innerSourceIndex]
129 : null;
130 if (originalSourceLines === undefined) {
131 const originalSource = innerSourceContents[innerSourceIndex];
132 originalSourceLines = originalSource
133 ? splitIntoLines(originalSource)
134 : null;
135 innerSourceContentLines[innerSourceIndex] = originalSourceLines;
136 }
137 if (originalSourceLines !== null) {
138 const originalChunk =
139 innerOriginalLine <= originalSourceLines.length
140 ? originalSourceLines[innerOriginalLine - 1].slice(
141 innerOriginalColumn,
142 innerOriginalColumn + locationInChunk,
143 )
144 : "";
145 if (innerChunk.slice(0, locationInChunk) === originalChunk) {
146 innerOriginalColumn += locationInChunk;
147 innerNameIndex = -1;
148 }
149 }
150 }
151
152 // We have a inner mapping to original source
153
154 // emit source when needed and compute global source index
155 let sourceIndex =
156 innerSourceIndex < innerSourceIndexMapping.length
157 ? innerSourceIndexMapping[innerSourceIndex]
158 : -2;
159 if (sourceIndex === -2) {
160 const [source, sourceContent] =
161 innerSourceIndex < innerSourceIndexValueMapping.length
162 ? innerSourceIndexValueMapping[innerSourceIndex]
163 : [null, undefined];
164 let globalIndex = sourceMapping.get(source);
165 if (globalIndex === undefined) {
166 sourceMapping.set(source, (globalIndex = sourceMapping.size));
167 onSource(globalIndex, source, sourceContent);
168 }
169 sourceIndex = globalIndex;
170 innerSourceIndexMapping[innerSourceIndex] = sourceIndex;
171 }
172
173 // emit name when needed and compute global name index
174 let finalNameIndex = -1;
175 if (innerNameIndex >= 0) {
176 // when we have a inner name
177 finalNameIndex =
178 innerNameIndex < innerNameIndexMapping.length
179 ? innerNameIndexMapping[innerNameIndex]
180 : -2;
181 if (finalNameIndex === -2) {
182 const name =
183 innerNameIndex < innerNameIndexValueMapping.length
184 ? innerNameIndexValueMapping[innerNameIndex]
185 : undefined;
186 if (name) {
187 let globalIndex = nameMapping.get(name);
188 if (globalIndex === undefined) {
189 nameMapping.set(name, (globalIndex = nameMapping.size));
190 onName(globalIndex, name);
191 }
192 finalNameIndex = globalIndex;
193 } else {
194 finalNameIndex = -1;
195 }
196 innerNameIndexMapping[innerNameIndex] = finalNameIndex;
197 }
198 } else if (nameIndex >= 0) {
199 // when we don't have an inner name,
200 // but we have an outer name
201 // it can be used when inner original code equals to the name
202 let originalSourceLines =
203 innerSourceContentLines[innerSourceIndex];
204 if (originalSourceLines === undefined) {
205 const originalSource = innerSourceContents[innerSourceIndex];
206 originalSourceLines = originalSource
207 ? splitIntoLines(originalSource)
208 : null;
209 innerSourceContentLines[innerSourceIndex] = originalSourceLines;
210 }
211 if (originalSourceLines !== null) {
212 const name = nameIndexValueMapping[nameIndex];
213 const originalName =
214 innerOriginalLine <= originalSourceLines.length
215 ? originalSourceLines[innerOriginalLine - 1].slice(
216 innerOriginalColumn,
217 innerOriginalColumn + name.length,
218 )
219 : "";
220 if (name === originalName) {
221 finalNameIndex =
222 nameIndex < nameIndexMapping.length
223 ? nameIndexMapping[nameIndex]
224 : -2;
225 if (finalNameIndex === -2) {
226 const name = nameIndexValueMapping[nameIndex];
227 if (name) {
228 let globalIndex = nameMapping.get(name);
229 if (globalIndex === undefined) {
230 nameMapping.set(name, (globalIndex = nameMapping.size));
231 onName(globalIndex, name);
232 }
233 finalNameIndex = globalIndex;
234 } else {
235 finalNameIndex = -1;
236 }
237 nameIndexMapping[nameIndex] = finalNameIndex;
238 }
239 }
240 }
241 }
242 onChunk(
243 chunk,
244 generatedLine,
245 generatedColumn,
246 sourceIndex,
247 innerOriginalLine,
248 innerOriginalColumn,
249 finalNameIndex,
250 );
251 return;
252 }
253 }
254
255 // We have a mapping to the inner source, but no inner mapping
256 if (removeInnerSource) {
257 onChunk(chunk, generatedLine, generatedColumn, -1, -1, -1, -1);
258 return;
259 }
260 if (sourceIndexMapping[sourceIndex] === -2) {
261 let globalIndex = sourceMapping.get(innerSourceName);
262 if (globalIndex === undefined) {
263 sourceMapping.set(source, (globalIndex = sourceMapping.size));
264 onSource(globalIndex, innerSourceName, innerSource);
265 }
266 sourceIndexMapping[sourceIndex] = globalIndex;
267 }
268 }
269
270 const finalSourceIndex =
271 sourceIndex < 0 || sourceIndex >= sourceIndexMapping.length
272 ? -1
273 : sourceIndexMapping[sourceIndex];
274 if (finalSourceIndex < 0) {
275 // no source, so we make it a generated chunk
276 onChunk(chunk, generatedLine, generatedColumn, -1, -1, -1, -1);
277 } else {
278 // Pass through the chunk with mapping
279 let finalNameIndex = -1;
280 if (nameIndex >= 0 && nameIndex < nameIndexMapping.length) {
281 finalNameIndex = nameIndexMapping[nameIndex];
282 if (finalNameIndex === -2) {
283 const name = nameIndexValueMapping[nameIndex];
284 let globalIndex = nameMapping.get(name);
285 if (globalIndex === undefined) {
286 nameMapping.set(name, (globalIndex = nameMapping.size));
287 onName(globalIndex, name);
288 }
289 finalNameIndex = globalIndex;
290 nameIndexMapping[nameIndex] = finalNameIndex;
291 }
292 }
293 onChunk(
294 chunk,
295 generatedLine,
296 generatedColumn,
297 finalSourceIndex,
298 originalLine,
299 originalColumn,
300 finalNameIndex,
301 );
302 }
303 },
304 (i, source, sourceContent) => {
305 if (source === innerSourceName) {
306 outerSourceIndex = i;
307 if (innerSource !== undefined) sourceContent = innerSource;
308 else innerSource = /** @type {string} */ (sourceContent);
309 sourceIndexMapping[i] = -2;
310 streamChunksOfSourceMap(
311 /** @type {string} */
312 (sourceContent),
313 innerSourceMap,
314 (
315 chunk,
316 generatedLine,
317 generatedColumn,
318 sourceIndex,
319 originalLine,
320 originalColumn,
321 nameIndex,
322 ) => {
323 while (innerSourceMapLineData.length < generatedLine) {
324 innerSourceMapLineData.push({
325 mappingsData: [],
326 chunks: [],
327 });
328 }
329 const data = innerSourceMapLineData[generatedLine - 1];
330 data.mappingsData.push(
331 generatedColumn,
332 sourceIndex,
333 originalLine,
334 originalColumn,
335 nameIndex,
336 );
337 data.chunks.push(/** @type {string} */ (chunk));
338 },
339 (i, source, sourceContent) => {
340 innerSourceContents[i] = sourceContent;
341 innerSourceContentLines[i] = undefined;
342 innerSourceIndexMapping[i] = -2;
343 innerSourceIndexValueMapping[i] = [source, sourceContent];
344 },
345 (i, name) => {
346 innerNameIndexMapping[i] = -2;
347 innerNameIndexValueMapping[i] = name;
348 },
349 false,
350 columns,
351 );
352 } else {
353 let globalIndex = sourceMapping.get(source);
354 if (globalIndex === undefined) {
355 sourceMapping.set(source, (globalIndex = sourceMapping.size));
356 onSource(globalIndex, source, sourceContent);
357 }
358 sourceIndexMapping[i] = globalIndex;
359 }
360 },
361 (i, name) => {
362 nameIndexMapping[i] = -2;
363 nameIndexValueMapping[i] = name;
364 },
365 finalSource,
366 columns,
367 );
368};
369
370module.exports = streamChunksOfCombinedSourceMap;
Note: See TracBrowser for help on using the repository browser.