Compare commits

...

59 Commits

Author SHA1 Message Date
Alex Lam S.L
7ccdf3337b v3.5.7 2019-04-24 14:05:07 +08:00
Alex Lam S.L
dafed54764 fix corner case in reduce_vars (#3378)
fixes #3377
2019-04-24 14:01:01 +08:00
Alex Lam S.L
a84beafd1b fix corner case in assignments (#3376)
fixes #3375
2019-04-24 02:50:15 +08:00
Alex Lam S.L
f01cc1e413 unwind IIFE class patterns (#3373)
fixes #2332
2019-04-21 09:49:07 +08:00
Alex Lam S.L
338dd144b8 v3.5.6 2019-04-21 07:19:29 +08:00
Alex Lam S.L
c719552317 fix corner cases in functions (#3372)
fixes #3371
2019-04-21 02:16:05 +08:00
Alex Lam S.L
855964a87a enhance unsafe evaluate (#3370) 2019-04-20 19:42:41 +08:00
Alex Lam S.L
a438e2fca9 update domprops (#3369)
fixes #2343
fixes #3037
2019-04-20 07:16:14 +08:00
Alex Lam S.L
00833e893a enhance functions (#3368) 2019-04-19 19:01:47 +08:00
Alex Lam S.L
f1a77e4fc0 v3.5.5 2019-04-19 15:22:46 +08:00
Alex Lam S.L
b55a2fd531 fix corner case in functions (#3367)
fixes #3366
2019-04-19 02:55:43 +08:00
Alex Lam S.L
e8a2c0b5bf fix corner case in functions (#3365)
fixes #3364
2019-04-18 17:03:52 +08:00
Alex Lam S.L
21cd7e3f57 reduce test exports (#3361) 2019-04-17 16:19:08 +08:00
Alex Lam S.L
5172ba5f2a introduce functions (#3360)
`var f = function() {};` => `function f() {}`
2019-04-15 22:23:11 +08:00
Alex Lam S.L
a57b069409 v3.5.4 2019-04-10 02:40:42 +08:00
Alex Lam S.L
4454656c3b update dependencies (#3358)
- commander@2.20.0
- semver@6.0.0
2019-04-10 02:39:56 +08:00
Alex Lam S.L
fa43768ce0 v3.5.3 2019-04-01 18:12:03 +08:00
Alex Lam S.L
a74e600fa0 mangle shadowed lambda under ie8 correctly (#3356)
fixes #3355
2019-04-01 15:22:00 +08:00
Ruben Bridgewater
4b21526310 Fix test expectation (#3357)
The test expects a specific precision value that is not met on all V8 versions anymore due to a recent consolidation of different algorithms across the V8 code base.

This makes sure the preceision is tested against one digit less to keep the test working on all V8 versions.

Refs: 98453126c1
Refs: https://github.com/nodejs/node/issues/25060#issuecomment-477953457
2019-03-30 02:08:27 +08:00
Alex Lam S.L
a7a7b1daed v3.5.2 2019-03-23 14:25:14 +08:00
Alex Lam S.L
7436977aa5 fix infinite loop triggered by #3347 (#3354)
fixes #3353
2019-03-23 14:21:54 +08:00
Alex Lam S.L
e3c565b46f v3.5.1 2019-03-21 13:54:14 +08:00
Alex Lam S.L
54b0b49b68 enhance inline (#3352) 2019-03-21 02:58:33 +08:00
Alex Lam S.L
65648d84a5 enhance collapse_vars (#3351) 2019-03-20 23:31:21 +08:00
Alex Lam S.L
fd788590f6 v3.5.0 2019-03-20 18:43:54 +08:00
Alex Lam S.L
143f9054da fix corner case in sequences (#3350) 2019-03-20 14:54:26 +08:00
Alex Lam S.L
f2286c33f1 enhance unsafe for Array (#3349) 2019-03-20 06:37:51 +08:00
Alex Lam S.L
b9615f7a62 improve compress performance (#3348)
fixes #3174
2019-03-20 02:53:04 +08:00
Alex Lam S.L
c520e99eda enhance comparisons (#3347) 2019-03-19 01:34:25 +08:00
Alex Lam S.L
615ae37ca3 introduce assignments (#3345) 2019-03-18 21:28:41 +08:00
Alex Lam S.L
7aa7f21872 fix corner case in evaluate (#3344) 2019-03-18 21:24:42 +08:00
Alex Lam S.L
4430a436eb fix corner case in inline (#3343) 2019-03-17 05:31:40 +08:00
Alex Lam S.L
9707ccdc9f v3.4.10 2019-03-16 00:16:21 +08:00
Alex Lam S.L
cb8f3a2a31 add Node.js 10 to CI tests (#3342) 2019-03-15 16:45:12 +08:00
Alex Lam S.L
8b3259e0c2 fix corner case in reduce_vars (#3341) 2019-03-15 16:06:47 +08:00
Alex Lam S.L
b66f47b8dd update dependencies
- acorn@6.1.1
- commander@2.19.0
- semver@5.6.0
2019-03-15 14:49:48 +08:00
Alex Lam S.L
8d2e6f333e fix function inlining after reduce_vars (#3340)
fixes #3297
2019-03-15 05:45:46 +08:00
Alex Lam S.L
b3ef5e514d enhance evaluate (#3339)
fixes #3299
2019-03-15 02:48:23 +08:00
Alex Lam S.L
627f5fb41e fix corner case with nameCache (#3338)
fixes #3301
2019-03-15 01:15:50 +08:00
Alex Lam S.L
d90777b724 parse mangle.properties.regex in --config-file properly (#3337)
fixes #3315
2019-03-15 00:20:20 +08:00
Alex Lam S.L
e49297e5eb improve usability of pure_funcs (#3336)
fixes #3325
2019-03-14 21:36:45 +08:00
Alex Lam S.L
ebd82b3fb6 fix corner case in collapse_vars (#3334)
fixes #3274
2019-03-14 16:05:56 +08:00
Alex Lam S.L
d074aa6e27 fix corner case in collapse_vars (#3333)
fixes #3247
fixes #3305
fixes #3314
fixes #3327
2019-03-13 23:48:52 +08:00
Alex Lam S.L
b052f62710 fix corner case in reduce_vars (#3332)
fixes #3267
2019-03-13 21:56:38 +08:00
Alex Lam S.L
d4ac84b255 fix corner case in arguments & reduce_vars (#3331)
fixes #3282
2019-03-13 08:46:03 +08:00
Alex Lam S.L
e250396d7e fix corner case in arguments (#3330)
Track modifications to `arguments[i]` under Strict Mode.

fixes #3273
2019-03-13 06:59:53 +08:00
Seul-gi Choi(Chase)
c6fa39b482 Update README.md (#3311)
fix anchor for mangle-options
2019-03-13 05:31:04 +08:00
silverwind
9aae4f2424 make tests compatible with Node.js 12 (#3304)
In Node.js 12, the formatting of console arguments will change slightly.
Previously, a string other than the first argument was formatted using
single quotes if the first argument was non-string. Now, quotes are
never added regardless of position of a string argument.

To make test compatible in all Node.js versions, I work around by
ensuring the first argument to console.log is a string which prevents
the quotes from being added on older versions of Node.js.

Ref: https://github.com/nodejs/node/pull/23162
2019-03-13 04:55:04 +08:00
Alex Lam S.L
008c236137 fix corner case in conditionals (#3329)
fixes #3245
fixes #3257
fixes #3260
fixes #3269
fixes #3271
fixes #3278
fixes #3309
fixes #3319
fixes #3321
2019-03-13 04:28:21 +08:00
Ed S
b1c0664066 Fix typo in warning (#3324)
protoype -> prototype
2019-03-13 02:15:54 +08:00
Alex Lam S.L
ea999b0e92 v3.4.9 2018-08-31 04:28:21 +00:00
Alex Lam S.L
ce7e220de4 fix corner case in conditionals (#3244) 2018-08-30 15:59:05 +08:00
Alex Lam S.L
2bdaca10ae enhance conditionals (#3243) 2018-08-30 01:06:34 +08:00
Alex Lam S.L
aa0029204e fix corner case in reduce_vars (#3241)
fixes #3240
2018-08-29 22:14:25 +08:00
Alex Lam S.L
f352bcec3a fix corner case in collapse_vars (#3239)
fixes #3238
2018-08-29 11:34:34 +08:00
Alex Lam S.L
08514030f4 v3.4.8 2018-08-23 15:27:34 +08:00
Alex Lam S.L
694ca5d045 fix corner case in unused (#3234)
fixes #3233
2018-08-23 06:03:39 +08:00
Alex Lam S.L
57fb58b263 enhance if_return (#3232) 2018-08-21 18:34:16 +08:00
alexlamsl
18c1c9b38a update dependencies
- commander@2.17.1
2018-08-14 17:06:09 +08:00
39 changed files with 5089 additions and 468 deletions

View File

@@ -19,6 +19,7 @@ env:
- NODEJS_VER=node/4
- NODEJS_VER=node/6
- NODEJS_VER=node/8
- NODEJS_VER=node/10
- NODEJS_VER=node/latest
before_install:
- git clone --branch v1.4.2 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs

View File

@@ -605,6 +605,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `arguments` (default: `true`) -- replace `arguments[index]` with function
parameter name whenever possible.
- `assignments` (default: `true`) -- apply optimizations to assignment expressions.
- `booleans` (default: `true`) -- various optimizations for boolean context,
for example `!!a ? b : c → a ? b : c`
@@ -634,6 +636,9 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `expression` (default: `false`) -- Pass `true` to preserve completion values
from terminal statements without `return`, e.g. in bookmarklets.
- `functions` (default: `true`) -- convert declarations from `var`to `function`
whenever possible.
- `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation)
- `hoist_funs` (default: `false`) -- hoist function declarations
@@ -664,7 +669,7 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `keep_fnames` (default: `false`) -- Pass `true` to prevent the
compressor from discarding function names. Useful for code relying on
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle-options).
- `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from
being compressed into `1/0`, which may cause performance issues on Chrome.

View File

@@ -6,6 +6,7 @@ environment:
- NODEJS_VER: node/4
- NODEJS_VER: node/6
- NODEJS_VER: node/8
- NODEJS_VER: node/10
- NODEJS_VER: node/latest
install:
- git clone --branch v1.4.2 --depth 1 https://github.com/jasongin/nvs.git %LOCALAPPDATA%\nvs

View File

@@ -56,6 +56,11 @@ program.option("--wrap <name>", "Embed everything as a function with “exports
program.arguments("[files...]").parseArgv(process.argv);
if (program.configFile) {
options = JSON.parse(read_file(program.configFile));
if (options.mangle && options.mangle.properties && options.mangle.properties.regex) {
options.mangle.properties.regex = UglifyJS.parse(options.mangle.properties.regex, {
expression: true
}).getValue();
}
}
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
fatal("ERROR: cannot write source map to STDOUT");
@@ -337,17 +342,9 @@ 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) {
UglifyJS.parse(value, {
expression: true
}).walk(new UglifyJS.TreeWalker(function(node) {
if (node instanceof UglifyJS.AST_Assign) {
var name = node.left.print_to_string();
var value = node.right;

View File

@@ -773,7 +773,7 @@ var AST_Label = DEFNODE("Label", "references", {
}
}, AST_Symbol);
var AST_SymbolRef = DEFNODE("SymbolRef", null, {
var AST_SymbolRef = DEFNODE("SymbolRef", "fixed", {
$documentation: "Reference to some symbol (not definition/declaration)",
}, AST_Symbol);

File diff suppressed because it is too large Load Diff

View File

@@ -123,7 +123,7 @@ function OutputStream(options) {
});
} : function(str) {
var s = "";
for (var i = 0, len = str.length; i < len; i++) {
for (var i = 0; i < str.length; i++) {
if (is_surrogate_pair_head(str[i]) && !is_surrogate_pair_tail(str[i + 1])
|| is_surrogate_pair_tail(str[i]) && !is_surrogate_pair_head(str[i - 1])) {
s += "\\u" + str.charCodeAt(i).toString(16);

View File

@@ -164,10 +164,6 @@ function is_unicode_connector_punctuation(ch) {
return UNICODE.connector_punctuation.test(ch);
}
function is_identifier(name) {
return !RESERVED_WORDS[name] && /^[a-z_$][a-z0-9_$]*$/i.test(name);
}
function is_identifier_start(code) {
return code == 36 || code == 95 || is_letter(code);
}
@@ -272,10 +268,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
function find_eol() {
var text = S.text;
for (var i = S.pos, n = S.text.length; i < n; ++i) {
var ch = text[i];
if (NEWLINE_CHARS[ch])
return i;
for (var i = S.pos; i < S.text.length; ++i) {
if (NEWLINE_CHARS[text[i]]) return i;
}
return -1;
}
@@ -758,17 +752,21 @@ function parse($TEXT, options) {
croak(msg, token.line, token.col);
}
function token_to_string(type, value) {
return type + (value === undefined ? "" : " «" + value + "»");
}
function unexpected(token) {
if (token == null)
token = S.token;
token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
token_error(token, "Unexpected token: " + token_to_string(token.type, token.value));
}
function expect_token(type, val) {
if (is(type, val)) {
return next();
}
token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
token_error(S.token, "Unexpected token: " + token_to_string(S.token.type, S.token.value) + ", expected: " + token_to_string(type, val));
}
function expect(punc) {
@@ -788,7 +786,7 @@ function parse($TEXT, options) {
function semicolon(optional) {
if (is("punc", ";")) next();
else if (!optional && !can_insert_semicolon()) unexpected();
else if (!optional && !can_insert_semicolon()) expect_token("punc", ";");
}
function parenthesised() {
@@ -1069,7 +1067,7 @@ function parse($TEXT, options) {
var in_statement = ctor === AST_Defun;
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
if (in_statement && !name)
unexpected();
expect_token("name");
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
unexpected(prev());
expect("(");
@@ -1119,7 +1117,7 @@ function parse($TEXT, options) {
expect("{");
var a = [];
while (!is("punc", "}")) {
if (is("eof")) unexpected();
if (is("eof")) expect_token("punc", "}");
a.push(statement(strict_defun));
}
next();
@@ -1130,7 +1128,7 @@ function parse($TEXT, options) {
expect("{");
var a = [], cur = null, branch = null, tmp;
while (!is("punc", "}")) {
if (is("eof")) unexpected();
if (is("eof")) expect_token("punc", "}");
if (is("keyword", "case")) {
if (branch) branch.end = prev();
cur = [];
@@ -1141,8 +1139,7 @@ function parse($TEXT, options) {
});
a.push(branch);
expect(":");
}
else if (is("keyword", "default")) {
} else if (is("keyword", "default")) {
if (branch) branch.end = prev();
cur = [];
branch = new AST_Default({
@@ -1150,8 +1147,7 @@ function parse($TEXT, options) {
body : cur
});
a.push(branch);
}
else {
} else {
if (!cur) unexpected();
cur.push(statement());
}
@@ -1420,10 +1416,10 @@ function parse($TEXT, options) {
}
function as_name() {
var tmp = S.token;
if (tmp.type != "name") unexpected();
if (!is("name")) expect_token("name");
var name = S.token.value;
next();
return tmp.value;
return name;
}
function _make_symbol(type) {
@@ -1625,6 +1621,7 @@ function parse($TEXT, options) {
}
if (options.expression) {
handle_regexp();
return expression(true);
}

View File

@@ -61,8 +61,6 @@ SymbolDef.next_id = 1;
SymbolDef.prototype = {
unmangleable: function(options) {
if (!options) options = {};
return this.global && !options.toplevel
|| this.undeclared
|| !options.eval && this.scope.pinned()
@@ -198,24 +196,20 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
}
if (node instanceof AST_SymbolLambda) {
var def = node.thedef;
if (def.orig.length == 1) {
redefine(node, node.scope.parent_scope);
node.thedef.init = def.init;
}
redefine(node, node.scope.parent_scope);
node.thedef.init = def.init;
return true;
}
}));
function redefine(node, scope) {
var name = node.name;
var refs = node.thedef.references;
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
refs.forEach(function(ref) {
ref.thedef = def;
ref.reference(options);
var old_def = node.thedef;
var new_def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
old_def.orig.concat(old_def.references).forEach(function(node) {
node.thedef = new_def;
node.reference(options);
});
node.thedef = def;
node.reference(options);
}
});
@@ -300,7 +294,7 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
AST_Lambda.DEFMETHOD("resolve", return_this);
AST_Scope.DEFMETHOD("resolve", function() {
return this.parent_scope;
return this.parent_scope.resolve();
});
AST_Toplevel.DEFMETHOD("resolve", return_this);
@@ -309,8 +303,12 @@ function names_in_use(scope, options) {
if (!names) {
scope.names_in_use = names = Object.create(scope.mangled_names || null);
scope.cname_holes = [];
var cache = options.cache && options.cache.props;
scope.enclosed.forEach(function(def) {
if (def.unmangleable(options)) names[def.name] = true;
if (def.global && cache && cache.has(def.name)) {
names[cache.get(def.name)] = true;
}
});
}
return names;
@@ -333,7 +331,7 @@ function next_mangled_name(scope, options, def) {
} while (scope = scope.parent_scope);
});
var name;
for (var i = 0, len = holes.length; i < len; i++) {
for (var i = 0; i < holes.length; i++) {
name = base54(holes[i]);
if (names[name]) continue;
holes.splice(i, 1);
@@ -342,7 +340,7 @@ function next_mangled_name(scope, options, def) {
}
while (true) {
name = base54(++scope.cname);
if (in_use[name] || !is_identifier(name) || options.reserved.has[name]) continue;
if (in_use[name] || RESERVED_WORDS[name] || options.reserved.has[name]) continue;
if (!names[name]) break;
holes.push(scope.cname);
}
@@ -422,7 +420,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
var name;
do {
name = base54(++lname);
} while (!is_identifier(name));
} while (RESERVED_WORDS[name]);
node.mangled_name = name;
return true;
}
@@ -493,7 +491,7 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
var name;
do {
name = base54(cname++);
} while (avoid[name] || !is_identifier(name));
} while (avoid[name] || RESERVED_WORDS[name]);
return name;
}
@@ -555,7 +553,7 @@ var base54 = (function() {
var freq = Object.create(null);
function init(chars) {
var array = [];
for (var i = 0, len = chars.length; i < len; i++) {
for (var i = 0; i < chars.length; i++) {
var ch = chars[i];
array.push(ch);
freq[ch] = -1e-2 * i;

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.4.7",
"version": "3.5.7",
"engines": {
"node": ">=0.8.0"
},
@@ -23,12 +23,12 @@
"LICENSE"
],
"dependencies": {
"commander": "~2.16.0",
"commander": "~2.20.0",
"source-map": "~0.6.1"
},
"devDependencies": {
"acorn": "~5.7.1",
"semver": "~5.5.0"
"acorn": "~6.1.1",
"semver": "~6.0.0"
},
"scripts": {
"test": "node test/run-tests.js"

View File

@@ -237,3 +237,342 @@ duplicate_argname: {
}
expect_stdout: "bar 42 foo 42 bar"
}
issue_3273: {
options = {
arguments: true,
}
input: {
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
function f(a) {
console.log(a, a);
a++;
console.log(a, a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 1",
]
}
issue_3273_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
function f(a) {
console.log(a, a);
a++;
console.log(a, a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 1",
]
}
issue_3273_local_strict: {
options = {
arguments: true,
}
input: {
function f(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
function f(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_local_strict_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
function f(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
function f(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_global_strict: {
options = {
arguments: true,
}
input: {
"use strict";
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
"use strict";
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_global_strict_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
"use strict";
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
"use strict";
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3282_1: {
options = {
arguments: true,
reduce_funcs: true,
reduce_vars: true,
keep_fargs: false,
unused: true,
}
input: {
(function(t) {
return function() {
t();
};
})(function() {
'use strict';
function e() {
return arguments[0];
}
e();
e();
})();
}
expect: {
(function() {
return function() {
(function() {
"use strict";
function e() {
return arguments[0];
}
e();
e();
})();
};
})()();
}
expect_stdout: true
}
issue_3282_1_passes: {
options = {
arguments: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
keep_fargs: false,
unused: true,
}
input: {
(function(t) {
return function() {
t();
};
})(function() {
'use strict';
function e() {
return arguments[0];
}
e();
e();
})();
}
expect: {
(function() {
return function() {
(function() {
"use strict";
function e(argument_0) {
return argument_0;
}
e();
e();
})();
};
})()();
}
expect_stdout: true
}
issue_3282_2: {
options = {
arguments: true,
reduce_vars: true,
keep_fargs: false,
unused: true,
}
input: {
(function(f) {
f();
})(function() {
return (function(t) {
return function() {
t();
};
})(function() {
'use strict';
function e() {
return arguments[0];
}
e();
e();
})();
});
}
expect: {
(function() {
(function() {
return function(t) {
return function() {
t();
};
}(function() {
"use strict";
function e() {
return arguments[0];
}
e();
e();
})();
})();
})();
}
expect_stdout: true
}
issue_3282_2_passes: {
options = {
arguments: true,
passes: 2,
reduce_vars: true,
keep_fargs: false,
unused: true,
}
input: {
(function(f) {
f();
})(function() {
return (function(t) {
return function() {
t();
};
})(function() {
'use strict';
function e() {
return arguments[0];
}
e();
e();
})();
});
}
expect: {
(function() {
(function() {
return function(t) {
return function() {
t();
};
}(function() {
"use strict";
function e(argument_0) {
return argument_0;
}
e();
e();
})();
})();
})();
}
expect_stdout: true
}

View File

@@ -239,3 +239,113 @@ index_length: {
}
expect_stdout: "1 2"
}
constructor_bad: {
options = {
unsafe: true
}
input: {
try {
Array(NaN);
console.log("FAIL1");
} catch (ex) {
try {
new Array(NaN);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
try {
Array(3.14);
console.log("FAIL1");
} catch (ex) {
try {
new Array(3.14);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
}
expect: {
try {
Array(NaN);
console.log("FAIL1");
} catch (ex) {
try {
Array(NaN);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
try {
Array(3.14);
console.log("FAIL1");
} catch (ex) {
try {
Array(3.14);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
}
expect_stdout: [
"PASS",
"PASS",
]
expect_warnings: [
"WARN: Invalid array length: 3.14 [test/compress/arrays.js:13,12]",
"WARN: Invalid array length: 3.14 [test/compress/arrays.js:17,16]",
]
}
constructor_good: {
options = {
unsafe: true
}
input: {
console.log(Array());
console.log(Array(0));
console.log(Array(1));
console.log(Array(6));
console.log(Array(7));
console.log(Array(1, 2));
console.log(Array(false));
console.log(Array("foo"));
console.log(Array(Array));
console.log(new Array());
console.log(new Array(0));
console.log(new Array(1));
console.log(new Array(6));
console.log(new Array(7));
console.log(new Array(1, 2));
console.log(new Array(false));
console.log(new Array("foo"));
console.log(new Array(Array));
}
expect: {
console.log([]);
console.log([]);
console.log([,]);
console.log([,,,,,,]);
console.log(Array(7));
console.log([ 1, 2 ]);
console.log([ false ]);
console.log([ "foo" ]);
console.log(Array(Array));
console.log([]);
console.log([]);
console.log([,]);
console.log([,,,,,,]);
console.log(Array(7));
console.log([ 1, 2 ]);
console.log([ false ]);
console.log([ "foo" ]);
console.log(Array(Array));
}
expect_stdout: true
expect_warnings: []
}

View File

@@ -1,5 +1,6 @@
asm_mixed: {
options = {
assignments: true,
booleans: true,
comparisons: true,
conditionals: true,

View File

@@ -1,5 +1,6 @@
op_equals_left_local_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
@@ -60,6 +61,7 @@ op_equals_left_local_var: {
op_equals_right_local_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
@@ -123,6 +125,7 @@ op_equals_right_local_var: {
}
op_equals_left_global_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
@@ -179,6 +182,7 @@ op_equals_left_global_var: {
op_equals_right_global_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
@@ -236,3 +240,74 @@ op_equals_right_global_var: {
x = g() & x;
}
}
increment_decrement_1: {
options = {
assignments: true,
reduce_vars: true,
}
input: {
console.log(function(a) {
a += 1;
a -= 1;
return a;
}(42));
}
expect: {
console.log(function(a){
++a;
--a;
return a;
}(42));
}
expect_stdout: "42"
}
increment_decrement_2: {
options = {
assignments: true,
passes: 2,
reduce_vars: true,
}
input: {
console.log(function(a) {
a = a + 1;
a = a - 1;
a += 1;
a -= 1;
return a;
}(42));
}
expect: {
console.log(function(a){
++a;
--a;
++a;
--a;
return a;
}(42));
}
expect_stdout: "42"
}
issue_3375: {
options = {
assignments: true,
reduce_vars: true,
}
input: {
console.log(typeof function(b) {
var a = b += 1;
--b;
return a;
}("object"));
}
expect: {
console.log(typeof function(b) {
var a = b += 1;
--b;
return a;
}("object"));
}
expect_stdout: "string"
}

View File

@@ -944,10 +944,10 @@ collapse_vars_misc1: {
function f5(x) { var z = foo(); return (5 - window.x) / z }
function f6() { return window.a * window.z && zap() }
function f7() { var b = window.a * window.z; return b + b }
function f8() { var b = window.a * window.z; return b + (b + 5) }
function f8() { var b = window.a * window.z; return b + (5 + b) }
function f9() { var b = window.a * window.z; return bar() || b }
function f10(x) { var a = 5; return a += 3; }
function f11(x) { var a = 5, b = 3; return a += --b; }
function f11(x) { var a = 5; return a += 2; }
}
}
@@ -3895,11 +3895,11 @@ issue_2436_10: {
o = { b: 3 };
return n;
}
console.log((c = o, [
c.a,
console.log([
(c = o).a,
f(c.b),
c.b,
]).join(" "));
].join(" "));
var c;
}
expect_stdout: "1 2 2"
@@ -5827,3 +5827,354 @@ issue_3215_4: {
}
expect_stdout: "number"
}
issue_3238_1: {
options = {
collapse_vars: true,
unsafe: true,
}
input: {
function f(a) {
var b, c;
if (a) {
b = Object.create(null);
c = Object.create(null);
}
return b === c;
}
console.log(f(0), f(1));
}
expect: {
function f(a) {
var b, c;
if (a) {
b = Object.create(null);
c = Object.create(null);
}
return b === c;
}
console.log(f(0), f(1));
}
expect_stdout: "true false"
}
issue_3238_2: {
options = {
collapse_vars: true,
unsafe: true,
}
input: {
function f(a) {
var b, c;
if (a) {
b = Error();
c = Error();
}
return b === c;
}
console.log(f(0), f(1));
}
expect: {
function f(a) {
var b, c;
if (a) {
b = Error();
c = Error();
}
return b === c;
}
console.log(f(0), f(1));
}
expect_stdout: "true false"
}
issue_3238_3: {
options = {
collapse_vars: true,
unsafe: true,
}
input: {
function f(a) {
var b, c;
if (a) {
b = new Date();
c = new Date();
}
return b === c;
}
console.log(f(0), f(1));
}
expect: {
function f(a) {
var b, c;
if (a) {
b = new Date();
c = new Date();
}
return b === c;
}
console.log(f(0), f(1));
}
expect_stdout: "true false"
}
issue_3238_4: {
options = {
collapse_vars: true,
unsafe: true,
}
input: {
function f(a) {
var b, c;
if (a) {
b = a && {};
c = a && {};
}
return b === c;
}
console.log(f(0), f(1));
}
expect: {
function f(a) {
var b, c;
if (a) {
b = a && {};
c = a && {};
}
return b === c;
}
console.log(f(0), f(1));
}
expect_stdout: "true false"
}
issue_3238_5: {
options = {
collapse_vars: true,
unsafe: true,
}
input: {
function f(a) {
var b, c;
if (a) {
b = a ? [] : 42;
c = a ? [] : 42;
}
return b === c;
}
console.log(f(0), f(1));
}
expect: {
function f(a) {
var b, c;
if (a) {
b = a ? [] : 42;
c = a ? [] : 42;
}
return b === c;
}
console.log(f(0), f(1));
}
expect_stdout: "true false"
}
issue_3238_6: {
options = {
collapse_vars: true,
unsafe: true,
}
input: {
function f(a) {
var b, c;
if (a) {
b = a && 0 || [];
c = a && 0 || [];
}
return b === c;
}
console.log(f(0), f(1));
}
expect: {
function f(a) {
var b, c;
if (a) {
b = a && 0 || [];
c = a && 0 || [];
}
return b === c;
}
console.log(f(0), f(1));
}
expect_stdout: "true false"
}
issue_3247: {
options = {
collapse_vars: true,
}
input: {
function f(o) {
console.log(o.p);
}
var a;
a = Object({ p: "PASS" });
a.q = true;
f(a, true);
}
expect: {
function f(o) {
console.log(o.p);
}
var a;
(a = Object({ p: "PASS" })).q = true;
f(a, true);
}
expect_stdout: "PASS"
}
issue_3305: {
options = {
collapse_vars: true,
conditionals: true,
sequences: true,
}
input: {
function calc(a) {
var x, w;
if (a) {
x = a;
w = 1;
} else {
x = 1;
w = 0;
}
return add(x, w);
}
function add(x, w) {
return x + w;
}
console.log(calc(41));
}
expect: {
function calc(a) {
var x, w;
return w = a ? (x = a, 1) : (x = 1, 0), add(x, w);
}
function add(x, w) {
return x + w;
}
console.log(calc(41));
}
expect_stdout: "42"
}
issue_3314: {
options = {
collapse_vars: true,
}
input: {
function test(a, b) {
console.log(a, b);
}
var a = "FAIL", b;
b = a = "PASS";
test(a, b);
}
expect: {
function test(a, b) {
console.log(a, b);
}
var a = "FAIL", b;
b = a = "PASS";
test(a, b);
}
expect_stdout: "PASS PASS"
}
issue_3327: {
options = {
collapse_vars: true,
conditionals: true,
sequences: true,
}
input: {
var a, b, l = ["PASS", 42];
if (l.length === 1) {
a = l[0].a;
b = l[0].b;
} else {
a = l[0];
b = l[1];
}
function echo(a, b) {
console.log(a, b);
}
echo(a, b);
}
expect: {
var a, b, l = ["PASS", 42];
function echo(a, b) {
console.log(a, b);
}
b = 1 === l.length ? (a = l[0].a, l[0].b) : (a = l[0], l[1]),
echo(a,b);
}
expect_stdout: "PASS 42"
}
assign_left: {
options = {
collapse_vars: true,
}
input: {
console.log(function(a, b) {
(b = a, b.p).q = "PASS";
return a.p.q;
}({p: {}}));
}
expect: {
console.log(function(a, b) {
(b = a).p.q = "PASS";
return a.p.q;
}({p: {}}));
}
expect_stdout: "PASS"
}
sub_property: {
options = {
collapse_vars: true,
}
input: {
console.log(function(a, b) {
return a[(b = a, b.length - 1)];
}([ "FAIL", "PASS" ]));
}
expect: {
console.log(function(a, b) {
return a[(b = a).length - 1];
}([ "FAIL", "PASS" ]));
}
expect_stdout: "PASS"
}
assign_undeclared: {
options = {
collapse_vars: true,
toplevel: true,
unused: true,
}
input: {
var A = (console.log(42), function() {});
B = new A();
console.log(typeof B);
}
expect: {
B = new (console.log(42), function() {})();
console.log(typeof B);
}
expect_stdout: [
"42",
"object",
]
}

View File

@@ -323,3 +323,25 @@ is_number_unsafe: {
}
expect_stdout: "true"
}
is_boolean_var: {
options = {
comparisons: true,
reduce_vars: true,
}
input: {
console.log(function(a, b) {
for (var i = 0, c = !b; i < a.length; i++)
if (!a[i] === c)
return i;
}([ false, true ], 42));
}
expect: {
console.log(function(a, b) {
for (var i = 0, c = !b; i < a.length; i++)
if (!a[i] == c)
return i;
}([ false, true ], 42));
}
expect_stdout: "1"
}

View File

@@ -1292,3 +1292,127 @@ to_and_or: {
}
expect_stdout: true
}
cond_seq_assign_1: {
options = {
conditionals: true,
sequences: true,
}
input: {
function f(a) {
var t;
if (a) {
t = "foo";
t = "bar";
} else {
console.log(t);
t = 42;
}
console.log(t);
}
f(f);
f();
}
expect: {
function f(a) {
var t;
t = a ? (t = "foo", "bar") : (console.log(t), 42),
console.log(t);
}
f(f),
f();
}
expect_stdout: [
"bar",
"undefined",
"42",
]
}
cond_seq_assign_2: {
options = {
conditionals: true,
sequences: true,
}
input: {
function f(a) {
var t;
if (a) {
t = "foo";
a = "bar";
} else {
console.log(t);
t = 42;
}
console.log(t);
}
f(f);
f();
}
expect: {
function f(a) {
var t;
a ? (t = "foo", a = "bar") : (console.log(t), t = 42),
console.log(t);
}
f(f),
f();
}
expect_stdout: [
"foo",
"undefined",
"42",
]
}
cond_seq_assign_3: {
options = {
assignments: true,
conditionals: true,
}
input: {
var c = 0;
if (this)
c = 1 + c, c = c + 1;
else
c = 1 + c, c = c + 1;
console.log(c);
}
expect: {
var c = 0;
this, c = 1 + c, c += 1;
console.log(c);
}
expect_stdout: "2"
}
issue_3271: {
options = {
conditionals: true,
}
input: {
function f(a) {
var i = 0, b = [];
if (a) {
b[i++] = 4,
b[i++] = 1;
} else {
b[i++] = 3,
b[i++] = 2,
b[i++] = 1;
}
return b;
}
console.log(f(0).pop(), f(1).pop());
}
expect: {
function f(a) {
var i = 0, b = [];
a ? b[i++] = 4 : (b[i++] = 3, b[i++] = 2),
b[i++] = 1;
return b;
}
console.log(f(0).pop(), f(1).pop());
}
expect_stdout: "1 1"
}

View File

@@ -1982,3 +1982,47 @@ issue_3192: {
"foo bar",
]
}
issue_3233: {
options = {
pure_getters: "strict",
side_effects: true,
unused: true,
}
input: {
var a = function b() {
b.c = "PASS";
};
a();
console.log(a.c);
}
expect: {
var a = function b() {
b.c = "PASS";
};
a();
console.log(a.c);
}
expect_stdout: "PASS"
}
issue_3375: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var b = 1;
var a = c = [], c = --b + ("function" == typeof f && f());
var a = c && c[a];
console.log(a, b);
}
expect: {
var b = 1;
var a = [], c = --b + ("function" == typeof f && f());
a = c && c[a];
console.log(a, b);
}
expect_stdout: "0 0"
}

View File

@@ -1124,14 +1124,14 @@ issue_2207_1: {
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));
console.log(Math.pow(Math.PI, Math.E - Math.LN10).toFixed(15));
}
expect: {
console.log("A");
console.log(7);
console.log(Math.cos(1.2345));
console.log(1.2543732512566947);
console.log(1.6093984514472044);
console.log("1.609398451447204");
}
expect_stdout: true
}
@@ -1245,12 +1245,12 @@ self_comparison_1: {
}
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);
console.log(typeof o.n, o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n);
}
expect: {
console.log(false, false, true, true, "number");
console.log("number", false, false, true, true);
}
expect_stdout: "false false true true 'number'"
expect_stdout: "number false false true true"
}
self_comparison_2: {
@@ -1265,12 +1265,12 @@ self_comparison_2: {
}
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);
console.log(typeof o.n, o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n);
}
expect: {
console.log(false, false, true, true, "number");
console.log("number", false, false, true, true);
}
expect_stdout: "false false true true 'number'"
expect_stdout: "number false false true true"
}
issue_2535_1: {
@@ -1540,7 +1540,7 @@ issue_2926_2: {
expect_stdout: "function"
}
issue_2968: {
issue_2968_1: {
options = {
collapse_vars: true,
evaluate: true,
@@ -1571,6 +1571,39 @@ issue_2968: {
expect_stdout: "PASS"
}
issue_2968_2: {
options = {
assignments: true,
collapse_vars: true,
evaluate: true,
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
var c = "FAIL";
(function() {
(function(a, b) {
a <<= 0;
a && (a[(c = "PASS", 0 >>> (b += 1))] = 0);
})(42, -42);
})();
console.log(c);
}
expect: {
var c = "FAIL";
(function() {
a = 42,
((a <<= 0) && (a[(c = "PASS", 0)] = 0));
var a;
})();
console.log(c);
}
expect_stdout: "PASS"
}
truthy_conditionals: {
options = {
conditionals: true,
@@ -1610,3 +1643,72 @@ truthy_loops: {
}
}
}
if_increment: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function(a) {
if (console)
return ++a;
}(0));
}
expect: {
console.log(function(a) {
if (console)
return 1;
}());
}
expect_stdout: "1"
}
try_increment: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function(a) {
try {
return ++a;
} catch (e) {}
}(0));
}
expect: {
console.log(function(a) {
try {
return 1;
} catch (e) {}
}());
}
expect_stdout: "1"
}
unsafe_escaped: {
options = {
evaluate: true,
inline: true,
passes: 3,
reduce_vars: true,
side_effects: true,
unsafe: true,
unused: true,
}
input: {
(function(a) {
console.log(function(index) {
return a[index];
}(function(term) {
return a.indexOf(term);
}("PASS")));
})([ "PASS" ]);
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
}

View File

@@ -358,6 +358,7 @@ inner_ref: {
issue_2107: {
options = {
assignments: true,
collapse_vars: true,
inline: true,
passes: 3,
@@ -387,6 +388,7 @@ issue_2107: {
issue_2114_1: {
options = {
assignments: true,
collapse_vars: true,
if_return: true,
inline: true,
@@ -419,6 +421,7 @@ issue_2114_1: {
issue_2114_2: {
options = {
assignments: true,
collapse_vars: true,
if_return: true,
inline: true,
@@ -1223,6 +1226,7 @@ issue_2630_1: {
issue_2630_2: {
options = {
assignments: true,
collapse_vars: true,
inline: true,
passes: 2,
@@ -1320,6 +1324,7 @@ issue_2630_4: {
issue_2630_5: {
options = {
assignments: true,
collapse_vars: true,
inline: true,
reduce_vars: true,
@@ -1398,6 +1403,8 @@ recursive_inline_2: {
issue_2657: {
options = {
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
unused: true,
@@ -2315,3 +2322,746 @@ issue_3125: {
}
expect_stdout: "PASS"
}
issue_3274: {
options = {
collapse_vars: true,
inline: true,
join_vars: true,
loops: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
var g = function(a) {
var c = a.p, b = c;
return b != c;
};
while (g(1))
console.log("FAIL");
console.log("PASS");
})();
}
expect: {
(function() {
for (var c; void 0, (c = 1..p) != c;)
console.log("FAIL");
console.log("PASS");
})();
}
expect_stdout: "PASS"
}
issue_3297_1: {
options = {
collapse_vars: true,
inline: true,
reduce_vars: true,
unused: true,
}
mangle = {}
input: {
function function1() {
var r = {
function2: function2
};
function function2() {
alert(1234);
function function3() {
function2();
};
function3();
}
return r;
}
}
expect: {
function function1() {
return {
function2: function n() {
alert(1234);
function t() {
n();
}
t();
}
};
}
}
}
issue_3297_2: {
options = {
collapse_vars: true,
conditionals: true,
inline: true,
reduce_vars: true,
unused: true,
}
mangle = {}
input: {
function function1(session) {
var public = {
processBulk: processBulk
};
return public;
function processBulk(bulk) {
var subparam1 = session();
function processOne(param1) {
var param2 = {
subparam1: subparam1
};
doProcessOne({
param1: param1,
param2: param2,
}, function () {
processBulk(bulk);
});
};
if (bulk && bulk.length > 0)
processOne(bulk.shift());
}
function doProcessOne(config, callback) {
console.log(JSON.stringify(config));
callback();
}
}
function1(function session() {
return 42;
}).processBulk([1, 2, 3]);
}
expect: {
function function1(o) {
return {
processBulk: function t(u) {
var r = o();
function n(n) {
var o = {
subparam1: r
};
c({
param1: n,
param2: o
}, function() {
t(u);
});
}
u && u.length > 0 && n(u.shift());
}
};
function c(n, o) {
console.log(JSON.stringify(n));
o();
}
}
function1(function() {
return 42;
}).processBulk([ 1, 2, 3 ]);
}
expect_stdout: [
'{"param1":1,"param2":{"subparam1":42}}',
'{"param1":2,"param2":{"subparam1":42}}',
'{"param1":3,"param2":{"subparam1":42}}',
]
}
issue_3297_3: {
options = {
collapse_vars: true,
comparisons: true,
conditionals: true,
inline: true,
join_vars: true,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
mangle = {}
input: {
function function1(session) {
var public = {
processBulk: processBulk
};
return public;
function processBulk(bulk) {
var subparam1 = session();
function processOne(param1) {
var param2 = {
subparam1: subparam1
};
doProcessOne({
param1: param1,
param2: param2,
}, function () {
processBulk(bulk);
});
};
if (bulk && bulk.length > 0)
processOne(bulk.shift());
}
function doProcessOne(config, callback) {
console.log(JSON.stringify(config));
callback();
}
}
function1(function session() {
return 42;
}).processBulk([1, 2, 3]);
}
expect: {
function function1(u) {
return {
processBulk: function n(r) {
var o, t = u();
r && 0 < r.length && (o = {
param1: r.shift(),
param2: {
subparam1: t
}
},
console.log(JSON.stringify(o)),
n(r));
}
};
}
function1(function() {
return 42;
}).processBulk([ 1, 2, 3 ]);
}
expect_stdout: [
'{"param1":1,"param2":{"subparam1":42}}',
'{"param1":2,"param2":{"subparam1":42}}',
'{"param1":3,"param2":{"subparam1":42}}',
]
}
cross_references_1: {
options = {
inline: true,
reduce_vars: true,
unused: true,
}
input: {
var Math = {
square: function(n) {
return n * n;
}
};
console.log((function(factory) {
return factory();
})(function() {
return function(Math) {
return function(n) {
return Math.square(n);
};
}(Math);
})(3));
}
expect: {
var Math = {
square: function(n) {
return n * n;
}
};
console.log(function(Math) {
return function(n) {
return Math.square(n);
};
}(Math)(3));
}
expect_stdout: "9"
}
cross_references_2: {
options = {
collapse_vars: true,
evaluate: true,
hoist_props: true,
inline: true,
passes: 4,
pure_getters: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var Math = {
square: function(n) {
return n * n;
}
};
console.log((function(factory) {
return factory();
})(function() {
return function(Math) {
return function(n) {
return Math.square(n);
};
}(Math);
})(3));
}
expect: {
console.log(9);
}
expect_stdout: "9"
}
cross_references_3: {
options = {
inline: true,
reduce_vars: true,
unused: true,
}
input: {
var Math = {
square: function(n) {
return n * n;
},
cube: function(n) {
return n * n * n;
}
};
console.log(function(factory) {
return factory();
}(function() {
return function(Math) {
return function(n) {
Math = {
square: function(x) {
return "(SQUARE" + x + ")";
},
cube: function(x) {
return "(CUBE" + x + ")";
}
};
return Math.square(n) + Math.cube(n);
};
}(Math);
})(2));
console.log(Math.square(3), Math.cube(3));
}
expect: {
var Math = {
square: function(n) {
return n * n;
},
cube: function(n) {
return n * n * n;
}
};
console.log(function(Math) {
return function(n) {
Math = {
square: function(x) {
return "(SQUARE" + x + ")";
},
cube: function(x) {
return "(CUBE" + x + ")";
}
};
return Math.square(n) + Math.cube(n);
};
}(Math)(2));
console.log(Math.square(3), Math.cube(3));
}
expect_stdout: [
"(SQUARE2)(CUBE2)",
"9 27",
]
}
loop_inline: {
options = {
inline: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function(o) {
function g(p) {
return o[p];
}
function h(q) {
while (g(q));
}
return h;
}([ 1, "foo", 0 ])(2));
}
expect: {
console.log(function(o) {
return function(q) {
while (p = q, o[p]);
var p;
};
}([ 1, "foo", 0 ])(2));
}
expect_stdout: "undefined"
}
functions: {
options = {
functions: true,
reduce_vars: true,
unused: true,
}
input: {
!function() {
var a = function a() {
return a && "a";
};
var b = function x() {
return !!x;
};
var c = function(c) {
return c;
};
if (c(b(a()))) {
var d = function() {};
var e = function y() {
return typeof y;
};
var f = function(f) {
return f;
};
console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);
}
}();
}
expect: {
!function() {
function a() {
return a && "a";
}
function b() {
return !!b;
}
var c = function(c) {
return c;
};
if (c(b(a()))) {
function d() {}
function e() {
return typeof e;
}
var f = function(f) {
return f;
};
console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);
}
}();
}
expect_stdout: "a true 42 function function function"
}
functions_use_strict: {
options = {
functions: true,
reduce_vars: true,
unused: true,
}
input: {
"use strict";
!function() {
var a = function a() {
return a && "a";
};
var b = function x() {
return !!x;
};
var c = function(c) {
return c;
};
if (c(b(a()))) {
var d = function() {};
var e = function y() {
return typeof y;
};
var f = function(f) {
return f;
};
console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);
}
}();
}
expect: {
"use strict";
!function() {
function a() {
return a && "a";
}
function b() {
return !!b;
}
var c = function(c) {
return c;
};
if (c(b(a()))) {
var d = function() {};
var e = function y() {
return typeof y;
};
var f = function(f) {
return f;
};
console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);
}
}();
}
expect_stdout: "a true 42 function function function"
}
issue_2437: {
options = {
collapse_vars: true,
conditionals: true,
functions: true,
inline: true,
join_vars: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function foo() {
return bar();
}
function bar() {
if (xhrDesc) {
var req = new XMLHttpRequest();
var result = !!req.onreadystatechange;
Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {});
return result;
} else {
var req = new XMLHttpRequest();
var detectFunc = function(){};
req.onreadystatechange = detectFunc;
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
req.onreadystatechange = null;
return result;
}
}
console.log(foo());
}
expect: {
console.log(function() {
if (xhrDesc) {
var result = !!(req = new XMLHttpRequest()).onreadystatechange;
return Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
result;
}
function detectFunc() {}
var req;
(req = new XMLHttpRequest()).onreadystatechange = detectFunc;
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
return req.onreadystatechange = null, result;
}());
}
}
issue_2485: {
options = {
functions: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
var foo = function(bar) {
var n = function(a, b) {
return a + b;
};
var sumAll = function(arg) {
return arg.reduce(n, 0);
};
var runSumAll = function(arg) {
return sumAll(arg);
};
bar.baz = function(arg) {
var n = runSumAll(arg);
return (n.get = 1), n;
};
return bar;
};
var bar = foo({});
console.log(bar.baz([1, 2, 3]));
}
expect: {
var foo = function(bar) {
function n(a, b) {
return a + b;
}
function runSumAll(arg) {
return function(arg) {
return arg.reduce(n, 0);
}(arg);
}
bar.baz = function(arg) {
var n = runSumAll(arg);
return (n.get = 1), n;
};
return bar;
};
var bar = foo({});
console.log(bar.baz([1, 2, 3]));
}
expect_stdout: "6"
}
issue_3364: {
options = {
functions: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {}
input: {
var s = 2, a = 100, b = 10, c = 0;
function f(p, e, r) {
try {
for (var i = 1; i-- > 0;)
var a = function(x) {
function g(y) {
y && y[a++];
}
var x = g(--s >= 0 && f(c++));
for (var j = 1; --j > 0;);
}();
} catch (e) {
try {
return;
} catch (z) {
for (var k = 1; --k > 0;) {
for (var l = 1; l > 0; --l) {
var n = function() {};
for (var k in n)
var o = (n, k);
}
}
}
}
}
var r = f();
console.log(c);
}
expect: {
var s = 2, c = 0;
(function n(r, o, a) {
try {
for (var f = 1; f-- >0;)
var t = function(r) {
(function(r) {
r && r[t++];
})(--s >= 0 && n(c++));
for (var o = 1; --o > 0;);
}();
} catch (o) {
try {
return;
} catch (r) {
for (var v = 1; --v > 0;)
for (var i = 1; i > 0;--i) {
function u() {}
for (var v in u);
}
}
}
})();
console.log(c);
}
expect_stdout: "2"
}
issue_3366: {
options = {
functions: true,
inline: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {
function g() {
return function() {};
}
var a = g();
(function() {
this && a && console.log("PASS");
})();
}
f();
}
expect: {
void function() {
this && a && console.log("PASS");
}();
function a() {}
}
expect_stdout: "PASS"
}
issue_3371: {
options = {
functions: true,
inline: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
(function() {
var a = function f() {
(function() {
console.log(typeof f);
})();
};
while (a());
})();
}
expect: {
(function() {
function a() {
console.log(typeof a);
}
while (a());
})();
}
expect_stdout: "function"
}
class_iife: {
options = {
inline: true,
sequences: true,
toplevel: true,
}
input: {
var A = function() {
function B() {}
B.prototype.m = function() {
console.log("PASS");
};
return B;
}();
new A().m();
}
expect: {
var A = (B.prototype.m = function() {
console.log("PASS");
}, B);
function B() {}
new A().m();
}
expect_stdout: "PASS"
}

View File

@@ -861,3 +861,111 @@ issue_3215_4: {
}
expect_stdout: "PASS"
}
issue_3355_1: {
mangle = {
ie8: false,
}
input: {
(function f() {
var f;
})();
(function g() {
})();
console.log(typeof f === typeof g);
}
expect: {
(function o() {
var o;
})();
(function o() {
})();
console.log(typeof f === typeof g);
}
expect_stdout: "true"
}
issue_3355_2: {
mangle = {
ie8: true,
}
input: {
(function f() {
var f;
})();
(function g() {
})();
console.log(typeof f === typeof g);
}
expect: {
(function f() {
var f;
})();
(function g() {
})();
console.log(typeof f === typeof g);
}
expect_stdout: "true"
}
issue_3355_3: {
mangle = {
ie8: false,
}
input: {
!function(a) {
"aaaaaaaaaa";
a();
var b = function c() {
var c = 42;
console.log("FAIL");
};
}(function() {
console.log("PASS");
});
}
expect: {
!function(a) {
"aaaaaaaaaa";
a();
var o = function a() {
var a = 42;
console.log("FAIL");
};
}(function() {
console.log("PASS");
});
}
expect_stdout: "PASS"
}
issue_3355_4: {
mangle = {
ie8: true,
}
input: {
!function(a) {
"aaaaaaaaaa";
a();
var b = function c() {
var c = 42;
console.log("FAIL");
};
}(function() {
console.log("PASS");
});
}
expect: {
!function(a) {
"aaaaaaaaaa";
a();
var o = function n() {
var n = 42;
console.log("FAIL");
};
}(function() {
console.log("PASS");
});
}
expect_stdout: "PASS"
}

View File

@@ -396,3 +396,151 @@ if_if_return_return: {
}
}
}
if_body_return_1: {
options = {
if_return: true,
}
input: {
var c = "PASS";
function f(a, b) {
if (a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect: {
var c = "PASS";
function f(a, b) {
if (a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect_stdout: [
"true",
"true",
"42",
"PASS",
]
}
if_body_return_2: {
options = {
if_return: true,
}
input: {
var c = "PASS";
function f(a, b) {
if (0 + a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect: {
var c = "PASS";
function f(a, b) {
if (0 + a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect_stdout: [
"true",
"true",
"42",
"PASS",
]
}
if_body_return_3: {
options = {
if_return: true,
}
input: {
var c = "PASS";
function f(a, b) {
if (1 == a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect: {
var c = "PASS";
function f(a, b) {
if (1 != a) return true;
if (b) throw new Error(c);
return 42;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect_stdout: [
"true",
"true",
"42",
"PASS",
]
}

View File

@@ -26,7 +26,7 @@ warn: {
}().length);
}
expect_warnings: [
"WARN: Function.protoype.caller not supported [test/compress/issue-2719.js:5,19]",
"WARN: Function.protoype.arguments not supported [test/compress/issue-2719.js:5,19]",
"WARN: Function.prototype.caller not supported [test/compress/issue-2719.js:5,19]",
"WARN: Function.prototype.arguments not supported [test/compress/issue-2719.js:5,19]",
]
}

View File

@@ -646,3 +646,30 @@ issue_2904: {
}
expect_stdout: "1"
}
issue_3371: {
options = {
functions: true,
join_vars: true,
loops: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
var a = function() {
console.log("PASS");
};
while (a());
})();
}
expect: {
(function() {
function a() {
console.log("PASS");
}
for (; a(); );
})();
}
expect_stdout: "PASS"
}

View File

@@ -642,3 +642,41 @@ issue_3065_4: {
})();
}
}
issue_3325_1: {
options = {
pure_funcs: "cb",
side_effects: true,
}
input: {
function cb() {
console.log("PASS");
}
cb();
}
expect: {
function cb() {
console.log("PASS");
}
}
}
issue_3325_2: {
options = {
pure_funcs: "xxxcbxxx",
side_effects: true,
}
input: {
function cb() {
console.log("PASS");
}
cb();
}
expect: {
function cb() {
console.log("PASS");
}
cb();
}
expect_stdout: "PASS"
}

View File

@@ -281,8 +281,8 @@ unsafe_evaluate_escaped: {
console.log(function(){ var o={p:3},a=[o]; console.log(a[0].p++); return o.p; }());
}
expect: {
console.log(function(){ var o={p:1}; console.log(o, o.p); return o.p; }());
console.log(function(){ var o={p:2}; console.log(o.p, o); return o.p; }());
console.log(function(){ var o={p:1}; console.log(o, 1); return o.p; }());
console.log(function(){ var o={p:2}; console.log(2, o); return o.p; }());
console.log(function(){ var o={p:3},a=[o]; console.log(a[0].p++); return o.p; }());
}
expect_stdout: true
@@ -2740,18 +2740,18 @@ issue_1814_2: {
!function() {
var b = a + 1;
!function(a) {
console.log(a++, b);
console.log(b, a++);
}(0);
}();
}
expect: {
!function() {
!function(a) {
console.log(a++, "321");
console.log("321", a++);
}(0);
}();
}
expect_stdout: "0 '321'"
expect_stdout: "321 0"
}
try_abort: {
@@ -5354,6 +5354,7 @@ issue_2774: {
issue_2799_1: {
options = {
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
@@ -6429,3 +6430,328 @@ issue_3140_5: {
}
expect_stdout: "1"
}
issue_3240_1: {
options = {
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
f(1);
function f(a) {
console.log(a);
var g = function() {
f(a - 1);
};
if (a) g();
}
})();
}
expect: {
(function() {
(function f(a) {
console.log(a);
var g = function() {
f(a - 1);
};
if (a) g();
})(1);
})();
}
expect_stdout: [
"1",
"0",
]
}
issue_3240_2: {
options = {
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
f(1);
function f(a) {
console.log(a);
var g = function() {
f(a - 1);
};
if (a) g();
}
})();
}
expect: {
(function() {
(function f(a) {
console.log(a);
if (a) (function() {
f(a - 1);
})();
})(1);
})();
}
expect_stdout: [
"1",
"0",
]
}
issue_3240_3: {
options = {
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
f();
function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
var g = function() {
(b ? function() {} : function() {
f.a++;
f(1);
})();
};
g();
}
})();
}
expect: {
(function() {
(function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
var g = function() {
(b ? function() {} : function() {
f.a++;
f(1);
})();
};
g();
})();
})();
}
expect_stdout: [
"0",
"1",
]
}
issue_3240_4: {
options = {
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
f();
function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
var g = function() {
(b ? function() {} : function() {
f.a++;
f(1);
})();
};
g();
}
})();
}
expect: {
(function() {
(function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
(function() {
(b ? function() {} : function() {
f.a++;
f(1);
})();
})();
})();
})();
}
expect_stdout: [
"0",
"1",
]
}
issues_3267_1: {
options = {
collapse_vars: true,
conditionals: true,
dead_code: true,
evaluate: true,
inline: true,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
(function(x) {
x();
})(function() {
(function(i) {
if (i)
return console.log("PASS");
throw "FAIL";
})(Object());
});
}
expect: {
!function(i) {
if (i)
return console.log("PASS");
throw "FAIL";
}(Object());
}
expect_stdout: "PASS"
}
issues_3267_2: {
options = {
collapse_vars: true,
conditionals: true,
dead_code: true,
evaluate: true,
inline: true,
keep_fargs: false,
passes: 2,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
(function(x) {
x();
})(function() {
(function(i) {
if (i)
return console.log("PASS");
throw "FAIL";
})(Object());
});
}
expect: {
!function() {
if (Object())
return console.log("PASS");
throw "FAIL";
}();
}
expect_stdout: "PASS"
}
issues_3267_3: {
options = {
collapse_vars: true,
conditionals: true,
dead_code: true,
evaluate: true,
inline: true,
keep_fargs: false,
passes: 2,
reduce_vars: true,
sequences: true,
side_effects: true,
unsafe: true,
unused: true,
}
input: {
(function(x) {
x();
})(function() {
(function(i) {
if (i)
return console.log("PASS");
throw "FAIL";
})(Object());
});
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
}
issue_3297: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function() {
function f() {
var a;
var b = function a() {
console.log(a === b) && f();
};
b();
}
f();
})();
}
expect: {
(function() {
(function f() {
var b = function a() {
console.log(a === b) && f();
};
b();
})();
})();
}
expect_stdout: "true"
}
drop_side_effect_free: {
options = {
collapse_vars: true,
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a = 123;
"" + (a && (a.b = 0) || a);
console.log(a);
}
expect: {
var a = 123;
a.b = 0;
console.log(a);
}
expect_stdout: "123"
}
issue_3377: {
options = {
reduce_vars: true,
unused: true,
}
input: {
console.log(function f() {
return f[0], (f = 42);
}());
}
expect: {
console.log(function f() {
return f[0], (f = 42);
}());
}
expect_stdout: "42"
}

View File

@@ -924,14 +924,14 @@ call: {
b.c = function() {
console.log(this === b ? "bar" : "baz");
},
a, b(),
b(),
(a, b.c)(),
a, function() {
function() {
console.log(this === a);
}(),
a, new b(),
a, new b.c(),
a, new function() {
new b(),
new b.c(),
new function() {
console.log(this === a);
}();
}
@@ -944,3 +944,23 @@ call: {
"false",
]
}
missing_link: {
options = {
conditionals: true,
evaluate: true,
sequences: true,
}
input: {
var a = 100;
a;
a++ + (0 ? 2 : 1);
console.log(a);
}
expect: {
var a = 100;
a,
a++,
console.log(a);
}
}

View File

@@ -1,7 +1,5 @@
exports["base54"] = base54;
exports["Compressor"] = Compressor;
exports["defaults"] = defaults;
exports["is_identifier"] = is_identifier;
exports["JS_Parse_Error"] = JS_Parse_Error;
exports["mangle_properties"] = mangle_properties;
exports["minify"] = minify;
@@ -9,7 +7,6 @@ exports["OutputStream"] = OutputStream;
exports["parse"] = parse;
exports["push_uniq"] = push_uniq;
exports["reserve_quoted_keys"] = reserve_quoted_keys;
exports["SourceMap"] = SourceMap;
exports["string_template"] = string_template;
exports["tokenizer"] = tokenizer;
exports["TreeTransformer"] = TreeTransformer;

View File

@@ -0,0 +1,8 @@
{
"compress": false,
"mangle": {
"properties": {
"regex": "/^_/"
}
}
}

View File

@@ -0,0 +1,8 @@
function f() {
"aaaaaaaaaa";
var o = {
prop: 1,
_int: 2,
};
return o.prop + o._int;
}

View File

@@ -3,7 +3,7 @@
"use strict";
var site = "https://browserbench.org/JetStream";
var site = "https://browserbench.org/JetStream1.1";
if (typeof phantom == "undefined") {
require("../tools/exit");
var args = process.argv.slice(2);

View File

@@ -1,6 +1,7 @@
var assert = require("assert");
var exec = require("child_process").exec;
var fs = require("fs");
var run_code = require("../sandbox").run_code;
function read(path) {
return fs.readFileSync(path, "utf8");
@@ -257,7 +258,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], "ERROR: Unexpected token: punc «{», expected: punc «,»");
done();
});
});
@@ -281,7 +282,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], "ERROR: Unexpected token: eof");
done();
});
});
@@ -293,7 +294,7 @@ 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], "ERROR: Unexpected token: eof");
done();
});
});
@@ -362,7 +363,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/dot_1.js:1,2",
"a.=",
" ^",
"ERROR: Unexpected token: operator (=)"
"ERROR: Unexpected token: operator «=», expected: name"
].join("\n"));
done();
});
@@ -376,7 +377,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/dot_2.js:1,0",
"%.a;",
"^",
"ERROR: Unexpected token: operator (%)"
"ERROR: Unexpected token: operator «%»"
].join("\n"));
done();
});
@@ -390,7 +391,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/dot_3.js:1,2",
"a./();",
" ^",
"ERROR: Unexpected token: operator (/)"
"ERROR: Unexpected token: operator «/», expected: name"
].join("\n"));
done();
});
@@ -404,7 +405,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/object.js:1,13",
"console.log({%: 1});",
" ^",
"ERROR: Unexpected token: operator (%)"
"ERROR: Unexpected token: operator «%»"
].join("\n"));
done();
});
@@ -502,7 +503,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/else.js:1,7",
"if (0) else 1;",
" ^",
"ERROR: Unexpected token: keyword (else)"
"ERROR: Unexpected token: keyword «else»"
].join("\n"));
done();
});
@@ -633,6 +634,14 @@ describe("bin/uglifyjs", function() {
done();
});
});
it("Should work with mangle.properties.regex from --config-file", function(done) {
var command = uglifyjscmd + " test/input/issue-3315/input.js --config-file test/input/issue-3315/config.json";
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, 'function f(){"aaaaaaaaaa";var a={prop:1,a:2};return a.prop+a.a}\n');
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) {
@@ -651,7 +660,7 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with explicit --no-rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js -mc --no-rename";
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2 --no-rename";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, "function f(n){return function(n){return n}(n)}\n");
@@ -659,7 +668,7 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with implicit --rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js -mc";
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, "function f(n){return n}\n");
@@ -667,7 +676,7 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with implicit --no-rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js -c";
var command = uglifyjscmd + " test/input/rename/input.js -c passes=2";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(x){return x}(x)}\n");
@@ -706,4 +715,32 @@ describe("bin/uglifyjs", function() {
done();
});
});
it("Should compress swarm of unused variables with reasonable performance", function(done) {
var code = [
"console.log(function() {",
];
for (var i = 0; i < 10000; i++) {
code.push("var obj" + i + " = {p: " + i + "};");
}
code.push("var map = {");
for (var i = 0; i < 10000; i++) {
code.push("obj" + i + ": obj" + i + ",");
}
code = code.concat([
"};",
"return obj25.p + obj121.p + obj1024.p;",
"}());",
]).join("\n");
exec(uglifyjscmd + " -mc", function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, [
"console.log(function(){",
"var p={p:25},n={p:121},o={p:1024};",
"return p.p+n.p+o.p",
"}());\n",
].join(""));
assert.strictEqual(run_code(stdout), run_code(code));
done();
}).stdin.end(code);
});
});

View File

@@ -13,7 +13,7 @@ describe("comments", function() {
var fail = function(e) {
return e instanceof UglifyJS.JS_Parse_Error
&& e.message === "Unexpected token: operator (>)"
&& e.message === "Unexpected token: operator «>»"
&& e.line === 2
&& e.col === 0;
}
@@ -36,7 +36,7 @@ describe("comments", function() {
var fail = function(e) {
return e instanceof UglifyJS.JS_Parse_Error
&& e.message === "Unexpected token: operator (>)"
&& e.message === "Unexpected token: operator «>»"
&& e.line === 5
&& e.col === 0;
}

View File

@@ -146,7 +146,7 @@ describe("Directives", function() {
UglifyJS.parse(tokenizer);
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error
&& e.message === "Unexpected token: punc (])"
&& /^Unexpected token: punc «]»/.test(e.message)
}, test[0]);
test[1].forEach(function(directive) {
assert.strictEqual(tokenizer.has_directive(directive), true, directive + " in " + test[0]);

View File

@@ -69,7 +69,7 @@ describe("Getters and setters", function() {
var fail = function(data) {
return function(e) {
return e instanceof UglifyJS.JS_Parse_Error
&& e.message === "Unexpected token: operator (" + data.operator + ")";
&& e.message === "Unexpected token: operator «" + data.operator + "»";
};
};
var errorMessage = function(data) {

View File

@@ -87,7 +87,7 @@ describe("minify", function() {
assert.strictEqual(run_code(compressed), run_code(original));
});
it("Should avoid mangled names in cache", function() {
it("Should avoid cached names when mangling top-level variables", function() {
var cache = {};
var original = "";
var compressed = "";
@@ -116,10 +116,34 @@ describe("minify", function() {
assert.strictEqual(run_code(compressed), run_code(original));
});
it("Should avoid cached names when mangling inner-scoped variables", function() {
var cache = {};
var original = "";
var compressed = "";
[
'var extend = function(a, b) { console.log("extend"); a(); b(); }; function A() { console.log("A"); };',
'var B = function(A) { function B() { console.log("B") }; extend(B, A); return B; }(A);',
].forEach(function(code) {
var result = UglifyJS.minify(code, {
compress: false,
nameCache: cache,
toplevel: true,
});
if (result.error) throw result.error;
original += code;
compressed += result.code;
});
assert.strictEqual(compressed, [
'var o=function(o,n){console.log("extend");o();n()};function n(){console.log("A")}',
'var e=function(n){function e(){console.log("B")}o(e,n);return e}(n);',
].join(""));
assert.strictEqual(run_code(compressed), run_code(original));
});
it("Should not parse invalid use of reserved words", function() {
assert.strictEqual(UglifyJS.minify("function enum(){}").error, undefined);
assert.strictEqual(UglifyJS.minify("function static(){}").error, undefined);
assert.strictEqual(UglifyJS.minify("function this(){}").error.message, "Unexpected token: name (this)");
assert.strictEqual(UglifyJS.minify("function this(){}").error.message, "Unexpected token: name «this»");
});
describe("keep_quoted_props", function() {
@@ -214,7 +238,7 @@ describe("minify", function() {
var result = UglifyJS.minify("function f(a{}");
var err = result.error;
assert.ok(err instanceof Error);
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token punc «{», expected punc «,»");
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token: punc «{», expected: punc «,»");
assert.strictEqual(err.filename, "0");
assert.strictEqual(err.line, 1);
assert.strictEqual(err.col, 12);
@@ -241,7 +265,7 @@ describe("minify", function() {
});
var err = result.error;
assert.ok(err instanceof Error);
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token: keyword (debugger)");
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token: keyword «debugger»");
});
it("Should skip inherited properties", function() {
var foo = Object.create({ skip: this });

View File

@@ -73,8 +73,10 @@ exports.run_code = function(code, reuse) {
process.stdout.write = original_write;
if (!reuse || code.indexOf(".prototype") >= 0) {
context = null;
} else for (var key in context) {
delete context[key];
} else {
vm.runInContext(Object.keys(context).map(function(name) {
return "delete " + name;
}).join("\n"), context);
}
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,61 +1,540 @@
<!doctype html>
<html>
<head>
</head>
<body>
<script>(function(){
var props = {};
<body>
<script>
!function() {
var names = [];
var scanned = [];
var to_scan = [];
function addObject(obj) {
if (obj == null) return;
try {
Object.getOwnPropertyNames(obj).forEach(add);
} catch(ex) {}
if (obj.prototype) {
Object.getOwnPropertyNames(obj.prototype).forEach(add);
}
if (typeof obj == "function") {
try {
Object.getOwnPropertyNames(new obj).forEach(add);
} catch(ex) {}
}
}
function scan(obj) {
if (obj && typeof obj == "object" && !~scanned.indexOf(obj)) {
scanned.push(obj);
to_scan.push(obj);
}
}
function add(name) {
props[name] = true;
}
scan(self);
[
"a",
"abbr",
"acronym",
"address",
"applet",
"area",
"article",
"aside",
"audio",
"b",
"base",
"basefont",
"bdi",
"bdo",
"bgsound",
"big",
"blink",
"blockquote",
"body",
"br",
"button",
"canvas",
"caption",
"center",
"checked",
"cite",
"code",
"col",
"colgroup",
"command",
"comment",
"compact",
"content",
"data",
"datalist",
"dd",
"declare",
"defer",
"del",
"details",
"dfn",
"dialog",
"dir",
"disabled",
"div",
"dl",
"dt",
"element",
"em",
"embed",
"fieldset",
"figcaption",
"figure",
"font",
"footer",
"form",
"frame",
"frameset",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"head",
"header",
"hgroup",
"hr",
"html",
"i",
"iframe",
"image",
"img",
"input",
"ins",
"isindex",
"ismap",
"kbd",
"keygen",
"label",
"legend",
"li",
"link",
"listing",
"main",
"map",
"mark",
"marquee",
"math",
"menu",
"menuitem",
"meta",
"meter",
"multicol",
"multiple",
"nav",
"nobr",
"noembed",
"noframes",
"nohref",
"noresize",
"noscript",
"noshade",
"nowrap",
"object",
"ol",
"optgroup",
"option",
"output",
"p",
"param",
"picture",
"plaintext",
"pre",
"progress",
"q",
"rb",
"readonly",
"rp",
"rt",
"rtc",
"ruby",
"s",
"samp",
"script",
"section",
"select",
"selected",
"shadow",
"small",
"source",
"spacer",
"span",
"strike",
"strong",
"style",
"sub",
"summary",
"sup",
"svg",
"table",
"tbody",
"td",
"template",
"textarea",
"tfoot",
"th",
"thead",
"time",
"title",
"tr",
"track",
"tt",
"u",
"ul",
"var",
"video",
"wbr",
"xmp",
"XXX",
].forEach(function(tag) {
scan(document.createElement(tag));
});
[
"abort",
"absolutedeviceorientation",
"activate",
"active",
"addsourcebuffer",
"addstream",
"addtrack",
"afterprint",
"afterscriptexecute",
"afterupdate",
"animationcancel",
"animationend",
"animationiteration",
"animationstart",
"appinstalled",
"audioend",
"audioprocess",
"audiostart",
"autocomplete",
"autocompleteerror",
"auxclick",
"beforeactivate",
"beforecopy",
"beforecut",
"beforedeactivate",
"beforeeditfocus",
"beforeinstallprompt",
"beforepaste",
"beforeprint",
"beforescriptexecute",
"beforeunload",
"beforeupdate",
"blocked",
"blur",
"bounce",
"boundary",
"cached",
"cancel",
"candidatewindowhide",
"candidatewindowshow",
"candidatewindowupdate",
"canplay",
"canplaythrough",
"cellchange",
"change",
"chargingchange",
"chargingtimechange",
"checking",
"click",
"close",
"compassneedscalibration",
"complete",
"connect",
"connecting",
"connectionstatechange",
"contextmenu",
"controllerchange",
"controlselect",
"copy",
"cuechange",
"cut",
"dataavailable",
"datachannel",
"datasetchanged",
"datasetcomplete",
"dblclick",
"deactivate",
"devicechange",
"devicelight",
"devicemotion",
"deviceorientation",
"deviceorientationabsolute",
"deviceproximity",
"dischargingtimechange",
"disconnect",
"display",
"downloading",
"drag",
"dragend",
"dragenter",
"dragexit",
"dragleave",
"dragover",
"dragstart",
"drop",
"durationchange",
"emptied",
"encrypted",
"end",
"ended",
"enter",
"enterpictureinpicture",
"error",
"errorupdate",
"exit",
"filterchange",
"finish",
"focus",
"focusin",
"focusout",
"freeze",
"fullscreenchange",
"fullscreenerror",
"gesturechange",
"gestureend",
"gesturestart",
"gotpointercapture",
"hashchange",
"help",
"icecandidate",
"iceconnectionstatechange",
"icegatheringstatechange",
"inactive",
"input",
"invalid",
"keydown",
"keypress",
"keyup",
"languagechange",
"layoutcomplete",
"leavepictureinpicture",
"levelchange",
"load",
"loadeddata",
"loadedmetadata",
"loadend",
"loading",
"loadingdone",
"loadingerror",
"loadstart",
"losecapture",
"lostpointercapture",
"mark",
"message",
"messageerror",
"mousedown",
"mouseenter",
"mouseleave",
"mousemove",
"mouseout",
"mouseover",
"mouseup",
"mousewheel",
"move",
"moveend",
"movestart",
"mozfullscreenchange",
"mozfullscreenerror",
"mozorientationchange",
"mozpointerlockchange",
"mozpointerlockerror",
"mscontentzoom",
"msfullscreenchange",
"msfullscreenerror",
"msgesturechange",
"msgesturedoubletap",
"msgestureend",
"msgesturehold",
"msgesturestart",
"msgesturetap",
"msgotpointercapture",
"msinertiastart",
"mslostpointercapture",
"msmanipulationstatechanged",
"msneedkey",
"msorientationchange",
"mspointercancel",
"mspointerdown",
"mspointerenter",
"mspointerhover",
"mspointerleave",
"mspointermove",
"mspointerout",
"mspointerover",
"mspointerup",
"mssitemodejumplistitemremoved",
"msthumbnailclick",
"negotiationneeded",
"nomatch",
"noupdate",
"obsolete",
"offline",
"online",
"open",
"orientationchange",
"pagechange",
"pagehide",
"pageshow",
"paste",
"pause",
"play",
"playing",
"pluginstreamstart",
"pointercancel",
"pointerdown",
"pointerenter",
"pointerleave",
"pointerlockchange",
"pointerlockerror",
"pointermove",
"pointerout",
"pointerover",
"pointerup",
"popstate",
"progress",
"propertychange",
"ratechange",
"reading",
"readystatechange",
"rejectionhandled",
"removesourcebuffer",
"removestream",
"removetrack",
"reset",
"resize",
"resizeend",
"resizestart",
"resourcetimingbufferfull",
"result",
"resume",
"rowenter",
"rowexit",
"rowsdelete",
"rowsinserted",
"scroll",
"search",
"seeked",
"seeking",
"select",
"selectionchange",
"selectstart",
"show",
"signalingstatechange",
"soundend",
"soundstart",
"sourceclose",
"sourceclosed",
"sourceended",
"sourceopen",
"speechend",
"speechstart",
"stalled",
"start",
"statechange",
"stop",
"storage",
"storagecommit",
"submit",
"success",
"suspend",
"textinput",
"timeout",
"timeupdate",
"toggle",
"touchcancel",
"touchend",
"touchmove",
"touchstart",
"track",
"transitioncancel",
"transitionend",
"transitionrun",
"transitionstart",
"unhandledrejection",
"unload",
"updateready",
"upgradeneeded",
"userproximity",
"versionchange",
"visibilitychange",
"voiceschanged",
"volumechange",
"vrdisplayactivate",
"vrdisplayconnect",
"vrdisplaydeactivate",
"vrdisplaydisconnect",
"vrdisplaypresentchange",
"waiting",
"waitingforkey",
"warning",
"webkitanimationend",
"webkitanimationiteration",
"webkitanimationstart",
"webkitcurrentplaybacktargetiswirelesschanged",
"webkitfullscreenchange",
"webkitfullscreenerror",
"webkitkeyadded",
"webkitkeyerror",
"webkitkeymessage",
"webkitneedkey",
"webkitorientationchange",
"webkitplaybacktargetavailabilitychanged",
"webkitpointerlockchange",
"webkitpointerlockerror",
"webkitresourcetimingbufferfull",
"webkittransitionend",
"wheel",
"zoom",
].forEach(function(type) {
[
"beforeunloadevent",
"compositionevent",
"customevent",
"devicemotionevent",
"deviceorientationevent",
"dragevent",
"event",
"events",
"focusevent",
"hashchangeevent",
"htmlevents",
"keyboardevent",
"messageevent",
"mouseevent",
"mouseevents",
"storageevent",
"svgevents",
"textevent",
"touchevent",
"uievent",
"uievents",
].forEach(function(interface) {
try {
var event = document.createEvent(interface);
event.initEvent(type, true, true);
scan(event);
} catch (e) {}
});
});
Object.getOwnPropertyNames(window).forEach(function(thing){
addObject(window[thing]);
});
try {
addObject(new Event("click"));
addObject(new Event("contextmenu"));
addObject(new Event("mouseup"));
addObject(new Event("mousedown"));
addObject(new Event("keydown"));
addObject(new Event("keypress"));
addObject(new Event("keyup"));
} catch(ex) {}
var ta = document.createElement("textarea");
ta.style.width = "100%";
ta.style.height = "20em";
ta.style.boxSizing = "border-box";
<!-- ta.value = Object.keys(props).sort(cmp).map(function(name){ -->
<!-- return JSON.stringify(name); -->
<!-- }).join(",\n"); -->
ta.value = JSON.stringify({
vars: [],
props: Object.keys(props).sort(cmp)
}, null, 2);
document.body.appendChild(ta);
function cmp(a, b) {
a = a.toLowerCase();
b = b.toLowerCase();
return a < b ? -1 : a > b ? 1 : 0;
}
})();</script>
</body>
var obj;
while (obj = to_scan.shift()) {
var proto = obj;
do {
Object.getOwnPropertyNames(proto).forEach(function(name) {
var visited = ~names.indexOf(name);
if (!visited) names.push(name);
try {
scan(obj[name]);
if (visited) return;
if (/^create/.test(name)) {
scan(obj[name]());
}
if (/^[A-Z]/.test(name)) {
scan(new obj[name]());
}
} catch (e) {}
});
} while (proto = Object.getPrototypeOf(proto));
}
names.sort();
document.write('<pre>[\n "');
document.write(names.join('",\n "'));
document.write('"\n]</pre>');
}();
</script>
</body>
</html>