"use strict";
var SourceNode = require("source-map").SourceNode;
var SourceMapConsumer = require("source-map").SourceMapConsumer;
var applySourceMap = function(
sourceNode,
sourceMapConsumer,
sourceFile,
removeGeneratedCodeForSourceFile
) {
var l2rResult = new SourceNode();
var l2rOutput = [];
var middleSourceContents = {};
var m2rMappingsByLine = {};
var rightSourceContentsSet = {};
var rightSourceContentsLines = {};
sourceMapConsumer.eachMapping(
function(mapping) {
(m2rMappingsByLine[mapping.generatedLine] =
m2rMappingsByLine[mapping.generatedLine] || []).push(mapping);
},
null,
SourceMapConsumer.GENERATED_ORDER
);
sourceNode.walkSourceContents(function(source, content) {
middleSourceContents["$" + source] = content;
});
var middleSource = middleSourceContents["$" + sourceFile];
var middleSourceLines = middleSource ? middleSource.split("\n") : undefined;
sourceNode.walk(function(chunk, middleMapping) {
var source;
if(
middleMapping.source === sourceFile &&
middleMapping.line &&
m2rMappingsByLine[middleMapping.line]
) {
var m2rBestFit;
var m2rMappings = m2rMappingsByLine[middleMapping.line];
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;
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) {
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;
}
}
}
source = m2rBestFit.source;
l2rOutput.push(
new SourceNode(
m2rBestFit.originalLine,
m2rBestFit.originalColumn,
source,
chunk,
allowMiddleName ? middleMapping.name : m2rBestFit.name
)
);
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) {
l2rOutput.push(chunk);
return;
}
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];
}
}
});
l2rResult.add(l2rOutput);
return l2rResult;
};
module.exports = applySourceMap;