Compare commits

..

36 Commits
v3.2.2 ... v2.x

Author SHA1 Message Date
Alex Lam S.L
0af80eca22 v2.8.29 2017-06-15 03:19:18 +08:00
Alex Lam S.L
23876a84a5 v2.8.28 2017-06-03 19:33:13 +08:00
Alex Lam S.L
092d0275a0 Merge pull request #2048 from alexlamsl/v2.8.28 2017-06-03 19:11:20 +08:00
Alex Lam S.L
06296bee7f add tests for AST_SymbolAccessor (#2049) 2017-06-03 16:10:44 +08:00
Alex Lam S.L
3818a9e9c1 fix non-identifier getter/setter name (#2041)
fixes #2040
2017-06-03 12:28:18 +08:00
Alex Lam S.L
75e2748b16 v2.8.27 2017-05-19 17:44:50 +08:00
Alex Lam S.L
a7c987ad2b Merge pull request #1971 from alexlamsl/v2.8.27 2017-05-19 17:21:39 +08:00
Alex Lam S.L
957c54bc87 introduce unsafe_regexp (#1970)
fixes #1964
2017-05-19 10:10:09 +08:00
Alex Lam S.L
4cbf5a7821 v2.8.26 2017-05-16 07:13:58 +08:00
Alex Lam S.L
93d4224072 Merge pull request #1947 from alexlamsl/v2.8.26 2017-05-16 07:12:28 +08:00
Alex Lam S.L
6cd580dc23 fix parsing of property access after new line (#1944)
Account for comments when detecting property access in `tokenizer`.

fixes #1943
2017-05-16 06:34:10 +08:00
Alex Lam S.L
ecb63ad8bc improve keyword-related parser errors (#1941)
fixes #1937
2017-05-16 06:33:57 +08:00
Alex Lam S.L
1ca43bcca1 v2.8.25 2017-05-15 19:45:33 +08:00
Alex Lam S.L
3ee1464aa4 Merge pull request #1938 from alexlamsl/v2.8.25 2017-05-15 19:44:44 +08:00
Alex Lam S.L
24967b8be8 fix & improve coverage of estree (#1935)
- fix `estree` conversion of getter/setter
- fix non-directive literal in `to_mozilla_ast()`
- revamp `test/mozilla-ast.js`
  - reuse `test/ufuzz.js` for code generation
  - use `acorn.parse()` for creating `estree`
- extend `test/ufuzz.js` for `acorn` workaround
  - catch variable redefinition
  - non-trivial literal as directive
  - adjust options for tolerance

Miscellaneous
- optional semi-colon when parsing directives

fixes #1914
closes #1915
2017-05-15 18:33:43 +08:00
Alex Lam S.L
a8c67ea353 fix bugs with getter/setter (#1926)
- `reduce_vars`
- `side_effects`
- property access for object
- `AST_SymbolAccessor` as key names

enhance `test/ufuzz.js`
- add object getter & setter
  - property assignment to setter
  - avoid infinite recursion in setter
- fix & adjust assignment operators
  - 50% `=`
  - 25% `+=`
  - 2.5% each for the rest
- avoid "Invalid array length"
- fix `console.log()`
  - bypass getter
  - curb recursive reference
- deprecate `-E`, always report runtime errors
2017-05-15 18:22:43 +08:00
olsonpm
d0b0aecfc5 document 3 max passes (#1928) 2017-05-15 18:18:38 +08:00
olsonpm
9f5a6029a3 clarify wording (#1931) 2017-05-15 18:18:27 +08:00
Alex Lam S.L
4027a0c962 fix parser bugs & CLI reporting (#1827)
fixes #1825
2017-05-15 18:18:04 +08:00
Alex Lam S.L
87f8a484e6 v2.8.24 2017-05-12 15:47:02 +08:00
Alex Lam S.L
c736834aa4 Merge pull request #1921 from alexlamsl/v2.8.24 2017-05-12 14:58:35 +08:00
olsonpm
9a98513981 add documentation for side_effects & [#@]__PURE__ (#1925) 2017-05-12 12:55:07 +08:00
Alex Lam S.L
f631d6437a avoid arguments and eval in reduce_vars (#1924)
fixes #1922
2017-05-12 12:45:38 +08:00
Alex Lam S.L
aa7e8783f8 fix invalid transform on const (#1919)
- preserve (re)assignment to `const` for runtime error
- suppress `cascade` on `const`, as runtime behaviour is ill-defined
2017-05-12 05:04:28 +08:00
Alex Lam S.L
13e5e33448 document known issues with const (#1916) 2017-05-12 03:36:54 +08:00
kzc
487ae8e3be change harmony references to uglify-es in README (#1902) 2017-05-10 16:38:10 +08:00
Alex Lam S.L
5dfda6e212 v2.8.23 2017-05-07 04:31:54 +08:00
Alex Lam S.L
d08c772eb3 Merge pull request #1871 from alexlamsl/v2.8.23 2017-05-07 04:06:51 +08:00
Alex Lam S.L
90ed54401b fix test for #1865 (#1873) 2017-05-07 03:04:17 +08:00
Alex Lam S.L
d8106b6c63 fix label-related bugs (#1835)
- deep cloning of `AST_LabeledStatement`
- `L:do{...}while(false)`
- empty statement with label within block

extend `test/ufuzz.js`
- generate labels for blocks & loops
- generate for-in statements
- skip suspicious option search if `minify()` errs

fixes #1833
2017-05-07 00:16:30 +08:00
alexlamsl
dda4eb96e1 backport test scripts 2017-05-06 23:48:28 +08:00
Alex Lam S.L
7305ba0296 fix unsafe on evaluate of reduce_vars (#1870)
Determine if variables with non-constant values can escape and be modified.

fixes #1865
2017-05-06 23:40:19 +08:00
Alex Lam S.L
2c21dc5e8e fix unused on for-in statements (#1843)
Only need to avoid `var` within the initialisation block.

fixes #1841
2017-05-06 23:34:21 +08:00
Alex Lam S.L
d0faa471db fix unused on labeled for-loop (#1831)
fixes #1830
2017-05-06 23:31:22 +08:00
Alex Lam S.L
6ad823d1e8 fix reduce_vars within try-block (#1818)
Possible partial execution due to exceptions.
2017-05-06 23:28:07 +08:00
Alex Lam S.L
43ad4e9775 fix variable substitution (#1816)
- let `collapse_vars` take care of value containing any symbols
- improve overhead accounting
2017-05-06 23:26:54 +08:00
124 changed files with 10969 additions and 21496 deletions

View File

@@ -1,29 +1,9 @@
**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**
- 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.
<!--
A complete parsable JS program exhibiting the issue with
UglifyJS alone - without third party tools or libraries.
Ideally the input should be as small as possible.
Post a link to a gist if necessary.
Issues without a reproducible test case will be closed.
-->
**The `uglifyjs` CLI command executed or `minify()` options used.**
**JavaScript output or error produced.**
<!--
Note: `uglify-js` only supports ES5.
Those wishing to minify ES6 should use `uglify-es`.
Note: the release version of uglify-js only supports ES5. Those wishing
to minify ES6 should use the experimental harmony branch.
-->

View File

@@ -4,11 +4,8 @@ node_js:
- "0.12"
- "4"
- "6"
- "8"
env:
- UGLIFYJS_TEST_ALL=1
matrix:
fast_finish: true
sudo: false
cache:
directories: tmp

1521
README.md

File diff suppressed because it is too large Load Diff

77
bin/extract-props.js Executable file
View File

@@ -0,0 +1,77 @@
#! /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;
}
}

View File

@@ -3,402 +3,633 @@
"use strict";
// 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);
});
var fs = require("fs");
var info = require("../package.json");
var path = require("path");
var program = require("commander");
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.")
var skip_keys = [ "cname", "enclosed", "inlined", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ];
var files = {};
var options = {
compress: false,
mangle: false
};
program.version(info.name + " " + info.version);
program.parseArgv = program.parse;
program.parse = undefined;
if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
else if (process.argv.indexOf("options") >= 0) program.helpInformation = function() {
var text = [];
var options = UglifyJS.default_options();
for (var option in options) {
text.push("--" + (option == "output" ? "beautify" : option == "sourceMap" ? "source-map" : option) + " options:");
text.push(format_object(options[option]));
text.push("");
}
return text.join("\n");
};
program.option("-p, --parse <options>", "Specify parser options.", parse_js());
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js());
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js());
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("--no-rename", "Disable symbol expansion.");
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("--timings", "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 (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
fatal("ERROR: cannot write source map to STDOUT");
}
[
"compress",
"ie8",
"mangle",
"rename",
"sourceMap",
"toplevel",
"wrap"
].forEach(function(name) {
if (name in program) {
if (name == "rename" && program[name]) return;
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 (program.comments) {
if (typeof options.output != "object") options.output = {};
options.output.comments = typeof program.comments == "string" ? program.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;
}
if (program.nameCache) {
options.nameCache = JSON.parse(read_file(program.nameCache, "{}"));
}
if (program.output == "ast") {
options.output = {
ast: true,
code: false
};
}
if (program.parse) {
if (!program.parse.acorn && !program.parse.spidermonkey) {
options.parse = program.parse;
} else if (program.sourceMap && program.sourceMap.content == "inline") {
fatal("ERROR: inline source map only works with built-in parser");
}
}
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) {
print_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 {
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();
}
.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.")
function convert_ast(fn) {
return UglifyJS.AST_Node.from_mozilla_ast(Object.keys(files).reduce(fn, null));
}
.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.")
function run() {
UglifyJS.AST_Node.warn_function = function(msg) {
.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 (program.timings) options.timings = true;
}
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);
});
if (ARGS.reserve_domprops) {
RESERVED = UglifyJS.readDefaultReservedFile(RESERVED);
}
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,
};
if (ARGS.mangle_props == 2) {
OUTPUT_OPTIONS.keep_quoted_props = true;
if (COMPRESS && !("properties" in COMPRESS))
COMPRESS.properties = false;
}
if (ARGS.support_ie8 === true && ARGS.screw_ie8 !== true) {
screw_ie8 = false;
}
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;
}
if (ARGS.wrap_iife) {
if (COMPRESS) COMPRESS.negate_iife = false;
OUTPUT_OPTIONS.wrap_iife = true;
}
if (BEAUTIFY)
UglifyJS.merge(OUTPUT_OPTIONS, BEAUTIFY);
if (ARGS.comments === "") {
OUTPUT_OPTIONS.comments = "some";
} else {
OUTPUT_OPTIONS.comments = ARGS.comments;
}
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";
}
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
});
}
else {
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
TOPLEVEL = UglifyJS.parse(code, {
filename : file,
toplevel : TOPLEVEL,
expression : ARGS.expr,
bare_returns : ARGS.bare_returns,
});
});
} 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;
});
}
}
} catch (ex) {
fatal(ex);
}
var result = UglifyJS.minify(files, options);
if (result.error) {
var ex = result.error;
if (ex.name == "SyntaxError") {
print_error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
} catch(ex) {
if (ex instanceof UglifyJS.JS_Parse_Error) {
print_error("Parse error at " + file + ":" + ex.line + "," + ex.col);
var col = ex.col;
var lines = files[ex.filename].split(/\r?\n/);
var lines = code.split(/\r?\n/);
var line = lines[ex.line - 1];
if (!line && !col) {
line = lines[ex.line - 2];
col = line.length;
}
if (line) {
var limit = 70;
if (col > limit) {
line = line.slice(col - limit);
col = limit;
if (col > 40) {
line = line.slice(col - 40);
col = 40;
}
print_error(line.slice(0, 80));
print_error(line.slice(0, col).replace(/\S/g, " ") + "^");
}
}
if (ex.defs) {
print_error("Supported options:");
print_error(format_object(ex.defs));
}
fatal(ex);
} else if (program.output == "ast") {
print(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") {
print(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 {
print(result.code);
}
if (program.nameCache) {
fs.writeFileSync(program.nameCache, JSON.stringify(options.nameCache));
}
if (result.timings) for (var phase in result.timings) {
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
}
}
function fatal(message) {
if (message instanceof Error) message = message.stack.replace(/^\S*?Error:/, "ERROR:")
print_error(message);
print_error(ex.stack);
process.exit(1);
}
// 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);
throw ex;
}
};
});
if (results.length) return results;
}
}
return [ glob ];
}
function read_file(path, default_value) {
try {
return fs.readFileSync(path, "utf8");
} catch (ex) {
if (ex.code == "ENOENT" && default_value != null) return default_value;
fatal(ex);
}
}
function parse_js(flag) {
return function(value, options) {
options = options || {};
try {
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 (flag) {
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;
function to_string(value) {
return value instanceof UglifyJS.AST_Constant ? value.getValue() : value.print_to_string({
quote_keys: true
cb();
});
}
}));
}();
function done() {
var OUTPUT_FILE = ARGS.o;
var SOURCE_MAP = (ARGS.source_map || ARGS.source_map_inline) ? UglifyJS.SourceMap({
file: P_RELATIVE ? path.relative(path.dirname(ARGS.source_map), OUTPUT_FILE) : OUTPUT_FILE,
root: ARGS.source_map_root || ORIG_MAP && ORIG_MAP.sourceRoot,
orig: ORIG_MAP,
}) : null;
OUTPUT_OPTIONS.source_map = SOURCE_MAP;
try {
var output = UglifyJS.OutputStream(OUTPUT_OPTIONS);
var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
} catch(ex) {
if (flag) {
fatal("Error parsing arguments for '" + flag + "': " + value);
} else {
options[value] = null;
if (ex instanceof UglifyJS.DefaultsError) {
print_error(ex.message);
print_error("Supported options:");
print_error(sys.inspect(ex.defs));
process.exit(1);
}
}
return options;
}
}
function parse_source_map() {
var parse = parse_js();
return function(value, options) {
var hasContent = options && "content" in options;
var settings = parse(value, options);
if (!hasContent && settings.content && settings.content != "inline") {
print_error("INFO: Using input source map: " + settings.content);
settings.content = read_file(settings.content, settings.content);
}
return settings;
}
}
function skip_key(key) {
return skip_keys.indexOf(key) >= 0;
}
function format_object(obj) {
var lines = [];
var padding = "";
Object.keys(obj).map(function(name) {
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
return [ name, JSON.stringify(obj[name]) ];
}).forEach(function(tokens) {
lines.push(" " + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){
TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
});
return lines.join("\n");
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;
try {
regex = ARGS.mangle_regex ? extractRegex(ARGS.mangle_regex) : null;
} catch (e) {
print_error("ERROR: Invalid --mangle-regex: " + e.message);
process.exit(1);
}
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)
}));
}
}
}
/* -----[ 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);
}
}
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 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();
} else {
fs.readFile(filename, "utf-8", cb);
}
}
function read_source_map(code) {
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
if (!match) {
print_error("WARN: inline source map not found");
return null;
}
return JSON.parse(new Buffer(match[2], "base64"));
}
function time_it(name, cont) {
var t1 = new Date().getTime();
var ret = cont();
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) {
process.stderr.write(msg);
process.stderr.write("\n");
console.error("%s", msg);
}
function print(txt) {
process.stdout.write(txt);
process.stdout.write("\n");
console.log("%s", txt);
}

View File

@@ -134,10 +134,11 @@ var AST_Debugger = DEFNODE("Debugger", null, {
$documentation: "Represents a debugger statement",
}, AST_Statement);
var AST_Directive = DEFNODE("Directive", "value quote", {
var AST_Directive = DEFNODE("Directive", "value scope quote", {
$documentation: "Represents a directive, like \"use strict\";",
$propdoc: {
value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
scope: "[AST_Scope/S] The scope that this directive affects",
quote: "[string] the original quote character"
},
}, AST_Statement);
@@ -181,13 +182,21 @@ var AST_BlockStatement = DEFNODE("BlockStatement", null, {
}, AST_Block);
var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
$documentation: "The empty statement (empty block or simply a semicolon)"
$documentation: "The empty statement (empty block or simply a semicolon)",
_walk: function(visitor) {
return visitor._visit(this);
}
}, 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);
@@ -298,9 +307,10 @@ var AST_With = DEFNODE("With", "expression", {
/* -----[ scope and functions ]----- */
var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent_scope enclosed cname", {
var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
$documentation: "Base class for all statements introducing a lexical scope",
$propdoc: {
directives: "[string*/S] an array of directives declared in this scope",
variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
functions: "[Object/S] like `variables`, but only lists function declarations",
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
@@ -316,14 +326,63 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
$propdoc: {
globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
},
wrap_commonjs: function(name) {
var body = this.body;
var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
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(",") + ")";
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 wrapped_tl;
}
@@ -352,11 +411,11 @@ var AST_Accessor = DEFNODE("Accessor", null, {
$documentation: "A setter/getter function. The `name` property is always null."
}, AST_Lambda);
var AST_Function = DEFNODE("Function", "inlined", {
var AST_Function = DEFNODE("Function", null, {
$documentation: "A function expression"
}, AST_Lambda);
var AST_Defun = DEFNODE("Defun", "inlined", {
var AST_Defun = DEFNODE("Defun", null, {
$documentation: "A function definition"
}, AST_Lambda);
@@ -493,10 +552,10 @@ var AST_Finally = DEFNODE("Finally", null, {
$documentation: "A `finally` node; only makes sense as part of a `try` statement"
}, AST_Block);
/* -----[ VAR ]----- */
/* -----[ VAR/CONST ]----- */
var AST_Definitions = DEFNODE("Definitions", "definitions", {
$documentation: "Base class for `var` nodes (variable declarations/initializations)",
$documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
$propdoc: {
definitions: "[AST_VarDef*] array of variable definitions"
},
@@ -514,10 +573,14 @@ 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] name of the variable",
name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
value: "[AST_Node?] initializer, or null of there's no initializer"
},
_walk: function(visitor) {
@@ -538,11 +601,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);
});
}
});
@@ -551,16 +614,68 @@ 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_Sequence = DEFNODE("Sequence", "expressions", {
$documentation: "A sequence expression (comma-separated expressions)",
var AST_Seq = DEFNODE("Seq", "car cdr", {
$documentation: "A sequence expression (two comma-separated expressions)",
$propdoc: {
expressions: "[AST_Node*] array of expressions (at least two)"
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;
}
},
_walk: function(visitor) {
return visitor._visit(this, function(){
this.expressions.forEach(function(node) {
node._walk(visitor);
});
this.car._walk(visitor);
if (this.cdr) this.cdr._walk(visitor);
});
}
});
@@ -613,7 +728,7 @@ var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
$documentation: "Unary postfix expression, i.e. `i++`"
}, AST_Unary);
var AST_Binary = DEFNODE("Binary", "operator left right", {
var AST_Binary = DEFNODE("Binary", "left operator right", {
$documentation: "Binary expression, i.e. `a + b`",
$propdoc: {
left: "[AST_Node] left-hand side expression",
@@ -722,13 +837,17 @@ var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
}, AST_Symbol);
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
$documentation: "A declaration symbol (symbol in var, function name or argument, symbol in catch)",
$documentation: "A declaration symbol (symbol in var/const, 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);
@@ -857,13 +976,13 @@ TreeWalker.prototype = {
if (!ret && descend) {
descend.call(node);
}
this.pop();
this.pop(node);
return ret;
},
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]) {
@@ -871,8 +990,9 @@ TreeWalker.prototype = {
}
this.stack.push(node);
},
pop: function() {
if (this.stack.pop() instanceof AST_Lambda) {
pop: function(node) {
this.stack.pop();
if (node instanceof AST_Lambda) {
this.directives = Object.getPrototypeOf(this.directives);
}
},
@@ -898,6 +1018,24 @@ TreeWalker.prototype = {
}
}
},
in_boolean_context: function() {
var stack = this.stack;
var i = stack.length, self = stack[--i];
while (i > 0) {
var p = stack[--i];
if ((p instanceof AST_If && p.condition === self) ||
(p instanceof AST_Conditional && p.condition === self) ||
(p instanceof AST_DWLoop && p.condition === self) ||
(p instanceof AST_For && p.condition === self) ||
(p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self))
{
return true;
}
if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")))
return false;
self = p;
}
},
loopcontrol_target: function(node) {
var stack = this.stack;
if (node.label) for (var i = stack.length; --i >= 0;) {

File diff suppressed because it is too large Load Diff

View File

@@ -1,228 +0,0 @@
"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 init_cache(cache) {
if (!cache) return;
if (!("cname" in cache)) cache.cname = -1;
if (!("props" in cache)) {
cache.props = new Dictionary();
} else if (!(cache.props instanceof Dictionary)) {
cache.props = Dictionary.fromObject(cache.props);
}
}
function to_json(cache) {
return {
cname: cache.cname,
props: cache.props.toObject()
};
}
function minify(files, options) {
var warn_function = AST_Node.warn_function;
try {
options = defaults(options, {
compress: {},
ie8: false,
keep_fnames: false,
mangle: {},
nameCache: null,
output: {},
parse: {},
rename: undefined,
sourceMap: false,
timings: false,
toplevel: false,
warnings: false,
wrap: false,
}, true);
var timings = options.timings && {
start: Date.now()
};
if (options.rename === undefined) {
options.rename = options.compress && options.mangle;
}
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" ]);
var quoted_props;
if (options.mangle) {
options.mangle = defaults(options.mangle, {
cache: options.nameCache && (options.nameCache.vars || {}),
eval: false,
ie8: false,
keep_fnames: false,
properties: false,
reserved: [],
toplevel: false,
}, true);
if (options.mangle.properties) {
if (typeof options.mangle.properties != "object") {
options.mangle.properties = {};
}
if (options.mangle.properties.keep_quoted) {
quoted_props = options.mangle.properties.reserved;
if (!Array.isArray(quoted_props)) quoted_props = [];
options.mangle.properties.reserved = quoted_props;
}
if (options.nameCache && !("cache" in options.mangle.properties)) {
options.mangle.properties.cache = options.nameCache.props || {};
}
}
init_cache(options.mangle.cache);
init_cache(options.mangle.properties.cache);
}
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);
};
}
if (timings) timings.parse = Date.now();
var toplevel;
if (files instanceof AST_Toplevel) {
toplevel = files;
} else {
if (typeof files == "string") {
files = [ files ];
}
options.parse = options.parse || {};
options.parse.toplevel = null;
for (var name in files) if (HOP(files, name)) {
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 (quoted_props) {
reserve_quoted_keys(toplevel, quoted_props);
}
if (options.wrap) {
toplevel = toplevel.wrap_commonjs(options.wrap);
}
if (timings) timings.rename = Date.now();
if (options.rename) {
toplevel.figure_out_scope(options.mangle);
toplevel.expand_names(options.mangle);
}
if (timings) timings.compress = Date.now();
if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
if (timings) timings.scope = Date.now();
if (options.mangle) toplevel.figure_out_scope(options.mangle);
if (timings) timings.mangle = Date.now();
if (options.mangle) {
base54.reset();
toplevel.compute_char_frequency(options.mangle);
toplevel.mangle_names(options.mangle);
}
if (timings) timings.properties = Date.now();
if (options.mangle && options.mangle.properties) {
toplevel = mangle_properties(toplevel, options.mangle.properties);
}
if (timings) timings.output = Date.now();
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) {
if (files instanceof AST_Toplevel) {
throw new Error("original source content unavailable");
} else for (var name in files) if (HOP(files, name)) {
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 (options.nameCache && options.mangle) {
if (options.mangle.cache) options.nameCache.vars = to_json(options.mangle.cache);
if (options.mangle.properties && options.mangle.properties.cache) {
options.nameCache.props = to_json(options.mangle.properties.cache);
}
}
if (timings) {
timings.end = Date.now();
result.timings = {
parse: 1e-3 * (timings.rename - timings.parse),
rename: 1e-3 * (timings.compress - timings.rename),
compress: 1e-3 * (timings.scope - timings.compress),
scope: 1e-3 * (timings.mangle - timings.scope),
mangle: 1e-3 * (timings.properties - timings.mangle),
properties: 1e-3 * (timings.output - timings.properties),
output: 1e-3 * (timings.end - timings.output),
total: 1e-3 * (timings.end - timings.start)
}
}
if (warnings.length) {
result.warnings = warnings;
}
return result;
} catch (ex) {
return { error: ex };
} finally {
AST_Node.warn_function = warn_function;
}
}

View File

@@ -145,11 +145,7 @@
});
},
SequenceExpression: function(M) {
return new AST_Sequence({
start : my_start_token(M),
end : my_end_token(M),
expressions: M.expressions.map(from_moz)
});
return AST_Seq.from_array(M.expressions.map(from_moz));
},
MemberExpression: function(M) {
return new (M.computed ? AST_Sub : AST_Dot)({
@@ -168,7 +164,7 @@
});
},
VariableDeclaration: function(M) {
return new AST_Var({
return new (M.kind === "const" ? AST_Const : AST_Var)({
start : my_start_token(M),
end : my_end_token(M),
definitions : M.declarations.map(from_moz)
@@ -204,7 +200,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 ? AST_SymbolVar
: p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : 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
@@ -324,15 +320,15 @@
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
return {
type: "VariableDeclaration",
kind: "var",
kind: M instanceof AST_Const ? "const" : "var",
declarations: M.definitions.map(to_moz)
};
});
def_to_moz(AST_Sequence, function To_Moz_SequenceExpression(M) {
def_to_moz(AST_Seq, function To_Moz_SequenceExpression(M) {
return {
type: "SequenceExpression",
expressions: M.expressions.map(to_moz)
expressions: M.to_array().map(to_moz)
};
});

View File

@@ -57,7 +57,6 @@ function OutputStream(options) {
beautify : false,
bracketize : false,
comments : false,
ie8 : false,
indent_level : 4,
indent_start : 0,
inline_script : true,
@@ -67,10 +66,12 @@ function OutputStream(options) {
preserve_line : false,
quote_keys : false,
quote_style : 0,
screw_ie8 : true,
semicolons : true,
shebang : true,
source_map : null,
webkit : false,
space_colon : true,
unescape_regexps : false,
width : 80,
wrap_iife : false,
}, true);
@@ -109,7 +110,7 @@ function OutputStream(options) {
var current_pos = 0;
var OUTPUT = "";
var to_utf8 = options.ascii_only ? function(str, identifier) {
function to_ascii(str, identifier) {
return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
var code = ch.charCodeAt(0).toString(16);
if (code.length <= 2 && !identifier) {
@@ -120,12 +121,6 @@ function OutputStream(options) {
return "\\u" + code;
}
});
} : function(str) {
return str.replace(/[\ud800-\udbff](?![\udc00-\udfff])/g, function(ch) {
return "\\u" + ch.charCodeAt(0).toString(16);
}).replace(/(^|[^\ud800-\udbff])([\udc00-\udfff])/g, function(match, prefix, ch) {
return prefix + "\\u" + ch.charCodeAt(0).toString(16);
});
};
function make_string(str, quote) {
@@ -141,12 +136,12 @@ function OutputStream(options) {
case "\t": return "\\t";
case "\b": return "\\b";
case "\f": return "\\f";
case "\x0B": return options.ie8 ? "\\x0B" : "\\v";
case "\x0B": return options.screw_ie8 ? "\\v" : "\\x0B";
case "\u2028": return "\\u2028";
case "\u2029": return "\\u2029";
case "\ufeff": return "\\ufeff";
case "\0":
return /[0-9]/.test(str.charAt(i+1)) ? "\\x00" : "\\0";
return /[0-7]/.test(str.charAt(i+1)) ? "\\x00" : "\\0";
}
return s;
});
@@ -156,7 +151,7 @@ function OutputStream(options) {
function quote_double() {
return '"' + str.replace(/\x22/g, '\\"') + '"';
}
str = to_utf8(str);
if (options.ascii_only) str = to_ascii(str);
switch (options.quote_style) {
case 1:
return quote_single();
@@ -181,7 +176,8 @@ function OutputStream(options) {
function make_name(name) {
name = name.toString();
name = to_utf8(name, true);
if (options.ascii_only)
name = to_ascii(name, true);
return name;
};
@@ -195,43 +191,12 @@ function OutputStream(options) {
var might_need_semicolon = false;
var might_add_newline = 0;
var last = "";
var mapping_token, mapping_name, mappings = options.source_map && [];
var do_add_mapping = mappings ? function() {
mappings.forEach(function(mapping) {
try {
options.source_map.add(
mapping.token.file,
mapping.line, mapping.col,
mapping.token.line, mapping.token.col,
!mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name
);
} catch(ex) {
AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
file: mapping.token.file,
line: mapping.token.line,
col: mapping.token.col,
cline: mapping.line,
ccol: mapping.col,
name: mapping.name || ""
})
}
});
mappings = [];
} : noop;
var ensure_line_len = options.max_line_len ? function() {
if (current_col > options.max_line_len) {
if (might_add_newline) {
var left = OUTPUT.slice(0, might_add_newline);
var right = OUTPUT.slice(might_add_newline);
if (mappings) {
var delta = right.length - current_col;
mappings.forEach(function(mapping) {
mapping.line++;
mapping.col += delta;
});
}
OUTPUT = left + "\n" + right;
current_line++;
current_pos++;
@@ -241,10 +206,7 @@ function OutputStream(options) {
AST_Node.warn("Output exceeds {max_line_len} characters", options);
}
}
if (might_add_newline) {
might_add_newline = 0;
do_add_mapping();
}
} : noop;
var requireSemicolonChars = makePredicate("( [ + * / - , .");
@@ -304,18 +266,6 @@ function OutputStream(options) {
}
might_need_space = false;
}
if (mapping_token) {
mappings.push({
token: mapping_token,
name: mapping_name,
line: current_line,
col: current_col
});
mapping_token = false;
if (!might_add_newline) do_add_mapping();
}
OUTPUT += str;
current_pos += str.length;
var a = str.split(/\r?\n/), n = a.length - 1;
@@ -407,12 +357,27 @@ function OutputStream(options) {
function colon() {
print(":");
space();
if (options.space_colon) space();
};
var add_mapping = mappings ? function(token, name) {
mapping_token = token;
mapping_name = name;
var add_mapping = options.source_map ? function(token, name) {
try {
if (token) options.source_map.add(
token.file || "?",
current_line, current_col,
token.line, token.col,
(!name && token.type == "name") ? token.value : name
);
} catch(ex) {
AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
file: token.file,
line: token.line,
col: token.col,
cline: current_line,
ccol: current_col,
name: name || ""
})
}
} : noop;
function get() {
@@ -438,7 +403,7 @@ function OutputStream(options) {
last : function() { return last },
semicolon : semicolon,
force_semicolon : force_semicolon,
to_utf8 : to_utf8,
to_ascii : to_ascii,
print_name : function(name) { print(make_name(name)) },
print_string : function(str, quote, escape_directive) {
var encoded = encode_string(str, quote);
@@ -482,17 +447,13 @@ function OutputStream(options) {
nodetype.DEFMETHOD("_codegen", generator);
};
var use_asm = false;
var in_directive = false;
var active_scope = null;
var use_asm = null;
AST_Node.DEFMETHOD("print", function(stream, force_parens){
var self = this, generator = self._codegen;
if (self instanceof AST_Scope) {
active_scope = self;
}
else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") {
use_asm = active_scope;
var self = this, generator = self._codegen, prev_use_asm = use_asm;
if (self instanceof AST_Directive && self.value == "use asm" && stream.parent() instanceof AST_Scope) {
use_asm = true;
}
function doit() {
self.add_comments(stream);
@@ -506,11 +467,10 @@ function OutputStream(options) {
doit();
}
stream.pop_node();
if (self === use_asm) {
use_asm = null;
if (self instanceof AST_Scope) {
use_asm = prev_use_asm;
}
});
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
AST_Node.DEFMETHOD("print_to_string", function(options){
var s = OutputStream(options);
@@ -608,13 +568,6 @@ function OutputStream(options) {
return true;
}
if (output.option('webkit')) {
var p = output.parent();
if (p instanceof AST_PropAccess && p.expression === this) {
return true;
}
}
if (output.option('wrap_iife')) {
var p = output.parent();
return p instanceof AST_Call && p.expression === this;
@@ -635,7 +588,7 @@ function OutputStream(options) {
|| p instanceof AST_Call && p.expression === this;
});
PARENS(AST_Sequence, function(output){
PARENS(AST_Seq, 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)
@@ -681,15 +634,14 @@ function OutputStream(options) {
// parens around it too, otherwise the call will be
// interpreted as passing the arguments to the upper New
// expression.
var parens = false;
this.walk(new TreeWalker(function(node) {
if (parens || node instanceof AST_Scope) return true;
if (node instanceof AST_Call) {
parens = true;
try {
this.walk(new TreeWalker(function(node){
if (node instanceof AST_Call) throw p;
}));
} catch(ex) {
if (ex !== p) throw ex;
return true;
}
}));
return parens;
}
});
@@ -725,7 +677,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)
@@ -950,7 +902,7 @@ function OutputStream(options) {
function make_then(self, output) {
var b = self.body;
if (output.option("bracketize")
|| output.option("ie8") && b instanceof AST_Do)
|| !output.option("screw_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
@@ -1081,19 +1033,24 @@ 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) {
var parens = false;
if (!noin) node.print(output);
else try {
// need to take some precautions here:
// https://github.com/mishoo/UglifyJS2/issues/60
if (noin) node.walk(new TreeWalker(function(node) {
if (parens || node instanceof AST_Scope) return true;
if (node instanceof AST_Binary && node.operator == "in") {
parens = true;
return true;
}
node.walk(new TreeWalker(function(node){
if (node instanceof AST_Binary && node.operator == "in")
throw output;
}));
node.print(output, parens);
node.print(output);
} catch(ex) {
if (ex !== output) throw ex;
node.print(output, true);
}
};
DEFPRINT(AST_VarDef, function(self, output){
@@ -1113,9 +1070,6 @@ function OutputStream(options) {
self.expression.print(output);
if (self instanceof AST_New && !need_constructor_parens(self, output))
return;
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
output.add_mapping(self.start);
}
output.with_parens(function(){
self.args.forEach(function(expr, i){
if (i) output.comma();
@@ -1129,19 +1083,18 @@ function OutputStream(options) {
AST_Call.prototype._codegen(self, output);
});
AST_Sequence.DEFMETHOD("_do_print", function(output){
this.expressions.forEach(function(node, index) {
if (index > 0) {
AST_Seq.DEFMETHOD("_do_print", function(output){
this.car.print(output);
if (this.cdr) {
output.comma();
if (output.should_break()) {
output.newline();
output.indent();
}
this.cdr.print(output);
}
node.print(output);
});
});
DEFPRINT(AST_Sequence, function(self, output){
DEFPRINT(AST_Seq, function(self, output){
self._do_print(output);
// var p = output.parent();
// if (p instanceof AST_Statement) {
@@ -1155,13 +1108,6 @@ function OutputStream(options) {
DEFPRINT(AST_Dot, function(self, output){
var expr = self.expression;
expr.print(output);
var prop = self.property;
if (output.option("ie8") && RESERVED_WORDS(prop)) {
output.print("[");
output.add_mapping(self.end);
output.print_string(prop);
output.print("]");
} else {
if (expr instanceof AST_Number && expr.getValue() >= 0) {
if (!/[xa-f.)]/i.test(output.last())) {
output.print(".");
@@ -1170,8 +1116,7 @@ function OutputStream(options) {
output.print(".");
// the name after dot would be mapped about here.
output.add_mapping(self.end);
output.print_name(prop);
}
output.print_name(self.property);
});
DEFPRINT(AST_Sub, function(self, output){
self.expression.print(output);
@@ -1271,7 +1216,7 @@ function OutputStream(options) {
&& +key + "" == key)
&& parseFloat(key) >= 0) {
output.print(make_num(key));
} else if (RESERVED_WORDS(key) ? !output.option("ie8") : is_identifier_string(key)) {
} else if (RESERVED_WORDS(key) ? output.option("screw_ie8") : is_identifier_string(key)) {
if (quote && output.option("keep_quoted_props")) {
output.print_string(key, quote);
} else {
@@ -1321,13 +1266,46 @@ 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 regexp = self.getValue();
var str = regexp.toString();
if (regexp.raw_source) {
str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
var str = self.getValue().toString();
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("\\\\");
}
str = output.to_utf8(str);
output.print(str);
var p = output.parent();
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)

View File

@@ -115,6 +115,8 @@ var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,;:"));
var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
/* -----[ Tokenizer ]----- */
// regexps adapted from http://xregexp.com/plugins/#unicode
@@ -475,31 +477,29 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
return name;
};
var read_regexp = with_eof_error("Unterminated regular expression", function(source) {
var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){
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) {
source += "\\" + ch;
regexp += "\\" + ch;
prev_backslash = false;
} else if (ch == "[") {
in_class = true;
source += ch;
regexp += ch;
} else if (ch == "]" && in_class) {
in_class = false;
source += ch;
regexp += ch;
} else if (ch == "/" && !in_class) {
break;
} else if (ch == "\\") {
prev_backslash = true;
} else {
source += ch;
regexp += ch;
}
var mods = read_name();
try {
var regexp = new RegExp(source, mods);
regexp.raw_source = source;
return token("regexp", regexp);
return token("regexp", new RegExp(regexp, mods));
} catch(e) {
parse_error(e.message);
}
@@ -633,7 +633,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
}
next_token.has_directive = function(directive) {
return S.directives[directive] > 0;
return S.directives[directive] !== undefined &&
S.directives[directive] > 0;
}
return next_token;
@@ -682,7 +683,9 @@ var PRECEDENCE = (function(a, ret){
{}
);
var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "string", "regexp", "name" ]);
var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
/* -----[ Parser ]----- */
@@ -690,13 +693,14 @@ function parse($TEXT, options) {
options = defaults(options, {
bare_returns : false,
cli : false,
expression : false,
filename : null,
html5_comments : true,
shebang : true,
strict : false,
toplevel : null,
}, true);
});
var S = {
input : (typeof $TEXT == "string"
@@ -937,6 +941,12 @@ function parse($TEXT, options) {
semicolon();
return node;
case "const":
next();
var node = const_();
semicolon();
return node;
case "with":
if (S.input.has_directive("use strict")) {
croak("Strict mode may not include a with statement");
@@ -1010,12 +1020,8 @@ function parse($TEXT, options) {
? (next(), var_(true))
: expression(true, true);
if (is("operator", "in")) {
if (init instanceof AST_Var) {
if (init.definitions.length > 1)
croak("Only one variable declaration allowed in for..in loop", init.start.line, init.start.col, init.start.pos);
} else if (!is_assignable(init)) {
croak("Invalid left-hand side in for..in loop", init.start.line, init.start.col, init.start.pos);
}
if (init instanceof AST_Var && init.definitions.length > 1)
croak("Only one variable declaration allowed in for..in loop");
next();
return for_in(init);
}
@@ -1054,35 +1060,30 @@ function parse($TEXT, options) {
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
if (in_statement && !name)
unexpected();
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
unexpected(prev());
expect("(");
var argnames = [];
for (var first = true; !is("punc", ")");) {
return new ctor({
name: name,
argnames: (function(first, a){
while (!is("punc", ")")) {
if (first) first = false; else expect(",");
argnames.push(as_symbol(AST_SymbolFunarg));
a.push(as_symbol(AST_SymbolFunarg));
}
next();
var loop = S.in_loop;
var labels = S.labels;
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 body = block_();
if (S.input.has_directive("use strict")) {
if (name) strict_verify_symbol(name);
argnames.forEach(strict_verify_symbol);
}
var a = block_();
S.input.pop_directives_stack();
--S.in_function;
S.in_loop = loop;
S.labels = labels;
return new ctor({
name: name,
argnames: argnames,
body: body
return a;
})(S.in_loop, S.labels)
});
};
@@ -1178,12 +1179,12 @@ function parse($TEXT, options) {
});
};
function vardefs(no_in) {
function vardefs(no_in, in_const) {
var a = [];
for (;;) {
a.push(new AST_VarDef({
start : S.token,
name : as_symbol(AST_SymbolVar),
name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
end : prev()
}));
@@ -1197,7 +1198,15 @@ function parse($TEXT, options) {
var var_ = function(no_in) {
return new AST_Var({
start : prev(),
definitions : vardefs(no_in),
definitions : vardefs(no_in, false),
end : prev()
});
};
var const_ = function() {
return new AST_Const({
start : prev(),
definitions : vardefs(false, true),
end : prev()
});
};
@@ -1224,6 +1233,7 @@ function parse($TEXT, options) {
var tok = S.token, ret;
switch (tok.type) {
case "name":
case "keyword":
ret = _make_symbol(AST_SymbolRef);
break;
case "num":
@@ -1253,6 +1263,13 @@ function parse($TEXT, options) {
break;
}
break;
case "operator":
if (!is_identifier_string(tok.value)) {
croak("Invalid getter/setter name: " + tok.value,
tok.line, tok.col, tok.pos);
}
ret = _make_symbol(AST_SymbolRef);
break;
}
next();
return ret;
@@ -1286,7 +1303,7 @@ function parse($TEXT, options) {
func.end = prev();
return subscripts(func, allow_calls);
}
if (ATOMIC_START_TOKEN(S.token.type)) {
if (ATOMIC_START_TOKEN[S.token.type]) {
return subscripts(as_atom_node(), allow_calls);
}
unexpected();
@@ -1400,20 +1417,12 @@ 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;
};
@@ -1474,17 +1483,8 @@ function parse($TEXT, options) {
function make_unary(ctor, token, expr) {
var op = token.value;
switch (op) {
case "++":
case "--":
if (!is_assignable(expr))
if ((op == "++" || op == "--") && !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 });
};
@@ -1529,6 +1529,7 @@ function parse($TEXT, options) {
};
function is_assignable(expr) {
if (options.cli) return true;
return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef;
};
@@ -1553,18 +1554,17 @@ function parse($TEXT, options) {
var expression = function(commas, no_in) {
var start = S.token;
var exprs = [];
while (true) {
exprs.push(maybe_assign(no_in));
if (!commas || !is("punc", ",")) break;
var expr = maybe_assign(no_in);
if (commas && is("punc", ",")) {
next();
commas = true;
}
return exprs.length == 1 ? exprs[0] : new AST_Sequence({
return new AST_Seq({
start : start,
expressions : exprs,
car : expr,
cdr : expression(true, no_in),
end : peek()
});
}
return expr;
};
function in_loop(cont) {

View File

@@ -43,16 +43,16 @@
"use strict";
function find_builtins(reserved) {
function find_builtins() {
// NaN will be included due to Number.NaN
[
var a = [
"null",
"true",
"false",
"Infinity",
"-Infinity",
"undefined",
].forEach(add);
];
[ Object, Array, Function, Number,
String, Boolean, Error, Math,
Date, RegExp
@@ -63,52 +63,24 @@ function find_builtins(reserved) {
}
});
function add(name) {
push_uniq(reserved, name);
push_uniq(a, name);
}
}
function reserve_quoted_keys(ast, reserved) {
function add(name) {
push_uniq(reserved, name);
}
ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ObjectKeyVal && node.quote) {
add(node.key);
} else if (node instanceof AST_Sub) {
addStrings(node.property, add);
}
}));
}
function addStrings(node, add) {
node.walk(new TreeWalker(function(node) {
if (node instanceof AST_Sequence) {
addStrings(node.tail_node(), add);
} else if (node instanceof AST_String) {
add(node.value);
} else if (node instanceof AST_Conditional) {
addStrings(node.consequent, add);
addStrings(node.alternative, add);
}
return true;
}));
return a;
}
function mangle_properties(ast, options) {
options = defaults(options, {
builtins: false,
cache: null,
debug: false,
keep_quoted: false,
ignore_quoted: false,
only_cache: false,
regex: null,
reserved: null,
}, true);
});
var reserved = options.reserved;
if (!Array.isArray(reserved)) reserved = [];
if (!options.builtins) find_builtins(reserved);
if (reserved == null)
reserved = find_builtins();
var cache = options.cache;
if (cache == null) {
@@ -119,11 +91,12 @@ function mangle_properties(ast, options) {
}
var regex = options.regex;
var ignore_quoted = options.ignore_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);
@@ -131,11 +104,12 @@ function mangle_properties(ast, options) {
var names_to_mangle = [];
var unmangleable = [];
var ignored = {};
// step 1: find candidates to mangle
ast.walk(new TreeWalker(function(node){
if (node instanceof AST_ObjectKeyVal) {
add(node.key);
add(node.key, ignore_quoted && node.quote);
}
else if (node instanceof AST_ObjectProperty) {
// setter or getter, since KeyVal is handled above
@@ -145,13 +119,14 @@ function mangle_properties(ast, options) {
add(node.property);
}
else if (node instanceof AST_Sub) {
addStrings(node.property, add);
addStrings(node.property, ignore_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))
node.key = mangle(node.key);
}
else if (node instanceof AST_ObjectProperty) {
@@ -161,9 +136,22 @@ function mangle_properties(ast, options) {
else if (node instanceof AST_Dot) {
node.property = mangle(node.property);
}
else if (!options.keep_quoted && node instanceof AST_Sub) {
else if (node instanceof AST_Sub) {
if (!ignore_quoted)
node.property = mangleStrings(node.property);
}
// else if (node instanceof AST_String) {
// if (should_mangle(node.value)) {
// AST_Node.warn(
// "Found \"{prop}\" property candidate for mangling in an arbitrary string [{file}:{line},{col}]", {
// file : node.start.file,
// line : node.start.line,
// col : node.start.col,
// prop : node.value
// }
// );
// }
// }
}));
// only function declarations after this line
@@ -179,13 +167,19 @@ function mangle_properties(ast, options) {
}
function should_mangle(name) {
if (ignore_quoted && name in ignored) 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) {
function add(name, ignore) {
if (ignore) {
ignored[name] = true;
return;
}
if (can_mangle(name))
push_uniq(names_to_mangle, name);
@@ -205,16 +199,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)) {
if (can_mangle(debug_mangled) && !(ignore_quoted && debug_mangled in ignored)) {
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
// check so we don't collide with a quoted name.
do {
mangled = base54(++cache.cname);
} while (!can_mangle(mangled));
} while (!can_mangle(mangled) || (ignore_quoted && mangled in ignored));
}
cache.props.set(name, mangled);
@@ -222,11 +219,36 @@ function mangle_properties(ast, options) {
return mangled;
}
function addStrings(node, ignore) {
var out = {};
try {
(function walk(node){
node.walk(new TreeWalker(function(node){
if (node instanceof AST_Seq) {
walk(node.cdr);
return true;
}
if (node instanceof AST_String) {
add(node.value, ignore);
return true;
}
if (node instanceof AST_Conditional) {
walk(node.consequent);
walk(node.alternative);
return true;
}
throw out;
}));
})(node);
} catch(ex) {
if (ex !== out) throw ex;
}
}
function mangleStrings(node) {
return node.transform(new TreeTransformer(function(node){
if (node instanceof AST_Sequence) {
var last = node.expressions.length - 1;
node.expressions[last] = mangleStrings(node.expressions[last]);
if (node instanceof AST_Seq) {
node.cdr = mangleStrings(node.cdr);
}
else if (node instanceof AST_String) {
node.value = mangle(node.value);
@@ -238,4 +260,5 @@ function mangle_properties(ast, options) {
return node;
}));
}
}

View File

@@ -43,16 +43,15 @@
"use strict";
function SymbolDef(scope, orig) {
function SymbolDef(scope, index, orig) {
this.name = orig.name;
this.orig = [ orig ];
this.eliminated = 0;
this.scope = scope;
this.references = [];
this.replaced = 0;
this.global = false;
this.mangled_name = null;
this.undeclared = false;
this.index = index;
this.id = SymbolDef.next_id++;
};
@@ -77,10 +76,10 @@ SymbolDef.prototype = {
else if (!this.mangled_name && !this.unmangleable(options)) {
var s = this.scope;
var sym = this.orig[0];
if (options.ie8 && sym instanceof AST_SymbolLambda)
if (!options.screw_ie8 && sym instanceof AST_SymbolLambda)
s = s.parent_scope;
var def;
if (def = this.redefined()) {
if (this.defun && (def = this.defun.variables.get(this.name))) {
this.mangled_name = def.mangled_name || def.name;
} else
this.mangled_name = s.next_mangled(options, this);
@@ -88,16 +87,13 @@ SymbolDef.prototype = {
cache.set(this.name, this.mangled_name);
}
}
},
redefined: function() {
return this.defun && this.defun.variables.get(this.name);
}
};
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
options = defaults(options, {
cache: null,
ie8: false,
screw_ie8: true,
});
// pass 1: setup scope chaining and handle definitions
@@ -160,7 +156,8 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
// later.
(node.scope = defun.parent_scope).def_function(node);
}
else if (node instanceof AST_SymbolVar) {
else if (node instanceof AST_SymbolVar
|| node instanceof AST_SymbolConst) {
defun.def_variable(node);
if (defun !== scope) {
node.mark_enclosed(options);
@@ -187,8 +184,16 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
self.walk(tw);
// pass 2: find back references and eval
self.globals = new Dictionary();
var func = null;
var globals = self.globals = new Dictionary();
var tw = new TreeWalker(function(node, descend){
if (node instanceof AST_Lambda) {
var prev_func = func;
func = node;
descend();
func = prev_func;
return true;
}
if (node instanceof AST_LoopControl && node.label) {
node.label.thedef.references.push(node);
return true;
@@ -201,30 +206,21 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
}
}
var sym = node.scope.find_variable(name);
if (node.scope instanceof AST_Lambda && name == "arguments") {
node.scope.uses_arguments = true;
}
if (!sym) {
sym = self.def_global(node);
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
sym.scope.uses_arguments = true;
}
node.thedef = sym;
node.reference(options);
return true;
}
// ensure mangling works if catch reuses a scope variable
var def;
if (node instanceof AST_SymbolCatch && (def = node.definition().redefined())) {
var s = node.scope;
while (s) {
push_uniq(s.enclosed, def);
if (s === def.scope) break;
s = s.parent_scope;
}
}
});
self.walk(tw);
// pass 3: fix up any scoping issue with IE8
if (options.ie8) {
if (!options.screw_ie8) {
self.walk(new TreeWalker(function(node, descend) {
if (node instanceof AST_SymbolCatch) {
var name = node.name;
@@ -236,7 +232,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
ref.reference(options);
});
node.thedef = def;
node.reference(options);
return true;
}
}));
@@ -252,7 +247,7 @@ AST_Toplevel.DEFMETHOD("def_global", function(node){
if (globals.has(name)) {
return globals.get(name);
} else {
var g = new SymbolDef(this, node);
var g = new SymbolDef(this, globals.size(), node);
g.undeclared = true;
g.global = true;
globals.set(name, g);
@@ -273,7 +268,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_SymbolFunarg({
this.def_variable(new AST_SymbolVar({
name: "arguments",
start: this.start,
end: this.end
@@ -313,7 +308,7 @@ AST_Scope.DEFMETHOD("def_function", function(symbol){
AST_Scope.DEFMETHOD("def_variable", function(symbol){
var def;
if (!this.variables.has(symbol.name)) {
def = new SymbolDef(this, symbol);
def = new SymbolDef(this, this.variables.size(), symbol);
this.variables.set(symbol.name, def);
def.global = !this.parent_scope;
} else {
@@ -330,8 +325,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 reserved from mangling.
if (member(m, options.reserved)) continue;
// shadow a name excepted from mangling.
if (options.except.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
@@ -363,18 +358,31 @@ AST_Function.DEFMETHOD("next_mangled", function(options, def){
});
AST_Symbol.DEFMETHOD("unmangleable", function(options){
var def = this.definition();
return !def || def.unmangleable(options);
return this.definition().unmangleable(options);
});
// labels are always mangleable
AST_Label.DEFMETHOD("unmangleable", return_false);
AST_Label.DEFMETHOD("unmangleable", function(){
return false;
});
AST_Symbol.DEFMETHOD("unreferenced", function(){
return this.definition().references.length == 0
&& !(this.scope.uses_eval || this.scope.uses_with);
});
AST_Symbol.DEFMETHOD("undeclared", function(){
return this.definition().undeclared;
});
AST_LabelRef.DEFMETHOD("undeclared", function(){
return false;
});
AST_Label.DEFMETHOD("undeclared", function(){
return false;
});
AST_Symbol.DEFMETHOD("definition", function(){
return this.thedef;
});
@@ -383,23 +391,23 @@ AST_Symbol.DEFMETHOD("global", function(){
return this.definition().global;
});
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) {
options = defaults(options, {
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
return defaults(options, {
eval : false,
ie8 : false,
except : [],
keep_fnames : false,
reserved : [],
screw_ie8 : true,
sort : false, // Ignored. Flag retained for backwards compatibility.
toplevel : false,
});
if (!Array.isArray(options.reserved)) options.reserved = [];
// Never mangle arguments
push_uniq(options.reserved, "arguments");
return options;
});
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
options = this._default_mangler_options(options);
// Never mangle arguments
options.except.push('arguments');
// We only need to mangle declaration nodes. Special logic wired
// into the code generator will display the mangled name if it's
// present (and for AST_SymbolRef-s it'll use the mangled name of
@@ -408,7 +416,11 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
var to_mangle = [];
if (options.cache) {
this.globals.each(collect);
this.globals.each(function(symbol){
if (options.except.indexOf(symbol.name) < 0) {
to_mangle.push(symbol);
}
});
}
var tw = new TreeWalker(function(node, descend){
@@ -420,7 +432,13 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
return true; // don't descend again in TreeWalker
}
if (node instanceof AST_Scope) {
node.variables.each(collect);
var p = tw.parent(), a = [];
node.variables.each(function(symbol){
if (options.except.indexOf(symbol.name) < 0) {
a.push(symbol);
}
});
to_mangle.push.apply(to_mangle, a);
return;
}
if (node instanceof AST_Label) {
@@ -429,7 +447,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
node.mangled_name = name;
return true;
}
if (!options.ie8 && node instanceof AST_SymbolCatch) {
if (options.screw_ie8 && node instanceof AST_SymbolCatch) {
to_mangle.push(node.definition());
return;
}
@@ -440,146 +458,109 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
if (options.cache) {
options.cache.cname = this.cname;
}
function collect(symbol) {
if (!member(symbol.name, options.reserved)) {
to_mangle.push(symbol);
}
}
});
AST_Toplevel.DEFMETHOD("find_unique_prefix", function(options) {
var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
var cache = options.cache && options.cache.props;
var prefixes = Object.create(null);
options.reserved.forEach(add_prefix);
this.globals.each(add_def);
this.walk(new TreeWalker(function(node) {
if (node instanceof AST_Scope) node.variables.each(add_def);
if (node instanceof AST_SymbolCatch) add_def(node.definition());
}));
var prefix, i = 0;
do {
prefix = create_name(i++);
} while (prefixes[prefix]);
return prefix;
function add_prefix(name) {
if (/[0-9]$/.test(name)) {
prefixes[name.replace(/[0-9]+$/, "")] = true;
}
}
function add_def(def) {
var name = def.name;
if (def.global && cache && cache.has(name)) name = cache.get(name);
else if (!def.unmangleable(options)) return;
add_prefix(name);
}
function create_name(num) {
var name = "";
do {
name += letters[num % letters.length];
num = Math.floor(num / letters.length);
} while (num);
return name;
}
});
AST_Toplevel.DEFMETHOD("expand_names", function(options) {
options = this._default_mangler_options(options);
var prefix = this.find_unique_prefix(options);
this.globals.each(rename);
this.walk(new TreeWalker(function(node) {
if (node instanceof AST_Scope) node.variables.each(rename);
if (node instanceof AST_SymbolCatch) rename(node.definition());
}));
function rename(def) {
if (def.global || def.unmangleable(options)) return;
if (member(def.name, options.reserved)) return;
var d = def.redefined();
def.name = d ? d.name : prefix + def.id;
def.orig.forEach(function(sym) {
sym.name = def.name;
});
def.references.forEach(function(sym) {
sym.name = def.name;
});
}
});
AST_Node.DEFMETHOD("tail_node", return_this);
AST_Sequence.DEFMETHOD("tail_node", function() {
return this.expressions[this.expressions.length - 1];
});
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
options = this._default_mangler_options(options);
try {
AST_Node.prototype.print = function(stream, force_parens) {
this._print(stream, force_parens);
if (this instanceof AST_Symbol && !this.unmangleable(options)) {
base54.consider(this.name, -1);
} else if (options.properties) {
if (this instanceof AST_Dot) {
base54.consider(this.property, -1);
} else if (this instanceof AST_Sub) {
skip_string(this.property);
}
}
};
base54.consider(this.print_to_string(), 1);
} finally {
AST_Node.prototype.print = AST_Node.prototype._print;
var tw = new TreeWalker(function(node){
if (node instanceof AST_Constant)
base54.consider(node.print_to_string());
else if (node instanceof AST_Return)
base54.consider("return");
else if (node instanceof AST_Throw)
base54.consider("throw");
else if (node instanceof AST_Continue)
base54.consider("continue");
else if (node instanceof AST_Break)
base54.consider("break");
else if (node instanceof AST_Debugger)
base54.consider("debugger");
else if (node instanceof AST_Directive)
base54.consider(node.value);
else if (node instanceof AST_While)
base54.consider("while");
else if (node instanceof AST_Do)
base54.consider("do while");
else if (node instanceof AST_If) {
base54.consider("if");
if (node.alternative) base54.consider("else");
}
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)
base54.consider("for");
else if (node instanceof AST_ForIn)
base54.consider("for in");
else if (node instanceof AST_Switch)
base54.consider("switch");
else if (node instanceof AST_Case)
base54.consider("case");
else if (node instanceof AST_Default)
base54.consider("default");
else if (node instanceof AST_With)
base54.consider("with");
else if (node instanceof AST_ObjectSetter)
base54.consider("set" + node.key);
else if (node instanceof AST_ObjectGetter)
base54.consider("get" + node.key);
else if (node instanceof AST_ObjectKeyVal)
base54.consider(node.key);
else if (node instanceof AST_New)
base54.consider("new");
else if (node instanceof AST_This)
base54.consider("this");
else if (node instanceof AST_Try)
base54.consider("try");
else if (node instanceof AST_Catch)
base54.consider("catch");
else if (node instanceof AST_Finally)
base54.consider("finally");
else if (node instanceof AST_Symbol && node.unmangleable(options))
base54.consider(node.name);
else if (node instanceof AST_Unary || node instanceof AST_Binary)
base54.consider(node.operator);
else if (node instanceof AST_Dot)
base54.consider(node.property);
});
this.walk(tw);
base54.sort();
function skip_string(node) {
if (node instanceof AST_String) {
base54.consider(node.value, -1);
} else if (node instanceof AST_Conditional) {
skip_string(node.consequent);
skip_string(node.alternative);
} else if (node instanceof AST_Sequence) {
skip_string(node.tail_node());
}
}
});
var base54 = (function() {
var leading = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_".split("");
var digits = "0123456789".split("");
var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
var chars, frequency;
function reset() {
frequency = Object.create(null);
leading.forEach(function(ch) {
frequency[ch] = 0;
});
digits.forEach(function(ch) {
frequency[ch] = 0;
});
chars = string.split("").map(function(ch){ return ch.charCodeAt(0) });
chars.forEach(function(ch){ frequency[ch] = 0 });
}
base54.consider = function(str, delta) {
base54.consider = function(str){
for (var i = str.length; --i >= 0;) {
frequency[str[i]] += delta;
var code = str.charCodeAt(i);
if (code in frequency) ++frequency[code];
}
};
function compare(a, b) {
return frequency[b] - frequency[a];
}
base54.sort = function() {
chars = mergeSort(leading, compare).concat(mergeSort(digits, compare));
chars = mergeSort(chars, function(a, b){
if (is_digit(a) && !is_digit(b)) return 1;
if (is_digit(b) && !is_digit(a)) return -1;
return frequency[b] - frequency[a];
});
};
base54.reset = reset;
reset();
base54.get = function(){ return chars };
base54.freq = function(){ return frequency };
function base54(num) {
var ret = "", base = 54;
num++;
do {
num--;
ret += chars[num % base];
ret += String.fromCharCode(chars[num % base]);
num = Math.floor(num / base);
base = 64;
} while (num > 0);
@@ -587,3 +568,89 @@ var base54 = (function() {
};
return base54;
})();
AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
options = defaults(options, {
assign_to_global : true,
eval : true,
func_arguments : true,
nested_defuns : true,
undeclared : false, // this makes a lot of noise
unreferenced : 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);
});

View File

@@ -70,7 +70,7 @@ TreeTransformer.prototype = new TreeWalker;
if (y !== undefined) x = y;
}
}
tw.pop();
tw.pop(this);
return x;
});
};
@@ -174,8 +174,9 @@ TreeTransformer.prototype = new TreeWalker;
self.args = do_list(self.args, tw);
});
_(AST_Sequence, function(self, tw){
self.expressions = do_list(self.expressions, tw);
_(AST_Seq, function(self, tw){
self.car = self.car.transform(tw);
self.cdr = self.cdr.transform(tw);
});
_(AST_Dot, function(self, tw){

View File

@@ -43,6 +43,13 @@
"use strict";
function array_to_hash(a) {
var ret = Object.create(null);
for (var i = 0; i < a.length; ++i)
ret[a[i]] = true;
return ret;
};
function slice(a, start) {
return Array.prototype.slice.call(a, start || 0);
};
@@ -339,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_Sequence && p.expressions[0] === node) ||
if ((p instanceof AST_Seq && p.car === 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 ) ||

View File

@@ -4,7 +4,7 @@
"homepage": "http://lisperator.net/uglifyjs",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.2.2",
"version": "2.8.29",
"engines": {
"node": ">=0.8.0"
},
@@ -29,16 +29,23 @@
"LICENSE"
],
"dependencies": {
"commander": "~2.12.1",
"source-map": "~0.6.1"
"source-map": "~0.5.1",
"yargs": "~3.10.0"
},
"devDependencies": {
"acorn": "~5.2.1",
"mocha": "~3.5.1",
"semver": "~5.4.1"
"acorn": "~5.0.3",
"mocha": "~2.3.4"
},
"optionalDependencies": {
"uglify-to-browserify": "~1.0.0"
},
"browserify": {
"transform": [
"uglify-to-browserify"
]
},
"scripts": {
"test": "node test/run-tests.js"
},
"keywords": ["uglify", "uglify-js", "minify", "minifier", "es5"]
"keywords": ["uglify", "uglify-js", "minify", "minifier"]
}

View File

@@ -4,14 +4,12 @@
"use strict";
var createHash = require("crypto").createHash;
var fetch = require("./fetch");
var fork = require("child_process").fork;
var zlib = require("zlib");
var args = process.argv.slice(2);
if (!args.length) {
args.push("-mc");
args.push("-mc", "warnings=false");
}
args.push("--timings");
args.push("--stats");
var urls = [
"https://code.jquery.com/jquery-3.2.1.js",
"https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js",
@@ -32,9 +30,13 @@ function done() {
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("Run-time:", elapsed.toFixed(3), "s");
console.log("Original:", info.input, "bytes");
console.log("Uglified:", info.output, "bytes");
console.log("GZipped: ", info.gzip, "bytes");
console.log("SHA1 sum:", info.sha1);
if (info.code) {
failures.push(url);
@@ -53,21 +55,15 @@ urls.forEach(function(url) {
results[url] = {
input: 0,
output: 0,
gzip: 0,
log: ""
};
fetch(url, function(err, res) {
if (err) throw err;
require(url.slice(0, url.indexOf(":"))).get(url, function(res) {
var uglifyjs = fork("bin/uglifyjs", args, { silent: true });
res.on("data", function(data) {
results[url].input += data.length;
}).pipe(uglifyjs.stdin);
uglifyjs.stdout.on("data", function(data) {
results[url].output += data.length;
}).pipe(zlib.createGzip({
level: zlib.Z_BEST_COMPRESSION
})).on("data", function(data) {
results[url].gzip += data.length;
}).pipe(createHash("sha1")).on("data", function(data) {
results[url].sha1 = data.toString("hex");
done();

67
test/compress/angular-inject.js vendored Normal file
View File

@@ -0,0 +1,67 @@
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;
}])
}
}

View File

@@ -128,114 +128,50 @@ constant_join_3: {
for_loop: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unsafe: true,
unused: true,
unsafe : true,
unused : true,
evaluate : true,
reduce_vars : true
};
input: {
function f0() {
var a = [1, 2, 3];
var b = 0;
for (var i = 0; i < a.length; i++)
b += a[i];
return b;
for (var i = 0; i < a.length; i++) {
console.log(a[i]);
}
}
function f1() {
var a = [1, 2, 3];
var b = 0;
for (var i = 0, len = a.length; i < len; i++)
b += a[i];
return b;
for (var i = 0, len = a.length; i < len; i++) {
console.log(a[i]);
}
}
function f2() {
var a = [1, 2, 3];
for (var i = 0; i < a.length; i++)
for (var i = 0; i < a.length; i++) {
a[i]++;
return a[2];
}
console.log(f0(), f1(), f2());
}
}
expect: {
function f0() {
var a = [1, 2, 3];
var b = 0;
for (var i = 0; i < 3; i++)
b += a[i];
return b;
console.log(a[i]);
}
function f1() {
var a = [1, 2, 3];
var b = 0;
for (var i = 0; i < 3; i++)
b += a[i];
return b;
console.log(a[i]);
}
function f2() {
var a = [1, 2, 3];
for (var i = 0; i < a.length; i++)
a[i]++;
return a[2];
}
console.log(f0(), f1(), f2());
}
expect_stdout: "6 6 4"
}
index: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var a = [ 1, 2 ];
console.log(a[0], a[1]);
}
expect: {
console.log(1, 2);
}
expect_stdout: "1 2"
}
length: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var a = [ 1, 2 ];
console.log(a.length);
}
expect: {
console.log(2);
}
expect_stdout: "2"
}
index_length: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var a = [ 1, 2 ];
console.log(a[0], a.length);
}
expect: {
console.log(1, 2);
}
expect_stdout: "1 2"
}

View File

@@ -2,7 +2,7 @@ ascii_only_true: {
options = {}
beautify = {
ascii_only : true,
ie8 : false,
screw_ie8 : true,
beautify : false,
}
input: {
@@ -13,14 +13,14 @@ ascii_only_true: {
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
}
}
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\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\'}'
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\'}'
}
ascii_only_false: {
options = {}
beautify = {
ascii_only : false,
ie8 : false,
screw_ie8 : true,
beautify : false,
}
input: {
@@ -31,5 +31,6 @@ ascii_only_false: {
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
}
}
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\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\'}'
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\'}'
}

View File

@@ -104,65 +104,3 @@ asm_mixed: {
}
}
asm_toplevel: {
options = {}
input: {
"use asm";
0.0;
function f() {
0.0;
(function(){
0.0;
});
}
0.0;
}
expect_exact: '"use asm";0.0;function f(){0.0;(function(){0.0})}0.0;'
}
asm_function_expression: {
options = {}
input: {
0.0;
var a = function() {
"use asm";
0.0;
}
function f() {
0.0;
return function(){
"use asm";
0.0;
}
0.0;
}
0.0;
}
expect_exact: '0;var a=function(){"use asm";0.0};function f(){0;return function(){"use asm";0.0};0}0;'
}
asm_nested_functions: {
options = {}
input: {
0.0;
function a() {
"use asm";
0.0;
}
0.0;
function b() {
0.0;
function c(){
"use asm";
0.0;
}
0.0;
function d(){
0.0;
}
0.0;
}
0.0;
}
expect_exact: '0;function a(){"use asm";0.0}0;function b(){0;function c(){"use asm";0.0}0;function d(){0}0}0;'
}

File diff suppressed because it is too large Load Diff

View File

@@ -74,41 +74,3 @@ dont_change_in_or_instanceof_expressions: {
null instanceof null;
}
}
self_comparison_1: {
options = {
comparisons: true,
}
input: {
a === a;
a !== b;
b.c === a.c;
b.c !== b.c;
}
expect: {
a == a;
a !== b;
b.c === a.c;
b.c != b.c;
}
}
self_comparison_2: {
options = {
comparisons: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
input: {
function f() {}
var o = {};
console.log(f != f, o === o);
}
expect: {
function f() {}
var o = {};
console.log(false, true);
}
expect_stdout: "false true"
}

View File

@@ -21,7 +21,7 @@ concat_1: {
var c = 1 + x() + 2 + "boo";
var d = 1 + x() + 2 + 3 + "boo";
var e = 1 + x() + 2 + "X3boo";
var f = "\x00360\x008\0";
var f = "\x00360\08\0";
}
}

View File

@@ -166,24 +166,22 @@ cond_1: {
conditionals: true
};
input: {
function foo(do_something, some_condition) {
if (some_condition) {
var do_something; // if undeclared it's assumed to have side-effects
if (some_condition()) {
do_something(x);
} else {
do_something(y);
}
if (some_condition) {
if (some_condition()) {
side_effects(x);
} else {
side_effects(y);
}
}
}
expect: {
function foo(do_something, some_condition) {
do_something(some_condition ? x : y);
some_condition ? side_effects(x) : side_effects(y);
}
var do_something;
do_something(some_condition() ? x : y);
some_condition() ? side_effects(x) : side_effects(y);
}
}
@@ -192,18 +190,16 @@ cond_2: {
conditionals: true
};
input: {
function foo(x, FooBar, some_condition) {
if (some_condition) {
var x, FooBar;
if (some_condition()) {
x = new FooBar(1);
} else {
x = new FooBar(2);
}
}
}
expect: {
function foo(x, FooBar, some_condition) {
x = new FooBar(some_condition ? 1 : 2);
}
var x, FooBar;
x = new FooBar(some_condition() ? 1 : 2);
}
}
@@ -609,42 +605,6 @@ cond_8c: {
}
}
cond_9: {
options = {
conditionals: true,
}
input: {
function f(x, y) {
g() ? x(1) : x(2);
x ? (y || x)() : (y || x)();
x ? y(a, b) : y(d, b, c);
x ? y(a, b, c) : y(a, b, c);
x ? y(a, b, c) : y(a, b, f);
x ? y(a, b, c) : y(a, e, c);
x ? y(a, b, c) : y(a, e, f);
x ? y(a, b, c) : y(d, b, c);
x ? y(a, b, c) : y(d, b, f);
x ? y(a, b, c) : y(d, e, c);
x ? y(a, b, c) : y(d, e, f);
}
}
expect: {
function f(x, y) {
g() ? x(1) : x(2);
x, (y || x)();
x ? y(a, b) : y(d, b, c);
x, y(a, b, c);
y(a, b, x ? c : f);
y(a, x ? b : e, c);
x ? y(a, b, c) : y(a, e, f);
y(x ? a : d, b, c);
x ? y(a, b, c) : y(d, b, f);
x ? y(a, b, c) : y(d, e, c);
x ? y(a, b, c) : y(d, e, f);
}
}
}
ternary_boolean_consequent: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
@@ -1019,12 +979,12 @@ delete_conditional_1: {
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);
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((NaN, !0));
}
expect_stdout: true
}
@@ -1046,160 +1006,12 @@ delete_conditional_2: {
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);
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((NaN, !0));
}
expect_stdout: true
}
issue_2535_1: {
options = {
booleans: true,
conditionals: true,
evaluate: true,
passes: 2,
side_effects: true,
}
input: {
if (true || x()) y();
if (true && x()) y();
if (x() || true) y();
if (x() && true) y();
if (false || x()) y();
if (false && x()) y();
if (x() || false) y();
if (x() && false) y();
}
expect: {
y();
x() && y();
(x(), 1) && y();
x() && y();
x() && y();
x() && y();
(x(), 0) && y();
}
}
issue_2535_2: {
options = {
booleans: true,
conditionals: true,
evaluate: true,
side_effects: true,
}
input: {
function x() {}
function y() {
return "foo";
}
console.log((x() || true) || y());
console.log((y() || true) || x());
console.log((x() || true) && y());
console.log((y() || true) && x());
console.log((x() && true) || y());
console.log((y() && true) || x());
console.log((x() && true) && y());
console.log((y() && true) && x());
console.log((x() || false) || y());
console.log((y() || false) || x());
console.log((x() || false) && y());
console.log((y() || false) && x());
console.log((x() && false) || y());
console.log((y() && false) || x());
console.log((x() && false) && y());
console.log((y() && false) && x());
}
expect: {
function x() {}
function y() {
return "foo";
}
console.log(x() || !0);
console.log(y() || !0);
console.log((x(), y()));
console.log((y(), x()));
console.log(!!x() || y());
console.log(!!y() || x());
console.log(x() && y());
console.log(y() && x());
console.log(x() || y());
console.log(y() || x());
console.log(!!x() && y());
console.log(!!y() && x());
console.log((x(), y()));
console.log((y(), x()));
console.log(x() && !1);
console.log(y() && !1);
}
expect_stdout: [
"true",
"foo",
"foo",
"undefined",
"foo",
"true",
"undefined",
"undefined",
"foo",
"foo",
"false",
"undefined",
"foo",
"undefined",
"undefined",
"false",
]
}
issue_2560: {
options = {
conditionals: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function log(x) {
console.log(x);
}
function foo() {
return log;
}
function bar() {
if (x !== (x = foo())) {
x(1);
} else {
x(2);
}
}
var x = function() {
console.log("init");
};
bar();
bar();
}
expect: {
function log(x) {
console.log(x);
}
function bar() {
x !== (x = log) ? x(1) : x(2);
}
var x = function() {
console.log("init");
};
bar();
bar();
}
expect_stdout: [
"1",
"2",
]
}

166
test/compress/const.js Normal file
View File

@@ -0,0 +1,166 @@
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
}

View File

@@ -31,7 +31,7 @@ dead_code_2_should_warn: {
function f() {
g();
x = 10;
throw new Error("foo");
throw "foo";
// completely discarding the `if` would introduce some
// bugs. UglifyJS v1 doesn't deal with this issue; in v2
// we copy any declarations to the upper scope.
@@ -46,60 +46,16 @@ dead_code_2_should_warn: {
})();
}
}
f();
}
expect: {
function f() {
g();
x = 10;
throw new Error("foo");
throw "foo";
var x;
function g(){};
}
f();
}
expect_stdout: true
node_version: "<=4"
}
dead_code_2_should_warn_strict: {
options = {
dead_code: true
};
input: {
"use strict";
function f() {
g();
x = 10;
throw new Error("foo");
// completely discarding the `if` would introduce some
// bugs. UglifyJS v1 doesn't deal with this issue; in v2
// we copy any declarations to the upper scope.
if (x) {
y();
var x;
function g(){};
// but nested declarations should not be kept.
(function(){
var q;
function y(){};
})();
}
}
f();
}
expect: {
"use strict";
function f() {
g();
x = 10;
throw new Error("foo");
var x;
}
f();
}
expect_stdout: true
node_version: ">=4"
}
dead_code_constant_boolean_should_warn_more: {
@@ -122,55 +78,141 @@ dead_code_constant_boolean_should_warn_more: {
foo();
var moo;
}
bar();
}
expect: {
var foo;
function bar() {}
// nothing for the while
// as for the for, it should keep:
var moo;
var x = 10, y;
bar();
var moo;
}
expect_stdout: true
node_version: "<=4"
}
dead_code_constant_boolean_should_warn_more_strict: {
dead_code_const_declaration: {
options = {
dead_code : true,
loops : true,
booleans : true,
conditionals : true,
evaluate : true,
side_effects : true,
reduce_vars : true,
};
input: {
"use strict";
while (!((foo && bar) || (x + "0"))) {
var unused;
const CONST_FOO = false;
if (CONST_FOO) {
console.log("unreachable");
var foo;
var moo;
function bar() {}
}
for (var x = 10, y; x && (y || x) && (!typeof x); ++x) {
asdf();
foo();
var moo;
}
bar();
}
expect: {
"use strict";
var foo;
// nothing for the while
// as for the for, it should keep:
var unused;
const CONST_FOO = !1;
var moo;
var x = 10, y;
bar();
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
node_version: ">=4"
}
try_catch_finally: {
@@ -178,8 +220,6 @@ try_catch_finally: {
conditionals: true,
dead_code: true,
evaluate: true,
passes: 2,
side_effects: true,
}
input: {
var a = 1;
@@ -232,188 +272,3 @@ accessor: {
}
expect: {}
}
issue_2233_1: {
options = {
pure_getters: "strict",
side_effects: true,
unsafe: true,
}
input: {
Array.isArray;
Boolean;
console.log;
Date;
decodeURI;
decodeURIComponent;
encodeURI;
encodeURIComponent;
Error.name;
escape;
eval;
EvalError;
Function.length;
isFinite;
isNaN;
JSON;
Math.random;
Number.isNaN;
parseFloat;
parseInt;
RegExp;
Object.defineProperty;
String.fromCharCode;
RangeError;
ReferenceError;
SyntaxError;
TypeError;
unescape;
URIError;
}
expect: {}
expect_stdout: true
}
global_timeout_and_interval_symbols: {
options = {
pure_getters: "strict",
side_effects: true,
unsafe: true,
}
input: {
// These global symbols do not exist in the test sandbox
// and must be tested separately.
clearInterval;
clearTimeout;
setInterval;
setTimeout;
}
expect: {}
}
issue_2233_2: {
options = {
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unsafe: true,
unused: true,
}
input: {
var RegExp;
Array.isArray;
RegExp;
UndeclaredGlobal;
function foo() {
var Number;
AnotherUndeclaredGlobal;
Math.sin;
Number.isNaN;
}
}
expect: {
var RegExp;
UndeclaredGlobal;
function foo() {
var Number;
AnotherUndeclaredGlobal;
Number.isNaN;
}
}
}
issue_2233_3: {
options = {
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var RegExp;
Array.isArray;
RegExp;
UndeclaredGlobal;
function foo() {
var Number;
AnotherUndeclaredGlobal;
Math.sin;
Number.isNaN;
}
}
expect: {
UndeclaredGlobal;
}
}
global_fns: {
options = {
side_effects: true,
unsafe: true,
}
input: {
Boolean(1, 2);
decodeURI(1, 2);
decodeURIComponent(1, 2);
Date(1, 2);
encodeURI(1, 2);
encodeURIComponent(1, 2);
Error(1, 2);
escape(1, 2);
EvalError(1, 2);
isFinite(1, 2);
isNaN(1, 2);
Number(1, 2);
Object(1, 2);
parseFloat(1, 2);
parseInt(1, 2);
RangeError(1, 2);
ReferenceError(1, 2);
String(1, 2);
SyntaxError(1, 2);
TypeError(1, 2);
unescape(1, 2);
URIError(1, 2);
try {
Function(1, 2);
} catch (e) {
console.log(e.name);
}
try {
RegExp(1, 2);
} catch (e) {
console.log(e.name);
}
try {
Array(NaN);
} catch (e) {
console.log(e.name);
}
}
expect: {
try {
Function(1, 2);
} catch (e) {
console.log(e.name);
}
try {
RegExp(1, 2);
} catch (e) {
console.log(e.name);
}
try {
Array(NaN);
} catch (e) {
console.log(e.name);
}
}
expect_stdout: [
"SyntaxError",
"SyntaxError",
"RangeError",
]
}

View File

@@ -179,9 +179,7 @@ keep_fnames: {
}
drop_assign: {
options = {
unused: true,
}
options = { unused: true };
input: {
function f1() {
var a;
@@ -202,7 +200,7 @@ drop_assign: {
var a;
return function() {
a = 1;
};
}
}
}
expect: {
@@ -219,17 +217,16 @@ drop_assign: {
return 1;
}
function f5() {
var a;
return function() {
1;
};
a = 1;
}
}
}
}
keep_assign: {
options = {
unused: "keep_assign",
}
options = { unused: "keep_assign" };
input: {
function f1() {
var a;
@@ -250,7 +247,7 @@ keep_assign: {
var a;
return function() {
a = 1;
};
}
}
}
expect: {
@@ -273,22 +270,19 @@ keep_assign: {
var a;
return function() {
a = 1;
};
}
}
}
}
drop_toplevel_funcs: {
options = {
toplevel: "funcs",
unused: true,
}
options = { toplevel: "funcs", unused: true };
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
};
}
}
a = 2;
function g() {}
@@ -304,16 +298,13 @@ drop_toplevel_funcs: {
}
drop_toplevel_vars: {
options = {
toplevel: "vars",
unused: true,
}
options = { toplevel: "vars", unused: true };
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
};
}
}
a = 2;
function g() {}
@@ -321,10 +312,11 @@ drop_toplevel_vars: {
console.log(b = 3);
}
expect: {
var c = g;
function f(d) {
return function() {
2;
};
c = 2;
}
}
2;
function g() {}
@@ -334,17 +326,13 @@ drop_toplevel_vars: {
}
drop_toplevel_vars_fargs: {
options = {
keep_fargs: false,
toplevel: "vars",
unused: true,
}
options = { keep_fargs: false, toplevel: "vars", unused: true };
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
};
}
}
a = 2;
function g() {}
@@ -352,10 +340,11 @@ drop_toplevel_vars_fargs: {
console.log(b = 3);
}
expect: {
var c = g;
function f() {
return function() {
2;
};
c = 2;
}
}
2;
function g() {}
@@ -365,16 +354,13 @@ drop_toplevel_vars_fargs: {
}
drop_toplevel_all: {
options = {
toplevel: true,
unused: true
}
options = { toplevel: true, unused: true };
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
};
}
}
a = 2;
function g() {}
@@ -388,16 +374,13 @@ drop_toplevel_all: {
}
drop_toplevel_retain: {
options = {
top_retain: "f,a,o",
unused: true,
}
options = { top_retain: "f,a,o", unused: true };
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
};
}
}
a = 2;
function g() {}
@@ -405,28 +388,26 @@ drop_toplevel_retain: {
console.log(b = 3);
}
expect: {
var a;
var a, c = g;
function f(d) {
return function() {
2;
};
c = 2;
}
}
a = 2;
function g() {}
console.log(3);
}
}
drop_toplevel_retain_array: {
options = {
top_retain: [ "f", "a", "o" ],
unused: true,
}
options = { top_retain: [ "f", "a", "o" ], unused: true };
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
};
}
}
a = 2;
function g() {}
@@ -434,28 +415,26 @@ drop_toplevel_retain_array: {
console.log(b = 3);
}
expect: {
var a;
var a, c = g;
function f(d) {
return function() {
2;
};
c = 2;
}
}
a = 2;
function g() {}
console.log(3);
}
}
drop_toplevel_retain_regex: {
options = {
top_retain: /^[fao]$/,
unused: true,
}
options = { top_retain: /^[fao]$/, unused: true };
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
};
}
}
a = 2;
function g() {}
@@ -463,29 +442,26 @@ drop_toplevel_retain_regex: {
console.log(b = 3);
}
expect: {
var a;
var a, c = g;
function f(d) {
return function() {
2;
};
c = 2;
}
}
a = 2;
function g() {}
console.log(3);
}
}
drop_toplevel_all_retain: {
options = {
toplevel: true,
top_retain: "f,a,o",
unused: true,
}
options = { toplevel: true, top_retain: "f,a,o", unused: true };
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
};
}
}
a = 2;
function g() {}
@@ -493,29 +469,26 @@ drop_toplevel_all_retain: {
console.log(b = 3);
}
expect: {
var a;
var a, c = g;
function f(d) {
return function() {
2;
};
c = 2;
}
}
a = 2;
function g() {}
console.log(3);
}
}
drop_toplevel_funcs_retain: {
options = {
toplevel: "funcs",
top_retain: "f,a,o",
unused: true,
}
options = { toplevel: "funcs", top_retain: "f,a,o", unused: true };
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
};
}
}
a = 2;
function g() {}
@@ -527,7 +500,7 @@ drop_toplevel_funcs_retain: {
function f(d) {
return function() {
c = 2;
};
}
}
a = 2;
function g() {}
@@ -536,17 +509,13 @@ drop_toplevel_funcs_retain: {
}
drop_toplevel_vars_retain: {
options = {
toplevel: "vars",
top_retain: "f,a,o",
unused: true,
}
options = { toplevel: "vars", top_retain: "f,a,o", unused: true };
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
};
}
}
a = 2;
function g() {}
@@ -554,11 +523,11 @@ drop_toplevel_vars_retain: {
console.log(b = 3);
}
expect: {
var a;
var a, c = g;
function f(d) {
return function() {
2;
};
c = 2;
}
}
a = 2;
function g() {}
@@ -568,16 +537,13 @@ drop_toplevel_vars_retain: {
}
drop_toplevel_keep_assign: {
options = {
toplevel: true,
unused: "keep_assign",
}
options = { toplevel: true, unused: "keep_assign" };
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
};
}
}
a = 2;
function g() {}
@@ -683,6 +649,37 @@ 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,
@@ -707,7 +704,6 @@ issue_1539: {
vardef_value: {
options = {
keep_fnames: false,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -769,7 +765,6 @@ assign_chain: {
issue_1583: {
options = {
keep_fargs: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -787,10 +782,10 @@ issue_1583: {
expect: {
function m(t) {
(function(e) {
(function() {
t = (function() {
return (function(a) {
return function(a) {};
})();
return a;
})(function(a) {});
})();
})();
}
@@ -821,6 +816,10 @@ issue_1709: {
var x = 1;
return x;
}(),
function y() {
const y = 2;
return y;
}(),
function z() {
function z() {}
return z;
@@ -833,6 +832,10 @@ issue_1709: {
var x = 1;
return x;
}(),
function() {
const y = 2;
return y;
}(),
function() {
function z() {}
return z;
@@ -932,8 +935,7 @@ issue_1715_3: {
try {
console;
} catch (a) {
var a;
x();
var a = x();
}
}
f();
@@ -1028,33 +1030,6 @@ delete_assign_2: {
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,
@@ -1090,188 +1065,7 @@ issue_1830_2: {
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_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function f() {
a--;
try {
a++;
x();
} catch(a) {
if (a) var a;
var a = 10;
}
}
f();
}
expect: {
!function() {
try {
x();
} catch(a) {
var a;
}
}();
}
}
issue_2105_1: {
options = {
collapse_vars: true,
inline: true,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
!function(factory) {
factory();
}( function() {
return function(fn) {
fn()().prop();
}( function() {
function bar() {
var quux = function() {
console.log("PASS");
}, foo = function() {
console.log;
quux();
};
return { prop: foo };
}
return bar;
} );
});
}
expect: {
({
prop: function() {
console.log;
console.log("PASS");
}
}).prop();
}
expect_stdout: "PASS"
}
issue_2105_2: {
options = {
collapse_vars: true,
inline: true,
passes: 3,
properties: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unsafe: true,
unused: true,
}
input: {
!function(factory) {
factory();
}( function() {
return function(fn) {
fn()().prop();
}( function() {
function bar() {
var quux = function() {
console.log("PASS");
}, foo = function() {
console.log;
quux();
};
return { prop: foo };
}
return bar;
} );
});
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
}
issue_2226_1: {
options = {
side_effects: true,
unused: true,
}
input: {
function f1() {
var a = b;
a += c;
}
function f2(a) {
a <<= b;
}
function f3(a) {
--a;
}
function f4() {
var a = b;
return a *= c;
}
function f5(a) {
x(a /= b);
}
}
expect: {
function f1() {
b;
c;
}
function f2(a) {
b;
}
function f3(a) {
0;
}
function f4() {
var a = b;
return a *= c;
}
function f5(a) {
x(a /= b);
}
}
}
issue_2226_2: {
reassign_const: {
options = {
cascade: true,
sequences: true,
@@ -1279,137 +1073,19 @@ issue_2226_2: {
unused: true,
}
input: {
console.log(function(a, b) {
a += b;
function f() {
const a = 1;
a = 2;
return a;
}(1, 2));
}
console.log(f());
}
expect: {
console.log(function(a, b) {
return a += b;
}(1, 2));
}
expect_stdout: "3"
}
issue_2226_3: {
options = {
collapse_vars: true,
side_effects: true,
unused: true,
}
input: {
console.log(function(a, b) {
a += b;
return a;
}(1, 2));
}
expect: {
console.log(function(a, b) {
return a += 2;
}(1));
}
expect_stdout: "3"
}
issue_2288: {
options = {
unused: true,
}
beautify = {
beautify: true,
}
input: {
function foo(o) {
for (var j = o.a, i = 0; i < 0; i++);
for (var i = 0; i < 0; i++);
}
}
expect: {
function foo(o) {
o.a;
for (var i = 0; i < 0; i++);
for (i = 0; i < 0; i++);
}
}
}
issue_2516_1: {
options = {
collapse_vars: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
function foo() {
function qux(x) {
bar.call(null, x);
}
function bar(x) {
var FOUR = 4;
var trouble = x || never_called();
var value = (FOUR - 1) * trouble;
console.log(value == 6 ? "PASS" : value);
}
Baz = qux;
}
var Baz;
foo();
Baz(2);
}
expect: {
function foo() {
Baz = function(x) {
(function(x) {
var trouble = x || never_called();
var value = (4 - 1) * trouble;
console.log(6 == value ? "PASS" : value);
}).call(null, x);
};
}
var Baz;
foo();
Baz(2);
}
}
issue_2516_2: {
options = {
collapse_vars: true,
reduce_funcs: true,
reduce_vars: true,
passes: 2,
unused: true,
}
input: {
function foo() {
function qux(x) {
bar.call(null, x);
}
function bar(x) {
var FOUR = 4;
var trouble = x || never_called();
var value = (FOUR - 1) * trouble;
console.log(value == 6 ? "PASS" : value);
}
Baz = qux;
}
var Baz;
foo();
Baz(2);
}
expect: {
function foo() {
Baz = function(x) {
(function(x) {
var value = (4 - 1) * (x || never_called());
console.log(6 == value ? "PASS" : value);
}).call(null, x);
};
}
var Baz;
foo();
Baz(2);
function f() {
const a = 1;
return a = 2, a;
}
console.log(f());
}
expect_stdout: true
}

View File

@@ -1,7 +1,6 @@
and: {
options = {
evaluate: true,
side_effects: true,
evaluate: true
}
input: {
var a;
@@ -77,8 +76,7 @@ and: {
or: {
options = {
evaluate: true,
side_effects: true,
evaluate: true
}
input: {
var a;
@@ -160,8 +158,7 @@ or: {
unary_prefix: {
options = {
evaluate: true,
side_effects: true,
evaluate: true
}
input: {
a = !0 && b;
@@ -253,27 +250,22 @@ unsafe_constant: {
unsafe_object: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
evaluate : true,
unsafe : true
}
input: {
var o = { a: 1 };
console.log(
o + 1,
o.a + 1,
o.b + 1,
o.a.b + 1
({a:1}) + 1,
({a:1}).a + 1,
({a:1}).b + 1,
({a:1}).a.b + 1
);
}
expect: {
var o = { a: 1 };
console.log(
o + 1,
({a:1}) + 1,
2,
o.b + 1,
({a:1}).b + 1,
1..b + 1
);
}
@@ -282,27 +274,22 @@ unsafe_object: {
unsafe_object_nested: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
evaluate : true,
unsafe : true
}
input: {
var o = { a: { b: 1 } };
console.log(
o + 1,
o.a + 1,
o.b + 1,
o.a.b + 1
({a:{b:1}}) + 1,
({a:{b:1}}).a + 1,
({a:{b:1}}).b + 1,
({a:{b:1}}).a.b + 1
);
}
expect: {
var o = { a: { b: 1 } };
console.log(
o + 1,
o.a + 1,
o.b + 1,
({a:{b:1}}) + 1,
({a:{b:1}}).a + 1,
({a:{b:1}}).b + 1,
2
);
}
@@ -311,26 +298,21 @@ unsafe_object_nested: {
unsafe_object_complex: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
evaluate : true,
unsafe : true
}
input: {
var o = { a: { b: 1 }, b: 1 };
console.log(
o + 1,
o.a + 1,
o.b + 1,
o.a.b + 1
({a:{b:1},b:1}) + 1,
({a:{b:1},b:1}).a + 1,
({a:{b:1},b:1}).b + 1,
({a:{b:1},b:1}).a.b + 1
);
}
expect: {
var o = { a: { b: 1 }, b: 1 };
console.log(
o + 1,
o.a + 1,
({a:{b:1},b:1}) + 1,
({a:{b:1},b:1}).a + 1,
2,
2
);
@@ -340,27 +322,22 @@ unsafe_object_complex: {
unsafe_object_repeated: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
evaluate : true,
unsafe : true
}
input: {
var o = { a: { b: 1 }, a: 1 };
console.log(
o + 1,
o.a + 1,
o.b + 1,
o.a.b + 1
({a:{b:1},a:1}) + 1,
({a:{b:1},a:1}).a + 1,
({a:{b:1},a:1}).b + 1,
({a:{b:1},a:1}).a.b + 1
);
}
expect: {
var o = { a: { b: 1 }, a: 1 };
console.log(
o + 1,
({a:{b:1},a:1}) + 1,
2,
o.b + 1,
({a:{b:1},a:1}).b + 1,
1..b + 1
);
}
@@ -370,7 +347,6 @@ unsafe_object_repeated: {
unsafe_object_accessor: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unsafe: true,
}
@@ -394,11 +370,10 @@ unsafe_object_accessor: {
}
}
prop_function: {
unsafe_function: {
options = {
evaluate: true,
properties: true,
side_effects: true,
evaluate : true,
unsafe : true
}
input: {
console.log(
@@ -411,9 +386,9 @@ prop_function: {
expect: {
console.log(
({a:{b:1},b:function(){}}) + 1,
({b:1}) + 1,
function(){} + 1,
2
({a:{b:1},b:function(){}}).a + 1,
({a:{b:1},b:function(){}}).b + 1,
({a:{b:1},b:function(){}}).a.b + 1
);
}
expect_stdout: true
@@ -639,11 +614,10 @@ unsafe_string_bad_index: {
expect_stdout: true
}
prototype_function: {
unsafe_prototype_function: {
options = {
evaluate: true,
properties: true,
side_effects: true,
evaluate : true,
unsafe : true
}
input: {
var a = ({valueOf: 0}) < 1;
@@ -662,28 +636,25 @@ prototype_function: {
var d = ({toString: 0}) + "";
var e = (({valueOf: 0}) + "")[2];
var f = (({toString: 0}) + "")[2];
var g = 0();
var h = 0();
var g = ({valueOf: 0}).valueOf();
var h = "" + ({toString: 0});
}
}
call_args: {
options = {
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 1;
const a = 1;
console.log(a);
+function(a) {
return a;
}(a);
}
expect: {
var a = 1;
const a = 1;
console.log(1);
+(1, 1);
}
@@ -693,21 +664,19 @@ call_args: {
call_args_drop_param: {
options = {
evaluate: true,
inline: true,
keep_fargs: false,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 1;
const a = 1;
console.log(a);
+function(a) {
return a;
}(a, b);
}
expect: {
const a = 1;
console.log(1);
+(b, 1);
}
@@ -810,15 +779,13 @@ unsafe_charAt_noop: {
input: {
console.log(
s.charAt(0),
"string".charAt(x),
(typeof x).charAt()
"string".charAt(x)
);
}
expect: {
console.log(
s.charAt(0),
"string".charAt(x),
(typeof x)[0]
"string".charAt(x)
);
}
}
@@ -955,12 +922,12 @@ delete_binary_1: {
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);
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((NaN, !0));
}
expect_stdout: true
}
@@ -981,12 +948,12 @@ delete_binary_2: {
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);
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((NaN, !0));
}
expect_stdout: true
}
@@ -1026,7 +993,6 @@ Infinity_NaN_undefined_LHS: {
issue_1964_1: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unsafe_regexp: false,
unused: true,
@@ -1034,7 +1000,6 @@ issue_1964_1: {
input: {
function f() {
var long_variable_name = /\s/;
console.log(long_variable_name.source);
return "a b c".split(long_variable_name)[1];
}
console.log(f());
@@ -1042,21 +1007,16 @@ issue_1964_1: {
expect: {
function f() {
var long_variable_name = /\s/;
console.log(long_variable_name.source);
return "a b c".split(long_variable_name)[1];
}
console.log(f());
}
expect_stdout: [
"\\s",
"b",
]
expect_stdout: "b"
}
issue_1964_2: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unsafe_regexp: true,
unused: true,
@@ -1064,279 +1024,15 @@ issue_1964_2: {
input: {
function f() {
var long_variable_name = /\s/;
console.log(long_variable_name.source);
return "a b c".split(long_variable_name)[1];
}
console.log(f());
}
expect: {
function f() {
console.log(/\s/.source);
return "a b c".split(/\s/)[1];
}
console.log(f());
}
expect_stdout: [
"\\s",
"b",
]
}
array_slice_index: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log([1,2,3].slice(1)[1]);
}
expect: {
console.log(3);
}
expect_stdout: "3"
}
string_charCodeAt: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log("foo".charCodeAt("bar".length));
}
expect: {
console.log(NaN);
}
expect_stdout: "NaN"
}
issue_2207_1: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(String.fromCharCode(65));
console.log(Math.max(3, 6, 2, 7, 3, 4));
console.log(Math.cos(1.2345));
console.log(Math.cos(1.2345) - Math.sin(4.321));
console.log(Math.pow(Math.PI, Math.E - Math.LN10));
}
expect: {
console.log("A");
console.log(7);
console.log(Math.cos(1.2345));
console.log(1.2543732512566947);
console.log(1.6093984514472044);
}
expect_stdout: true
}
issue_2207_2: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(Math.E);
console.log(Math.LN10);
console.log(Math.LN2);
console.log(Math.LOG2E);
console.log(Math.LOG10E);
console.log(Math.PI);
console.log(Math.SQRT1_2);
console.log(Math.SQRT2);
}
expect: {
console.log(Math.E);
console.log(Math.LN10);
console.log(Math.LN2);
console.log(Math.LOG2E);
console.log(Math.LOG10E);
console.log(Math.PI);
console.log(Math.SQRT1_2);
console.log(Math.SQRT2);
}
expect_stdout: true
}
issue_2207_3: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(Number.MAX_VALUE);
console.log(Number.MIN_VALUE);
console.log(Number.NaN);
console.log(Number.NEGATIVE_INFINITY);
console.log(Number.POSITIVE_INFINITY);
}
expect: {
console.log(Number.MAX_VALUE);
console.log(5e-324);
console.log(NaN);
console.log(-1/0);
console.log(1/0);
}
expect_stdout: true
}
issue_2231_1: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(Object.keys(void 0));
}
expect: {
console.log(Object.keys(void 0));
}
expect_stdout: true
}
issue_2231_2: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(Object.getOwnPropertyNames(null));
}
expect: {
console.log(Object.getOwnPropertyNames(null));
}
expect_stdout: true
}
self_comparison_1: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var o = { n: NaN };
console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n);
}
expect: {
console.log(false, false, true, true, "number");
}
expect_stdout: "false false true true 'number'"
}
self_comparison_2: {
options = {
evaluate: true,
hoist_props: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = { n: NaN };
console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n);
}
expect: {
console.log(false, false, true, true, "number");
}
expect_stdout: "false false true true 'number'"
}
issue_2535_1: {
options = {
booleans: true,
evaluate: true,
sequences: true,
side_effects: true,
}
input: {
if ((x() || true) || y()) z();
if ((x() || true) && y()) z();
if ((x() && true) || y()) z();
if ((x() && true) && y()) z();
if ((x() || false) || y()) z();
if ((x() || false) && y()) z();
if ((x() && false) || y()) z();
if ((x() && false) && y()) z();
}
expect: {
if (x(), 1) z();
if (x(), y()) z();
if (x() || y()) z();
if (x() && y()) z();
if (x() || y()) z();
if (x() && y()) z();
if (x(), y()) z();
if (x(), 0) z();
}
}
issue_2535_2: {
options = {
booleans: true,
evaluate: true,
sequences: true,
side_effects: true,
}
input: {
(x() || true) || y();
(x() || true) && y();
(x() && true) || y();
(x() && true) && y();
(x() || false) || y();
(x() || false) && y();
(x() && false) || y();
(x() && false) && y();
}
expect: {
x(),
x(), y(),
x() || y(),
x() && y(),
x() || y(),
x() && y(),
x(), y(),
x();
}
}
issue_2535_3: {
options = {
booleans: true,
evaluate: true,
}
input: {
console.log(Object(1) && 1 && 2);
console.log(Object(1) && true && 1 && 2 && Object(2));
console.log(Object(1) && true && 1 && null && 2 && Object(2));
console.log(2 == Object(1) || 0 || void 0 || null);
console.log(2 == Object(1) || 0 || void 0 || null || Object(2));
console.log(2 == Object(1) || 0 || void 0 || "ok" || null || Object(2));
}
expect: {
console.log(Object(1) && 2);
console.log(Object(1) && Object(2));
console.log(Object(1) && null);
console.log(2 == Object(1) || null);
console.log(2 == Object(1) || Object(2));
console.log(2 == Object(1) || "ok");
}
expect_stdout: true
expect_warnings: [
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1316,20]",
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1317,20]",
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1318,20]",
"WARN: Condition left of && always false [test/compress/evaluate.js:1318,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1319,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1320,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1321,20]",
"WARN: Condition left of || always true [test/compress/evaluate.js:1321,20]",
]
expect_stdout: "b"
}

View File

@@ -19,10 +19,8 @@ iifes_returning_constants_keep_fargs_true: {
booleans : true,
if_return : true,
join_vars : true,
reduce_funcs : true,
reduce_vars : true,
cascade : true,
inline : true,
}
input: {
(function(){ return -1.23; }());
@@ -56,10 +54,8 @@ iifes_returning_constants_keep_fargs_false: {
booleans : true,
if_return : true,
join_vars : true,
reduce_funcs : true,
reduce_vars : true,
cascade : true,
inline : true,
}
input: {
(function(){ return -1.23; }());
@@ -86,8 +82,6 @@ issue_485_crashing_1530: {
conditionals: true,
dead_code: true,
evaluate: true,
inline: true,
side_effects: true,
}
input: {
(function(a) {
@@ -95,14 +89,15 @@ issue_485_crashing_1530: {
var b = 42;
})(this);
}
expect: {}
expect: {
this, void 0;
}
}
issue_1841_1: {
options = {
keep_fargs: false,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -117,8 +112,9 @@ issue_1841_1: {
expect: {
var b = 10;
!function() {
for (var key in "hi")
for (var key in "hi") {
b = 42;
}
}(--b);
console.log(b);
}
@@ -129,7 +125,6 @@ issue_1841_2: {
options = {
keep_fargs: false,
pure_getters: false,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -144,531 +139,11 @@ issue_1841_2: {
expect: {
var b = 10;
!function(arg) {
for (var key in "hi")
for (var key in "hi") {
arg.baz, b = 42;
}
}(--b);
console.log(b);
}
expect_exact: "42"
}
function_returning_constant_literal: {
options = {
inline: true,
passes: 2,
properties: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: 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"
}
hoist_funs: {
options = {
hoist_funs: true,
}
input: {
console.log(1, typeof f, typeof g);
if (console.log(2, typeof f, typeof g))
console.log(3, typeof f, typeof g);
else {
console.log(4, typeof f, typeof g);
function f() {}
console.log(5, typeof f, typeof g);
}
function g() {}
console.log(6, typeof f, typeof g);
}
expect: {
function f() {}
function g() {}
console.log(1, typeof f, typeof g);
if (console.log(2, typeof f, typeof g))
console.log(3, typeof f, typeof g);
else {
console.log(4, typeof f, typeof g);
console.log(5, typeof f, typeof g);
}
console.log(6, typeof f, typeof g);
}
expect_stdout: [
"1 'function' 'function'",
"2 'function' 'function'",
"4 'function' 'function'",
"5 'function' 'function'",
"6 'function' 'function'",
]
node_version: "<=4"
}
hoist_funs_strict: {
options = {
hoist_funs: true,
}
input: {
"use strict";
console.log(1, typeof f, typeof g);
if (console.log(2, typeof f, typeof g))
console.log(3, typeof f, typeof g);
else {
console.log(4, typeof f, typeof g);
function f() {}
console.log(5, typeof f, typeof g);
}
function g() {}
console.log(6, typeof f, typeof g);
}
expect: {
"use strict";
function g() {}
console.log(1, typeof f, typeof g);
if (console.log(2, typeof f, typeof g))
console.log(3, typeof f, typeof g);
else {
console.log(4, typeof f, typeof g);
function f() {}
console.log(5, typeof f, typeof g);
}
console.log(6, typeof f, typeof g);
}
expect_stdout: [
"1 'undefined' 'function'",
"2 'undefined' 'function'",
"4 'function' 'function'",
"5 'function' 'function'",
"6 'undefined' 'function'",
]
node_version: ">=4"
}
issue_203: {
options = {
keep_fargs: false,
side_effects: true,
unsafe_Func: true,
unused: true,
}
input: {
var m = {};
var fn = Function("require", "module", "exports", "module.exports = 42;");
fn(null, m, m.exports);
console.log(m.exports);
}
expect: {
var m = {};
var fn = Function("n,o", "o.exports=42");
fn(null, m, m.exports);
console.log(m.exports);
}
expect_stdout: "42"
}
no_webkit: {
beautify = {
webkit: false,
}
input: {
console.log(function() {
1 + 1;
}.a = 1);
}
expect_exact: "console.log(function(){1+1}.a=1);"
expect_stdout: "1"
}
webkit: {
beautify = {
webkit: true,
}
input: {
console.log(function() {
1 + 1;
}.a = 1);
}
expect_exact: "console.log((function(){1+1}).a=1);"
expect_stdout: "1"
}
issue_2084: {
options = {
collapse_vars: true,
conditionals: true,
evaluate: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
var c = 0;
!function() {
!function(c) {
c = 1 + c;
var c = 0;
function f14(a_1) {
if (c = 1 + c, 0 !== 23..toString())
c = 1 + c, a_1 && (a_1[0] = 0);
}
f14();
}(-1);
}();
console.log(c);
}
expect: {
var c = 0;
!function(c) {
c = 1 + c,
c = 1 + (c = 0),
0 !== 23..toString() && (c = 1 + c);
}(-1),
console.log(c);
}
expect_stdout: "0"
}
issue_2097: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {
try {
throw 0;
} catch (e) {
console.log(arguments[0]);
}
}
f(1);
}
expect: {
!function() {
try {
throw 0;
} catch (e) {
console.log(arguments[0]);
}
}(1);
}
expect_stdout: "1"
}
issue_2101: {
options = {
inline: true,
}
input: {
a = {};
console.log(function() {
return function() {
return this.a;
}();
}() === function() {
return a;
}());
}
expect: {
a = {};
console.log(function() {
return this.a;
}() === a);
}
expect_stdout: "true"
}
inner_ref: {
options = {
inline: true,
unused: true,
}
input: {
console.log(function(a) {
return function() {
return a;
}();
}(1), function(a) {
return function(a) {
return a;
}();
}(2));
}
expect: {
console.log(function(a) {
return a;
}(1), function(a) {
return a;
}());
}
expect_stdout: "1 undefined"
}
issue_2107: {
options = {
cascade: true,
collapse_vars: true,
inline: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
var c = 0;
!function() {
c++;
}(c++ + new function() {
this.a = 0;
var a = (c = c + 1) + (c = 1 + c);
return c++ + a;
}());
console.log(c);
}
expect: {
var c = 0;
c++, new function() {
this.a = 0, c = 1 + (c += 1), c++;
}(), c++, console.log(c);
}
expect_stdout: "5"
}
issue_2114_1: {
options = {
collapse_vars: true,
if_return: true,
inline: true,
keep_fargs: false,
side_effects: true,
unused: true,
}
input: {
var c = 0;
!function(a) {
a = 0;
}([ {
0: c = c + 1,
length: c = 1 + c
}, typeof void function a() {
var b = function f1(a) {
}(b && (b.b += (c = c + 1, 0)));
}() ]);
console.log(c);
}
expect: {
var c = 0;
c = 1 + (c += 1), function() {
var b = void (b && (b.b += (c += 1, 0)));
}();
console.log(c);
}
expect_stdout: "2"
}
issue_2114_2: {
options = {
collapse_vars: true,
if_return: true,
inline: true,
keep_fargs: false,
passes: 2,
side_effects: true,
unused: true,
}
input: {
var c = 0;
!function(a) {
a = 0;
}([ {
0: c = c + 1,
length: c = 1 + c
}, typeof void function a() {
var b = function f1(a) {
}(b && (b.b += (c = c + 1, 0)));
}() ]);
console.log(c);
}
expect: {
var c = 0;
c = 1 + (c += 1), function() {
var b = void (b && (b.b += (c += 1, 0)));
}();
console.log(c);
}
expect_stdout: "2"
}
issue_2428: {
options = {
collapse_vars: true,
inline: true,
passes: 3,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
function bar(k) {
console.log(k);
}
function foo(x) {
return bar(x);
}
function baz(a) {
foo(a);
}
baz(42);
baz("PASS");
}
expect: {
function baz(a) {
console.log(a);
}
baz(42);
baz("PASS");
}
expect_stdout: [
"42",
"PASS",
]
}
issue_2531_1: {
options = {
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
function outer() {
function inner(value) {
function closure() {
return value;
}
return function() {
return closure();
};
}
return inner("Hello");
}
console.log("Greeting:", outer()());
}
expect: {
function outer() {
return function(value) {
return function() {
return value;
};
}("Hello");
}
console.log("Greeting:", outer()());
}
expect_stdout: "Greeting: Hello"
}
issue_2531_2: {
options = {
evaluate: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
function outer() {
function inner(value) {
function closure() {
return value;
}
return function() {
return closure();
};
}
return inner("Hello");
}
console.log("Greeting:", outer()());
}
expect: {
function outer() {
return function() {
return "Hello";
};
}
console.log("Greeting:", outer()());
}
expect_stdout: "Greeting: Hello"
}
issue_2531_3: {
options = {
evaluate: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function outer() {
function inner(value) {
function closure() {
return value;
}
return function() {
return closure();
};
}
return inner("Hello");
}
console.log("Greeting:", outer()());
}
expect: {
console.log("Greeting:", "Hello");
}
expect_stdout: "Greeting: Hello"
}
empty_body: {
options = {
reduce_vars: true,
side_effects: true,
}
input: {
function f() {
function noop() {}
noop();
return noop;
}
}
expect: {
function f() {
function noop() {}
return noop;
}
}
}

View File

@@ -37,7 +37,6 @@ object: {
VALUE: 42,
},
},
side_effects: true,
unsafe: true,
}
input: {
@@ -121,7 +120,7 @@ mixed: {
properties: true,
}
input: {
var FOO = { BAR: 0 };
const FOO = { BAR: 0 };
console.log(FOO.BAR);
console.log(++CONFIG.DEBUG);
console.log(++CONFIG.VALUE);
@@ -131,7 +130,7 @@ mixed: {
console.log(CONFIG);
}
expect: {
var FOO = { BAR: 0 };
const FOO = { BAR: 0 };
console.log("moo");
console.log(++CONFIG.DEBUG);
console.log(++CONFIG.VALUE);
@@ -141,9 +140,9 @@ mixed: {
console.log(CONFIG);
}
expect_warnings: [
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:126,22]',
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]',
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:128,22]',
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:130,8]',
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:129,8]',
]
}
@@ -161,39 +160,3 @@ issue_1801: {
console.log(!0);
}
}
issue_1986: {
options = {
global_defs: {
"@alert": "console.log",
},
}
input: {
alert(42);
}
expect: {
console.log(42);
}
}
issue_2167: {
options = {
conditionals: true,
dead_code: true,
evaluate: true,
global_defs: {
"@isDevMode": "function(){}",
},
passes: 2,
side_effects: true,
}
input: {
if (isDevMode()) {
greetOverlord();
}
doWork();
}
expect: {
doWork();
}
}

View File

@@ -1,666 +0,0 @@
issue_2377_1: {
options = {
evaluate: true,
inline: true,
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var obj = {
foo: 1,
bar: 2,
square: function(x) {
return x * x;
},
cube: function(x) {
return x * x * x;
},
};
console.log(obj.foo, obj.cube(3));
}
expect: {
var obj_foo = 1, obj_cube = function(x) {
return x * x * x;
};
console.log(obj_foo, obj_cube(3));
}
expect_stdout: "1 27"
}
issue_2377_2: {
options = {
evaluate: true,
inline: true,
hoist_props: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var obj = {
foo: 1,
bar: 2,
square: function(x) {
return x * x;
},
cube: function(x) {
return x * x * x;
},
};
console.log(obj.foo, obj.cube(3));
}
expect: {
console.log(1, function(x) {
return x * x * x;
}(3));
}
expect_stdout: "1 27"
}
issue_2377_3: {
options = {
evaluate: true,
inline: true,
hoist_props: true,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var obj = {
foo: 1,
bar: 2,
square: function(x) {
return x * x;
},
cube: function(x) {
return x * x * x;
},
};
console.log(obj.foo, obj.cube(3));
}
expect: {
console.log(1, 27);
}
expect_stdout: "1 27"
}
direct_access_1: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 0;
var obj = {
a: 1,
b: 2,
};
for (var k in obj) a++;
console.log(a, obj.a);
}
expect: {
var a = 0;
var obj = {
a: 1,
b: 2,
};
for (var k in obj) a++;
console.log(a, obj.a);
}
expect_stdout: "2 1"
}
direct_access_2: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = { a: 1 };
var f = function(k) {
if (o[k]) return "PASS";
};
console.log(f("a"));
}
expect: {
var o = { a: 1 };
console.log(function(k) {
if (o[k]) return "PASS";
}("a"));
}
expect_stdout: "PASS"
}
direct_access_3: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = { a: 1 };
o.b;
console.log(o.a);
}
expect: {
var o = { a: 1 };
o.b;
console.log(o.a);
}
expect_stdout: "1"
}
single_use: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var obj = {
bar: function() {
return 42;
},
};
console.log(obj.bar());
}
expect: {
console.log({
bar: function() {
return 42;
},
}.bar());
}
}
name_collision_1: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
input: {
var obj_foo = 1;
var obj_bar = 2;
function f() {
var obj = {
foo: 3,
bar: 4,
"b-r": 5,
"b+r": 6,
"b!r": 7,
};
console.log(obj_foo, obj.foo, obj.bar, obj["b-r"], obj["b+r"], obj["b!r"]);
}
f();
}
expect: {
var obj_foo = 1;
var obj_bar = 2;
function f() {
var obj_foo$0 = 3,
obj_bar = 4,
obj_b_r = 5,
obj_b_r$0 = 6,
obj_b_r$1 = 7;
console.log(obj_foo, obj_foo$0, obj_bar, obj_b_r, obj_b_r$0, obj_b_r$1);
}
f();
}
expect_stdout: "1 3 4 5 6 7"
}
name_collision_2: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
input: {
var o = {
p: 1,
0: function(x) {
return x;
},
1: function(x) {
return x + 1;
}
}, o__$0 = 2, o__$1 = 3;
console.log(o.p === o.p, o[0](4), o[1](5), o__$0, o__$1);
}
expect: {
var o_p = 1,
o__ = function(x) {
return x;
},
o__$2 = function(x) {
return x + 1;
},
o__$0 = 2,
o__$1 = 3;
console.log(o_p === o_p, o__(4), o__$2(5), o__$0, o__$1);
}
expect_stdout: "true 4 6 2 3"
}
name_collision_3: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
input: {
var o = {
p: 1,
0: function(x) {
return x;
},
1: function(x) {
return x + 1;
}
}, o__$0 = 2, o__$1 = 3;
console.log(o.p === o.p, o[0](4), o[1](5));
}
expect: {
var o_p = 1,
o__ = function(x) {
return x;
},
o__$2 = function(x) {
return x + 1;
},
o__$0 = 2,
o__$1 = 3;
console.log(o_p === o_p, o__(4), o__$2(5));
}
expect_stdout: "true 4 6"
}
contains_this_1: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
u: function() {
return this === this;
},
p: 1
};
console.log(o.p, o.p);
}
expect: {
console.log(1, 1);
}
expect_stdout: "1 1"
}
contains_this_2: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
u: function() {
return this === this;
},
p: 1
};
console.log(o.p, o.p, o.u);
}
expect: {
console.log(1, 1, function() {
return this === this;
});
}
expect_stdout: true
}
contains_this_3: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
u: function() {
return this === this;
},
p: 1
};
console.log(o.p, o.p, o.u());
}
expect: {
var o = {
u: function() {
return this === this;
},
p: 1
};
console.log(o.p, o.p, o.u());
}
expect_stdout: "1 1 true"
}
new_this: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: 1,
b: 2,
f: function(a) {
this.b = a;
}
};
console.log(new o.f(o.a).b, o.b);
}
expect: {
console.log(new function(a) {
this.b = a;
}(1).b, 2);
}
expect_stdout: "1 2"
}
issue_2473_1: {
options = {
hoist_props: false,
reduce_vars: true,
top_retain: [ "x", "y" ],
toplevel: true,
unused: true,
}
input: {
var x = {};
var y = [];
var z = {};
}
expect: {
var x = {};
var y = [];
}
}
issue_2473_2: {
options = {
hoist_props: true,
reduce_vars: true,
top_retain: [ "x", "y" ],
toplevel: true,
unused: true,
}
input: {
var x = {};
var y = [];
var z = {};
}
expect: {
var x = {};
var y = [];
}
}
issue_2473_3: {
options = {
hoist_props: true,
reduce_vars: true,
top_retain: "o",
toplevel: true,
unused: true,
}
input: {
var o = {
a: 1,
b: 2,
};
console.log(o.a, o.b);
}
expect: {
var o = {
a: 1,
b: 2,
};
console.log(o.a, o.b);
}
expect_stdout: "1 2"
}
issue_2473_4: {
options = {
hoist_props: true,
reduce_vars: true,
top_retain: "o",
toplevel: true,
unused: true,
}
input: {
(function() {
var o = {
a: 1,
b: 2,
};
console.log(o.a, o.b);
})();
}
expect: {
(function() {
var o_a = 1, o_b = 2;
console.log(o_a, o_b);
})();
}
expect_stdout: "1 2"
}
issue_2508_1: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: [ 1 ],
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
(function(x) {
console.log(x);
})([ 1 ]);
}
expect_stdout: true
}
issue_2508_2: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: { b: 2 },
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
(function(x) {
console.log(x);
})({ b: 2 });
}
expect_stdout: true
}
issue_2508_3: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: [ o ],
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
var o = {
a: [ o ],
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect_stdout: true
}
issue_2508_4: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: { b: o },
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
var o = {
a: { b: o },
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect_stdout: true
}
issue_2508_5: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
f: function(x) {
console.log(x);
}
};
o.f(o.f);
}
expect: {
var o_f = function(x) {
console.log(x);
};
o_f(o_f);
}
expect_stdout: true
}
issue_2519: {
options = {
collapse_vars: true,
evaluate: true,
hoist_props: true,
reduce_vars: true,
unused: true,
}
input: {
function testFunc() {
var dimensions = {
minX: 5,
maxX: 6,
};
var scale = 1;
var d = {
x: (dimensions.maxX + dimensions.minX) / 2,
};
return d.x * scale;
}
console.log(testFunc());
}
expect: {
function testFunc() {
return 1 * ((6 + 5) / 2);
}
console.log(testFunc());
}
expect_stdout: "5.5"
}

