Compare commits
119 Commits
harmony-v2
...
v3.0.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43add9416b | ||
|
|
efcf167e5e | ||
|
|
6ed90913ca | ||
|
|
569c21e952 | ||
|
|
87c3a2c0ce | ||
|
|
baef8bf050 | ||
|
|
0813c5316f | ||
|
|
c88139492d | ||
|
|
cb45886512 | ||
|
|
050474ab44 | ||
|
|
f6c805ae1d | ||
|
|
9464d3c20f | ||
|
|
f18abd1b9c | ||
|
|
3be06ad085 | ||
|
|
265008c948 | ||
|
|
ff526be61d | ||
|
|
e005099fb1 | ||
|
|
504a436e9d | ||
|
|
3ca902258c | ||
|
|
fd0951231c | ||
|
|
9e29b6dad2 | ||
|
|
c391576d52 | ||
|
|
ac73c5d421 | ||
|
|
547f41beba | ||
|
|
daaefc17b9 | ||
|
|
1d407e761e | ||
|
|
2b44f4ae30 | ||
|
|
e51c3541da | ||
|
|
3bf194684b | ||
|
|
aae7d49d0c | ||
|
|
0459af2ecc | ||
|
|
04f2344efc | ||
|
|
bad9d5cf88 | ||
|
|
a0f5f862df | ||
|
|
41996be86f | ||
|
|
5fd8244a2e | ||
|
|
c14e280585 | ||
|
|
bc3fa78e8c | ||
|
|
8c7c107765 | ||
|
|
3dd328dce3 | ||
|
|
014f428153 | ||
|
|
a3b2eb75bd | ||
|
|
da295de82b | ||
|
|
4f8ca4626e | ||
|
|
e54748365c | ||
|
|
2d99d06601 | ||
|
|
98cf95e5b5 | ||
|
|
7313465cba | ||
|
|
2c7ee956fd | ||
|
|
ecf3563c45 | ||
|
|
dee5a27516 | ||
|
|
5a25d24b56 | ||
|
|
bffdc8dca8 | ||
|
|
69b5663653 | ||
|
|
ea9289771b | ||
|
|
2cb55b2ad0 | ||
|
|
bbb5f2a89c | ||
|
|
76d19b60ad | ||
|
|
9e62628171 | ||
|
|
9bf72cf758 | ||
|
|
64d74432f6 | ||
|
|
45ce369480 | ||
|
|
ca32a09032 | ||
|
|
6f954aa3d0 | ||
|
|
f05d4f7af3 | ||
|
|
88e7a542cd | ||
|
|
4dcff038cb | ||
|
|
b4b9305db0 | ||
|
|
28cfb65c47 | ||
|
|
0f4f01b66c | ||
|
|
5d9f1da3ab | ||
|
|
d1aa09c5c7 | ||
|
|
6d5f341999 | ||
|
|
4ffb6fce76 | ||
|
|
71a8d0d236 | ||
|
|
1a498db2d3 | ||
|
|
44dfa5a318 | ||
|
|
251ff1d1af | ||
|
|
ec443e422c | ||
|
|
32deb365d5 | ||
|
|
2244743545 | ||
|
|
04b8964505 | ||
|
|
d6fbc365e2 | ||
|
|
9a978843f5 | ||
|
|
0479ff0c54 | ||
|
|
cf72fe552f | ||
|
|
a1532eb076 | ||
|
|
c2a1bceb77 | ||
|
|
e3c9c22c75 | ||
|
|
0f4cd73dcc | ||
|
|
281e882d27 | ||
|
|
cc6aa3e5ac | ||
|
|
e869779a98 | ||
|
|
06cdb74279 | ||
|
|
ff289b90a9 | ||
|
|
9b6bc67c33 | ||
|
|
4b90dc1fdb | ||
|
|
951770fc68 | ||
|
|
48b3fe9952 | ||
|
|
a400741868 | ||
|
|
59a4e56bc8 | ||
|
|
1f1fccc45d | ||
|
|
b7f6b73f4e | ||
|
|
9469c03ac9 | ||
|
|
d57527697f | ||
|
|
f7ca4f2297 | ||
|
|
c076e7b60d | ||
|
|
4a55bb0be5 | ||
|
|
28ecea50a6 | ||
|
|
9a311705f5 | ||
|
|
ee3fe0f4cd | ||
|
|
87f6e1b091 | ||
|
|
c934fc8142 | ||
|
|
257ddc3bdb | ||
|
|
1ddc05725d | ||
|
|
e6b76a4879 | ||
|
|
a0c3836ba0 | ||
|
|
f8a71b56fd | ||
|
|
11e9bdc427 |
25
.github/ISSUE_TEMPLATE.md
vendored
25
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,9 +1,20 @@
|
||||
- Bug report or feature request? <!-- Note: sub-optimal but correct code is not a bug -->
|
||||
- `uglify-js` version (`uglifyjs -V`)
|
||||
- JavaScript input - ideally as small as possible.
|
||||
- The `uglifyjs` CLI command executed or `minify()` options used.
|
||||
- An example of JavaScript output produced and/or the error or warning.
|
||||
**Bug report or feature request?**
|
||||
|
||||
<!-- Note: sub-optimal but correct code is not a bug -->
|
||||
|
||||
**ES5 or ES6+ input?**
|
||||
|
||||
<!-- Note: for ES6 see: https://github.com/mishoo/UglifyJS2/tree/harmony#harmony -->
|
||||
|
||||
**Uglify version (`uglifyjs -V`)**
|
||||
|
||||
**JavaScript input** <!-- ideally as small as possible -->
|
||||
|
||||
**The `uglifyjs` CLI command executed or `minify()` options used.**
|
||||
|
||||
**JavaScript output or error produced.**
|
||||
|
||||
<!--
|
||||
Note: the release version of uglify-js only supports ES5. Those wishing
|
||||
to minify ES6 should use the experimental harmony branch.
|
||||
Note: `uglify-js` only supports ES5.
|
||||
Those wishing to minify ES6 should use `uglify-es`.
|
||||
-->
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
language: node_js
|
||||
before_install: "npm install -g npm"
|
||||
node_js:
|
||||
- "0.10"
|
||||
- "0.12"
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
#! /usr/bin/env node
|
||||
|
||||
"use strict";
|
||||
|
||||
var U2 = require("../tools/node");
|
||||
var fs = require("fs");
|
||||
var yargs = require("yargs");
|
||||
var ARGS = yargs
|
||||
.describe("o", "Output file")
|
||||
.argv;
|
||||
var files = ARGS._.slice();
|
||||
var output = {
|
||||
vars: {},
|
||||
props: {}
|
||||
};
|
||||
|
||||
if (ARGS.o) try {
|
||||
output = JSON.parse(fs.readFileSync(ARGS.o, "utf8"));
|
||||
} catch(ex) {}
|
||||
|
||||
files.forEach(getProps);
|
||||
|
||||
if (ARGS.o) {
|
||||
fs.writeFileSync(ARGS.o, JSON.stringify(output, null, 2), "utf8");
|
||||
} else {
|
||||
console.log("%s", JSON.stringify(output, null, 2));
|
||||
}
|
||||
|
||||
function getProps(filename) {
|
||||
var code = fs.readFileSync(filename, "utf8");
|
||||
var ast = U2.parse(code);
|
||||
|
||||
ast.walk(new U2.TreeWalker(function(node){
|
||||
if (node instanceof U2.AST_ObjectKeyVal) {
|
||||
add(node.key);
|
||||
}
|
||||
else if (node instanceof U2.AST_ObjectProperty) {
|
||||
add(node.key.name);
|
||||
}
|
||||
else if (node instanceof U2.AST_Dot) {
|
||||
add(node.property);
|
||||
}
|
||||
else if (node instanceof U2.AST_Sub) {
|
||||
addStrings(node.property);
|
||||
}
|
||||
}));
|
||||
|
||||
function addStrings(node) {
|
||||
var out = {};
|
||||
try {
|
||||
(function walk(node){
|
||||
node.walk(new U2.TreeWalker(function(node){
|
||||
if (node instanceof U2.AST_Seq) {
|
||||
walk(node.cdr);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof U2.AST_String) {
|
||||
add(node.value);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof U2.AST_Conditional) {
|
||||
walk(node.consequent);
|
||||
walk(node.alternative);
|
||||
return true;
|
||||
}
|
||||
throw out;
|
||||
}));
|
||||
})(node);
|
||||
} catch(ex) {
|
||||
if (ex !== out) throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
function add(name) {
|
||||
output.props[name] = true;
|
||||
}
|
||||
}
|
||||
939
bin/uglifyjs
939
bin/uglifyjs
@@ -3,633 +3,382 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var UglifyJS = require("../tools/node");
|
||||
var sys = require("util");
|
||||
var yargs = require("yargs");
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var acorn;
|
||||
var screw_ie8 = true;
|
||||
var ARGS = yargs
|
||||
.usage("$0 input1.js [input2.js ...] [options]\n\
|
||||
Use a single dash to read input from the standard input.\
|
||||
\n\n\
|
||||
NOTE: by default there is no mangling/compression.\n\
|
||||
Without [options] it will simply parse input files and dump the AST\n\
|
||||
with whitespace and comments discarded. To achieve compression and\n\
|
||||
mangling you need to use `-c` and `-m`.\
|
||||
")
|
||||
.describe("source-map", "Specify an output file where to generate source map.")
|
||||
.describe("source-map-root", "The path to the original source to be included in the source map.")
|
||||
.describe("source-map-url", "The path to the source map to be added in //# sourceMappingURL. Defaults to the value passed with --source-map.")
|
||||
.describe("source-map-inline", "Write base64-encoded source map to the end of js output. Disabled by default")
|
||||
.describe("source-map-include-sources", "Pass this flag if you want to include the content of source files in the source map as sourcesContent property.")
|
||||
.describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.")
|
||||
.describe("screw-ie8", "Do not support Internet Explorer 6/7/8. This flag is enabled by default.")
|
||||
.describe("support-ie8", "Support non-standard Internet Explorer 6/7/8 javascript.")
|
||||
.describe("expr", "Parse a single expression, rather than a program (for parsing JSON)")
|
||||
.describe("p", "Skip prefix for original filenames that appear in source maps. \
|
||||
For example -p 3 will drop 3 directories from file names and ensure they are relative paths. \
|
||||
You can also specify -p relative, which will make UglifyJS figure out itself the relative paths between original sources, \
|
||||
the source map and the output file.")
|
||||
.describe("o", "Output file (default STDOUT).")
|
||||
.describe("b", "Beautify output/specify output options.")
|
||||
.describe("m", "Mangle names/pass mangler options.")
|
||||
.describe("r", "Reserved names to exclude from mangling.")
|
||||
.describe("c", "Enable compressor/pass compressor options. \
|
||||
Pass options like -c hoist_vars=false,if_return=false. \
|
||||
Use -c with no argument to use the default compression options.")
|
||||
.describe("d", "Global definitions")
|
||||
.describe("e", "Embed everything in a big function, with a configurable parameter/argument list.")
|
||||
|
||||
.describe("comments", "Preserve copyright comments in the output. \
|
||||
By default this works like Google Closure, keeping JSDoc-style comments that contain \"@license\" or \"@preserve\". \
|
||||
You can optionally pass one of the following arguments to this flag:\n\
|
||||
- \"all\" to keep all comments\n\
|
||||
- a valid JS RegExp like `/foo/`or `/^!/` to keep only matching comments.\n\
|
||||
\
|
||||
Note that currently not *all* comments can be kept when compression is on, \
|
||||
because of dead code removal or cascading statements into sequences.")
|
||||
|
||||
.describe("preamble", "Preamble to prepend to the output. You can use this to insert a \
|
||||
comment, for example for licensing information. This will not be \
|
||||
parsed, but the source map will adjust for its presence.")
|
||||
|
||||
.describe("stats", "Display operations run time on STDERR.")
|
||||
.describe("acorn", "Use Acorn for parsing.")
|
||||
.describe("spidermonkey", "Assume input files are SpiderMonkey AST format (as JSON).")
|
||||
.describe("self", "Build itself (UglifyJS2) as a library (implies --wrap=UglifyJS --export-all)")
|
||||
.describe("wrap", "Embed everything in a big function, making the “exports” and “global” variables available. \
|
||||
You need to pass an argument to this option to specify the name that your module will take when included in, say, a browser.")
|
||||
.describe("export-all", "Only used when --wrap, this tells UglifyJS to add code to automatically export all globals.")
|
||||
.describe("lint", "Display some scope warnings")
|
||||
.describe("v", "Verbose")
|
||||
.describe("V", "Print version number and exit.")
|
||||
.describe("noerr", "Don't throw an error for unknown options in -c, -b or -m.")
|
||||
.describe("bare-returns", "Allow return outside of functions. Useful when minifying CommonJS modules.")
|
||||
.describe("keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.")
|
||||
.describe("quotes", "Quote style (0 - auto, 1 - single, 2 - double, 3 - original)")
|
||||
.describe("reserved-file", "File containing reserved names")
|
||||
.describe("reserve-domprops", "Make (most?) DOM properties reserved for --mangle-props")
|
||||
.describe("mangle-props", "Mangle property names (0 - disabled, 1 - mangle all properties, 2 - mangle unquoted properies)")
|
||||
.describe("mangle-regex", "Only mangle property names matching the regex")
|
||||
.describe("name-cache", "File to hold mangled names mappings")
|
||||
.describe("pure-funcs", "List of functions that can be safely removed if their return value is not used")
|
||||
.describe("dump-spidermonkey-ast", "Dump SpiderMonkey AST to stdout.")
|
||||
.describe("wrap-iife", "Wrap IIFEs in parenthesis. Note: this disables the negate_iife compression option")
|
||||
|
||||
.alias("p", "prefix")
|
||||
.alias("o", "output")
|
||||
.alias("v", "verbose")
|
||||
.alias("b", "beautify")
|
||||
.alias("m", "mangle")
|
||||
.alias("c", "compress")
|
||||
.alias("d", "define")
|
||||
.alias("r", "reserved")
|
||||
.alias("V", "version")
|
||||
.alias("e", "enclose")
|
||||
.alias("q", "quotes")
|
||||
|
||||
.string("source-map")
|
||||
.string("source-map-root")
|
||||
.string("source-map-url")
|
||||
.string("b")
|
||||
.string("beautify")
|
||||
.string("m")
|
||||
.string("mangle")
|
||||
.string("mangle-props-debug")
|
||||
.string("c")
|
||||
.string("compress")
|
||||
.string("d")
|
||||
.string("define")
|
||||
.string("e")
|
||||
.string("enclose")
|
||||
.string("comments")
|
||||
.string("wrap")
|
||||
.string("p")
|
||||
.string("prefix")
|
||||
.string("name-cache")
|
||||
|
||||
.array("reserved-file")
|
||||
.array("pure-funcs")
|
||||
|
||||
.boolean("expr")
|
||||
.boolean("source-map-inline")
|
||||
.boolean("source-map-include-sources")
|
||||
.boolean("screw-ie8")
|
||||
.boolean("support-ie8")
|
||||
.boolean("export-all")
|
||||
.boolean("self")
|
||||
.boolean("v")
|
||||
.boolean("verbose")
|
||||
.boolean("stats")
|
||||
.boolean("acorn")
|
||||
.boolean("spidermonkey")
|
||||
.boolean("dump-spidermonkey-ast")
|
||||
.boolean("lint")
|
||||
.boolean("V")
|
||||
.boolean("version")
|
||||
.boolean("noerr")
|
||||
.boolean("bare-returns")
|
||||
.boolean("keep-fnames")
|
||||
.boolean("reserve-domprops")
|
||||
.boolean("wrap-iife")
|
||||
|
||||
.wrap(80)
|
||||
|
||||
.argv
|
||||
;
|
||||
|
||||
normalize(ARGS);
|
||||
|
||||
if (ARGS.noerr) {
|
||||
UglifyJS.DefaultsError.croak = function(msg, defs) {
|
||||
print_error("WARN: " + msg);
|
||||
};
|
||||
}
|
||||
|
||||
if (ARGS.version || ARGS.V) {
|
||||
var json = require("../package.json");
|
||||
print(json.name + ' ' + json.version);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (ARGS.ast_help) {
|
||||
var desc = UglifyJS.describe_ast();
|
||||
print(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (ARGS.h || ARGS.help) {
|
||||
print(yargs.help());
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (ARGS.acorn) {
|
||||
acorn = require("acorn");
|
||||
}
|
||||
|
||||
var COMPRESS = getOptions("c", true);
|
||||
var MANGLE = getOptions("m", true);
|
||||
var BEAUTIFY = getOptions("b", true);
|
||||
var RESERVED = null;
|
||||
|
||||
if (ARGS.reserved_file) ARGS.reserved_file.forEach(function(filename){
|
||||
RESERVED = UglifyJS.readReservedFile(filename, RESERVED);
|
||||
// workaround for tty output truncation upon process.exit()
|
||||
[process.stdout, process.stderr].forEach(function(stream){
|
||||
if (stream._handle && stream._handle.setBlocking)
|
||||
stream._handle.setBlocking(true);
|
||||
});
|
||||
|
||||
if (ARGS.reserve_domprops) {
|
||||
RESERVED = UglifyJS.readDefaultReservedFile(RESERVED);
|
||||
}
|
||||
var fs = require("fs");
|
||||
var info = require("../package.json");
|
||||
var path = require("path");
|
||||
var program = require("commander");
|
||||
var UglifyJS = require("../tools/node");
|
||||
|
||||
if (ARGS.d) {
|
||||
if (COMPRESS) COMPRESS.global_defs = getOptions("d");
|
||||
}
|
||||
|
||||
if (ARGS.pure_funcs) {
|
||||
if (COMPRESS) COMPRESS.pure_funcs = ARGS.pure_funcs;
|
||||
}
|
||||
|
||||
if (ARGS.r) {
|
||||
if (MANGLE) MANGLE.except = ARGS.r.replace(/^\s+|\s+$/g).split(/\s*,+\s*/);
|
||||
}
|
||||
|
||||
if (RESERVED && MANGLE) {
|
||||
if (!MANGLE.except) MANGLE.except = RESERVED.vars;
|
||||
else MANGLE.except = MANGLE.except.concat(RESERVED.vars);
|
||||
}
|
||||
|
||||
function readNameCache(key) {
|
||||
return UglifyJS.readNameCache(ARGS.name_cache, key);
|
||||
}
|
||||
|
||||
function writeNameCache(key, cache) {
|
||||
return UglifyJS.writeNameCache(ARGS.name_cache, key, cache);
|
||||
}
|
||||
|
||||
function extractRegex(str) {
|
||||
if (/^\/.*\/[a-zA-Z]*$/.test(str)) {
|
||||
var regex_pos = str.lastIndexOf("/");
|
||||
return new RegExp(str.substr(1, regex_pos - 1), str.substr(regex_pos + 1));
|
||||
} else {
|
||||
throw new Error("Invalid regular expression: " + str);
|
||||
}
|
||||
}
|
||||
|
||||
if (ARGS.quotes === true) {
|
||||
ARGS.quotes = 3;
|
||||
}
|
||||
|
||||
if (ARGS.mangle_props === true) {
|
||||
ARGS.mangle_props = 1;
|
||||
} else if (ARGS.mangle_props === "unquoted") {
|
||||
ARGS.mangle_props = 2;
|
||||
}
|
||||
|
||||
var OUTPUT_OPTIONS = {
|
||||
beautify : BEAUTIFY ? true : false,
|
||||
max_line_len : 32000,
|
||||
preamble : ARGS.preamble || null,
|
||||
quote_style : ARGS.quotes != null ? ARGS.quotes : 0,
|
||||
var skip_keys = [ "cname", "enclosed", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ];
|
||||
var files = {};
|
||||
var options = {
|
||||
compress: false,
|
||||
mangle: false
|
||||
};
|
||||
|
||||
if (ARGS.mangle_props == 2) {
|
||||
OUTPUT_OPTIONS.keep_quoted_props = true;
|
||||
if (COMPRESS && !("properties" in COMPRESS))
|
||||
COMPRESS.properties = false;
|
||||
program.version(info.name + ' ' + info.version);
|
||||
program.parseArgv = program.parse;
|
||||
program.parse = undefined;
|
||||
program.option("-p, --parse <options>", "Specify parser options.", parse_js("parse", true));
|
||||
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js("compress", true));
|
||||
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js("mangle", true));
|
||||
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js("mangle-props", true));
|
||||
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js("beautify", true));
|
||||
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
||||
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
||||
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
||||
program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("define"));
|
||||
program.option("--ie8", "Support non-standard Internet Explorer 8.");
|
||||
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
|
||||
program.option("--name-cache <file>", "File to hold mangled name mappings.");
|
||||
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
|
||||
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_source_map());
|
||||
program.option("--stats", "Display operations run time on STDERR.")
|
||||
program.option("--toplevel", "Compress and/or mangle variables in toplevel scope.");
|
||||
program.option("--verbose", "Print diagnostic messages.");
|
||||
program.option("--warn", "Print warning messages.");
|
||||
program.option("--wrap <name>", "Embed everything as a function with “exports” corresponding to “name” globally.");
|
||||
program.arguments("[files...]").parseArgv(process.argv);
|
||||
if (program.configFile) {
|
||||
options = JSON.parse(read_file(program.configFile));
|
||||
}
|
||||
|
||||
if (ARGS.support_ie8 === true && ARGS.screw_ie8 !== true) {
|
||||
screw_ie8 = false;
|
||||
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
||||
fatal("ERROR: cannot write source map to STDOUT");
|
||||
}
|
||||
|
||||
if (COMPRESS) COMPRESS.screw_ie8 = screw_ie8;
|
||||
if (MANGLE) MANGLE.screw_ie8 = screw_ie8;
|
||||
OUTPUT_OPTIONS.screw_ie8 = screw_ie8;
|
||||
|
||||
if (ARGS.keep_fnames) {
|
||||
if (COMPRESS) COMPRESS.keep_fnames = true;
|
||||
if (MANGLE) MANGLE.keep_fnames = true;
|
||||
[
|
||||
"compress",
|
||||
"ie8",
|
||||
"mangle",
|
||||
"sourceMap",
|
||||
"toplevel",
|
||||
"wrap"
|
||||
].forEach(function(name) {
|
||||
if (name in program) {
|
||||
options[name] = program[name];
|
||||
}
|
||||
});
|
||||
if (program.beautify) {
|
||||
options.output = typeof program.beautify == "object" ? program.beautify : {};
|
||||
if (!("beautify" in options.output)) {
|
||||
options.output.beautify = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ARGS.wrap_iife) {
|
||||
if (COMPRESS) COMPRESS.negate_iife = false;
|
||||
OUTPUT_OPTIONS.wrap_iife = true;
|
||||
if (program.comments) {
|
||||
if (typeof options.output != "object") options.output = {};
|
||||
options.output.comments = typeof program.comments == "string" ? program.comments : "some";
|
||||
}
|
||||
|
||||
if (BEAUTIFY)
|
||||
UglifyJS.merge(OUTPUT_OPTIONS, BEAUTIFY);
|
||||
|
||||
if (ARGS.comments === "") {
|
||||
OUTPUT_OPTIONS.comments = "some";
|
||||
if (program.define) {
|
||||
if (typeof options.compress != "object") options.compress = {};
|
||||
if (typeof options.compress.global_defs != "object") options.compress.global_defs = {};
|
||||
for (var expr in program.define) {
|
||||
options.compress.global_defs[expr] = program.define[expr];
|
||||
}
|
||||
}
|
||||
if (program.keepFnames) {
|
||||
options.keep_fnames = true;
|
||||
}
|
||||
if (program.mangleProps) {
|
||||
if (program.mangleProps.domprops) {
|
||||
delete program.mangleProps.domprops;
|
||||
} else {
|
||||
if (typeof program.mangleProps != "object") program.mangleProps = {};
|
||||
if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
|
||||
require("../tools/domprops").forEach(function(name) {
|
||||
UglifyJS._push_uniq(program.mangleProps.reserved, name);
|
||||
});
|
||||
}
|
||||
if (typeof options.mangle != "object") options.mangle = {};
|
||||
options.mangle.properties = program.mangleProps;
|
||||
}
|
||||
var cache;
|
||||
if (program.nameCache) {
|
||||
cache = JSON.parse(read_file(program.nameCache, "{}"));
|
||||
if (options.mangle) {
|
||||
if (typeof options.mangle != "object") options.mangle = {};
|
||||
options.mangle.cache = to_cache("vars");
|
||||
if (options.mangle.properties) {
|
||||
if (typeof options.mangle.properties != "object") options.mangle.properties = {};
|
||||
options.mangle.properties.cache = to_cache("props");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (program.output == "ast") {
|
||||
options.output = {
|
||||
ast: true,
|
||||
code: false
|
||||
};
|
||||
}
|
||||
if (program.parse) {
|
||||
if (program.parse.acorn || program.parse.spidermonkey) {
|
||||
if (program.sourceMap) fatal("ERROR: inline source map only works with built-in parser");
|
||||
} else {
|
||||
options.parse = program.parse;
|
||||
}
|
||||
}
|
||||
var convert_path = function(name) {
|
||||
return name;
|
||||
};
|
||||
if (typeof program.sourceMap == "object" && "base" in program.sourceMap) {
|
||||
convert_path = function() {
|
||||
var base = program.sourceMap.base;
|
||||
delete options.sourceMap.base;
|
||||
return function(name) {
|
||||
return path.relative(base, name);
|
||||
};
|
||||
}();
|
||||
}
|
||||
if (program.verbose) {
|
||||
options.warnings = "verbose";
|
||||
} else if (program.warn) {
|
||||
options.warnings = true;
|
||||
}
|
||||
if (program.self) {
|
||||
if (program.args.length) {
|
||||
console.error("WARN: Ignoring input files since --self was passed");
|
||||
}
|
||||
if (!options.wrap) options.wrap = "UglifyJS";
|
||||
simple_glob(UglifyJS.FILES).forEach(function(name) {
|
||||
files[convert_path(name)] = read_file(name);
|
||||
});
|
||||
run();
|
||||
} else if (program.args.length) {
|
||||
simple_glob(program.args).forEach(function(name) {
|
||||
files[convert_path(name)] = read_file(name);
|
||||
});
|
||||
run();
|
||||
} else {
|
||||
OUTPUT_OPTIONS.comments = ARGS.comments;
|
||||
var chunks = [];
|
||||
process.stdin.setEncoding("utf8");
|
||||
process.stdin.on("data", function(chunk) {
|
||||
chunks.push(chunk);
|
||||
}).on("end", function() {
|
||||
files = [ chunks.join("") ];
|
||||
run();
|
||||
});
|
||||
process.stdin.resume();
|
||||
}
|
||||
|
||||
var files = ARGS._.slice();
|
||||
|
||||
if (process.platform === "win32")
|
||||
files = UglifyJS.simple_glob(files);
|
||||
|
||||
if (ARGS.self) {
|
||||
if (files.length > 0) {
|
||||
print_error("WARN: Ignoring input files since --self was passed");
|
||||
}
|
||||
files = UglifyJS.FILES;
|
||||
if (!ARGS.wrap) ARGS.wrap = "UglifyJS";
|
||||
function convert_ast(fn) {
|
||||
return UglifyJS.AST_Node.from_mozilla_ast(Object.keys(files).reduce(fn, null));
|
||||
}
|
||||
|
||||
var ORIG_MAP = ARGS.in_source_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 (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);
|
||||
}
|
||||
|
||||
if (files.filter(function(el){ return el == "-" }).length > 1) {
|
||||
print_error("ERROR: Can read a single file from STDIN (two or more dashes specified)");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var STATS = {};
|
||||
var TOPLEVEL = null;
|
||||
var P_RELATIVE = ARGS.p && ARGS.p == "relative";
|
||||
var SOURCES_CONTENT = {};
|
||||
var index = 0;
|
||||
|
||||
!function cb() {
|
||||
if (index == files.length) return done();
|
||||
var file = files[index++];
|
||||
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, '/');
|
||||
} else {
|
||||
var p = parseInt(ARGS.p, 10);
|
||||
if (!isNaN(p)) {
|
||||
file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/");
|
||||
}
|
||||
}
|
||||
}
|
||||
SOURCES_CONTENT[file] = code;
|
||||
time_it("parse", function(){
|
||||
if (ARGS.spidermonkey) {
|
||||
var program = JSON.parse(code);
|
||||
if (!TOPLEVEL) TOPLEVEL = program;
|
||||
else TOPLEVEL.body = TOPLEVEL.body.concat(program.body);
|
||||
}
|
||||
else if (ARGS.acorn) {
|
||||
TOPLEVEL = acorn.parse(code, {
|
||||
locations : true,
|
||||
sourceFile : file,
|
||||
program : TOPLEVEL
|
||||
function run() {
|
||||
UglifyJS.AST_Node.warn_function = function(msg) {
|
||||
console.error("WARN:", msg);
|
||||
};
|
||||
if (program.stats) program.stats = Date.now();
|
||||
try {
|
||||
if (program.parse) {
|
||||
if (program.parse.acorn) {
|
||||
files = convert_ast(function(toplevel, name) {
|
||||
return require("acorn").parse(files[name], {
|
||||
locations: true,
|
||||
program: toplevel,
|
||||
sourceFile: name
|
||||
});
|
||||
});
|
||||
} else if (program.parse.spidermonkey) {
|
||||
files = convert_ast(function(toplevel, name) {
|
||||
var obj = JSON.parse(files[name]);
|
||||
if (!toplevel) return obj;
|
||||
toplevel.body = toplevel.body.concat(obj.body);
|
||||
return toplevel;
|
||||
});
|
||||
}
|
||||
else {
|
||||
try {
|
||||
TOPLEVEL = UglifyJS.parse(code, {
|
||||
filename : file,
|
||||
toplevel : TOPLEVEL,
|
||||
expression : ARGS.expr,
|
||||
bare_returns : ARGS.bare_returns,
|
||||
});
|
||||
} catch(ex) {
|
||||
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
||||
print_error("Parse error at " + file + ":" + ex.line + "," + ex.col);
|
||||
var col = ex.col;
|
||||
var line = code.split(/\r?\n/)[ex.line - (col ? 1 : 2)];
|
||||
if (line) {
|
||||
if (col > 40) {
|
||||
line = line.slice(col - 40);
|
||||
col = 40;
|
||||
}
|
||||
if (col) {
|
||||
print_error(line.slice(0, 80));
|
||||
print_error(line.slice(0, col).replace(/\S/g, " ") + "^");
|
||||
} else {
|
||||
print_error(line.slice(-40));
|
||||
print_error(line.slice(-40).replace(/\S/g, " ") + "^");
|
||||
}
|
||||
}
|
||||
print_error(ex.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
} catch (ex) {
|
||||
fatal(ex);
|
||||
}
|
||||
var result = UglifyJS.minify(files, options);
|
||||
if (result.error) {
|
||||
var ex = result.error;
|
||||
if (ex.name == "SyntaxError") {
|
||||
console.error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
|
||||
var col = ex.col;
|
||||
var lines = files[ex.filename].split(/\r?\n/);
|
||||
var line = lines[ex.line - 1];
|
||||
if (!line && !col) {
|
||||
line = lines[ex.line - 2];
|
||||
col = line.length;
|
||||
}
|
||||
if (line) {
|
||||
if (col > 40) {
|
||||
line = line.slice(col - 40);
|
||||
col = 40;
|
||||
}
|
||||
};
|
||||
});
|
||||
cb();
|
||||
});
|
||||
}();
|
||||
console.error(line.slice(0, 80));
|
||||
console.error(line.slice(0, col).replace(/\S/g, " ") + "^");
|
||||
}
|
||||
}
|
||||
if (ex.defs) {
|
||||
console.error("Supported options:");
|
||||
console.error(ex.defs);
|
||||
}
|
||||
fatal(ex);
|
||||
} else if (program.output == "ast") {
|
||||
console.log(JSON.stringify(result.ast, function(key, value) {
|
||||
if (skip_key(key)) return;
|
||||
if (value instanceof UglifyJS.AST_Token) return;
|
||||
if (value instanceof UglifyJS.Dictionary) return;
|
||||
if (value instanceof UglifyJS.AST_Node) {
|
||||
var result = {
|
||||
_class: "AST_" + value.TYPE
|
||||
};
|
||||
value.CTOR.PROPS.forEach(function(prop) {
|
||||
result[prop] = value[prop];
|
||||
});
|
||||
return result;
|
||||
}
|
||||
return value;
|
||||
}, 2));
|
||||
} else if (program.output == "spidermonkey") {
|
||||
console.log(JSON.stringify(UglifyJS.minify(result.code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ast: true,
|
||||
code: false
|
||||
}
|
||||
}).ast.to_mozilla_ast(), null, 2));
|
||||
} else if (program.output) {
|
||||
fs.writeFileSync(program.output, result.code);
|
||||
if (result.map) {
|
||||
fs.writeFileSync(program.output + ".map", result.map);
|
||||
}
|
||||
} else {
|
||||
console.log(result.code);
|
||||
}
|
||||
if (program.nameCache) {
|
||||
fs.writeFileSync(program.nameCache, JSON.stringify(cache, function(key, value) {
|
||||
return value instanceof UglifyJS.Dictionary ? value.toObject() : value;
|
||||
}));
|
||||
}
|
||||
if (program.stats) console.error("Elapsed:", Date.now() - program.stats);
|
||||
}
|
||||
|
||||
function done() {
|
||||
var OUTPUT_FILE = ARGS.o;
|
||||
function fatal(message) {
|
||||
if (message instanceof Error) message = message.stack.replace(/^\S*?Error:/, "ERROR:")
|
||||
console.error(message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
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;
|
||||
// A file glob function that only supports "*" and "?" wildcards in the basename.
|
||||
// Example: "foo/bar/*baz??.*.js"
|
||||
// Argument `glob` may be a string or an array of strings.
|
||||
// Returns an array of strings. Garbage in, garbage out.
|
||||
function simple_glob(glob) {
|
||||
if (Array.isArray(glob)) {
|
||||
return [].concat.apply([], glob.map(simple_glob));
|
||||
}
|
||||
if (glob.match(/\*|\?/)) {
|
||||
var dir = path.dirname(glob);
|
||||
try {
|
||||
var entries = fs.readdirSync(dir);
|
||||
} catch (ex) {}
|
||||
if (entries) {
|
||||
var pattern = "^" + path.basename(glob)
|
||||
.replace(/[.+^$[\]\\(){}]/g, "\\$&")
|
||||
.replace(/\*/g, "[^/\\\\]*")
|
||||
.replace(/\?/g, "[^/\\\\]") + "$";
|
||||
var mod = process.platform === "win32" ? "i" : "";
|
||||
var rx = new RegExp(pattern, mod);
|
||||
var results = entries.filter(function(name) {
|
||||
return rx.test(name);
|
||||
}).map(function(name) {
|
||||
return path.join(dir, name);
|
||||
});
|
||||
if (results.length) return results;
|
||||
}
|
||||
}
|
||||
return [ glob ];
|
||||
}
|
||||
|
||||
function read_file(path, default_value) {
|
||||
try {
|
||||
var output = UglifyJS.OutputStream(OUTPUT_OPTIONS);
|
||||
var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
|
||||
} catch(ex) {
|
||||
if (ex instanceof UglifyJS.DefaultsError) {
|
||||
print_error(ex.message);
|
||||
print_error("Supported options:");
|
||||
print_error(sys.inspect(ex.defs));
|
||||
process.exit(1);
|
||||
}
|
||||
return fs.readFileSync(path, "utf8");
|
||||
} catch (ex) {
|
||||
if (ex.code == "ENOENT" && default_value != null) return default_value;
|
||||
fatal(ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){
|
||||
TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
|
||||
});
|
||||
|
||||
if (ARGS.wrap != null) {
|
||||
TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all);
|
||||
}
|
||||
|
||||
if (ARGS.enclose != null) {
|
||||
var arg_parameter_list = ARGS.enclose;
|
||||
if (arg_parameter_list === true) {
|
||||
arg_parameter_list = [];
|
||||
}
|
||||
else if (!(arg_parameter_list instanceof Array)) {
|
||||
arg_parameter_list = [arg_parameter_list];
|
||||
}
|
||||
TOPLEVEL = TOPLEVEL.wrap_enclose(arg_parameter_list);
|
||||
}
|
||||
|
||||
if (ARGS.mangle_props || ARGS.name_cache) (function(){
|
||||
var reserved = RESERVED ? RESERVED.props : null;
|
||||
var cache = readNameCache("props");
|
||||
var regex;
|
||||
|
||||
function parse_js(flag, constants) {
|
||||
return function(value, options) {
|
||||
options = options || {};
|
||||
try {
|
||||
regex = ARGS.mangle_regex ? extractRegex(ARGS.mangle_regex) : null;
|
||||
} catch (e) {
|
||||
print_error("ERROR: Invalid --mangle-regex: " + e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
UglifyJS.minify(value, {
|
||||
parse: {
|
||||
expression: true
|
||||
},
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ast: true,
|
||||
code: false
|
||||
}
|
||||
}).ast.walk(new UglifyJS.TreeWalker(function(node) {
|
||||
if (node instanceof UglifyJS.AST_Assign) {
|
||||
var name = node.left.print_to_string();
|
||||
var value = node.right;
|
||||
if (!constants) {
|
||||
options[name] = value;
|
||||
} else if (value instanceof UglifyJS.AST_Array) {
|
||||
options[name] = value.elements.map(to_string);
|
||||
} else {
|
||||
options[name] = to_string(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_PropAccess) {
|
||||
var name = node.print_to_string();
|
||||
options[name] = true;
|
||||
return true;
|
||||
}
|
||||
if (!(node instanceof UglifyJS.AST_Sequence)) throw node;
|
||||
|
||||
TOPLEVEL = UglifyJS.mangle_properties(TOPLEVEL, {
|
||||
reserved : reserved,
|
||||
cache : cache,
|
||||
only_cache : !ARGS.mangle_props,
|
||||
regex : regex,
|
||||
ignore_quoted : ARGS.mangle_props == 2,
|
||||
debug : typeof ARGS.mangle_props_debug === "undefined" ? false : ARGS.mangle_props_debug
|
||||
});
|
||||
writeNameCache("props", cache);
|
||||
})();
|
||||
|
||||
var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint
|
||||
var TL_CACHE = readNameCache("vars");
|
||||
if (MANGLE) MANGLE.cache = TL_CACHE;
|
||||
|
||||
if (SCOPE_IS_NEEDED) {
|
||||
time_it("scope", function(){
|
||||
TOPLEVEL.figure_out_scope(MANGLE || { screw_ie8: screw_ie8, cache: TL_CACHE });
|
||||
if (ARGS.lint) {
|
||||
TOPLEVEL.scope_warnings();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (COMPRESS) {
|
||||
time_it("squeeze", function(){
|
||||
TOPLEVEL = compressor.compress(TOPLEVEL);
|
||||
});
|
||||
}
|
||||
|
||||
if (SCOPE_IS_NEEDED) {
|
||||
time_it("scope", function(){
|
||||
TOPLEVEL.figure_out_scope(MANGLE || { screw_ie8: screw_ie8, cache: TL_CACHE });
|
||||
if (MANGLE && !TL_CACHE) {
|
||||
TOPLEVEL.compute_char_frequency(MANGLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (MANGLE) time_it("mangle", function(){
|
||||
TOPLEVEL.mangle_names(MANGLE);
|
||||
});
|
||||
|
||||
writeNameCache("vars", TL_CACHE);
|
||||
|
||||
if (ARGS.source_map_include_sources) {
|
||||
for (var file in SOURCES_CONTENT) {
|
||||
if (SOURCES_CONTENT.hasOwnProperty(file)) {
|
||||
SOURCE_MAP.get().setSourceContent(file, SOURCES_CONTENT[file]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ARGS.dump_spidermonkey_ast) {
|
||||
print(JSON.stringify(TOPLEVEL.to_mozilla_ast(), null, 2));
|
||||
} else {
|
||||
time_it("generate", function(){
|
||||
TOPLEVEL.print(output);
|
||||
});
|
||||
|
||||
output = output.get();
|
||||
|
||||
if (SOURCE_MAP) {
|
||||
if (ARGS.source_map_inline) {
|
||||
var base64_string = new Buffer(SOURCE_MAP.toString()).toString('base64');
|
||||
output += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + base64_string;
|
||||
} else {
|
||||
fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
|
||||
var source_map_url = ARGS.source_map_url || (
|
||||
P_RELATIVE
|
||||
? path.relative(path.dirname(OUTPUT_FILE), ARGS.source_map)
|
||||
: ARGS.source_map
|
||||
);
|
||||
output += "\n//# sourceMappingURL=" + source_map_url;
|
||||
}
|
||||
}
|
||||
|
||||
if (OUTPUT_FILE) {
|
||||
fs.writeFileSync(OUTPUT_FILE, output, "utf8");
|
||||
} else {
|
||||
print(output);
|
||||
}
|
||||
}
|
||||
|
||||
if (ARGS.stats) {
|
||||
print_error(UglifyJS.string_template("Timing information (compressed {count} files):", {
|
||||
count: files.length
|
||||
}));
|
||||
for (var i in STATS) if (STATS.hasOwnProperty(i)) {
|
||||
print_error(UglifyJS.string_template("- {name}: {time}s", {
|
||||
name: i,
|
||||
time: (STATS[i] / 1000).toFixed(3)
|
||||
function to_string(value) {
|
||||
return value instanceof UglifyJS.AST_Constant ? value.getValue() : value.print_to_string({
|
||||
quote_keys: true
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----[ 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(flag, constants) {
|
||||
var x = ARGS[flag];
|
||||
if (x == null || x === false) return null;
|
||||
var ret = {};
|
||||
if (x !== "") {
|
||||
if (Array.isArray(x)) x = x.map(function (v) { return "(" + v + ")"; }).join(", ");
|
||||
|
||||
var ast;
|
||||
try {
|
||||
ast = UglifyJS.parse(x, { cli: true, expression: true });
|
||||
} catch(ex) {
|
||||
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
||||
print_error("Error parsing arguments for flag `" + flag + "': " + x);
|
||||
process.exit(1);
|
||||
}
|
||||
fatal("Error parsing arguments for '" + flag + "': " + value);
|
||||
}
|
||||
ast.walk(new UglifyJS.TreeWalker(function(node){
|
||||
if (node instanceof UglifyJS.AST_Seq) return; // descend
|
||||
if (node instanceof UglifyJS.AST_Assign) {
|
||||
var name = node.left.print_to_string().replace(/-/g, "_");
|
||||
var value = node.right;
|
||||
if (constants)
|
||||
value = new Function("return (" + value.print_to_string() + ")")();
|
||||
ret[name] = value;
|
||||
return true; // no descend
|
||||
}
|
||||
if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_Binary) {
|
||||
var name = node.print_to_string().replace(/-/g, "_");
|
||||
ret[name] = true;
|
||||
return true; // no descend
|
||||
}
|
||||
print_error(node.TYPE)
|
||||
print_error("Error parsing arguments for flag `" + flag + "': " + x);
|
||||
process.exit(1);
|
||||
}));
|
||||
return options;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function read_whole_file(filename, cb) {
|
||||
if (filename == "-") {
|
||||
var chunks = [];
|
||||
process.stdin.setEncoding('utf-8');
|
||||
process.stdin.on('data', function (chunk) {
|
||||
chunks.push(chunk);
|
||||
}).on('end', function () {
|
||||
cb(null, chunks.join(""));
|
||||
});
|
||||
process.openStdin();
|
||||
function parse_source_map() {
|
||||
var parse = parse_js("sourceMap", true);
|
||||
return function(value, options) {
|
||||
var hasContent = options && options.sourceMap && "content" in options.sourceMap;
|
||||
var settings = parse(value, options);
|
||||
if (!hasContent && settings.content && settings.content != "inline") {
|
||||
console.error("INFO: Using input source map:", settings.content);
|
||||
settings.content = read_file(settings.content, settings.content);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
|
||||
function to_cache(key) {
|
||||
if (cache[key]) {
|
||||
cache[key].props = UglifyJS.Dictionary.fromObject(cache[key].props);
|
||||
} else {
|
||||
fs.readFile(filename, "utf-8", cb);
|
||||
cache[key] = {
|
||||
cname: -1,
|
||||
props: new UglifyJS.Dictionary()
|
||||
};
|
||||
}
|
||||
return cache[key];
|
||||
}
|
||||
|
||||
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();
|
||||
if (ARGS.stats) {
|
||||
var spent = new Date().getTime() - t1;
|
||||
if (STATS[name]) STATS[name] += spent;
|
||||
else STATS[name] = spent;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function print_error(msg) {
|
||||
console.error("%s", msg);
|
||||
}
|
||||
|
||||
function print(txt) {
|
||||
console.log("%s", txt);
|
||||
function skip_key(key) {
|
||||
return skip_keys.indexOf(key) >= 0;
|
||||
}
|
||||
|
||||
176
lib/ast.js
176
lib/ast.js
@@ -182,21 +182,13 @@ var AST_BlockStatement = DEFNODE("BlockStatement", null, {
|
||||
}, AST_Block);
|
||||
|
||||
var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
|
||||
$documentation: "The empty statement (empty block or simply a semicolon)",
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this);
|
||||
}
|
||||
$documentation: "The empty statement (empty block or simply a semicolon)"
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", {
|
||||
$documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
|
||||
$propdoc: {
|
||||
body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.body._walk(visitor);
|
||||
});
|
||||
}
|
||||
}, AST_Statement);
|
||||
|
||||
@@ -214,12 +206,13 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
|
||||
clone: function(deep) {
|
||||
var node = this._clone(deep);
|
||||
if (deep) {
|
||||
var refs = node.label.references;
|
||||
var label = this.label;
|
||||
var label = node.label;
|
||||
var def = this.label;
|
||||
node.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_LoopControl
|
||||
&& node.label && node.label.thedef === label) {
|
||||
refs.push(node);
|
||||
&& node.label && node.label.thedef === def) {
|
||||
node.label.thedef = label;
|
||||
label.references.push(node);
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -325,62 +318,13 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||
$propdoc: {
|
||||
globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
|
||||
},
|
||||
wrap_enclose: function(arg_parameter_pairs) {
|
||||
var self = this;
|
||||
var args = [];
|
||||
var parameters = [];
|
||||
|
||||
arg_parameter_pairs.forEach(function(pair) {
|
||||
var splitAt = pair.lastIndexOf(":");
|
||||
|
||||
args.push(pair.substr(0, splitAt));
|
||||
parameters.push(pair.substr(splitAt + 1));
|
||||
});
|
||||
|
||||
var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";
|
||||
wrap_commonjs: function(name) {
|
||||
var body = this.body;
|
||||
var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
|
||||
wrapped_tl = parse(wrapped_tl);
|
||||
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
|
||||
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
||||
return MAP.splice(self.body);
|
||||
}
|
||||
}));
|
||||
return wrapped_tl;
|
||||
},
|
||||
wrap_commonjs: function(name, export_all) {
|
||||
var self = this;
|
||||
var to_export = [];
|
||||
if (export_all) {
|
||||
self.figure_out_scope();
|
||||
self.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_SymbolDeclaration && node.definition().global) {
|
||||
if (!find_if(function(n){ return n.name == node.name }, to_export))
|
||||
to_export.push(node);
|
||||
}
|
||||
}));
|
||||
}
|
||||
var wrapped_tl = "(function(exports, global){ '$ORIG'; '$EXPORTS'; global['" + name + "'] = exports; }({}, (function(){return this}())))";
|
||||
wrapped_tl = parse(wrapped_tl);
|
||||
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
|
||||
if (node instanceof AST_Directive) {
|
||||
switch (node.value) {
|
||||
case "$ORIG":
|
||||
return MAP.splice(self.body);
|
||||
case "$EXPORTS":
|
||||
var body = [];
|
||||
to_export.forEach(function(sym){
|
||||
body.push(new AST_SimpleStatement({
|
||||
body: new AST_Assign({
|
||||
left: new AST_Sub({
|
||||
expression: new AST_SymbolRef({ name: "exports" }),
|
||||
property: new AST_String({ value: sym.name }),
|
||||
}),
|
||||
operator: "=",
|
||||
right: new AST_SymbolRef(sym),
|
||||
}),
|
||||
}));
|
||||
});
|
||||
return MAP.splice(body);
|
||||
}
|
||||
return MAP.splice(body);
|
||||
}
|
||||
}));
|
||||
return wrapped_tl;
|
||||
@@ -551,10 +495,10 @@ var AST_Finally = DEFNODE("Finally", null, {
|
||||
$documentation: "A `finally` node; only makes sense as part of a `try` statement"
|
||||
}, AST_Block);
|
||||
|
||||
/* -----[ VAR/CONST ]----- */
|
||||
/* -----[ VAR ]----- */
|
||||
|
||||
var AST_Definitions = DEFNODE("Definitions", "definitions", {
|
||||
$documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
|
||||
$documentation: "Base class for `var` nodes (variable declarations/initializations)",
|
||||
$propdoc: {
|
||||
definitions: "[AST_VarDef*] array of variable definitions"
|
||||
},
|
||||
@@ -572,14 +516,10 @@ var AST_Var = DEFNODE("Var", null, {
|
||||
$documentation: "A `var` statement"
|
||||
}, AST_Definitions);
|
||||
|
||||
var AST_Const = DEFNODE("Const", null, {
|
||||
$documentation: "A `const` statement"
|
||||
}, AST_Definitions);
|
||||
|
||||
var AST_VarDef = DEFNODE("VarDef", "name value", {
|
||||
$documentation: "A variable declaration; only appears in a AST_Definitions node",
|
||||
$propdoc: {
|
||||
name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
|
||||
name: "[AST_SymbolVar] name of the variable",
|
||||
value: "[AST_Node?] initializer, or null of there's no initializer"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
@@ -600,11 +540,11 @@ var AST_Call = DEFNODE("Call", "expression args", {
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.expression._walk(visitor);
|
||||
var args = this.args;
|
||||
for (var i = 0, len = args.length; i < len; i++) {
|
||||
args[i]._walk(visitor);
|
||||
}
|
||||
this.expression._walk(visitor);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -613,68 +553,16 @@ var AST_New = DEFNODE("New", null, {
|
||||
$documentation: "An object instantiation. Derives from a function call since it has exactly the same properties"
|
||||
}, AST_Call);
|
||||
|
||||
var AST_Seq = DEFNODE("Seq", "car cdr", {
|
||||
$documentation: "A sequence expression (two comma-separated expressions)",
|
||||
var AST_Sequence = DEFNODE("Sequence", "expressions", {
|
||||
$documentation: "A sequence expression (comma-separated expressions)",
|
||||
$propdoc: {
|
||||
car: "[AST_Node] first element in sequence",
|
||||
cdr: "[AST_Node] second element in sequence"
|
||||
},
|
||||
$cons: function(x, y) {
|
||||
var seq = new AST_Seq(x);
|
||||
seq.car = x;
|
||||
seq.cdr = y;
|
||||
return seq;
|
||||
},
|
||||
$from_array: function(array) {
|
||||
if (array.length == 0) return null;
|
||||
if (array.length == 1) return array[0].clone();
|
||||
var list = null;
|
||||
for (var i = array.length; --i >= 0;) {
|
||||
list = AST_Seq.cons(array[i], list);
|
||||
}
|
||||
var p = list;
|
||||
while (p) {
|
||||
if (p.cdr && !p.cdr.cdr) {
|
||||
p.cdr = p.cdr.car;
|
||||
break;
|
||||
}
|
||||
p = p.cdr;
|
||||
}
|
||||
return list;
|
||||
},
|
||||
to_array: function() {
|
||||
var p = this, a = [];
|
||||
while (p) {
|
||||
a.push(p.car);
|
||||
if (p.cdr && !(p.cdr instanceof AST_Seq)) {
|
||||
a.push(p.cdr);
|
||||
break;
|
||||
}
|
||||
p = p.cdr;
|
||||
}
|
||||
return a;
|
||||
},
|
||||
add: function(node) {
|
||||
var p = this;
|
||||
while (p) {
|
||||
if (!(p.cdr instanceof AST_Seq)) {
|
||||
var cell = AST_Seq.cons(p.cdr, node);
|
||||
return p.cdr = cell;
|
||||
}
|
||||
p = p.cdr;
|
||||
}
|
||||
},
|
||||
len: function() {
|
||||
if (this.cdr instanceof AST_Seq) {
|
||||
return this.cdr.len() + 1;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
expressions: "[AST_Node*] array of expressions (at least two)"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.car._walk(visitor);
|
||||
if (this.cdr) this.cdr._walk(visitor);
|
||||
this.expressions.forEach(function(node) {
|
||||
node._walk(visitor);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -727,7 +615,7 @@ var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
|
||||
$documentation: "Unary postfix expression, i.e. `i++`"
|
||||
}, AST_Unary);
|
||||
|
||||
var AST_Binary = DEFNODE("Binary", "left operator right", {
|
||||
var AST_Binary = DEFNODE("Binary", "operator left right", {
|
||||
$documentation: "Binary expression, i.e. `a + b`",
|
||||
$propdoc: {
|
||||
left: "[AST_Node] left-hand side expression",
|
||||
@@ -797,8 +685,8 @@ var AST_Object = DEFNODE("Object", "properties", {
|
||||
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
|
||||
$documentation: "Base class for literal object properties",
|
||||
$propdoc: {
|
||||
key: "[string] the property name converted to a string for ObjectKeyVal. For setters and getters this is an arbitrary AST_Node.",
|
||||
value: "[AST_Node] property value. For setters and getters this is an AST_Function."
|
||||
key: "[string] the property name converted to a string for ObjectKeyVal. For setters and getters this is an AST_SymbolAccessor.",
|
||||
value: "[AST_Node] property value. For setters and getters this is an AST_Accessor."
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
@@ -836,17 +724,13 @@ var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
|
||||
$documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
|
||||
$documentation: "A declaration symbol (symbol in var, function name or argument, symbol in catch)",
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_SymbolVar = DEFNODE("SymbolVar", null, {
|
||||
$documentation: "Symbol defining a variable",
|
||||
}, AST_SymbolDeclaration);
|
||||
|
||||
var AST_SymbolConst = DEFNODE("SymbolConst", null, {
|
||||
$documentation: "A constant declaration"
|
||||
}, AST_SymbolDeclaration);
|
||||
|
||||
var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
|
||||
$documentation: "Symbol naming a function argument",
|
||||
}, AST_SymbolVar);
|
||||
@@ -981,7 +865,7 @@ TreeWalker.prototype = {
|
||||
parent: function(n) {
|
||||
return this.stack[this.stack.length - 2 - (n || 0)];
|
||||
},
|
||||
push: function (node) {
|
||||
push: function(node) {
|
||||
if (node instanceof AST_Lambda) {
|
||||
this.directives = Object.create(this.directives);
|
||||
} else if (node instanceof AST_Directive && !this.directives[node.value]) {
|
||||
@@ -1035,16 +919,16 @@ TreeWalker.prototype = {
|
||||
self = p;
|
||||
}
|
||||
},
|
||||
loopcontrol_target: function(label) {
|
||||
loopcontrol_target: function(node) {
|
||||
var stack = this.stack;
|
||||
if (label) for (var i = stack.length; --i >= 0;) {
|
||||
if (node.label) for (var i = stack.length; --i >= 0;) {
|
||||
var x = stack[i];
|
||||
if (x instanceof AST_LabeledStatement && x.label.name == label.name) {
|
||||
if (x instanceof AST_LabeledStatement && x.label.name == node.label.name)
|
||||
return x.body;
|
||||
}
|
||||
} else for (var i = stack.length; --i >= 0;) {
|
||||
var x = stack[i];
|
||||
if (x instanceof AST_Switch || x instanceof AST_IterationStatement)
|
||||
if (x instanceof AST_IterationStatement
|
||||
|| node instanceof AST_Break && x instanceof AST_Switch)
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
2133
lib/compress.js
2133
lib/compress.js
File diff suppressed because it is too large
Load Diff
154
lib/minify.js
Normal file
154
lib/minify.js
Normal file
@@ -0,0 +1,154 @@
|
||||
"use strict";
|
||||
|
||||
var to_ascii = typeof atob == "undefined" ? function(b64) {
|
||||
return new Buffer(b64, "base64").toString();
|
||||
} : atob;
|
||||
var to_base64 = typeof btoa == "undefined" ? function(str) {
|
||||
return new Buffer(str).toString("base64");
|
||||
} : btoa;
|
||||
|
||||
function read_source_map(code) {
|
||||
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
|
||||
if (!match) {
|
||||
AST_Node.warn("inline source map not found");
|
||||
return null;
|
||||
}
|
||||
return to_ascii(match[2]);
|
||||
}
|
||||
|
||||
function set_shorthand(name, options, keys) {
|
||||
if (options[name]) {
|
||||
keys.forEach(function(key) {
|
||||
if (options[key]) {
|
||||
if (typeof options[key] != "object") options[key] = {};
|
||||
if (!(name in options[key])) options[key][name] = options[name];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function minify(files, options) {
|
||||
var warn_function = AST_Node.warn_function;
|
||||
try {
|
||||
if (typeof files == "string") {
|
||||
files = [ files ];
|
||||
}
|
||||
options = defaults(options, {
|
||||
compress: {},
|
||||
ie8: false,
|
||||
keep_fnames: false,
|
||||
mangle: {},
|
||||
output: {},
|
||||
parse: {},
|
||||
sourceMap: false,
|
||||
toplevel: false,
|
||||
warnings: false,
|
||||
wrap: false,
|
||||
}, true);
|
||||
set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
|
||||
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("warnings", options, [ "compress" ]);
|
||||
if (options.mangle) {
|
||||
options.mangle = defaults(options.mangle, {
|
||||
cache: null,
|
||||
eval: false,
|
||||
ie8: false,
|
||||
keep_fnames: false,
|
||||
properties: false,
|
||||
reserved: [],
|
||||
toplevel: false,
|
||||
}, true);
|
||||
}
|
||||
if (options.sourceMap) {
|
||||
options.sourceMap = defaults(options.sourceMap, {
|
||||
content: null,
|
||||
filename: null,
|
||||
includeSources: false,
|
||||
root: null,
|
||||
url: null,
|
||||
}, true);
|
||||
}
|
||||
var warnings = [];
|
||||
if (options.warnings && !AST_Node.warn_function) {
|
||||
AST_Node.warn_function = function(warning) {
|
||||
warnings.push(warning);
|
||||
};
|
||||
}
|
||||
var toplevel;
|
||||
if (files instanceof AST_Toplevel) {
|
||||
toplevel = files;
|
||||
} else {
|
||||
options.parse = options.parse || {};
|
||||
options.parse.toplevel = null;
|
||||
for (var name in files) {
|
||||
options.parse.filename = name;
|
||||
options.parse.toplevel = parse(files[name], options.parse);
|
||||
if (options.sourceMap && options.sourceMap.content == "inline") {
|
||||
if (Object.keys(files).length > 1)
|
||||
throw new Error("inline source map only works with singular input");
|
||||
options.sourceMap.content = read_source_map(files[name]);
|
||||
}
|
||||
}
|
||||
toplevel = options.parse.toplevel;
|
||||
}
|
||||
if (options.wrap) {
|
||||
toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||
}
|
||||
if (options.compress) {
|
||||
toplevel.figure_out_scope(options.mangle);
|
||||
toplevel = new Compressor(options.compress).compress(toplevel);
|
||||
}
|
||||
if (options.mangle) {
|
||||
toplevel.figure_out_scope(options.mangle);
|
||||
base54.reset();
|
||||
toplevel.compute_char_frequency(options.mangle);
|
||||
toplevel.mangle_names(options.mangle);
|
||||
if (options.mangle.properties) {
|
||||
toplevel = mangle_properties(toplevel, options.mangle.properties);
|
||||
}
|
||||
}
|
||||
var result = {};
|
||||
if (options.output.ast) {
|
||||
result.ast = toplevel;
|
||||
}
|
||||
if (!HOP(options.output, "code") || options.output.code) {
|
||||
if (options.sourceMap) {
|
||||
if (typeof options.sourceMap.content == "string") {
|
||||
options.sourceMap.content = JSON.parse(options.sourceMap.content);
|
||||
}
|
||||
options.output.source_map = SourceMap({
|
||||
file: options.sourceMap.filename,
|
||||
orig: options.sourceMap.content,
|
||||
root: options.sourceMap.root
|
||||
});
|
||||
if (options.sourceMap.includeSources) {
|
||||
for (var name in files) {
|
||||
options.output.source_map.get().setSourceContent(name, files[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete options.output.ast;
|
||||
delete options.output.code;
|
||||
var stream = OutputStream(options.output);
|
||||
toplevel.print(stream);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (warnings.length) {
|
||||
result.warnings = warnings;
|
||||
}
|
||||
return result;
|
||||
} catch (ex) {
|
||||
return { error: ex };
|
||||
} finally {
|
||||
AST_Node.warn_function = warn_function;
|
||||
}
|
||||
}
|
||||
@@ -111,23 +111,19 @@
|
||||
},
|
||||
Property: function(M) {
|
||||
var key = M.key;
|
||||
var name = key.type == "Identifier" ? key.name : key.value;
|
||||
var args = {
|
||||
start : my_start_token(key),
|
||||
end : my_end_token(M.value),
|
||||
key : name,
|
||||
key : key.type == "Identifier" ? key.name : key.value,
|
||||
value : from_moz(M.value)
|
||||
};
|
||||
switch (M.kind) {
|
||||
case "init":
|
||||
return new AST_ObjectKeyVal(args);
|
||||
case "set":
|
||||
args.value.name = from_moz(key);
|
||||
return new AST_ObjectSetter(args);
|
||||
case "get":
|
||||
args.value.name = from_moz(key);
|
||||
return new AST_ObjectGetter(args);
|
||||
}
|
||||
if (M.kind == "init") return new AST_ObjectKeyVal(args);
|
||||
args.key = new AST_SymbolAccessor({
|
||||
name: args.key
|
||||
});
|
||||
args.value = new AST_Accessor(args.value);
|
||||
if (M.kind == "get") return new AST_ObjectGetter(args);
|
||||
if (M.kind == "set") return new AST_ObjectSetter(args);
|
||||
},
|
||||
ArrayExpression: function(M) {
|
||||
return new AST_Array({
|
||||
@@ -149,7 +145,11 @@
|
||||
});
|
||||
},
|
||||
SequenceExpression: function(M) {
|
||||
return AST_Seq.from_array(M.expressions.map(from_moz));
|
||||
return new AST_Sequence({
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M),
|
||||
expressions: M.expressions.map(from_moz)
|
||||
});
|
||||
},
|
||||
MemberExpression: function(M) {
|
||||
return new (M.computed ? AST_Sub : AST_Dot)({
|
||||
@@ -168,7 +168,7 @@
|
||||
});
|
||||
},
|
||||
VariableDeclaration: function(M) {
|
||||
return new (M.kind === "const" ? AST_Const : AST_Var)({
|
||||
return new AST_Var({
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M),
|
||||
definitions : M.declarations.map(from_moz)
|
||||
@@ -204,7 +204,7 @@
|
||||
Identifier: function(M) {
|
||||
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
|
||||
return new ( p.type == "LabeledStatement" ? AST_Label
|
||||
: p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar)
|
||||
: p.type == "VariableDeclarator" && p.id === M ? AST_SymbolVar
|
||||
: p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
|
||||
: p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
|
||||
: p.type == "CatchClause" ? AST_SymbolCatch
|
||||
@@ -256,10 +256,7 @@
|
||||
map("CallExpression", AST_Call, "callee>expression, arguments@args");
|
||||
|
||||
def_to_moz(AST_Toplevel, function To_Moz_Program(M) {
|
||||
return {
|
||||
type: "Program",
|
||||
body: M.body.map(to_moz)
|
||||
};
|
||||
return to_moz_scope("Program", M);
|
||||
});
|
||||
|
||||
def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) {
|
||||
@@ -267,7 +264,7 @@
|
||||
type: "FunctionDeclaration",
|
||||
id: to_moz(M.name),
|
||||
params: M.argnames.map(to_moz),
|
||||
body: to_moz_block(M)
|
||||
body: to_moz_scope("BlockStatement", M)
|
||||
}
|
||||
});
|
||||
|
||||
@@ -276,7 +273,7 @@
|
||||
type: "FunctionExpression",
|
||||
id: to_moz(M.name),
|
||||
params: M.argnames.map(to_moz),
|
||||
body: to_moz_block(M)
|
||||
body: to_moz_scope("BlockStatement", M)
|
||||
}
|
||||
});
|
||||
|
||||
@@ -327,15 +324,15 @@
|
||||
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
|
||||
return {
|
||||
type: "VariableDeclaration",
|
||||
kind: M instanceof AST_Const ? "const" : "var",
|
||||
kind: "var",
|
||||
declarations: M.definitions.map(to_moz)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Seq, function To_Moz_SequenceExpression(M) {
|
||||
def_to_moz(AST_Sequence, function To_Moz_SequenceExpression(M) {
|
||||
return {
|
||||
type: "SequenceExpression",
|
||||
expressions: M.to_array().map(to_moz)
|
||||
expressions: M.expressions.map(to_moz)
|
||||
};
|
||||
});
|
||||
|
||||
@@ -382,11 +379,10 @@
|
||||
});
|
||||
|
||||
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
|
||||
var key = (
|
||||
is_identifier(M.key)
|
||||
? {type: "Identifier", name: M.key}
|
||||
: {type: "Literal", value: M.key}
|
||||
);
|
||||
var key = {
|
||||
type: "Literal",
|
||||
value: M.key instanceof AST_SymbolAccessor ? M.key.name : M.key
|
||||
};
|
||||
var kind;
|
||||
if (M instanceof AST_ObjectKeyVal) {
|
||||
kind = "init";
|
||||
@@ -547,8 +543,8 @@
|
||||
moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
|
||||
exports, my_start_token, my_end_token, from_moz
|
||||
);
|
||||
me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(
|
||||
to_moz, to_moz_block
|
||||
me_to_moz = new Function("to_moz", "to_moz_block", "to_moz_scope", "return(" + me_to_moz + ")")(
|
||||
to_moz, to_moz_block, to_moz_scope
|
||||
);
|
||||
MOZ_TO_ME[moztype] = moz_to_me;
|
||||
def_to_moz(mytype, me_to_moz);
|
||||
@@ -606,4 +602,14 @@
|
||||
};
|
||||
};
|
||||
|
||||
function to_moz_scope(type, node) {
|
||||
var body = node.body.map(to_moz);
|
||||
if (node.body[0] instanceof AST_SimpleStatement && node.body[0].body instanceof AST_String) {
|
||||
body.unshift(to_moz(new AST_EmptyStatement(node.body[0])));
|
||||
}
|
||||
return {
|
||||
type: type,
|
||||
body: body
|
||||
};
|
||||
};
|
||||
})();
|
||||
|
||||
147
lib/output.js
147
lib/output.js
@@ -53,26 +53,24 @@ function is_some_comments(comment) {
|
||||
function OutputStream(options) {
|
||||
|
||||
options = defaults(options, {
|
||||
indent_start : 0,
|
||||
indent_level : 4,
|
||||
quote_keys : false,
|
||||
space_colon : true,
|
||||
ascii_only : false,
|
||||
unescape_regexps : false,
|
||||
inline_script : false,
|
||||
width : 80,
|
||||
max_line_len : false,
|
||||
beautify : false,
|
||||
source_map : null,
|
||||
bracketize : false,
|
||||
semicolons : true,
|
||||
comments : false,
|
||||
shebang : true,
|
||||
preserve_line : false,
|
||||
screw_ie8 : true,
|
||||
preamble : null,
|
||||
quote_style : 0,
|
||||
ie8 : false,
|
||||
indent_level : 4,
|
||||
indent_start : 0,
|
||||
inline_script : true,
|
||||
keep_quoted_props: false,
|
||||
max_line_len : false,
|
||||
preamble : null,
|
||||
preserve_line : false,
|
||||
quote_keys : false,
|
||||
quote_style : 0,
|
||||
semicolons : true,
|
||||
shebang : true,
|
||||
source_map : null,
|
||||
width : 80,
|
||||
wrap_iife : false,
|
||||
}, true);
|
||||
|
||||
@@ -136,7 +134,7 @@ function OutputStream(options) {
|
||||
case "\t": return "\\t";
|
||||
case "\b": return "\\b";
|
||||
case "\f": return "\\f";
|
||||
case "\x0B": return options.screw_ie8 ? "\\v" : "\\x0B";
|
||||
case "\x0B": return options.ie8 ? "\\x0B" : "\\v";
|
||||
case "\u2028": return "\\u2028";
|
||||
case "\u2029": return "\\u2029";
|
||||
case "\ufeff": return "\\ufeff";
|
||||
@@ -190,11 +188,7 @@ function OutputStream(options) {
|
||||
var might_need_space = false;
|
||||
var might_need_semicolon = false;
|
||||
var might_add_newline = 0;
|
||||
var last = null;
|
||||
|
||||
function last_char() {
|
||||
return last.charAt(last.length - 1);
|
||||
};
|
||||
var last = "";
|
||||
|
||||
var ensure_line_len = options.max_line_len ? function() {
|
||||
if (current_col > options.max_line_len) {
|
||||
@@ -218,10 +212,11 @@ function OutputStream(options) {
|
||||
function print(str) {
|
||||
str = String(str);
|
||||
var ch = str.charAt(0);
|
||||
var prev = last.charAt(last.length - 1);
|
||||
if (might_need_semicolon) {
|
||||
might_need_semicolon = false;
|
||||
|
||||
if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {
|
||||
if (prev == ":" && ch == "}" || (!ch || ";}".indexOf(ch) < 0) && prev != ";") {
|
||||
if (options.semicolons || requireSemicolonChars(ch)) {
|
||||
OUTPUT += ";";
|
||||
current_col++;
|
||||
@@ -258,7 +253,6 @@ function OutputStream(options) {
|
||||
}
|
||||
|
||||
if (might_need_space) {
|
||||
var prev = last_char();
|
||||
if ((is_identifier_char(prev)
|
||||
&& (is_identifier_char(ch) || ch == "\\"))
|
||||
|| (ch == "/" && ch == prev)
|
||||
@@ -361,7 +355,7 @@ function OutputStream(options) {
|
||||
|
||||
function colon() {
|
||||
print(":");
|
||||
if (options.space_colon) space();
|
||||
space();
|
||||
};
|
||||
|
||||
var add_mapping = options.source_map ? function(token, name) {
|
||||
@@ -510,8 +504,8 @@ function OutputStream(options) {
|
||||
}));
|
||||
}
|
||||
|
||||
if (comments.length > 0 && output.pos() == 0) {
|
||||
if (output.option("shebang") && comments[0].type == "comment5") {
|
||||
if (output.pos() == 0) {
|
||||
if (comments.length > 0 && output.option("shebang") && comments[0].type == "comment5") {
|
||||
output.print("#!" + comments.shift().value + "\n");
|
||||
output.indent();
|
||||
}
|
||||
@@ -586,22 +580,13 @@ function OutputStream(options) {
|
||||
return first_in_statement(output);
|
||||
});
|
||||
|
||||
PARENS([ AST_Unary, AST_Undefined ], function(output){
|
||||
PARENS(AST_Unary, function(output){
|
||||
var p = output.parent();
|
||||
return p instanceof AST_PropAccess && p.expression === this
|
||||
|| p instanceof AST_Call && p.expression === this;
|
||||
});
|
||||
|
||||
PARENS([ AST_Infinity, AST_NaN ], function(output){
|
||||
var p = output.parent();
|
||||
return p instanceof AST_PropAccess && p.expression === this
|
||||
|| p instanceof AST_Call && p.expression === this
|
||||
|| p instanceof AST_Unary && p.operator != "+" && p.operator != "-"
|
||||
|| p instanceof AST_Binary && p.right === this
|
||||
&& (p.operator == "/" || p.operator == "%");
|
||||
});
|
||||
|
||||
PARENS(AST_Seq, function(output){
|
||||
PARENS(AST_Sequence, function(output){
|
||||
var p = output.parent();
|
||||
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
|
||||
|| p instanceof AST_Unary // !(foo, bar, baz)
|
||||
@@ -690,7 +675,7 @@ function OutputStream(options) {
|
||||
}
|
||||
});
|
||||
|
||||
PARENS([ AST_Assign, AST_Conditional ], function (output){
|
||||
PARENS([ AST_Assign, AST_Conditional ], function(output){
|
||||
var p = output.parent();
|
||||
// !(a = false) → true
|
||||
if (p instanceof AST_Unary)
|
||||
@@ -915,7 +900,7 @@ function OutputStream(options) {
|
||||
function make_then(self, output) {
|
||||
var b = self.body;
|
||||
if (output.option("bracketize")
|
||||
|| !output.option("screw_ie8") && b instanceof AST_Do)
|
||||
|| output.option("ie8") && b instanceof AST_Do)
|
||||
return make_block(b, output);
|
||||
// The squeezer replaces "block"-s that contain only a single
|
||||
// statement with the statement itself; technically, the AST
|
||||
@@ -1046,9 +1031,6 @@ function OutputStream(options) {
|
||||
DEFPRINT(AST_Var, function(self, output){
|
||||
self._do_print(output, "var");
|
||||
});
|
||||
DEFPRINT(AST_Const, function(self, output){
|
||||
self._do_print(output, "const");
|
||||
});
|
||||
|
||||
function parenthesize_for_noin(node, output, noin) {
|
||||
if (!noin) node.print(output);
|
||||
@@ -1096,18 +1078,19 @@ function OutputStream(options) {
|
||||
AST_Call.prototype._codegen(self, output);
|
||||
});
|
||||
|
||||
AST_Seq.DEFMETHOD("_do_print", function(output){
|
||||
this.car.print(output);
|
||||
if (this.cdr) {
|
||||
output.comma();
|
||||
if (output.should_break()) {
|
||||
output.newline();
|
||||
output.indent();
|
||||
AST_Sequence.DEFMETHOD("_do_print", function(output){
|
||||
this.expressions.forEach(function(node, index) {
|
||||
if (index > 0) {
|
||||
output.comma();
|
||||
if (output.should_break()) {
|
||||
output.newline();
|
||||
output.indent();
|
||||
}
|
||||
}
|
||||
this.cdr.print(output);
|
||||
}
|
||||
node.print(output);
|
||||
});
|
||||
});
|
||||
DEFPRINT(AST_Seq, function(self, output){
|
||||
DEFPRINT(AST_Sequence, function(self, output){
|
||||
self._do_print(output);
|
||||
// var p = output.parent();
|
||||
// if (p instanceof AST_Statement) {
|
||||
@@ -1230,7 +1213,7 @@ function OutputStream(options) {
|
||||
&& +key + "" == key)
|
||||
&& parseFloat(key) >= 0) {
|
||||
output.print(make_num(key));
|
||||
} else if (RESERVED_WORDS(key) ? output.option("screw_ie8") : is_identifier_string(key)) {
|
||||
} else if (RESERVED_WORDS(key) ? !output.option("ie8") : is_identifier_string(key)) {
|
||||
if (quote && output.option("keep_quoted_props")) {
|
||||
output.print_string(key, quote);
|
||||
} else {
|
||||
@@ -1258,24 +1241,7 @@ function OutputStream(options) {
|
||||
var def = self.definition();
|
||||
output.print_name(def ? def.mangled_name || def.name : self.name);
|
||||
});
|
||||
DEFPRINT(AST_Undefined, function(self, output){
|
||||
output.print("void 0");
|
||||
});
|
||||
DEFPRINT(AST_Hole, noop);
|
||||
DEFPRINT(AST_Infinity, function(self, output){
|
||||
output.print("1");
|
||||
output.space();
|
||||
output.print("/");
|
||||
output.space();
|
||||
output.print("0");
|
||||
});
|
||||
DEFPRINT(AST_NaN, function(self, output){
|
||||
output.print("0");
|
||||
output.space();
|
||||
output.print("/");
|
||||
output.space();
|
||||
output.print("0");
|
||||
});
|
||||
DEFPRINT(AST_This, function(self, output){
|
||||
output.print("this");
|
||||
});
|
||||
@@ -1293,45 +1259,14 @@ function OutputStream(options) {
|
||||
}
|
||||
});
|
||||
|
||||
function regexp_safe_literal(code) {
|
||||
return [
|
||||
0x5c , // \
|
||||
0x2f , // /
|
||||
0x2e , // .
|
||||
0x2b , // +
|
||||
0x2a , // *
|
||||
0x3f , // ?
|
||||
0x28 , // (
|
||||
0x29 , // )
|
||||
0x5b , // [
|
||||
0x5d , // ]
|
||||
0x7b , // {
|
||||
0x7d , // }
|
||||
0x24 , // $
|
||||
0x5e , // ^
|
||||
0x3a , // :
|
||||
0x7c , // |
|
||||
0x21 , // !
|
||||
0x0a , // \n
|
||||
0x0d , // \r
|
||||
0x00 , // \0
|
||||
0xfeff , // Unicode BOM
|
||||
0x2028 , // unicode "line separator"
|
||||
0x2029 , // unicode "paragraph separator"
|
||||
].indexOf(code) < 0;
|
||||
};
|
||||
|
||||
DEFPRINT(AST_RegExp, function(self, output){
|
||||
var str = self.getValue().toString();
|
||||
var regexp = self.getValue();
|
||||
var str = regexp.toString();
|
||||
if (regexp.raw_source) {
|
||||
str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
|
||||
}
|
||||
if (output.option("ascii_only")) {
|
||||
str = output.to_ascii(str);
|
||||
} else if (output.option("unescape_regexps")) {
|
||||
str = str.split("\\\\").map(function(str){
|
||||
return str.replace(/\\u[0-9a-fA-F]{4}|\\x[0-9a-fA-F]{2}/g, function(s){
|
||||
var code = parseInt(s.substr(2), 16);
|
||||
return regexp_safe_literal(code) ? String.fromCharCode(code) : s;
|
||||
});
|
||||
}).join("\\\\");
|
||||
}
|
||||
output.print(str);
|
||||
var p = output.parent();
|
||||
|
||||
239
lib/parse.js
239
lib/parse.js
@@ -111,7 +111,7 @@ var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u20
|
||||
|
||||
var NEWLINE_CHARS = makePredicate(characters("\n\r\u2028\u2029"));
|
||||
|
||||
var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
|
||||
var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,;:"));
|
||||
|
||||
var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
|
||||
|
||||
@@ -285,7 +285,11 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX(value)) ||
|
||||
(type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) ||
|
||||
(type == "punc" && PUNC_BEFORE_EXPRESSION(value)));
|
||||
prev_was_dot = (type == "punc" && value == ".");
|
||||
if (type == "punc" && value == ".") {
|
||||
prev_was_dot = true;
|
||||
} else if (!is_comment) {
|
||||
prev_was_dot = false;
|
||||
}
|
||||
var ret = {
|
||||
type : type,
|
||||
value : value,
|
||||
@@ -473,31 +477,33 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
return name;
|
||||
};
|
||||
|
||||
var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){
|
||||
var read_regexp = with_eof_error("Unterminated regular expression", function(source) {
|
||||
var prev_backslash = false, ch, in_class = false;
|
||||
while ((ch = next(true))) if (NEWLINE_CHARS(ch)) {
|
||||
parse_error("Unexpected line terminator");
|
||||
} else if (prev_backslash) {
|
||||
regexp += "\\" + ch;
|
||||
source += "\\" + ch;
|
||||
prev_backslash = false;
|
||||
} else if (ch == "[") {
|
||||
in_class = true;
|
||||
regexp += ch;
|
||||
source += ch;
|
||||
} else if (ch == "]" && in_class) {
|
||||
in_class = false;
|
||||
regexp += ch;
|
||||
source += ch;
|
||||
} else if (ch == "/" && !in_class) {
|
||||
break;
|
||||
} else if (ch == "\\") {
|
||||
prev_backslash = true;
|
||||
} else {
|
||||
regexp += ch;
|
||||
source += ch;
|
||||
}
|
||||
var mods = read_name();
|
||||
try {
|
||||
return token("regexp", new RegExp(regexp, mods));
|
||||
var regexp = new RegExp(source, mods);
|
||||
regexp.raw_source = source;
|
||||
return token("regexp", regexp);
|
||||
} catch(e) {
|
||||
parse_error(e.message);
|
||||
parse_error(e.message);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -629,8 +635,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
}
|
||||
|
||||
next_token.has_directive = function(directive) {
|
||||
return S.directives[directive] !== undefined &&
|
||||
S.directives[directive] > 0;
|
||||
return S.directives[directive] > 0;
|
||||
}
|
||||
|
||||
return next_token;
|
||||
@@ -688,14 +693,13 @@ var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "nam
|
||||
function parse($TEXT, options) {
|
||||
|
||||
options = defaults(options, {
|
||||
strict : false,
|
||||
filename : null,
|
||||
toplevel : null,
|
||||
expression : false,
|
||||
html5_comments : true,
|
||||
bare_returns : false,
|
||||
expression : false,
|
||||
filename : null,
|
||||
html5_comments : true,
|
||||
shebang : true,
|
||||
cli : false,
|
||||
strict : false,
|
||||
toplevel : null,
|
||||
});
|
||||
|
||||
var S = {
|
||||
@@ -803,28 +807,23 @@ function parse($TEXT, options) {
|
||||
};
|
||||
|
||||
var statement = embed_tokens(function() {
|
||||
var tmp;
|
||||
handle_regexp();
|
||||
switch (S.token.type) {
|
||||
case "string":
|
||||
var dir = false;
|
||||
if (S.in_directives === true) {
|
||||
if ((is_token(peek(), "punc", ";") || peek().nlb) && S.token.raw.indexOf("\\") === -1) {
|
||||
if (S.in_directives) {
|
||||
var token = peek();
|
||||
if (S.token.raw.indexOf("\\") == -1
|
||||
&& (token.nlb
|
||||
|| is_token(token, "eof")
|
||||
|| is_token(token, "punc", ";")
|
||||
|| is_token(token, "punc", "}"))) {
|
||||
S.input.add_directive(S.token.value);
|
||||
} else {
|
||||
S.in_directives = false;
|
||||
}
|
||||
}
|
||||
var dir = S.in_directives, stat = simple_statement();
|
||||
if (dir) {
|
||||
return new AST_Directive({
|
||||
start : stat.body.start,
|
||||
end : stat.body.end,
|
||||
quote : stat.body.quote,
|
||||
value : stat.body.value,
|
||||
});
|
||||
}
|
||||
return stat;
|
||||
return dir ? new AST_Directive(stat.body) : stat;
|
||||
case "num":
|
||||
case "regexp":
|
||||
case "operator":
|
||||
@@ -856,75 +855,97 @@ function parse($TEXT, options) {
|
||||
}
|
||||
|
||||
case "keyword":
|
||||
switch (tmp = S.token.value, next(), tmp) {
|
||||
switch (S.token.value) {
|
||||
case "break":
|
||||
next();
|
||||
return break_cont(AST_Break);
|
||||
|
||||
case "continue":
|
||||
next();
|
||||
return break_cont(AST_Continue);
|
||||
|
||||
case "debugger":
|
||||
next();
|
||||
semicolon();
|
||||
return new AST_Debugger();
|
||||
|
||||
case "do":
|
||||
next();
|
||||
var body = in_loop(statement);
|
||||
expect_token("keyword", "while");
|
||||
var condition = parenthesised();
|
||||
semicolon(true);
|
||||
return new AST_Do({
|
||||
body : in_loop(statement),
|
||||
condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(true), tmp)
|
||||
body : body,
|
||||
condition : condition
|
||||
});
|
||||
|
||||
case "while":
|
||||
next();
|
||||
return new AST_While({
|
||||
condition : parenthesised(),
|
||||
body : in_loop(statement)
|
||||
});
|
||||
|
||||
case "for":
|
||||
next();
|
||||
return for_();
|
||||
|
||||
case "function":
|
||||
next();
|
||||
return function_(AST_Defun);
|
||||
|
||||
case "if":
|
||||
next();
|
||||
return if_();
|
||||
|
||||
case "return":
|
||||
if (S.in_function == 0 && !options.bare_returns)
|
||||
croak("'return' outside of function");
|
||||
next();
|
||||
var value = null;
|
||||
if (is("punc", ";")) {
|
||||
next();
|
||||
} else if (!can_insert_semicolon()) {
|
||||
value = expression(true);
|
||||
semicolon();
|
||||
}
|
||||
return new AST_Return({
|
||||
value: ( is("punc", ";")
|
||||
? (next(), null)
|
||||
: can_insert_semicolon()
|
||||
? null
|
||||
: (tmp = expression(true), semicolon(), tmp) )
|
||||
value: value
|
||||
});
|
||||
|
||||
case "switch":
|
||||
next();
|
||||
return new AST_Switch({
|
||||
expression : parenthesised(),
|
||||
body : in_loop(switch_body_)
|
||||
});
|
||||
|
||||
case "throw":
|
||||
next();
|
||||
if (S.token.nlb)
|
||||
croak("Illegal newline after 'throw'");
|
||||
var value = expression(true);
|
||||
semicolon();
|
||||
return new AST_Throw({
|
||||
value: (tmp = expression(true), semicolon(), tmp)
|
||||
value: value
|
||||
});
|
||||
|
||||
case "try":
|
||||
next();
|
||||
return try_();
|
||||
|
||||
case "var":
|
||||
return tmp = var_(), semicolon(), tmp;
|
||||
|
||||
case "const":
|
||||
return tmp = const_(), semicolon(), tmp;
|
||||
next();
|
||||
var node = var_();
|
||||
semicolon();
|
||||
return node;
|
||||
|
||||
case "with":
|
||||
if (S.input.has_directive("use strict")) {
|
||||
croak("Strict mode may not include a with statement");
|
||||
}
|
||||
next();
|
||||
return new AST_With({
|
||||
expression : parenthesised(),
|
||||
body : statement()
|
||||
@@ -1034,29 +1055,32 @@ function parse($TEXT, options) {
|
||||
if (in_statement && !name)
|
||||
unexpected();
|
||||
expect("(");
|
||||
var argnames = [];
|
||||
for (var first = true; !is("punc", ")");) {
|
||||
if (first) first = false; else expect(",");
|
||||
argnames.push(as_symbol(AST_SymbolFunarg));
|
||||
}
|
||||
next();
|
||||
var loop = S.in_loop;
|
||||
var labels = S.labels;
|
||||
++S.in_function;
|
||||
S.in_directives = true;
|
||||
S.input.push_directives_stack();
|
||||
S.in_loop = 0;
|
||||
S.labels = [];
|
||||
var body = block_();
|
||||
if (S.input.has_directive("use strict")) {
|
||||
if (name) strict_verify_symbol(name);
|
||||
argnames.forEach(strict_verify_symbol);
|
||||
}
|
||||
S.input.pop_directives_stack();
|
||||
--S.in_function;
|
||||
S.in_loop = loop;
|
||||
S.labels = labels;
|
||||
return new ctor({
|
||||
name: name,
|
||||
argnames: (function(first, a){
|
||||
while (!is("punc", ")")) {
|
||||
if (first) first = false; else expect(",");
|
||||
a.push(as_symbol(AST_SymbolFunarg));
|
||||
}
|
||||
next();
|
||||
return a;
|
||||
})(true, []),
|
||||
body: (function(loop, labels){
|
||||
++S.in_function;
|
||||
S.in_directives = true;
|
||||
S.input.push_directives_stack();
|
||||
S.in_loop = 0;
|
||||
S.labels = [];
|
||||
var a = block_();
|
||||
S.input.pop_directives_stack();
|
||||
--S.in_function;
|
||||
S.in_loop = loop;
|
||||
S.labels = labels;
|
||||
return a;
|
||||
})(S.in_loop, S.labels)
|
||||
argnames: argnames,
|
||||
body: body
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1152,12 +1176,12 @@ function parse($TEXT, options) {
|
||||
});
|
||||
};
|
||||
|
||||
function vardefs(no_in, in_const) {
|
||||
function vardefs(no_in) {
|
||||
var a = [];
|
||||
for (;;) {
|
||||
a.push(new AST_VarDef({
|
||||
start : S.token,
|
||||
name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
|
||||
name : as_symbol(AST_SymbolVar),
|
||||
value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
|
||||
end : prev()
|
||||
}));
|
||||
@@ -1171,15 +1195,7 @@ function parse($TEXT, options) {
|
||||
var var_ = function(no_in) {
|
||||
return new AST_Var({
|
||||
start : prev(),
|
||||
definitions : vardefs(no_in, false),
|
||||
end : prev()
|
||||
});
|
||||
};
|
||||
|
||||
var const_ = function() {
|
||||
return new AST_Const({
|
||||
start : prev(),
|
||||
definitions : vardefs(false, true),
|
||||
definitions : vardefs(no_in),
|
||||
end : prev()
|
||||
});
|
||||
};
|
||||
@@ -1320,10 +1336,15 @@ function parse($TEXT, options) {
|
||||
var type = start.type;
|
||||
var name = as_property_name();
|
||||
if (type == "name" && !is("punc", ":")) {
|
||||
var key = new AST_SymbolAccessor({
|
||||
start: S.token,
|
||||
name: as_property_name(),
|
||||
end: prev()
|
||||
});
|
||||
if (name == "get") {
|
||||
a.push(new AST_ObjectGetter({
|
||||
start : start,
|
||||
key : as_atom_node(),
|
||||
key : key,
|
||||
value : create_accessor(),
|
||||
end : prev()
|
||||
}));
|
||||
@@ -1332,7 +1353,7 @@ function parse($TEXT, options) {
|
||||
if (name == "set") {
|
||||
a.push(new AST_ObjectSetter({
|
||||
start : start,
|
||||
key : as_atom_node(),
|
||||
key : key,
|
||||
value : create_accessor(),
|
||||
end : prev()
|
||||
}));
|
||||
@@ -1354,14 +1375,15 @@ function parse($TEXT, options) {
|
||||
|
||||
function as_property_name() {
|
||||
var tmp = S.token;
|
||||
next();
|
||||
switch (tmp.type) {
|
||||
case "operator":
|
||||
if (!KEYWORDS(tmp.value)) unexpected();
|
||||
case "num":
|
||||
case "string":
|
||||
case "name":
|
||||
case "operator":
|
||||
case "keyword":
|
||||
case "atom":
|
||||
next();
|
||||
return tmp.value;
|
||||
default:
|
||||
unexpected();
|
||||
@@ -1370,16 +1392,9 @@ function parse($TEXT, options) {
|
||||
|
||||
function as_name() {
|
||||
var tmp = S.token;
|
||||
if (tmp.type != "name") unexpected();
|
||||
next();
|
||||
switch (tmp.type) {
|
||||
case "name":
|
||||
case "operator":
|
||||
case "keyword":
|
||||
case "atom":
|
||||
return tmp.value;
|
||||
default:
|
||||
unexpected();
|
||||
}
|
||||
return tmp.value;
|
||||
};
|
||||
|
||||
function _make_symbol(type) {
|
||||
@@ -1391,12 +1406,20 @@ function parse($TEXT, options) {
|
||||
});
|
||||
};
|
||||
|
||||
function strict_verify_symbol(sym) {
|
||||
if (sym.name == "arguments" || sym.name == "eval")
|
||||
croak("Unexpected " + sym.name + " in strict mode", sym.start.line, sym.start.col, sym.start.pos);
|
||||
}
|
||||
|
||||
function as_symbol(type, noerror) {
|
||||
if (!is("name")) {
|
||||
if (!noerror) croak("Name expected");
|
||||
return null;
|
||||
}
|
||||
var sym = _make_symbol(type);
|
||||
if (S.input.has_directive("use strict") && sym instanceof AST_SymbolDeclaration) {
|
||||
strict_verify_symbol(sym);
|
||||
}
|
||||
next();
|
||||
return sym;
|
||||
};
|
||||
@@ -1440,14 +1463,14 @@ function parse($TEXT, options) {
|
||||
if (is("operator") && UNARY_PREFIX(start.value)) {
|
||||
next();
|
||||
handle_regexp();
|
||||
var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls));
|
||||
var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(allow_calls));
|
||||
ex.start = start;
|
||||
ex.end = prev();
|
||||
return ex;
|
||||
}
|
||||
var val = expr_atom(allow_calls);
|
||||
while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) {
|
||||
val = make_unary(AST_UnaryPostfix, S.token.value, val);
|
||||
val = make_unary(AST_UnaryPostfix, S.token, val);
|
||||
val.start = start;
|
||||
val.end = S.token;
|
||||
next();
|
||||
@@ -1455,9 +1478,19 @@ function parse($TEXT, options) {
|
||||
return val;
|
||||
};
|
||||
|
||||
function make_unary(ctor, op, expr) {
|
||||
if ((op == "++" || op == "--") && !is_assignable(expr))
|
||||
croak("Invalid use of " + op + " operator", null, ctor === AST_UnaryPrefix ? expr.start.col - 1 : null);
|
||||
function make_unary(ctor, token, expr) {
|
||||
var op = token.value;
|
||||
switch (op) {
|
||||
case "++":
|
||||
case "--":
|
||||
if (!is_assignable(expr))
|
||||
croak("Invalid use of " + op + " operator", token.line, token.col, token.pos);
|
||||
break;
|
||||
case "delete":
|
||||
if (expr instanceof AST_SymbolRef && S.input.has_directive("use strict"))
|
||||
croak("Calling delete on expression not allowed in strict mode", expr.start.line, expr.start.col, expr.start.pos);
|
||||
break;
|
||||
}
|
||||
return new ctor({ operator: op, expression: expr });
|
||||
};
|
||||
|
||||
@@ -1502,7 +1535,6 @@ function parse($TEXT, options) {
|
||||
};
|
||||
|
||||
function is_assignable(expr) {
|
||||
if (options.cli) return true;
|
||||
return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef;
|
||||
};
|
||||
|
||||
@@ -1527,17 +1559,18 @@ function parse($TEXT, options) {
|
||||
|
||||
var expression = function(commas, no_in) {
|
||||
var start = S.token;
|
||||
var expr = maybe_assign(no_in);
|
||||
if (commas && is("punc", ",")) {
|
||||
var exprs = [];
|
||||
while (true) {
|
||||
exprs.push(maybe_assign(no_in));
|
||||
if (!commas || !is("punc", ",")) break;
|
||||
next();
|
||||
return new AST_Seq({
|
||||
start : start,
|
||||
car : expr,
|
||||
cdr : expression(true, no_in),
|
||||
end : peek()
|
||||
});
|
||||
commas = true;
|
||||
}
|
||||
return expr;
|
||||
return exprs.length == 1 ? exprs[0] : new AST_Sequence({
|
||||
start : start,
|
||||
expressions : exprs,
|
||||
end : peek()
|
||||
});
|
||||
};
|
||||
|
||||
function in_loop(cont) {
|
||||
|
||||
@@ -43,8 +43,16 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
function find_builtins() {
|
||||
var a = [];
|
||||
function find_builtins(reserved) {
|
||||
// NaN will be included due to Number.NaN
|
||||
[
|
||||
"null",
|
||||
"true",
|
||||
"false",
|
||||
"Infinity",
|
||||
"-Infinity",
|
||||
"undefined",
|
||||
].forEach(add);
|
||||
[ Object, Array, Function, Number,
|
||||
String, Boolean, Error, Math,
|
||||
Date, RegExp
|
||||
@@ -55,24 +63,23 @@ function find_builtins() {
|
||||
}
|
||||
});
|
||||
function add(name) {
|
||||
push_uniq(a, name);
|
||||
push_uniq(reserved, name);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
function mangle_properties(ast, options) {
|
||||
options = defaults(options, {
|
||||
reserved : null,
|
||||
cache : null,
|
||||
only_cache : false,
|
||||
regex : null,
|
||||
ignore_quoted : false,
|
||||
debug : false
|
||||
builtins: false,
|
||||
cache: null,
|
||||
debug: false,
|
||||
keep_quoted: false,
|
||||
only_cache: false,
|
||||
regex: null,
|
||||
reserved: null,
|
||||
});
|
||||
|
||||
var reserved = options.reserved;
|
||||
if (reserved == null)
|
||||
reserved = find_builtins();
|
||||
var reserved = options.reserved || [];
|
||||
if (!options.builtins) find_builtins(reserved);
|
||||
|
||||
var cache = options.cache;
|
||||
if (cache == null) {
|
||||
@@ -83,12 +90,12 @@ function mangle_properties(ast, options) {
|
||||
}
|
||||
|
||||
var regex = options.regex;
|
||||
var ignore_quoted = options.ignore_quoted;
|
||||
var keep_quoted = options.keep_quoted;
|
||||
|
||||
// note debug is either false (disabled), or a string of the debug suffix to use (enabled).
|
||||
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
|
||||
// the same as passing an empty string.
|
||||
var debug = (options.debug !== false);
|
||||
var debug = options.debug !== false;
|
||||
var debug_name_suffix;
|
||||
if (debug) {
|
||||
debug_name_suffix = (options.debug === true ? "" : options.debug);
|
||||
@@ -96,12 +103,12 @@ function mangle_properties(ast, options) {
|
||||
|
||||
var names_to_mangle = [];
|
||||
var unmangleable = [];
|
||||
var ignored = {};
|
||||
var to_keep = {};
|
||||
|
||||
// step 1: find candidates to mangle
|
||||
ast.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_ObjectKeyVal) {
|
||||
add(node.key, ignore_quoted && node.quote);
|
||||
add(node.key, keep_quoted && node.quote);
|
||||
}
|
||||
else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter, since KeyVal is handled above
|
||||
@@ -111,14 +118,14 @@ function mangle_properties(ast, options) {
|
||||
add(node.property);
|
||||
}
|
||||
else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, ignore_quoted);
|
||||
addStrings(node.property, keep_quoted);
|
||||
}
|
||||
}));
|
||||
|
||||
// step 2: transform the tree, renaming properties
|
||||
return ast.transform(new TreeTransformer(function(node){
|
||||
if (node instanceof AST_ObjectKeyVal) {
|
||||
if (!(ignore_quoted && node.quote))
|
||||
if (!(keep_quoted && node.quote))
|
||||
node.key = mangle(node.key);
|
||||
}
|
||||
else if (node instanceof AST_ObjectProperty) {
|
||||
@@ -129,7 +136,7 @@ function mangle_properties(ast, options) {
|
||||
node.property = mangle(node.property);
|
||||
}
|
||||
else if (node instanceof AST_Sub) {
|
||||
if (!ignore_quoted)
|
||||
if (!keep_quoted)
|
||||
node.property = mangleStrings(node.property);
|
||||
}
|
||||
// else if (node instanceof AST_String) {
|
||||
@@ -149,27 +156,26 @@ function mangle_properties(ast, options) {
|
||||
// only function declarations after this line
|
||||
|
||||
function can_mangle(name) {
|
||||
if (!is_identifier(name)) return false;
|
||||
if (unmangleable.indexOf(name) >= 0) return false;
|
||||
if (reserved.indexOf(name) >= 0) return false;
|
||||
if (options.only_cache) {
|
||||
return cache.props.has(name);
|
||||
}
|
||||
if (/^[0-9.]+$/.test(name)) return false;
|
||||
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function should_mangle(name) {
|
||||
if (ignore_quoted && name in ignored) return false;
|
||||
if (keep_quoted && name in to_keep) return false;
|
||||
if (regex && !regex.test(name)) return false;
|
||||
if (reserved.indexOf(name) >= 0) return false;
|
||||
return cache.props.has(name)
|
||||
|| names_to_mangle.indexOf(name) >= 0;
|
||||
}
|
||||
|
||||
function add(name, ignore) {
|
||||
if (ignore) {
|
||||
ignored[name] = true;
|
||||
function add(name, keep) {
|
||||
if (keep) {
|
||||
to_keep[name] = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -192,19 +198,19 @@ function mangle_properties(ast, options) {
|
||||
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
|
||||
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
|
||||
|
||||
if (can_mangle(debug_mangled) && !(ignore_quoted && debug_mangled in ignored)) {
|
||||
if (can_mangle(debug_mangled) && !(keep_quoted && debug_mangled in to_keep)) {
|
||||
mangled = debug_mangled;
|
||||
}
|
||||
}
|
||||
|
||||
// either debug mode is off, or it is on and we could not use the mangled name
|
||||
if (!mangled) {
|
||||
// note can_mangle() does not check if the name collides with the 'ignored' set
|
||||
// (filled with quoted properties when ignore_quoted set). Make sure we add this
|
||||
// Note: `can_mangle()` does not check if the name collides with the `to_keep` set
|
||||
// (filled with quoted properties when `keep_quoted` is set). Make sure we add this
|
||||
// check so we don't collide with a quoted name.
|
||||
do {
|
||||
mangled = base54(++cache.cname);
|
||||
} while (!can_mangle(mangled) || (ignore_quoted && mangled in ignored));
|
||||
} while (!can_mangle(mangled) || keep_quoted && mangled in to_keep);
|
||||
}
|
||||
|
||||
cache.props.set(name, mangled);
|
||||
@@ -212,17 +218,17 @@ function mangle_properties(ast, options) {
|
||||
return mangled;
|
||||
}
|
||||
|
||||
function addStrings(node, ignore) {
|
||||
function addStrings(node, keep) {
|
||||
var out = {};
|
||||
try {
|
||||
(function walk(node){
|
||||
node.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_Seq) {
|
||||
walk(node.cdr);
|
||||
if (node instanceof AST_Sequence) {
|
||||
walk(node.expressions[node.expressions.length - 1]);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_String) {
|
||||
add(node.value, ignore);
|
||||
add(node.value, keep);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Conditional) {
|
||||
@@ -240,8 +246,9 @@ function mangle_properties(ast, options) {
|
||||
|
||||
function mangleStrings(node) {
|
||||
return node.transform(new TreeTransformer(function(node){
|
||||
if (node instanceof AST_Seq) {
|
||||
node.cdr = mangleStrings(node.cdr);
|
||||
if (node instanceof AST_Sequence) {
|
||||
var last = node.expressions.length - 1;
|
||||
node.expressions[last] = mangleStrings(node.expressions[last]);
|
||||
}
|
||||
else if (node instanceof AST_String) {
|
||||
node.value = mangle(node.value);
|
||||
@@ -253,5 +260,4 @@ function mangle_properties(ast, options) {
|
||||
return node;
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
125
lib/scope.js
125
lib/scope.js
@@ -76,7 +76,7 @@ SymbolDef.prototype = {
|
||||
else if (!this.mangled_name && !this.unmangleable(options)) {
|
||||
var s = this.scope;
|
||||
var sym = this.orig[0];
|
||||
if (!options.screw_ie8 && sym instanceof AST_SymbolLambda)
|
||||
if (options.ie8 && sym instanceof AST_SymbolLambda)
|
||||
s = s.parent_scope;
|
||||
var def;
|
||||
if (this.defun && (def = this.defun.variables.get(this.name))) {
|
||||
@@ -92,8 +92,8 @@ SymbolDef.prototype = {
|
||||
|
||||
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
options = defaults(options, {
|
||||
screw_ie8: true,
|
||||
cache: null
|
||||
cache: null,
|
||||
ie8: false,
|
||||
});
|
||||
|
||||
// pass 1: setup scope chaining and handle definitions
|
||||
@@ -156,8 +156,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
// later.
|
||||
(node.scope = defun.parent_scope).def_function(node);
|
||||
}
|
||||
else if (node instanceof AST_SymbolVar
|
||||
|| node instanceof AST_SymbolConst) {
|
||||
else if (node instanceof AST_SymbolVar) {
|
||||
defun.def_variable(node);
|
||||
if (defun !== scope) {
|
||||
node.mark_enclosed(options);
|
||||
@@ -220,7 +219,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
self.walk(tw);
|
||||
|
||||
// pass 3: fix up any scoping issue with IE8
|
||||
if (!options.screw_ie8) {
|
||||
if (options.ie8) {
|
||||
self.walk(new TreeWalker(function(node, descend) {
|
||||
if (node instanceof AST_SymbolCatch) {
|
||||
var name = node.name;
|
||||
@@ -268,7 +267,7 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){
|
||||
AST_Lambda.DEFMETHOD("init_scope_vars", function(){
|
||||
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
|
||||
this.uses_arguments = false;
|
||||
this.def_variable(new AST_SymbolVar({
|
||||
this.def_variable(new AST_SymbolFunarg({
|
||||
name: "arguments",
|
||||
start: this.start,
|
||||
end: this.end
|
||||
@@ -325,8 +324,8 @@ AST_Scope.DEFMETHOD("next_mangled", function(options){
|
||||
if (!is_identifier(m)) continue; // skip over "do"
|
||||
|
||||
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not
|
||||
// shadow a name excepted from mangling.
|
||||
if (options.except.indexOf(m) >= 0) continue;
|
||||
// shadow a name reserved from mangling.
|
||||
if (options.reserved.indexOf(m) >= 0) continue;
|
||||
|
||||
// we must ensure that the mangled name does not shadow a name
|
||||
// from some parent scope that is referenced in this or in
|
||||
@@ -361,11 +360,6 @@ AST_Symbol.DEFMETHOD("unmangleable", function(options){
|
||||
return this.definition().unmangleable(options);
|
||||
});
|
||||
|
||||
// property accessors are not mangleable
|
||||
AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){
|
||||
return true;
|
||||
});
|
||||
|
||||
// labels are always mangleable
|
||||
AST_Label.DEFMETHOD("unmangleable", function(){
|
||||
return false;
|
||||
@@ -398,12 +392,11 @@ AST_Symbol.DEFMETHOD("global", function(){
|
||||
|
||||
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
||||
return defaults(options, {
|
||||
except : [],
|
||||
eval : false,
|
||||
sort : false, // Ignored. Flag retained for backwards compatibility.
|
||||
ie8 : false,
|
||||
keep_fnames : false,
|
||||
reserved : [],
|
||||
toplevel : false,
|
||||
screw_ie8 : true,
|
||||
keep_fnames : false
|
||||
});
|
||||
});
|
||||
|
||||
@@ -411,7 +404,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
options = this._default_mangler_options(options);
|
||||
|
||||
// Never mangle arguments
|
||||
options.except.push('arguments');
|
||||
options.reserved.push('arguments');
|
||||
|
||||
// We only need to mangle declaration nodes. Special logic wired
|
||||
// into the code generator will display the mangled name if it's
|
||||
@@ -422,7 +415,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
|
||||
if (options.cache) {
|
||||
this.globals.each(function(symbol){
|
||||
if (options.except.indexOf(symbol.name) < 0) {
|
||||
if (options.reserved.indexOf(symbol.name) < 0) {
|
||||
to_mangle.push(symbol);
|
||||
}
|
||||
});
|
||||
@@ -439,7 +432,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
if (node instanceof AST_Scope) {
|
||||
var p = tw.parent(), a = [];
|
||||
node.variables.each(function(symbol){
|
||||
if (options.except.indexOf(symbol.name) < 0) {
|
||||
if (options.reserved.indexOf(symbol.name) < 0) {
|
||||
a.push(symbol);
|
||||
}
|
||||
});
|
||||
@@ -452,7 +445,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
node.mangled_name = name;
|
||||
return true;
|
||||
}
|
||||
if (options.screw_ie8 && node instanceof AST_SymbolCatch) {
|
||||
if (!options.ie8 && node instanceof AST_SymbolCatch) {
|
||||
to_mangle.push(node.definition());
|
||||
return;
|
||||
}
|
||||
@@ -492,8 +485,6 @@ AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
|
||||
}
|
||||
else if (node instanceof AST_Var)
|
||||
base54.consider("var");
|
||||
else if (node instanceof AST_Const)
|
||||
base54.consider("const");
|
||||
else if (node instanceof AST_Lambda)
|
||||
base54.consider("function");
|
||||
else if (node instanceof AST_For)
|
||||
@@ -573,89 +564,3 @@ var base54 = (function() {
|
||||
};
|
||||
return base54;
|
||||
})();
|
||||
|
||||
AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
|
||||
options = defaults(options, {
|
||||
undeclared : false, // this makes a lot of noise
|
||||
unreferenced : true,
|
||||
assign_to_global : true,
|
||||
func_arguments : true,
|
||||
nested_defuns : true,
|
||||
eval : true
|
||||
});
|
||||
var tw = new TreeWalker(function(node){
|
||||
if (options.undeclared
|
||||
&& node instanceof AST_SymbolRef
|
||||
&& node.undeclared())
|
||||
{
|
||||
// XXX: this also warns about JS standard names,
|
||||
// i.e. Object, Array, parseInt etc. Should add a list of
|
||||
// exceptions.
|
||||
AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", {
|
||||
name: node.name,
|
||||
file: node.start.file,
|
||||
line: node.start.line,
|
||||
col: node.start.col
|
||||
});
|
||||
}
|
||||
if (options.assign_to_global)
|
||||
{
|
||||
var sym = null;
|
||||
if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef)
|
||||
sym = node.left;
|
||||
else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef)
|
||||
sym = node.init;
|
||||
if (sym
|
||||
&& (sym.undeclared()
|
||||
|| (sym.global() && sym.scope !== sym.definition().scope))) {
|
||||
AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", {
|
||||
msg: sym.undeclared() ? "Accidental global?" : "Assignment to global",
|
||||
name: sym.name,
|
||||
file: sym.start.file,
|
||||
line: sym.start.line,
|
||||
col: sym.start.col
|
||||
});
|
||||
}
|
||||
}
|
||||
if (options.eval
|
||||
&& node instanceof AST_SymbolRef
|
||||
&& node.undeclared()
|
||||
&& node.name == "eval") {
|
||||
AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start);
|
||||
}
|
||||
if (options.unreferenced
|
||||
&& (node instanceof AST_SymbolDeclaration || node instanceof AST_Label)
|
||||
&& !(node instanceof AST_SymbolCatch)
|
||||
&& node.unreferenced()) {
|
||||
AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
|
||||
type: node instanceof AST_Label ? "Label" : "Symbol",
|
||||
name: node.name,
|
||||
file: node.start.file,
|
||||
line: node.start.line,
|
||||
col: node.start.col
|
||||
});
|
||||
}
|
||||
if (options.func_arguments
|
||||
&& node instanceof AST_Lambda
|
||||
&& node.uses_arguments) {
|
||||
AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", {
|
||||
name: node.name ? node.name.name : "anonymous",
|
||||
file: node.start.file,
|
||||
line: node.start.line,
|
||||
col: node.start.col
|
||||
});
|
||||
}
|
||||
if (options.nested_defuns
|
||||
&& node instanceof AST_Defun
|
||||
&& !(tw.parent() instanceof AST_Scope)) {
|
||||
AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", {
|
||||
name: node.name.name,
|
||||
type: tw.parent().TYPE,
|
||||
file: node.start.file,
|
||||
line: node.start.line,
|
||||
col: node.start.col
|
||||
});
|
||||
}
|
||||
});
|
||||
this.walk(tw);
|
||||
});
|
||||
|
||||
@@ -174,9 +174,8 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
self.args = do_list(self.args, tw);
|
||||
});
|
||||
|
||||
_(AST_Seq, function(self, tw){
|
||||
self.car = self.car.transform(tw);
|
||||
self.cdr = self.cdr.transform(tw);
|
||||
_(AST_Sequence, function(self, tw){
|
||||
self.expressions = do_list(self.expressions, tw);
|
||||
});
|
||||
|
||||
_(AST_Dot, function(self, tw){
|
||||
|
||||
@@ -346,7 +346,7 @@ function first_in_statement(stack) {
|
||||
for (var i = 0, p; p = stack.parent(i); i++) {
|
||||
if (p instanceof AST_Statement && p.body === node)
|
||||
return true;
|
||||
if ((p instanceof AST_Seq && p.car === node ) ||
|
||||
if ((p instanceof AST_Sequence && p.expressions[0] === node) ||
|
||||
(p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) ||
|
||||
(p instanceof AST_Dot && p.expression === node ) ||
|
||||
(p instanceof AST_Sub && p.expression === node ) ||
|
||||
|
||||
22
package.json
22
package.json
@@ -4,7 +4,7 @@
|
||||
"homepage": "http://lisperator.net/uglifyjs",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "2.8.19",
|
||||
"version": "3.0.8",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
@@ -29,23 +29,13 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"source-map": "~0.5.1",
|
||||
"yargs": "~3.10.0"
|
||||
"commander": "~2.9.0",
|
||||
"source-map": "~0.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"acorn": "~0.6.0",
|
||||
"escodegen": "~1.3.3",
|
||||
"esfuzz": "~0.3.1",
|
||||
"estraverse": "~1.5.1",
|
||||
"mocha": "~2.3.4"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"uglify-to-browserify": "~1.0.0"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
"uglify-to-browserify"
|
||||
]
|
||||
"acorn": "~5.0.3",
|
||||
"mocha": "~2.3.4",
|
||||
"semver": "~5.3.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node test/run-tests.js"
|
||||
|
||||
@@ -7,12 +7,12 @@ var createHash = require("crypto").createHash;
|
||||
var fork = require("child_process").fork;
|
||||
var args = process.argv.slice(2);
|
||||
if (!args.length) {
|
||||
args.push("-mc", "warnings=false");
|
||||
args.push("-mc");
|
||||
}
|
||||
args.push("--stats");
|
||||
var urls = [
|
||||
"https://code.jquery.com/jquery-3.1.1.js",
|
||||
"https://code.angularjs.org/1.6.1/angular.js",
|
||||
"https://code.jquery.com/jquery-3.2.1.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.9.0/math.js",
|
||||
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
|
||||
"https://unpkg.com/react@15.3.2/dist/react.js",
|
||||
@@ -29,11 +29,11 @@ function done() {
|
||||
var info = results[url];
|
||||
console.log();
|
||||
console.log(url);
|
||||
console.log(info.log);
|
||||
var elapsed = 0;
|
||||
info.log.replace(/: ([0-9]+\.[0-9]{3})s/g, function(match, time) {
|
||||
elapsed += parseFloat(time);
|
||||
});
|
||||
console.log(info.log.replace(/Elapsed: ([0-9]+)\s*/g, function(match, time) {
|
||||
elapsed += 1e-3 * parseInt(time);
|
||||
return "";
|
||||
}));
|
||||
console.log("Run-time:", elapsed.toFixed(3), "s");
|
||||
console.log("Original:", info.input, "bytes");
|
||||
console.log("Uglified:", info.output, "bytes");
|
||||
|
||||
67
test/compress/angular-inject.js
vendored
67
test/compress/angular-inject.js
vendored
@@ -1,67 +0,0 @@
|
||||
ng_inject_defun: {
|
||||
options = {
|
||||
angular: true
|
||||
};
|
||||
input: {
|
||||
/*@ngInject*/
|
||||
function Controller(dependency) {
|
||||
return dependency;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function Controller(dependency) {
|
||||
return dependency;
|
||||
}
|
||||
Controller.$inject=['dependency']
|
||||
}
|
||||
}
|
||||
|
||||
ng_inject_assignment: {
|
||||
options = {
|
||||
angular: true
|
||||
};
|
||||
input: {
|
||||
/*@ngInject*/
|
||||
var Controller = function(dependency) {
|
||||
return dependency;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var Controller = function(dependency) {
|
||||
return dependency;
|
||||
}
|
||||
Controller.$inject=['dependency']
|
||||
}
|
||||
}
|
||||
|
||||
ng_inject_inline: {
|
||||
options = {
|
||||
angular: true
|
||||
};
|
||||
input: {
|
||||
angular.module('a').
|
||||
factory('b',
|
||||
/*@ngInject*/
|
||||
function(dependency) {
|
||||
return dependency;
|
||||
}).
|
||||
directive('c',
|
||||
/*@ngInject*/
|
||||
function(anotherDependency) {
|
||||
return anotherDependency;
|
||||
})
|
||||
}
|
||||
expect: {
|
||||
angular.module('a').
|
||||
factory('b',[
|
||||
'dependency',
|
||||
function(dependency) {
|
||||
return dependency;
|
||||
}]).
|
||||
directive('c',[
|
||||
'anotherDependency',
|
||||
function(anotherDependency) {
|
||||
return anotherDependency;
|
||||
}])
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ ascii_only_true: {
|
||||
options = {}
|
||||
beautify = {
|
||||
ascii_only : true,
|
||||
screw_ie8 : true,
|
||||
ie8 : false,
|
||||
beautify : false,
|
||||
}
|
||||
input: {
|
||||
@@ -20,7 +20,7 @@ ascii_only_false: {
|
||||
options = {}
|
||||
beautify = {
|
||||
ascii_only : false,
|
||||
screw_ie8 : true,
|
||||
ie8 : false,
|
||||
beautify : false,
|
||||
}
|
||||
input: {
|
||||
@@ -33,4 +33,3 @@ ascii_only_false: {
|
||||
}
|
||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\08\\0"+"\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ collapse_vars_side_effects_1: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
@@ -68,11 +68,10 @@ collapse_vars_side_effects_1: {
|
||||
log(x, s.charAt(i++), y, 7);
|
||||
}
|
||||
function f4() {
|
||||
var log = console.log.bind(console),
|
||||
i = 10,
|
||||
var i = 10,
|
||||
x = i += 2,
|
||||
y = i += 3;
|
||||
log(x, i += 4, y, i);
|
||||
console.log.bind(console)(x, i += 4, y, i);
|
||||
}
|
||||
f1(), f2(), f3(), f4();
|
||||
}
|
||||
@@ -151,7 +150,7 @@ collapse_vars_issue_721: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
define(["require", "exports", 'handlebars'], function (require, exports, hb) {
|
||||
@@ -217,7 +216,7 @@ collapse_vars_properties: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1(obj) {
|
||||
@@ -244,7 +243,7 @@ collapse_vars_if: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
@@ -294,7 +293,7 @@ collapse_vars_while: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:false, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1(y) {
|
||||
@@ -393,9 +392,9 @@ collapse_vars_do_while: {
|
||||
}
|
||||
function f3(y) {
|
||||
function fn(n) { console.log(n); }
|
||||
var a = 2;
|
||||
var a = 2, x = 7;
|
||||
do {
|
||||
fn(a = 7);
|
||||
fn(a = x);
|
||||
break;
|
||||
} while (y);
|
||||
}
|
||||
@@ -468,8 +467,9 @@ collapse_vars_do_while_drop_assign: {
|
||||
}
|
||||
function f3(y) {
|
||||
function fn(n) { console.log(n); }
|
||||
var x = 7;
|
||||
do {
|
||||
fn(7);
|
||||
fn(x);
|
||||
break;
|
||||
} while (y);
|
||||
}
|
||||
@@ -583,8 +583,8 @@ collapse_vars_assignment: {
|
||||
return a = a;
|
||||
}
|
||||
function f1(c) {
|
||||
const a = 3 / c;
|
||||
const b = 1 - a;
|
||||
var a = 3 / c;
|
||||
var b = 1 - a;
|
||||
return b;
|
||||
}
|
||||
function f2(c) {
|
||||
@@ -670,8 +670,8 @@ collapse_vars_lvalues: {
|
||||
function f4(x) { var a = (x -= 3); return x + a; }
|
||||
function f5(x) { var w = e1(), v = e2(), c = v = --x; return (w = x) - c; }
|
||||
function f6(x) { var w = e1(), v = e2(); return (v = --x) - (w = x); }
|
||||
function f7(x) { var w = e1(), v = e2(), c = v - x; return (w = x) - c; }
|
||||
function f8(x) { var w = e1(), v = e2(); return (w = x) - (v - x); }
|
||||
function f7(x) { var w = e1(); return (w = x) - (e2() - x); }
|
||||
function f8(x) { var w = e1(); return (w = x) - (e2() - x); }
|
||||
function f9(x) { var w = e1(); return e2() - x - (w = x); }
|
||||
}
|
||||
}
|
||||
@@ -700,10 +700,10 @@ collapse_vars_lvalues_drop_assign: {
|
||||
function f2(x) { var z = x, a = ++z; return z += a; }
|
||||
function f3(x) { var a = (x -= 3); return x + a; }
|
||||
function f4(x) { var a = (x -= 3); return x + a; }
|
||||
function f5(x) { var v = (e1(), e2()), c = v = --x; return x - c; }
|
||||
function f5(x) { e1(); var v = e2(), c = v = --x; return x - c; }
|
||||
function f6(x) { e1(), e2(); return --x - x; }
|
||||
function f7(x) { var v = (e1(), e2()), c = v - x; return x - c; }
|
||||
function f8(x) { var v = (e1(), e2()); return x - (v - x); }
|
||||
function f7(x) { e1(); return x - (e2() - x); }
|
||||
function f8(x) { e1(); return x - (e2() - x); }
|
||||
function f9(x) { e1(); return e2() - x - x; }
|
||||
}
|
||||
}
|
||||
@@ -712,7 +712,7 @@ collapse_vars_misc1: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f0(o, a, h) {
|
||||
@@ -724,10 +724,10 @@ collapse_vars_misc1: {
|
||||
return t;
|
||||
}
|
||||
function f1(x) { var y = 5 - x; return y; }
|
||||
function f2(x) { const z = foo(), y = z / (5 - x); return y; }
|
||||
function f2(x) { var z = foo(), y = z / (5 - x); return y; }
|
||||
function f3(x) { var z = foo(), y = (5 - x) / z; return y; }
|
||||
function f4(x) { var z = foo(), y = (5 - u) / z; return y; }
|
||||
function f5(x) { const z = foo(), y = (5 - window.x) / z; return y; }
|
||||
function f5(x) { var z = foo(), y = (5 - window.x) / z; return y; }
|
||||
function f6() { var b = window.a * window.z; return b && zap(); }
|
||||
function f7() { var b = window.a * window.z; return b + b; }
|
||||
function f8() { var b = window.a * window.z; var c = b + 5; return b + c; }
|
||||
@@ -744,7 +744,7 @@ collapse_vars_misc1: {
|
||||
function f2(x) { return foo() / (5 - x) }
|
||||
function f3(x) { return (5 - x) / foo() }
|
||||
function f4(x) { var z = foo(); return (5 - u) / z }
|
||||
function f5(x) { const z = foo(); return (5 - window.x) / z }
|
||||
function f5(x) { var z = foo(); return (5 - window.x) / z }
|
||||
function f6() { return window.a * window.z && zap() }
|
||||
function f7() { var b = window.a * window.z; return b + b }
|
||||
function f8() { var b = window.a * window.z; return b + (b + 5) }
|
||||
@@ -789,7 +789,7 @@ collapse_vars_repeated: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
@@ -812,19 +812,17 @@ collapse_vars_repeated: {
|
||||
}
|
||||
expect: {
|
||||
function f1() {
|
||||
return -3
|
||||
return -3;
|
||||
}
|
||||
function f2(x) {
|
||||
return x
|
||||
return x;
|
||||
}
|
||||
(function(x){
|
||||
var a = "GOOD" + x, e = "BAD", e = a;
|
||||
console.log(e + "!");
|
||||
})("!"),
|
||||
console.log("GOOD!!");
|
||||
})(),
|
||||
(function(x){
|
||||
var a = "GOOD" + x, e = "BAD" + x, e = a;
|
||||
console.log(e + "!");
|
||||
})("!");
|
||||
console.log("GOOD!!");
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
@@ -833,7 +831,7 @@ collapse_vars_closures: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function constant_vars_can_be_replaced_in_any_scope() {
|
||||
@@ -923,7 +921,7 @@ collapse_vars_try: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
@@ -1048,10 +1046,9 @@ collapse_vars_object: {
|
||||
}
|
||||
expect: {
|
||||
function f0(x, y) {
|
||||
var z = x + y;
|
||||
return {
|
||||
get b() { return 7; },
|
||||
r: z
|
||||
r: x + y
|
||||
};
|
||||
}
|
||||
function f1(x, y) {
|
||||
@@ -1121,7 +1118,7 @@ collapse_vars_constants: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1(x) {
|
||||
@@ -1159,7 +1156,7 @@ collapse_vars_arguments: {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||
toplevel:true
|
||||
toplevel:true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
var outer = function() {
|
||||
@@ -1286,6 +1283,7 @@ collapse_vars_regexp: {
|
||||
join_vars: true,
|
||||
cascade: true,
|
||||
side_effects: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
@@ -1319,8 +1317,8 @@ collapse_vars_regexp: {
|
||||
};
|
||||
}
|
||||
(function(){
|
||||
var result, s = "acdabcdeabbb", rx = /ab*/g;
|
||||
while (result = rx.exec(s))
|
||||
var result, rx = /ab*/g;
|
||||
while (result = rx.exec("acdabcdeabbb"))
|
||||
console.log(result[0]);
|
||||
})();
|
||||
}
|
||||
@@ -1344,7 +1342,10 @@ issue_1537: {
|
||||
issue_1562: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var v = 1, B = 2;
|
||||
@@ -1363,14 +1364,11 @@ issue_1562: {
|
||||
var v = 1;
|
||||
for (v in objs) f(2);
|
||||
|
||||
var x = 3;
|
||||
while(x + 2) bar(10);
|
||||
while(5) bar(10);
|
||||
|
||||
var y = 4;
|
||||
do bar(20); while(y + 2);
|
||||
do bar(20); while(6);
|
||||
|
||||
var z = 5;
|
||||
for (; f(z + 2) ;) bar(30);
|
||||
for (; f(7) ;) bar(30);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1573,6 +1571,7 @@ var_side_effects_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
pure_getters: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var print = console.log.bind(console);
|
||||
@@ -1591,3 +1590,599 @@ var_side_effects_3: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
reduce_vars_assign: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
var a = 1;
|
||||
a = [].length,
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
var a = 1;
|
||||
a = [].length,
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
iife_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var log = function(x) {
|
||||
console.log(x);
|
||||
}, foo = bar();
|
||||
log(foo);
|
||||
}
|
||||
expect: {
|
||||
(function(x) {
|
||||
console.log(x);
|
||||
})(bar());
|
||||
}
|
||||
}
|
||||
|
||||
iife_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_vars: false,
|
||||
toplevel: true,
|
||||
unused: false,
|
||||
}
|
||||
input: {
|
||||
var foo = bar();
|
||||
!function(x) {
|
||||
console.log(x);
|
||||
}(foo);
|
||||
}
|
||||
expect: {
|
||||
!function(x) {
|
||||
console.log(x);
|
||||
}(bar());
|
||||
}
|
||||
}
|
||||
|
||||
var_defs: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
}
|
||||
input: {
|
||||
var f1 = function(x, y) {
|
||||
var a, b, r = x + y, q = r * r, z = q - r, a = z, b = 7;
|
||||
console.log(a + b);
|
||||
};
|
||||
f1("1", 0);
|
||||
}
|
||||
expect: {
|
||||
var f1 = function(x, y) {
|
||||
var r = x + y, a = r * r - r, b = 7;
|
||||
console.log(a + b);
|
||||
};
|
||||
f1("1", 0);
|
||||
}
|
||||
expect_stdout: "97"
|
||||
}
|
||||
|
||||
assignment: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a;
|
||||
a = x;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for_init: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y) {
|
||||
var a = x;
|
||||
var b = y;
|
||||
for (a; b;);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(x, y) {
|
||||
var b = y;
|
||||
for (x; b;);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch_case: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y, z) {
|
||||
var a = x();
|
||||
var b = y();
|
||||
var c = z;
|
||||
switch (a) {
|
||||
default: d();
|
||||
case b: e();
|
||||
case c: f();
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(x, y, z) {
|
||||
var c = z;
|
||||
switch (x()) {
|
||||
default: d();
|
||||
case y(): e();
|
||||
case c: f();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_27: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(jQuery) {
|
||||
var $;
|
||||
$ = jQuery;
|
||||
$("body").addClass("foo");
|
||||
})(jQuery);
|
||||
}
|
||||
expect: {
|
||||
(function(jQuery) {
|
||||
jQuery("body").addClass("foo");
|
||||
})(jQuery);
|
||||
}
|
||||
}
|
||||
|
||||
modified: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f1(b) {
|
||||
var a = b;
|
||||
return b + a;
|
||||
}
|
||||
function f2(b) {
|
||||
var a = b;
|
||||
return b++ + a;
|
||||
}
|
||||
function f3(b) {
|
||||
var a = b++;
|
||||
return b + a;
|
||||
}
|
||||
function f4(b) {
|
||||
var a = b++;
|
||||
return b++ + a;
|
||||
}
|
||||
function f5(b) {
|
||||
var a = function() {
|
||||
return b;
|
||||
}();
|
||||
return b++ + a;
|
||||
}
|
||||
console.log(f1(1), f2(1), f3(1), f4(1), f5(1));
|
||||
}
|
||||
expect: {
|
||||
function f1(b) {
|
||||
return b + b;
|
||||
}
|
||||
function f2(b) {
|
||||
var a = b;
|
||||
return b++ + a;
|
||||
}
|
||||
function f3(b) {
|
||||
var a = b++;
|
||||
return b + a;
|
||||
}
|
||||
function f4(b) {
|
||||
var a = b++;
|
||||
return b++ + a;
|
||||
}
|
||||
function f5(b) {
|
||||
var a = function() {
|
||||
return b;
|
||||
}();
|
||||
return b++ + a;
|
||||
}
|
||||
console.log(f1(1), f2(1), f3(1), f4(1), f5(1));
|
||||
}
|
||||
expect_stdout: "2 2 3 3 2"
|
||||
}
|
||||
|
||||
issue_1858: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
pure_getters: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(x) {
|
||||
var a = {}, b = a.b = x;
|
||||
return a.b + b;
|
||||
}(1));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(x) {
|
||||
var a = {}, b = a.b = x;
|
||||
return a.b + b;
|
||||
}(1));
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
anonymous_function: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f(a) {
|
||||
f ^= 0;
|
||||
return f * a;
|
||||
}(1));
|
||||
}
|
||||
expect: {
|
||||
console.log(function f(a) {
|
||||
f ^= 0;
|
||||
return f * a;
|
||||
}(1));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
side_effects_property: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a = [];
|
||||
var b = 0;
|
||||
a[b++] = function() { return 42;};
|
||||
var c = a[b++]();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var a = [];
|
||||
var b = 0;
|
||||
a[b++] = function() { return 42;};
|
||||
var c = a[b++]();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
undeclared: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y) {
|
||||
var a;
|
||||
a = x;
|
||||
b = y;
|
||||
return b + a;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(x, y) {
|
||||
var a;
|
||||
a = x;
|
||||
b = y;
|
||||
return b + a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ref_scope: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var a = 1, b = 2, c = 3;
|
||||
var a = c++, b = b /= a;
|
||||
return function() {
|
||||
return a;
|
||||
}() + b;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var a = 1, b = 2, c = 3;
|
||||
b = b /= a = c++;
|
||||
return function() {
|
||||
return a;
|
||||
}() + b;
|
||||
}());
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
chained_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a = 2;
|
||||
var a = 3 / a;
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 3 / (a = 2);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
chained_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
var a = 2;
|
||||
a = 3 / a;
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
a = 3 / (a = 2);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
chained_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a, b) {
|
||||
var c = a, c = b;
|
||||
b++;
|
||||
return c;
|
||||
}(1, 2));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a, b) {
|
||||
var c = a, c = b;
|
||||
b++;
|
||||
return c;
|
||||
}(1, 2));
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
boolean_binary_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
a++;
|
||||
(function() {} || a || 3).toString();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
a++;
|
||||
(function() {} || a || 3).toString();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
boolean_binary_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var c = 0;
|
||||
c += 1;
|
||||
(function() {
|
||||
c = 1 + c;
|
||||
} || 9).toString();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = 0;
|
||||
c += 1;
|
||||
(function() {
|
||||
c = 1 + c;
|
||||
} || 9).toString();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
inner_lvalues: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a, b = 10;
|
||||
var a = (--b || a || 3).toString(), c = --b + -a;
|
||||
console.log(null, a, b);
|
||||
}
|
||||
expect: {
|
||||
var a, b = 10;
|
||||
var a = (--b || a || 3).toString(), c = --b + -a;
|
||||
console.log(null, a, b);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
double_def: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a = x, a = a && y;
|
||||
a();
|
||||
}
|
||||
expect: {
|
||||
var a = x;
|
||||
(a = a && y)();
|
||||
}
|
||||
}
|
||||
|
||||
toplevel_single_reference: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
for (var b in x) {
|
||||
var a = b;
|
||||
b(a);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
for (var b in x)
|
||||
b(a = b);
|
||||
}
|
||||
}
|
||||
|
||||
unused_orig: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
console.log(function(b) {
|
||||
var a;
|
||||
var c = b;
|
||||
for (var d in c) {
|
||||
var a = c[0];
|
||||
return --b + a;
|
||||
}
|
||||
try {
|
||||
} catch (e) {
|
||||
--b + a;
|
||||
}
|
||||
a && a.NaN;
|
||||
}([2]), a);
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
console.log(function(b) {
|
||||
var c = b;
|
||||
for (var d in c) {
|
||||
var a = c[0];
|
||||
return --b + a;
|
||||
}
|
||||
a && a.NaN;
|
||||
}([2]), a);
|
||||
}
|
||||
expect_stdout: "3 1"
|
||||
}
|
||||
|
||||
issue_315: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(s) {
|
||||
var w, _i, _len, _ref, _results;
|
||||
_ref = s.trim().split(" ");
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
w = _ref[_i];
|
||||
_results.push(w.toLowerCase());
|
||||
}
|
||||
return _results;
|
||||
}("test"));
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var w, _i, _len, _ref, _results;
|
||||
for (_results = [], _i = 0, _len = (_ref = "test".trim().split(" ")).length; _i < _len ; _i++)
|
||||
w = _ref[_i], _results.push(w.toLowerCase());
|
||||
return _results;
|
||||
}());
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
lvalues_def: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b = 1;
|
||||
var a = b++, b = +function() {}();
|
||||
a && a[a++];
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b = 1;
|
||||
var a = b++, b = +void 0;
|
||||
a && a[a++];
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
compound_assignment: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
a = 1;
|
||||
a += a + 2;
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
a = 1;
|
||||
a += a + 2;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "4"
|
||||
}
|
||||
|
||||
@@ -840,8 +840,8 @@ equality_conditionals_false: {
|
||||
f(0, true, 0),
|
||||
f(1, 2, 3),
|
||||
f(1, null, 3),
|
||||
f(0/0),
|
||||
f(0/0, "foo");
|
||||
f(NaN),
|
||||
f(NaN, "foo");
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
@@ -888,8 +888,8 @@ equality_conditionals_true: {
|
||||
f(0, true, 0),
|
||||
f(1, 2, 3),
|
||||
f(1, null, 3),
|
||||
f(0/0),
|
||||
f(0/0, "foo");
|
||||
f(NaN),
|
||||
f(NaN, "foo");
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
@@ -962,3 +962,56 @@ condition_symbol_matches_consequent: {
|
||||
}
|
||||
expect_stdout: "3 7 true 4"
|
||||
}
|
||||
|
||||
delete_conditional_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (1 ? undefined : x));
|
||||
console.log(delete (1 ? void 0 : x));
|
||||
console.log(delete (1 ? Infinity : x));
|
||||
console.log(delete (1 ? 1 / 0 : x));
|
||||
console.log(delete (1 ? NaN : x));
|
||||
console.log(delete (1 ? 0 / 0 : x));
|
||||
}
|
||||
expect: {
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_conditional_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
keep_infinity: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (0 ? x : undefined));
|
||||
console.log(delete (0 ? x : void 0));
|
||||
console.log(delete (0 ? x : Infinity));
|
||||
console.log(delete (0 ? x : 1 / 0));
|
||||
console.log(delete (0 ? x : NaN));
|
||||
console.log(delete (0 ? x : 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
issue_1191: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
function foo(rot) {
|
||||
const rotTol = 5;
|
||||
if (rot < -rotTol || rot > rotTol)
|
||||
bar();
|
||||
baz();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(rot) {
|
||||
(rot < -5 || rot > 5) && bar();
|
||||
baz();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1194: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
function f1() {const a = "X"; return a + a;}
|
||||
function f2() {const aa = "X"; return aa + aa;}
|
||||
function f3() {const aaa = "X"; return aaa + aaa;}
|
||||
}
|
||||
expect: {
|
||||
function f1(){return"XX"}
|
||||
function f2(){return"XX"}
|
||||
function f3(){return"XX"}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1396: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
function foo(a) {
|
||||
const VALUE = 1;
|
||||
console.log(2 | VALUE);
|
||||
console.log(VALUE + 1);
|
||||
console.log(VALUE);
|
||||
console.log(a & VALUE);
|
||||
}
|
||||
function bar() {
|
||||
const s = "01234567890123456789";
|
||||
console.log(s + s + s + s + s);
|
||||
|
||||
const CONSTANT = "abc";
|
||||
console.log(CONSTANT + CONSTANT + CONSTANT + CONSTANT + CONSTANT);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(a) {
|
||||
console.log(3);
|
||||
console.log(2);
|
||||
console.log(1);
|
||||
console.log(1 & a);
|
||||
}
|
||||
function bar() {
|
||||
const s = "01234567890123456789";
|
||||
console.log(s + s + s + s + s);
|
||||
|
||||
console.log("abcabcabcabcabc");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unused_regexp_literal: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
}
|
||||
input: {
|
||||
function f(){ var a = /b/; }
|
||||
}
|
||||
expect: {
|
||||
function f(){}
|
||||
}
|
||||
}
|
||||
|
||||
regexp_literal_not_const: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
(function(){
|
||||
var result;
|
||||
const s = 'acdabcdeabbb';
|
||||
const REGEXP_LITERAL = /ab*/g;
|
||||
while (result = REGEXP_LITERAL.exec(s)) {
|
||||
console.log(result[0]);
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var result;
|
||||
const REGEXP_LITERAL = /ab*/g;
|
||||
while (result = REGEXP_LITERAL.exec("acdabcdeabbb")) console.log(result[0]);
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
@@ -90,131 +90,6 @@ dead_code_constant_boolean_should_warn_more: {
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dead_code_const_declaration: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
const CONST_FOO = false;
|
||||
if (CONST_FOO) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
const CONST_FOO = !1;
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dead_code_const_annotation: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
toplevel : true,
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
/** @const */ var CONST_FOO_ANN = false;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
var CONST_FOO_ANN = !1;
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dead_code_const_annotation_regex: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
// @constraint this shouldn't be a constant
|
||||
var CONST_FOO_ANN = false;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("reachable");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
var CONST_FOO_ANN = !1;
|
||||
CONST_FOO_ANN && console.log('reachable');
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dead_code_const_annotation_complex_scope: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
toplevel : true,
|
||||
};
|
||||
input: {
|
||||
var unused_var;
|
||||
/** @const */ var test = 'test';
|
||||
// @const
|
||||
var CONST_FOO_ANN = false;
|
||||
var unused_var_2;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
if (test === 'test') {
|
||||
var beef = 'good';
|
||||
/** @const */ var meat = 'beef';
|
||||
var pork = 'bad';
|
||||
if (meat === 'pork') {
|
||||
console.log('also unreachable');
|
||||
} else if (pork === 'good') {
|
||||
console.log('reached, not const');
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused_var;
|
||||
var test = 'test';
|
||||
var CONST_FOO_ANN = !1;
|
||||
var unused_var_2;
|
||||
var moo;
|
||||
function bar() {}
|
||||
var beef = 'good';
|
||||
var meat = 'beef';
|
||||
var pork = 'bad';
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
try_catch_finally: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
@@ -256,3 +131,19 @@ try_catch_finally: {
|
||||
"1",
|
||||
]
|
||||
}
|
||||
|
||||
accessor: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
get a() {},
|
||||
set a(v){
|
||||
this.b = 2;
|
||||
},
|
||||
b: 1
|
||||
});
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
@@ -649,37 +649,6 @@ drop_value: {
|
||||
}
|
||||
}
|
||||
|
||||
const_assign: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
const b = 2;
|
||||
return 1 + b;
|
||||
}
|
||||
|
||||
function g() {
|
||||
const b = 2;
|
||||
b = 3;
|
||||
return 1 + b;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
function g() {
|
||||
const b = 2;
|
||||
b = 3;
|
||||
return 1 + b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1539: {
|
||||
options = {
|
||||
cascade: true,
|
||||
@@ -816,10 +785,6 @@ issue_1709: {
|
||||
var x = 1;
|
||||
return x;
|
||||
}(),
|
||||
function y() {
|
||||
const y = 2;
|
||||
return y;
|
||||
}(),
|
||||
function z() {
|
||||
function z() {}
|
||||
return z;
|
||||
@@ -832,10 +797,6 @@ issue_1709: {
|
||||
var x = 1;
|
||||
return x;
|
||||
}(),
|
||||
function() {
|
||||
const y = 2;
|
||||
return y;
|
||||
}(),
|
||||
function() {
|
||||
function z() {}
|
||||
return z;
|
||||
@@ -935,7 +896,8 @@ issue_1715_3: {
|
||||
try {
|
||||
console;
|
||||
} catch (a) {
|
||||
var a = x();
|
||||
var a;
|
||||
x();
|
||||
}
|
||||
}
|
||||
f();
|
||||
@@ -974,3 +936,175 @@ issue_1715_4: {
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
delete_assign_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
console.log(delete (a = undefined));
|
||||
console.log(delete (a = void 0));
|
||||
console.log(delete (a = Infinity));
|
||||
console.log(delete (a = 1 / 0));
|
||||
console.log(delete (a = NaN));
|
||||
console.log(delete (a = 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log((void 0, !0));
|
||||
console.log((void 0, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((NaN, !0));
|
||||
console.log((0 / 0, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_assign_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
keep_infinity: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
console.log(delete (a = undefined));
|
||||
console.log(delete (a = void 0));
|
||||
console.log(delete (a = Infinity));
|
||||
console.log(delete (a = 1 / 0));
|
||||
console.log(delete (a = NaN));
|
||||
console.log(delete (a = 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log((void 0, !0));
|
||||
console.log((void 0, !0));
|
||||
console.log((Infinity, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((NaN, !0));
|
||||
console.log((0 / 0, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
drop_var: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
console.log(a, b);
|
||||
var a = 1, b = 2;
|
||||
console.log(a, b);
|
||||
var a = 3;
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
console.log(a, b);
|
||||
var a = 1, b = 2;
|
||||
console.log(a, b);
|
||||
a = 3;
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: [
|
||||
"undefined undefined",
|
||||
"1 2",
|
||||
"3 2",
|
||||
]
|
||||
}
|
||||
|
||||
issue_1830_1: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
L: for (var b = console.log(1); !1;) continue L;
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
L: for (console.log(1); !1;) continue L;
|
||||
}();
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_1830_2: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
L: for (var a = 1, b = console.log(a); --a;) continue L;
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
var a = 1;
|
||||
L: for (console.log(a); --a;) continue L;
|
||||
}();
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_1838: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
loops: true,
|
||||
unused: true,
|
||||
}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var b = a;
|
||||
while (c);
|
||||
}
|
||||
}
|
||||
expect_exact: [
|
||||
"function f() {",
|
||||
" for (a; c; ) ;",
|
||||
"}",
|
||||
]
|
||||
}
|
||||
|
||||
var_catch_toplevel: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
negate_iife: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
a--;
|
||||
try {
|
||||
a++;
|
||||
} catch(a) {
|
||||
if (a) var a;
|
||||
var a = 10;
|
||||
}
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
a--;
|
||||
try {
|
||||
a++;
|
||||
} catch(a) {
|
||||
var a;
|
||||
}
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ and: {
|
||||
a = 7;
|
||||
|
||||
a = false;
|
||||
a = 0/0;
|
||||
a = NaN;
|
||||
a = 0;
|
||||
a = void 0;
|
||||
a = null;
|
||||
@@ -67,7 +67,7 @@ and: {
|
||||
a = 6 << condition && -4.5;
|
||||
|
||||
a = condition && false;
|
||||
a = console.log("b") && 0/0;
|
||||
a = console.log("b") && NaN;
|
||||
a = console.log("c") && 0;
|
||||
a = 2 * condition && void 0;
|
||||
a = condition + 3 && null;
|
||||
@@ -149,7 +149,7 @@ or: {
|
||||
a = 6 << condition || -4.5;
|
||||
|
||||
a = condition || false;
|
||||
a = console.log("b") || 0/0;
|
||||
a = console.log("b") || NaN;
|
||||
a = console.log("c") || 0;
|
||||
a = 2 * condition || void 0;
|
||||
a = condition + 3 || null;
|
||||
@@ -533,7 +533,7 @@ unsafe_array: {
|
||||
[1, 2, 3, a][0] + 1,
|
||||
2,
|
||||
3,
|
||||
0/0,
|
||||
NaN,
|
||||
"1,21",
|
||||
5,
|
||||
(void 0)[1] + 1
|
||||
@@ -645,16 +645,17 @@ call_args: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
const a = 1;
|
||||
var a = 1;
|
||||
console.log(a);
|
||||
+function(a) {
|
||||
return a;
|
||||
}(a);
|
||||
}
|
||||
expect: {
|
||||
const a = 1;
|
||||
var a = 1;
|
||||
console.log(1);
|
||||
+(1, 1);
|
||||
}
|
||||
@@ -666,17 +667,17 @@ call_args_drop_param: {
|
||||
evaluate: true,
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
const a = 1;
|
||||
var a = 1;
|
||||
console.log(a);
|
||||
+function(a) {
|
||||
return a;
|
||||
}(a, b);
|
||||
}
|
||||
expect: {
|
||||
const a = 1;
|
||||
console.log(1);
|
||||
+(b, 1);
|
||||
}
|
||||
@@ -802,3 +803,190 @@ issue_1649: {
|
||||
}
|
||||
expect_stdout: "-2";
|
||||
}
|
||||
|
||||
issue_1760_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
!function(a) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (NaN) {
|
||||
a = +"foo";
|
||||
}
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function(a) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (NaN) {
|
||||
a = 0 / 0;
|
||||
}
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
issue_1760_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_infinity: true,
|
||||
}
|
||||
input: {
|
||||
!function(a) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (Infinity) {
|
||||
a = 123456789 / 0;
|
||||
}
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function(a) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (Infinity) {
|
||||
a = 1 / 0;
|
||||
}
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "Infinity"
|
||||
}
|
||||
|
||||
delete_expr_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete undefined);
|
||||
console.log(delete void 0);
|
||||
console.log(delete Infinity);
|
||||
console.log(delete (1 / 0));
|
||||
console.log(delete NaN);
|
||||
console.log(delete (0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log(delete undefined);
|
||||
console.log((void 0, !0));
|
||||
console.log(delete Infinity);
|
||||
console.log((1 / 0, !0));
|
||||
console.log(delete NaN);
|
||||
console.log((0 / 0, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_expr_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
keep_infinity: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete undefined);
|
||||
console.log(delete void 0);
|
||||
console.log(delete Infinity);
|
||||
console.log(delete (1 / 0));
|
||||
console.log(delete NaN);
|
||||
console.log(delete (0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log(delete undefined);
|
||||
console.log((void 0, !0));
|
||||
console.log(delete Infinity);
|
||||
console.log((1 / 0, !0));
|
||||
console.log(delete NaN);
|
||||
console.log((0 / 0, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_binary_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (true && undefined));
|
||||
console.log(delete (true && void 0));
|
||||
console.log(delete (true && Infinity));
|
||||
console.log(delete (true && (1 / 0)));
|
||||
console.log(delete (true && NaN));
|
||||
console.log(delete (true && (0 / 0)));
|
||||
}
|
||||
expect: {
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_binary_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
keep_infinity: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (false || undefined));
|
||||
console.log(delete (false || void 0));
|
||||
console.log(delete (false || Infinity));
|
||||
console.log(delete (false || (1 / 0)));
|
||||
console.log(delete (false || NaN));
|
||||
console.log(delete (false || (0 / 0)));
|
||||
}
|
||||
expect: {
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
Infinity_NaN_undefined_LHS: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
Infinity = Infinity;
|
||||
++Infinity;
|
||||
Infinity--;
|
||||
NaN *= NaN;
|
||||
++NaN;
|
||||
NaN--;
|
||||
undefined |= undefined;
|
||||
++undefined;
|
||||
undefined--;
|
||||
}
|
||||
}
|
||||
expect_exact: [
|
||||
"function f() {",
|
||||
" Infinity = 1 / 0;",
|
||||
" ++Infinity;",
|
||||
" Infinity--;",
|
||||
" NaN *= NaN;",
|
||||
" ++NaN;",
|
||||
" NaN--;",
|
||||
" undefined |= void 0;",
|
||||
" ++undefined;",
|
||||
" undefined--;",
|
||||
"}",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -93,3 +93,77 @@ issue_485_crashing_1530: {
|
||||
this, void 0;
|
||||
}
|
||||
}
|
||||
|
||||
issue_1841_1: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var b = 10;
|
||||
!function(arg) {
|
||||
for (var key in "hi")
|
||||
var n = arg.baz, n = [ b = 42 ];
|
||||
}(--b);
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var b = 10;
|
||||
!function() {
|
||||
for (var key in "hi")
|
||||
b = 42;
|
||||
}(--b);
|
||||
console.log(b);
|
||||
}
|
||||
expect_exact: "42"
|
||||
}
|
||||
|
||||
issue_1841_2: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
pure_getters: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var b = 10;
|
||||
!function(arg) {
|
||||
for (var key in "hi")
|
||||
var n = arg.baz, n = [ b = 42 ];
|
||||
}(--b);
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var b = 10;
|
||||
!function(arg) {
|
||||
for (var key in "hi")
|
||||
arg.baz, b = 42;
|
||||
}(--b);
|
||||
console.log(b);
|
||||
}
|
||||
expect_exact: "42"
|
||||
}
|
||||
|
||||
function_returning_constant_literal: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
toplevel: true,
|
||||
evaluate: true,
|
||||
cascade: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function greeter() {
|
||||
return { message: 'Hello there' };
|
||||
}
|
||||
var greeting = greeter();
|
||||
console.log(greeting.message);
|
||||
}
|
||||
expect: {
|
||||
console.log("Hello there");
|
||||
}
|
||||
expect_stdout: "Hello there"
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ mixed: {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
const FOO = { BAR: 0 };
|
||||
var FOO = { BAR: 0 };
|
||||
console.log(FOO.BAR);
|
||||
console.log(++CONFIG.DEBUG);
|
||||
console.log(++CONFIG.VALUE);
|
||||
@@ -130,7 +130,7 @@ mixed: {
|
||||
console.log(CONFIG);
|
||||
}
|
||||
expect: {
|
||||
const FOO = { BAR: 0 };
|
||||
var FOO = { BAR: 0 };
|
||||
console.log("moo");
|
||||
console.log(++CONFIG.DEBUG);
|
||||
console.log(++CONFIG.VALUE);
|
||||
@@ -145,3 +145,18 @@ mixed: {
|
||||
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:129,8]',
|
||||
]
|
||||
}
|
||||
|
||||
issue_1801: {
|
||||
options = {
|
||||
booleans: true,
|
||||
global_defs: {
|
||||
"CONFIG.FOO.BAR": true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
console.log(CONFIG.FOO.BAR);
|
||||
}
|
||||
expect: {
|
||||
console.log(!0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,3 @@
|
||||
const_declaration: {
|
||||
options = {
|
||||
evaluate: true
|
||||
};
|
||||
|
||||
input: {
|
||||
const goog = goog || {};
|
||||
}
|
||||
expect: {
|
||||
const goog = goog || {};
|
||||
}
|
||||
}
|
||||
|
||||
const_pragma: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
|
||||
@@ -193,6 +193,7 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
|
||||
cascade: true,
|
||||
side_effects: true,
|
||||
sequences: false,
|
||||
keep_infinity: false,
|
||||
}
|
||||
input: {
|
||||
var f = console.log;
|
||||
@@ -224,10 +225,73 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
|
||||
};
|
||||
if (o) {
|
||||
f(void 0, void 0);
|
||||
f(0/0, 0/0);
|
||||
f(NaN, NaN);
|
||||
f(1/0, 1/0);
|
||||
f(-1/0, -1/0);
|
||||
f(0/0, 0/0);
|
||||
f(NaN, NaN);
|
||||
}
|
||||
with (o) {
|
||||
f(undefined, void 0);
|
||||
f(NaN, 0/0);
|
||||
f(Infinity, 1/0);
|
||||
f(-Infinity, -1/0);
|
||||
f(9 + undefined, 9 + void 0);
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
assorted_Infinity_NaN_undefined_in_with_scope_keep_infinity: {
|
||||
options = {
|
||||
unused: true,
|
||||
evaluate: true,
|
||||
dead_code: true,
|
||||
conditionals: true,
|
||||
comparisons: true,
|
||||
booleans: true,
|
||||
hoist_funs: true,
|
||||
keep_fargs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
cascade: true,
|
||||
side_effects: true,
|
||||
sequences: false,
|
||||
keep_infinity: true,
|
||||
}
|
||||
input: {
|
||||
var f = console.log;
|
||||
var o = {
|
||||
undefined : 3,
|
||||
NaN : 4,
|
||||
Infinity : 5,
|
||||
};
|
||||
if (o) {
|
||||
f(undefined, void 0);
|
||||
f(NaN, 0/0);
|
||||
f(Infinity, 1/0);
|
||||
f(-Infinity, -(1/0));
|
||||
f(2 + 7 + undefined, 2 + 7 + void 0);
|
||||
}
|
||||
with (o) {
|
||||
f(undefined, void 0);
|
||||
f(NaN, 0/0);
|
||||
f(Infinity, 1/0);
|
||||
f(-Infinity, -(1/0));
|
||||
f(2 + 7 + undefined, 2 + 7 + void 0);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var f = console.log, o = {
|
||||
undefined : 3,
|
||||
NaN : 4,
|
||||
Infinity : 5
|
||||
};
|
||||
if (o) {
|
||||
f(void 0, void 0);
|
||||
f(NaN, NaN);
|
||||
f(Infinity, 1/0);
|
||||
f(-Infinity, -1/0);
|
||||
f(NaN, NaN);
|
||||
}
|
||||
with (o) {
|
||||
f(undefined, void 0);
|
||||
|
||||
@@ -154,12 +154,12 @@ should_warn: {
|
||||
"WARN: Boolean || always true [test/compress/issue-1261.js:129,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:129,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:129,23]",
|
||||
"WARN: Boolean || always true [test/compress/issue-1261.js:130,8]",
|
||||
"WARN: Condition left of || always true [test/compress/issue-1261.js:130,8]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:130,8]",
|
||||
"WARN: Boolean && always false [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Boolean && always false [test/compress/issue-1261.js:132,8]",
|
||||
"WARN: Condition left of && always false [test/compress/issue-1261.js:132,8]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:132,8]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:133,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:133,23]",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
issue_1321_no_debug: {
|
||||
mangle_props = {
|
||||
ignore_quoted: true
|
||||
keep_quoted: true
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
@@ -19,7 +19,7 @@ issue_1321_no_debug: {
|
||||
|
||||
issue_1321_debug: {
|
||||
mangle_props = {
|
||||
ignore_quoted: true,
|
||||
keep_quoted: true,
|
||||
debug: ""
|
||||
}
|
||||
input: {
|
||||
@@ -39,7 +39,7 @@ issue_1321_debug: {
|
||||
|
||||
issue_1321_with_quoted: {
|
||||
mangle_props = {
|
||||
ignore_quoted: false
|
||||
keep_quoted: false
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
|
||||
@@ -23,7 +23,7 @@ typeof_eq_undefined: {
|
||||
typeof_eq_undefined_ie8: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
screw_ie8: false
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
var a = typeof b != "undefined";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
screw_ie8: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
try { throw "foo"; } catch (x) { console.log(x); }
|
||||
@@ -16,10 +16,10 @@ screw_ie8: {
|
||||
|
||||
support_ie8: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
try { throw "foo"; } catch (x) { console.log(x); }
|
||||
@@ -85,15 +85,3 @@ unsafe_undefined: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
runtime_error: {
|
||||
input: {
|
||||
const a = 1;
|
||||
console.log(a++);
|
||||
}
|
||||
expect: {
|
||||
const a = 1;
|
||||
console.log(a++);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -18,9 +18,7 @@ chained_evaluation_1: {
|
||||
expect: {
|
||||
(function() {
|
||||
(function() {
|
||||
var c;
|
||||
c = f(1);
|
||||
c.bar = 1;
|
||||
f(1).bar = 1;
|
||||
})();
|
||||
})();
|
||||
}
|
||||
@@ -45,11 +43,9 @@ chained_evaluation_2: {
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var a = "long piece of string";
|
||||
(function() {
|
||||
var c;
|
||||
c = f(a);
|
||||
c.bar = a;
|
||||
var b = "long piece of string";
|
||||
f(b).bar = b;
|
||||
})();
|
||||
})();
|
||||
}
|
||||
|
||||
@@ -35,11 +35,11 @@ f7: {
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_exact: [
|
||||
"var a = 100, b = 10;",
|
||||
"var b = 10;",
|
||||
"",
|
||||
"!function() {",
|
||||
" for (;b = a, !1; ) ;",
|
||||
"}(), console.log(a, b);",
|
||||
" for (;b = 100, !1; ) ;",
|
||||
"}(), console.log(100, b);",
|
||||
]
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
mangle_catch: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
@@ -22,11 +22,11 @@ mangle_catch: {
|
||||
|
||||
mangle_catch_ie8: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
@@ -44,11 +44,11 @@ mangle_catch_ie8: {
|
||||
|
||||
mangle_catch_var: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
@@ -66,11 +66,11 @@ mangle_catch_var: {
|
||||
|
||||
mangle_catch_var_ie8: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
@@ -88,11 +88,11 @@ mangle_catch_var_ie8: {
|
||||
|
||||
mangle_catch_toplevel: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
@@ -110,11 +110,11 @@ mangle_catch_toplevel: {
|
||||
|
||||
mangle_catch_ie8_toplevel: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
@@ -132,11 +132,11 @@ mangle_catch_ie8_toplevel: {
|
||||
|
||||
mangle_catch_var_toplevel: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
@@ -154,11 +154,11 @@ mangle_catch_var_toplevel: {
|
||||
|
||||
mangle_catch_var_ie8_toplevel: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
@@ -176,11 +176,11 @@ mangle_catch_var_ie8_toplevel: {
|
||||
|
||||
mangle_catch_redef_1: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
@@ -198,11 +198,11 @@ mangle_catch_redef_1: {
|
||||
|
||||
mangle_catch_redef_1_ie8: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
@@ -220,11 +220,11 @@ mangle_catch_redef_1_ie8: {
|
||||
|
||||
mangle_catch_redef_1_toplevel: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
@@ -242,11 +242,11 @@ mangle_catch_redef_1_toplevel: {
|
||||
|
||||
mangle_catch_redef_1_ie8_toplevel: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
@@ -264,11 +264,11 @@ mangle_catch_redef_1_ie8_toplevel: {
|
||||
|
||||
mangle_catch_redef_2: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
@@ -285,11 +285,11 @@ mangle_catch_redef_2: {
|
||||
|
||||
mangle_catch_redef_2_ie8: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
@@ -306,11 +306,11 @@ mangle_catch_redef_2_ie8: {
|
||||
|
||||
mangle_catch_redef_2_toplevel: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
@@ -327,11 +327,11 @@ mangle_catch_redef_2_toplevel: {
|
||||
|
||||
mangle_catch_redef_2_ie8_toplevel: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
function_iife_catch: {
|
||||
mangle = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
function f(n) {
|
||||
@@ -21,7 +21,7 @@ function_iife_catch: {
|
||||
|
||||
function_iife_catch_ie8: {
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
function f(n) {
|
||||
@@ -42,7 +42,7 @@ function_iife_catch_ie8: {
|
||||
|
||||
function_catch_catch: {
|
||||
mangle = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
var o = 0;
|
||||
@@ -70,7 +70,7 @@ function_catch_catch: {
|
||||
|
||||
function_catch_catch_ie8: {
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
var o = 0;
|
||||
|
||||
54
test/compress/issue-1750.js
Normal file
54
test/compress/issue-1750.js
Normal file
@@ -0,0 +1,54 @@
|
||||
case_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b = 1;
|
||||
switch (true) {
|
||||
case a, true:
|
||||
default:
|
||||
b = 2;
|
||||
case true:
|
||||
}
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b = 1;
|
||||
switch (true) {
|
||||
case a, true:
|
||||
b = 2;
|
||||
}
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "0 2"
|
||||
}
|
||||
|
||||
case_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b = 1;
|
||||
switch (0) {
|
||||
default:
|
||||
b = 2;
|
||||
case a:
|
||||
a = 3;
|
||||
case 0:
|
||||
}
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b = 1;
|
||||
switch (0) {
|
||||
case a:
|
||||
a = 3;
|
||||
}
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "3 1"
|
||||
}
|
||||
239
test/compress/issue-1770.js
Normal file
239
test/compress/issue-1770.js
Normal file
@@ -0,0 +1,239 @@
|
||||
mangle_props: {
|
||||
mangle_props = {}
|
||||
input: {
|
||||
var obj = {
|
||||
undefined: 1,
|
||||
NaN: 2,
|
||||
Infinity: 3,
|
||||
"-Infinity": 4,
|
||||
null: 5,
|
||||
};
|
||||
console.log(
|
||||
obj[void 0],
|
||||
obj[undefined],
|
||||
obj["undefined"],
|
||||
obj[0/0],
|
||||
obj[NaN],
|
||||
obj["NaN"],
|
||||
obj[1/0],
|
||||
obj[Infinity],
|
||||
obj["Infinity"],
|
||||
obj[-1/0],
|
||||
obj[-Infinity],
|
||||
obj["-Infinity"],
|
||||
obj[null],
|
||||
obj["null"]
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var obj = {
|
||||
undefined: 1,
|
||||
NaN: 2,
|
||||
Infinity: 3,
|
||||
"-Infinity": 4,
|
||||
null: 5,
|
||||
};
|
||||
console.log(
|
||||
obj[void 0],
|
||||
obj[void 0],
|
||||
obj["undefined"],
|
||||
obj[0/0],
|
||||
obj[NaN],
|
||||
obj["NaN"],
|
||||
obj[1/0],
|
||||
obj[1/0],
|
||||
obj["Infinity"],
|
||||
obj[-1/0],
|
||||
obj[-1/0],
|
||||
obj["-Infinity"],
|
||||
obj[null],
|
||||
obj["null"]
|
||||
);
|
||||
}
|
||||
expect_stdout: "1 1 1 2 2 2 3 3 3 4 4 4 5 5"
|
||||
}
|
||||
|
||||
numeric_literal: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
mangle_props = {}
|
||||
input: {
|
||||
var obj = {
|
||||
0: 0,
|
||||
"-0": 1,
|
||||
42: 2,
|
||||
"42": 3,
|
||||
0x25: 4,
|
||||
"0x25": 5,
|
||||
1E42: 6,
|
||||
"1E42": 7,
|
||||
"1e+42": 8,
|
||||
};
|
||||
console.log(obj[-0], obj[-""], obj["-0"]);
|
||||
console.log(obj[42], obj["42"]);
|
||||
console.log(obj[0x25], obj["0x25"], obj[37], obj["37"]);
|
||||
console.log(obj[1E42], obj["1E42"], obj["1e+42"]);
|
||||
}
|
||||
expect_exact: [
|
||||
'var obj = {',
|
||||
' 0: 0,',
|
||||
' "-0": 1,',
|
||||
' 42: 2,',
|
||||
' "42": 3,',
|
||||
' 37: 4,',
|
||||
' a: 5,',
|
||||
' 1e42: 6,',
|
||||
' b: 7,',
|
||||
' "1e+42": 8',
|
||||
'};',
|
||||
'',
|
||||
'console.log(obj[-0], obj[-""], obj["-0"]);',
|
||||
'',
|
||||
'console.log(obj[42], obj["42"]);',
|
||||
'',
|
||||
'console.log(obj[37], obj["a"], obj[37], obj["37"]);',
|
||||
'',
|
||||
'console.log(obj[1e42], obj["b"], obj["1e+42"]);',
|
||||
]
|
||||
expect_stdout: [
|
||||
"0 0 1",
|
||||
"3 3",
|
||||
"4 5 4 4",
|
||||
"8 7 8",
|
||||
]
|
||||
}
|
||||
|
||||
identifier: {
|
||||
mangle_props = {}
|
||||
input: {
|
||||
var obj = {
|
||||
abstract: 1,
|
||||
boolean: 2,
|
||||
byte: 3,
|
||||
char: 4,
|
||||
class: 5,
|
||||
double: 6,
|
||||
enum: 7,
|
||||
export: 8,
|
||||
extends: 9,
|
||||
final: 10,
|
||||
float: 11,
|
||||
goto: 12,
|
||||
implements: 13,
|
||||
import: 14,
|
||||
int: 15,
|
||||
interface: 16,
|
||||
let: 17,
|
||||
long: 18,
|
||||
native: 19,
|
||||
package: 20,
|
||||
private: 21,
|
||||
protected: 22,
|
||||
public: 23,
|
||||
short: 24,
|
||||
static: 25,
|
||||
super: 26,
|
||||
synchronized: 27,
|
||||
this: 28,
|
||||
throws: 29,
|
||||
transient: 30,
|
||||
volatile: 31,
|
||||
yield: 32,
|
||||
false: 33,
|
||||
null: 34,
|
||||
true: 35,
|
||||
break: 36,
|
||||
case: 37,
|
||||
catch: 38,
|
||||
const: 39,
|
||||
continue: 40,
|
||||
debugger: 41,
|
||||
default: 42,
|
||||
delete: 43,
|
||||
do: 44,
|
||||
else: 45,
|
||||
finally: 46,
|
||||
for: 47,
|
||||
function: 48,
|
||||
if: 49,
|
||||
in: 50,
|
||||
instanceof: 51,
|
||||
new: 52,
|
||||
return: 53,
|
||||
switch: 54,
|
||||
throw: 55,
|
||||
try: 56,
|
||||
typeof: 57,
|
||||
var: 58,
|
||||
void: 59,
|
||||
while: 60,
|
||||
with: 61,
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var obj = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3,
|
||||
d: 4,
|
||||
e: 5,
|
||||
f: 6,
|
||||
g: 7,
|
||||
h: 8,
|
||||
i: 9,
|
||||
j: 10,
|
||||
k: 11,
|
||||
l: 12,
|
||||
m: 13,
|
||||
n: 14,
|
||||
o: 15,
|
||||
p: 16,
|
||||
q: 17,
|
||||
r: 18,
|
||||
s: 19,
|
||||
t: 20,
|
||||
u: 21,
|
||||
v: 22,
|
||||
w: 23,
|
||||
x: 24,
|
||||
y: 25,
|
||||
z: 26,
|
||||
A: 27,
|
||||
B: 28,
|
||||
C: 29,
|
||||
D: 30,
|
||||
F: 31,
|
||||
G: 32,
|
||||
false: 33,
|
||||
null: 34,
|
||||
true: 35,
|
||||
H: 36,
|
||||
I: 37,
|
||||
J: 38,
|
||||
K: 39,
|
||||
L: 40,
|
||||
M: 41,
|
||||
N: 42,
|
||||
O: 43,
|
||||
P: 44,
|
||||
Q: 45,
|
||||
R: 46,
|
||||
S: 47,
|
||||
T: 48,
|
||||
U: 49,
|
||||
V: 50,
|
||||
W: 51,
|
||||
X: 52,
|
||||
Y: 53,
|
||||
Z: 54,
|
||||
$: 55,
|
||||
_: 56,
|
||||
aa: 57,
|
||||
ba: 58,
|
||||
ca: 59,
|
||||
da: 60,
|
||||
ea: 61,
|
||||
};
|
||||
}
|
||||
}
|
||||
15
test/compress/issue-1787.js
Normal file
15
test/compress/issue-1787.js
Normal file
@@ -0,0 +1,15 @@
|
||||
unary_prefix: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var x = -(2 / 3);
|
||||
return x;
|
||||
}());
|
||||
}
|
||||
expect_exact: "console.log(-2/3);"
|
||||
expect_stdout: true
|
||||
}
|
||||
134
test/compress/issue-1833.js
Normal file
134
test/compress/issue-1833.js
Normal file
@@ -0,0 +1,134 @@
|
||||
iife_for: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
function g() {
|
||||
L: for (;;) break L;
|
||||
}
|
||||
g();
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
!function() {
|
||||
L: for (;;) break L;
|
||||
}();
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
iife_for_in: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
function g() {
|
||||
L: for (var a in x) break L;
|
||||
}
|
||||
g();
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
!function() {
|
||||
L: for (var a in x) break L;
|
||||
}();
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
iife_do: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
function g() {
|
||||
L: do {
|
||||
break L;
|
||||
} while (1);
|
||||
}
|
||||
g();
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
!function() {
|
||||
L: do {
|
||||
break L;
|
||||
} while (1);
|
||||
}();
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
iife_while: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
function g() {
|
||||
L: while (1) break L;
|
||||
}
|
||||
g();
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
!function() {
|
||||
L: while (1) break L;
|
||||
}();
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
label_do: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
L: do {
|
||||
continue L;
|
||||
} while (0);
|
||||
}
|
||||
expect: {
|
||||
L: do {
|
||||
continue L;
|
||||
} while (0);
|
||||
}
|
||||
}
|
||||
|
||||
label_while: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
L: while (0) continue L;
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(){L:;}"
|
||||
}
|
||||
31
test/compress/issue-1943.js
Normal file
31
test/compress/issue-1943.js
Normal file
@@ -0,0 +1,31 @@
|
||||
operator: {
|
||||
input: {
|
||||
a. //comment
|
||||
typeof
|
||||
}
|
||||
expect_exact: "a.typeof;"
|
||||
}
|
||||
|
||||
name: {
|
||||
input: {
|
||||
a. //comment
|
||||
b
|
||||
}
|
||||
expect_exact: "a.b;"
|
||||
}
|
||||
|
||||
keyword: {
|
||||
input: {
|
||||
a. //comment
|
||||
default
|
||||
}
|
||||
expect_exact: "a.default;"
|
||||
}
|
||||
|
||||
atom: {
|
||||
input: {
|
||||
a. //comment
|
||||
true
|
||||
}
|
||||
expect_exact: "a.true;"
|
||||
}
|
||||
@@ -38,7 +38,7 @@ mixed: {
|
||||
}
|
||||
}
|
||||
input: {
|
||||
const ENV = 3;
|
||||
var ENV = 3;
|
||||
var FOO = 4;
|
||||
f(ENV * 10);
|
||||
--FOO;
|
||||
@@ -49,7 +49,7 @@ mixed: {
|
||||
x = DEBUG;
|
||||
}
|
||||
expect: {
|
||||
const ENV = 3;
|
||||
var ENV = 3;
|
||||
var FOO = 4;
|
||||
f(10);
|
||||
--FOO;
|
||||
@@ -60,7 +60,7 @@ mixed: {
|
||||
x = 0;
|
||||
}
|
||||
expect_warnings: [
|
||||
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,14]',
|
||||
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,12]',
|
||||
'WARN: global_defs FOO redefined [test/compress/issue-208.js:42,12]',
|
||||
'WARN: global_defs FOO redefined [test/compress/issue-208.js:44,10]',
|
||||
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:45,8]',
|
||||
|
||||
@@ -6,7 +6,7 @@ NaN_and_Infinity_must_have_parens: {
|
||||
}
|
||||
expect: {
|
||||
(1/0).toString();
|
||||
(0/0).toString();
|
||||
NaN.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,36 @@ NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined: {
|
||||
}
|
||||
}
|
||||
|
||||
NaN_and_Infinity_must_have_parens_evaluate: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
(123456789 / 0).toString();
|
||||
(+"foo").toString();
|
||||
}
|
||||
expect: {
|
||||
(1/0).toString();
|
||||
NaN.toString();
|
||||
}
|
||||
}
|
||||
|
||||
NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined_evaluate: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
var Infinity, NaN;
|
||||
(123456789 / 0).toString();
|
||||
(+"foo").toString();
|
||||
}
|
||||
expect: {
|
||||
var Infinity, NaN;
|
||||
(1/0).toString();
|
||||
(0/0).toString();
|
||||
}
|
||||
}
|
||||
|
||||
beautify_off_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
|
||||
@@ -159,7 +159,7 @@ negate_iife_4: {
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(){ return t })() ? console.log(true) : console.log(false), function(){
|
||||
!function(){ return t }() ? console.log(false) : console.log(true), function(){
|
||||
console.log("something");
|
||||
}();
|
||||
}
|
||||
@@ -183,7 +183,7 @@ negate_iife_5: {
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(){ return t })() ? foo(true) : bar(false), function(){
|
||||
!function(){ return t }() ? bar(false) : foo(true), function(){
|
||||
console.log("something");
|
||||
}();
|
||||
}
|
||||
@@ -207,7 +207,7 @@ negate_iife_5_off: {
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(){ return t })() ? foo(true) : bar(false), function(){
|
||||
!function(){ return t }() ? bar(false) : foo(true), function(){
|
||||
console.log("something");
|
||||
}();
|
||||
}
|
||||
|
||||
@@ -146,50 +146,6 @@ parse_do_while_without_semicolon: {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
keep_collapse_const_in_own_block_scope: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
loops: true
|
||||
}
|
||||
input: {
|
||||
var i=2;
|
||||
const c=5;
|
||||
while(i--)
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var i=2;
|
||||
const c=5;
|
||||
for(;i--;)
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
keep_collapse_const_in_own_block_scope_2: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
loops: true
|
||||
}
|
||||
input: {
|
||||
const c=5;
|
||||
var i=2; // Moves to loop, while it did not in previous test
|
||||
while(i--)
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
const c=5;
|
||||
for(var i=2;i--;)
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
evaluate: {
|
||||
options = {
|
||||
loops: true,
|
||||
@@ -215,8 +171,7 @@ evaluate: {
|
||||
a();
|
||||
for(;;)
|
||||
c();
|
||||
// rule disabled due to issue_1532
|
||||
do d(); while (false);
|
||||
d();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +201,7 @@ issue_1532: {
|
||||
issue_186: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
var x = 3;
|
||||
@@ -265,7 +220,7 @@ issue_186: {
|
||||
issue_186_ie8: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
var x = 3;
|
||||
@@ -284,7 +239,7 @@ issue_186_ie8: {
|
||||
issue_186_beautify: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
var x = 3;
|
||||
@@ -311,7 +266,7 @@ issue_186_beautify: {
|
||||
issue_186_beautify_ie8: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
var x = 3;
|
||||
@@ -341,7 +296,7 @@ issue_186_bracketize: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
bracketize: true,
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
var x = 3;
|
||||
@@ -361,7 +316,7 @@ issue_186_bracketize_ie8: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
bracketize: true,
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
var x = 3;
|
||||
@@ -381,7 +336,7 @@ issue_186_beautify_bracketize: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
bracketize: true,
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
var x = 3;
|
||||
@@ -413,7 +368,7 @@ issue_186_beautify_bracketize_ie8: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
bracketize: true,
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
var x = 3;
|
||||
@@ -458,3 +413,26 @@ issue_1648: {
|
||||
}
|
||||
expect_exact: "function f(){for(x();1;);}"
|
||||
}
|
||||
|
||||
do_switch: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
do {
|
||||
switch (a) {
|
||||
case b:
|
||||
continue;
|
||||
}
|
||||
} while (false);
|
||||
}
|
||||
expect: {
|
||||
do {
|
||||
switch (a) {
|
||||
case b:
|
||||
continue;
|
||||
}
|
||||
} while (false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,9 @@ negate_iife_2: {
|
||||
negate_iife: true
|
||||
};
|
||||
input: {
|
||||
(function(){ return {} })().x = 10; // should not transform this one
|
||||
}
|
||||
expect: {
|
||||
(function(){ return {} })().x = 10;
|
||||
}
|
||||
expect_exact: "({}).x=10;"
|
||||
}
|
||||
|
||||
negate_iife_2_side_effects: {
|
||||
@@ -38,11 +36,9 @@ negate_iife_2_side_effects: {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(function(){ return {} })().x = 10; // should not transform this one
|
||||
}
|
||||
expect: {
|
||||
(function(){ return {} })().x = 10;
|
||||
}
|
||||
expect_exact: "({}).x=10;"
|
||||
}
|
||||
|
||||
negate_iife_3: {
|
||||
|
||||
12
test/compress/node_version.js
Normal file
12
test/compress/node_version.js
Normal file
@@ -0,0 +1,12 @@
|
||||
eval_let: {
|
||||
input: {
|
||||
eval("let a;");
|
||||
console.log();
|
||||
}
|
||||
expect: {
|
||||
eval("let a;");
|
||||
console.log();
|
||||
}
|
||||
expect_stdout: ""
|
||||
node_version: ">=6"
|
||||
}
|
||||
@@ -186,7 +186,7 @@ unary_binary_parenthesis: {
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var v = [ 0, 1, 0/0, 1/0, null, void 0, true, false, "", "foo", /foo/ ];
|
||||
var v = [ 0, 1, NaN, 1/0, null, void 0, true, false, "", "foo", /foo/ ];
|
||||
v.forEach(function(x) {
|
||||
v.forEach(function(y) {
|
||||
console.log(
|
||||
|
||||
@@ -13,7 +13,7 @@ keep_properties: {
|
||||
dot_properties: {
|
||||
options = {
|
||||
properties: true,
|
||||
screw_ie8: false
|
||||
ie8: true,
|
||||
};
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
@@ -36,7 +36,7 @@ dot_properties: {
|
||||
dot_properties_es5: {
|
||||
options = {
|
||||
properties: true,
|
||||
screw_ie8: true
|
||||
ie8: false,
|
||||
};
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
@@ -77,7 +77,7 @@ sub_properties: {
|
||||
a[3.14] = 3;
|
||||
a.if = 4;
|
||||
a["foo bar"] = 5;
|
||||
a[0/0] = 6;
|
||||
a[NaN] = 6;
|
||||
a[null] = 7;
|
||||
a[void 0] = 8;
|
||||
}
|
||||
@@ -125,7 +125,7 @@ evaluate_string_length: {
|
||||
|
||||
mangle_properties: {
|
||||
mangle_props = {
|
||||
ignore_quoted: false
|
||||
keep_quoted: false
|
||||
};
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
@@ -148,7 +148,7 @@ mangle_unquoted_properties: {
|
||||
properties: false
|
||||
}
|
||||
mangle_props = {
|
||||
ignore_quoted: true
|
||||
keep_quoted: true
|
||||
}
|
||||
beautify = {
|
||||
beautify: false,
|
||||
@@ -233,12 +233,12 @@ mangle_debug_suffix: {
|
||||
}
|
||||
}
|
||||
|
||||
mangle_debug_suffix_ignore_quoted: {
|
||||
mangle_debug_suffix_keep_quoted: {
|
||||
options = {
|
||||
properties: false
|
||||
}
|
||||
mangle_props = {
|
||||
ignore_quoted: true,
|
||||
keep_quoted: true,
|
||||
debug: "XYZ",
|
||||
reserved: []
|
||||
}
|
||||
|
||||
180
test/compress/pure_getters.js
Normal file
180
test/compress/pure_getters.js
Normal file
@@ -0,0 +1,180 @@
|
||||
strict: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: false,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a, b = null, c = {};
|
||||
a.prop;
|
||||
b.prop;
|
||||
c.prop;
|
||||
d.prop;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
undefined.prop;
|
||||
}
|
||||
expect: {
|
||||
var a, b = null, c = {};
|
||||
a.prop;
|
||||
b.prop;
|
||||
c.prop;
|
||||
d.prop;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
(void 0).prop;
|
||||
}
|
||||
}
|
||||
|
||||
strict_reduce_vars: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a, b = null, c = {};
|
||||
a.prop;
|
||||
b.prop;
|
||||
c.prop;
|
||||
d.prop;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
undefined.prop;
|
||||
}
|
||||
expect: {
|
||||
var a, b = null, c = {};
|
||||
a.prop;
|
||||
b.prop;
|
||||
d.prop;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
(void 0).prop;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
reduce_vars: false,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a, b = null, c = {};
|
||||
a.prop;
|
||||
b.prop;
|
||||
c.prop;
|
||||
d.prop;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
undefined.prop;
|
||||
}
|
||||
expect: {
|
||||
var a, b = null, c = {};
|
||||
d;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
(void 0).prop;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_reduce_vars: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a, b = null, c = {};
|
||||
a.prop;
|
||||
b.prop;
|
||||
c.prop;
|
||||
d.prop;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
undefined.prop;
|
||||
}
|
||||
expect: {
|
||||
var a, b = null, c = {};
|
||||
d;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
(void 0).prop;
|
||||
}
|
||||
}
|
||||
|
||||
chained: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
a.b.c;
|
||||
}
|
||||
expect: {
|
||||
a.b.c;
|
||||
}
|
||||
}
|
||||
|
||||
impure_getter_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
get a() {
|
||||
console.log(1);
|
||||
},
|
||||
b: 1
|
||||
}).a;
|
||||
({
|
||||
get a() {
|
||||
console.log(1);
|
||||
},
|
||||
b: 1
|
||||
}).b;
|
||||
}
|
||||
expect: {
|
||||
({
|
||||
get a() {
|
||||
console.log(1);
|
||||
},
|
||||
b: 1
|
||||
}).a;
|
||||
({
|
||||
get a() {
|
||||
console.log(1);
|
||||
},
|
||||
b: 1
|
||||
}).b;
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
impure_getter_2: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
// will produce incorrect output because getter is not pure
|
||||
({
|
||||
get a() {
|
||||
console.log(1);
|
||||
},
|
||||
b: 1
|
||||
}).a;
|
||||
({
|
||||
get a() {
|
||||
console.log(1);
|
||||
},
|
||||
b: 1
|
||||
}).b;
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
@@ -41,22 +41,20 @@ reduce_vars: {
|
||||
var A = 1;
|
||||
(function() {
|
||||
console.log(-3);
|
||||
console.log(-4);
|
||||
console.log(A - 5);
|
||||
})();
|
||||
(function f1() {
|
||||
var a = 2;
|
||||
console.log(-3);
|
||||
console.log(a - 5);
|
||||
eval("console.log(a);");
|
||||
})();
|
||||
(function f2(eval) {
|
||||
var a = 2;
|
||||
console.log(-3);
|
||||
console.log(a - 5);
|
||||
eval("console.log(a);");
|
||||
})(eval);
|
||||
(function() {
|
||||
return "yes";
|
||||
})();
|
||||
console.log(2);
|
||||
"yes";
|
||||
console.log(A + 1);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
@@ -66,7 +64,7 @@ modified: {
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
unused : true
|
||||
unused : true,
|
||||
}
|
||||
input: {
|
||||
function f0() {
|
||||
@@ -136,12 +134,11 @@ modified: {
|
||||
}
|
||||
|
||||
function f2() {
|
||||
var b = 2;
|
||||
b = 3;
|
||||
console.log(1 + b);
|
||||
console.log(b + 3);
|
||||
3;
|
||||
console.log(4);
|
||||
console.log(1 + b + 3);
|
||||
console.log(6);
|
||||
console.log(4);
|
||||
console.log(7);
|
||||
}
|
||||
|
||||
function f3() {
|
||||
@@ -300,7 +297,7 @@ unsafe_evaluate_array: {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_evaluate_equality: {
|
||||
unsafe_evaluate_equality_1: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
@@ -308,47 +305,62 @@ unsafe_evaluate_equality: {
|
||||
unused : true
|
||||
}
|
||||
input: {
|
||||
function f0(){
|
||||
function f0() {
|
||||
var a = {};
|
||||
console.log(a === a);
|
||||
return a === a;
|
||||
}
|
||||
|
||||
function f1(){
|
||||
function f1() {
|
||||
var a = [];
|
||||
console.log(a === a);
|
||||
return a === a;
|
||||
}
|
||||
console.log(f0(), f1());
|
||||
}
|
||||
expect: {
|
||||
function f0() {
|
||||
return true;
|
||||
}
|
||||
function f1() {
|
||||
return true;
|
||||
}
|
||||
console.log(f0(), f1());
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
function f2(){
|
||||
unsafe_evaluate_equality_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate : true,
|
||||
passes : 2,
|
||||
reduce_vars : true,
|
||||
unsafe : true,
|
||||
unused : true
|
||||
}
|
||||
input: {
|
||||
function f2() {
|
||||
var a = {a:1, b:2};
|
||||
var b = a;
|
||||
var c = a;
|
||||
console.log(b === c);
|
||||
return b === c;
|
||||
}
|
||||
|
||||
function f3(){
|
||||
function f3() {
|
||||
var a = [1, 2, 3];
|
||||
var b = a;
|
||||
var c = a;
|
||||
console.log(b === c);
|
||||
return b === c;
|
||||
}
|
||||
console.log(f2(), f3());
|
||||
}
|
||||
expect: {
|
||||
function f0(){
|
||||
console.log(true);
|
||||
function f2() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function f1(){
|
||||
console.log(true);
|
||||
}
|
||||
|
||||
function f2(){
|
||||
console.log(true);
|
||||
}
|
||||
|
||||
function f3(){
|
||||
console.log(true);
|
||||
function f3() {
|
||||
return true;
|
||||
}
|
||||
console.log(f2(), f3());
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
passes: {
|
||||
@@ -375,12 +387,11 @@ passes: {
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
var b = 2;
|
||||
b = 3;
|
||||
console.log(1 + b);
|
||||
console.log(b + 3);
|
||||
3;
|
||||
console.log(4);
|
||||
console.log(1 + b + 3);
|
||||
console.log(6);
|
||||
console.log(4);
|
||||
console.log(7);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -573,7 +584,7 @@ inner_var_label: {
|
||||
}
|
||||
}
|
||||
|
||||
inner_var_for: {
|
||||
inner_var_for_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
@@ -602,6 +613,29 @@ inner_var_for: {
|
||||
}
|
||||
}
|
||||
|
||||
inner_var_for_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
var a = 1;
|
||||
for (var b = 1; --b;) var a = 2;
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
a = 1;
|
||||
for (var b = 1; --b;) var a = 2;
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
inner_var_for_in_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -1399,6 +1433,8 @@ issue_1670_1: {
|
||||
evaluate: true,
|
||||
dead_code: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1429,6 +1465,8 @@ issue_1670_2: {
|
||||
dead_code: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1458,6 +1496,8 @@ issue_1670_3: {
|
||||
evaluate: true,
|
||||
dead_code: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1488,6 +1528,8 @@ issue_1670_4: {
|
||||
dead_code: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1516,6 +1558,8 @@ issue_1670_5: {
|
||||
evaluate: true,
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1544,6 +1588,8 @@ issue_1670_6: {
|
||||
evaluate: true,
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1627,7 +1673,7 @@ redefine_arguments_1: {
|
||||
return typeof arguments;
|
||||
}
|
||||
function g() {
|
||||
return"number";
|
||||
return "number";
|
||||
}
|
||||
function h(x) {
|
||||
var arguments = x;
|
||||
@@ -1666,9 +1712,7 @@ redefine_arguments_2: {
|
||||
console.log(function() {
|
||||
var arguments;
|
||||
return typeof arguments;
|
||||
}(), function() {
|
||||
return"number";
|
||||
}(), function(x) {
|
||||
}(), "number", function(x) {
|
||||
var arguments = x;
|
||||
return typeof arguments;
|
||||
}());
|
||||
@@ -1705,7 +1749,10 @@ redefine_arguments_3: {
|
||||
console.log(function() {
|
||||
var arguments;
|
||||
return typeof arguments;
|
||||
}(), "number", "undefined");
|
||||
}(), "number", function(x) {
|
||||
var arguments = x;
|
||||
return typeof arguments;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "object number undefined"
|
||||
}
|
||||
@@ -1777,9 +1824,7 @@ redefine_farg_2: {
|
||||
console.log(function(a) {
|
||||
var a;
|
||||
return typeof a;
|
||||
}([]), function() {
|
||||
return "number";
|
||||
}(),function(a, b) {
|
||||
}([]), "number",function(a, b) {
|
||||
var a = b;
|
||||
return typeof a;
|
||||
}([]));
|
||||
@@ -1816,10 +1861,7 @@ redefine_farg_3: {
|
||||
console.log(function(a) {
|
||||
var a;
|
||||
return typeof a;
|
||||
}([]), "number", function(a) {
|
||||
var a = void 0;
|
||||
return typeof a;
|
||||
}([]));
|
||||
}([]), "number", "undefined");
|
||||
}
|
||||
expect_stdout: "object number undefined"
|
||||
}
|
||||
@@ -1854,3 +1896,644 @@ delay_def: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
booleans: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
if (a != 0);
|
||||
switch (a) {
|
||||
case 0:
|
||||
return "FAIL";
|
||||
case false:
|
||||
return "PASS";
|
||||
}
|
||||
}(false));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
if (!1);
|
||||
switch (!1) {
|
||||
case 0:
|
||||
return "FAIL";
|
||||
case !1:
|
||||
return "PASS";
|
||||
}
|
||||
}(!1));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
side_effects_assign: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = typeof void (a && a.in == 1, 0);
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = typeof void (a && a.in);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
pure_getters_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
var a = (a.b, 2);
|
||||
} catch (e) {}
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
var a = (a.b, 2);
|
||||
} catch (e) {}
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
pure_getters_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
var a = a && a.b;
|
||||
}
|
||||
expect: {
|
||||
var a = a && a.b;
|
||||
}
|
||||
}
|
||||
|
||||
pure_getters_3: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
var a = a && a.b;
|
||||
}
|
||||
expect: {
|
||||
}
|
||||
}
|
||||
|
||||
catch_var: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
throw {};
|
||||
} catch (e) {
|
||||
var e;
|
||||
console.log(!!e);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
throw {};
|
||||
} catch (e) {
|
||||
var e;
|
||||
console.log(!!e);
|
||||
}
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
var_assign_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
var a;
|
||||
a = 2;
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
console.log(2);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
var_assign_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
var a;
|
||||
if (a = 2) console.log(a);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
if (2) console.log(2);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
var_assign_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
var a;
|
||||
while (a = 2);
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
var a;
|
||||
while (a = 2);
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
var_assign_4: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function a() {
|
||||
a = 2;
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function a() {
|
||||
a = 2,
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
var_assign_5: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
var a;
|
||||
!function(b) {
|
||||
a = 2;
|
||||
console.log(a, b);
|
||||
}(a);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
var a;
|
||||
!function(b) {
|
||||
a = 2,
|
||||
console.log(a, b);
|
||||
}(a);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "2 undefined"
|
||||
}
|
||||
|
||||
var_assign_6: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
var a = function(){}(a = 1);
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
var a = function(){}(a = 1);
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
immutable: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
var a = "test";
|
||||
console.log(a.indexOf("e"));
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
console.log("test".indexOf("e"));
|
||||
}();
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_1814_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 42;
|
||||
!function() {
|
||||
var b = a;
|
||||
!function(a) {
|
||||
console.log(a++, b);
|
||||
}(0);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
!function(a) {
|
||||
console.log(a++, 42);
|
||||
}(0);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "0 42"
|
||||
}
|
||||
|
||||
issue_1814_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = "32";
|
||||
!function() {
|
||||
var b = a + 1;
|
||||
!function(a) {
|
||||
console.log(a++, b);
|
||||
}(0);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
!function(a) {
|
||||
console.log(a++, "321");
|
||||
}(0);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "0 '321'"
|
||||
}
|
||||
|
||||
try_abort: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
try {
|
||||
var a = 1;
|
||||
throw "";
|
||||
var b = 2;
|
||||
} catch (e) {
|
||||
}
|
||||
console.log(a, b);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
try {
|
||||
var a = 1;
|
||||
throw "";
|
||||
var b = 2;
|
||||
} catch (e) {
|
||||
}
|
||||
console.log(a, b);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "1 undefined"
|
||||
}
|
||||
|
||||
boolean_binary_assign: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
var a;
|
||||
void 0 && (a = 1);
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
var a;
|
||||
void 0;
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
cond_assign: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
var a;
|
||||
void 0 ? (a = 1) : 0;
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
var a;
|
||||
void 0 ? (a = 1) : 0;
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
iife_assign: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
var a = 1, b = 0;
|
||||
!function() {
|
||||
b++;
|
||||
return;
|
||||
a = 2;
|
||||
}();
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
var a = 1, b = 0;
|
||||
!function() {
|
||||
b++;
|
||||
return;
|
||||
a = 2;
|
||||
}();
|
||||
console.log(a);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_1850_1: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
console.log(a, a, a);
|
||||
}
|
||||
var a = 1;
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
console.log(a, a, a);
|
||||
}
|
||||
var a = 1;
|
||||
f();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1850_2: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: "funcs",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
console.log(a, a, a);
|
||||
}
|
||||
var a = 1;
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
(function() {
|
||||
console.log(a, a, a);
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1850_3: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: "vars",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
console.log(a, a, a);
|
||||
}
|
||||
var a = 1;
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
console.log(a, a, a);
|
||||
}
|
||||
var a = 1;
|
||||
f();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1850_4: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
console.log(a, a, a);
|
||||
}
|
||||
var a = 1;
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
(function() {
|
||||
console.log(a, a, a);
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1865: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
function f(some) {
|
||||
some.thing = false;
|
||||
}
|
||||
console.log(function() {
|
||||
var some = { thing: true };
|
||||
f(some);
|
||||
return some.thing;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
function f(some) {
|
||||
some.thing = false;
|
||||
}
|
||||
console.log(function() {
|
||||
var some = { thing: true };
|
||||
f(some);
|
||||
return some.thing;
|
||||
}());
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1922_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
arguments[0] = 2;
|
||||
return a;
|
||||
}(1));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
arguments[0] = 2;
|
||||
return a;
|
||||
}(1));
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
issue_1922_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var a;
|
||||
eval("a = 1");
|
||||
return a;
|
||||
}(1));
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var a;
|
||||
eval("a = 1");
|
||||
return a;
|
||||
}(1));
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
accessor: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
console.log({
|
||||
get a() {
|
||||
a = 2;
|
||||
return a;
|
||||
},
|
||||
b: 1
|
||||
}.b, a);
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
console.log({
|
||||
get a() {
|
||||
a = 2;
|
||||
return a;
|
||||
},
|
||||
b: 1
|
||||
}.b, a);
|
||||
}
|
||||
expect_stdout: "1 1"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
do_screw: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
}
|
||||
beautify = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
@@ -14,10 +14,10 @@ do_screw: {
|
||||
|
||||
dont_screw: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
}
|
||||
beautify = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
@@ -28,7 +28,7 @@ dont_screw: {
|
||||
|
||||
do_screw_constants: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
f(undefined, Infinity);
|
||||
@@ -38,7 +38,7 @@ do_screw_constants: {
|
||||
|
||||
dont_screw_constants: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
f(undefined, Infinity);
|
||||
@@ -47,9 +47,15 @@ dont_screw_constants: {
|
||||
}
|
||||
|
||||
do_screw_try_catch: {
|
||||
options = { screw_ie8: true };
|
||||
mangle = { screw_ie8: true };
|
||||
beautify = { screw_ie8: true };
|
||||
options = {
|
||||
ie8: false,
|
||||
}
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
beautify = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
good = function(e){
|
||||
return function(error){
|
||||
@@ -75,9 +81,15 @@ do_screw_try_catch: {
|
||||
}
|
||||
|
||||
dont_screw_try_catch: {
|
||||
options = { screw_ie8: false };
|
||||
mangle = { screw_ie8: false };
|
||||
beautify = { screw_ie8: false };
|
||||
options = {
|
||||
ie8: true,
|
||||
}
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
beautify = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
bad = function(e){
|
||||
return function(error){
|
||||
@@ -103,9 +115,15 @@ dont_screw_try_catch: {
|
||||
}
|
||||
|
||||
do_screw_try_catch_undefined: {
|
||||
options = { screw_ie8: true };
|
||||
mangle = { screw_ie8: true };
|
||||
beautify = { screw_ie8: true };
|
||||
options = {
|
||||
ie8: false,
|
||||
}
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
beautify = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
function a(b){
|
||||
try {
|
||||
@@ -132,9 +150,15 @@ do_screw_try_catch_undefined: {
|
||||
}
|
||||
|
||||
dont_screw_try_catch_undefined: {
|
||||
options = { screw_ie8: false };
|
||||
mangle = { screw_ie8: false };
|
||||
beautify = { screw_ie8: false };
|
||||
options = {
|
||||
ie8: true,
|
||||
}
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
beautify = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
function a(b){
|
||||
try {
|
||||
@@ -164,11 +188,11 @@ reduce_vars: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
@@ -196,10 +220,10 @@ reduce_vars: {
|
||||
|
||||
issue_1586_1: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
@@ -215,10 +239,10 @@ issue_1586_1: {
|
||||
|
||||
issue_1586_2: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: true,
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
|
||||
@@ -440,3 +440,273 @@ func_def_5: {
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
issue_1758: {
|
||||
options = {
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(c) {
|
||||
var undefined = 42;
|
||||
return function() {
|
||||
c--;
|
||||
c--, c.toString();
|
||||
return;
|
||||
}();
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function(c) {
|
||||
var undefined = 42;
|
||||
return function() {
|
||||
return c--, c--, void c.toString();
|
||||
}();
|
||||
}());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
delete_seq_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (1, undefined));
|
||||
console.log(delete (1, void 0));
|
||||
console.log(delete (1, Infinity));
|
||||
console.log(delete (1, 1 / 0));
|
||||
console.log(delete (1, NaN));
|
||||
console.log(delete (1, 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_seq_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (1, 2, undefined));
|
||||
console.log(delete (1, 2, void 0));
|
||||
console.log(delete (1, 2, Infinity));
|
||||
console.log(delete (1, 2, 1 / 0));
|
||||
console.log(delete (1, 2, NaN));
|
||||
console.log(delete (1, 2, 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_seq_3: {
|
||||
options = {
|
||||
booleans: true,
|
||||
keep_infinity: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (1, 2, undefined));
|
||||
console.log(delete (1, 2, void 0));
|
||||
console.log(delete (1, 2, Infinity));
|
||||
console.log(delete (1, 2, 1 / 0));
|
||||
console.log(delete (1, 2, NaN));
|
||||
console.log(delete (1, 2, 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
console.log(!0);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_seq_4: {
|
||||
options = {
|
||||
booleans: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function f() {}
|
||||
console.log(delete (f(), undefined));
|
||||
console.log(delete (f(), void 0));
|
||||
console.log(delete (f(), Infinity));
|
||||
console.log(delete (f(), 1 / 0));
|
||||
console.log(delete (f(), NaN));
|
||||
console.log(delete (f(), 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
function f() {}
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_seq_5: {
|
||||
options = {
|
||||
booleans: true,
|
||||
keep_infinity: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function f() {}
|
||||
console.log(delete (f(), undefined));
|
||||
console.log(delete (f(), void 0));
|
||||
console.log(delete (f(), Infinity));
|
||||
console.log(delete (f(), 1 / 0));
|
||||
console.log(delete (f(), NaN));
|
||||
console.log(delete (f(), 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
function f() {}
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_seq_6: {
|
||||
options = {
|
||||
booleans: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
console.log(delete (1, a));
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
console.log(!0);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
side_effects: {
|
||||
options = {
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
0, a(), 1, b(), 2, c(), 3;
|
||||
}
|
||||
expect: {
|
||||
a(), b(), c();
|
||||
}
|
||||
}
|
||||
|
||||
side_effects_cascade_1: {
|
||||
options = {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b) {
|
||||
a -= 42;
|
||||
if (a < 0) a = 0;
|
||||
b.a = a;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(a, b) {
|
||||
(a -= 42) < 0 && (a = 0), b.a = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
side_effects_cascade_2: {
|
||||
options = {
|
||||
cascade: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b) {
|
||||
b = a,
|
||||
!a + (b += a) || (b += a),
|
||||
b = a,
|
||||
b;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(a, b) {
|
||||
b = a,
|
||||
!a + (b += a) || (b += a),
|
||||
b = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
side_effects_cascade_3: {
|
||||
options = {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b) {
|
||||
"foo" ^ (b += a),
|
||||
b ? false : (b = a) ? -1 : (b -= a) - (b ^= a),
|
||||
a-- || !a,
|
||||
a;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(a, b) {
|
||||
!(b += a) && ((b = a) || (b -= a, b ^= a)),
|
||||
--a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_27: {
|
||||
options = {
|
||||
cascade: true,
|
||||
passes: 2,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(jQuery) {
|
||||
var $;
|
||||
$ = jQuery;
|
||||
$("body").addClass("foo");
|
||||
})(jQuery);
|
||||
}
|
||||
expect: {
|
||||
(function(jQuery) {
|
||||
jQuery("body").addClass("foo");
|
||||
})(jQuery);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,3 +8,12 @@ octal_escape_sequence: {
|
||||
var border_check = "\x20\x30\x38\x30\x00\x30\xc0\x30";
|
||||
}
|
||||
}
|
||||
|
||||
issue_1929: {
|
||||
input: {
|
||||
function f(s) {
|
||||
return s.split(/[\\/]/);
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(s){return s.split(/[\\\\/]/)}"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
constant_switch_1: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (1+1) {
|
||||
case 1: foo(); break;
|
||||
@@ -13,7 +18,12 @@ constant_switch_1: {
|
||||
}
|
||||
|
||||
constant_switch_2: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (1) {
|
||||
case 1: foo();
|
||||
@@ -28,7 +38,12 @@ constant_switch_2: {
|
||||
}
|
||||
|
||||
constant_switch_3: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (10) {
|
||||
case 1: foo();
|
||||
@@ -44,7 +59,12 @@ constant_switch_3: {
|
||||
}
|
||||
|
||||
constant_switch_4: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (2) {
|
||||
case 1:
|
||||
@@ -65,7 +85,12 @@ constant_switch_4: {
|
||||
}
|
||||
|
||||
constant_switch_5: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (1) {
|
||||
case 1:
|
||||
@@ -94,7 +119,12 @@ constant_switch_5: {
|
||||
}
|
||||
|
||||
constant_switch_6: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
OUT: {
|
||||
foo();
|
||||
@@ -123,7 +153,12 @@ constant_switch_6: {
|
||||
}
|
||||
|
||||
constant_switch_7: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
OUT: {
|
||||
foo();
|
||||
@@ -161,7 +196,12 @@ constant_switch_7: {
|
||||
}
|
||||
|
||||
constant_switch_8: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
OUT: switch (1) {
|
||||
case 1:
|
||||
@@ -185,7 +225,12 @@ constant_switch_8: {
|
||||
}
|
||||
|
||||
constant_switch_9: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
OUT: switch (1) {
|
||||
case 1:
|
||||
@@ -210,7 +255,10 @@ constant_switch_9: {
|
||||
}
|
||||
|
||||
drop_default_1: {
|
||||
options = { dead_code: true };
|
||||
options = {
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (foo) {
|
||||
case 'bar': baz();
|
||||
@@ -225,7 +273,10 @@ drop_default_1: {
|
||||
}
|
||||
|
||||
drop_default_2: {
|
||||
options = { dead_code: true };
|
||||
options = {
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (foo) {
|
||||
case 'bar': baz(); break;
|
||||
@@ -241,7 +292,10 @@ drop_default_2: {
|
||||
}
|
||||
|
||||
keep_default: {
|
||||
options = { dead_code: true };
|
||||
options = {
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (foo) {
|
||||
case 'bar': baz();
|
||||
@@ -263,6 +317,8 @@ issue_1663: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
var a = 100, b = 10;
|
||||
@@ -294,6 +350,7 @@ issue_1663: {
|
||||
drop_case: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (foo) {
|
||||
@@ -312,6 +369,7 @@ drop_case: {
|
||||
keep_case: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (foo) {
|
||||
@@ -332,6 +390,7 @@ issue_376: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (true) {
|
||||
@@ -354,6 +413,7 @@ issue_376: {
|
||||
issue_441_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (foo) {
|
||||
@@ -381,6 +441,7 @@ issue_441_1: {
|
||||
issue_441_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (foo) {
|
||||
@@ -414,6 +475,8 @@ issue_1674: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (0) {
|
||||
@@ -435,6 +498,7 @@ issue_1679: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
var a = 100, b = 10;
|
||||
@@ -482,6 +546,7 @@ issue_1680_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
@@ -522,6 +587,7 @@ issue_1680_1: {
|
||||
issue_1680_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
var a = 100, b = 10;
|
||||
@@ -557,6 +623,7 @@ issue_1680_2: {
|
||||
issue_1690_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (console.log("PASS")) {}
|
||||
@@ -570,6 +637,7 @@ issue_1690_1: {
|
||||
issue_1690_2: {
|
||||
options = {
|
||||
dead_code: false,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (console.log("PASS")) {}
|
||||
@@ -585,6 +653,7 @@ if_switch_typeof: {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
if (a) switch(typeof b) {}
|
||||
@@ -597,6 +666,7 @@ if_switch_typeof: {
|
||||
issue_1698: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
@@ -618,6 +688,7 @@ issue_1698: {
|
||||
issue_1705_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
@@ -646,6 +717,7 @@ issue_1705_2: {
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
switches: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -666,6 +738,7 @@ issue_1705_2: {
|
||||
issue_1705_3: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (a) {
|
||||
@@ -721,3 +794,25 @@ beautify: {
|
||||
"}",
|
||||
]
|
||||
}
|
||||
|
||||
issue_1758: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1, b = 2;
|
||||
switch (a--) {
|
||||
default:
|
||||
b++;
|
||||
}
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = 1, b = 2;
|
||||
a--;
|
||||
b++;
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "0 3"
|
||||
}
|
||||
|
||||
13
test/exports.js
Normal file
13
test/exports.js
Normal file
@@ -0,0 +1,13 @@
|
||||
exports["Compressor"] = Compressor;
|
||||
exports["JS_Parse_Error"] = JS_Parse_Error;
|
||||
exports["OutputStream"] = OutputStream;
|
||||
exports["SourceMap"] = SourceMap;
|
||||
exports["TreeWalker"] = TreeWalker;
|
||||
exports["base54"] = base54;
|
||||
exports["defaults"] = defaults;
|
||||
exports["mangle_properties"] = mangle_properties;
|
||||
exports["minify"] = minify;
|
||||
exports["parse"] = parse;
|
||||
exports["string_template"] = string_template;
|
||||
exports["tokenizer"] = tokenizer;
|
||||
exports["is_identifier"] = is_identifier;
|
||||
1
test/input/invalid/assign_4.js
Normal file
1
test/input/invalid/assign_4.js
Normal file
@@ -0,0 +1 @@
|
||||
++null
|
||||
14
test/input/invalid/delete.js
Normal file
14
test/input/invalid/delete.js
Normal file
@@ -0,0 +1,14 @@
|
||||
function f(x) {
|
||||
delete 42;
|
||||
delete (0, x);
|
||||
delete null;
|
||||
delete x;
|
||||
}
|
||||
|
||||
function g(x) {
|
||||
"use strict";
|
||||
delete 42;
|
||||
delete (0, x);
|
||||
delete null;
|
||||
delete x;
|
||||
}
|
||||
1
test/input/invalid/dot_1.js
Normal file
1
test/input/invalid/dot_1.js
Normal file
@@ -0,0 +1 @@
|
||||
a.=
|
||||
1
test/input/invalid/dot_2.js
Normal file
1
test/input/invalid/dot_2.js
Normal file
@@ -0,0 +1 @@
|
||||
%.a;
|
||||
1
test/input/invalid/dot_3.js
Normal file
1
test/input/invalid/dot_3.js
Normal file
@@ -0,0 +1 @@
|
||||
a./();
|
||||
1
test/input/invalid/else.js
Normal file
1
test/input/invalid/else.js
Normal file
@@ -0,0 +1 @@
|
||||
if (0) else 1;
|
||||
6
test/input/invalid/function_1.js
Normal file
6
test/input/invalid/function_1.js
Normal file
@@ -0,0 +1,6 @@
|
||||
function f(arguments) {
|
||||
}
|
||||
|
||||
function g(arguments) {
|
||||
"use strict";
|
||||
}
|
||||
6
test/input/invalid/function_2.js
Normal file
6
test/input/invalid/function_2.js
Normal file
@@ -0,0 +1,6 @@
|
||||
function arguments() {
|
||||
}
|
||||
|
||||
function eval() {
|
||||
"use strict";
|
||||
}
|
||||
6
test/input/invalid/function_3.js
Normal file
6
test/input/invalid/function_3.js
Normal file
@@ -0,0 +1,6 @@
|
||||
!function eval() {
|
||||
}();
|
||||
|
||||
!function arguments() {
|
||||
"use strict";
|
||||
}();
|
||||
1
test/input/invalid/object.js
Normal file
1
test/input/invalid/object.js
Normal file
@@ -0,0 +1 @@
|
||||
console.log({%: 1});
|
||||
1
test/input/invalid/return.js
Normal file
1
test/input/invalid/return.js
Normal file
@@ -0,0 +1 @@
|
||||
return 42;
|
||||
8
test/input/invalid/try.js
Normal file
8
test/input/invalid/try.js
Normal file
@@ -0,0 +1,8 @@
|
||||
function f() {
|
||||
try {} catch (eval) {}
|
||||
}
|
||||
|
||||
function g() {
|
||||
"use strict";
|
||||
try {} catch (eval) {}
|
||||
}
|
||||
8
test/input/invalid/var.js
Normal file
8
test/input/invalid/var.js
Normal file
@@ -0,0 +1,8 @@
|
||||
function f() {
|
||||
var eval;
|
||||
}
|
||||
|
||||
function g() {
|
||||
"use strict";
|
||||
var eval;
|
||||
}
|
||||
@@ -12,7 +12,7 @@ if (typeof phantom == "undefined") {
|
||||
});
|
||||
var args = process.argv.slice(2);
|
||||
if (!args.length) {
|
||||
args.push("-mc", "warnings=false");
|
||||
args.push("-mc");
|
||||
}
|
||||
args.push("--stats");
|
||||
var child_process = require("child_process");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var UglifyJS = require('../../');
|
||||
var UglifyJS = require("../node");
|
||||
var assert = require("assert");
|
||||
|
||||
describe("Accessor tokens", function() {
|
||||
@@ -16,7 +16,7 @@ describe("Accessor tokens", function() {
|
||||
assert.equal(node.start.pos, 12);
|
||||
assert.equal(node.end.endpos, 46);
|
||||
|
||||
assert(node.key instanceof UglifyJS.AST_SymbolRef);
|
||||
assert(node.key instanceof UglifyJS.AST_SymbolAccessor);
|
||||
assert.equal(node.key.start.pos, 16);
|
||||
assert.equal(node.key.end.endpos, 22);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var UglifyJS = require('../../');
|
||||
var UglifyJS = require("../node");
|
||||
var assert = require("assert");
|
||||
|
||||
describe("arguments", function() {
|
||||
|
||||
@@ -2,6 +2,10 @@ var assert = require("assert");
|
||||
var exec = require("child_process").exec;
|
||||
var readFileSync = require("fs").readFileSync;
|
||||
|
||||
function read(path) {
|
||||
return readFileSync(path, "utf8");
|
||||
}
|
||||
|
||||
describe("bin/uglifyjs", function () {
|
||||
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
|
||||
it("should produce a functional build when using --self", function (done) {
|
||||
@@ -15,12 +19,12 @@ describe("bin/uglifyjs", function () {
|
||||
eval(stdout);
|
||||
|
||||
assert.strictEqual(typeof WrappedUglifyJS, 'object');
|
||||
assert.strictEqual(true, WrappedUglifyJS.parse('foo;') instanceof WrappedUglifyJS.AST_Node);
|
||||
assert.strictEqual(WrappedUglifyJS.minify("foo([true,,2+3]);").code, "foo([!0,,5]);");
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should be able to filter comments correctly with `--comment all`", function (done) {
|
||||
it("Should be able to filter comments correctly with `--comments all`", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/comments/filter.js --comments all';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
@@ -50,18 +54,18 @@ describe("bin/uglifyjs", function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should append source map to output when using --source-map-inline", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1323/sample.js --source-map-inline';
|
||||
it("Should append source map to output when using --source-map url=inline", function (done) {
|
||||
var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map url=inline";
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n" +
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxHQUFJQSxLQUFNLFdBQ04sUUFBU0MsS0FBS0QsS0FDVixNQUFPQSxLQUdYLE1BQU9DIn0=\n");
|
||||
done();
|
||||
});
|
||||
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n" +
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxHQUFJQSxLQUFNLFdBQ04sUUFBU0MsS0FBS0QsS0FDVixNQUFPQSxLQUdYLE1BQU9DIn0=\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("should not append source map to output when not using --source-map-inline", function (done) {
|
||||
it("should not append source map to output when not using --source-map url=inline", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1323/sample.js';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
@@ -72,130 +76,134 @@ describe("bin/uglifyjs", function () {
|
||||
});
|
||||
});
|
||||
it("Should work with --keep-fnames (mangle only)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --keep-fnames (mangle & compress)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c unused=false';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with keep_fnames under mangler options", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep_fnames=true';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --define (simple)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/global_defs/simple.js --define D=5 -c';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "console.log(5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --define (nested)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/global_defs/nested.js --define C.D=5,C.V=3 -c';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "console.log(3,5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --define (AST_Node)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/global_defs/simple.js --define console.log=stdout.println -c';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "stdout.println(D);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with `--beautify`", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, readFileSync("test/input/issue-1482/default.js", "utf8"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with `--beautify bracketize`", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b bracketize';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, readFileSync("test/input/issue-1482/bracketize.js", "utf8"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should process inline source map", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-520/input.js -mc toplevel --in-source-map inline --source-map-inline';
|
||||
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, readFileSync("test/input/issue-520/output.js", "utf8"));
|
||||
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --keep-fnames (mangle & compress)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c unused=false';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with keep_fnames under mangler options", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep_fnames=true';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --define (simple)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/global_defs/simple.js --define D=5 -c';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "console.log(5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --define (nested)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/global_defs/nested.js --define C.D=5,C.V=3 -c';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "console.log(3,5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --define (AST_Node)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/global_defs/simple.js --define console.log=stdout.println -c';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "stdout.println(D);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with `--beautify`", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, read("test/input/issue-1482/default.js"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with `--beautify bracketize`", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b bracketize';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, read("test/input/issue-1482/bracketize.js"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should process inline source map", function(done) {
|
||||
var command = uglifyjscmd + " test/input/issue-520/input.js -mc toplevel --source-map content=inline,url=inline";
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, read("test/input/issue-520/output.js"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should warn for missing inline source map", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1323/sample.js --in-source-map inline';
|
||||
var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map content=inline,url=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(stdout, [
|
||||
"var bar=function(){function foo(bar){return bar}return foo}();",
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxHQUFJQSxLQUFNLFdBQ04sUUFBU0MsS0FBS0QsS0FDVixNQUFPQSxLQUdYLE1BQU9DIn0=",
|
||||
"",
|
||||
].join("\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';
|
||||
var command = uglifyjscmd + " test/input/issue-520/input.js test/input/issue-520/output.js --source-map content=inline,url=inline";
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stderr, "ERROR: Inline source map only works with singular input\n");
|
||||
assert.strictEqual(stderr.split(/\n/)[0], "ERROR: inline source map only works with singular input");
|
||||
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';
|
||||
var command = uglifyjscmd + " test/input/issue-520/input.js --source-map content=inline,url=inline -p acorn";
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stderr, "ERROR: Inline source map only works with built-in parser\n");
|
||||
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';
|
||||
var command = uglifyjscmd + " test/input/issue-520/input.js --source-map content=inline,url=inline -p spidermonkey";
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stderr, "ERROR: Inline source map only works with built-in parser\n");
|
||||
assert.strictEqual(stderr, "ERROR: inline source map only works with built-in parser\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -208,7 +216,7 @@ describe("bin/uglifyjs", function () {
|
||||
assert.strictEqual(lines[0], "Parse error at test/input/invalid/simple.js:1,12");
|
||||
assert.strictEqual(lines[1], "function f(a{}");
|
||||
assert.strictEqual(lines[2], " ^");
|
||||
assert.strictEqual(lines[3], "SyntaxError: Unexpected token punc «{», expected punc «,»");
|
||||
assert.strictEqual(lines[3], "ERROR: Unexpected token punc «{», expected punc «,»");
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -221,7 +229,7 @@ describe("bin/uglifyjs", function () {
|
||||
assert.strictEqual(lines[0], "Parse error at test/input/invalid/tab.js:1,12");
|
||||
assert.strictEqual(lines[1], "\t\tfoo(\txyz, 0abc);");
|
||||
assert.strictEqual(lines[2], "\t\t \t ^");
|
||||
assert.strictEqual(lines[3], "SyntaxError: Invalid syntax: 0abc");
|
||||
assert.strictEqual(lines[3], "ERROR: Invalid syntax: 0abc");
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -234,7 +242,7 @@ describe("bin/uglifyjs", function () {
|
||||
assert.strictEqual(lines[0], "Parse error at test/input/invalid/eof.js:2,0");
|
||||
assert.strictEqual(lines[1], "foo, bar(");
|
||||
assert.strictEqual(lines[2], " ^");
|
||||
assert.strictEqual(lines[3], "SyntaxError: Unexpected token: eof (undefined)");
|
||||
assert.strictEqual(lines[3], "ERROR: Unexpected token: eof (undefined)");
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -247,63 +255,284 @@ describe("bin/uglifyjs", function () {
|
||||
assert.strictEqual(lines[0], "Parse error at test/input/invalid/loop-no-body.js:2,0");
|
||||
assert.strictEqual(lines[1], "for (var i = 0; i < 1; i++) ");
|
||||
assert.strictEqual(lines[2], " ^");
|
||||
assert.strictEqual(lines[3], "SyntaxError: Unexpected token: eof (undefined)");
|
||||
assert.strictEqual(lines[3], "ERROR: Unexpected token: eof (undefined)");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should support hyphen as shorthand", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep-fnames=true';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (5--)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_1.js';
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_1.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/assign_1.js:1,18",
|
||||
"console.log(1 || 5--);",
|
||||
" ^",
|
||||
"SyntaxError: Invalid use of -- operator"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/assign_1.js:1,18",
|
||||
"console.log(1 || 5--);",
|
||||
" ^",
|
||||
"ERROR: Invalid use of -- operator"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (Math.random() /= 2)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_2.js';
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_2.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/assign_2.js:1,32",
|
||||
"console.log(2 || (Math.random() /= 2));",
|
||||
" ^",
|
||||
"SyntaxError: Invalid assignment"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/assign_2.js:1,32",
|
||||
"console.log(2 || (Math.random() /= 2));",
|
||||
" ^",
|
||||
"ERROR: Invalid assignment"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (++this)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_3.js';
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_3.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/assign_3.js:1,18",
|
||||
"console.log(3 || ++this);",
|
||||
" ^",
|
||||
"SyntaxError: Invalid use of ++ operator"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/assign_3.js:1,17",
|
||||
"console.log(3 || ++this);",
|
||||
" ^",
|
||||
"ERROR: Invalid use of ++ operator"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (++null)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_4.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/assign_4.js:1,0",
|
||||
"++null",
|
||||
"^",
|
||||
"ERROR: Invalid use of ++ operator"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (a.=)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/dot_1.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/dot_1.js:1,2",
|
||||
"a.=",
|
||||
" ^",
|
||||
"ERROR: Unexpected token: operator (=)"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (%.a)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/dot_2.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/dot_2.js:1,0",
|
||||
"%.a;",
|
||||
"^",
|
||||
"ERROR: Unexpected token: operator (%)"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (a./();)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/dot_3.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/dot_3.js:1,2",
|
||||
"a./();",
|
||||
" ^",
|
||||
"ERROR: Unexpected token: operator (/)"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error ({%: 1})", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/object.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/object.js:1,13",
|
||||
"console.log({%: 1});",
|
||||
" ^",
|
||||
"ERROR: Unexpected token: operator (%)"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (delete x)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/delete.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/delete.js:13,11",
|
||||
" delete x;",
|
||||
" ^",
|
||||
"ERROR: Calling delete on expression not allowed in strict mode"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (function g(arguments))", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/function_1.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/function_1.js:4,11",
|
||||
"function g(arguments) {",
|
||||
" ^",
|
||||
"ERROR: Unexpected arguments in strict mode"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (function eval())", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/function_2.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/function_2.js:4,9",
|
||||
"function eval() {",
|
||||
" ^",
|
||||
"ERROR: Unexpected eval in strict mode"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (iife arguments())", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/function_3.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/function_3.js:4,10",
|
||||
"!function arguments() {",
|
||||
" ^",
|
||||
"ERROR: Unexpected arguments in strict mode"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (catch(eval))", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/try.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/try.js:7,18",
|
||||
" try {} catch (eval) {}",
|
||||
" ^",
|
||||
"ERROR: Unexpected eval in strict mode"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (var eval)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/var.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/var.js:7,8",
|
||||
" var eval;",
|
||||
" ^",
|
||||
"ERROR: Unexpected eval in strict mode"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (else)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/else.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/else.js:1,7",
|
||||
"if (0) else 1;",
|
||||
" ^",
|
||||
"ERROR: Unexpected token: keyword (else)"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (return)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/return.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/return.js:1,0",
|
||||
"return 42;",
|
||||
"^",
|
||||
"ERROR: 'return' outside of function"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should handle literal string as source map input", function(done) {
|
||||
var command = [
|
||||
uglifyjscmd,
|
||||
"test/input/issue-1236/simple.js",
|
||||
"--source-map",
|
||||
'content="' + read_map() + '",url=inline'
|
||||
].join(" ");
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, [
|
||||
'"use strict";var foo=function foo(x){return"foo "+x};console.log(foo("bar"));',
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiWUFBQSxJQUFJQSxLQUFNLFFBQU5BLEtBQU1DLEdBQUEsTUFBSyxPQUFTQSxFQUN4QkMsU0FBUUMsSUFBSUgsSUFBSSJ9",
|
||||
""
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
|
||||
function read_map() {
|
||||
var map = JSON.parse(read("./test/input/issue-1236/simple.js.map"));
|
||||
delete map.sourcesContent;
|
||||
return JSON.stringify(map).replace(/"/g, '\\"');
|
||||
}
|
||||
});
|
||||
it("Should dump AST as JSON", function(done) {
|
||||
var command = uglifyjscmd + " test/input/global_defs/simple.js -mco ast";
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
var ast = JSON.parse(stdout);
|
||||
assert.strictEqual(ast._class, "AST_Toplevel");
|
||||
assert.ok(Array.isArray(ast.body));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var UglifyJS = require('../../');
|
||||
var UglifyJS = require("../node");
|
||||
var assert = require("assert");
|
||||
|
||||
describe("comment filters", function() {
|
||||
@@ -75,9 +75,15 @@ describe("comment filters", function() {
|
||||
|
||||
it("Should handle shebang and preamble correctly", function() {
|
||||
var code = UglifyJS.minify("#!/usr/bin/node\nvar x = 10;", {
|
||||
fromString: true,
|
||||
output: { preamble: "/* Build */" }
|
||||
}).code;
|
||||
assert.strictEqual(code, "#!/usr/bin/node\n/* Build */\nvar x=10;");
|
||||
})
|
||||
});
|
||||
|
||||
it("Should handle preamble without shebang correctly", function() {
|
||||
var code = UglifyJS.minify("var x = 10;", {
|
||||
output: { preamble: "/* Build */" }
|
||||
}).code;
|
||||
assert.strictEqual(code, "/* Build */\nvar x=10;");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../../");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("Comment", function() {
|
||||
it("Should recognize eol of single line comments", function() {
|
||||
@@ -20,7 +20,7 @@ describe("Comment", function() {
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.throws(function() {
|
||||
uglify.parse(tests[i], {fromString: true})
|
||||
uglify.parse(tests[i]);
|
||||
}, fail, tests[i]);
|
||||
}
|
||||
});
|
||||
@@ -43,7 +43,7 @@ describe("Comment", function() {
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.throws(function() {
|
||||
uglify.parse(tests[i], {fromString: true})
|
||||
uglify.parse(tests[i]);
|
||||
}, fail, tests[i]);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -6,9 +6,7 @@ describe("comment before constant", function() {
|
||||
|
||||
it("Should test comment before constant is retained and output after mangle.", function() {
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true,
|
||||
compress: { collapse_vars: false, reduce_vars: false },
|
||||
mangle: {},
|
||||
output: { comments: true },
|
||||
});
|
||||
assert.strictEqual(result.code, 'function f(){/*c1*/var/*c2*/n=/*c3*/!1;return n}');
|
||||
@@ -16,12 +14,9 @@ describe("comment before constant", function() {
|
||||
|
||||
it("Should test code works when comments disabled.", function() {
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true,
|
||||
compress: { collapse_vars: false, reduce_vars: false },
|
||||
mangle: {},
|
||||
output: { comments: false },
|
||||
});
|
||||
assert.strictEqual(result.code, 'function f(){var n=!1;return n}');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../../");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("Directives", function() {
|
||||
it ("Should allow tokenizer to store directives state", function() {
|
||||
@@ -197,7 +197,7 @@ describe("Directives", function() {
|
||||
assert.strictEqual(
|
||||
uglify.minify(
|
||||
'"use strict";\'use strict\';"use strict";"use strict";;\'use strict\';console.log(\'use strict\');',
|
||||
{fromString: true, output: {beautify: true, quote_style: 3}, compress: false}
|
||||
{output: {beautify: true, quote_style: 3}, compress: false}
|
||||
).code,
|
||||
'"use strict";\n\n\'use strict\';\n\n"use strict";\n\n"use strict";\n\n;\'use strict\';\n\nconsole.log(\'use strict\');'
|
||||
);
|
||||
@@ -225,7 +225,7 @@ describe("Directives", function() {
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.strictEqual(
|
||||
uglify.minify(tests[i][0], {fromString: true, quote_style: 3, compress: false, mangle: false}).code,
|
||||
uglify.minify(tests[i][0], {compress: false, mangle: false}).code,
|
||||
tests[i][1],
|
||||
tests[i][0]
|
||||
);
|
||||
@@ -234,7 +234,7 @@ describe("Directives", function() {
|
||||
|
||||
it("Should add double semicolon when relying on automatic semicolon insertion", function() {
|
||||
var code = uglify.minify('"use strict";"use\\x20strict";',
|
||||
{fromString: true, output: {semicolons: false}, compress: false}
|
||||
{output: {semicolons: false}, compress: false}
|
||||
).code;
|
||||
assert.strictEqual(code, '"use strict";;"use strict"\n');
|
||||
});
|
||||
@@ -340,7 +340,7 @@ describe("Directives", function() {
|
||||
];
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.strictEqual(
|
||||
uglify.minify(tests[i][0], {fromString: true, output:{quote_style: tests[i][1]}, compress: false}).code,
|
||||
uglify.minify(tests[i][0], {output:{quote_style: tests[i][1]}, compress: false}).code,
|
||||
tests[i][2],
|
||||
tests[i][0] + " using mode " + tests[i][1]
|
||||
);
|
||||
@@ -351,18 +351,28 @@ describe("Directives", function() {
|
||||
var tests = [
|
||||
[
|
||||
'"use strict";"use strict";"use strict";"use foo";"use strict";;"use sloppy";doSomething("foo");',
|
||||
'"use strict";"use foo";doSomething("foo");'
|
||||
'"use strict";"use foo";doSomething("foo");',
|
||||
'function f(){ "use strict" }',
|
||||
'function f(){ "use asm" }',
|
||||
'function f(){ "use nondirective" }',
|
||||
'function f(){ ;"use strict" }',
|
||||
'function f(){ "use \n"; }',
|
||||
],
|
||||
[
|
||||
// Nothing gets optimised in the compressor because "use asm" is the first statement
|
||||
'"use asm";"use\\x20strict";1+1;',
|
||||
'"use asm";;"use strict";1+1;' // Yet, the parser noticed that "use strict" wasn't a directive
|
||||
'"use asm";;"use strict";1+1;', // Yet, the parser noticed that "use strict" wasn't a directive
|
||||
'function f(){"use strict"}',
|
||||
'function f(){"use asm"}',
|
||||
'function f(){"use nondirective"}',
|
||||
'function f(){}',
|
||||
'function f(){}',
|
||||
]
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.strictEqual(
|
||||
uglify.minify(tests[i][0], {fromString: true, compress: {collapse_vars: true, side_effects: true}}).code,
|
||||
uglify.minify(tests[i][0]).code,
|
||||
tests[i][1],
|
||||
tests[i][0]
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var UglifyJS = require('../../');
|
||||
var UglifyJS = require("../node");
|
||||
var assert = require("assert");
|
||||
|
||||
describe("Getters and setters", function() {
|
||||
@@ -71,7 +71,7 @@ describe("Getters and setters", function() {
|
||||
var fail = function(data) {
|
||||
return function (e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error &&
|
||||
e.message === "Invalid getter/setter name: " + data.operator;
|
||||
e.message === "Unexpected token: operator (" + data.operator + ")";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,58 +1,80 @@
|
||||
var Uglify = require('../../');
|
||||
var assert = require("assert");
|
||||
var exec = require("child_process").exec;
|
||||
var path = require("path");
|
||||
var readFileSync = require("fs").readFileSync;
|
||||
|
||||
describe("minify() with input file globs", function() {
|
||||
it("minify() with one input file glob string.", function() {
|
||||
var result = Uglify.minify("test/input/issue-1242/foo.*");
|
||||
assert.strictEqual(result.code, 'function foo(o){print("Foo:",2*o)}var print=console.log.bind(console);');
|
||||
});
|
||||
it("minify() with an array of one input file glob.", function() {
|
||||
var result = Uglify.minify([
|
||||
"test/input/issue-1242/b*.es5",
|
||||
]);
|
||||
assert.strictEqual(result.code, 'function bar(n){return 3*n}function baz(n){return n/2}');
|
||||
});
|
||||
it("minify() with an array of multiple input file globs.", function() {
|
||||
var result = Uglify.minify([
|
||||
"test/input/issue-1242/???.es5",
|
||||
"test/input/issue-1242/*.js",
|
||||
], {
|
||||
compress: { toplevel: true }
|
||||
describe("bin/uglifyjs with input file globs", function() {
|
||||
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
|
||||
it("bin/uglifyjs with one input file extension glob.", function(done) {
|
||||
var command = uglifyjscmd + ' "test/input/issue-1242/foo.*" -cm';
|
||||
|
||||
exec(command, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, 'function foo(o){print("Foo:",2*o)}var print=console.log.bind(console);\n');
|
||||
done();
|
||||
});
|
||||
assert.strictEqual(result.code, 'var print=console.log.bind(console),a=function(n){return 3*n}(3),b=function(n){return n/2}(12);print("qux",a,b),function(n){print("Foo:",2*n)}(11);');
|
||||
});
|
||||
it("should throw with non-matching glob string", function() {
|
||||
var glob = "test/input/issue-1242/blah.*";
|
||||
assert.strictEqual(Uglify.simple_glob(glob).length, 1);
|
||||
assert.strictEqual(Uglify.simple_glob(glob)[0], glob);
|
||||
assert.throws(function() {
|
||||
Uglify.minify(glob);
|
||||
}, "should throw file not found");
|
||||
it("bin/uglifyjs with one input file name glob.", function(done) {
|
||||
var command = uglifyjscmd + ' "test/input/issue-1242/b*.es5" -cm';
|
||||
|
||||
exec(command, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, 'function bar(n){return 3*n}function baz(n){return n/2}\n');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('"?" in glob string should not match "/"', function() {
|
||||
var glob = "test/input?issue-1242/foo.*";
|
||||
assert.strictEqual(Uglify.simple_glob(glob).length, 1);
|
||||
assert.strictEqual(Uglify.simple_glob(glob)[0], glob);
|
||||
assert.throws(function() {
|
||||
Uglify.minify(glob);
|
||||
}, "should throw file not found");
|
||||
it("bin/uglifyjs with multiple input file globs.", function(done) {
|
||||
var command = uglifyjscmd + ' "test/input/issue-1242/???.es5" "test/input/issue-1242/*.js" -mc toplevel';
|
||||
|
||||
exec(command, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, 'var print=console.log.bind(console),a=function(n){return 3*n}(3),b=function(n){return n/2}(12);print("qux",a,b),function(n){print("Foo:",2*n)}(11);\n');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("should handle special characters in glob string", function() {
|
||||
var result = Uglify.minify("test/input/issue-1632/^{*}[???](*)+$.??");
|
||||
assert.strictEqual(result.code, "console.log(x);");
|
||||
it("should throw with non-matching glob string", function(done) {
|
||||
var command = uglifyjscmd + ' "test/input/issue-1242/blah.*"';
|
||||
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.ok(/^ERROR: ENOENT/.test(stderr));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("should handle array of glob strings - matching and otherwise", function() {
|
||||
it('"?" in glob string should not match "/"', function(done) {
|
||||
var command = uglifyjscmd + ' "test/input?issue-1242/foo.*"';
|
||||
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.ok(/^ERROR: ENOENT/.test(stderr));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("should handle special characters in glob string", function(done) {
|
||||
var command = uglifyjscmd + ' "test/input/issue-1632/^{*}[???](*)+$.??" -cm';
|
||||
|
||||
exec(command, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "console.log(x);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("should handle array of glob strings - matching and otherwise", function(done) {
|
||||
var dir = "test/input/issue-1242";
|
||||
var matches = Uglify.simple_glob([
|
||||
var command = uglifyjscmd + ' "' + [
|
||||
path.join(dir, "b*.es5"),
|
||||
path.join(dir, "z*.es5"),
|
||||
path.join(dir, "*.js"),
|
||||
]);
|
||||
assert.strictEqual(matches.length, 4);
|
||||
assert.strictEqual(matches[0], path.join(dir, "bar.es5"));
|
||||
assert.strictEqual(matches[1], path.join(dir, "baz.es5"));
|
||||
assert.strictEqual(matches[2], path.join(dir, "z*.es5"));
|
||||
assert.strictEqual(matches[3], path.join(dir, "qux.js"));
|
||||
path.join(dir, "*.js")
|
||||
].join('" "') + '"';
|
||||
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.ok(/^ERROR: ENOENT.*?z\*\.es5/.test(stderr));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,12 +8,7 @@ describe("Huge number of comments.", function() {
|
||||
for (i = 1; i <= 5000; ++i) { js += "// " + i + "\n"; }
|
||||
for (; i <= 10000; ++i) { js += "/* " + i + " */ /**/"; }
|
||||
js += "x; }";
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true,
|
||||
mangle: false,
|
||||
compress: {}
|
||||
});
|
||||
var result = Uglify.minify(js, { mangle: false });
|
||||
assert.strictEqual(result.code, "function lots_of_comments(x){return 7-x}");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ describe("input sourcemaps", function() {
|
||||
transpilemap = sourceMap || getMap();
|
||||
|
||||
var result = Uglify.minify(transpiled, {
|
||||
fromString: true,
|
||||
inSourceMap: transpilemap,
|
||||
outSourceMap: true
|
||||
sourceMap: {
|
||||
content: transpilemap
|
||||
}
|
||||
});
|
||||
|
||||
map = new SourceMapConsumer(result.map);
|
||||
|
||||
@@ -11,7 +11,7 @@ describe("let", function() {
|
||||
s += "var v" + i + "=0;";
|
||||
}
|
||||
s += '}';
|
||||
var result = Uglify.minify(s, {fromString: true, compress: false});
|
||||
var result = Uglify.minify(s, {compress: false});
|
||||
|
||||
// Verify that select keywords and reserved keywords not produced
|
||||
assert.strictEqual(result.code.indexOf("var let="), -1);
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
var Uglify = require('../../');
|
||||
var Uglify = require("../node");
|
||||
var assert = require("assert");
|
||||
|
||||
describe("line-endings", function() {
|
||||
var options = {
|
||||
fromString: true,
|
||||
mangle: false,
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
beautify: false,
|
||||
comments: /^!/,
|
||||
|
||||
@@ -6,43 +6,41 @@ describe("Input file as map", function() {
|
||||
var jsMap = {
|
||||
'/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};'
|
||||
};
|
||||
var result = Uglify.minify(jsMap, {fromString: true, outSourceMap: true});
|
||||
var result = Uglify.minify(jsMap, {sourceMap: true});
|
||||
|
||||
var map = JSON.parse(result.map);
|
||||
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
|
||||
assert.deepEqual(map.sources, ['/scripts/foo.js']);
|
||||
assert.strictEqual(map.file, undefined);
|
||||
|
||||
result = Uglify.minify(jsMap, {fromString: true, outFileName: 'out.js'});
|
||||
assert.strictEqual(result.map, null);
|
||||
result = Uglify.minify(jsMap);
|
||||
assert.strictEqual(result.map, undefined);
|
||||
|
||||
result = Uglify.minify(jsMap, {fromString: true, outFileName: 'out.js', outSourceMap: true});
|
||||
result = Uglify.minify(jsMap, {sourceMap: {filename: 'out.js'}});
|
||||
map = JSON.parse(result.map);
|
||||
assert.strictEqual(map.file, 'out.js');
|
||||
});
|
||||
|
||||
it("Should accept array of objects and strings", function() {
|
||||
it("Should accept array of strings", function() {
|
||||
var jsSeq = [
|
||||
{'/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};'},
|
||||
'var foo = {"x": 1, y: 2, \'z\': 3};',
|
||||
'var bar = 15;'
|
||||
];
|
||||
var result = Uglify.minify(jsSeq, {fromString: true, outSourceMap: true});
|
||||
var result = Uglify.minify(jsSeq, {sourceMap: true});
|
||||
|
||||
var map = JSON.parse(result.map);
|
||||
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3},bar=15;');
|
||||
assert.strictEqual(map.sources[0], '/scripts/foo.js');
|
||||
assert.deepEqual(map.sources, ['0', '1']);
|
||||
});
|
||||
|
||||
it("Should correctly include source", function() {
|
||||
var jsSeq = [
|
||||
{'/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};'},
|
||||
'var bar = 15;'
|
||||
];
|
||||
var result = Uglify.minify(jsSeq, {fromString: true, outSourceMap: true, sourceMapIncludeSources: true});
|
||||
var jsMap = {
|
||||
'/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};'
|
||||
};
|
||||
var result = Uglify.minify(jsMap, {sourceMap: {includeSources: true}});
|
||||
|
||||
var map = JSON.parse(result.map);
|
||||
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3},bar=15;');
|
||||
assert.deepEqual(map.sourcesContent, ['var foo = {"x": 1, y: 2, \'z\': 3};', 'var bar = 15;']);
|
||||
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
|
||||
assert.deepEqual(map.sourcesContent, ['var foo = {"x": 1, y: 2, \'z\': 3};']);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -2,10 +2,14 @@ var Uglify = require('../../');
|
||||
var assert = require("assert");
|
||||
var readFileSync = require("fs").readFileSync;
|
||||
|
||||
function read(path) {
|
||||
return readFileSync(path, "utf8");
|
||||
}
|
||||
|
||||
describe("minify", function() {
|
||||
it("Should test basic sanity of minify with default options", function() {
|
||||
var js = 'function foo(bar) { if (bar) return 3; else return 7; var u = not_called(); }';
|
||||
var result = Uglify.minify(js, {fromString: true});
|
||||
var result = Uglify.minify(js);
|
||||
assert.strictEqual(result.code, 'function foo(n){return n?3:7}');
|
||||
});
|
||||
|
||||
@@ -13,7 +17,7 @@ describe("minify", function() {
|
||||
it("Should preserve quotes in object literals", function() {
|
||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true, output: {
|
||||
output: {
|
||||
keep_quoted_props: true
|
||||
}});
|
||||
assert.strictEqual(result.code, 'var foo={"x":1,y:2,"z":3};');
|
||||
@@ -22,7 +26,7 @@ describe("minify", function() {
|
||||
it("Should preserve quote styles when quote_style is 3", function() {
|
||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true, output: {
|
||||
output: {
|
||||
keep_quoted_props: true,
|
||||
quote_style: 3
|
||||
}});
|
||||
@@ -32,7 +36,7 @@ describe("minify", function() {
|
||||
it("Should not preserve quotes in object literals when disabled", function() {
|
||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true, output: {
|
||||
output: {
|
||||
keep_quoted_props: false,
|
||||
quote_style: 3
|
||||
}});
|
||||
@@ -44,12 +48,13 @@ describe("minify", function() {
|
||||
it("Shouldn't mangle quoted properties", function() {
|
||||
var js = 'a["foo"] = "bar"; a.color = "red"; x = {"bar": 10};';
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true,
|
||||
compress: {
|
||||
properties: false
|
||||
},
|
||||
mangleProperties: {
|
||||
ignore_quoted: true
|
||||
mangle: {
|
||||
properties: {
|
||||
keep_quoted: true
|
||||
}
|
||||
},
|
||||
output: {
|
||||
keep_quoted_props: true,
|
||||
@@ -63,10 +68,12 @@ describe("minify", function() {
|
||||
|
||||
describe("inSourceMap", function() {
|
||||
it("Should read the given string filename correctly when sourceMapIncludeSources is enabled (#1236)", function() {
|
||||
var result = Uglify.minify('./test/input/issue-1236/simple.js', {
|
||||
outSourceMap: "simple.min.js.map",
|
||||
inSourceMap: "./test/input/issue-1236/simple.js.map",
|
||||
sourceMapIncludeSources: true
|
||||
var result = Uglify.minify(read("./test/input/issue-1236/simple.js"), {
|
||||
sourceMap: {
|
||||
content: read("./test/input/issue-1236/simple.js.map"),
|
||||
filename: "simple.min.js",
|
||||
includeSources: true
|
||||
}
|
||||
});
|
||||
|
||||
var map = JSON.parse(result.map);
|
||||
@@ -77,10 +84,12 @@ describe("minify", function() {
|
||||
'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", {
|
||||
var code = Uglify.minify(read("./test/input/issue-520/input.js"), {
|
||||
compress: { toplevel: true },
|
||||
inSourceMap: "inline",
|
||||
sourceMapInline: true
|
||||
sourceMap: {
|
||||
content: "inline",
|
||||
url: "inline"
|
||||
}
|
||||
}).code + "\n";
|
||||
assert.strictEqual(code, readFileSync("test/input/issue-520/output.js", "utf8"));
|
||||
});
|
||||
@@ -91,9 +100,11 @@ describe("minify", function() {
|
||||
warnings.push(txt);
|
||||
};
|
||||
try {
|
||||
var result = Uglify.minify("./test/input/issue-1323/sample.js", {
|
||||
inSourceMap: "inline",
|
||||
var result = Uglify.minify(read("./test/input/issue-1323/sample.js"), {
|
||||
mangle: false,
|
||||
sourceMap: {
|
||||
content: "inline"
|
||||
}
|
||||
});
|
||||
assert.strictEqual(result.code, "var bar=function(){function foo(bar){return bar}return foo}();");
|
||||
assert.strictEqual(warnings.length, 1);
|
||||
@@ -103,41 +114,34 @@ describe("minify", 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
|
||||
});
|
||||
});
|
||||
});
|
||||
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
|
||||
});
|
||||
var result = Uglify.minify([
|
||||
read("./test/input/issue-520/input.js"),
|
||||
read("./test/input/issue-520/output.js")
|
||||
], {
|
||||
sourceMap: {
|
||||
content: "inline",
|
||||
url: "inline"
|
||||
}
|
||||
});
|
||||
var err = result.error;
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.stack.split(/\n/)[0], "Error: inline source map only works with singular input");
|
||||
});
|
||||
});
|
||||
|
||||
describe("sourceMapInline", function() {
|
||||
it("should append source map to output js when sourceMapInline is enabled", function() {
|
||||
var result = Uglify.minify('var a = function(foo) { return foo; };', {
|
||||
fromString: true,
|
||||
sourceMapInline: true
|
||||
sourceMap: {
|
||||
url: "inline"
|
||||
}
|
||||
});
|
||||
var code = result.code;
|
||||
assert.strictEqual(code, "var a=function(n){return n};\n" +
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIj8iXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsR0FBSUEsR0FBSSxTQUFTQyxHQUFPLE1BQU9BIn0=");
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsR0FBSUEsR0FBSSxTQUFTQyxHQUFPLE1BQU9BIn0=");
|
||||
});
|
||||
it("should not append source map to output js when sourceMapInline is not enabled", function() {
|
||||
var result = Uglify.minify('var a = function(foo) { return foo; };', {
|
||||
fromString: true
|
||||
});
|
||||
var result = Uglify.minify('var a = function(foo) { return foo; };');
|
||||
var code = result.code;
|
||||
assert.strictEqual(code, "var a=function(n){return n};");
|
||||
});
|
||||
@@ -146,7 +150,6 @@ describe("minify", function() {
|
||||
describe("#__PURE__", function() {
|
||||
it("should drop #__PURE__ hint after use", function() {
|
||||
var result = Uglify.minify('//@__PURE__ comment1 #__PURE__ comment2\n foo(), bar();', {
|
||||
fromString: true,
|
||||
output: {
|
||||
comments: "all",
|
||||
beautify: false,
|
||||
@@ -157,7 +160,6 @@ describe("minify", function() {
|
||||
});
|
||||
it("should not drop #__PURE__ hint if function is retained", function() {
|
||||
var result = Uglify.minify("var a = /*#__PURE__*/(function(){ foo(); })();", {
|
||||
fromString: true,
|
||||
output: {
|
||||
comments: "all",
|
||||
beautify: false,
|
||||
@@ -169,27 +171,14 @@ describe("minify", function() {
|
||||
});
|
||||
|
||||
describe("JS_Parse_Error", function() {
|
||||
it("should throw syntax error", function() {
|
||||
assert.throws(function() {
|
||||
Uglify.minify("function f(a{}", { fromString: true });
|
||||
}, function(err) {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token punc «{», expected punc «,»");
|
||||
assert.strictEqual(err.filename, 0);
|
||||
assert.strictEqual(err.line, 1);
|
||||
assert.strictEqual(err.col, 12);
|
||||
return true;
|
||||
});
|
||||
it("should return syntax error", function() {
|
||||
var result = Uglify.minify("function f(a{}");
|
||||
var err = result.error;
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token punc «{», expected punc «,»");
|
||||
assert.strictEqual(err.filename, "0");
|
||||
assert.strictEqual(err.line, 1);
|
||||
assert.strictEqual(err.col, 12);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Compressor", function() {
|
||||
it("should be backward compatible with ast.transform(compressor)", function() {
|
||||
var ast = Uglify.parse("function f(a){for(var i=0;i<a;i++)console.log(i)}");
|
||||
ast.figure_out_scope();
|
||||
ast = ast.transform(Uglify.Compressor());
|
||||
assert.strictEqual(ast.print_to_string(), "function f(a){for(var i=0;i<a;i++)console.log(i)}");
|
||||
});
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
@@ -34,7 +34,6 @@ describe("New", function() {
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.strictEqual(
|
||||
uglify.minify(tests[i], {
|
||||
fromString: true,
|
||||
output: {beautify: true},
|
||||
compress: false,
|
||||
mangle: false
|
||||
@@ -76,7 +75,6 @@ describe("New", function() {
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.strictEqual(
|
||||
uglify.minify(tests[i], {
|
||||
fromString: true,
|
||||
output: {beautify: false},
|
||||
compress: false,
|
||||
mangle: false
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../../");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("Number literals", function () {
|
||||
it("Should not allow legacy octal literals in strict mode", function() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var UglifyJS = require("../../");
|
||||
var UglifyJS = require("../node");
|
||||
var assert = require("assert");
|
||||
|
||||
describe("operator", function() {
|
||||
|
||||
@@ -42,8 +42,8 @@ describe("test/jetstream.js", function() {
|
||||
run("npm", ["install", "phantomjs-prebuilt@2.1.14"], done);
|
||||
});
|
||||
[
|
||||
"-mc warnings=false",
|
||||
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto,warnings=false",
|
||||
"-mc",
|
||||
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
|
||||
].forEach(function(options) {
|
||||
it("Should pass with options " + options, function(done) {
|
||||
var args = options.split(/ /);
|
||||
|
||||
@@ -13,9 +13,7 @@ describe("screw-ie8", function () {
|
||||
}\
|
||||
console.log('undefined is ' + undefined);\
|
||||
return b === undefined;\
|
||||
};", {
|
||||
fromString: true
|
||||
}
|
||||
};"
|
||||
).code,
|
||||
'function a(o){try{throw"Stuff"}catch(o){console.log("caught: "+o)}return console.log("undefined is "+void 0),void 0===o}'
|
||||
);
|
||||
|
||||
@@ -1,32 +1,21 @@
|
||||
var assert = require("assert");
|
||||
var exec = require("child_process").exec;
|
||||
var uglify = require("../../");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("spidermonkey export/import sanity test", function() {
|
||||
it("should produce a functional build when using --self with spidermonkey", function (done) {
|
||||
this.timeout(20000);
|
||||
it("should produce a functional build when using --self with spidermonkey", function(done) {
|
||||
this.timeout(30000);
|
||||
|
||||
var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs';
|
||||
var command = uglifyjs + " --self -cm --wrap SpiderUglify --dump-spidermonkey-ast | " +
|
||||
uglifyjs + " --spidermonkey -cm";
|
||||
var command = uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey | " +
|
||||
uglifyjs + " -p spidermonkey -cm";
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
exec(command, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
eval(stdout);
|
||||
assert.strictEqual(typeof SpiderUglify, "object");
|
||||
|
||||
var ast = SpiderUglify.parse("foo([true,,2+3]);");
|
||||
assert.strictEqual(true, ast instanceof SpiderUglify.AST_Node);
|
||||
|
||||
ast.figure_out_scope();
|
||||
ast = SpiderUglify.Compressor({}).compress(ast);
|
||||
assert.strictEqual(true, ast instanceof SpiderUglify.AST_Node);
|
||||
|
||||
var stream = SpiderUglify.OutputStream({});
|
||||
ast.print(stream);
|
||||
var code = stream.toString();
|
||||
assert.strictEqual(code, "foo([!0,,5]);");
|
||||
assert.strictEqual(SpiderUglify.minify("foo([true,,2+3]);").code, "foo([!0,,5]);");
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var UglifyJS = require('../../');
|
||||
var UglifyJS = require("../node");
|
||||
var assert = require("assert");
|
||||
|
||||
describe("String literals", function() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../../");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("With", function() {
|
||||
it("Should throw syntaxError when using with statement in strict mode", function() {
|
||||
|
||||
@@ -1,103 +1,73 @@
|
||||
// Testing UglifyJS <-> SpiderMonkey AST conversion
|
||||
// through generative testing.
|
||||
"use strict";
|
||||
|
||||
var UglifyJS = require(".."),
|
||||
escodegen = require("escodegen"),
|
||||
esfuzz = require("esfuzz"),
|
||||
estraverse = require("estraverse"),
|
||||
prefix = "\r ";
|
||||
var acorn = require("acorn");
|
||||
var ufuzz = require("./ufuzz");
|
||||
var UglifyJS = require("..");
|
||||
|
||||
// Normalizes input AST for UglifyJS in order to get correct comparison.
|
||||
|
||||
function normalizeInput(ast) {
|
||||
return estraverse.replace(ast, {
|
||||
enter: function(node, parent) {
|
||||
switch (node.type) {
|
||||
// Internally mark all the properties with semi-standard type "Property".
|
||||
case "ObjectExpression":
|
||||
node.properties.forEach(function (property) {
|
||||
property.type = "Property";
|
||||
});
|
||||
break;
|
||||
|
||||
// Since UglifyJS doesn"t recognize different types of property keys,
|
||||
// decision on SpiderMonkey node type is based on check whether key
|
||||
// can be valid identifier or not - so we do in input AST.
|
||||
case "Property":
|
||||
var key = node.key;
|
||||
if (key.type === "Literal" && typeof key.value === "string" && UglifyJS.is_identifier(key.value)) {
|
||||
node.key = {
|
||||
type: "Identifier",
|
||||
name: key.value
|
||||
};
|
||||
} else if (key.type === "Identifier" && !UglifyJS.is_identifier(key.name)) {
|
||||
node.key = {
|
||||
type: "Literal",
|
||||
value: key.name
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
// UglifyJS internally flattens all the expression sequences - either
|
||||
// to one element (if sequence contains only one element) or flat list.
|
||||
case "SequenceExpression":
|
||||
node.expressions = node.expressions.reduce(function flatten(list, expr) {
|
||||
return list.concat(expr.type === "SequenceExpression" ? expr.expressions.reduce(flatten, []) : [expr]);
|
||||
}, []);
|
||||
if (node.expressions.length === 1) {
|
||||
return node.expressions[0];
|
||||
}
|
||||
break;
|
||||
}
|
||||
function try_beautify(code) {
|
||||
var beautified = UglifyJS.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
beautify: true,
|
||||
bracketize: true
|
||||
}
|
||||
});
|
||||
if (beautified.error) {
|
||||
console.log("// !!! beautify failed !!!");
|
||||
console.log(beautified.error.stack);
|
||||
console.log(code);
|
||||
} else {
|
||||
console.log("// (beautified)");
|
||||
console.log(beautified.code);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function(options) {
|
||||
console.log("--- UglifyJS <-> Mozilla AST conversion");
|
||||
|
||||
for (var counter = 0; counter < options.iterations; counter++) {
|
||||
process.stdout.write(prefix + counter + "/" + options.iterations);
|
||||
|
||||
var ast1 = normalizeInput(esfuzz.generate({
|
||||
maxDepth: options.maxDepth
|
||||
}));
|
||||
|
||||
var ast2 =
|
||||
UglifyJS
|
||||
.AST_Node
|
||||
.from_mozilla_ast(ast1)
|
||||
.to_mozilla_ast();
|
||||
|
||||
var astPair = [
|
||||
{name: 'expected', value: ast1},
|
||||
{name: 'actual', value: ast2}
|
||||
];
|
||||
|
||||
var jsPair = astPair.map(function(item) {
|
||||
return {
|
||||
name: item.name,
|
||||
value: escodegen.generate(item.value)
|
||||
}
|
||||
});
|
||||
|
||||
if (jsPair[0].value !== jsPair[1].value) {
|
||||
var fs = require("fs");
|
||||
var acorn = require("acorn");
|
||||
|
||||
fs.existsSync("tmp") || fs.mkdirSync("tmp");
|
||||
|
||||
jsPair.forEach(function (item) {
|
||||
var fileName = "tmp/dump_" + item.name;
|
||||
var ast = acorn.parse(item.value);
|
||||
fs.writeFileSync(fileName + ".js", item.value);
|
||||
fs.writeFileSync(fileName + ".json", JSON.stringify(ast, null, 2));
|
||||
});
|
||||
|
||||
process.stdout.write("\n");
|
||||
throw new Error("Got different outputs, check out tmp/dump_*.{js,json} for codes and ASTs.");
|
||||
function test(original, estree, description) {
|
||||
var transformed = UglifyJS.minify(UglifyJS.AST_Node.from_mozilla_ast(estree), {
|
||||
compress: false,
|
||||
mangle: false
|
||||
});
|
||||
if (transformed.error || original !== transformed.code) {
|
||||
console.log("//=============================================================");
|
||||
console.log("// !!!!!! Failed... round", round);
|
||||
console.log("// original code");
|
||||
try_beautify(original);
|
||||
console.log();
|
||||
console.log();
|
||||
console.log("//-------------------------------------------------------------");
|
||||
console.log("//", description);
|
||||
if (transformed.error) {
|
||||
console.log(transformed.error.stack);
|
||||
} else {
|
||||
try_beautify(transformed.code);
|
||||
}
|
||||
console.log("!!!!!! Failed... round", round);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
process.stdout.write(prefix + "Probability of error is less than " + (100 / options.iterations) + "%, stopping.\n");
|
||||
};
|
||||
var num_iterations = ufuzz.num_iterations;
|
||||
for (var round = 1; round <= num_iterations; round++) {
|
||||
process.stdout.write(round + " of " + num_iterations + "\r");
|
||||
var code = ufuzz.createTopLevelCode();
|
||||
var uglified = UglifyJS.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ast: true
|
||||
}
|
||||
});
|
||||
test(uglified.code, uglified.ast.to_mozilla_ast(), "AST_Node.to_mozilla_ast()");
|
||||
try {
|
||||
test(uglified.code, acorn.parse(code), "acorn.parse()");
|
||||
} catch (e) {
|
||||
console.log("//=============================================================");
|
||||
console.log("// acorn parser failed... round", round);
|
||||
console.log(e);
|
||||
console.log("// original code");
|
||||
console.log(code);
|
||||
}
|
||||
}
|
||||
console.log();
|
||||
|
||||
6
test/node.js
Normal file
6
test/node.js
Normal file
@@ -0,0 +1,6 @@
|
||||
var fs = require("fs");
|
||||
|
||||
new Function("MOZ_SourceMap", "exports", require("../tools/node").FILES.map(function(file) {
|
||||
if (/exports\.js$/.test(file)) file = require.resolve("./exports");
|
||||
return fs.readFileSync(file, "utf8");
|
||||
}).join("\n\n"))(require("source-map"), exports);
|
||||
@@ -1,25 +1,15 @@
|
||||
#! /usr/bin/env node
|
||||
|
||||
var U = require("../tools/node");
|
||||
var U = require("./node");
|
||||
var path = require("path");
|
||||
var fs = require("fs");
|
||||
var assert = require("assert");
|
||||
var vm = require("vm");
|
||||
var sandbox = require("./sandbox");
|
||||
var semver = require("semver");
|
||||
|
||||
var tests_dir = path.dirname(module.filename);
|
||||
var failures = 0;
|
||||
var failed_files = {};
|
||||
var same_stdout = ~process.version.lastIndexOf("v0.12.", 0) ? function(expected, actual) {
|
||||
if (typeof expected != typeof actual) return false;
|
||||
if (typeof expected != "string") {
|
||||
if (expected.name != actual.name) return false;
|
||||
expected = expected.message.slice(expected.message.lastIndexOf("\n") + 1);
|
||||
actual = actual.message.slice(actual.message.lastIndexOf("\n") + 1);
|
||||
}
|
||||
return expected == actual;
|
||||
} : function(expected, actual) {
|
||||
return typeof expected == typeof actual && expected.toString() == actual.toString();
|
||||
};
|
||||
|
||||
run_compress_tests();
|
||||
if (failures) {
|
||||
@@ -34,12 +24,6 @@ mocha_tests();
|
||||
var run_sourcemaps_tests = require('./sourcemaps');
|
||||
run_sourcemaps_tests();
|
||||
|
||||
var run_ast_conversion_tests = require("./mozilla-ast");
|
||||
|
||||
run_ast_conversion_tests({
|
||||
iterations: 1000
|
||||
});
|
||||
|
||||
/* -----[ utils ]----- */
|
||||
|
||||
function tmpl() {
|
||||
@@ -181,12 +165,13 @@ function run_compress_tests() {
|
||||
failed_files[file] = 1;
|
||||
}
|
||||
}
|
||||
if (test.expect_stdout) {
|
||||
var stdout = run_code(input_code);
|
||||
if (test.expect_stdout
|
||||
&& (!test.node_version || semver.satisfies(process.version, test.node_version))) {
|
||||
var stdout = sandbox.run_code(input_code);
|
||||
if (test.expect_stdout === true) {
|
||||
test.expect_stdout = stdout;
|
||||
}
|
||||
if (!same_stdout(test.expect_stdout, stdout)) {
|
||||
if (!sandbox.same_stdout(test.expect_stdout, stdout)) {
|
||||
log("!!! Invalid input or expected stdout\n---INPUT---\n{input}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
|
||||
input: input_formatted,
|
||||
expected_type: typeof test.expect_stdout == "string" ? "STDOUT" : "ERROR",
|
||||
@@ -197,8 +182,8 @@ function run_compress_tests() {
|
||||
failures++;
|
||||
failed_files[file] = 1;
|
||||
} else {
|
||||
stdout = run_code(output);
|
||||
if (!same_stdout(test.expect_stdout, stdout)) {
|
||||
stdout = sandbox.run_code(output);
|
||||
if (!sandbox.same_stdout(test.expect_stdout, stdout)) {
|
||||
log("!!! failed\n---INPUT---\n{input}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
|
||||
input: input_formatted,
|
||||
expected_type: typeof test.expect_stdout == "string" ? "STDOUT" : "ERROR",
|
||||
@@ -291,7 +276,14 @@ function parse_test(file) {
|
||||
if (node instanceof U.AST_LabeledStatement) {
|
||||
var label = node.label;
|
||||
assert.ok(
|
||||
["input", "expect", "expect_exact", "expect_warnings", "expect_stdout"].indexOf(label.name) >= 0,
|
||||
[
|
||||
"input",
|
||||
"expect",
|
||||
"expect_exact",
|
||||
"expect_warnings",
|
||||
"expect_stdout",
|
||||
"node_version",
|
||||
].indexOf(label.name) >= 0,
|
||||
tmpl("Unsupported label {name} [{line},{col}]", {
|
||||
name: label.name,
|
||||
line: label.start.line,
|
||||
@@ -299,7 +291,7 @@ function parse_test(file) {
|
||||
})
|
||||
);
|
||||
var stat = node.body;
|
||||
if (label.name == "expect_exact") {
|
||||
if (label.name == "expect_exact" || label.name == "node_version") {
|
||||
test[label.name] = read_string(stat);
|
||||
} else if (label.name == "expect_stdout") {
|
||||
if (stat.TYPE == "SimpleStatement" && stat.body instanceof U.AST_Boolean) {
|
||||
@@ -330,19 +322,3 @@ function evaluate(code) {
|
||||
code = make_code(code, { beautify: true });
|
||||
return new Function("return(" + code + ")")();
|
||||
}
|
||||
|
||||
function run_code(code) {
|
||||
var stdout = "";
|
||||
var original_write = process.stdout.write;
|
||||
process.stdout.write = function(chunk) {
|
||||
stdout += chunk;
|
||||
};
|
||||
try {
|
||||
new vm.Script(code).runInNewContext({ console: console }, { timeout: 5000 });
|
||||
return stdout;
|
||||
} catch (ex) {
|
||||
return ex;
|
||||
} finally {
|
||||
process.stdout.write = original_write;
|
||||
}
|
||||
}
|
||||
|
||||
77
test/sandbox.js
Normal file
77
test/sandbox.js
Normal file
@@ -0,0 +1,77 @@
|
||||
var semver = require("semver");
|
||||
var vm = require("vm");
|
||||
|
||||
function safe_log(arg, level) {
|
||||
if (arg) switch (typeof arg) {
|
||||
case "function":
|
||||
return arg.toString();
|
||||
case "object":
|
||||
if (/Error$/.test(arg.name)) return arg.toString();
|
||||
arg.constructor.toString();
|
||||
if (level--) for (var key in arg) {
|
||||
if (!Object.getOwnPropertyDescriptor(arg, key).get) {
|
||||
arg[key] = safe_log(arg[key], level);
|
||||
}
|
||||
}
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
var FUNC_TOSTRING = [
|
||||
"Function.prototype.toString = Function.prototype.valueOf = function() {",
|
||||
" var id = 0;",
|
||||
" return function() {",
|
||||
' if (this === Array) return "[Function: Array]";',
|
||||
' if (this === Object) return "[Function: Object]";',
|
||||
" var i = this.name;",
|
||||
' if (typeof i != "number") {',
|
||||
" i = ++id;",
|
||||
' Object.defineProperty(this, "name", {',
|
||||
" get: function() {",
|
||||
" return i;",
|
||||
" }",
|
||||
" });",
|
||||
" }",
|
||||
' return "[Function: " + i + "]";',
|
||||
" }",
|
||||
"}();",
|
||||
].join("\n");
|
||||
exports.run_code = function(code) {
|
||||
var stdout = "";
|
||||
var original_write = process.stdout.write;
|
||||
process.stdout.write = function(chunk) {
|
||||
stdout += chunk;
|
||||
};
|
||||
try {
|
||||
vm.runInNewContext([
|
||||
FUNC_TOSTRING,
|
||||
"!function() {",
|
||||
code,
|
||||
"}();",
|
||||
].join("\n"), {
|
||||
console: {
|
||||
log: function() {
|
||||
return console.log.apply(console, [].map.call(arguments, function(arg) {
|
||||
return safe_log(arg, 3);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}, { timeout: 5000 });
|
||||
return stdout;
|
||||
} catch (ex) {
|
||||
return ex;
|
||||
} finally {
|
||||
process.stdout.write = original_write;
|
||||
}
|
||||
};
|
||||
exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
|
||||
if (typeof expected != typeof actual) return false;
|
||||
if (typeof expected != "string") {
|
||||
if (expected.name != actual.name) return false;
|
||||
expected = expected.message.slice(expected.message.lastIndexOf("\n") + 1);
|
||||
actual = actual.message.slice(actual.message.lastIndexOf("\n") + 1);
|
||||
}
|
||||
return expected == actual;
|
||||
} : function(expected, actual) {
|
||||
return typeof expected == typeof actual && expected.toString() == actual.toString();
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
var UglifyJS = require("..");
|
||||
var UglifyJS = require("./node");
|
||||
var ok = require("assert");
|
||||
|
||||
module.exports = function () {
|
||||
|
||||
1422
test/ufuzz.js
1422
test/ufuzz.js
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user