fix corner cases in `sourceMap` (#3397)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sat, 4 May 2019 12:08:57 +0000 (20:08 +0800)
committerGitHub <noreply@github.com>
Sat, 4 May 2019 12:08:57 +0000 (20:08 +0800)
fixes #3255
fixes #3294

lib/minify.js
test/input/issue-3040/expect.js [moved from test/input/pr-3040/expect.js with 100% similarity]
test/input/issue-3040/input.js [moved from test/input/pr-3040/input.js with 100% similarity]
test/input/issue-3040/input.js.map [moved from test/input/pr-3040/input.js.map with 100% similarity]
test/input/issue-3294/input.js [new file with mode: 0644]
test/input/issue-3294/output.js [new file with mode: 0644]
test/mocha/cli.js
test/mocha/comments.js
test/mocha/sourcemaps.js

index 5f865c6..1bb6309 100644 (file)
@@ -8,7 +8,7 @@ var to_base64 = typeof btoa == "undefined" ? function(str) {
 } : btoa;
 
 function read_source_map(name, code) {
-    var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
+    var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(\S+)\s*$/.exec(code);
     if (!match) {
         AST_Node.warn("inline source map not found: " + name);
         return null;
@@ -204,10 +204,14 @@ function minify(files, options) {
             result.code = stream.get();
             if (options.sourceMap) {
                 result.map = options.output.source_map.toString();
-                if (options.sourceMap.url == "inline") {
-                    result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(result.map);
-                } else if (options.sourceMap.url) {
-                    result.code += "\n//# sourceMappingURL=" + options.sourceMap.url;
+                var url = options.sourceMap.url;
+                if (url) {
+                    result.code = result.code.replace(/\n\/\/# sourceMappingURL=\S+\s*$/, "");
+                    if (url == "inline") {
+                        result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(result.map);
+                    } else {
+                        result.code += "\n//# sourceMappingURL=" + url;
+                    }
                 }
             }
         }
diff --git a/test/input/issue-3294/input.js b/test/input/issue-3294/input.js
new file mode 100644 (file)
index 0000000..09ee40f
--- /dev/null
@@ -0,0 +1,6 @@
+var Foo = function Foo(){console.log(1+2);}; new Foo();
+
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,DeadBeef
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLElBQU0sR0FBRyxHQUFDLEFBQUUsWUFBVyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLEFBQUUsQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDOyJ9
+
+
diff --git a/test/input/issue-3294/output.js b/test/input/issue-3294/output.js
new file mode 100644 (file)
index 0000000..f6d1380
--- /dev/null
@@ -0,0 +1,2 @@
+new function(){console.log(3)};
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
index 6d6e1e8..f99a8be 100644 (file)
@@ -114,13 +114,12 @@ describe("bin/uglifyjs", function() {
 
         var child = exec(command, function(err, stdout) {
             if (err) throw err;
-
-            assert.strictEqual(stdout, read("test/input/pr-3040/expect.js"));
+            assert.strictEqual(stdout, read("test/input/issue-3040/expect.js"));
             done();
         });
         setTimeout(function() {
-            fs.writeFileSync(mapFile, read("test/input/pr-3040/input.js.map"));
-            child.stdin.end(read("test/input/pr-3040/input.js"));
+            fs.writeFileSync(mapFile, read("test/input/issue-3040/input.js.map"));
+            child.stdin.end(read("test/input/issue-3040/input.js"));
         }, 1000);
     });
     it("Should work with --keep-fnames (mangle only)", function(done) {
index 3907f2f..04dd171 100644 (file)
@@ -277,6 +277,43 @@ describe("comments", function() {
         ].join("\n"));
     });
 
+    it("Should not duplicate sourceMappingURL", function() {
+        var code = [
+            "//# sourceMappingURL=input.map",
+            "print(42);",
+            "//# sourceMappingURL=input.map",
+            "",
+            "//# sourceMappingURL=input.map",
+            "//# sourceMappingURL=input.map",
+            "",
+        ].join("\n");
+
+        var result = UglifyJS.minify(code, {
+            output: { comments: true },
+        });
+        if (result.error) throw result.error;
+        assert.strictEqual(result.code, [
+            "//# sourceMappingURL=input.map",
+            "print(42);",
+            "//# sourceMappingURL=input.map",
+            "//# sourceMappingURL=input.map",
+            "//# sourceMappingURL=input.map",
+        ].join("\n"));
+
+        result = UglifyJS.minify(code, {
+            output: { comments: true },
+            sourceMap: { url: "output.map" },
+        });
+        if (result.error) throw result.error;
+        assert.strictEqual(result.code, [
+            "//# sourceMappingURL=input.map",
+            "print(42);",
+            "//# sourceMappingURL=input.map",
+            "//# sourceMappingURL=input.map",
+            "//# sourceMappingURL=output.map",
+        ].join("\n"));
+    });
+
     describe("comment before constant", function() {
         var js = 'function f() { /*c1*/ var /*c2*/ foo = /*c3*/ false; return foo; }';
 
index f625b22..78e100b 100644 (file)
@@ -169,6 +169,18 @@ describe("sourcemaps", function() {
             map = JSON.parse(result.map);
             assert.ok(!("sourcesContent" in map));
         });
+        it("Should parse the correct sourceMappingURL", function() {
+            var result = UglifyJS.minify(read("./test/input/issue-3294/input.js"), {
+                compress: { toplevel: true },
+                sourceMap: {
+                    content: "inline",
+                    includeSources: true,
+                    url: "inline"
+                }
+            });
+            if (result.error) throw result.error;
+            assert.strictEqual(result.code + "\n", readFileSync("test/input/issue-3294/output.js", "utf8"));
+        });
     });
 
     describe("sourceMapInline", function() {