From a49584bb66e898f5f90635e05f997b757dfec1fa Mon Sep 17 00:00:00 2001 From: Sergei Startsev Date: Fri, 16 Sep 2016 22:44:25 +0300 Subject: [PATCH] fix incorrect concatenation of source maps --- lib/output.js | 76 +++++++++-------------------- lib/sourcemaps.js | 119 ++++++++++------------------------------------ 2 files changed, 48 insertions(+), 147 deletions(-) diff --git a/lib/output.js b/lib/output.js index 3dda1fa..7437e78 100644 --- a/lib/output.js +++ b/lib/output.js @@ -4,69 +4,39 @@ var fs = require('fs'); var Promise = require('bluebird'); var asp = require('bluebird').promisify; var extend = require('./utils').extend; - var fromFileURL = require('./utils').fromFileURL; -var toFileURL = require('./utils').toFileURL; function countLines(str) { return str.split(/\r\n|\r|\n/).length; } -// Process compiler outputs, gathering: -// -// concatOutputs: list of source strings to concatenate -// sourceMapsWithOffsets: list of [absolute offset, -// source map string] pairs -// -// Takes lists as empty references and populates via push. -function processOutputs(outputs) { - var removeSourceMaps = require('./sourcemaps').removeSourceMaps; - - var offset = 0; - - var outputObj = {}; - - var sources = outputObj.sources = []; - var sourceMapsWithOffsets = outputObj.sourceMapsWithOffsets = []; - - outputs.forEach(function(output) { - var source; - if (typeof output == 'object') { - source = output.source || ''; - var offset_ = output.sourceMapOffset || 0; - var map = output.sourceMap; - if (map) { - sourceMapsWithOffsets.push([offset + offset_, map]); - } - } - // NB perhaps we should enforce output is always an object down the chain? - else if (typeof output == 'string') { - source = output; - } - else { - throw "Unexpected output format: " + output.toString(); +function createOutput(outFile, outputs, basePath, sourceMaps, sourceMapContents) { + var concatenate = require('./sourcemaps').concatenate; + var files = outputs.map(function (el) { + if (el.source) { + //normalize source urls + el.sourceMap.sources = el.sourceMap.sources.map(function (sourceURL) { + return sourceURL.replace(/\\/g, "/"); + }); + return { + code: el.source, + map: el.sourceMap + }; + } else { + return { + code: el, + map: undefined + }; } - source = removeSourceMaps(source || ''); - offset += countLines(source); - sources.push(source); }); - - return outputObj; -} - -function createOutput(outFile, outputs, basePath, sourceMaps, sourceMapContents) { - var concatenateSourceMaps = require('./sourcemaps').concatenateSourceMaps; - - var outputObj = processOutputs(outputs); - - if (sourceMaps) - var sourceMap = concatenateSourceMaps(outFile, outputObj.sourceMapsWithOffsets, basePath, sourceMapContents); - - var output = outputObj.sources.join('\n'); + //concatenates sources and appropriate source maps + var concatenated = concatenate(files, outFile).toStringWithSourceMap({ + file: path.basename(outFile) + }); return { - source: output, - sourceMap: sourceMap + source: concatenated.code, + sourceMap: concatenated.map.toString() }; } diff --git a/lib/sourcemaps.js b/lib/sourcemaps.js index 2e70880..4392699 100644 --- a/lib/sourcemaps.js +++ b/lib/sourcemaps.js @@ -1,105 +1,36 @@ var sourceMap = require('source-map'); +var SourceNode = sourceMap.SourceNode; +var SourceMapConsumer = sourceMap.SourceMapConsumer; var path = require('path'); -var fs = require('fs'); -var toFileURL = require('./utils').toFileURL; -var fromFileURL = require('./utils').fromFileURL; +exports.concatenate = function(files, outFile) { + var concatenated = new SourceNode(); -var wrapSourceMap = function(map) { - return new sourceMap.SourceMapConsumer(map); -}; - -var sourceMapRegEx = /\/\/[@#] ?(sourceURL|sourceMappingURL)=([^\n'"]+)/; -exports.removeSourceMaps = function(source) { - return source.replace(sourceMapRegEx, ''); -}; - -function getMapObject(map) { - if (typeof map != 'string') - return map; - - try { - return JSON.parse(map); - } - catch(error) { - throw new Error('Invalid JSON: ' + map); - } -} - -function isFileURL(url) { - return url.substr(0, 8) == 'file:///'; -} - -exports.concatenateSourceMaps = function(outFile, mapsWithOffsets, basePath, sourceMapContents) { - var generated = new sourceMap.SourceMapGenerator({ - file: path.basename(outFile) - }); - - var outPath = path.dirname(outFile); - - var contentsBySource = sourceMapContents ? {} : null; - - mapsWithOffsets.forEach(function(pair) { - var offset = pair[0]; - var map = getMapObject(pair[1]); - - if (sourceMapContents && map.sourcesContent) { - for (var i=0; i