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;
|
var ORIG_MAP = ARGS.in_source_map;
|
||||||
|
|
||||||
if (ORIG_MAP) {
|
if (ORIG_MAP && ORIG_MAP != "inline") {
|
||||||
ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP));
|
ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP));
|
||||||
if (files.length == 0) {
|
if (files.length == 0) {
|
||||||
print_error("INFO: Using file from the input source map: " + ORIG_MAP.file);
|
print_error("INFO: Using file from the input source map: " + ORIG_MAP.file);
|
||||||
files = [ ORIG_MAP.file ];
|
files = [ ORIG_MAP.file ];
|
||||||
}
|
}
|
||||||
if (ARGS.source_map_root == null) {
|
|
||||||
ARGS.source_map_root = ORIG_MAP.sourceRoot;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files.length == 0) {
|
if (files.length == 0) {
|
||||||
files = [ "-" ];
|
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) {
|
if (files.indexOf("-") >= 0 && ARGS.source_map) {
|
||||||
print_error("ERROR: Source map doesn't work with input from STDIN");
|
print_error("ERROR: Source map doesn't work with input from STDIN");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@@ -308,37 +316,19 @@ if (files.filter(function(el){ return el == "-" }).length > 1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var STATS = {};
|
var STATS = {};
|
||||||
var OUTPUT_FILE = ARGS.o;
|
|
||||||
var TOPLEVEL = null;
|
var TOPLEVEL = null;
|
||||||
var P_RELATIVE = ARGS.p && ARGS.p == "relative";
|
var P_RELATIVE = ARGS.p && ARGS.p == "relative";
|
||||||
var SOURCES_CONTENT = {};
|
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) {
|
async.eachLimit(files, 1, function (file, cb) {
|
||||||
read_whole_file(file, function (err, code) {
|
read_whole_file(file, function (err, code) {
|
||||||
if (err) {
|
if (err) {
|
||||||
print_error("ERROR: can't read file: " + file);
|
print_error("ERROR: can't read file: " + file);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
if (ORIG_MAP == "inline") {
|
||||||
|
ORIG_MAP = read_source_map(code);
|
||||||
|
}
|
||||||
if (ARGS.p != null) {
|
if (ARGS.p != null) {
|
||||||
if (P_RELATIVE) {
|
if (P_RELATIVE) {
|
||||||
file = path.relative(path.dirname(ARGS.source_map), file).replace(/\\/g, '/');
|
file = path.relative(path.dirname(ARGS.source_map), file).replace(/\\/g, '/');
|
||||||
@@ -385,6 +375,28 @@ async.eachLimit(files, 1, function (file, cb) {
|
|||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
}, function () {
|
}, 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(){
|
if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){
|
||||||
TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
|
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) {
|
function time_it(name, cont) {
|
||||||
var t1 = new Date().getTime();
|
var t1 = new Date().getTime();
|
||||||
var ret = cont();
|
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();
|
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 Uglify = require('../../');
|
||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
|
var readFileSync = require("fs").readFileSync;
|
||||||
|
|
||||||
describe("minify", function() {
|
describe("minify", function() {
|
||||||
it("Should test basic sanity of minify with default options", function() {
|
it("Should test basic sanity of minify with default options", function() {
|
||||||
@@ -75,6 +76,51 @@ describe("minify", function() {
|
|||||||
assert.equal(map.sourcesContent[0],
|
assert.equal(map.sourcesContent[0],
|
||||||
'let foo = x => "foo " + x;\nconsole.log(foo("bar"));');
|
'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() {
|
describe("sourceMapInline", function() {
|
||||||
|
|||||||
@@ -37,6 +37,15 @@ UglifyJS.AST_Node.warn_function = function(txt) {
|
|||||||
console.error("WARN: %s", 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) {
|
exports.minify = function(files, options) {
|
||||||
options = UglifyJS.defaults(options, {
|
options = UglifyJS.defaults(options, {
|
||||||
spidermonkey : false,
|
spidermonkey : false,
|
||||||
@@ -57,17 +66,28 @@ exports.minify = function(files, options) {
|
|||||||
});
|
});
|
||||||
UglifyJS.base54.reset();
|
UglifyJS.base54.reset();
|
||||||
|
|
||||||
|
var inMap = options.inSourceMap;
|
||||||
|
if (typeof inMap == "string" && inMap != "inline") {
|
||||||
|
inMap = JSON.parse(fs.readFileSync(inMap, "utf8"));
|
||||||
|
}
|
||||||
|
|
||||||
// 1. parse
|
// 1. parse
|
||||||
var toplevel = null,
|
var toplevel = null,
|
||||||
sourcesContent = {};
|
sourcesContent = {};
|
||||||
|
|
||||||
if (options.spidermonkey) {
|
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);
|
toplevel = UglifyJS.AST_Node.from_mozilla_ast(files);
|
||||||
} else {
|
} else {
|
||||||
function addFile(file, fileUrl) {
|
function addFile(file, fileUrl) {
|
||||||
var code = options.fromString
|
var code = options.fromString
|
||||||
? file
|
? file
|
||||||
: fs.readFileSync(file, "utf8");
|
: fs.readFileSync(file, "utf8");
|
||||||
|
if (inMap == "inline") {
|
||||||
|
inMap = read_source_map(code);
|
||||||
|
}
|
||||||
sourcesContent[fileUrl] = code;
|
sourcesContent[fileUrl] = code;
|
||||||
toplevel = UglifyJS.parse(code, {
|
toplevel = UglifyJS.parse(code, {
|
||||||
filename: fileUrl,
|
filename: fileUrl,
|
||||||
@@ -75,7 +95,12 @@ exports.minify = function(files, options) {
|
|||||||
bare_returns: options.parse ? options.parse.bare_returns : undefined
|
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) {
|
[].concat(files).forEach(function (files, i) {
|
||||||
if (typeof files === 'string') {
|
if (typeof files === 'string') {
|
||||||
addFile(files, options.fromString ? i : files);
|
addFile(files, options.fromString ? i : files);
|
||||||
@@ -114,11 +139,7 @@ exports.minify = function(files, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 5. output
|
// 5. output
|
||||||
var inMap = options.inSourceMap;
|
|
||||||
var output = { max_line_len: 32000 };
|
var output = { max_line_len: 32000 };
|
||||||
if (typeof options.inSourceMap == "string") {
|
|
||||||
inMap = JSON.parse(fs.readFileSync(options.inSourceMap, "utf8"));
|
|
||||||
}
|
|
||||||
if (options.outSourceMap || options.sourceMapInline) {
|
if (options.outSourceMap || options.sourceMapInline) {
|
||||||
output.source_map = UglifyJS.SourceMap({
|
output.source_map = UglifyJS.SourceMap({
|
||||||
// prefer outFileName, otherwise use outSourceMap without .map suffix
|
// prefer outFileName, otherwise use outSourceMap without .map suffix
|
||||||
|
|||||||
Reference in New Issue
Block a user