diff --git a/lib/sourcemap.js b/lib/sourcemap.js index f2a6c8720..65c1ba7d4 100644 --- a/lib/sourcemap.js +++ b/lib/sourcemap.js @@ -74,12 +74,21 @@ function SourceMap(options) { } function add(source, gen_line, gen_col, orig_line, orig_col, name) { + var generatedPos = { line: gen_line + options.dest_line_diff, column: gen_col }; if (orig_map) { var info = orig_map.originalPositionFor({ line: orig_line, column: orig_col }); if (info.source === null) { + if (generatedPos.column !== 0) { + generator.addMapping({ + generated: generatedPos, + original: null, + source: null, + name: null + }); + } return; } source = info.source; @@ -88,7 +97,7 @@ function SourceMap(options) { name = info.name || name; } generator.addMapping({ - generated : { line: gen_line + options.dest_line_diff, column: gen_col }, + generated : generatedPos, original : { line: orig_line + options.orig_line_diff, column: orig_col }, source : source, name : name diff --git a/test/mocha/input-sourcemaps.js b/test/mocha/input-sourcemaps.js index bda6e1a21..a0aa57dcf 100644 --- a/test/mocha/input-sourcemaps.js +++ b/test/mocha/input-sourcemaps.js @@ -1,6 +1,7 @@ var Uglify = require('../../'); var assert = require("assert"); var SourceMapConsumer = require("source-map").SourceMapConsumer; +var SourceMapGenerator = require("source-map").SourceMapGenerator; describe("input sourcemaps", function() { var transpilemap, map; @@ -63,4 +64,47 @@ describe("input sourcemaps", function() { assert.ok(pos.line <= 2, msg); }) }); + + it("Should preserve unmapped segments in output source map", function() { + var generator = new SourceMapGenerator(); + + generator.addMapping({ + source: "source.ts", + generated: {line: 1, column: 0}, + original: {line: 1, column: 0}, + }); + + generator.addMapping({ + source: null, + original: null, + generated: {line: 1, column: 38} + }); + + generator.addMapping({ + source: "source.ts", + generated: {line: 1, column: 51}, + original: {line: 2, column: 0}, + }); + + // Everything except the "say('hello');" part is mapped to "source.ts". The "say" + // function call is not mapped to any original source location. e.g. this can + // happen when a code transformer inserts generated code in between existing code. + var inputFile = "function say(msg) {console.log(msg)};say('hello');process.exit(1);"; + var result = Uglify.minify(inputFile, { + sourceMap: { + content: JSON.parse(generator.toString()) + } + }); + + var transformedMap = new SourceMapConsumer(result.map); + var hasMappedSource = true; + + for (let i = 0; i < result.code.length; i++) { + var info = transformedMap.originalPositionFor({line: 1, column: i}); + hasMappedSource = hasMappedSource && !!info.source; + } + + assert.equal(hasMappedSource, false, "Expected transformed source map to preserve the " + + "mapping without original source location"); + }); });