support optional output of names in source maps (#3784)

This commit is contained in:
Alex Lam S.L
2020-04-17 00:20:48 +01:00
committed by GitHub
parent 0ce71bbec0
commit 83f42ede36
5 changed files with 115 additions and 27 deletions

View File

@@ -126,6 +126,7 @@ a double dash to prevent input files being used as option arguments:
`includeSources` Pass this flag if you want to include
the content of source files in the
source map as sourcesContent property.
`names` Include symbol names in the source map.
`root` Path to the original source to be included in
the source map.
`url` If specified, path to the source map to append in
@@ -159,6 +160,9 @@ Additional options:
- `--source-map "root='<URL>'"` to pass the URL where the original files can be found.
- `--source-map "names=false"` to omit symbol names if you want to reduce size
of the source map file.
- `--source-map "url='<URL>'"` to specify the URL where the source map can be found.
Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
`//# sourceMappingURL=` directive.
@@ -593,6 +597,9 @@ var result = UglifyJS.minify({"compiled.js": "compiled code"}, {
If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.url`.
If you wish to reduce file size of the source map, set option `sourceMap.names`
to be `false` and all symbol names will be omitted.
## Parse options
- `bare_returns` (default `false`) -- support top level `return` statements

View File

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

View File

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

View File

@@ -2,6 +2,7 @@ var assert = require("assert");
var exec = require("child_process").exec;
var fs = require("fs");
var run_code = require("../sandbox").run_code;
var to_ascii = require("../node").to_ascii;
function read(path) {
return fs.readFileSync(path, "utf8");
@@ -48,6 +49,62 @@ describe("bin/uglifyjs", function() {
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) {
var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline --verbose";
exec(command, function(err, stdout, stderr) {

View File

@@ -7,11 +7,13 @@ function read(path) {
}
function source_map(code) {
return JSON.parse(UglifyJS.minify(code, {
var result = UglifyJS.minify(code, {
compress: false,
mangle: false,
sourceMap: true,
}).map);
});
if (result.error) throw result.error;
return JSON.parse(result.map);
}
function get_map() {
@@ -65,6 +67,40 @@ describe("sourcemaps", function() {
].join("\n"));
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() {
var result = UglifyJS.minify([
"var obj = {};",