You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			330 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			JavaScript
		
	
		
		
			
		
	
	
			330 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			JavaScript
		
	
| 
											9 months ago
										 | /* | ||
|  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | ||
|  | 	Author Tobias Koppers @sokra | ||
|  | */ | ||
|  | 
 | ||
|  | "use strict"; | ||
|  | 
 | ||
|  | const streamChunksOfSourceMap = require("./streamChunksOfSourceMap"); | ||
|  | const splitIntoLines = require("./splitIntoLines"); | ||
|  | 
 | ||
|  | const streamChunksOfCombinedSourceMap = ( | ||
|  | 	source, | ||
|  | 	sourceMap, | ||
|  | 	innerSourceName, | ||
|  | 	innerSource, | ||
|  | 	innerSourceMap, | ||
|  | 	removeInnerSource, | ||
|  | 	onChunk, | ||
|  | 	onSource, | ||
|  | 	onName, | ||
|  | 	finalSource, | ||
|  | 	columns | ||
|  | ) => { | ||
|  | 	let sourceMapping = new Map(); | ||
|  | 	let nameMapping = new Map(); | ||
|  | 	const sourceIndexMapping = []; | ||
|  | 	const nameIndexMapping = []; | ||
|  | 	const nameIndexValueMapping = []; | ||
|  | 	let innerSourceIndex = -2; | ||
|  | 	const innerSourceIndexMapping = []; | ||
|  | 	const innerSourceIndexValueMapping = []; | ||
|  | 	const innerSourceContents = []; | ||
|  | 	const innerSourceContentLines = []; | ||
|  | 	const innerNameIndexMapping = []; | ||
|  | 	const innerNameIndexValueMapping = []; | ||
|  | 	const innerSourceMapLineData = []; | ||
|  | 	const findInnerMapping = (line, column) => { | ||
|  | 		if (line > innerSourceMapLineData.length) return -1; | ||
|  | 		const { mappingsData } = innerSourceMapLineData[line - 1]; | ||
|  | 		let l = 0; | ||
|  | 		let r = mappingsData.length / 5; | ||
|  | 		while (l < r) { | ||
|  | 			let m = (l + r) >> 1; | ||
|  | 			if (mappingsData[m * 5] <= column) { | ||
|  | 				l = m + 1; | ||
|  | 			} else { | ||
|  | 				r = m; | ||
|  | 			} | ||
|  | 		} | ||
|  | 		if (l === 0) return -1; | ||
|  | 		return l - 1; | ||
|  | 	}; | ||
|  | 	return streamChunksOfSourceMap( | ||
|  | 		source, | ||
|  | 		sourceMap, | ||
|  | 		( | ||
|  | 			chunk, | ||
|  | 			generatedLine, | ||
|  | 			generatedColumn, | ||
|  | 			sourceIndex, | ||
|  | 			originalLine, | ||
|  | 			originalColumn, | ||
|  | 			nameIndex | ||
|  | 		) => { | ||
|  | 			// Check if this is a mapping to the inner source
 | ||
|  | 			if (sourceIndex === innerSourceIndex) { | ||
|  | 				// Check if there is a mapping in the inner source
 | ||
|  | 				const idx = findInnerMapping(originalLine, originalColumn); | ||
|  | 				if (idx !== -1) { | ||
|  | 					const { chunks, mappingsData } = innerSourceMapLineData[ | ||
|  | 						originalLine - 1 | ||
|  | 					]; | ||
|  | 					const mi = idx * 5; | ||
|  | 					const innerSourceIndex = mappingsData[mi + 1]; | ||
|  | 					const innerOriginalLine = mappingsData[mi + 2]; | ||
|  | 					let innerOriginalColumn = mappingsData[mi + 3]; | ||
|  | 					let innerNameIndex = mappingsData[mi + 4]; | ||
|  | 					if (innerSourceIndex >= 0) { | ||
|  | 						// Check for an identity mapping
 | ||
|  | 						// where we are allowed to adjust the original column
 | ||
|  | 						const innerChunk = chunks[idx]; | ||
|  | 						const innerGeneratedColumn = mappingsData[mi]; | ||
|  | 						const locationInChunk = originalColumn - innerGeneratedColumn; | ||
|  | 						if (locationInChunk > 0) { | ||
|  | 							let originalSourceLines = | ||
|  | 								innerSourceIndex < innerSourceContentLines.length | ||
|  | 									? innerSourceContentLines[innerSourceIndex] | ||
|  | 									: null; | ||
|  | 							if (originalSourceLines === undefined) { | ||
|  | 								const originalSource = innerSourceContents[innerSourceIndex]; | ||
|  | 								originalSourceLines = originalSource | ||
|  | 									? splitIntoLines(originalSource) | ||
|  | 									: null; | ||
|  | 								innerSourceContentLines[innerSourceIndex] = originalSourceLines; | ||
|  | 							} | ||
|  | 							if (originalSourceLines !== null) { | ||
|  | 								const originalChunk = | ||
|  | 									innerOriginalLine <= originalSourceLines.length | ||
|  | 										? originalSourceLines[innerOriginalLine - 1].slice( | ||
|  | 												innerOriginalColumn, | ||
|  | 												innerOriginalColumn + locationInChunk | ||
|  | 										  ) | ||
|  | 										: ""; | ||
|  | 								if (innerChunk.slice(0, locationInChunk) === originalChunk) { | ||
|  | 									innerOriginalColumn += locationInChunk; | ||
|  | 									innerNameIndex = -1; | ||
|  | 								} | ||
|  | 							} | ||
|  | 						} | ||
|  | 
 | ||
|  | 						// We have a inner mapping to original source
 | ||
|  | 
 | ||
|  | 						// emit source when needed and compute global source index
 | ||
|  | 						let sourceIndex = | ||
|  | 							innerSourceIndex < innerSourceIndexMapping.length | ||
|  | 								? innerSourceIndexMapping[innerSourceIndex] | ||
|  | 								: -2; | ||
|  | 						if (sourceIndex === -2) { | ||
|  | 							const [source, sourceContent] = | ||
|  | 								innerSourceIndex < innerSourceIndexValueMapping.length | ||
|  | 									? innerSourceIndexValueMapping[innerSourceIndex] | ||
|  | 									: [null, undefined]; | ||
|  | 							let globalIndex = sourceMapping.get(source); | ||
|  | 							if (globalIndex === undefined) { | ||
|  | 								sourceMapping.set(source, (globalIndex = sourceMapping.size)); | ||
|  | 								onSource(globalIndex, source, sourceContent); | ||
|  | 							} | ||
|  | 							sourceIndex = globalIndex; | ||
|  | 							innerSourceIndexMapping[innerSourceIndex] = sourceIndex; | ||
|  | 						} | ||
|  | 
 | ||
|  | 						// emit name when needed and compute global name index
 | ||
|  | 						let finalNameIndex = -1; | ||
|  | 						if (innerNameIndex >= 0) { | ||
|  | 							// when we have a inner name
 | ||
|  | 							finalNameIndex = | ||
|  | 								innerNameIndex < innerNameIndexMapping.length | ||
|  | 									? innerNameIndexMapping[innerNameIndex] | ||
|  | 									: -2; | ||
|  | 							if (finalNameIndex === -2) { | ||
|  | 								const name = | ||
|  | 									innerNameIndex < innerNameIndexValueMapping.length | ||
|  | 										? innerNameIndexValueMapping[innerNameIndex] | ||
|  | 										: undefined; | ||
|  | 								if (name) { | ||
|  | 									let globalIndex = nameMapping.get(name); | ||
|  | 									if (globalIndex === undefined) { | ||
|  | 										nameMapping.set(name, (globalIndex = nameMapping.size)); | ||
|  | 										onName(globalIndex, name); | ||
|  | 									} | ||
|  | 									finalNameIndex = globalIndex; | ||
|  | 								} else { | ||
|  | 									finalNameIndex = -1; | ||
|  | 								} | ||
|  | 								innerNameIndexMapping[innerNameIndex] = finalNameIndex; | ||
|  | 							} | ||
|  | 						} else if (nameIndex >= 0) { | ||
|  | 							// when we don't have an inner name,
 | ||
|  | 							// but we have an outer name
 | ||
|  | 							// it can be used when inner original code equals to the name
 | ||
|  | 							let originalSourceLines = | ||
|  | 								innerSourceContentLines[innerSourceIndex]; | ||
|  | 							if (originalSourceLines === undefined) { | ||
|  | 								const originalSource = innerSourceContents[innerSourceIndex]; | ||
|  | 								originalSourceLines = originalSource | ||
|  | 									? splitIntoLines(originalSource) | ||
|  | 									: null; | ||
|  | 								innerSourceContentLines[innerSourceIndex] = originalSourceLines; | ||
|  | 							} | ||
|  | 							if (originalSourceLines !== null) { | ||
|  | 								const name = nameIndexValueMapping[nameIndex]; | ||
|  | 								const originalName = | ||
|  | 									innerOriginalLine <= originalSourceLines.length | ||
|  | 										? originalSourceLines[innerOriginalLine - 1].slice( | ||
|  | 												innerOriginalColumn, | ||
|  | 												innerOriginalColumn + name.length | ||
|  | 										  ) | ||
|  | 										: ""; | ||
|  | 								if (name === originalName) { | ||
|  | 									finalNameIndex = | ||
|  | 										nameIndex < nameIndexMapping.length | ||
|  | 											? nameIndexMapping[nameIndex] | ||
|  | 											: -2; | ||
|  | 									if (finalNameIndex === -2) { | ||
|  | 										const name = nameIndexValueMapping[nameIndex]; | ||
|  | 										if (name) { | ||
|  | 											let globalIndex = nameMapping.get(name); | ||
|  | 											if (globalIndex === undefined) { | ||
|  | 												nameMapping.set(name, (globalIndex = nameMapping.size)); | ||
|  | 												onName(globalIndex, name); | ||
|  | 											} | ||
|  | 											finalNameIndex = globalIndex; | ||
|  | 										} else { | ||
|  | 											finalNameIndex = -1; | ||
|  | 										} | ||
|  | 										nameIndexMapping[nameIndex] = finalNameIndex; | ||
|  | 									} | ||
|  | 								} | ||
|  | 							} | ||
|  | 						} | ||
|  | 						onChunk( | ||
|  | 							chunk, | ||
|  | 							generatedLine, | ||
|  | 							generatedColumn, | ||
|  | 							sourceIndex, | ||
|  | 							innerOriginalLine, | ||
|  | 							innerOriginalColumn, | ||
|  | 							finalNameIndex | ||
|  | 						); | ||
|  | 						return; | ||
|  | 					} | ||
|  | 				} | ||
|  | 
 | ||
|  | 				// We have a mapping to the inner source, but no inner mapping
 | ||
|  | 				if (removeInnerSource) { | ||
|  | 					onChunk(chunk, generatedLine, generatedColumn, -1, -1, -1, -1); | ||
|  | 					return; | ||
|  | 				} else { | ||
|  | 					if (sourceIndexMapping[sourceIndex] === -2) { | ||
|  | 						let globalIndex = sourceMapping.get(innerSourceName); | ||
|  | 						if (globalIndex === undefined) { | ||
|  | 							sourceMapping.set(source, (globalIndex = sourceMapping.size)); | ||
|  | 							onSource(globalIndex, innerSourceName, innerSource); | ||
|  | 						} | ||
|  | 						sourceIndexMapping[sourceIndex] = globalIndex; | ||
|  | 					} | ||
|  | 				} | ||
|  | 			} | ||
|  | 
 | ||
|  | 			const finalSourceIndex = | ||
|  | 				sourceIndex < 0 || sourceIndex >= sourceIndexMapping.length | ||
|  | 					? -1 | ||
|  | 					: sourceIndexMapping[sourceIndex]; | ||
|  | 			if (finalSourceIndex < 0) { | ||
|  | 				// no source, so we make it a generated chunk
 | ||
|  | 				onChunk(chunk, generatedLine, generatedColumn, -1, -1, -1, -1); | ||
|  | 			} else { | ||
|  | 				// Pass through the chunk with mapping
 | ||
|  | 				let finalNameIndex = -1; | ||
|  | 				if (nameIndex >= 0 && nameIndex < nameIndexMapping.length) { | ||
|  | 					finalNameIndex = nameIndexMapping[nameIndex]; | ||
|  | 					if (finalNameIndex === -2) { | ||
|  | 						const name = nameIndexValueMapping[nameIndex]; | ||
|  | 						let globalIndex = nameMapping.get(name); | ||
|  | 						if (globalIndex === undefined) { | ||
|  | 							nameMapping.set(name, (globalIndex = nameMapping.size)); | ||
|  | 							onName(globalIndex, name); | ||
|  | 						} | ||
|  | 						finalNameIndex = globalIndex; | ||
|  | 						nameIndexMapping[nameIndex] = finalNameIndex; | ||
|  | 					} | ||
|  | 				} | ||
|  | 				onChunk( | ||
|  | 					chunk, | ||
|  | 					generatedLine, | ||
|  | 					generatedColumn, | ||
|  | 					finalSourceIndex, | ||
|  | 					originalLine, | ||
|  | 					originalColumn, | ||
|  | 					finalNameIndex | ||
|  | 				); | ||
|  | 			} | ||
|  | 		}, | ||
|  | 		(i, source, sourceContent) => { | ||
|  | 			if (source === innerSourceName) { | ||
|  | 				innerSourceIndex = i; | ||
|  | 				if (innerSource !== undefined) sourceContent = innerSource; | ||
|  | 				else innerSource = sourceContent; | ||
|  | 				sourceIndexMapping[i] = -2; | ||
|  | 				streamChunksOfSourceMap( | ||
|  | 					sourceContent, | ||
|  | 					innerSourceMap, | ||
|  | 					( | ||
|  | 						chunk, | ||
|  | 						generatedLine, | ||
|  | 						generatedColumn, | ||
|  | 						sourceIndex, | ||
|  | 						originalLine, | ||
|  | 						originalColumn, | ||
|  | 						nameIndex | ||
|  | 					) => { | ||
|  | 						while (innerSourceMapLineData.length < generatedLine) { | ||
|  | 							innerSourceMapLineData.push({ | ||
|  | 								mappingsData: [], | ||
|  | 								chunks: [] | ||
|  | 							}); | ||
|  | 						} | ||
|  | 						const data = innerSourceMapLineData[generatedLine - 1]; | ||
|  | 						data.mappingsData.push( | ||
|  | 							generatedColumn, | ||
|  | 							sourceIndex, | ||
|  | 							originalLine, | ||
|  | 							originalColumn, | ||
|  | 							nameIndex | ||
|  | 						); | ||
|  | 						data.chunks.push(chunk); | ||
|  | 					}, | ||
|  | 					(i, source, sourceContent) => { | ||
|  | 						innerSourceContents[i] = sourceContent; | ||
|  | 						innerSourceContentLines[i] = undefined; | ||
|  | 						innerSourceIndexMapping[i] = -2; | ||
|  | 						innerSourceIndexValueMapping[i] = [source, sourceContent]; | ||
|  | 					}, | ||
|  | 					(i, name) => { | ||
|  | 						innerNameIndexMapping[i] = -2; | ||
|  | 						innerNameIndexValueMapping[i] = name; | ||
|  | 					}, | ||
|  | 					false, | ||
|  | 					columns | ||
|  | 				); | ||
|  | 			} else { | ||
|  | 				let globalIndex = sourceMapping.get(source); | ||
|  | 				if (globalIndex === undefined) { | ||
|  | 					sourceMapping.set(source, (globalIndex = sourceMapping.size)); | ||
|  | 					onSource(globalIndex, source, sourceContent); | ||
|  | 				} | ||
|  | 				sourceIndexMapping[i] = globalIndex; | ||
|  | 			} | ||
|  | 		}, | ||
|  | 		(i, name) => { | ||
|  | 			nameIndexMapping[i] = -2; | ||
|  | 			nameIndexValueMapping[i] = name; | ||
|  | 		}, | ||
|  | 		finalSource, | ||
|  | 		columns | ||
|  | 	); | ||
|  | }; | ||
|  | 
 | ||
|  | module.exports = streamChunksOfCombinedSourceMap; |