| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 | 
							- /*
 
- 	MIT License http://www.opensource.org/licenses/mit-license.php
 
- 	Author Tobias Koppers @sokra
 
- */
 
- "use strict";
 
- const Source = require("./Source");
 
- const { getMap, getSourceAndMap } = require("./helpers/getFromStreamChunks");
 
- const splitIntoLines = require("./helpers/splitIntoLines");
 
- const streamChunks = require("./helpers/streamChunks");
 
- /** @typedef {import("./Source").HashLike} HashLike */
 
- /** @typedef {import("./Source").MapOptions} MapOptions */
 
- /** @typedef {import("./Source").RawSourceMap} RawSourceMap */
 
- /** @typedef {import("./Source").SourceAndMap} SourceAndMap */
 
- /** @typedef {import("./Source").SourceValue} SourceValue */
 
- /** @typedef {import("./helpers/getGeneratedSourceInfo").GeneratedSourceInfo} GeneratedSourceInfo */
 
- /** @typedef {import("./helpers/streamChunks").OnChunk} OnChunk */
 
- /** @typedef {import("./helpers/streamChunks").OnName} OnName */
 
- /** @typedef {import("./helpers/streamChunks").OnSource} OnSource */
 
- /** @typedef {import("./helpers/streamChunks").Options} Options */
 
- // since v8 7.0, Array.prototype.sort is stable
 
- const hasStableSort =
 
- 	typeof process === "object" &&
 
- 	process.versions &&
 
- 	typeof process.versions.v8 === "string" &&
 
- 	!/^[0-6]\./.test(process.versions.v8);
 
- // This is larger than max string length
 
- const MAX_SOURCE_POSITION = 0x20000000;
 
- class Replacement {
 
- 	/**
 
- 	 * @param {number} start start
 
- 	 * @param {number} end end
 
- 	 * @param {string} content content
 
- 	 * @param {string=} name name
 
- 	 */
 
- 	constructor(start, end, content, name) {
 
- 		this.start = start;
 
- 		this.end = end;
 
- 		this.content = content;
 
- 		this.name = name;
 
- 		if (!hasStableSort) {
 
- 			this.index = -1;
 
- 		}
 
- 	}
 
- }
 
