support optional output of `names` in source maps (#3784)
authorAlex Lam S.L <alexlamsl@gmail.com>
Thu, 16 Apr 2020 23:20:48 +0000 (00:20 +0100)
committerGitHub <noreply@github.com>
Thu, 16 Apr 2020 23:20:48 +0000 (07:20 +0800)
README.md
lib/minify.js
lib/sourcemap.js
test/mocha/cli.js
test/mocha/sourcemaps.js

index 7e07cc8..c22808d 100644 (file)
--- a/README.md
+++ b/README.md
@@ -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
index ab397f5..2182d65 100644 (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");
index fc200ce..0e982f0 100644 (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;
index 8642a6b..5f29bbd 100644 (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) {
index 23698c5..91b38cd 100644 (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 = {};",