support optional output of names in source maps

This commit is contained in:
alexlamsl 2020-04-17 05:29:13 +08:00
parent 46d142cbf6
commit 0568c665fb
4 changed files with 108 additions and 27 deletions

View File

@ -129,6 +129,7 @@ function minify(files, options) {
content: null, content: null,
filename: null, filename: null,
includeSources: false, includeSources: false,
names: true,
root: null, root: null,
url: null, url: null,
}, true); }, true);
@ -138,7 +139,7 @@ function minify(files, options) {
warnings.push(warning); warnings.push(warning);
}, options.warnings == "verbose"); }, options.warnings == "verbose");
if (timings) timings.parse = Date.now(); if (timings) timings.parse = Date.now();
var source_maps, toplevel; var toplevel;
if (files instanceof AST_Toplevel) { if (files instanceof AST_Toplevel) {
toplevel = files; toplevel = files;
} else { } else {
@ -151,19 +152,17 @@ function minify(files, options) {
if (typeof source_map_content == "string" && source_map_content != "inline") { if (typeof source_map_content == "string" && source_map_content != "inline") {
source_map_content = parse_source_map(source_map_content); source_map_content = parse_source_map(source_map_content);
} }
source_maps = source_map_content && Object.create(null); if (source_map_content) options.sourceMap.orig = Object.create(null);
for (var name in files) if (HOP(files, name)) { for (var name in files) if (HOP(files, name)) {
options.parse.filename = name; options.parse.filename = name;
options.parse.toplevel = toplevel = parse(files[name], options.parse); options.parse.toplevel = toplevel = parse(files[name], options.parse);
if (source_maps) { if (source_map_content == "inline") {
if (source_map_content == "inline") { var inlined_content = read_source_map(name, toplevel);
var inlined_content = read_source_map(name, toplevel); if (inlined_content) {
if (inlined_content) { options.sourceMap.orig[name] = parse_source_map(inlined_content);
source_maps[name] = parse_source_map(inlined_content);
}
} else {
source_maps[name] = source_map_content;
} }
} else if (source_map_content) {
options.sourceMap.orig[name] = source_map_content;
} }
} }
} }
@ -202,12 +201,7 @@ function minify(files, options) {
} }
if (!HOP(options.output, "code") || options.output.code) { if (!HOP(options.output, "code") || options.output.code) {
if (options.sourceMap) { if (options.sourceMap) {
options.output.source_map = SourceMap({ options.output.source_map = SourceMap(options.sourceMap);
content: options.sourceMap.includeSources,
file: options.sourceMap.filename,
orig: source_maps,
root: options.sourceMap.root
});
if (options.sourceMap.includeSources) { if (options.sourceMap.includeSources) {
if (files instanceof AST_Toplevel) { if (files instanceof AST_Toplevel) {
throw new Error("original source content unavailable"); throw new Error("original source content unavailable");

View File

@ -90,14 +90,8 @@ function create_array_map() {
} }
function SourceMap(options) { function SourceMap(options) {
options = defaults(options, {
content: false,
file: null,
root: null,
orig: null,
}, true);
var sources = create_array_map(); var sources = create_array_map();
var sources_content = options.content && Object.create(null); var sources_content = options.includeSources && Object.create(null);
var names = create_array_map(); var names = create_array_map();
var mappings = ""; var mappings = "";
if (options.orig) Object.keys(options.orig).forEach(function(name) { if (options.orig) Object.keys(options.orig).forEach(function(name) {
@ -155,7 +149,7 @@ function SourceMap(options) {
toString: function() { toString: function() {
return JSON.stringify({ return JSON.stringify({
version: 3, version: 3,
file: options.file || undefined, file: options.filename || undefined,
sourceRoot: options.root || undefined, sourceRoot: options.root || undefined,
sources: sources, sources: sources,
sourcesContent: sources_content ? sources.map(function(source) { sourcesContent: sources_content ? sources.map(function(source) {
@ -188,7 +182,7 @@ function SourceMap(options) {
original_line = orig_line; original_line = orig_line;
mappings += vlq_encode(orig_col - original_column); mappings += vlq_encode(orig_col - original_column);
original_column = orig_col; original_column = orig_col;
if (name != null) { if (options.names && name != null) {
var name_idx = names.index(name); var name_idx = names.index(name);
mappings += vlq_encode(name_idx - name_index); mappings += vlq_encode(name_idx - name_index);
name_index = name_idx; name_index = name_idx;

View File

@ -2,6 +2,7 @@ var assert = require("assert");
var exec = require("child_process").exec; var exec = require("child_process").exec;
var fs = require("fs"); var fs = require("fs");
var run_code = require("../sandbox").run_code; var run_code = require("../sandbox").run_code;
var to_ascii = require("../node").to_ascii;
function read(path) { function read(path) {
return fs.readFileSync(path, "utf8"); return fs.readFileSync(path, "utf8");
@ -48,6 +49,62 @@ describe("bin/uglifyjs", function() {
done(); done();
}); });
}); });
it("Should work with --source-map names=true", function(done) {
exec([
uglifyjscmd,
"--beautify",
"--source-map", [
"names=true",
"url=inline",
].join(","),
].join(" "), function(err, stdout) {
if (err) throw err;
var expected = [
"var obj = {",
" p: a,",
" q: b",
"};",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,",
].join("\n")
assert.strictEqual(stdout.slice(0, expected.length), expected);
var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim()));
assert.deepEqual(map.names, [ "obj", "p", "a", "q", "b" ]);
done();
}).stdin.end([
"var obj = {",
" p: a,",
" q: b",
"};",
].join("\n"));
});
it("Should work with --source-map names=false", function(done) {
exec([
uglifyjscmd,
"--beautify",
"--source-map", [
"names=false",
"url=inline",
].join(","),
].join(" "), function(err, stdout) {
if (err) throw err;
var expected = [
"var obj = {",
" p: a,",
" q: b",
"};",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,",
].join("\n")
assert.strictEqual(stdout.slice(0, expected.length), expected);
var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim()));
assert.deepEqual(map.names, []);
done();
}).stdin.end([
"var obj = {",
" p: a,",
" q: b",
"};",
].join("\n"));
});
it("Should give sensible error against invalid input source map", function(done) { it("Should give sensible error against invalid input source map", function(done) {
var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline --verbose"; var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline --verbose";
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {

View File

@ -7,11 +7,13 @@ function read(path) {
} }
function source_map(code) { function source_map(code) {
return JSON.parse(UglifyJS.minify(code, { var result = UglifyJS.minify(code, {
compress: false, compress: false,
mangle: false, mangle: false,
sourceMap: true, sourceMap: true,
}).map); });
if (result.error) throw result.error;
return JSON.parse(result.map);
} }
function get_map() { function get_map() {
@ -65,6 +67,40 @@ describe("sourcemaps", function() {
].join("\n")); ].join("\n"));
assert.deepEqual(map.names, [ "enabled", "x" ]); assert.deepEqual(map.names, [ "enabled", "x" ]);
}); });
it("Should work with sourceMap.names=true", function() {
var result = UglifyJS.minify([
"var obj = {",
" p: a,",
" q: b",
"};",
].join("\n"), {
compress: false,
mangle: false,
sourceMap: {
names: true,
},
});
if (result.error) throw result.error;
var map = JSON.parse(result.map);
assert.deepEqual(map.names, [ "obj", "p", "a", "q", "b" ]);
});
it("Should work with sourceMap.names=false", function() {
var result = UglifyJS.minify([
"var obj = {",
" p: a,",
" q: b",
"};",
].join("\n"), {
compress: false,
mangle: false,
sourceMap: {
names: false,
},
});
if (result.error) throw result.error;
var map = JSON.parse(result.map);
assert.deepEqual(map.names, []);
});
it("Should mark array/object literals", function() { it("Should mark array/object literals", function() {
var result = UglifyJS.minify([ var result = UglifyJS.minify([
"var obj = {};", "var obj = {};",