- class ReplaceSource extends Source {
 
- 	/**
 
- 	 * @param {Source} source source
 
- 	 * @param {string=} name name
 
- 	 */
 
- 	constructor(source, name) {
 
- 		super();
 
- 		this._source = source;
 
- 		this._name = name;
 
- 		/** @type {Replacement[]} */
 
- 		this._replacements = [];
 
- 		this._isSorted = true;
 
- 	}
 
- 	getName() {
 
- 		return this._name;
 
- 	}
 
- 	getReplacements() {
 
- 		this._sortReplacements();
 
- 		return this._replacements;
 
- 	}
 
- 	/**
 
- 	 * @param {number} start start
 
- 	 * @param {number} end end
 
- 	 * @param {string} newValue new value
 
- 	 * @param {string=} name name
 
- 	 * @returns {void}
 
- 	 */
 
- 	replace(start, end, newValue, name) {
 
- 		if (typeof newValue !== "string") {
 
- 			throw new Error(
 
- 				`insertion must be a string, but is a ${typeof newValue}`,
 
- 			);
 
- 		}
 
- 		this._replacements.push(new Replacement(start, end, newValue, name));
 
- 		this._isSorted = false;
 
- 	}
 
- 	/**
 
- 	 * @param {number} pos pos
 
- 	 * @param {string} newValue new value
 
- 	 * @param {string=} name name
 
- 	 * @returns {void}
 
- 	 */
 
- 	insert(pos, newValue, name) {
 
- 		if (typeof newValue !== "string") {
 
- 			throw new Error(
 
- 				`insertion must be a string, but is a ${typeof newValue}: ${newValue}`,
 
- 			);
 
- 		}
 
- 		this._replacements.push(new Replacement(pos, pos - 1, newValue, name));
 
- 		this._isSorted = false;
 
- 	}
 
- 	/**
 
- 	 * @returns {SourceValue} source
 
- 	 */
 
- 	source() {
 
- 		if (this._replacements.length === 0) {
 
- 			return this._source.source();
 
- 		}
 
- 		let current = this._source.source();
 
- 		let pos = 0;
 
- 		const result = [];
 
- 		this._sortReplacements();
 
- 		for (const replacement of this._replacements) {
 
- 			const start = Math.floor(replacement.start);
 
- 			const end = Math.floor(replacement.end + 1);
 
- 			if (pos < start) {
 
- 				const offset = start - pos;
 
- 				result.push(current.slice(0, offset));
 
- 				current = current.slice(offset);
 
- 				pos = start;
 
- 			}
 
- 			result.push(replacement.content);
 
- 			if (pos < end) {
 
- 				const offset = end - pos;
 
- 				current = current.slice(offset);
 
- 				pos = end;
 
- 			}
 
- 		}
 
- 		result.push(current);
 
- 		return result.join("");
 
- 	}
 
- 	/**
 
- 	 * @param {MapOptions=} options map options
 
- 	 * @returns {RawSourceMap | null} map
 
- 	 */
 
- 	map(options) {
 
- 		if (this._replacements.length === 0) {
 
- 			return this._source.map(options);
 
- 		}
 
- 		return getMap(this, options);
 
- 	}
 
- 	/**
 
- 	 * @param {MapOptions=} options map options
 
- 	 * @returns {SourceAndMap} source and map
 
- 	 */
 
- 	sourceAndMap(options) {
 
- 		if (this._replacements.length === 0) {
 
- 			return this._source.sourceAndMap(options);
 
- 		}
 
- 		return getSourceAndMap(this, options);
 
- 	}
 
- 	original() {
 
- 		return this._source;
 
- 	}
 
- 	_sortReplacements() {
 
- 		if (this._isSorted) return;
 
- 		if (hasStableSort) {
 
- 			this._replacements.sort((a, b) => {
 
- 				const diff1 = a.start - b.start;
 
- 				if (diff1 !== 0) return diff1;
 
- 				const diff2 = a.end - b.end;
 
- 				if (diff2 !== 0) return diff2;
 
- 				return 0;
 
- 			});
 
- 		} else {
 
- 			for (const [i, repl] of this._replacements.entries()) repl.index = i;
 
- 			this._replacements.sort((a, b) => {
 
- 				const diff1 = a.start - b.start;
 
- 				if (diff1 !== 0) return diff1;
 
- 				const diff2 = a.end - b.end;
 
- 				if (diff2 !== 0) return diff2;
 
- 				return (
 
- 					/** @type {number} */ (a.index) - /** @type {number} */ (b.index)
 
- 				);
 
- 			});
 
- 		}
 
- 		this._isSorted = true;
 
- 	}
 
- 	/**
 
- 	 * @param {Options} options options
 
- 	 * @param {OnChunk} onChunk called for each chunk of code
 
- 	 * @param {OnSource} onSource called for each source
 
- 	 * @param {OnName} onName called for each name
 
- 	 * @returns {GeneratedSourceInfo} generated source info
 
- 	 */
 
- 	streamChunks(options, onChunk, onSource, onName) {
 
- 		this._sortReplacements();
 
- 		const replacements = this._replacements;
 
- 		let pos = 0;
 
- 		let i = 0;
 
- 		let replacementEnd = -1;
 
- 		let nextReplacement =
 
- 			i < replacements.length
 
- 				? Math.floor(replacements[i].start)
 
- 				: MAX_SOURCE_POSITION;
 
- 		let generatedLineOffset = 0;
 
- 		let generatedColumnOffset = 0;
 
- 		let generatedColumnOffsetLine = 0;
 
- 		/** @type {(string | string[] | undefined)[]} */
 
- 		const sourceContents = [];
 
- 		/** @type {Map<string, number>} */
 
- 		const nameMapping = new Map();
 
- 		/** @type {number[]} */
 
- 		const nameIndexMapping = [];
 
- 		/**
 
- 		 * @param {number} sourceIndex source index
 
- 		 * @param {number} line line
 
- 		 * @param {number} column column
 
- 		 * @param {string} expectedChunk expected chunk
 
- 		 * @returns {boolean} result
 
- 		 */
 
- 		const checkOriginalContent = (sourceIndex, line, column, expectedChunk) => {
 
- 			/** @type {undefined | string | string[]} */
 
- 			let content =
 
- 				sourceIndex < sourceContents.length
 
- 					? sourceContents[sourceIndex]
 
- 					: undefined;
 
- 			if (content === undefined) return false;
 
- 			if (typeof content === "string") {
 
- 				content = splitIntoLines(content);
 
- 				sourceContents[sourceIndex] = content;
 
- 			}
 
- 			const contentLine = line <= content.length ? content[line - 1] : null;
 
- 			if (contentLine === null) return false;
 
- 			return (
 
- 				contentLine.slice(column, column + expectedChunk.length) ===
 
- 				expectedChunk
 
- 			);
 
- 		};
 
- 		const { generatedLine, generatedColumn } = streamChunks(
 
- 			this._source,
 
- 			{ ...options, finalSource: false },
 
- 			(
 
- 				_chunk,
 
- 				generatedLine,
 
- 				generatedColumn,
 
- 				sourceIndex,
 
- 				originalLine,
 
- 				originalColumn,
 
- 				nameIndex,
 
- 			) => {
 
- 				let chunkPos = 0;
 
- 				const chunk = /** @type {string} */ (_chunk);
 
- 				const endPos = pos + chunk.length;
 
- 				// Skip over when it has been replaced
 
- 				if (replacementEnd > pos) {
 
- 					// Skip over the whole chunk
 
- 					if (replacementEnd >= endPos) {
 
- 						const line = generatedLine + generatedLineOffset;
 
- 						if (chunk.endsWith("\n")) {
 
- 							generatedLineOffset--;
 
- 							if (generatedColumnOffsetLine === line) {
 
- 								// undo exiting corrections form the current line
 
- 								generatedColumnOffset += generatedColumn;
 
- 							}
 
- 						} else if (generatedColumnOffsetLine === line) {
 
- 							generatedColumnOffset -= chunk.length;
 
- 						} else {
 
- 							generatedColumnOffset = -chunk.length;
 
- 							generatedColumnOffsetLine = line;
 
- 						}
 
- 						pos = endPos;
 
- 						return;
 
- 					}
 
- 					// Partially skip over chunk
 
- 					chunkPos = replacementEnd - pos;
 
- 					if (
 
- 						checkOriginalContent(
 
- 							sourceIndex,
 
- 							originalLine,
 
- 							originalColumn,
 
- 							chunk.slice(0, chunkPos),
 
- 						)
 
- 					) {
 
- 						originalColumn += chunkPos;
 
- 					}
 
- 					pos += chunkPos;
 
- 					const line = generatedLine + generatedLineOffset;
 
- 					if (generatedColumnOffsetLine === line) {
 
- 						generatedColumnOffset -= chunkPos;
 
- 					} else {
 
- 						generatedColumnOffset = -chunkPos;
 
- 						generatedColumnOffsetLine = line;
 
- 					}
 
- 					generatedColumn += chunkPos;
 
- 				}
 
- 				// Is a replacement in the chunk?
 
- 				if (nextReplacement < endPos) {
 
- 					do {
 
- 						let line = generatedLine + generatedLineOffset;
 
- 						if (nextReplacement > pos) {
 
- 							// Emit chunk until replacement
 
- 							const offset = nextReplacement - pos;
 
- 							const chunkSlice = chunk.slice(chunkPos, chunkPos + offset);
 
- 							onChunk(
 
- 								chunkSlice,
 
- 								line,
 
- 								generatedColumn +
 
- 									(line === generatedColumnOffsetLine
 
- 										? generatedColumnOffset
 
- 										: 0),
 
- 								sourceIndex,
 
- 								originalLine,
 
- 								originalColumn,
 
- 								nameIndex < 0 || nameIndex >= nameIndexMapping.length
 
- 									? -1
 
- 									: nameIndexMapping[nameIndex],
 
- 							);
 
- 							generatedColumn += offset;
 
- 							chunkPos += offset;
 
- 							pos = nextReplacement;
 
- 							if (
 
- 								checkOriginalContent(
 
- 									sourceIndex,
 
- 									originalLine,
 
- 									originalColumn,
 
- 									chunkSlice,
 
- 								)
 
- 							) {
 
- 								originalColumn += chunkSlice.length;
 
- 							}
 
- 						}
 
- 						// Insert replacement content splitted into chunks by lines
 
- 						const { content, name } = replacements[i];
 
- 						const matches = splitIntoLines(content);
 
- 						let replacementNameIndex = nameIndex;
 
- 						if (sourceIndex >= 0 && name) {
 
- 							let globalIndex = nameMapping.get(name);
 
- 							if (globalIndex === undefined) {
 
- 								globalIndex = nameMapping.size;
 
- 								nameMapping.set(name, globalIndex);
 
- 								onName(globalIndex, name);
 
- 							}
 
- 							replacementNameIndex = globalIndex;
 
- 						}
 
- 						for (let m = 0; m < matches.length; m++) {
 
- 							const contentLine = matches[m];
 
- 							onChunk(
 
- 								contentLine,
 
- 								line,
 
- 								generatedColumn +
 
- 									(line === generatedColumnOffsetLine
 
- 										? generatedColumnOffset
 
- 										: 0),
 
- 								sourceIndex,
 
- 								originalLine,
 
- 								originalColumn,
 
- 								replacementNameIndex,
 
- 							);
 
- 							// Only the first chunk has name assigned
 
- 							replacementNameIndex = -1;
 
- 							if (m === matches.length - 1 && !contentLine.endsWith("\n")) {
 
- 								if (generatedColumnOffsetLine === line) {
 
- 									generatedColumnOffset += contentLine.length;
 
- 								} else {
 
- 									generatedColumnOffset = contentLine.length;
 
- 									generatedColumnOffsetLine = line;
 
- 								}
 
- 							} else {
 
- 								generatedLineOffset++;
 
- 								line++;
 
- 								generatedColumnOffset = -generatedColumn;
 
- 								generatedColumnOffsetLine = line;
 
- 							}
 
- 						}
 
- 						// Remove replaced content by settings this variable
 
- 						replacementEnd = Math.max(
 
- 							replacementEnd,
 
- 							Math.floor(replacements[i].end + 1),
 
- 						);
 
- 						// Move to next replacement
 
- 						i++;
 
- 						nextReplacement =
 
- 							i < replacements.length
 
- 								? Math.floor(replacements[i].start)
 
- 								: MAX_SOURCE_POSITION;
 
- 						// Skip over when it has been replaced
 
- 						const offset = chunk.length - endPos + replacementEnd - chunkPos;
 
- 						if (offset > 0) {
 
- 							// Skip over whole chunk
 
- 							if (replacementEnd >= endPos) {
 
- 								const line = generatedLine + generatedLineOffset;
 
- 								if (chunk.endsWith("\n")) {
 
- 									generatedLineOffset--;
 
- 									if (generatedColumnOffsetLine === line) {
 
- 										// undo exiting corrections form the current line
 
- 										generatedColumnOffset += generatedColumn;
 
- 									}
 
- 								} else if (generatedColumnOffsetLine === line) {
 
- 									generatedColumnOffset -= chunk.length - chunkPos;
 
- 								} else {
 
- 									generatedColumnOffset = chunkPos - chunk.length;
 
- 									generatedColumnOffsetLine = line;
 
- 								}
 
- 								pos = endPos;
 
- 								return;
 
- 							}
 
- 							// Partially skip over chunk
 
- 							const line = generatedLine + generatedLineOffset;
 
- 							if (
 
- 								checkOriginalContent(
 
- 									sourceIndex,
 
- 									originalLine,
 
- 									originalColumn,
 
- 									chunk.slice(chunkPos, chunkPos + offset),
 
- 								)
 
- 							) {
 
- 								originalColumn += offset;
 
- 							}
 
- 							chunkPos += offset;
 
- 							pos += offset;
 
- 							if (generatedColumnOffsetLine === line) {
 
- 								generatedColumnOffset -= offset;
 
- 							} else {
 
- 								generatedColumnOffset = -offset;
 
- 								generatedColumnOffsetLine = line;
 
- 							}
 
- 							generatedColumn += offset;
 
- 						}
 
- 					} while (nextReplacement < endPos);
 
- 				}
 
- 				// Emit remaining chunk
 
- 				if (chunkPos < chunk.length) {
 
- 					const chunkSlice = chunkPos === 0 ? chunk : chunk.slice(chunkPos);
 
- 					const line = generatedLine + generatedLineOffset;
 
- 					onChunk(
 
- 						chunkSlice,
 
- 						line,
 
- 						generatedColumn +
 
- 							(line === generatedColumnOffsetLine ? generatedColumnOffset : 0),
 
- 						sourceIndex,
 
- 						originalLine,
 
- 						originalColumn,
 
- 						nameIndex < 0 ? -1 : nameIndexMapping[nameIndex],
 
- 					);
 
- 				}
 
- 				pos = endPos;
 
- 			},
 
- 			(sourceIndex, source, sourceContent) => {
 
- 				while (sourceContents.length < sourceIndex) {
 
- 					sourceContents.push(undefined);
 
- 				}
 
- 				sourceContents[sourceIndex] = sourceContent;
 
- 				onSource(sourceIndex, source, sourceContent);
 
- 			},
 
- 			(nameIndex, name) => {
 
- 				let globalIndex = nameMapping.get(name);
 
- 				if (globalIndex === undefined) {
 
- 					globalIndex = nameMapping.size;
 
- 					nameMapping.set(name, globalIndex);
 
- 					onName(globalIndex, name);
 
- 				}
 
- 				nameIndexMapping[nameIndex] = globalIndex;
 
- 			},
 
- 		);
 
- 		// Handle remaining replacements
 
- 		let remainer = "";
 
- 		for (; i < replacements.length; i++) {
 
- 			remainer += replacements[i].content;
 
- 		}
 
- 		// Insert remaining replacements content splitted into chunks by lines
 
- 		let line = /** @type {number} */ (generatedLine) + generatedLineOffset;
 
- 		const matches = splitIntoLines(remainer);
 
- 		for (let m = 0; m < matches.length; m++) {
 
- 			const contentLine = matches[m];
 
- 			onChunk(
 
- 				contentLine,
 
- 				line,
 
- 				/** @type {number} */
 
- 				(generatedColumn) +
 
- 					(line === generatedColumnOffsetLine ? generatedColumnOffset : 0),
 
- 				-1,
 
- 				-1,
 
- 				-1,
 
- 				-1,
 
- 			);
 
- 			if (m === matches.length - 1 && !contentLine.endsWith("\n")) {
 
- 				if (generatedColumnOffsetLine === line) {
 
- 					generatedColumnOffset += contentLine.length;
 
- 				} else {
 
- 					generatedColumnOffset = contentLine.length;
 
- 					generatedColumnOffsetLine = line;
 
- 				}
 
- 			} else {
 
- 				generatedLineOffset++;
 
- 				line++;
 
- 				generatedColumnOffset = -(/** @type {number} */ (generatedColumn));
 
- 				generatedColumnOffsetLine = line;
 
- 			}
 
- 		}
 
- 		return {
 
- 			generatedLine: line,
 
- 			generatedColumn:
 
- 				/** @type {number} */
 
- 				(generatedColumn) +
 
- 				(line === generatedColumnOffsetLine ? generatedColumnOffset : 0),
 
- 		};
 
- 	}
 
- 	/**
 
- 	 * @param {HashLike} hash hash
 
- 	 * @returns {void}
 
- 	 */
 
- 	updateHash(hash) {
 
- 		this._sortReplacements();
 
- 		hash.update("ReplaceSource");
 
- 		this._source.updateHash(hash);
 
- 		hash.update(this._name || "");
 
- 		for (const repl of this._replacements) {
 
- 			hash.update(
 
- 				`${repl.start}${repl.end}${repl.content}${repl.name ? repl.name : ""}`,
 
- 			);
 
- 		}
 
- 	}
 
- }
 
- module.exports = ReplaceSource;
 
- module.exports.Replacement = Replacement;
 
 
  |