| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 | /*	MIT License http://www.opensource.org/licenses/mit-license.php	Author Tobias Koppers @sokra*/"use strict";const Source = require("./Source");const RawSource = require("./RawSource");const streamChunks = require("./helpers/streamChunks");const { getMap, getSourceAndMap } = require("./helpers/getFromStreamChunks");const stringsAsRawSources = new WeakSet();class ConcatSource extends Source {	constructor() {		super();		this._children = [];		for (let i = 0; i < arguments.length; i++) {			const item = arguments[i];			if (item instanceof ConcatSource) {				for (const child of item._children) {					this._children.push(child);				}			} else {				this._children.push(item);			}		}		this._isOptimized = arguments.length === 0;	}	getChildren() {		if (!this._isOptimized) this._optimize();		return this._children;	}	add(item) {		if (item instanceof ConcatSource) {			for (const child of item._children) {				this._children.push(child);			}		} else {			this._children.push(item);		}		this._isOptimized = false;	}	addAllSkipOptimizing(items) {		for (const item of items) {			this._children.push(item);		}	}	buffer() {		if (!this._isOptimized) this._optimize();		const buffers = [];		for (const child of this._children) {			if (typeof child.buffer === "function") {				buffers.push(child.buffer());			} else {				const bufferOrString = child.source();				if (Buffer.isBuffer(bufferOrString)) {					buffers.push(bufferOrString);				} else {					// This will not happen					buffers.push(Buffer.from(bufferOrString, "utf-8"));				}			}		}		return Buffer.concat(buffers);	}	source() {		if (!this._isOptimized) this._optimize();		let source = "";		for (const child of this._children) {			source += child.source();		}		return source;	}	size() {		if (!this._isOptimized) this._optimize();		let size = 0;		for (const child of this._children) {			size += child.size();		}		return size;	}	map(options) {		return getMap(this, options);	}	sourceAndMap(options) {		return getSourceAndMap(this, options);	}	streamChunks(options, onChunk, onSource, onName) {		if (!this._isOptimized) this._optimize();		if (this._children.length === 1)			return this._children[0].streamChunks(options, onChunk, onSource, onName);		let currentLineOffset = 0;		let currentColumnOffset = 0;		let sourceMapping = new Map();		let nameMapping = new Map();		const finalSource = !!(options && options.finalSource);		let code = "";		let needToCloseMapping = false;		for (const item of this._children) {			const sourceIndexMapping = [];			const nameIndexMapping = [];			let lastMappingLine = 0;			const { generatedLine, generatedColumn, source } = streamChunks(				item,				options,				// eslint-disable-next-line no-loop-func				(					chunk,					generatedLine,					generatedColumn,					sourceIndex,					originalLine,					originalColumn,					nameIndex				) => {					const line = generatedLine + currentLineOffset;					const column =						generatedLine === 1							? generatedColumn + currentColumnOffset							: generatedColumn;					if (needToCloseMapping) {						if (generatedLine !== 1 || generatedColumn !== 0) {							onChunk(								undefined,								currentLineOffset + 1,								currentColumnOffset,								-1,								-1,								-1,								-1							);						}						needToCloseMapping = false;					}					const resultSourceIndex =						sourceIndex < 0 || sourceIndex >= sourceIndexMapping.length							? -1							: sourceIndexMapping[sourceIndex];					const resultNameIndex =						nameIndex < 0 || nameIndex >= nameIndexMapping.length							? -1							: nameIndexMapping[nameIndex];					lastMappingLine = resultSourceIndex < 0 ? 0 : generatedLine;					if (finalSource) {						if (chunk !== undefined) code += chunk;						if (resultSourceIndex >= 0) {							onChunk(								undefined,								line,								column,								resultSourceIndex,								originalLine,								originalColumn,								resultNameIndex							);						}					} else {						if (resultSourceIndex < 0) {							onChunk(chunk, line, column, -1, -1, -1, -1);						} else {							onChunk(								chunk,								line,								column,								resultSourceIndex,								originalLine,								originalColumn,								resultNameIndex							);						}					}				},				(i, source, sourceContent) => {					let globalIndex = sourceMapping.get(source);					if (globalIndex === undefined) {						sourceMapping.set(source, (globalIndex = sourceMapping.size));						onSource(globalIndex, source, sourceContent);					}					sourceIndexMapping[i] = globalIndex;				},				(i, name) => {					let globalIndex = nameMapping.get(name);					if (globalIndex === undefined) {						nameMapping.set(name, (globalIndex = nameMapping.size));						onName(globalIndex, name);					}					nameIndexMapping[i] = globalIndex;				}			);			if (source !== undefined) code += source;			if (needToCloseMapping) {				if (generatedLine !== 1 || generatedColumn !== 0) {					onChunk(						undefined,						currentLineOffset + 1,						currentColumnOffset,						-1,						-1,						-1,						-1					);					needToCloseMapping = false;				}			}			if (generatedLine > 1) {				currentColumnOffset = generatedColumn;			} else {				currentColumnOffset += generatedColumn;			}			needToCloseMapping =				needToCloseMapping ||				(finalSource && lastMappingLine === generatedLine);			currentLineOffset += generatedLine - 1;		}		return {			generatedLine: currentLineOffset + 1,			generatedColumn: currentColumnOffset,			source: finalSource ? code : undefined		};	}	updateHash(hash) {		if (!this._isOptimized) this._optimize();		hash.update("ConcatSource");		for (const item of this._children) {			item.updateHash(hash);		}	}	_optimize() {		const newChildren = [];		let currentString = undefined;		let currentRawSources = undefined;		const addStringToRawSources = string => {			if (currentRawSources === undefined) {				currentRawSources = string;			} else if (Array.isArray(currentRawSources)) {				currentRawSources.push(string);			} else {				currentRawSources = [					typeof currentRawSources === "string"						? currentRawSources						: currentRawSources.source(),					string				];			}		};		const addSourceToRawSources = source => {			if (currentRawSources === undefined) {				currentRawSources = source;			} else if (Array.isArray(currentRawSources)) {				currentRawSources.push(source.source());			} else {				currentRawSources = [					typeof currentRawSources === "string"						? currentRawSources						: currentRawSources.source(),					source.source()				];			}		};		const mergeRawSources = () => {			if (Array.isArray(currentRawSources)) {				const rawSource = new RawSource(currentRawSources.join(""));				stringsAsRawSources.add(rawSource);				newChildren.push(rawSource);			} else if (typeof currentRawSources === "string") {				const rawSource = new RawSource(currentRawSources);				stringsAsRawSources.add(rawSource);				newChildren.push(rawSource);			} else {				newChildren.push(currentRawSources);			}		};		for (const child of this._children) {			if (typeof child === "string") {				if (currentString === undefined) {					currentString = child;				} else {					currentString += child;				}			} else {				if (currentString !== undefined) {					addStringToRawSources(currentString);					currentString = undefined;				}				if (stringsAsRawSources.has(child)) {					addSourceToRawSources(child);				} else {					if (currentRawSources !== undefined) {						mergeRawSources();						currentRawSources = undefined;					}					newChildren.push(child);				}			}		}		if (currentString !== undefined) {			addStringToRawSources(currentString);		}		if (currentRawSources !== undefined) {			mergeRawSources();		}		this._children = newChildren;		this._isOptimized = true;	}}module.exports = ConcatSource;
 |