allow --in-source-map inline (#1490)
- limited to one input file (or `stdin`) - only works with built-in parser fixes #520
This commit is contained in:
71
bin/uglifyjs
71
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();
|
||||
|
||||
3
test/input/issue-520/input.js
Normal file
3
test/input/issue-520/input.js
Normal file
@@ -0,0 +1,3 @@
|
||||
var Foo = function Foo(){console.log(1+2);}; new Foo();
|
||||
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLElBQU0sR0FBRyxHQUFDLEFBQUUsWUFBVyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLEFBQUUsQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDOyJ9
|
||||
2
test/input/issue-520/output.js
Normal file
2
test/input/issue-520/output.js
Normal file
@@ -0,0 +1,2 @@
|
||||
new function(){console.log(3)};
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxHQUFyQyxZQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user