source: frontend/node_modules/webpack-sources/lib/ConcatSource.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.6 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 RawSource = require("./RawSource");
9const Source = require("./Source");
10const { getMap, getSourceAndMap } = require("./helpers/getFromStreamChunks");
11const streamChunks = require("./helpers/streamChunks");
12
13/** @typedef {import("./CompatSource").SourceLike} SourceLike */
14/** @typedef {import("./Source").HashLike} HashLike */
15/** @typedef {import("./Source").MapOptions} MapOptions */
16/** @typedef {import("./Source").RawSourceMap} RawSourceMap */
17/** @typedef {import("./Source").SourceAndMap} SourceAndMap */
18/** @typedef {import("./Source").SourceValue} SourceValue */
19/** @typedef {import("./helpers/getGeneratedSourceInfo").GeneratedSourceInfo} GeneratedSourceInfo */
20/** @typedef {import("./helpers/streamChunks").OnChunk} OnChunk */
21/** @typedef {import("./helpers/streamChunks").OnName} OnName */
22/** @typedef {import("./helpers/streamChunks").OnSource} OnSource */
23/** @typedef {import("./helpers/streamChunks").Options} Options */
24
25/** @typedef {string | Source | SourceLike} Child */
26
27const stringsAsRawSources = new WeakSet();
28
29class ConcatSource extends Source {
30 /**
31 * @param {Child[]} args children
32 */
33 constructor(...args) {
34 super();
35 /**
36 * @private
37 * @type {Child[]}
38 */
39 this._children = [];
40
41 // Indexed loops avoid the iterator-protocol overhead `for...of`
42 // pays per element. Hot during webpack's emit when many
43 // ConcatSources are constructed/flattened.
44 for (let i = 0, l = args.length; i < l; i++) {
45 const item = args[i];
46 if (item instanceof ConcatSource) {
47 const children = item._children;
48 for (let j = 0, jl = children.length; j < jl; j++) {
49 this._children.push(children[j]);
50 }
51 } else {
52 this._children.push(item);
53 }
54 }
55
56 /**
57 * @private
58 * @type {boolean}
59 */
60 this._isOptimized = args.length === 0;
61 }
62
63 /**
64 * @returns {Source[]} children
65 */
66 getChildren() {
67 if (!this._isOptimized) this._optimize();
68 return /** @type {Source[]} */ (this._children);
69 }
70
71 /**
72 * @param {Child} item item
73 * @returns {void}
74 */
75 add(item) {
76 if (item instanceof ConcatSource) {
77 const children = item._children;
78 for (let i = 0, l = children.length; i < l; i++) {
79 this._children.push(children[i]);
80 }
81 } else {
82 this._children.push(item);
83 }
84 this._isOptimized = false;
85 }
86
87 /**
88 * @param {Child[]} items items
89 * @returns {void}
90 */
91 addAllSkipOptimizing(items) {
92 for (let i = 0, l = items.length; i < l; i++) {
93 this._children.push(items[i]);
94 }
95 }
96
97 /**
98 * @returns {Buffer} buffer
99 */
100 buffer() {
101 return Buffer.concat(this.buffers());
102 }
103
104 /**
105 * @returns {Buffer[]} buffers
106 */
107 buffers() {
108 if (!this._isOptimized) this._optimize();
109 const children = /** @type {SourceLike[]} */ (this._children);
110 const childCount = children.length;
111 /** @type {Buffer[]} */
112 const buffers = [];
113 // Indexed loop + manual splat avoids the iterator allocation per
114 // child and the inner for-of allocation per child.buffers() call.
115 // Hot path during webpack's emit on deeply-nested ConcatSources.
116 for (let ci = 0; ci < childCount; ci++) {
117 const child = children[ci];
118 if (typeof child.buffers === "function") {
119 const childBuffers = child.buffers();
120 for (let bi = 0, blen = childBuffers.length; bi < blen; bi++) {
121 buffers.push(childBuffers[bi]);
122 }
123 } else if (typeof child.buffer === "function") {
124 buffers.push(child.buffer());
125 } else {
126 const bufferOrString = child.source();
127 if (Buffer.isBuffer(bufferOrString)) {
128 buffers.push(bufferOrString);
129 } else {
130 // This will not happen
131 buffers.push(Buffer.from(bufferOrString, "utf8"));
132 }
133 }
134 }
135 return buffers;
136 }
137
138 /**
139 * @returns {SourceValue} source
140 */
141 source() {
142 if (!this._isOptimized) this._optimize();
143 const children = /** @type {Source[]} */ (this._children);
144 const childCount = children.length;
145 let source = "";
146 for (let ci = 0; ci < childCount; ci++) {
147 source += children[ci].source();
148 }
149 return source;
150 }
151
152 /**
153 * @returns {number} size
154 */
155 size() {
156 if (!this._isOptimized) this._optimize();
157 const children = /** @type {Source[]} */ (this._children);
158 const childCount = children.length;
159 let size = 0;
160 for (let ci = 0; ci < childCount; ci++) {
161 size += children[ci].size();
162 }
163 return size;
164 }
165
166 /**
167 * @param {MapOptions=} options map options
168 * @returns {RawSourceMap | null} map
169 */
170 map(options) {
171 return getMap(this, options);
172 }
173
174 /**
175 * @param {MapOptions=} options map options
176 * @returns {SourceAndMap} source and map
177 */
178 sourceAndMap(options) {
179 return getSourceAndMap(this, options);
180 }
181
182 /**
183 * @param {Options} options options
184 * @param {OnChunk} onChunk called for each chunk of code
185 * @param {OnSource} onSource called for each source
186 * @param {OnName} onName called for each name
187 * @returns {GeneratedSourceInfo} generated source info
188 */
189 streamChunks(options, onChunk, onSource, onName) {
190 if (!this._isOptimized) this._optimize();
191 if (this._children.length === 1) {
192 return /** @type {ConcatSource[]} */ (this._children)[0].streamChunks(
193 options,
194 onChunk,
195 onSource,
196 onName,
197 );
198 }
199 let currentLineOffset = 0;
200 let currentColumnOffset = 0;
201 const sourceMapping = new Map();
202 const nameMapping = new Map();
203 const finalSource = Boolean(options && options.finalSource);
204 let code = "";
205 let needToCloseMapping = false;
206 const children = /** @type {Source[]} */ (this._children);
207 const childCount = children.length;
208 for (let ci = 0; ci < childCount; ci++) {
209 const item = children[ci];
210 /** @type {number[]} */
211 const sourceIndexMapping = [];
212 /** @type {number[]} */
213 const nameIndexMapping = [];
214 let lastMappingLine = 0;
215 const { generatedLine, generatedColumn, source } = streamChunks(
216 item,
217 options,
218 // eslint-disable-next-line no-loop-func
219 (
220 chunk,
221 generatedLine,
222 generatedColumn,
223 sourceIndex,
224 originalLine,
225 originalColumn,
226 nameIndex,
227 ) => {
228 const line = generatedLine + currentLineOffset;
229 const column =
230 generatedLine === 1
231 ? generatedColumn + currentColumnOffset
232 : generatedColumn;
233 if (needToCloseMapping) {
234 if (generatedLine !== 1 || generatedColumn !== 0) {
235 onChunk(
236 undefined,
237 currentLineOffset + 1,
238 currentColumnOffset,
239 -1,
240 -1,
241 -1,
242 -1,
243 );
244 }
245 needToCloseMapping = false;
246 }
247 const resultSourceIndex =
248 sourceIndex < 0 || sourceIndex >= sourceIndexMapping.length
249 ? -1
250 : sourceIndexMapping[sourceIndex];
251 let _chunk;
252 // When using finalSource, we process the entire source code at once at the end, rather than chunk by chunk
253 if (finalSource) {
254 if (chunk !== undefined) code += chunk;
255 } else {
256 _chunk = chunk;
257 }
258 if (resultSourceIndex < 0) {
259 lastMappingLine = 0;
260 onChunk(_chunk, line, column, -1, -1, -1, -1);
261 } else {
262 // Only compute the remapped name index when the chunk
263 // actually carries a source mapping; otherwise it is
264 // unused.
265 const resultNameIndex =
266 nameIndex < 0 || nameIndex >= nameIndexMapping.length
267 ? -1
268 : nameIndexMapping[nameIndex];
269 lastMappingLine = generatedLine;
270 onChunk(
271 _chunk,
272 line,
273 column,
274 resultSourceIndex,
275 originalLine,
276 originalColumn,
277 resultNameIndex,
278 );
279 }
280 },
281 (i, source, sourceContent) => {
282 let globalIndex = sourceMapping.get(source);
283 if (globalIndex === undefined) {
284 sourceMapping.set(source, (globalIndex = sourceMapping.size));
285 onSource(globalIndex, source, sourceContent);
286 }
287 sourceIndexMapping[i] = globalIndex;
288 },
289 (i, name) => {
290 let globalIndex = nameMapping.get(name);
291 if (globalIndex === undefined) {
292 nameMapping.set(name, (globalIndex = nameMapping.size));
293 onName(globalIndex, name);
294 }
295 nameIndexMapping[i] = globalIndex;
296 },
297 );
298 if (source !== undefined) code += source;
299 if (
300 needToCloseMapping &&
301 (generatedLine !== 1 || generatedColumn !== 0)
302 ) {
303 onChunk(
304 undefined,
305 currentLineOffset + 1,
306 currentColumnOffset,
307 -1,
308 -1,
309 -1,
310 -1,
311 );
312 needToCloseMapping = false;
313 }
314 if (/** @type {number} */ (generatedLine) > 1) {
315 currentColumnOffset = /** @type {number} */ (generatedColumn);
316 } else {
317 currentColumnOffset += /** @type {number} */ (generatedColumn);
318 }
319 needToCloseMapping =
320 needToCloseMapping ||
321 (finalSource && lastMappingLine === generatedLine);
322 currentLineOffset += /** @type {number} */ (generatedLine) - 1;
323 }
324 return {
325 generatedLine: currentLineOffset + 1,
326 generatedColumn: currentColumnOffset,
327 source: finalSource ? code : undefined,
328 };
329 }
330
331 /**
332 * @param {HashLike} hash hash
333 * @returns {void}
334 */
335 updateHash(hash) {
336 if (!this._isOptimized) this._optimize();
337 const children = /** @type {Source[]} */ (this._children);
338 const childCount = children.length;
339 hash.update("ConcatSource");
340 for (let ci = 0; ci < childCount; ci++) {
341 children[ci].updateHash(hash);
342 }
343 }
344
345 _optimize() {
346 const newChildren = [];
347 let currentString;
348 /** @type {undefined | string | [string, string] | SourceLike} */
349 let currentRawSources;
350 /**
351 * @param {string} string string
352 * @returns {void}
353 */
354 const addStringToRawSources = (string) => {
355 if (currentRawSources === undefined) {
356 currentRawSources = string;
357 } else if (Array.isArray(currentRawSources)) {
358 currentRawSources.push(string);
359 } else {
360 currentRawSources = [
361 typeof currentRawSources === "string"
362 ? currentRawSources
363 : /** @type {string} */ (currentRawSources.source()),
364 string,
365 ];
366 }
367 };
368 /**
369 * @param {SourceLike} source source
370 * @returns {void}
371 */
372 const addSourceToRawSources = (source) => {
373 if (currentRawSources === undefined) {
374 currentRawSources = source;
375 } else if (Array.isArray(currentRawSources)) {
376 currentRawSources.push(
377 /** @type {string} */
378 (source.source()),
379 );
380 } else {
381 currentRawSources = [
382 typeof currentRawSources === "string"
383 ? currentRawSources
384 : /** @type {string} */ (currentRawSources.source()),
385 /** @type {string} */
386 (source.source()),
387 ];
388 }
389 };
390 const mergeRawSources = () => {
391 if (Array.isArray(currentRawSources)) {
392 const rawSource = new RawSource(currentRawSources.join(""));
393 stringsAsRawSources.add(rawSource);
394 newChildren.push(rawSource);
395 } else if (typeof currentRawSources === "string") {
396 const rawSource = new RawSource(currentRawSources);
397 stringsAsRawSources.add(rawSource);
398 newChildren.push(rawSource);
399 } else {
400 newChildren.push(currentRawSources);
401 }
402 };
403 const children = this._children;
404 for (let ci = 0, cl = children.length; ci < cl; ci++) {
405 const child = children[ci];
406 if (typeof child === "string") {
407 if (currentString === undefined) {
408 currentString = child;
409 } else {
410 currentString += child;
411 }
412 } else {
413 if (currentString !== undefined) {
414 addStringToRawSources(currentString);
415 currentString = undefined;
416 }
417 if (stringsAsRawSources.has(child)) {
418 addSourceToRawSources(
419 /** @type {SourceLike} */
420 (child),
421 );
422 } else {
423 if (currentRawSources !== undefined) {
424 mergeRawSources();
425 currentRawSources = undefined;
426 }
427 newChildren.push(child);
428 }
429 }
430 }
431 if (currentString !== undefined) {
432 addStringToRawSources(currentString);
433 }
434 if (currentRawSources !== undefined) {
435 mergeRawSources();
436 }
437 this._children = newChildren;
438 this._isOptimized = true;
439 }
440}
441
442module.exports = ConcatSource;
Note: See TracBrowser for help on using the repository browser.