View File

@@ -88,24 +88,3 @@ sequences_funs: {
}
}
}
issue_2295: {
options = {
collapse_vars: true,
hoist_vars: true,
}
input: {
function foo(o) {
var a = o.a;
if (a) return a;
var a = 1;
}
}
expect: {
function foo(o) {
var a = o.a;
if (a) return a;
a = 1;
}
}
}

View File

@@ -302,27 +302,3 @@ issue_1437_conditionals: {
}
}
}
issue_512: {
options = {
conditionals: true,
if_return: true,
sequences: true,
side_effects: true,
}
input: {
function a() {
if (b()) {
c();
return;
}
throw e;
}
}
expect: {
function a() {
if (!b()) throw e;
c();
}
}
}

View File

@@ -71,13 +71,11 @@ non_hoisted_function_after_return_2a: {
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:51,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:48,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]",
"WARN: pass 0: last_count: Infinity, count: 37",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:53,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]",
"WARN: pass 1: last_count: 37, count: 18",
]
}
@@ -111,146 +109,10 @@ non_hoisted_function_after_return_2b: {
}
expect_warnings: [
// duplicate warnings no longer emitted
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:99,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:99,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:103,12]",
]
}
non_hoisted_function_after_return_strict: {
options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true
}
input: {
"use strict";
function foo(x) {
if (x) {
return bar();
not_called1();
} else {
return baz();
not_called2();
}
function bar() { return 7; }
return not_reached;
function UnusedFunction() {}
function baz() { return 8; }
}
console.log(foo(0), foo(1));
}
expect: {
"use strict";
function foo(x) {
return x ? bar() : baz();
function bar() { return 7 }
function baz() { return 8 }
}
console.log(foo(0), foo(1));
}
expect_stdout: "8 7"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:133,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:136,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:139,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:140,21]",
]
}
non_hoisted_function_after_return_2a_strict: {
options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true,
collapse_vars: false, passes: 2, warnings: "verbose"
}
input: {
"use strict";
function foo(x) {
if (x) {
return bar(1);
var a = not_called(1);
} else {
return bar(2);
var b = not_called(2);
}
var c = bar(3);
function bar(x) { return 7 - x; }
function nope() {}
return b || c;
}
console.log(foo(0), foo(1));
}
expect: {
"use strict";
function foo(x) {
return bar(x ? 1 : 2);
function bar(x) {
return 7 - x;
}
}
console.log(foo(0), foo(1));
}
expect_stdout: "5 6"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:175,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:175,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:178,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:178,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:175,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:182,21]",
"WARN: pass 0: last_count: Infinity, count: 48",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:180,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:180,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:183,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:178,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:180,16]",
"WARN: pass 1: last_count: 48, count: 29",
]
}
non_hoisted_function_after_return_2b_strict: {
options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true,
collapse_vars: false
}
input: {
"use strict";
function foo(x) {
if (x) {
return bar(1);
} else {
return bar(2);
var b;
}
var c = bar(3);
function bar(x) {
return 7 - x;
}
return b || c;
}
console.log(foo(0), foo(1));
}
expect: {
"use strict";
function foo(x) {
return bar(x ? 1 : 2);
function bar(x) { return 7 - x; }
}
console.log(foo(0), foo(1));
}
expect_stdout: "5 6"
expect_warnings: [
// duplicate warnings no longer emitted
"WARN: Dropping unreachable code [test/compress/issue-1034.js:229,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:229,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:231,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:231,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:235,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:95,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:95,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:101,12]",
]
}

