You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							185 lines
						
					
					
						
							5.5 KiB
						
					
					
				
			
		
		
	
	
							185 lines
						
					
					
						
							5.5 KiB
						
					
					
				/* | 
						|
	MIT License http://www.opensource.org/licenses/mit-license.php | 
						|
	Author Tobias Koppers @sokra | 
						|
*/ | 
						|
 | 
						|
"use strict"; | 
						|
 | 
						|
var SourceNode = require("source-map").SourceNode; | 
						|
var SourceMapConsumer = require("source-map").SourceMapConsumer; | 
						|
 | 
						|
var applySourceMap = function( | 
						|
	sourceNode, | 
						|
	sourceMapConsumer, | 
						|
	sourceFile, | 
						|
	removeGeneratedCodeForSourceFile | 
						|
) { | 
						|
	// The following notations are used to name stuff: | 
						|
	// Left <------------> Middle <-------------------> Right | 
						|
	// Input arguments: | 
						|
	//        sourceNode                                       - Code mapping from Left to Middle | 
						|
	//                   sourceFile                            - Name of a Middle file | 
						|
	//                              sourceMapConsumer          - Code mapping from Middle to Right | 
						|
	// Variables: | 
						|
	//           l2m                      m2r | 
						|
	// Left <-----------------------------------------> Right | 
						|
	// Variables: | 
						|
	//                       l2r | 
						|
 | 
						|
	var l2rResult = new SourceNode(); | 
						|
	var l2rOutput = []; | 
						|
 | 
						|
	var middleSourceContents = {}; | 
						|
 | 
						|
	var m2rMappingsByLine = {}; | 
						|
 | 
						|
	var rightSourceContentsSet = {}; | 
						|
	var rightSourceContentsLines = {}; | 
						|
 | 
						|
	// Store all mappings by generated line | 
						|
	sourceMapConsumer.eachMapping( | 
						|
		function(mapping) { | 
						|
			(m2rMappingsByLine[mapping.generatedLine] = | 
						|
				m2rMappingsByLine[mapping.generatedLine] || []).push(mapping); | 
						|
		}, | 
						|
		null, | 
						|
		SourceMapConsumer.GENERATED_ORDER | 
						|
	); | 
						|
 | 
						|
	// Store all source contents | 
						|
	sourceNode.walkSourceContents(function(source, content) { | 
						|
		middleSourceContents["$" + source] = content; | 
						|
	}); | 
						|
 | 
						|
	var middleSource = middleSourceContents["$" + sourceFile]; | 
						|
	var middleSourceLines = middleSource ? middleSource.split("\n") : undefined; | 
						|
 | 
						|
	// Walk all left to middle mappings | 
						|
	sourceNode.walk(function(chunk, middleMapping) { | 
						|
		var source; | 
						|
 | 
						|
		// Find a mapping from middle to right | 
						|
		if( | 
						|
			middleMapping.source === sourceFile && | 
						|
			middleMapping.line && | 
						|
			m2rMappingsByLine[middleMapping.line] | 
						|
		) { | 
						|
			var m2rBestFit; | 
						|
			var m2rMappings = m2rMappingsByLine[middleMapping.line]; | 
						|
			// Note: if this becomes a performance problem, use binary search | 
						|
			for(var i = 0; i < m2rMappings.length; i++) { | 
						|
				if(m2rMappings[i].generatedColumn <= middleMapping.column) { | 
						|
					m2rBestFit = m2rMappings[i]; | 
						|
				} | 
						|
			} | 
						|
			if(m2rBestFit) { | 
						|
				var allowMiddleName = false; | 
						|
				var middleLine; | 
						|
				var rightSourceContent; | 
						|
				var rightSourceContentLines; | 
						|
				var rightSource = m2rBestFit.source; | 
						|
				// Check if we have middle and right source for this mapping | 
						|
				// Then we could have an "identify" mapping | 
						|
				if( | 
						|
					middleSourceLines && | 
						|
					rightSource && | 
						|
					(middleLine = middleSourceLines[m2rBestFit.generatedLine - 1]) && | 
						|
					((rightSourceContentLines = rightSourceContentsLines[rightSource]) || | 
						|
						(rightSourceContent = sourceMapConsumer.sourceContentFor( | 
						|
							rightSource, | 
						|
							true | 
						|
						))) | 
						|
				) { | 
						|
					if(!rightSourceContentLines) { | 
						|
						rightSourceContentLines = rightSourceContentsLines[ | 
						|
							rightSource | 
						|
						] = rightSourceContent.split("\n"); | 
						|
					} | 
						|
					var rightLine = rightSourceContentLines[m2rBestFit.originalLine - 1]; | 
						|
					if(rightLine) { | 
						|
						var offset = middleMapping.column - m2rBestFit.generatedColumn; | 
						|
						if(offset > 0) { | 
						|
							var middlePart = middleLine.slice( | 
						|
								m2rBestFit.generatedColumn, | 
						|
								middleMapping.column | 
						|
							); | 
						|
							var rightPart = rightLine.slice( | 
						|
								m2rBestFit.originalColumn, | 
						|
								m2rBestFit.originalColumn + offset | 
						|
							); | 
						|
							if(middlePart === rightPart) { | 
						|
								// When original and generated code is equal we assume we have an "identity" mapping | 
						|
								// In this case we can offset the original position | 
						|
								m2rBestFit = Object.assign({}, m2rBestFit, { | 
						|
									originalColumn: m2rBestFit.originalColumn + offset, | 
						|
									generatedColumn: middleMapping.column | 
						|
								}); | 
						|
							} | 
						|
						} | 
						|
						if(!m2rBestFit.name && middleMapping.name) { | 
						|
							allowMiddleName = | 
						|
								rightLine.slice( | 
						|
									m2rBestFit.originalColumn, | 
						|
									m2rBestFit.originalColumn + middleMapping.name.length | 
						|
								) === middleMapping.name; | 
						|
						} | 
						|
					} | 
						|
				} | 
						|
 | 
						|
				// Construct a left to right node from the found middle to right mapping | 
						|
				source = m2rBestFit.source; | 
						|
				l2rOutput.push( | 
						|
					new SourceNode( | 
						|
						m2rBestFit.originalLine, | 
						|
						m2rBestFit.originalColumn, | 
						|
						source, | 
						|
						chunk, | 
						|
						allowMiddleName ? middleMapping.name : m2rBestFit.name | 
						|
					) | 
						|
				); | 
						|
 | 
						|
				// Set the source contents once | 
						|
				if(!("$" + source in rightSourceContentsSet)) { | 
						|
					rightSourceContentsSet["$" + source] = true; | 
						|
					var sourceContent = sourceMapConsumer.sourceContentFor(source, true); | 
						|
					if(sourceContent) { | 
						|
						l2rResult.setSourceContent(source, sourceContent); | 
						|
					} | 
						|
				} | 
						|
				return; | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		if((removeGeneratedCodeForSourceFile && middleMapping.source === sourceFile) || !middleMapping.source) { | 
						|
			// Construct a left to middle node with only generated code | 
						|
			// Because user do not want mappings to middle sources | 
						|
			// Or this chunk has no mapping | 
						|
			l2rOutput.push(chunk); | 
						|
			return; | 
						|
		} | 
						|
 | 
						|
		// Construct a left to middle node | 
						|
		source = middleMapping.source; | 
						|
		l2rOutput.push( | 
						|
			new SourceNode( | 
						|
				middleMapping.line, | 
						|
				middleMapping.column, | 
						|
				source, | 
						|
				chunk, | 
						|
				middleMapping.name | 
						|
			) | 
						|
		); | 
						|
		if("$" + source in middleSourceContents) { | 
						|
			if(!("$" + source in rightSourceContentsSet)) { | 
						|
				l2rResult.setSourceContent(source, middleSourceContents["$" + source]); | 
						|
				delete middleSourceContents["$" + source]; | 
						|
			} | 
						|
		} | 
						|
	}); | 
						|
 | 
						|
	// Put output into the resulting SourceNode | 
						|
	l2rResult.add(l2rOutput); | 
						|
	return l2rResult; | 
						|
}; | 
						|
 | 
						|
module.exports = applySourceMap;
 | 
						|
 |