From dd76272fb1e724227c941666d69acb158fe1c87a Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Tue, 3 Nov 2015 14:24:36 +0000 Subject: [PATCH] fix source map merging - closes #2522, fixes #2336 --- packages/babel-cli/src/babel/file.js | 2 +- .../src/transformation/file/index.js | 31 ++++++++++++--- packages/babel-core/test/api.js | 39 +++++++++++++++++++ 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/packages/babel-cli/src/babel/file.js b/packages/babel-cli/src/babel/file.js index b8e03b526f..068cd3b870 100644 --- a/packages/babel-cli/src/babel/file.js +++ b/packages/babel-cli/src/babel/file.js @@ -25,7 +25,7 @@ module.exports = function (commander, filenames, opts) { let offset = 0; _.each(results, function (result) { - let filename = result.filename; + let filename = result.filename || "stdout"; code += result.code + "\n"; if (result.map) { diff --git a/packages/babel-core/src/transformation/file/index.js b/packages/babel-core/src/transformation/file/index.js index 5d5e18f29f..9257f8f882 100644 --- a/packages/babel-core/src/transformation/file/index.js +++ b/packages/babel-core/src/transformation/file/index.js @@ -355,13 +355,32 @@ export default class File extends Store { if (inputMap) { let inputMapConsumer = new sourceMap.SourceMapConsumer(inputMap); let outputMapConsumer = new sourceMap.SourceMapConsumer(map); - let outputMapGenerator = sourceMap.SourceMapGenerator.fromSourceMap(outputMapConsumer); - outputMapGenerator.applySourceMap(inputMapConsumer); - let mergedMap = outputMapGenerator.toJSON(); - mergedMap.sources = inputMap.sources; - mergedMap.file = inputMap.file; - return mergedMap; + let mergedGenerator = new sourceMap.SourceMapGenerator({ + file: inputMapConsumer.file, + sourceRoot: inputMapConsumer.sourceRoot + }); + + inputMapConsumer.eachMapping(function (mapping) { + mergedGenerator.addMapping({ + source: inputMapConsumer.file, + + original: { + line: mapping.originalLine, + column: mapping.originalColumn + }, + + generated: outputMapConsumer.generatedPositionFor({ + line: mapping.generatedLine, + column: mapping.generatedColumn, + source: outputMapConsumer.file + }) + }); + }); + + let mergedMap = mergedGenerator.toJSON(); + inputMap.mappings = mergedMap.mappings; + return inputMap; } else { return map; } diff --git a/packages/babel-core/test/api.js b/packages/babel-core/test/api.js index 445efb8921..e279d5f613 100644 --- a/packages/babel-core/test/api.js +++ b/packages/babel-core/test/api.js @@ -3,6 +3,7 @@ require("../lib/api/node"); var buildExternalHelpers = require("../lib/tools/build-external-helpers"); var transform = require("../lib/api/node").transform; var Pipeline = require("../lib/transformation/pipeline"); +var sourceMap = require("source-map"); var assert = require("assert"); var File = require("../lib/transformation/file").default; @@ -33,6 +34,44 @@ suite("api", function () { }); }); + test("source map merging", function () { + var result = transform([ + 'function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }', + '', + 'let Foo = function Foo() {', + ' _classCallCheck(this, Foo);', + '};', + '', + '//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZG91dCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztJQUFNLEdBQUcsWUFBSCxHQUFHO3dCQUFILEdBQUciLCJmaWxlIjoidW5kZWZpbmVkIiwic291cmNlc0NvbnRlbnQiOlsiY2xhc3MgRm9vIHt9XG4iXX0=' + ].join("\n"), { + sourceMap: true + }); + + assert.deepEqual([ + "function _classCallCheck(instance, Constructor) {", + " if (!(instance instanceof Constructor)) {", + ' throw new TypeError("Cannot call a class as a function");', + " }", + "}", + "", + "let Foo = function Foo() {", + " _classCallCheck(this, Foo);", + "};" + ].join("\n"), result.code); + + var consumer = new sourceMap.SourceMapConsumer(result.map); + + assert.deepEqual(consumer.originalPositionFor({ + line: 7, + column: 4 + }), { + name: null, + source: "stdout", + line: 1, + column: 6 + }); + }); + test("code option false", function () { return transformAsync("foo('bar');", { code: false }).then(function (result) { assert.ok(!result.code);