View File

@@ -1,7 +1,19 @@
const_declaration: {
options = {
evaluate: true
};
input: {
const goog = goog || {};
}
expect: {
const goog = goog || {};
}
}
const_pragma: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
};
@@ -17,7 +29,6 @@ const_pragma: {
not_const: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
};

View File

@@ -1,91 +1,90 @@
multiple_functions: {
options = {
hoist_funs: false,
if_return: true,
}
options = { if_return: true, hoist_funs: false };
input: {
( function() {
if ( !window ) {
return;
}
function f() {}
function g() {}
} )();
}
expect: {
( function() {
function f() {}
function g() {}
// NOTE: other compression steps will reduce this
// down to just `window`.
if ( window );
function f() {}
function g() {}
} )();
}
}
single_function: {
options = {
hoist_funs: false,
if_return: true,
}
options = { if_return: true, hoist_funs: false };
input: {
( function() {
if ( !window ) {
return;
}
function f() {}
} )();
}
expect: {
( function() {
if ( window );
function f() {}
if ( window );
} )();
}
}
deeply_nested: {
options = {
hoist_funs: false,
if_return: true,
}
options = { if_return: true, hoist_funs: false };
input: {
( function() {
if ( !window ) {
return;
}
function f() {}
function g() {}
if ( !document ) {
return;
}
function h() {}
} )();
}
expect: {
( function() {
function f() {}
function g() {}
function h() {}
// NOTE: other compression steps will reduce this
// down to just `window`.
if ( window )
if (document);
function f() {}
function g() {}
function h() {}
} )();
}
}
not_hoisted_when_already_nested: {
options = {
hoist_funs: false,
if_return: true,
}
options = { if_return: true, hoist_funs: false };
input: {
( function() {
if ( !window ) {
return;
}
if ( foo ) function f() {}
} )();
}
expect: {
@@ -95,70 +94,3 @@ not_hoisted_when_already_nested: {
} )();
}
}
defun_if_return: {
options = {
hoist_funs: false,
if_return: true,
}
input: {
function e() {
function f() {}
if (!window) return;
else function g() {}
function h() {}
}
}
expect: {
function e() {
function f() {}
if (window) function g() {}
function h() {}
}
}
}
defun_hoist_funs: {
options = {
hoist_funs: true,
if_return: true,
}
input: {
function e() {
function f() {}
if (!window) return;
else function g() {}
function h() {}
}
}
expect: {
function e() {
function f() {}
function g() {}
function h() {}
if (window);
}
}
}
defun_else_if_return: {
options = {
hoist_funs: false,
if_return: true,
}
input: {
function e() {
function f() {}
if (window) function g() {}
else return;
function h() {}
}
}
expect: {
function e() {
function f() {}
if (window) function g() {}
function h() {}
}
}
}

