Compare commits

...

35 Commits

Author SHA1 Message Date
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
30 changed files with 2425 additions and 289 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`
@@ -664,7 +666,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;

File diff suppressed because it is too large Load Diff

View File

@@ -758,17 +758,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 +792,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 +1073,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 +1123,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 +1134,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 +1145,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 +1153,7 @@ function parse($TEXT, options) {
body : cur
});
a.push(branch);
}
else {
} else {
if (!cur) unexpected();
cur.push(statement());
}
@@ -1420,10 +1422,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 +1627,7 @@ function parse($TEXT, options) {
}
if (options.expression) {
handle_regexp();
return expression(true);
}

View File

@@ -309,8 +309,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;

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.0",
"engines": {
"node": ">=0.8.0"
},
@@ -23,12 +23,12 @@
"LICENSE"
],
"dependencies": {
"commander": "~2.16.0",
"commander": "~2.19.0",
"source-map": "~0.6.1"
},
"devDependencies": {
"acorn": "~5.7.1",
"semver": "~5.5.0"
"acorn": "~6.1.1",
"semver": "~5.6.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,52 @@ 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"
}

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; }
}
}
@@ -5827,3 +5827,297 @@ 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"
}

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,26 @@ 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"
}

View File

@@ -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,47 @@ 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"
}

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,356 @@ 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",
]
}

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

@@ -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

@@ -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,310 @@ 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"
}

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

@@ -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

@@ -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 });