added --acorn and --spidermonkey options
This commit is contained in:
47
README.md
47
README.md
@@ -23,8 +23,9 @@ files.
|
|||||||
The available options are:
|
The available options are:
|
||||||
|
|
||||||
--source-map Specify an output file where to generate source map.
|
--source-map Specify an output file where to generate source map.
|
||||||
|
[string]
|
||||||
--source-map-root The path to the original source to be included in the
|
--source-map-root The path to the original source to be included in the
|
||||||
source map.
|
source map. [string]
|
||||||
--in-source-map Input source map, useful if you're compressing JS that was
|
--in-source-map Input source map, useful if you're compressing JS that was
|
||||||
generated from some other original code.
|
generated from some other original code.
|
||||||
-p, --prefix Skip prefix for original filenames that appear in source
|
-p, --prefix Skip prefix for original filenames that appear in source
|
||||||
@@ -49,12 +50,15 @@ The available options are:
|
|||||||
compression is on, because of dead code removal or
|
compression is on, because of dead code removal or
|
||||||
cascading statements into sequences. [string]
|
cascading statements into sequences. [string]
|
||||||
--stats Display operations run time on STDERR. [boolean]
|
--stats Display operations run time on STDERR. [boolean]
|
||||||
|
--acorn Use Acorn for parsing. [boolean]
|
||||||
|
--spidermonkey Assume input fles are SpiderMonkey AST format (as JSON).
|
||||||
|
[boolean]
|
||||||
-v, --verbose Verbose [boolean]
|
-v, --verbose Verbose [boolean]
|
||||||
|
|
||||||
Specify `--output` (`-o`) to declare the output file. Otherwise the output
|
Specify `--output` (`-o`) to declare the output file. Otherwise the output
|
||||||
goes to STDOUT.
|
goes to STDOUT.
|
||||||
|
|
||||||
### Source map options
|
## Source map options
|
||||||
|
|
||||||
UglifyJS2 can generate a source map file, which is highly useful for
|
UglifyJS2 can generate a source map file, which is highly useful for
|
||||||
debugging your compressed JavaScript. To get a source map, pass
|
debugging your compressed JavaScript. To get a source map, pass
|
||||||
@@ -83,7 +87,7 @@ mapping will refer to `http://foo.com/src/js/file1.js` and
|
|||||||
as the source map root, and the original files as `js/file1.js` and
|
as the source map root, and the original files as `js/file1.js` and
|
||||||
`js/file2.js`).
|
`js/file2.js`).
|
||||||
|
|
||||||
#### Composed source map
|
### Composed source map
|
||||||
|
|
||||||
When you're compressing JS code that was output by a compiler such as
|
When you're compressing JS code that was output by a compiler such as
|
||||||
CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd
|
CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd
|
||||||
@@ -98,7 +102,7 @@ To use this feature you need to pass `--in-source-map
|
|||||||
to the file containing the generated JS, so if that's correct you can omit
|
to the file containing the generated JS, so if that's correct you can omit
|
||||||
input files from the command line.
|
input files from the command line.
|
||||||
|
|
||||||
### Mangler options
|
## Mangler options
|
||||||
|
|
||||||
To enable the mangler you need to pass `--mangle` (`-m`). Optionally you
|
To enable the mangler you need to pass `--mangle` (`-m`). Optionally you
|
||||||
can pass `-m sort` (we'll possibly have other flags in the future) in order
|
can pass `-m sort` (we'll possibly have other flags in the future) in order
|
||||||
@@ -115,7 +119,7 @@ comma-separated list of names. For example:
|
|||||||
|
|
||||||
to prevent the `require`, `exports` and `$` names from being changed.
|
to prevent the `require`, `exports` and `$` names from being changed.
|
||||||
|
|
||||||
### Compressor options
|
## Compressor options
|
||||||
|
|
||||||
You need to pass `--compress` (`-c`) to enable the compressor. Optionally
|
You need to pass `--compress` (`-c`) to enable the compressor. Optionally
|
||||||
you can pass a comma-separated list of options. Options are in the form
|
you can pass a comma-separated list of options. Options are in the form
|
||||||
@@ -184,7 +188,7 @@ will evaluate references to them to the value itself and drop unreachable
|
|||||||
code as usual. The possible downside of this approach is that the build
|
code as usual. The possible downside of this approach is that the build
|
||||||
will contain the `const` declarations.
|
will contain the `const` declarations.
|
||||||
|
|
||||||
### Beautifier options
|
## Beautifier options
|
||||||
|
|
||||||
The code generator tries to output shortest code possible by default. In
|
The code generator tries to output shortest code possible by default. In
|
||||||
case you want beautified output, pass `--beautify` (`-b`). Optionally you
|
case you want beautified output, pass `--beautify` (`-b`). Optionally you
|
||||||
@@ -242,3 +246,34 @@ discarded by the compressor as not referenced.
|
|||||||
|
|
||||||
The safest comments where to place copyright information (or other info that
|
The safest comments where to place copyright information (or other info that
|
||||||
needs to me kept in the output) are comments attached to toplevel nodes.
|
needs to me kept in the output) are comments attached to toplevel nodes.
|
||||||
|
|
||||||
|
## Support for the SpiderMonkey AST
|
||||||
|
|
||||||
|
UglifyJS2 has its own abstract syntax tree format; for
|
||||||
|
[practical reasons](http://lisperator.net/blog/uglifyjs-why-not-switching-to-spidermonkey-ast/)
|
||||||
|
we can't easily change to using the SpiderMonkey AST internally. However,
|
||||||
|
UglifyJS now has a converter which can import a SpiderMonkey AST.
|
||||||
|
|
||||||
|
For example [Acorn](https://github.com/marijnh/acorn) is a super-fast parser
|
||||||
|
that produces a SpiderMonkey AST. It has a small CLI utility that parses
|
||||||
|
one file and dumps the AST in JSON on the standard output. To use UglifyJS
|
||||||
|
to mangle and compress that:
|
||||||
|
|
||||||
|
acorn file.js | uglifyjs2 --spidermonkey -m -c
|
||||||
|
|
||||||
|
The `--spidermonkey` option tells UglifyJS that all input files are not
|
||||||
|
JavaScript, but JS code described in SpiderMonkey AST in JSON. Therefore we
|
||||||
|
don't use our own parser in this case, but just transform that AST into our
|
||||||
|
internal AST.
|
||||||
|
|
||||||
|
### Use Acorn for parsing
|
||||||
|
|
||||||
|
More for fun, I added the `--acorn` option which will use Acorn to do all
|
||||||
|
the parsing. If you pass this option, UglifyJS will `require("acorn")`. At
|
||||||
|
the time I'm writing this it needs
|
||||||
|
[this commit](https://github.com/mishoo/acorn/commit/17c0d189c7f9ce5447293569036949b5d0a05fef)
|
||||||
|
in Acorn to support multiple input files and properly generate source maps.
|
||||||
|
|
||||||
|
Acorn is really fast (e.g. 250ms instead of 380ms on some 650K code), but
|
||||||
|
converting the SpiderMonkey tree that Acorn produces takes another 150ms so
|
||||||
|
in total it's a bit more than just using UglifyJS's own parser.
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ var UglifyJS = require("../tools/node");
|
|||||||
var sys = require("util");
|
var sys = require("util");
|
||||||
var optimist = require("optimist");
|
var optimist = require("optimist");
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
|
var acorn;
|
||||||
var ARGS = optimist
|
var ARGS = optimist
|
||||||
.usage("$0 input1.js [input2.js ...] [options]\n\
|
.usage("$0 input1.js [input2.js ...] [options]\n\
|
||||||
Use a single dash to read input from the standard input.\
|
Use a single dash to read input from the standard input.\
|
||||||
@@ -40,6 +41,8 @@ Note that currently not *all* comments can be kept when compression is on, \
|
|||||||
because of dead code removal or cascading statements into sequences.")
|
because of dead code removal or cascading statements into sequences.")
|
||||||
|
|
||||||
.describe("stats", "Display operations run time on STDERR.")
|
.describe("stats", "Display operations run time on STDERR.")
|
||||||
|
.describe("acorn", "Use Acorn for parsing.")
|
||||||
|
.describe("spidermonkey", "Assume input fles are SpiderMonkey AST format (as JSON).")
|
||||||
.describe("v", "Verbose")
|
.describe("v", "Verbose")
|
||||||
|
|
||||||
.alias("p", "prefix")
|
.alias("p", "prefix")
|
||||||
@@ -60,40 +63,25 @@ because of dead code removal or cascading statements into sequences.")
|
|||||||
.string("comments")
|
.string("comments")
|
||||||
.boolean("v")
|
.boolean("v")
|
||||||
.boolean("stats")
|
.boolean("stats")
|
||||||
|
.boolean("acorn")
|
||||||
|
.boolean("spidermonkey")
|
||||||
|
|
||||||
.wrap(80)
|
.wrap(80)
|
||||||
|
|
||||||
.argv
|
.argv
|
||||||
;
|
;
|
||||||
|
|
||||||
function normalize(o) {
|
|
||||||
for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) {
|
|
||||||
o[i.replace(/-/g, "_")] = o[i];
|
|
||||||
delete o[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
normalize(ARGS);
|
|
||||||
|
|
||||||
if (ARGS.h || ARGS.help) {
|
if (ARGS.h || ARGS.help) {
|
||||||
sys.puts(optimist.help());
|
sys.puts(optimist.help());
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOptions(x) {
|
if (ARGS.acorn) {
|
||||||
x = ARGS[x];
|
acorn = require("acorn");
|
||||||
if (!x) return null;
|
|
||||||
var ret = {};
|
|
||||||
if (x !== true) {
|
|
||||||
x.replace(/^\s+|\s+$/g).split(/\s*,+\s*/).forEach(function(opt){
|
|
||||||
var a = opt.split(/\s*[=:]\s*/);
|
|
||||||
ret[a[0]] = a.length > 1 ? new Function("return(" + a[1] + ")")() : true;
|
|
||||||
});
|
|
||||||
normalize(ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
normalize(ARGS);
|
||||||
|
|
||||||
var COMPRESS = getOptions("c");
|
var COMPRESS = getOptions("c");
|
||||||
var MANGLE = getOptions("m");
|
var MANGLE = getOptions("m");
|
||||||
var BEAUTIFY = getOptions("b");
|
var BEAUTIFY = getOptions("b");
|
||||||
@@ -190,13 +178,32 @@ files.forEach(function(file) {
|
|||||||
file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/");
|
file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/");
|
||||||
}
|
}
|
||||||
time_it("parse", function(){
|
time_it("parse", function(){
|
||||||
TOPLEVEL = UglifyJS.parse(code, {
|
if (ARGS.spidermonkey) {
|
||||||
filename: file,
|
var program = JSON.parse(code);
|
||||||
toplevel: TOPLEVEL
|
if (!TOPLEVEL) TOPLEVEL = program;
|
||||||
});
|
else TOPLEVEL.body = TOPLEVEL.body.concat(program.body);
|
||||||
|
}
|
||||||
|
else if (ARGS.acorn) {
|
||||||
|
TOPLEVEL = acorn.parse(code, {
|
||||||
|
locations : true,
|
||||||
|
trackComments : true,
|
||||||
|
sourceFile : file,
|
||||||
|
program : TOPLEVEL
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TOPLEVEL = UglifyJS.parse(code, {
|
||||||
|
filename: file,
|
||||||
|
toplevel: TOPLEVEL
|
||||||
|
});
|
||||||
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){
|
||||||
|
TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
|
||||||
|
});
|
||||||
|
|
||||||
var SCOPE_IS_NEEDED = COMPRESS || MANGLE;
|
var SCOPE_IS_NEEDED = COMPRESS || MANGLE;
|
||||||
|
|
||||||
if (SCOPE_IS_NEEDED) {
|
if (SCOPE_IS_NEEDED) {
|
||||||
@@ -256,6 +263,27 @@ if (ARGS.stats) {
|
|||||||
|
|
||||||
/* -----[ functions ]----- */
|
/* -----[ functions ]----- */
|
||||||
|
|
||||||
|
function normalize(o) {
|
||||||
|
for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) {
|
||||||
|
o[i.replace(/-/g, "_")] = o[i];
|
||||||
|
delete o[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOptions(x) {
|
||||||
|
x = ARGS[x];
|
||||||
|
if (!x) return null;
|
||||||
|
var ret = {};
|
||||||
|
if (x !== true) {
|
||||||
|
x.replace(/^\s+|\s+$/g).split(/\s*,+\s*/).forEach(function(opt){
|
||||||
|
var a = opt.split(/\s*[=:]\s*/);
|
||||||
|
ret[a[0]] = a.length > 1 ? new Function("return(" + a[1] + ")")() : true;
|
||||||
|
});
|
||||||
|
normalize(ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
function read_whole_file(filename) {
|
function read_whole_file(filename) {
|
||||||
if (filename == "-") {
|
if (filename == "-") {
|
||||||
// XXX: this sucks. How does one read the whole STDIN
|
// XXX: this sucks. How does one read the whole STDIN
|
||||||
@@ -279,4 +307,4 @@ function time_it(name, cont) {
|
|||||||
else STATS[name] = spent;
|
else STATS[name] = spent;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user