View File

@@ -96,13 +96,6 @@ pure_function_calls_toplevel: {
})();
})();
// pure top-level calls will be dropped regardless of the leading comments position
var MyClass = /*#__PURE__*//*@class*/(function(){
function MyClass() {}
MyClass.prototype.method = function() {};
return MyClass;
})();
// comment #__PURE__ comment
bar(), baz(), quux();
a.b(), /* @__PURE__ */ c.d.e(), f.g();
@@ -117,12 +110,10 @@ pure_function_calls_toplevel: {
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:92,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:92,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:90,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:107,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:108,31]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:100,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:101,31]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:84,33]",
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:84,12]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:100,45]",
"WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:100,12]",
]
}
@@ -157,29 +148,29 @@ should_warn: {
baz();
}
expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,61]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,23]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:137,23]",
"WARN: Boolean || always true [test/compress/issue-1261.js:138,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:138,23]",
"WARN: Condition always true [test/compress/issue-1261.js:138,23]",
"WARN: Condition left of || always true [test/compress/issue-1261.js:139,8]",
"WARN: Condition always true [test/compress/issue-1261.js:139,8]",
"WARN: Boolean && always false [test/compress/issue-1261.js:140,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:140,23]",
"WARN: Condition always false [test/compress/issue-1261.js:140,23]",
"WARN: Condition left of && always false [test/compress/issue-1261.js:141,8]",
"WARN: Condition always false [test/compress/issue-1261.js:141,8]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:142,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:142,23]",
"WARN: Condition always true [test/compress/issue-1261.js:142,23]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:143,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:143,31]",
"WARN: Condition always true [test/compress/issue-1261.js:143,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:144,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:145,24]",
"WARN: Condition always true [test/compress/issue-1261.js:145,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:146,31]",
"WARN: Condition always false [test/compress/issue-1261.js:146,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,61]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,23]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:128,23]",
"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: 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: 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]",
"WARN: Condition always true [test/compress/issue-1261.js:133,23]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:134,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:134,31]",
"WARN: Condition always true [test/compress/issue-1261.js:134,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:136,24]",
"WARN: Condition always true [test/compress/issue-1261.js:136,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,31]",
"WARN: Condition always false [test/compress/issue-1261.js:137,8]",
]
}

