aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/uglifyjs71
-rw-r--r--test/input/issue-520/input.js3
-rw-r--r--test/input/issue-520/output.js2
-rw-r--r--test/mocha/cli.js48
-rw-r--r--test/mocha/minify.js46
-rw-r--r--tools/node.js31
6 files changed, 171 insertions, 30 deletions
diff --git a/bin/uglifyjs b/bin/uglifyjs
index 27717fb6..d0c3abb2 100755
--- a/bin/uglifyjs
+++ b/bin/uglifyjs
@@ -282,21 +282,29 @@ if (ARGS.self) {
var ORIG_MAP = ARGS.in_source_map;
-if (ORIG_MAP) {
+if (ORIG_MAP && ORIG_MAP != "inline") {
ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP));
if (files.length == 0) {
print_error("INFO: Using file from the input source map: " + ORIG_MAP.file);
files = [ ORIG_MAP.file ];
}
- if (ARGS.source_map_root == null) {
- ARGS.source_map_root = ORIG_MAP.sourceRoot;
- }
}
if (files.length == 0) {
files = [ "-" ];
}
+if (ORIG_MAP == "inline") {
+ if (files.length > 1) {
+ print_error("ERROR: Inline source map only works with singular input");
+ process.exit(1);
+ }
+ if (ARGS.acorn || ARGS.spidermonkey) {
+ print_error("ERROR: Inline source map only works with built-in parser");
+ process.exit(1);
+ }
+}
+
if (files.indexOf("-") >= 0 && ARGS.source_map) {
print_error("ERROR: Source map doesn't work with input from STDIN");
process.exit(1);
@@ -308,37 +316,19 @@ if (files.filter(function(el){ return el == "-" }).length > 1) {
}
var STATS = {};
-var OUTPUT_FILE = ARGS.o;
var TOPLEVEL = null;
var P_RELATIVE = ARGS.p && ARGS.p == "relative";
var SOURCES_CONTENT = {};
-var SOURCE_MAP = (ARGS.source_map || ARGS.source_map_inline) ? UglifyJS.SourceMap({
- file: P_RELATIVE ? path.relative(path.dirname(ARGS.source_map), OUTPUT_FILE) : OUTPUT_FILE,
- root: ARGS.source_map_root,
- orig: ORIG_MAP,
-}) : null;
-
-OUTPUT_OPTIONS.source_map = SOURCE_MAP;
-
-try {
- var output = UglifyJS.OutputStream(OUTPUT_OPTIONS);
- var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
-} catch(ex) {
- if (ex instanceof UglifyJS.DefaultsError) {
- print_error(ex.msg);
- print_error("Supported options:");
- print_error(sys.inspect(ex.defs));
- process.exit(1);
- }
-}
-
async.eachLimit(files, 1, function (file, cb) {
read_whole_file(file, function (err, code) {
if (err) {
print_error("ERROR: can't read file: " + file);
process.exit(1);
}
+ if (ORIG_MAP == "inline") {
+ ORIG_MAP = read_source_map(code);
+ }
if (ARGS.p != null) {
if (P_RELATIVE) {
file = path.relative(path.dirname(ARGS.source_map), file).replace(/\\/g, '/');
@@ -385,6 +375,28 @@ async.eachLimit(files, 1, function (file, cb) {
cb();
});
}, function () {
+ var OUTPUT_FILE = ARGS.o;
+
+ var SOURCE_MAP = (ARGS.source_map || ARGS.source_map_inline) ? UglifyJS.SourceMap({
+ file: P_RELATIVE ? path.relative(path.dirname(ARGS.source_map), OUTPUT_FILE) : OUTPUT_FILE,
+ root: ARGS.source_map_root || ORIG_MAP && ORIG_MAP.sourceRoot,
+ orig: ORIG_MAP,
+ }) : null;
+
+ OUTPUT_OPTIONS.source_map = SOURCE_MAP;
+
+ try {
+ var output = UglifyJS.OutputStream(OUTPUT_OPTIONS);
+ var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
+ } catch(ex) {
+ if (ex instanceof UglifyJS.DefaultsError) {
+ print_error(ex.msg);
+ print_error("Supported options:");
+ print_error(sys.inspect(ex.defs));
+ process.exit(1);
+ }
+ }
+
if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){
TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
});
@@ -576,6 +588,15 @@ function read_whole_file(filename, cb) {
}
}
+function read_source_map(code) {
+ var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
+ if (!match) {
+ print_error("WARN: inline source map not found");
+ return null;
+ }
+ return JSON.parse(new Buffer(match[2], "base64"));
+}
+
function time_it(name, cont) {
var t1 = new Date().getTime();
var ret = cont();
diff --git a/test/input/issue-520/input.js b/test/input/issue-520/input.js
new file mode 100644
index 00000000..62428a52
--- /dev/null
+++ b/test/input/issue-520/input.js
@@ -0,0 +1,3 @@
+var Foo = function Foo(){console.log(1+2);}; new Foo();
+
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLElBQU0sR0FBRyxHQUFDLEFBQUUsWUFBVyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLEFBQUUsQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDOyJ9
diff --git a/test/input/issue-520/output.js b/test/input/issue-520/output.js
new file mode 100644
index 00000000..8d19855b
--- /dev/null
+++ b/test/input/issue-520/output.js
@@ -0,0 +1,2 @@
+new function(){console.log(3)};
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxHQUFyQyxZQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
diff --git a/test/mocha/cli.js b/test/mocha/cli.js
index 450df1fd..52c70935 100644
--- a/test/mocha/cli.js
+++ b/test/mocha/cli.js
@@ -151,4 +151,52 @@ describe("bin/uglifyjs", function () {
done();
});
});
+ it("Should process inline source map", function(done) {
+ var command = uglifyjscmd + ' test/input/issue-520/input.js -cm toplevel --in-source-map inline --source-map-inline';
+
+ exec(command, function (err, stdout) {
+ if (err) throw err;
+
+ assert.strictEqual(stdout, readFileSync("test/input/issue-520/output.js", "utf8"));
+ done();
+ });
+ });
+ it("Should warn for missing inline source map", function(done) {
+ var command = uglifyjscmd + ' test/input/issue-1323/sample.js --in-source-map inline';
+
+ exec(command, function (err, stdout, stderr) {
+ if (err) throw err;
+
+ assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n");
+ assert.strictEqual(stderr, "WARN: inline source map not found\n");
+ done();
+ });
+ });
+ it("Should fail with multiple input and inline source map", function(done) {
+ var command = uglifyjscmd + ' test/input/issue-520/input.js test/input/issue-520/output.js --in-source-map inline --source-map-inline';
+
+ exec(command, function (err, stdout, stderr) {
+ assert.ok(err);
+ assert.strictEqual(stderr, "ERROR: Inline source map only works with singular input\n");
+ done();
+ });
+ });
+ it("Should fail with acorn and inline source map", function(done) {
+ var command = uglifyjscmd + ' test/input/issue-520/input.js --in-source-map inline --source-map-inline --acorn';
+
+ exec(command, function (err, stdout, stderr) {
+ assert.ok(err);
+ assert.strictEqual(stderr, "ERROR: Inline source map only works with built-in parser\n");
+ done();
+ });
+ });
+ it("Should fail with SpiderMonkey and inline source map", function(done) {
+ var command = uglifyjscmd + ' test/input/issue-520/input.js --in-source-map inline --source-map-inline --spidermonkey';
+
+ exec(command, function (err, stdout, stderr) {
+ assert.ok(err);
+ assert.strictEqual(stderr, "ERROR: Inline source map only works with built-in parser\n");
+ done();
+ });
+ });
});
diff --git a/test/mocha/minify.js b/test/mocha/minify.js
index 8fe1565f..1b830cb5 100644
--- a/test/mocha/minify.js
+++ b/test/mocha/minify.js
@@ -1,5 +1,6 @@
var Uglify = require('../../');
var assert = require("assert");
+var readFileSync = require("fs").readFileSync;
describe("minify", function() {
it("Should test basic sanity of minify with default options", function() {
@@ -75,6 +76,51 @@ describe("minify", function() {
assert.equal(map.sourcesContent[0],
'let foo = x => "foo " + x;\nconsole.log(foo("bar"));');
});
+ it("Should process inline source map", function() {
+ var code = Uglify.minify("./test/input/issue-520/input.js", {
+ inSourceMap: "inline",
+ sourceMapInline: true
+ }).code + "\n";
+ assert.strictEqual(code, readFileSync("test/input/issue-520/output.js", "utf8"));
+ });
+ it("Should warn for missing inline source map", function() {
+ var warn_function = Uglify.AST_Node.warn_function;
+ var warnings = [];
+ Uglify.AST_Node.warn_function = function(txt) {
+ warnings.push(txt);
+ };
+ try {
+ var result = Uglify.minify("./test/input/issue-1323/sample.js", {
+ inSourceMap: "inline",
+ mangle: false,
+ });
+ assert.strictEqual(result.code, "var bar=function(){function foo(bar){return bar}return foo}();");
+ assert.strictEqual(warnings.length, 1);
+ assert.strictEqual(warnings[0], "inline source map not found");
+ } finally {
+ Uglify.AST_Node.warn_function = warn_function;
+ }
+ });
+ it("Should fail with multiple input and inline source map", function() {
+ assert.throws(function() {
+ Uglify.minify([
+ "./test/input/issue-520/input.js",
+ "./test/input/issue-520/output.js"
+ ], {
+ inSourceMap: "inline",
+ sourceMapInline: true
+ });
+ }, "multiple input and inline source map");
+ });
+ it("Should fail with SpiderMonkey and inline source map", function() {
+ assert.throws(function() {
+ Uglify.minify("./test/input/issue-520/input.js", {
+ inSourceMap: "inline",
+ sourceMapInline: true,
+ spidermonkey: true
+ });
+ }, "SpiderMonkey and inline source map");
+ });
});
describe("sourceMapInline", function() {
diff --git a/tools/node.js b/tools/node.js
index 108803e5..c64b4e5c 100644
--- a/tools/node.js
+++ b/tools/node.js
@@ -37,6 +37,15 @@ UglifyJS.AST_Node.warn_function = function(txt) {
console.error("WARN: %s", txt);
};
+function read_source_map(code) {
+ var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
+ if (!match) {
+ UglifyJS.AST_Node.warn("inline source map not found");
+ return null;
+ }
+ return JSON.parse(new Buffer(match[2], "base64"));
+}
+
exports.minify = function(files, options) {
options = UglifyJS.defaults(options, {
spidermonkey : false,
@@ -57,17 +66,28 @@ exports.minify = function(files, options) {
});
UglifyJS.base54.reset();
+ var inMap = options.inSourceMap;
+ if (typeof inMap == "string" && inMap != "inline") {
+ inMap = JSON.parse(fs.readFileSync(inMap, "utf8"));
+ }
+
// 1. parse
var toplevel = null,
sourcesContent = {};
if (options.spidermonkey) {
+ if (inMap == "inline") {
+ throw new Error("inline source map only works with built-in parser");
+ }
toplevel = UglifyJS.AST_Node.from_mozilla_ast(files);
} else {
function addFile(file, fileUrl) {
var code = options.fromString
? file
: fs.readFileSync(file, "utf8");
+ if (inMap == "inline") {
+ inMap = read_source_map(code);
+ }
sourcesContent[fileUrl] = code;
toplevel = UglifyJS.parse(code, {
filename: fileUrl,
@@ -75,7 +95,12 @@ exports.minify = function(files, options) {
bare_returns: options.parse ? options.parse.bare_returns : undefined
});
}
- if (!options.fromString) files = UglifyJS.simple_glob(files);
+ if (!options.fromString) {
+ files = UglifyJS.simple_glob(files);
+ if (inMap == "inline" && files.length > 1) {
+ throw new Error("inline source map only works with singular input");
+ }
+ }
[].concat(files).forEach(function (files, i) {
if (typeof files === 'string') {
addFile(files, options.fromString ? i : files);
@@ -114,11 +139,7 @@ exports.minify = function(files, options) {
}
// 5. output
- var inMap = options.inSourceMap;
var output = { max_line_len: 32000 };
- if (typeof options.inSourceMap == "string") {
- inMap = JSON.parse(fs.readFileSync(options.inSourceMap, "utf8"));
- }
if (options.outSourceMap || options.sourceMapInline) {
output.source_map = UglifyJS.SourceMap({
// prefer outFileName, otherwise use outSourceMap without .map suffix