From e667f0acb87484617f506b561ecf0497ef9bdf25 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Tue, 23 May 2017 20:25:48 +0800 Subject: [PATCH] fix source map offset (#1993) Account for whitespace insertions. fixes #505 fixes #890 --- lib/output.js | 69 ++++++++++++++++++++++++---------- test/input/issue-505/input.js | 5 +++ test/input/issue-505/output.js | 5 +++ test/input/issue-520/output.js | 2 +- test/mocha/cli.js | 6 +-- test/mocha/minify.js | 14 ++++++- test/sourcemaps.js | 12 +++--- 7 files changed, 83 insertions(+), 30 deletions(-) create mode 100644 test/input/issue-505/input.js create mode 100644 test/input/issue-505/output.js diff --git a/lib/output.js b/lib/output.js index 40800559..e9765f7c 100644 --- a/lib/output.js +++ b/lib/output.js @@ -189,12 +189,43 @@ function OutputStream(options) { var might_need_semicolon = false; var might_add_newline = 0; var last = ""; + var mapping_token, mapping_name, mappings = options.source_map && []; + + var do_add_mapping = mappings ? function() { + mappings.forEach(function(mapping) { + try { + options.source_map.add( + mapping.token.file, + mapping.line, mapping.col, + mapping.token.line, mapping.token.col, + !mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name + ); + } catch(ex) { + AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { + file: mapping.token.file, + line: mapping.token.line, + col: mapping.token.col, + cline: mapping.line, + ccol: mapping.col, + name: mapping.name || "" + }) + } + }); + mappings = []; + } : noop; var ensure_line_len = options.max_line_len ? function() { if (current_col > options.max_line_len) { if (might_add_newline) { var left = OUTPUT.slice(0, might_add_newline); var right = OUTPUT.slice(might_add_newline); + if (mappings) { + var delta = right.length - current_col; + mappings.forEach(function(mapping) { + mapping.line++; + mapping.col += delta; + }); + } OUTPUT = left + "\n" + right; current_line++; current_pos++; @@ -204,7 +235,10 @@ function OutputStream(options) { AST_Node.warn("Output exceeds {max_line_len} characters", options); } } - might_add_newline = 0; + if (might_add_newline) { + might_add_newline = 0; + do_add_mapping(); + } } : noop; var requireSemicolonChars = makePredicate("( [ + * / - , ."); @@ -264,6 +298,18 @@ function OutputStream(options) { } might_need_space = false; } + + if (mapping_token) { + mappings.push({ + token: mapping_token, + name: mapping_name, + line: current_line, + col: current_col + }); + mapping_token = false; + if (!might_add_newline) do_add_mapping(); + } + OUTPUT += str; current_pos += str.length; var a = str.split(/\r?\n/), n = a.length - 1; @@ -358,24 +404,9 @@ function OutputStream(options) { space(); }; - var add_mapping = options.source_map ? function(token, name) { - try { - if (token) options.source_map.add( - token.file || "?", - current_line, current_col, - token.line, token.col, - (!name && token.type == "name") ? token.value : name - ); - } catch(ex) { - AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { - file: token.file, - line: token.line, - col: token.col, - cline: current_line, - ccol: current_col, - name: name || "" - }) - } + var add_mapping = mappings ? function(token, name) { + mapping_token = token; + mapping_name = name; } : noop; function get() { diff --git a/test/input/issue-505/input.js b/test/input/issue-505/input.js new file mode 100644 index 00000000..600b12cf --- /dev/null +++ b/test/input/issue-505/input.js @@ -0,0 +1,5 @@ +function test(callback) { + 'aaaaaaaaaaaaaaaa'; + callback(err, data); + callback(err, data); +} diff --git a/test/input/issue-505/output.js b/test/input/issue-505/output.js new file mode 100644 index 00000000..5a1bc018 --- /dev/null +++ b/test/input/issue-505/output.js @@ -0,0 +1,5 @@ +function test(a){ +"aaaaaaaaaaaaaaaa" +;a(err,data),a(err,data) +} +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7QUFDVjtDQUNBQSxFQUFTQyxJQUFLQyxNQUNkRixFQUFTQyxJQUFLQyJ9 \ No newline at end of file diff --git a/test/input/issue-520/output.js b/test/input/issue-520/output.js index 8d19855b..f6d13804 100644 --- a/test/input/issue-520/output.js +++ b/test/input/issue-520/output.js @@ -1,2 +1,2 @@ new function(){console.log(3)}; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxHQUFyQyxZQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19 +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19 diff --git a/test/mocha/cli.js b/test/mocha/cli.js index db4a2c33..565b6069 100644 --- a/test/mocha/cli.js +++ b/test/mocha/cli.js @@ -63,7 +63,7 @@ describe("bin/uglifyjs", function () { if (err) throw err; assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n" + - "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxHQUFJQSxLQUFNLFdBQ04sUUFBU0MsS0FBS0QsS0FDVixNQUFPQSxLQUdYLE1BQU9DIn0=\n"); + "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DIn0=\n"); done(); }); }); @@ -175,7 +175,7 @@ describe("bin/uglifyjs", function () { assert.strictEqual(stdout, [ "var bar=function(){function foo(bar){return bar}return foo}();", - "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxHQUFJQSxLQUFNLFdBQ04sUUFBU0MsS0FBS0QsS0FDVixNQUFPQSxLQUdYLE1BQU9DIn0=", + "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DIn0=", "", ].join("\n")); assert.strictEqual(stderr, "WARN: inline source map not found\n"); @@ -514,7 +514,7 @@ describe("bin/uglifyjs", function () { assert.strictEqual(stdout, [ '"use strict";var foo=function foo(x){return"foo "+x};console.log(foo("bar"));', - "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiWUFBQSxJQUFJQSxLQUFNLFFBQU5BLEtBQU1DLEdBQUEsTUFBSyxPQUFTQSxFQUN4QkMsU0FBUUMsSUFBSUgsSUFBSSJ9", + "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiYUFBQSxJQUFJQSxJQUFNLFNBQU5BLElBQU1DLEdBQUEsTUFBSyxPQUFTQSxHQUN4QkMsUUFBUUMsSUFBSUgsSUFBSSJ9", "" ].join("\n")); done(); diff --git a/test/mocha/minify.js b/test/mocha/minify.js index 99771755..77b798ec 100644 --- a/test/mocha/minify.js +++ b/test/mocha/minify.js @@ -138,13 +138,25 @@ describe("minify", function() { }); var code = result.code; assert.strictEqual(code, "var a=function(n){return n};\n" + - "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsR0FBSUEsR0FBSSxTQUFTQyxHQUFPLE1BQU9BIn0="); + "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BIn0="); }); it("should not append source map to output js when sourceMapInline is not enabled", function() { var result = Uglify.minify('var a = function(foo) { return foo; };'); var code = result.code; assert.strictEqual(code, "var a=function(n){return n};"); }); + it("should work with max_line_len", function() { + var result = Uglify.minify(read("./test/input/issue-505/input.js"), { + output: { + max_line_len: 20 + }, + sourceMap: { + url: "inline" + } + }); + assert.strictEqual(result.error, undefined); + assert.strictEqual(result.code, read("./test/input/issue-505/output.js")); + }); }); describe("#__PURE__", function() { diff --git a/test/sourcemaps.js b/test/sourcemaps.js index 4757d1e0..2717eff4 100644 --- a/test/sourcemaps.js +++ b/test/sourcemaps.js @@ -1,4 +1,4 @@ -var UglifyJS = require("./node"); +var UglifyJS = require(".."); var ok = require("assert"); module.exports = function () { @@ -26,11 +26,11 @@ module.exports = function () { } function source_map(js) { - var source_map = UglifyJS.SourceMap(); - var stream = UglifyJS.OutputStream({ source_map: source_map }); - var parsed = UglifyJS.parse(js); - parsed.print(stream); - return JSON.parse(source_map.toString()); + return JSON.parse(UglifyJS.minify(js, { + compress: false, + mangle: false, + sourceMap: true + }).map); } // Run standalone -- 2.34.1