View File

@@ -1,8 +1,6 @@
issue_1321_no_debug: {
mangle = {
properties: {
keep_quoted: true,
},
mangle_props = {
ignore_quoted: true
}
input: {
var x = {};
@@ -12,19 +10,17 @@ issue_1321_no_debug: {
}
expect: {
var x = {};
x.x = 1;
x["a"] = 2 * x.x;
console.log(x.x, x["a"]);
x.b = 1;
x["a"] = 2 * x.b;
console.log(x.b, x["a"]);
}
expect_stdout: true
}
issue_1321_debug: {
mangle = {
properties: {
debug: "",
keep_quoted: true,
},
mangle_props = {
ignore_quoted: true,
debug: ""
}
input: {
var x = {};
@@ -34,18 +30,16 @@ issue_1321_debug: {
}
expect: {
var x = {};
x.x = 1;
x["_$foo$_"] = 2 * x.x;
console.log(x.x, x["_$foo$_"]);
x.a = 1;
x["_$foo$_"] = 2 * x.a;
console.log(x.a, x["_$foo$_"]);
}
expect_stdout: true
}
issue_1321_with_quoted: {
mangle = {
properties: {
keep_quoted: false,
},
mangle_props = {
ignore_quoted: false
}
input: {
var x = {};
@@ -55,9 +49,9 @@ issue_1321_with_quoted: {
}
expect: {
var x = {};
x.x = 1;
x["o"] = 2 * x.x;
console.log(x.x, x["o"]);
x.a = 1;
x["b"] = 2 * x.a;
console.log(x.a, x["b"]);
}
expect_stdout: true
}

View File

@@ -1,7 +1,6 @@
typeof_eq_undefined: {
options = {
comparisons: true,
typeofs: true,
comparisons: true
}
input: {
var a = typeof b != "undefined";
@@ -24,8 +23,7 @@ typeof_eq_undefined: {
typeof_eq_undefined_ie8: {
options = {
comparisons: true,
ie8: true,
typeofs: true,
screw_ie8: false
}
input: {
var a = typeof b != "undefined";
@@ -47,8 +45,7 @@ typeof_eq_undefined_ie8: {
undefined_redefined: {
options = {
comparisons: true,
typeofs: true,
comparisons: true
}
input: {
function f(undefined) {
@@ -61,8 +58,7 @@ undefined_redefined: {
undefined_redefined_mangle: {
options = {
comparisons: true,
typeofs: true,
comparisons: true
}
mangle = {}
input: {

View File

@@ -1,9 +1,9 @@
screw_ie8: {
options = {
ie8: false,
screw_ie8: true,
}
mangle = {
ie8: false,
screw_ie8: true,
}
input: {
try { throw "foo"; } catch (x) { console.log(x); }
@@ -16,10 +16,10 @@ screw_ie8: {
support_ie8: {
options = {
ie8: true,
screw_ie8: false,
}
mangle = {
ie8: true,
screw_ie8: false,
}
input: {
try { throw "foo"; } catch (x) { console.log(x); }
@@ -85,3 +85,15 @@ unsafe_undefined: {
}
expect_stdout: true
}
runtime_error: {
input: {
const a = 1;
console.log(a++);
}
expect: {
const a = 1;
console.log(a++);
}
expect_stdout: true
}

View File

@@ -2,7 +2,6 @@ chained_evaluation_1: {
options = {
collapse_vars: true,
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -19,7 +18,9 @@ chained_evaluation_1: {
expect: {
(function() {
(function() {
f(1).bar = 1;
var c;
c = f(1);
c.bar = 1;
})();
})();
}
@@ -29,7 +30,6 @@ chained_evaluation_2: {
options = {
collapse_vars: true,
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -46,8 +46,9 @@ chained_evaluation_2: {
expect: {
(function() {
(function() {
var b = "long piece of string";
f(b).bar = b;
var c, b = "long piece of string";
c = f(b);
c.bar = b;
})();
})();
}

View File

@@ -26,7 +26,7 @@ issue_1639_1: {
}
expect: {
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
if (--b, 0) var ignore = 0;
if (--b, !1) var ignore = 0;
console.log(a, b);
}
expect_stdout: true
@@ -57,7 +57,7 @@ issue_1639_2: {
expect: {
var a = 100, b = 10;
function f19() {
++a, 0;
++a, 1;
}
f19(),
console.log(a, b);

View File

@@ -15,7 +15,6 @@ f7: {
negate_iife: true,
passes: 3,
properties: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -39,7 +38,7 @@ f7: {
"var b = 10;",
"",
"!function() {",
" b = 100;",
" for (;b = 100, !1; ) ;",
"}(), console.log(100, b);",
]
expect_stdout: true

View File

@@ -1,6 +1,5 @@
side_effects_catch: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -35,7 +34,6 @@ side_effects_catch: {
side_effects_else: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -64,7 +62,6 @@ side_effects_else: {
side_effects_finally: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -101,7 +98,6 @@ side_effects_finally: {
side_effects_label: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -134,7 +130,6 @@ side_effects_label: {
side_effects_switch: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,

View File

@@ -1,10 +1,10 @@
mangle_catch: {
options = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
input: {
@@ -22,11 +22,11 @@ mangle_catch: {
mangle_catch_ie8: {
options = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
input: {
@@ -44,11 +44,11 @@ mangle_catch_ie8: {
mangle_catch_var: {
options = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
input: {
@@ -66,11 +66,11 @@ mangle_catch_var: {
mangle_catch_var_ie8: {
options = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
input: {
@@ -88,11 +88,11 @@ mangle_catch_var_ie8: {
mangle_catch_toplevel: {
options = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
input: {
@@ -110,11 +110,11 @@ mangle_catch_toplevel: {
mangle_catch_ie8_toplevel: {
options = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
input: {
@@ -132,11 +132,11 @@ mangle_catch_ie8_toplevel: {
mangle_catch_var_toplevel: {
options = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
input: {
@@ -154,11 +154,11 @@ mangle_catch_var_toplevel: {
mangle_catch_var_ie8_toplevel: {
options = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
input: {
@@ -176,11 +176,11 @@ mangle_catch_var_ie8_toplevel: {
mangle_catch_redef_1: {
options = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
input: {
@@ -198,11 +198,11 @@ mangle_catch_redef_1: {
mangle_catch_redef_1_ie8: {
options = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
input: {
@@ -220,11 +220,11 @@ mangle_catch_redef_1_ie8: {
mangle_catch_redef_1_toplevel: {
options = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
input: {
@@ -242,11 +242,11 @@ mangle_catch_redef_1_toplevel: {
mangle_catch_redef_1_ie8_toplevel: {
options = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
input: {
@@ -264,11 +264,11 @@ mangle_catch_redef_1_ie8_toplevel: {
mangle_catch_redef_2: {
options = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
input: {
@@ -285,11 +285,11 @@ mangle_catch_redef_2: {
mangle_catch_redef_2_ie8: {
options = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
input: {
@@ -306,11 +306,11 @@ mangle_catch_redef_2_ie8: {
mangle_catch_redef_2_toplevel: {
options = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
input: {
@@ -327,11 +327,11 @@ mangle_catch_redef_2_toplevel: {
mangle_catch_redef_2_ie8_toplevel: {
options = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
input: {

View File

@@ -1,6 +1,6 @@
function_iife_catch: {
mangle = {
ie8: false,
screw_ie8: true,
}
input: {
function f(n) {
@@ -21,7 +21,7 @@ function_iife_catch: {
function_iife_catch_ie8: {
mangle = {
ie8: true,
screw_ie8: false,
}
input: {
function f(n) {
@@ -42,7 +42,7 @@ function_iife_catch_ie8: {
function_catch_catch: {
mangle = {
ie8: false,
screw_ie8: true,
}
input: {
var o = 0;
@@ -70,7 +70,7 @@ function_catch_catch: {
function_catch_catch_ie8: {
mangle = {
ie8: true,
screw_ie8: false,
}
input: {
var o = 0;

View File

@@ -7,7 +7,7 @@ case_1: {
input: {
var a = 0, b = 1;
switch (true) {
case a || true:
case a, true:
default:
b = 2;
case true:
@@ -17,7 +17,7 @@ case_1: {
expect: {
var a = 0, b = 1;
switch (true) {
case a || true:
case a, true:
b = 2;
}
console.log(a, b);

View File

@@ -1,7 +1,5 @@
mangle_props: {
mangle = {
properties: true,
}
mangle_props = {}
input: {
var obj = {
undefined: 1,
@@ -56,12 +54,10 @@ mangle_props: {
}
numeric_literal: {
mangle = {
properties: true,
}
beautify = {
beautify: true,
}
mangle_props = {}
input: {
var obj = {
0: 0,
@@ -86,7 +82,7 @@ numeric_literal: {
' 42: 2,',
' "42": 3,',
' 37: 4,',
' o: 5,',
' a: 5,',
' 1e42: 6,',
' b: 7,',
' "1e+42": 8',
@@ -96,7 +92,7 @@ numeric_literal: {
'',
'console.log(obj[42], obj["42"]);',
'',
'console.log(obj[37], obj["o"], obj[37], obj["37"]);',
'console.log(obj[37], obj["a"], obj[37], obj["37"]);',
'',
'console.log(obj[1e42], obj["b"], obj["1e+42"]);',
]
@@ -109,9 +105,7 @@ numeric_literal: {
}
identifier: {
mangle = {
properties: true,
}
mangle_props = {}
input: {
var obj = {
abstract: 1,
@@ -179,32 +173,32 @@ identifier: {
}
expect: {
var obj = {
e: 1,
t: 2,
n: 3,
a: 4,
i: 5,
o: 6,
r: 7,
l: 8,
s: 9,
c: 10,
f: 11,
u: 12,
d: 13,
h: 14,
p: 15,
b: 16,
v: 17,
w: 18,
y: 19,
g: 20,
m: 21,
k: 22,
x: 23,
j: 24,
z: 25,
q: 26,
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,
@@ -235,11 +229,11 @@ identifier: {
Z: 54,
$: 55,
_: 56,
ee: 57,
te: 58,
ne: 59,
ae: 60,
ie: 61,
aa: 57,
ba: 58,
ca: 59,
da: 60,
ea: 61,
};
}
}

View File

@@ -1,8 +1,6 @@
unary_prefix: {
options = {
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -12,6 +10,10 @@ unary_prefix: {
return x;
}());
}
expect_exact: "console.log(-2/3);"
expect: {
console.log(function() {
return -2 / 3;
}());
}
expect_stdout: true
}

View File

@@ -1,7 +1,6 @@
iife_for: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -27,7 +26,6 @@ iife_for: {
iife_for_in: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -53,7 +51,6 @@ iife_for_in: {
iife_do: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -83,7 +80,6 @@ iife_do: {
iife_while: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -134,5 +130,5 @@ label_while: {
L: while (0) continue L;
}
}
expect_exact: "function f(){L:0}"
expect_exact: "function f(){L:;}"
}

View File

@@ -38,7 +38,7 @@ mixed: {
}
}
input: {
var ENV = 3;
const ENV = 3;
var FOO = 4;
f(ENV * 10);
--FOO;
@@ -49,7 +49,7 @@ mixed: {
x = DEBUG;
}
expect: {
var ENV = 3;
const 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,12]',
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,14]',
'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]',

View File

@@ -1,498 +0,0 @@
collapse_vars_constants: {
options = {
collapse_vars: true,
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
function f1(x) {
var a = 4, b = x.prop, c = 5, d = sideeffect1(), e = sideeffect2();
return b + (function() { return d - a * e - c; })();
}
function f2(x) {
var a = 4, b = x.prop, c = 5, not_used = sideeffect1(), e = sideeffect2();
return b + (function() { return -a * e - c; })();
}
}
expect: {
function f1(x) {
var b = x.prop, d = sideeffect1(), e = sideeffect2();
return b + (d - 4 * e - 5);
}
function f2(x) {
var b = x.prop;
sideeffect1();
return b + (-4 * sideeffect2() - 5);
}
}
}
modified: {
options = {
collapse_vars: true,
inline: true,
unused: true,
}
input: {
function f5(b) {
var a = function() {
return b;
}();
return b++ + a;
}
console.log(f5(1));
}
expect: {
function f5(b) {
var a = b;
return b++ + a;
}
console.log(f5(1));
}
expect_stdout: "2"
}
ref_scope: {
options = {
collapse_vars: true,
inline: 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 a + b;
}());
}
expect_stdout: true
}
safe_undefined: {
options = {
conditionals: true,
if_return: true,
inline: true,
unsafe: false,
unused: true,
}
mangle = {}
input: {
var a, c;
console.log(function(undefined) {
return function() {
if (a)
return b;
if (c)
return d;
};
}(1)());
}
expect: {
var a, c;
console.log(a ? b : c ? d : void 0);
}
expect_stdout: true
}
negate_iife_3: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: true,
}
input: {
(function(){ return t })() ? console.log(true) : console.log(false);
}
expect: {
t ? console.log(true) : console.log(false);
}
}
negate_iife_3_off: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: false,
}
input: {
(function(){ return t })() ? console.log(true) : console.log(false);
}
expect: {
t ? console.log(true) : console.log(false);
}
}
negate_iife_4: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: true,
sequences: true,
}
input: {
(function(){ return t })() ? console.log(true) : console.log(false);
(function(){
console.log("something");
})();
}
expect: {
t ? console.log(true) : console.log(false), void console.log("something");
}
}
negate_iife_5: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: true,
sequences: true,
}
input: {
if ((function(){ return t })()) {
foo(true);
} else {
bar(false);
}
(function(){
console.log("something");
})();
}
expect: {
t ? foo(true) : bar(false), void console.log("something");
}
}
negate_iife_5_off: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: false,
sequences: true,
};
input: {
if ((function(){ return t })()) {
foo(true);
} else {
bar(false);
}
(function(){
console.log("something");
})();
}
expect: {
t ? foo(true) : bar(false), void console.log("something");
}
}
issue_1254_negate_iife_true: {
options = {
expression: true,
inline: true,
negate_iife: true,
}
input: {
(function() {
return function() {
console.log('test')
};
})()();
}
expect_exact: 'void console.log("test");'
expect_stdout: true
}
issue_1254_negate_iife_nested: {
options = {
expression: true,
inline: true,
negate_iife: true,
}
input: {
(function() {
return function() {
console.log('test')
};
})()()()()();
}
expect_exact: '(void console.log("test"))()()();'
}
negate_iife_issue_1073: {
options = {
conditionals: true,
evaluate: true,
inline: true,
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
unused: true,
};
input: {
new (function(a) {
return function Foo() {
this.x = a;
console.log(this);
};
}(7))();
}
expect: {
new function() {
this.x = 7,
console.log(this);
}();
}
expect_stdout: true
}
issue_1288_side_effects: {
options = {
conditionals: true,
evaluate: true,
inline: true,
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
};
input: {
if (w) ;
else {
(function f() {})();
}
if (!x) {
(function() {
x = {};
})();
}
if (y)
(function() {})();
else
(function(z) {
return z;
})(0);
}
expect: {
w;
x || (x = {});
y;
}
}
inner_var_for_in_1: {
options = {
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
}
input: {
function f() {
var a = 1, b = 2;
for (b in (function() {
return x(a, b, c);
})()) {
var c = 3, d = 4;
x(a, b, c, d);
}
x(a, b, c, d);
}
}
expect: {
function f() {
var a = 1, b = 2;
for (b in x(1, b, c)) {
var c = 3, d = 4;
x(1, b, c, d);
}
x(1, b, c, d);
}
}
}
issue_1595_3: {
options = {
evaluate: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function f(a) {
return g(a + 1);
})(2);
}
expect: {
g(3);
}
}
issue_1758: {
options = {
inline: true,
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 c--, c--, void c.toString();
}());
}
expect_stdout: "undefined"
}
wrap_iife: {
options = {
inline: true,
negate_iife: false,
}
beautify = {
wrap_iife: true,
}
input: {
(function() {
return function() {
console.log('test')
};
})()();
}
expect_exact: 'void console.log("test");'
}
wrap_iife_in_expression: {
options = {
inline: true,
negate_iife: false,
}
beautify = {
wrap_iife: true,
}
input: {
foo = (function () {
return bar();
})();
}
expect_exact: 'foo=bar();'
}
wrap_iife_in_return_call: {
options = {
inline: true,
negate_iife: false,
}
beautify = {
wrap_iife: true,
}
input: {
(function() {
return (function() {
console.log('test')
})();
})()();
}
expect_exact: '(void console.log("test"))();'
}
pure_annotation_1: {
options = {
inline: true,
side_effects: true,
}
input: {
/*@__PURE__*/(function() {
console.log("hello");
}());
}
expect_exact: ""
}
pure_annotation_2: {
options = {
collapse_vars: true,
inline: true,
side_effects: true,
}
input: {
/*@__PURE__*/(function(n) {
console.log("hello", n);
}(42));
}
expect_exact: ""
}
drop_fargs: {
options = {
cascade: true,
inline: true,
keep_fargs: false,
side_effects: true,
unused: true,
}
input: {
var a = 1;
!function(a_1) {
a++;
}(a++ + (a && a.var));
console.log(a);
}
expect: {
var a = 1;
++a && a.var, a++;
console.log(a);
}
expect_stdout: "3"
}
keep_fargs: {
options = {
cascade: true,
inline: true,
keep_fargs: true,
side_effects: true,
unused: true,
}
input: {
var a = 1;
!function(a_1) {
a++;
}(a++ + (a && a.var));
console.log(a);
}
expect: {
var a = 1;
++a && a.var, a++;
console.log(a);
}
expect_stdout: "3"
}

View File

@@ -17,6 +17,6 @@ wrongly_optimized: {
foo();
}
// TODO: optimize to `func(), bar()`
(func(), 1) && bar();
(func(), 0) || bar();
}
}

View File

@@ -100,7 +100,7 @@ wrongly_optimized: {
foo();
}
// TODO: optimize to `func(), bar()`
if (func(), 1) bar();
if (func(), !0) bar();
}
}
@@ -159,7 +159,7 @@ negate_iife_4: {
})();
}
expect: {
!function(){ return t }() ? console.log(false) : console.log(true), function(){
(function(){ return t })() ? console.log(true) : console.log(false), function(){
console.log("something");
}();
}
@@ -183,7 +183,7 @@ negate_iife_5: {
})();
}
expect: {
!function(){ return t }() ? bar(false) : foo(true), function(){
(function(){ return t })() ? foo(true) : bar(false), function(){
console.log("something");
}();
}
@@ -207,7 +207,7 @@ negate_iife_5_off: {
})();
}
expect: {
!function(){ return t }() ? bar(false) : foo(true), function(){
(function(){ return t })() ? foo(true) : bar(false), function(){
console.log("something");
}();
}

View File

@@ -1,45 +1,37 @@
dont_reuse_prop: {
mangle = {
properties: {
regex: /asd/,
},
}
mangle_props = {
regex: /asd/
};
input: {
"aaaaaaaaaabbbbb";
var obj = {};
obj.a = 123;
obj.asd = 256;
console.log(obj.a);
}
expect: {
"aaaaaaaaaabbbbb";
var obj = {};
obj.a = 123;
obj.b = 256;
console.log(obj.a);
}
expect_stdout: "123"
}
unmangleable_props_should_always_be_reserved: {
mangle = {
properties: {
regex: /asd/,
},
}
mangle_props = {
regex: /asd/
};
input: {
"aaaaaaaaaabbbbb";
var obj = {};
obj.asd = 256;
obj.a = 123;
console.log(obj.a);
}
expect: {
"aaaaaaaaaabbbbb";
var obj = {};
obj.b = 256;
obj.a = 123;
console.log(obj.a);
}
expect_stdout: "123"
}

View File

@@ -1,8 +1,7 @@
this_binding_conditionals: {
options = {
conditionals: true,
evaluate: true,
side_effects: true,
evaluate : true
};
input: {
(1 && a)();
@@ -52,7 +51,6 @@ this_binding_collapse_vars: {
options = {
collapse_vars: true,
toplevel: true,
unused: true,
};
input: {
var c = a; c();

View File

@@ -146,13 +146,55 @@ 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,
dead_code: true,
evaluate: true,
loops: true,
passes: 2,
side_effects: true,
};
input: {
while (true) {
@@ -203,7 +245,7 @@ issue_1532: {
issue_186: {
beautify = {
beautify: false,
ie8: false,
screw_ie8: true,
}
input: {
var x = 3;
@@ -222,7 +264,7 @@ issue_186: {
issue_186_ie8: {
beautify = {
beautify: false,
ie8: true,
screw_ie8: false,
}
input: {
var x = 3;
@@ -241,7 +283,7 @@ issue_186_ie8: {
issue_186_beautify: {
beautify = {
beautify: true,
ie8: false,
screw_ie8: true,
}
input: {
var x = 3;
@@ -268,7 +310,7 @@ issue_186_beautify: {
issue_186_beautify_ie8: {
beautify = {
beautify: true,
ie8: true,
screw_ie8: false,
}
input: {
var x = 3;
@@ -298,7 +340,7 @@ issue_186_bracketize: {
beautify = {
beautify: false,
bracketize: true,
ie8: false,
screw_ie8: true,
}
input: {
var x = 3;
@@ -318,7 +360,7 @@ issue_186_bracketize_ie8: {
beautify = {
beautify: false,
bracketize: true,
ie8: true,
screw_ie8: false,
}
input: {
var x = 3;
@@ -338,7 +380,7 @@ issue_186_beautify_bracketize: {
beautify = {
beautify: true,
bracketize: true,
ie8: false,
screw_ie8: true,
}
input: {
var x = 3;
@@ -370,7 +412,7 @@ issue_186_beautify_bracketize_ie8: {
beautify = {
beautify: true,
bracketize: true,
ie8: true,
screw_ie8: false,
}
input: {
var x = 3;
@@ -438,57 +480,3 @@ do_switch: {
} while (false);
}
}
in_parenthesis_1: {
input: {
for (("foo" in {});0;);
}
expect_exact: 'for(("foo"in{});0;);'
}
in_parenthesis_2: {
input: {
for ((function(){ "foo" in {}; });0;);
}
expect_exact: 'for(function(){"foo"in{}};0;);'
}
init_side_effects: {
options = {
loops: true,
side_effects: true,
};
input: {
for (function() {}(), i = 0; i < 5; i++) console.log(i);
for (function() {}(); i < 10; i++) console.log(i);
}
expect: {
for (i = 0; i < 5; i++) console.log(i);
for (; i < 10; i++) console.log(i);
}
expect_stdout: true
}
dead_code_condition: {
options = {
dead_code: true,
evaluate: true,
loops: true,
sequences: true,
}
input: {
for (var a = 0, b = 5; (a += 1, 3) - 3 && b > 0; b--) {
var c = function() {
b--;
}(a++);
}
console.log(a);
}
expect: {
var c;
var a = 0, b = 5;
a += 1, 0,
console.log(a);
}
expect_stdout: "1"
}

View File

@@ -22,25 +22,27 @@ negate_iife_1_off: {
negate_iife_2: {
options = {
inline: true,
negate_iife: true,
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: {
options = {
inline: true,
negate_iife: true,
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: {
@@ -60,7 +62,6 @@ negate_iife_3_evaluate: {
options = {
conditionals: true,
evaluate: true,
inline: true,
negate_iife: true,
}
input: {
@@ -103,7 +104,6 @@ negate_iife_3_off_evaluate: {
options = {
conditionals: true,
evaluate: true,
inline: true,
negate_iife: false,
}
input: {

View File

@@ -82,19 +82,3 @@ new_with_unary_prefix: {
}
expect_exact: 'var bar=(+new Date).toString(32);';
}
dot_parenthesis_1: {
input: {
console.log(new (Math.random().constructor) instanceof Number);
}
expect_exact: "console.log(new(Math.random().constructor)instanceof Number);"
expect_stdout: "true"
}
dot_parenthesis_2: {
input: {
console.log(typeof new function(){Math.random()}.constructor);
}
expect_exact: "console.log(typeof new function(){Math.random()}.constructor);"
expect_stdout: "function"
}

View File

@@ -1,38 +0,0 @@
eval_let_6: {
input: {
eval("let a;");
console.log();
}
expect: {
eval("let a;");
console.log();
}
expect_stdout: ""
node_version: ">=6"
}
eval_let_4: {
input: {
eval("let a;");
console.log();
}
expect: {
eval("let a;");
console.log();
}
expect_stdout: SyntaxError("Block-scoped declarations (let, const, function, class) not yet supported outside strict mode")
node_version: "4"
}
eval_let_0: {
input: {
eval("let a;");
console.log();
}
expect: {
eval("let a;");
console.log();
}
expect_stdout: SyntaxError("Unexpected identifier")
node_version: "<=0.12"
}

View File

@@ -1,8 +1,7 @@
keep_properties: {
options = {
evaluate: true,
properties: false,
}
properties: false
};
input: {
a["foo"] = "bar";
}
@@ -13,12 +12,9 @@ keep_properties: {
dot_properties: {
options = {
evaluate: true,
properties: true,
}
beautify = {
ie8: true,
}
screw_ie8: false
};
input: {
a["foo"] = "bar";
a["if"] = "if";
@@ -39,12 +35,9 @@ dot_properties: {
dot_properties_es5: {
options = {
evaluate: true,
properties: true,
}
beautify = {
ie8: false,
}
screw_ie8: true
};
input: {
a["foo"] = "bar";
a["if"] = "if";
@@ -64,8 +57,8 @@ dot_properties_es5: {
sub_properties: {
options = {
evaluate: true,
properties: true,
}
properties: true
};
input: {
a[0] = 0;
a["0"] = 1;
@@ -84,18 +77,18 @@ sub_properties: {
a[3.14] = 3;
a.if = 4;
a["foo bar"] = 5;
a.NaN = 6;
a.null = 7;
a[NaN] = 6;
a[null] = 7;
a[void 0] = 8;
}
}
evaluate_array_length: {
options = {
evaluate: true,
properties: true,
unsafe: true,
}
evaluate: true
};
input: {
a = [1, 2, 3].length;
a = [1, 2, 3].join()["len" + "gth"];
@@ -112,10 +105,10 @@ evaluate_array_length: {
evaluate_string_length: {
options = {
evaluate: true,
properties: true,
unsafe: true,
}
evaluate: true
};
input: {
a = "foo".length;
a = ("foo" + "bar")["len" + "gth"];
@@ -131,11 +124,9 @@ evaluate_string_length: {
}
mangle_properties: {
mangle = {
properties: {
keep_quoted: false,
},
}
mangle_props = {
ignore_quoted: false
};
input: {
a["foo"] = "bar";
a.color = "red";
@@ -146,21 +137,18 @@ mangle_properties: {
expect: {
a["a"] = "bar";
a.b = "red";
x = {o: 10};
a.r(x.o, a.a);
a['r']({b: "blue", a: "baz"});
x = {c: 10};
a.d(x.c, a.a);
a['d']({b: "blue", a: "baz"});
}
}
mangle_unquoted_properties: {
options = {
evaluate: true,
properties: false,
properties: false
}
mangle = {
properties: {
keep_quoted: true,
},
mangle_props = {
ignore_quoted: true
}
beautify = {
beautify: false,
@@ -189,26 +177,24 @@ mangle_unquoted_properties: {
function f1() {
a["foo"] = "bar";
a.color = "red";
a.r = 2;
x = {"bar": 10, b: 7};
a.b = 9;
a.b = 2;
x = {"bar": 10, c: 7};
a.c = 9;
}
function f2() {
a.foo = "bar";
a['color'] = "red";
x = {bar: 10, b: 7};
a.b = 9;
a.r = 3;
x = {bar: 10, c: 7};
a.c = 9;
a.b = 3;
}
}
}
mangle_debug: {
mangle = {
properties: {
debug: "",
},
}
mangle_props = {
debug: ""
};
input: {
a.foo = "bar";
x = { baz: "ban" };
@@ -220,11 +206,9 @@ mangle_debug: {
}
mangle_debug_true: {
mangle = {
properties: {
debug: true,
},
}
mangle_props = {
debug: true
};
input: {
a.foo = "bar";
x = { baz: "ban" };
@@ -236,11 +220,9 @@ mangle_debug_true: {
}
mangle_debug_suffix: {
mangle = {
properties: {
debug: "XYZ",
},
}
mangle_props = {
debug: "XYZ"
};
input: {
a.foo = "bar";
x = { baz: "ban" };
@@ -251,17 +233,14 @@ mangle_debug_suffix: {
}
}
mangle_debug_suffix_keep_quoted: {
mangle_debug_suffix_ignore_quoted: {
options = {
evaluate: true,
properties: false,
properties: false
}
mangle = {
properties: {
mangle_props = {
ignore_quoted: true,
debug: "XYZ",
keep_quoted: true,
reserved: [],
},
reserved: []
}
beautify = {
beautify: false,
@@ -678,379 +657,3 @@ accessor_this: {
expect_exact: 'var a=1;var b={get this(){return a},set this(c){a=c}};console.log(b.this,b.this=2,b.this);'
expect_stdout: "1 2 2"
}
issue_2208_1: {
options = {
inline: true,
properties: true,
side_effects: true,
}
input: {
console.log({
p: function() {
return 42;
}
}.p());
}
expect: {
console.log(42);
}
expect_stdout: "42"
}
issue_2208_2: {
options = {
inline: true,
properties: true,
side_effects: true,
}
input: {
console.log({
a: 42,
p: function() {
return this.a;
}
}.p());
}
expect: {
console.log({
a: 42,
p: function() {
return this.a;
}
}.p());
}
expect_stdout: "42"
}
issue_2208_3: {
options = {
inline: true,
properties: true,
side_effects: true,
}
input: {
a = 42;
console.log({
p: function() {
return function() {
return this.a;
}();
}
}.p());
}
expect: {
a = 42;
console.log(function() {
return this.a;
}());
}
expect_stdout: "42"
}
issue_2208_4: {
options = {
inline: true,
properties: true,
side_effects: true,
}
input: {
function foo() {}
console.log({
a: foo(),
p: function() {
return 42;
}
}.p());
}
expect: {
function foo() {}
console.log((foo(), function() {
return 42;
})());
}
expect_stdout: "42"
}
issue_2208_5: {
options = {
inline: true,
properties: true,
side_effects: true,
}
input: {
console.log({
p: "FAIL",
p: function() {
return 42;
}
}.p());
}
expect: {
console.log(42);
}
expect_stdout: "42"
}
issue_2256: {
options = {
side_effects: true,
}
mangle = {
properties: {
keep_quoted: true,
},
}
input: {
({ "keep": 1 });
g.keep = g.change;
}
expect: {
g.keep = g.g;
}
}
lhs_prop_1: {
options = {
evaluate: true,
properties: true,
}
input: {
console.log(++{
a: 1
}.a);
}
expect: {
console.log(++{
a: 1
}.a);
}
expect_stdout: "2"
}
lhs_prop_2: {
options = {
evaluate: true,
inline: true,
properties: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
[1][0] = 42;
(function(a) {
a.b = "g";
})("abc");
(function(a) {
a[2] = "g";
})("def");
(function(a) {
a[""] = "g";
})("ghi");
}
expect: {
[1][0] = 42;
"abc".b = "g";
"def"[2] = "g";
"ghi"[""] = "g";
}
}
literal_duplicate_key_side_effects: {
options = {
properties: true,
side_effects: true,
}
input: {
console.log({
a: "FAIL",
a: console.log ? "PASS" : "FAIL"
}.a);
}
expect: {
console.log(console.log ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
}
prop_side_effects_1: {
options = {
evaluate: true,
inline: true,
properties: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var C = 1;
console.log(C);
var obj = {
bar: function() {
return C + C;
}
};
console.log(obj.bar());
}
expect: {
console.log(1);
var obj = {
bar: function() {
return 2;
}
};
console.log(obj.bar());
}
expect_stdout: [
"1",
"2",
]
}
prop_side_effects_2: {
options = {
evaluate: true,
inline: true,
passes: 2,
properties: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var C = 1;
console.log(C);
var obj = {
"": function() {
return C + C;
}
};
console.log(obj[""]());
}
expect: {
console.log(1);
console.log(2);
}
expect_stdout: [
"1",
"2",
]
}
accessor_1: {
options = {
properties: true,
}
input: {
console.log({
a: "FAIL",
get a() {
return "PASS";
}
}.a);
}
expect: {
console.log({
a: "FAIL",
get a() {
return "PASS";
}
}.a);
}
expect_stdout: "PASS"
node_version: ">=4"
}
accessor_2: {
options = {
properties: true,
}
input: {
console.log({
get a() {
return "PASS";
},
set a(v) {},
a: "FAIL"
}.a);
}
expect: {
console.log({
get a() {
return "PASS";
},
set a(v) {},
a: "FAIL"
}.a);
}
expect_stdout: true
}
array_hole: {
options = {
properties: true,
side_effects: true,
}
input: {
console.log(
[ 1, 2, , 3][1],
[ 1, 2, , 3][2],
[ 1, 2, , 3][3]
);
}
expect: {
console.log(2, void 0, 3);
}
expect_stdout: "2 undefined 3"
}
new_this: {
options = {
properties: true,
side_effects: true,
}
input: {
new {
f: function(a) {
this.a = a;
}
}.f(42);
}
expect: {
new function(a) {
this.a = a;
}(42);
}
}
issue_2513: {
options = {
evaluate: true,
properties: true,
}
input: {
!function(Infinity, NaN, undefined) {
console.log("a"[1/0], "b"["Infinity"]);
console.log("c"[0/0], "d"["NaN"]);
console.log("e"[void 0], "f"["undefined"]);
}(0, 0, 0);
}
expect: {
!function(Infinity, NaN, undefined) {
console.log("a"[1/0], "b"[1/0]);
console.log("c".NaN, "d".NaN);
console.log("e"[void 0], "f"[void 0]);
}(0, 0, 0);
}
expect_stdout: [
"undefined undefined",
"undefined undefined",
"undefined undefined",
]
}

View File

@@ -1,7 +1,6 @@
strict: {
options = {
pure_getters: "strict",
reduce_funcs: false,
reduce_vars: false,
side_effects: true,
toplevel: true,
@@ -31,7 +30,6 @@ strict: {
strict_reduce_vars: {
options = {
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -60,7 +58,6 @@ strict_reduce_vars: {
unsafe: {
options = {
pure_getters: true,
reduce_funcs: false,
reduce_vars: false,
side_effects: true,
toplevel: true,
@@ -87,7 +84,6 @@ unsafe: {
unsafe_reduce_vars: {
options = {
pure_getters: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -182,432 +178,3 @@ impure_getter_2: {
}
expect: {}
}
issue_2110_1: {
options = {
cascade: true,
pure_getters: "strict",
sequences: true,
side_effects: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
function f() {
function f() {}
function g() {
return this;
}
f.g = g;
return f.g();
}
console.log(typeof f());
}
expect: {
function f() {
function f() {}
return f.g = function() {
return this;
}, f.g();
}
console.log(typeof f());
}
expect_stdout: "function"
}
issue_2110_2: {
options = {
collapse_vars: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
function f() {
function f() {}
function g() {
return this;
}
f.g = g;
return f.g();
}
console.log(typeof f());
}
expect: {
function f() {
function f() {}
f.g = function() {
return this;
};
return f.g();
}
console.log(typeof f());
}
expect_stdout: "function"
}
set_immutable_1: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 1;
a.foo += "";
if (a.foo) console.log("FAIL");
else console.log("PASS");
}
expect: {
1..foo += "";
if (1..foo) console.log("FAIL");
else console.log("PASS");
}
expect_stdout: "PASS"
}
set_immutable_2: {
options = {
cascade: true,
conditionals: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
}
input: {
var a = 1;
a.foo += "";
if (a.foo) console.log("FAIL");
else console.log("PASS");
}
expect: {
var a = 1;
a.foo += "", a.foo ? console.log("FAIL") : console.log("PASS");
}
expect_stdout: "PASS"
}
set_immutable_3: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var a = 1;
a.foo += "";
if (a.foo) console.log("FAIL");
else console.log("PASS");
}
expect: {
"use strict";
1..foo += "";
if (1..foo) console.log("FAIL");
else console.log("PASS");
}
expect_stdout: true
}
set_immutable_4: {
options = {
cascade: true,
conditionals: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
}
input: {
"use strict";
var a = 1;
a.foo += "";
if (a.foo) console.log("FAIL");
else console.log("PASS");
}
expect: {
"use strict";
var a = 1;
a.foo += "", a.foo ? console.log("FAIL") : console.log("PASS");
}
expect_stdout: true
}
set_mutable_1: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
!function a() {
a.foo += "";
if (a.foo) console.log("PASS");
else console.log("FAIL");
}();
}
expect: {
!function a() {
if (a.foo += "") console.log("PASS");
else console.log("FAIL");
}();
}
expect_stdout: "PASS"
}
set_mutable_2: {
options = {
cascade: true,
conditionals: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
}
input: {
!function a() {
a.foo += "";
if (a.foo) console.log("PASS");
else console.log("FAIL");
}();
}
expect: {
!function a() {
(a.foo += "") ? console.log("PASS") : console.log("FAIL");
}();
}
expect_stdout: "PASS"
}
issue_2313_1: {
options = {
cascade: true,
conditionals: true,
pure_getters: "strict",
sequences: true,
side_effects: true,
}
input: {
function x() {
console.log(1);
return {
y: function() {
console.log(2);
return {
z: 0
};
}
};
}
x().y().z++;
if (x().y().z) {
console.log(3);
}
}
expect: {
function x() {
return console.log(1), {
y: function() {
return console.log(2), {
z: 0
};
}
};
}
x().y().z++,
x().y().z && console.log(3);
}
expect_stdout: [
"1",
"2",
"1",
"2",
]
}
issue_2313_2: {
options = {
cascade: true,
conditionals: true,
pure_getters: true,
sequences: true,
side_effects: true,
}
input: {
function x() {
console.log(1);
return {
y: function() {
console.log(2);
return {
z: 0
};
}
};
}
x().y().z++;
if (x().y().z) {
console.log(3);
}
}
expect: {
function x() {
return console.log(1), {
y: function() {
return console.log(2), {
z: 0
};
}
};
}
x().y().z++,
x().y().z && console.log(3);
}
expect_stdout: [
"1",
"2",
"1",
"2",
]
}
issue_2313_3: {
options = {
collapse_vars: true,
conditionals: true,
pure_getters: "strict",
}
input: {
function x() {
console.log(1);
return {
y: function() {
console.log(2);
return {
z: 0
};
}
};
}
x().y().z++;
if (x().y().z) {
console.log(3);
}
}
expect: {
function x() {
console.log(1);
return {
y: function() {
console.log(2);
return {
z: 0
};
}
};
}
x().y().z++;
x().y().z && console.log(3);
}
expect_stdout: [
"1",
"2",
"1",
"2",
]
}
issue_2313_4: {
options = {
collapse_vars: true,
conditionals: true,
pure_getters: true,
}
input: {
function x() {
console.log(1);
return {
y: function() {
console.log(2);
return {
z: 0
};
}
};
}
x().y().z++;
if (x().y().z) {
console.log(3);
}
}
expect: {
function x() {
console.log(1);
return {
y: function() {
console.log(2);
return {
z: 0
};
}
};
}
x().y().z++;
x().y().z && console.log(3);
}
expect_stdout: [
"1",
"2",
"1",
"2",
]
}
issue_2313_5: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
x().y++;
x().y;
}
expect: {
x().y++;
x().y;
}
}
issue_2313_6: {
options = {
pure_getters: true,
side_effects: true,
}
input: {
x().y++;
x().y;
}
expect: {
x().y++;
x();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,536 +0,0 @@
mangle_catch: {
rename = true
options = {
ie8: false,
toplevel: false,
}
mangle = {
ie8: false,
toplevel: false,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
a = "PASS";
}
console.log(a);
}
expect_exact: 'var a="FAIL";try{throw 1}catch(o){a="PASS"}console.log(a);'
expect_stdout: "PASS"
}
mangle_catch_ie8: {
rename = true
options = {
ie8: true,
toplevel: false,
}
mangle = {
ie8: true,
toplevel: false,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
a = "PASS";
}
console.log(a);
}
expect_exact: 'var a="FAIL";try{throw 1}catch(args){a="PASS"}console.log(a);'
expect_stdout: "PASS"
}
mangle_catch_var: {
rename = true
options = {
ie8: false,
toplevel: false,
}
mangle = {
ie8: false,
toplevel: false,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
var a = "PASS";
}
console.log(a);
}
expect_exact: 'var a="FAIL";try{throw 1}catch(o){var a="PASS"}console.log(a);'
expect_stdout: "PASS"
}
mangle_catch_var_ie8: {
rename = true
options = {
ie8: true,
toplevel: false,
}
mangle = {
ie8: true,
toplevel: false,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
var a = "PASS";
}
console.log(a);
}
expect_exact: 'var a="FAIL";try{throw 1}catch(args){var a="PASS"}console.log(a);'
expect_stdout: "PASS"
}
mangle_catch_toplevel: {
rename = true
options = {
ie8: false,
toplevel: true,
}
mangle = {
ie8: false,
toplevel: true,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
a = "PASS";
}
console.log(a);
}
expect_exact: 'var o="FAIL";try{throw 1}catch(c){o="PASS"}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_ie8_toplevel: {
rename = true
options = {
ie8: true,
toplevel: true,
}
mangle = {
ie8: true,
toplevel: true,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
a = "PASS";
}
console.log(a);
}
expect_exact: 'var o="FAIL";try{throw 1}catch(c){o="PASS"}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_var_toplevel: {
rename = true
options = {
ie8: false,
toplevel: true,
}
mangle = {
ie8: false,
toplevel: true,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
var a = "PASS";
}
console.log(a);
}
expect_exact: 'var o="FAIL";try{throw 1}catch(r){var o="PASS"}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_var_ie8_toplevel: {
rename = true
options = {
ie8: true,
toplevel: true,
}
mangle = {
ie8: true,
toplevel: true,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
var a = "PASS";
}
console.log(a);
}
expect_exact: 'var o="FAIL";try{throw 1}catch(r){var o="PASS"}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_redef_1: {
rename = true
options = {
ie8: false,
toplevel: false,
}
mangle = {
ie8: false,
toplevel: false,
}
input: {
var a = "PASS";
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'var a="PASS";try{throw"FAIL1"}catch(a){var a="FAIL2"}console.log(a);'
expect_stdout: "PASS"
}
mangle_catch_redef_1_ie8: {
rename = true
options = {
ie8: true,
toplevel: false,
}
mangle = {
ie8: true,
toplevel: false,
}
input: {
var a = "PASS";
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'var a="PASS";try{throw"FAIL1"}catch(a){var a="FAIL2"}console.log(a);'
expect_stdout: "PASS"
}
mangle_catch_redef_1_toplevel: {
rename = true
options = {
ie8: false,
toplevel: true,
}
mangle = {
ie8: false,
toplevel: true,
}
input: {
var a = "PASS";
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'var o="PASS";try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_redef_1_ie8_toplevel: {
rename = true
options = {
ie8: true,
toplevel: true,
}
mangle = {
ie8: true,
toplevel: true,
}
input: {
var a = "PASS";
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'var o="PASS";try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_redef_2: {
rename = true
options = {
ie8: false,
toplevel: false,
}
mangle = {
ie8: false,
toplevel: false,
}
input: {
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'try{throw"FAIL1"}catch(a){var a="FAIL2"}console.log(a);'
expect_stdout: "undefined"
}
mangle_catch_redef_2_ie8: {
rename = true
options = {
ie8: true,
toplevel: false,
}
mangle = {
ie8: true,
toplevel: false,
}
input: {
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'try{throw"FAIL1"}catch(a){var a="FAIL2"}console.log(a);'
expect_stdout: "undefined"
}
mangle_catch_redef_2_toplevel: {
rename = true
options = {
ie8: false,
toplevel: true,
}
mangle = {
ie8: false,
toplevel: true,
}
input: {
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
expect_stdout: "undefined"
}
mangle_catch_redef_2_ie8_toplevel: {
rename = true
options = {
ie8: true,
toplevel: true,
}
mangle = {
ie8: true,
toplevel: true,
}
input: {
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
expect_stdout: "undefined"
}
issue_2120_1: {
rename = true
mangle = {
ie8: false,
}
input: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (t) {
try {
throw 0;
} catch (a) {
if (t) b = "PASS";
}
}
console.log(b);
}
expect_stdout: "PASS"
}
issue_2120_2: {
rename = true
mangle = {
ie8: true,
}
input: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect_stdout: "PASS"
}
function_iife_catch: {
rename = true
mangle = {
ie8: false,
}
input: {
function f(n) {
!function() {
try {
throw 0;
} catch (n) {
var a = 1;
console.log(n, a);
}
}();
}
f();
}
expect_exact: "function f(o){!function(){try{throw 0}catch(c){var o=1;console.log(c,o)}}()}f();"
expect_stdout: "0 1"
}
function_iife_catch_ie8: {
rename = true
mangle = {
ie8: true,
}
input: {
function f(n) {
!function() {
try {
throw 0;
} catch (n) {
var a = 1;
console.log(n, a);
}
}();
}
f();
}
expect_exact: "function f(o){!function(){try{throw 0}catch(o){var c=1;console.log(o,c)}}()}f();"
expect_stdout: "0 1"
}
function_catch_catch: {
rename = true
mangle = {
ie8: false,
}
input: {
var o = 0;
function f() {
try {
throw 1;
} catch (c) {
try {
throw 2;
} catch (o) {
var o = 3;
console.log(o);
}
}
console.log(o);
}
f();
}
expect_exact: "var o=0;function f(){try{throw 1}catch(c){try{throw 2}catch(o){var o=3;console.log(o)}}console.log(o)}f();"
expect_stdout: [
"3",
"undefined",
]
}
function_catch_catch_ie8: {
rename = true
mangle = {
ie8: true,
}
input: {
var o = 0;
function f() {
try {
throw 1;
} catch (c) {
try {
throw 2;
} catch (o) {
var o = 3;
console.log(o);
}
}
console.log(o);
}
f();
}
expect_exact: "var o=0;function f(){try{throw 1}catch(c){try{throw 2}catch(o){var o=3;console.log(o)}}console.log(o)}f();"
expect_stdout: [
"3",
"undefined",
]
}

View File

@@ -122,25 +122,3 @@ return_undefined: {
}
}
}
return_void: {
options = {
if_return: true,
inline: true,
reduce_vars: true,
unused: true,
}
input: {
function f() {
function g() {
h();
}
return g();
}
}
expect: {
function f() {
h();
}
}
}

View File

@@ -1,14 +0,0 @@
console_log: {
input: {
console.log("%% %s");
console.log("%% %s", "%s");
}
expect: {
console.log("%% %s");
console.log("%% %s", "%s");
}
expect_stdout: [
"%% %s",
"% %s",
]
}

View File

@@ -1,9 +1,9 @@
do_screw: {
options = {
ie8: false,
screw_ie8: true,
}
beautify = {
ie8: false,
screw_ie8: true,
ascii_only: true,
}
input: {
@@ -14,10 +14,10 @@ do_screw: {
dont_screw: {
options = {
ie8: true,
screw_ie8: false,
}
beautify = {
ie8: true,
screw_ie8: false,
ascii_only: true,
}
input: {
@@ -28,7 +28,7 @@ dont_screw: {
do_screw_constants: {
options = {
ie8: false,
screw_ie8: true,
}
input: {
f(undefined, Infinity);
@@ -38,7 +38,7 @@ do_screw_constants: {
dont_screw_constants: {
options = {
ie8: true,
screw_ie8: false,
}
input: {
f(undefined, Infinity);
@@ -47,15 +47,9 @@ dont_screw_constants: {
}
do_screw_try_catch: {
options = {
ie8: false,
}
mangle = {
ie8: false,
}
beautify = {
ie8: false,
}
options = { screw_ie8: true };
mangle = { screw_ie8: true };
beautify = { screw_ie8: true };
input: {
good = function(e){
return function(error){
@@ -81,15 +75,9 @@ do_screw_try_catch: {
}
dont_screw_try_catch: {
options = {
ie8: true,
}
mangle = {
ie8: true,
}
beautify = {
ie8: true,
}
options = { screw_ie8: false };
mangle = { screw_ie8: false };
beautify = { screw_ie8: false };
input: {
bad = function(e){
return function(error){
@@ -115,15 +103,9 @@ dont_screw_try_catch: {
}
do_screw_try_catch_undefined: {
options = {
ie8: false,
}
mangle = {
ie8: false,
}
beautify = {
ie8: false,
}
options = { screw_ie8: true };
mangle = { screw_ie8: true };
beautify = { screw_ie8: true };
input: {
function a(b){
try {
@@ -150,15 +132,9 @@ do_screw_try_catch_undefined: {
}
dont_screw_try_catch_undefined: {
options = {
ie8: true,
}
mangle = {
ie8: true,
}
beautify = {
ie8: true,
}
options = { screw_ie8: false };
mangle = { screw_ie8: false };
beautify = { screw_ie8: false };
input: {
function a(b){
try {
@@ -187,13 +163,12 @@ dont_screw_try_catch_undefined: {
reduce_vars: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
ie8: true,
screw_ie8: false,
unused: true,
}
mangle = {
ie8: true,
screw_ie8: false,
}
input: {
function f() {
@@ -221,10 +196,10 @@ reduce_vars: {
issue_1586_1: {
options = {
ie8: true,
screw_ie8: false,
}
mangle = {
ie8: true,
screw_ie8: false,
}
input: {
function f() {
@@ -240,10 +215,10 @@ issue_1586_1: {
issue_1586_2: {
options = {
ie8: false,
screw_ie8: true,
}
mangle = {
ie8: false,
screw_ie8: true,
}
input: {
function f() {
@@ -256,139 +231,3 @@ issue_1586_2: {
}
expect_exact: "function f(){try{x()}catch(c){console.log(c.message)}}"
}
issue_2120_1: {
mangle = {
ie8: false,
}
input: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (t) {
try {
throw 0;
} catch (a) {
if (t) b = "PASS";
}
}
console.log(b);
}
expect_stdout: "PASS"
}
issue_2120_2: {
mangle = {
ie8: true,
}
input: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect_stdout: "PASS"
}
issue_2254_1: {
mangle = {
ie8: false,
}
input: {
"eeeeee";
try {
console.log(f("PASS"));
} catch (e) {}
function f(s) {
try {
throw "FAIL";
} catch (e) {
return s;
}
}
}
expect: {
"eeeeee";
try {
console.log(f("PASS"));
} catch (e) {}
function f(e) {
try {
throw "FAIL";
} catch (t) {
return e;
}
}
}
expect_stdout: "PASS"
}
issue_2254_2: {
mangle = {
ie8: true,
}
input: {
"eeeeee";
try {
console.log(f("PASS"));
} catch (e) {}
function f(s) {
try {
throw "FAIL";
} catch (e) {
return s;
}
}
}
expect: {
"eeeeee";
try {
console.log(f("PASS"));
} catch (e) {}
function f(t) {
try {
throw "FAIL";
} catch (e) {
return t;
}
}
}
expect_stdout: "PASS"
}

View File

@@ -176,11 +176,6 @@ for_sequences: {
// 4
x = (foo in bar);
for (y = 5; false;);
// 5
x = function() {
foo in bar;
};
for (y = 5; false;);
}
expect: {
// 1
@@ -193,10 +188,6 @@ for_sequences: {
// 4
x = (foo in bar);
for (y = 5; false;);
// 5
for (x = function() {
foo in bar;
}, y = 5; false;);
}
}
@@ -252,12 +243,13 @@ negate_iife_for: {
input: {
(function() {})();
for (i = 0; i < 5; i++) console.log(i);
(function() {})();
for (; i < 10; i++) console.log(i);
for (; i < 5; i++) console.log(i);
}
expect: {
for (!function() {}(), i = 0; i < 5; i++) console.log(i);
for (!function() {}(); i < 10; i++) console.log(i);
for (function() {}(); i < 5; i++) console.log(i);
}
expect_stdout: true
}
@@ -468,7 +460,7 @@ issue_1758: {
console.log(function(c) {
var undefined = 42;
return function() {
return c--, c--, void c.toString();
return c--, c--, c.toString(), void 0;
}();
}());
}
@@ -489,12 +481,12 @@ delete_seq_1: {
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);
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
}
@@ -513,12 +505,12 @@ delete_seq_2: {
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);
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
}
@@ -538,12 +530,12 @@ delete_seq_3: {
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);
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
}
@@ -614,168 +606,31 @@ delete_seq_6: {
}
expect: {
var a;
console.log(!0);
console.log((a, !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);
}
}
issue_2062: {
options = {
booleans: true,
cascade: true,
conditionals: true,
side_effects: true,
}
input: {
var a = 1;
if ([ a || a++ + a--, a++ + a--, a && a.var ]);
console.log(a);
}
expect: {
var a = 1;
a || (a++, a--), a++, --a && a.var;
console.log(a);
}
expect_stdout: "1"
}
issue_2313: {
reassign_const: {
options = {
cascade: true,
sequences: true,
side_effects: true,
}
input: {
var a = 0, b = 0;
var foo = {
get c() {
function f() {
const a = 1;
a++;
return 42;
},
set c(c) {
b++;
},
d: function() {
this.c++;
if (this.c) console.log(a, b);
return a;
}
}
foo.d();
console.log(f());
}
expect: {
var a = 0, b = 0;
var foo = {
get c() {
return a++, 42;
},
set c(c) {
b++;
},
d: function() {
if (this.c++, this.c) console.log(a, b);
function f() {
const a = 1;
return a++, a;
}
console.log(f());
}
foo.d();
}
expect_stdout: "2 1"
expect_stdout: true
}

View File

@@ -8,12 +8,3 @@ 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(/[\\\\/]/)}"
}

View File

@@ -714,7 +714,6 @@ issue_1705_2: {
options = {
dead_code: true,
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -817,50 +816,3 @@ issue_1758: {
}
expect_stdout: "0 3"
}
issue_2535: {
options = {
evaluate: true,
dead_code: true,
switches: true,
}
input: {
switch(w(), 42) {
case 13: x();
case 42: y();
default: z();
}
}
expect: {
w(), 42;
42;
y();
z();
}
}
issue_1750: {
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;
true;
a, true;
b = 2;
console.log(a, b);
}
expect_stdout: "0 2"
}

View File

@@ -45,9 +45,9 @@ condition_evaluate: {
if (void 0 == null);
}
expect: {
while (0);
for (; 1;);
if (1);
while (!1);
for (; !0;);
if (!0);
}
}
@@ -68,7 +68,6 @@ label_if_break: {
conditionals: true,
dead_code: true,
evaluate: true,
side_effects: true,
}
input: {
L: if (true) {

View File

@@ -1,7 +1,6 @@
typeof_evaluation: {
options = {
evaluate: true,
typeofs: true,
evaluate: true
};
input: {
a = typeof 1;
@@ -45,7 +44,7 @@ typeof_in_boolean_context: {
function f2() { return g(), "Yes"; }
foo();
console.log(1);
var a = !(console.log(2), 1);
var a = !(console.log(2), !0);
foo();
}
}
@@ -58,83 +57,6 @@ issue_1668: {
if (typeof bar);
}
expect: {
if (1);
if (!0);
}
}
typeof_defun_1: {
options = {
evaluate: true,
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
typeofs: true,
unused: true,
}
input: {
function f() {
console.log("YES");
}
function g() {
h = 42;
console.log("NOPE");
}
function h() {
console.log("YUP");
}
g = 42;
"function" == typeof f && f();
"function" == typeof g && g();
"function" == typeof h && h();
}
expect: {
function g() {
h = 42;
console.log("NOPE");
}
function h() {
console.log("YUP");
}
g = 42;
console.log("YES");
"function" == typeof g && g();
h();
}
expect_stdout: [
"YES",
"YUP",
]
}
typeof_defun_2: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
typeofs: true,
}
input: {
var f = function() {
console.log(x);
};
var x = 0;
x++ < 2 && typeof f == "function" && f();
x++ < 2 && typeof f == "function" && f();
x++ < 2 && typeof f == "function" && f();
}
expect: {
var f = function() {
console.log(x);
};
var x = 0;
x++ < 2 && f();
x++ < 2 && f();
x++ < 2 && f();
}
expect_stdout: [
"1",
"2",
]
}

View File

@@ -15,43 +15,3 @@ unicode_parse_variables: {
var l = 3;
}
}
issue_2242_1: {
beautify = {
ascii_only: false,
}
input: {
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
}
expect_exact: 'console.log("\\ud83d","\\ude00","\ud83d\ude00","\\ud83d@\\ude00");'
}
issue_2242_2: {
beautify = {
ascii_only: true,
}
input: {
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
}
expect_exact: 'console.log("\\ud83d","\\ude00","\\ud83d\\ude00","\\ud83d@\\ude00");'
}
issue_2242_3: {
options = {
evaluate: false,
}
input: {
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
}
expect_exact: 'console.log("\\ud83d"+"\\ude00","\\ud83d"+"@"+"\\ude00");'
}
issue_2242_4: {
options = {
evaluate: true,
}
input: {
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
}
expect_exact: 'console.log("\ud83d\ude00","\\ud83d@\\ude00");'
}

View File

@@ -1,14 +0,0 @@
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["reserve_quoted_keys"] = reserve_quoted_keys;
exports["string_template"] = string_template;
exports["tokenizer"] = tokenizer;
exports["is_identifier"] = is_identifier;

View File

@@ -1,31 +0,0 @@
var fs = require("fs");
var path = require("path");
try {
fs.mkdirSync("./tmp");
} catch (e) {
if (e.code != "EEXIST") throw e;
}
function local(url) {
return path.join("./tmp", encodeURIComponent(url));
}
function read(url) {
return fs.createReadStream(local(url));
}
module.exports = function(url, callback) {
var result = read(url);
result.on("error", function(e) {
if (e.code != "ENOENT") return callback(e);
require(url.slice(0, url.indexOf(":"))).get(url, function(res) {
if (res.statusCode !== 200) return callback(res);
res.pipe(fs.createWriteStream(local(url)).on("close", function() {
callback(null, read(url));
}));
});
}).on("open", function() {
callback(null, result);
});
};

View File

@@ -1,14 +0,0 @@
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;
}

View File

@@ -1,4 +0,0 @@
var a, b = [1, 2];
for (1, 2, a in b) {
console.log(a, b[a]);
}

View File

@@ -1,4 +0,0 @@
var c = [1, 2];
for (var a, b in c) {
console.log(a, c[a]);
}

View File

@@ -1,6 +0,0 @@
function f(arguments) {
}
function g(arguments) {
"use strict";
}

View File

@@ -1,6 +0,0 @@
function arguments() {
}
function eval() {
"use strict";
}

View File

@@ -1,6 +0,0 @@
!function eval() {
}();
!function arguments() {
"use strict";
}();

View File

@@ -1,8 +0,0 @@
function f() {
try {} catch (eval) {}
}
function g() {
"use strict";
try {} catch (eval) {}
}

View File

@@ -1,8 +0,0 @@
function f() {
var eval;
}
function g() {
"use strict";
var eval;
}

View File

@@ -1 +0,0 @@
console.log(x);

View File

@@ -1 +0,0 @@
{"version": 3,"sources": ["index.js"],"mappings": ";"}

View File

@@ -1,10 +0,0 @@
function foo() {
return function() {
console.log("PASS");
};
}
(function() {
var f = foo();
f();
})();

View File

@@ -1,5 +0,0 @@
function test(callback) {
'aaaaaaaaaaaaaaaa';
callback(err, data);
callback(err, data);
}

View File

@@ -1,5 +0,0 @@
function test(a){
"aaaaaaaaaaaaaaaa"
;a(err,data),a(err,data)
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7QUFDVjtDQUNBQSxFQUFTQyxJQUFLQyxNQUNkRixFQUFTQyxJQUFLQyJ9

View File

@@ -1,2 +1,2 @@
new function(){console.log(3)};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxHQUFyQyxZQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19

View File

@@ -3,7 +3,7 @@
"use strict";
var site = "http://browserbench.org/JetStream";
var site = "http://browserbench.org/JetStream/";
if (typeof phantom == "undefined") {
// workaround for tty output truncation upon process.exit()
[process.stdout, process.stderr].forEach(function(stream){
@@ -11,38 +11,25 @@ if (typeof phantom == "undefined") {
stream._handle.setBlocking(true);
});
var args = process.argv.slice(2);
var debug = args.indexOf("--debug");
if (debug >= 0) {
args.splice(debug, 1);
debug = true;
} else {
debug = false;
}
if (!args.length) {
args.push("-mcb", "beautify=false,webkit");
args.push("-mc", "warnings=false");
}
args.push("--timings");
args.push("--stats");
var child_process = require("child_process");
var fetch = require("./fetch");
try {
require("phantomjs-prebuilt");
} catch(e) {
child_process.execSync("npm install phantomjs-prebuilt@2.1.14");
}
var http = require("http");
var server = http.createServer(function(request, response) {
request.resume();
var url = site + request.url;
fetch(url, function(err, res) {
if (err) throw err;
response.writeHead(200, {
"Content-Type": {
css: "text/css",
js: "application/javascript",
png: "image/png"
}[url.slice(url.lastIndexOf(".") + 1)] || "text/html; charset=utf-8"
});
if (/\.js$/.test(url)) {
var url = decodeURIComponent(request.url.slice(1));
var stderr = "";
var uglifyjs = child_process.fork("bin/uglifyjs", args, {
silent: true
}).on("exit", function(code) {
console.log("uglifyjs", url.slice(site.length + 1), args.join(" "));
console.log("uglifyjs", url.indexOf(site) == 0 ? url.slice(site.length) : url, args.join(" "));
console.log(stderr);
if (code) throw new Error("uglifyjs failed with code " + code);
});
@@ -50,31 +37,20 @@ if (typeof phantom == "undefined") {
stderr += data;
}).setEncoding("utf8");
uglifyjs.stdout.pipe(response);
http.get(url, function(res) {
res.pipe(uglifyjs.stdin);
} else {
res.pipe(response);
}
});
}).listen();
server.on("listening", function() {
var port = server.address().port;
if (debug) {
console.log("http://localhost:" + port + "/");
} else {
child_process.exec("npm install phantomjs-prebuilt@2.1.14 --no-save", function(error) {
if (error) throw error;
var program = require("phantomjs-prebuilt").exec(process.argv[1], port);
}).listen().on("listening", function() {
var phantomjs = require("phantomjs-prebuilt");
var program = phantomjs.exec(process.argv[1], server.address().port);
program.stdout.pipe(process.stdout);
program.stderr.pipe(process.stderr);
program.on("exit", function(code) {
server.close();
if (code) throw new Error("JetStream failed!");
console.log("JetStream completed successfully.");
process.exit(0);
});
});
}
});
server.timeout = 0;
} else {
var page = require("webpage").create();
@@ -87,6 +63,10 @@ if (typeof phantom == "undefined") {
phantom.exit(1);
};
var url = "http://localhost:" + require("system").args[1] + "/";
page.onResourceRequested = function(requestData, networkRequest) {
if (/\.js$/.test(requestData.url))
networkRequest.changeUrl(url + encodeURIComponent(requestData.url));
}
page.onConsoleMessage = function(msg) {
if (/Error:/i.test(msg)) {
console.error(msg);
@@ -97,8 +77,8 @@ if (typeof phantom == "undefined") {
phantom.exit();
}
};
page.open(url, function(status) {
if (status != "success") phantom.exit(1);
page.open(site, function(status) {
if (status != "success") phantomjs.exit(1);
page.evaluate(function() {
JetStream.switchToQuick();
JetStream.start();

View File

@@ -1,4 +1,4 @@
var UglifyJS = require("../node");
var UglifyJS = require('../../');
var assert = require("assert");
describe("Accessor tokens", function() {

View File

@@ -1,4 +1,4 @@
var UglifyJS = require("../node");
var UglifyJS = require('../../');
var assert = require("assert");
describe("arguments", function() {

View File

@@ -2,14 +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) {
this.timeout(30000);
this.timeout(15000);
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
@@ -19,14 +15,12 @@ describe("bin/uglifyjs", function () {
eval(stdout);
assert.strictEqual(typeof WrappedUglifyJS, 'object');
var result = WrappedUglifyJS.minify("foo([true,,2+3]);");
assert.strictEqual(result.error, undefined);
assert.strictEqual(result.code, "foo([!0,,5]);");
assert.strictEqual(true, WrappedUglifyJS.parse('foo;') instanceof WrappedUglifyJS.AST_Node);
done();
});
});
it("Should be able to filter comments correctly with `--comments all`", function (done) {
it("Should be able to filter comments correctly with `--comment all`", function (done) {
var command = uglifyjscmd + ' test/input/comments/filter.js --comments all';
exec(command, function (err, stdout) {
@@ -56,18 +50,18 @@ describe("bin/uglifyjs", function () {
done();
});
});
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";
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';
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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==\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 url=inline", function (done) {
it("should not append source map to output when not using --source-map-inline", function (done) {
var command = uglifyjscmd + ' test/input/issue-1323/sample.js';
exec(command, function (err, stdout) {
@@ -77,23 +71,6 @@ describe("bin/uglifyjs", function () {
done();
});
});
it("should not consider source map file content as source map file name (issue #2082)", function (done) {
var command = [
uglifyjscmd,
"test/input/issue-2082/sample.js",
"--source-map", "content=test/input/issue-2082/sample.js.map",
"--source-map", "url=inline",
].join(" ");
exec(command, function (err, stdout, stderr) {
if (err) throw err;
var stderrLines = stderr.split('\n');
assert.strictEqual(stderrLines[0], 'INFO: Using input source map: test/input/issue-2082/sample.js.map');
assert.notStrictEqual(stderrLines[1], 'INFO: Using input source map: {"version": 3,"sources": ["index.js"],"mappings": ";"}');
done();
});
});
it("Should work with --keep-fnames (mangle only)", function (done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
@@ -160,7 +137,7 @@ describe("bin/uglifyjs", function () {
exec(command, function (err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, read("test/input/issue-1482/default.js"));
assert.strictEqual(stdout, readFileSync("test/input/issue-1482/default.js", "utf8"));
done();
});
});
@@ -170,59 +147,55 @@ describe("bin/uglifyjs", function () {
exec(command, function (err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, read("test/input/issue-1482/bracketize.js"));
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 --source-map content=inline,url=inline";
var command = uglifyjscmd + ' test/input/issue-520/input.js -mc toplevel --in-source-map inline --source-map-inline';
exec(command, function (err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, read("test/input/issue-520/output.js"));
assert.strictEqual(stdout, readFileSync("test/input/issue-520/output.js", "utf8"));
done();
});
});
it("Should warn for missing inline source map", function(done) {
var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map content=inline,url=inline";
var command = uglifyjscmd + ' test/input/issue-1323/sample.js --in-source-map inline';
exec(command, function (err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, [
"var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
"",
].join("\n"));
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n");
assert.strictEqual(stderr, "WARN: inline source map not found\n");
done();
});
});
it("Should fail with multiple input and inline source map", function(done) {
var command = uglifyjscmd + " test/input/issue-520/input.js test/input/issue-520/output.js --source-map content=inline,url=inline";
var command = uglifyjscmd + ' test/input/issue-520/input.js test/input/issue-520/output.js --in-source-map inline --source-map-inline';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stderr.split(/\n/)[0], "ERROR: inline source map only works with singular input");
assert.strictEqual(stderr, "ERROR: Inline source map only works with singular input\n");
done();
});
});
it("Should fail with acorn and inline source map", function(done) {
var command = uglifyjscmd + " test/input/issue-520/input.js --source-map content=inline,url=inline -p acorn";
var command = uglifyjscmd + ' test/input/issue-520/input.js --in-source-map inline --source-map-inline --acorn';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stderr, "ERROR: inline source map only works with built-in parser\n");
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 --source-map content=inline,url=inline -p spidermonkey";
var command = uglifyjscmd + ' test/input/issue-520/input.js --in-source-map inline --source-map-inline --spidermonkey';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stderr, "ERROR: inline source map only works with built-in parser\n");
assert.strictEqual(stderr, "ERROR: Inline source map only works with built-in parser\n");
done();
});
});
@@ -235,7 +208,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], "ERROR: Unexpected token punc «{», expected punc «,»");
assert.strictEqual(lines[3], "SyntaxError: Unexpected token punc «{», expected punc «,»");
done();
});
});
@@ -248,7 +221,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], "ERROR: Invalid syntax: 0abc");
assert.strictEqual(lines[3], "SyntaxError: Invalid syntax: 0abc");
done();
});
});
@@ -261,7 +234,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], "ERROR: Unexpected token: eof (undefined)");
assert.strictEqual(lines[3], "SyntaxError: Unexpected token: eof (undefined)");
done();
});
});
@@ -274,7 +247,17 @@ 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], "ERROR: Unexpected token: eof (undefined)");
assert.strictEqual(lines[3], "SyntaxError: 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();
});
});
@@ -288,7 +271,7 @@ describe("bin/uglifyjs", function () {
"Parse error at test/input/invalid/assign_1.js:1,18",
"console.log(1 || 5--);",
" ^",
"ERROR: Invalid use of -- operator"
"SyntaxError: Invalid use of -- operator"
].join("\n"));
done();
});
@@ -303,7 +286,7 @@ describe("bin/uglifyjs", function () {
"Parse error at test/input/invalid/assign_2.js:1,32",
"console.log(2 || (Math.random() /= 2));",
" ^",
"ERROR: Invalid assignment"
"SyntaxError: Invalid assignment"
].join("\n"));
done();
});
@@ -318,7 +301,7 @@ describe("bin/uglifyjs", function () {
"Parse error at test/input/invalid/assign_3.js:1,17",
"console.log(3 || ++this);",
" ^",
"ERROR: Invalid use of ++ operator"
"SyntaxError: Invalid use of ++ operator"
].join("\n"));
done();
});
@@ -333,7 +316,7 @@ describe("bin/uglifyjs", function () {
"Parse error at test/input/invalid/assign_4.js:1,0",
"++null",
"^",
"ERROR: Invalid use of ++ operator"
"SyntaxError: Invalid use of ++ operator"
].join("\n"));
done();
});
@@ -348,7 +331,7 @@ describe("bin/uglifyjs", function () {
"Parse error at test/input/invalid/dot_1.js:1,2",
"a.=",
" ^",
"ERROR: Unexpected token: operator (=)"
"SyntaxError: Unexpected token: operator (=)"
].join("\n"));
done();
});
@@ -363,7 +346,7 @@ describe("bin/uglifyjs", function () {
"Parse error at test/input/invalid/dot_2.js:1,0",
"%.a;",
"^",
"ERROR: Unexpected token: operator (%)"
"SyntaxError: Unexpected token: operator (%)"
].join("\n"));
done();
});
@@ -378,7 +361,7 @@ describe("bin/uglifyjs", function () {
"Parse error at test/input/invalid/dot_3.js:1,2",
"a./();",
" ^",
"ERROR: Unexpected token: operator (/)"
"SyntaxError: Unexpected token: operator (/)"
].join("\n"));
done();
});
@@ -393,97 +376,7 @@ describe("bin/uglifyjs", function () {
"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"
"SyntaxError: Unexpected token: operator (%)"
].join("\n"));
done();
});
@@ -498,7 +391,7 @@ describe("bin/uglifyjs", function () {
"Parse error at test/input/invalid/else.js:1,7",
"if (0) else 1;",
" ^",
"ERROR: Unexpected token: keyword (else)"
"SyntaxError: Unexpected token: keyword (else)"
].join("\n"));
done();
});
@@ -513,141 +406,9 @@ describe("bin/uglifyjs", function () {
"Parse error at test/input/invalid/return.js:1,0",
"return 42;",
"^",
"ERROR: 'return' outside of function"
"SyntaxError: 'return' outside of function"
].join("\n"));
done();
});
});
it("Should throw syntax error (for-in init)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/for-in_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/for-in_1.js:2,5",
"for (1, 2, a in b) {",
" ^",
"ERROR: Invalid left-hand side in for..in loop"
].join("\n"));
done();
});
});
it("Should throw syntax error (for-in var)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/for-in_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/for-in_2.js:2,5",
"for (var a, b in c) {",
" ^",
"ERROR: Only one variable declaration allowed in for..in loop"
].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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiYUFBQSxJQUFJQSxJQUFNLFNBQU5BLElBQU1DLEdBQUEsTUFBSyxPQUFTQSxHQUN4QkMsUUFBUUMsSUFBSUgsSUFBSSJ9",
""
].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 include function calls in source map", function(done) {
var command = [
uglifyjscmd,
"test/input/issue-2310/input.js",
"-c",
"--source-map", "url=inline",
].join(" ");
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, [
'function foo(){return function(){console.log("PASS")}}foo()();',
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIiwiZiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsTUFDTCxPQUFPLFdBQ0hDLFFBQVFDLElBQUksU0FLUkYsS0FDUkcifQ==",
""
].join("\n"));
done();
});
});
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();
});
});
it("Should print supported options on invalid option syntax", function(done) {
var command = uglifyjscmd + " test/input/comments/filter.js -b ascii-only";
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `ascii-only` is not a supported option/.test(stderr), stderr);
done();
});
});
it("Should work with --mangle reserved=[]", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=[callback]";
exec(command, function (err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, 'function test(callback){"aaaaaaaaaaaaaaaa";callback(err,data);callback(err,data)}\n');
done();
});
});
it("Should work with --mangle reserved=false", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=false";
exec(command, function (err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, 'function test(a){"aaaaaaaaaaaaaaaa";a(err,data);a(err,data)}\n');
done();
});
});
it("Should fail with --mangle-props reserved=[in]", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js --mangle-props reserved=[in]";
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `reserved=\[in]` is not a supported option/.test(stderr), stderr);
done();
});
});
it("Should fail with --define a-b", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b";
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr, "Error parsing arguments for 'define': a-b\n");
done();
});
});
});

View File

@@ -1,4 +1,4 @@
var UglifyJS = require("../node");
var UglifyJS = require('../../');
var assert = require("assert");
describe("comment filters", function() {
@@ -75,6 +75,7 @@ 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;");
@@ -82,6 +83,7 @@ describe("comment filters", function() {
it("Should handle preamble without shebang correctly", function() {
var code = UglifyJS.minify("var x = 10;", {
fromString: true,
output: { preamble: "/* Build */" }
}).code;
assert.strictEqual(code, "/* Build */\nvar x=10;");

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../node");
var uglify = require("../../");
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]);
uglify.parse(tests[i], {fromString: true})
}, 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]);
uglify.parse(tests[i], {fromString: true})
}, fail, tests[i]);
}
});

View File

@@ -6,7 +6,9 @@ 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}');
@@ -14,9 +16,12 @@ 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}');
});
});

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../node");
var uglify = require("../../");
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\');',
{output: {beautify: true, quote_style: 3}, compress: false}
{fromString: true, 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], {compress: false, mangle: false}).code,
uglify.minify(tests[i][0], {fromString: true, quote_style: 3, 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";',
{output: {semicolons: false}, compress: false}
{fromString: true, 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], {output:{quote_style: tests[i][1]}, compress: false}).code,
uglify.minify(tests[i][0], {fromString: true, output:{quote_style: tests[i][1]}, compress: false}).code,
tests[i][2],
tests[i][0] + " using mode " + tests[i][1]
);
@@ -372,7 +372,7 @@ describe("Directives", function() {
for (var i = 0; i < tests.length; i++) {
assert.strictEqual(
uglify.minify(tests[i][0]).code,
uglify.minify(tests[i][0], {fromString: true}).code,
tests[i][1],
tests[i][0]
);

View File

@@ -1,4 +1,4 @@
var UglifyJS = require("../node");
var UglifyJS = require('../../');
var assert = require("assert");
describe("Getters and setters", function() {

View File

@@ -1,80 +1,58 @@
var Uglify = require('../../');
var assert = require("assert");
var exec = require("child_process").exec;
var path = require("path");
var readFileSync = require("fs").readFileSync;
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();
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("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("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 }
});
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("bin/uglifyjs with multiple input file globs.", function(done) {
var command = uglifyjscmd + ' "test/input/issue-1242/???.es5" "test/input/issue-1242/*.js" -mc toplevel,passes=2';
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, 'var print=console.log.bind(console);print("qux",9,6),print("Foo:",22);\n');
done();
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('"?" 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("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 special characters in glob string", function() {
var result = Uglify.minify("test/input/issue-1632/^{*}[???](*)+$.??");
assert.strictEqual(result.code, "console.log(x);");
});
});
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) {
it("should handle array of glob strings - matching and otherwise", function() {
var dir = "test/input/issue-1242";
var command = uglifyjscmd + ' "' + [
var matches = Uglify.simple_glob([
path.join(dir, "b*.es5"),
path.join(dir, "z*.es5"),
path.join(dir, "*.js")
].join('" "') + '"';
exec(command, function(err, stdout, stderr) {
assert.ok(err);
assert.ok(/^ERROR: ENOENT.*?z\*\.es5/.test(stderr));
done();
});
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"));
});
});

Some files were not shown because too many files have changed in this diff Show More