Compare commits

..

37 Commits

Author SHA1 Message Date
Alex Lam S.L
9e2290b29c Merge pull request #1636 from alexlamsl/harmony-v2.8.15
Merging from master for 2.8.15
2017-03-23 16:08:53 +08:00
alexlamsl
97d0fc271d Merge branch 'master' into harmony-v2.8.15 2017-03-23 15:28:17 +08:00
Alex Lam S.L
6b2f34769a v2.8.15 2017-03-23 13:36:47 +08:00
Alex Lam S.L
48ffbef51d account for cross-scope modifications in collapse_vars (#1634)
mostly done by @kzc

fixes #1631
2017-03-23 07:17:34 +08:00
Alex Lam S.L
c0f3feae9f introduce compressor.info() (#1633)
report the following only when `options.warnings = "verbose"`
- unused elements due to inlining
- collpased variables
2017-03-23 06:49:49 +08:00
Alex Lam S.L
a00040dd93 fix a bug in simple_glob (#1632)
- "?" should not match "/"
- other minor clean-ups
2017-03-23 06:11:16 +08:00
Alex Lam S.L
ee95c1b38b metadata cleanup (#1630)
- mention performance anomaly in Node 7 and drop from CI
- remove unused npm "scripts"
- mark browserify dependency as optional
- stop `test/mozilla-ast.js` from spamming console output in later versions of Node.js
2017-03-23 01:31:46 +08:00
Alex Lam S.L
4bceb85cbf throw parse error on invalid assignments (#1627)
fixes #1626
2017-03-21 14:11:32 +08:00
Alex Lam S.L
7906033e82 Merge pull request #1624 from alexlamsl/harmony-v2.8.14
Merging from master for 2.8.14
2017-03-19 18:24:29 +08:00
alexlamsl
4bf21ce5c1 add expect_stdout to tests 2017-03-19 15:35:39 +08:00
alexlamsl
44d6b47bdc Merge branch 'master' into harmony-v2.8.14 2017-03-19 15:31:18 +08:00
Alex Lam S.L
30a75049f5 v2.8.14 2017-03-19 15:24:57 +08:00
Alex Lam S.L
a3cc3a9b87 make expect_stdout work on Node.js 0.12 (#1623)
That particular version of Node.js has messed up error messages, so provide a version-specific workaround.

Also fixed an formatting issue which would cause `expect_stdout` to fail if error message contains excerpts of input.

Apply `expect_stdout` to more applicable tests.
2017-03-19 12:00:32 +08:00
Alex Lam S.L
96f8befdd7 fix commit 88fb83a (#1622)
The following is wrong:
    `a == (b ? a : c)` => `b`
Because:
- `b` may not be boolean
- `a` might have side effects
- `a == a` is not always `true` (think `NaN`)
- `a == c` is not always `false`
2017-03-19 11:59:42 +08:00
Alex Lam S.L
cd58635dcc fix AST_Binary.lift_sequences() (#1621)
Commit eab99a1c fails to account for side effects from compound assignments.
2017-03-19 03:04:22 +08:00
Alex Lam S.L
274331d0ea transform String.charAt() to index access (#1620)
Guarded by `unsafe` as `charAt()` can be overridden.
2017-03-19 02:17:15 +08:00
Alex Lam S.L
129e449c8e Merge pull request #1614 from alexlamsl/harmony-v2.8.13
Merging from master for 2.8.13
2017-03-18 13:02:09 +08:00
alexlamsl
75c3c8963f Merge branch 'master' into harmony-v2.8.13 2017-03-18 02:52:45 +08:00
Alex Lam S.L
0489d6de64 handle runtime errors in expect_stdout (#1618)
allow test to pass if both `input` and `expect` throws the same kind of error
2017-03-18 02:33:51 +08:00
Alex Lam S.L
fb092839c2 fix top-level directives in compress tests (#1615)
`input` and `expect` are parsed as `AST_BlockStatement` which does not support `AST_Directive` by default.

Emulate that by transforming preceding `AST_SimpleStatement`s of `AST_String` into `AST_Directive`.
2017-03-18 01:56:15 +08:00
Alex Zaworski
d26b7522d9 Allow 'name' as object literal shorthand property (#1617)
fixes #1613
2017-03-18 01:29:13 +08:00
Christian Maughan Tegnér
b7c112eefe Add --in-source-map inline documentation (#1611) 2017-03-17 03:08:38 +08:00
Alex Lam S.L
b2b8a0d386 v2.8.13 2017-03-17 02:01:33 +08:00
Alex Lam S.L
ac40301813 fix chained evaluation (#1610)
`reduce_vars` enables substitution of variables but did not clone the value's `AST_Node`.

This confuses `collapse_vars` and result in invalid AST and subsequent crash.

fixes #1609
2017-03-17 00:26:48 +08:00
Alex Lam S.L
3563d8c09e extend test/run-tests.js to optionally execute uglified output (#1604)
fixes #1588
2017-03-16 23:20:06 +08:00
Alex Lam S.L
5ae04b3545 make collapse_vars consistent with toplevel (#1608)
fixes #1605
2017-03-16 13:22:26 +08:00
Alex Lam S.L
a80b228d8b fix hoist_vars on reduce_vars (#1607)
`hoist_vars` converts variable declarations into plain assignments, which then confuses `reduce_vars`

fixes #1606
2017-03-16 12:03:30 +08:00
Alex Lam S.L
cf4bf4ceb1 fix stack issues with AST_Node.evaluate() (#1603)
As patched in #1597, `make_node_from_constant()` makes inconsistent and sometimes incorrect calls to `optimize()` and `transform()`.

Fix those issues properly by changing the semantics of `evaluate()` and `make_node_from_constant()`, with the side effect that `evaluate()` no longer eagerly converts constant to `AST_Node`.
2017-03-16 01:02:59 +08:00
Alex Lam S.L
8223b2e0db fix AST_Node.optimize() (#1602)
Liberal use of `Compressor.transform()` and `AST_Node.optimize()` presents an issue for look-up operations like `TreeWalker.in_boolean_context()` and `TreeWalker.parent()`.

This is an incremental fix such that `AST_Node.optimize()` would now contain the correct stack information when called correctly.
2017-03-15 18:44:13 +08:00
Alex Lam S.L
2fd86d3cb0 Merge pull request #1601 from alexlamsl/harmony-v2.8.12
Merging from master for 2.8.12
2017-03-14 14:29:32 +08:00
Alex Lam S.L
381bd3836e minor clean-ups (#1600)
- remove obsolete optimisation in `AST_Binary` after #1477
- improve `TreeWalker.has_directive()` readability and resilience against multiple visits
2017-03-14 13:19:05 +08:00
alexlamsl
8f7ab602e2 Merge branch 'master' into harmony-v2.8.12 2017-03-14 13:17:42 +08:00
Alex Lam S.L
1dd339f95e fix unused crashes (#1599)
- `AST_DefaultAssign` on `keep_fargs`
- `AST_Expansion on` `keep_fargs`
- `AST_Destructuring` on top-level declarations without `toplevel`
2017-03-14 13:13:43 +08:00
Alex Lam S.L
919d5e3482 v2.8.12 2017-03-11 05:00:55 +08:00
Alex Lam S.L
e3a3db73ae temporary fix for boolean bug (#1597)
fixes #1592
2017-03-11 04:59:55 +08:00
Alex Lam S.L
d9344f30b8 disallow parameter substitution for named IIFEs (#1596)
Self-referenced function has non-fixed values assigned to its parameters.

Let `unused` & `!keep_fnames` do the scanning, then apply `reduce_vars` only to unnamed functions.

fixes #1595
2017-03-11 03:34:55 +08:00
Alex Lam S.L
be80f7e706 support multi-line string in tests (#1590)
`expect_exact` sometimes have multiple lines and `\n` are hard to read.

Use array of strings to emulate line breaks and improve readability.
2017-03-10 11:27:30 +08:00
48 changed files with 1503 additions and 478 deletions

View File

@@ -5,7 +5,6 @@ node_js:
- "0.12"
- "4"
- "6"
- "7"
env:
- UGLIFYJS_TEST_ALL=1
matrix:

View File

@@ -10,8 +10,10 @@ There's also an
[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox,
Chrome and probably Safari).
Note: release versions of `uglify-js` only support ECMAScript 5 (ES5). If you wish to minify
#### Note:
- release versions of `uglify-js` only support ECMAScript 5 (ES5). If you wish to minify
ES2015+ (ES6+) code then please use the [harmony](#harmony) development branch.
- Node 7 has a known performance regression and runs `uglify-js` twice as slow.
Install
-------
@@ -68,7 +70,8 @@ The available options are:
--source-map-inline Write base64-encoded source map to the end of js output.
--in-source-map Input source map, useful if you're compressing
JS that was generated from some other original
code.
code. Specify "inline" if the source map is included
inline with the sources.
--screw-ie8 Use this flag if you don't wish to support
Internet Explorer 6/7/8.
By default UglifyJS will not try to be IE-proof.
@@ -200,9 +203,10 @@ compressed JS by mapping every token in the compiled JS to its original
location.
To use this feature you need to pass `--in-source-map
/path/to/input/source.map`. Normally the input source map should also point
to the file containing the generated JS, so if that's correct you can omit
input files from the command line.
/path/to/input/source.map` or `--in-source-map inline` if the source map is
included inline with the sources. Normally the input source map should also
point to the file containing the generated JS, so if that's correct you can
omit input files from the command line.
## Mangler options

View File

@@ -814,9 +814,6 @@ var AST_VarDef = DEFNODE("VarDef", "name value", {
name: "[AST_SymbolVar|AST_SymbolConst|AST_Destructuring] name of the variable",
value: "[AST_Node?] initializer, or null of there's no initializer"
},
is_destructuring: function() {
return this.name instanceof AST_Destructuring;
},
_walk: function(visitor) {
return visitor._visit(this, function(){
this.name._walk(visitor);
@@ -1323,11 +1320,13 @@ TreeWalker.prototype = {
push: function (node) {
if (node instanceof AST_Lambda) {
this.directives = Object.create(this.directives);
} else if (node instanceof AST_Directive) {
this.directives[node.value] = this.directives[node.value] ? "up" : true;
} else if (node instanceof AST_Directive && !this.directives[node.value]) {
this.directives[node.value] = node;
} else if (node instanceof AST_Class) {
this.directives = Object.create(this.directives);
this.directives["use strict"] = this.directives["use strict"] ? "up" : true;
if (!this.directives["use strict"]) {
this.directives["use strict"] = node;
}
}
this.stack.push(node);
},
@@ -1355,7 +1354,7 @@ TreeWalker.prototype = {
for (var i = 0; i < node.body.length; ++i) {
var st = node.body[i];
if (!(st instanceof AST_Directive)) break;
if (st.value == type) return true;
if (st.value == type) return st;
}
}
},

File diff suppressed because it is too large Load Diff

View File

@@ -1998,7 +1998,6 @@ function parse($TEXT, options) {
// allow trailing comma
break;
start = S.token;
var type = start.type;
var name = as_property_name();
var value;
@@ -2009,9 +2008,6 @@ function parse($TEXT, options) {
a.push(concise);
continue;
}
if (!(start.type !== name)) {
unexpected(S.token);
}
value = new AST_SymbolRef({
start: prev(),
@@ -2471,12 +2467,52 @@ function parse($TEXT, options) {
};
function is_assignable(expr) {
if (!options.strict) return true;
if (expr instanceof AST_This) return false;
if (expr instanceof AST_Super) return false;
return (expr instanceof AST_PropAccess || expr instanceof AST_Symbol);
return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef;
};
function to_destructuring(node) {
if (node instanceof AST_Object) {
node = new AST_Destructuring({
start: node.start,
names: node.properties.map(to_destructuring),
is_array: false,
end: node.end
});
} else if (node instanceof AST_Array) {
var names = [];
for (var i = 0; i < node.elements.length; i++) {
// Only allow expansion as last element
if (node.elements[i] instanceof AST_Expansion) {
if (i + 1 !== node.elements.length) {
token_error(node.elements[i].start, "Spread must the be last element in destructuring array");
}
node.elements[i].expression = to_destructuring(node.elements[i].expression);
}
names.push(to_destructuring(node.elements[i]));
}
node = new AST_Destructuring({
start: node.start,
names: names,
is_array: true,
end: node.end
});
} else if (node instanceof AST_ObjectProperty) {
node.value = to_destructuring(node.value);
} else if (node instanceof AST_Assign) {
node = new AST_DefaultAssign({
start: node.start,
left: node.left,
operator: "=",
right: node.right,
end: node.end
});
}
return node;
}
// In ES6, AssignmentExpression can also be an ArrowFunction
var maybe_assign = function(no_in) {
var start = S.token;
@@ -2510,56 +2546,7 @@ function parse($TEXT, options) {
var val = S.token.value;
if (is("operator") && ASSIGNMENT(val)) {
if (is_assignable(left)) {
var walk = function(node) {
var newNode;
if (node instanceof AST_Object) {
newNode = new AST_Destructuring({
start: node.start,
names: node.properties.map(walk),
is_array: false,
end: node.end
});
node = newNode;
} else if (node instanceof AST_Array) {
var names = [];
for (var i = 0; i < node.elements.length; i++) {
// Only allow expansion as last element
if (node.elements[i] instanceof AST_Expansion) {
if (i + 1 !== node.elements.length) {
token_error(node.elements[i].start, "Spread must the be last element in destructuring array");
}
node.elements[i].expression = walk(node.elements[i].expression);
}
names.push(walk(node.elements[i]));
}
newNode = new AST_Destructuring({
start: node.start,
names: names,
is_array: true,
end: node.end
});
node = newNode;
} else if (node instanceof AST_ObjectProperty) {
node.value = walk(node.value);
} else if (node instanceof AST_Assign) {
node = new AST_DefaultAssign({
start: node.start,
left: node.left,
operator: "=",
right: node.right,
end: node.end
});
}
return node;
}
left = walk(left);
if (is_assignable(left) || (left = to_destructuring(left)) instanceof AST_Destructuring) {
next();
return new AST_Assign({
start : start,

View File

@@ -279,7 +279,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
if (node instanceof AST_SymbolCatch) {
var name = node.name;
var refs = node.thedef.references;
var scope = node.thedef.scope.parent_scope;
var scope = node.thedef.scope.parent_scope.parent_scope;
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
refs.forEach(function(ref) {
ref.thedef = def;

View File

@@ -126,9 +126,11 @@ function merge(obj, ext) {
return count;
};
function noop() {};
function noop() {}
function return_false() { return false; }
function return_true() { return true; }
function return_this() { return this; }
function return_null() { return null; }
var MAP = (function(){
function MAP(a, f, backwards) {

View File

@@ -4,7 +4,7 @@
"homepage": "http://lisperator.net/uglifyjs",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "2.8.11",
"version": "2.8.15",
"engines": {
"node": ">=0.8.0"
},
@@ -30,7 +30,6 @@
],
"dependencies": {
"source-map": "~0.5.1",
"uglify-to-browserify": "~1.0.0",
"yargs": "~3.10.0"
},
"devDependencies": {
@@ -40,13 +39,15 @@
"estraverse": "~1.5.1",
"mocha": "~2.3.4"
},
"optionalDependencies": {
"uglify-to-browserify": "~1.0.0"
},
"browserify": {
"transform": [
"uglify-to-browserify"
]
},
"scripts": {
"shrinkwrap": "rm ./npm-shrinkwrap.json; rm -rf ./node_modules; npm i && npm shrinkwrap && npm outdated",
"test": "node test/run-tests.js"
},
"keywords": ["uglify", "uglify-js", "minify", "minifier"]

View File

@@ -43,6 +43,7 @@ collapse_vars_side_effects_1: {
z = i += 4;
log(x, z, y, i);
}
f1(), f2(), f3(), f4();
}
expect: {
function f1() {
@@ -73,7 +74,9 @@ collapse_vars_side_effects_1: {
y = i += 3;
log(x, i += 4, y, i);
}
f1(), f2(), f3(), f4();
}
expect_stdout: true
}
collapse_vars_side_effects_2: {
@@ -823,6 +826,7 @@ collapse_vars_repeated: {
console.log(e + "!");
})("!");
}
expect_stdout: true
}
collapse_vars_closures: {
@@ -1109,6 +1113,7 @@ collapse_vars_eval_and_with: {
return function() { with (o) console.log(a) };
})()();
}
expect_stdout: true
}
collapse_vars_constants: {
@@ -1152,7 +1157,8 @@ collapse_vars_arguments: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
toplevel:true
}
input: {
var outer = function() {
@@ -1167,6 +1173,7 @@ collapse_vars_arguments: {
(function(){console.log(arguments);})(7, 1);
})();
}
expect_stdout: true
}
collapse_vars_short_circuit: {
@@ -1316,11 +1323,13 @@ collapse_vars_regexp: {
console.log(result[0]);
})();
}
expect_stdout: true
}
issue_1537: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var k = '';
@@ -1335,6 +1344,7 @@ issue_1537: {
issue_1537_for_of: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var k = '';
@@ -1349,6 +1359,7 @@ issue_1537_for_of: {
issue_1537_destructuring_1: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var x = 1, y = 2;
@@ -1363,6 +1374,7 @@ issue_1537_destructuring_1: {
issue_1537_destructuring_2: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var x = foo();
@@ -1377,6 +1389,7 @@ issue_1537_destructuring_2: {
issue_1537_destructuring_3: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var x = Math.random();
@@ -1391,6 +1404,7 @@ issue_1537_destructuring_3: {
issue_1537_destructuring_for_in: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var x = 1, y = 2;
@@ -1409,6 +1423,7 @@ issue_1537_destructuring_for_in: {
issue_1537_destructuring_for_of: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var x = 1, y = 2;
@@ -1427,6 +1442,7 @@ issue_1537_destructuring_for_of: {
issue_1562: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var v = 1, B = 2;
@@ -1455,3 +1471,153 @@ issue_1562: {
for (; f(z + 2) ;) bar(30);
}
}
issue_1605_1: {
options = {
collapse_vars: true,
toplevel: false,
}
input: {
function foo(x) {
var y = x;
return y;
}
var o = new Object;
o.p = 1;
}
expect: {
function foo(x) {
return x;
}
var o = new Object;
o.p = 1;
}
}
issue_1605_2: {
options = {
collapse_vars: true,
toplevel: "vars",
}
input: {
function foo(x) {
var y = x;
return y;
}
var o = new Object;
o.p = 1;
}
expect: {
function foo(x) {
return x;
}
(new Object).p = 1;
}
}
issue_1631_1: {
options = {
cascade: true,
collapse_vars: true,
hoist_funs: true,
join_vars: true,
sequences: true,
side_effects: true,
}
input: {
var pc = 0;
function f(x) {
pc = 200;
return 100;
}
function x() {
var t = f();
pc += t;
return pc;
}
console.log(x());
}
expect: {
function f(x) {
return pc = 200, 100;
}
function x() {
var t = f();
return pc += t;
}
var pc = 0;
console.log(x());
}
expect_stdout: "300"
}
issue_1631_2: {
options = {
cascade: true,
collapse_vars: true,
hoist_funs: true,
join_vars: true,
sequences: true,
side_effects: true,
}
input: {
var a = 0, b = 1;
function f() {
a = 2;
return 4;
}
function g() {
var t = f();
b = a + t;
return b;
}
console.log(g());
}
expect: {
function f() {
return a = 2, 4;
}
function g() {
var t = f();
return b = a + t;
}
var a = 0, b = 1;
console.log(g());
}
expect_stdout: "6"
}
issue_1631_3: {
options = {
cascade: true,
collapse_vars: true,
hoist_funs: true,
join_vars: true,
sequences: true,
side_effects: true,
}
input: {
function g() {
var a = 0, b = 1;
function f() {
a = 2;
return 4;
}
var t = f();
b = a + t;
return b;
}
console.log(g());
}
expect: {
function g() {
function f() {
return a = 2, 4;
}
var a = 0, b = 1, t = f();
return b = a + t;
}
console.log(g());
}
expect_stdout: "6"
}

View File

@@ -51,6 +51,7 @@ concat_2: {
"1" + "2" + "3"
);
}
expect_stdout: true
}
concat_3: {
@@ -79,6 +80,7 @@ concat_3: {
1 + 2 + "3" + "4" + "5"
);
}
expect_stdout: true
}
concat_4: {
@@ -107,6 +109,7 @@ concat_4: {
1 + "2" + "3" + "4" + "5"
);
}
expect_stdout: true
}
concat_5: {
@@ -135,6 +138,7 @@ concat_5: {
"1" + 2 + "3" + "4" + "5"
);
}
expect_stdout: true
}
concat_6: {
@@ -163,6 +167,7 @@ concat_6: {
"1" + "2" + "3" + "4" + "5"
);
}
expect_stdout: true
}
concat_7: {
@@ -188,6 +193,7 @@ concat_7: {
x += "foo"
);
}
expect_stdout: true
}
concat_8: {
@@ -213,4 +219,5 @@ concat_8: {
x += "foo"
);
}
expect_stdout: true
}

View File

@@ -797,3 +797,99 @@ no_evaluate: {
}
}
}
equality_conditionals_false: {
options = {
conditionals: false,
sequences: true,
}
input: {
function f(a, b, c) {
console.log(
a == (b ? a : a),
a == (b ? a : c),
a != (b ? a : a),
a != (b ? a : c),
a === (b ? a : a),
a === (b ? a : c),
a !== (b ? a : a),
a !== (b ? a : c)
);
}
f(0, 0, 0);
f(0, true, 0);
f(1, 2, 3);
f(1, null, 3);
f(NaN);
f(NaN, "foo");
}
expect: {
function f(a, b, c) {
console.log(
a == (b ? a : a),
a == (b ? a : c),
a != (b ? a : a),
a != (b ? a : c),
a === (b ? a : a),
a === (b ? a : c),
a !== (b ? a : a),
a !== (b ? a : c)
);
}
f(0, 0, 0),
f(0, true, 0),
f(1, 2, 3),
f(1, null, 3),
f(NaN),
f(NaN, "foo");
}
expect_stdout: true
}
equality_conditionals_true: {
options = {
conditionals: true,
sequences: true,
}
input: {
function f(a, b, c) {
console.log(
a == (b ? a : a),
a == (b ? a : c),
a != (b ? a : a),
a != (b ? a : c),
a === (b ? a : a),
a === (b ? a : c),
a !== (b ? a : a),
a !== (b ? a : c)
);
}
f(0, 0, 0);
f(0, true, 0);
f(1, 2, 3);
f(1, null, 3);
f(NaN);
f(NaN, "foo");
}
expect: {
function f(a, b, c) {
console.log(
(b, a == a),
a == (b ? a : c),
(b, a != a),
a != (b ? a : c),
(b, a === a),
a === (b ? a : c),
(b, a !== a),
a !== (b ? a : c)
);
}
f(0, 0, 0),
f(0, true, 0),
f(1, 2, 3),
f(1, null, 3),
f(NaN),
f(NaN, "foo");
}
expect_stdout: true
}

View File

@@ -162,4 +162,5 @@ regexp_literal_not_const: {
while (result = REGEXP_LITERAL.exec("acdabcdeabbb")) console.log(result[0]);
})();
}
expect_stdout: true
}

View File

@@ -87,6 +87,7 @@ dead_code_constant_boolean_should_warn_more: {
var x = 10, y;
var moo;
}
expect_stdout: true
}
dead_code_block_decls_die: {
@@ -135,6 +136,7 @@ dead_code_const_declaration: {
var moo;
function bar() {}
}
expect_stdout: true
}
dead_code_const_annotation: {
@@ -162,6 +164,7 @@ dead_code_const_annotation: {
var moo;
function bar() {}
}
expect_stdout: true
}
dead_code_const_annotation_regex: {
@@ -185,6 +188,7 @@ dead_code_const_annotation_regex: {
var CONST_FOO_ANN = !1;
CONST_FOO_ANN && console.log('reachable');
}
expect_stdout: true
}
dead_code_const_annotation_complex_scope: {
@@ -230,4 +234,5 @@ dead_code_const_annotation_complex_scope: {
var meat = 'beef';
var pork = 'bad';
}
expect_stdout: true
}

View File

@@ -293,3 +293,17 @@ reduce_vars: {
for ([x,y] in pairs);
}
}
unused: {
options = {
unused: true,
}
input: {
let { foo: [, , ...a] } = { foo: [1, 2, 3, 4], bar: 5 };
console.log(a);
}
expect: {
let { foo: [, , ...a] } = { foo: [1, 2, 3, 4], bar: 5 };
console.log(a);
}
}

View File

@@ -200,6 +200,7 @@ negative_zero: {
1 / (-0)
);
}
expect_stdout: true
}
positive_zero: {
@@ -220,6 +221,7 @@ positive_zero: {
1 / (0)
);
}
expect_stdout: true
}
pow: {
@@ -337,6 +339,7 @@ unsafe_constant: {
(void 0).a
);
}
expect_stdout: true
}
unsafe_object: {
@@ -360,6 +363,7 @@ unsafe_object: {
1..b + 1
);
}
expect_stdout: true
}
unsafe_object_nested: {
@@ -383,6 +387,7 @@ unsafe_object_nested: {
2
);
}
expect_stdout: true
}
unsafe_object_complex: {
@@ -406,6 +411,7 @@ unsafe_object_complex: {
2
);
}
expect_stdout: true
}
unsafe_object_repeated: {
@@ -429,6 +435,7 @@ unsafe_object_repeated: {
1..b + 1
);
}
expect_stdout: true
}
unsafe_object_accessor: {
@@ -478,6 +485,7 @@ unsafe_function: {
({a:{b:1},b:function(){}}).a.b + 1
);
}
expect_stdout: true
}
unsafe_integer_key: {
@@ -505,6 +513,7 @@ unsafe_integer_key: {
1["1"] + 1
);
}
expect_stdout: true
}
unsafe_integer_key_complex: {
@@ -532,6 +541,7 @@ unsafe_integer_key_complex: {
2
);
}
expect_stdout: true
}
unsafe_float_key: {
@@ -559,6 +569,7 @@ unsafe_float_key: {
1["3.14"] + 1
);
}
expect_stdout: true
}
unsafe_float_key_complex: {
@@ -586,6 +597,7 @@ unsafe_float_key_complex: {
2
);
}
expect_stdout: true
}
unsafe_array: {
@@ -621,6 +633,7 @@ unsafe_array: {
(void 0)[1] + 1
);
}
expect_stdout: true
}
unsafe_string: {
@@ -648,6 +661,7 @@ unsafe_string: {
"11"
);
}
expect_stdout: true
}
unsafe_array_bad_index: {
@@ -669,6 +683,7 @@ unsafe_array_bad_index: {
[1, 2, 3, 4][3.14] + 1
);
}
expect_stdout: true
}
unsafe_string_bad_index: {
@@ -690,6 +705,7 @@ unsafe_string_bad_index: {
"1234"[3.14] + 1
);
}
expect_stdout: true
}
unsafe_prototype_function: {
@@ -736,6 +752,7 @@ call_args: {
console.log(1);
+(1, 1);
}
expect_stdout: true
}
call_args_drop_param: {
@@ -757,6 +774,7 @@ call_args_drop_param: {
console.log(1);
+(b, 1);
}
expect_stdout: true
}
in_boolean_context: {
@@ -794,4 +812,74 @@ in_boolean_context: {
(foo(), !1)
);
}
expect_stdout: true
}
unsafe_charAt: {
options = {
evaluate : true,
unsafe : true
}
input: {
console.log(
"1234" + 1,
"1234".charAt(0) + 1,
"1234".charAt(6 - 5) + 1,
("12" + "34").charAt(0) + 1,
("12" + "34").charAt(6 - 5) + 1,
[1, 2, 3, 4].join("").charAt(0) + 1
);
}
expect: {
console.log(
"12341",
"11",
"21",
"11",
"21",
"11"
);
}
expect_stdout: true
}
unsafe_charAt_bad_index: {
options = {
evaluate : true,
unsafe : true
}
input: {
console.log(
"1234".charAt() + 1,
"1234".charAt("a") + 1,
"1234".charAt(3.14) + 1
);
}
expect: {
console.log(
"11",
"11",
"41"
);
}
expect_stdout: true
}
unsafe_charAt_noop: {
options = {
evaluate : true,
unsafe : true
}
input: {
console.log(
s.charAt(0),
"string".charAt(x)
);
}
expect: {
console.log(
s.charAt(0),
"string".charAt(x)
);
}
}

View File

@@ -39,6 +39,7 @@ iifes_returning_constants_keep_fargs_true: {
console.log(6);
console.log((a(), b(), 6));
}
expect_stdout: true
}
iifes_returning_constants_keep_fargs_false: {
@@ -73,6 +74,7 @@ iifes_returning_constants_keep_fargs_false: {
console.log(6);
console.log((a(), b(), 6));
}
expect_stdout: true
}
issue_485_crashing_1530: {

View File

@@ -286,3 +286,48 @@ fat_arrow_as_param: {
}
expect_exact: "foo(x=>x);foo(x=>x,y=>y);foo(x=>(x,x));foo(x=>(x,x),y=>(y,y));"
}
default_assign: {
options = {
keep_fargs: false,
unused: true,
}
input: {
function f(a, b = 3) {
console.log(a);
}
}
expect: {
function f(a) {
console.log(a);
}
}
}
expansion: {
options = {
keep_fargs: false,
unused: true,
}
input: {
function f(a, ...b) {
console.log(a);
}
}
expect: {
function f(a) {
console.log(a);
}
}
}
issue_1613: {
mangle = { toplevel: true };
input: {
const name = 1;
const foo = {
name
};
}
expect_exact: "const n=1;const c={name:n};"
}

View File

@@ -47,22 +47,6 @@ html_comment_in_greater_than_or_equal: {
expect_exact: "function f(a,b){return a-- >=b}";
}
html_comment_in_right_shift_assign: {
input: {
// Note: illegal javascript
function f(a, b) { return a-- >>= b; }
}
expect_exact: "function f(a,b){return a-- >>=b}";
}
html_comment_in_zero_fill_right_shift_assign: {
input: {
// Note: illegal javascript
function f(a, b) { return a-- >>>= b; }
}
expect_exact: "function f(a,b){return a-- >>>=b}";
}
html_comment_in_string_literal: {
input: {
function f() { return "<!--HTML-->comment in<!--string literal-->"; }

View File

@@ -39,7 +39,7 @@ non_hoisted_function_after_return_2a: {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true,
collapse_vars: false, passes: 2
collapse_vars: false, passes: 2, warnings: "verbose"
}
input: {
function foo(x) {
@@ -75,7 +75,7 @@ non_hoisted_function_after_return_2a: {
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]"
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]",
]
}
@@ -114,8 +114,5 @@ non_hoisted_function_after_return_2b: {
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:101,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:95,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:97,16]"
]
}

View File

@@ -49,4 +49,3 @@ mangle_keep_fnames_true: {
}
}
}

View File

@@ -46,4 +46,5 @@ string_plus_optimization: {
}
foo();
}
expect_stdout: true
}

View File

@@ -14,6 +14,7 @@ issue_1321_no_debug: {
x["a"] = 2 * x.b;
console.log(x.b, x["a"]);
}
expect_stdout: true
}
issue_1321_debug: {
@@ -33,6 +34,7 @@ issue_1321_debug: {
x["_$foo$_"] = 2 * x.a;
console.log(x.a, x["_$foo$_"]);
}
expect_stdout: true
}
issue_1321_with_quoted: {
@@ -51,4 +53,5 @@ issue_1321_with_quoted: {
x["b"] = 2 * x.a;
console.log(x.a, x["b"]);
}
expect_stdout: true
}

View File

@@ -42,4 +42,5 @@ conditional_false_stray_else_in_loop: {
}
}
expect_exact: "for(var i=1;i<=4;++i)if(!(i<=2))console.log(i);"
expect_stdout: true
}

View File

@@ -13,9 +13,9 @@ same_variable_in_multiple_for_loop: {
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true
};
mangle = {};
collapse_vars: true,
}
mangle = {}
input: {
for (let i = 0; i < 3; i++) {
let a = 100;
@@ -38,6 +38,7 @@ same_variable_in_multiple_for_loop: {
}
}
}
expect_stdout: true
}
same_variable_in_multiple_forOf: {
@@ -55,9 +56,9 @@ same_variable_in_multiple_forOf: {
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true
};
mangle = {};
collapse_vars: true,
}
mangle = {}
input: {
var test = [ "a", "b", "c" ];
for (let tmp of test) {
@@ -75,10 +76,11 @@ same_variable_in_multiple_forOf: {
console.log(o);
let e;
e = [ "e", "f", "g" ];
for (let o of e)
for (let o of e)
console.log(o);
}
}
expect_stdout: true
}
same_variable_in_multiple_forIn: {
@@ -96,9 +98,9 @@ same_variable_in_multiple_forIn: {
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true
};
mangle = {};
collapse_vars: true,
}
mangle = {}
input: {
var test = [ "a", "b", "c" ];
for (let tmp in test) {
@@ -120,6 +122,7 @@ same_variable_in_multiple_forIn: {
console.log(o);
}
}
expect_stdout: true
}
different_variable_in_multiple_for_loop: {
@@ -137,9 +140,9 @@ different_variable_in_multiple_for_loop: {
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true
};
mangle = {};
collapse_vars: true,
}
mangle = {}
input: {
for (let i = 0; i < 3; i++) {
let a = 100;
@@ -162,6 +165,7 @@ different_variable_in_multiple_for_loop: {
}
}
}
expect_stdout: true
}
different_variable_in_multiple_forOf: {
@@ -179,9 +183,9 @@ different_variable_in_multiple_forOf: {
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true
};
mangle = {};
collapse_vars: true,
}
mangle = {}
input: {
var test = [ "a", "b", "c" ];
for (let tmp of test) {
@@ -203,6 +207,7 @@ different_variable_in_multiple_forOf: {
console.log(o);
}
}
expect_stdout: true
}
different_variable_in_multiple_forIn: {
@@ -220,9 +225,9 @@ different_variable_in_multiple_forIn: {
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true
};
mangle = {};
collapse_vars: true,
}
mangle = {}
input: {
var test = [ "a", "b", "c" ];
for (let tmp in test) {
@@ -244,6 +249,7 @@ different_variable_in_multiple_forIn: {
console.log(o);
}
}
expect_stdout: true
}
more_variable_in_multiple_for: {
@@ -261,9 +267,9 @@ more_variable_in_multiple_for: {
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true
};
mangle = {};
collapse_vars: true,
}
mangle = {}
input: {
for (let a = 9, i = 0; i < 20; i += a) {
let b = a++ + i;
@@ -281,5 +287,5 @@ more_variable_in_multiple_for: {
console.log(o, c, e, l, f);
}
}
expect_stdout: true
}

View File

@@ -0,0 +1,99 @@
screw_ie8: {
options = {
screw_ie8: true,
}
mangle = {
screw_ie8: true,
}
input: {
try { throw "foo"; } catch (x) { console.log(x); }
}
expect_exact: 'try{throw"foo"}catch(o){console.log(o)}'
expect_stdout: [
"foo"
]
}
support_ie8: {
options = {
screw_ie8: false,
}
mangle = {
screw_ie8: false,
}
input: {
try { throw "foo"; } catch (x) { console.log(x); }
}
expect_exact: 'try{throw"foo"}catch(x){console.log(x)}'
expect_stdout: "foo"
}
safe_undefined: {
options = {
conditionals: true,
if_return: true,
unsafe: false,
}
mangle = {}
input: {
var a, c;
console.log(function(undefined) {
return function() {
if (a)
return b;
if (c)
return d;
};
}(1)());
}
expect: {
var a, c;
console.log(function(n) {
return function() {
return a ? b : c ? d : void 0;
};
}(1)());
}
expect_stdout: true
}
unsafe_undefined: {
options = {
conditionals: true,
if_return: true,
unsafe: true,
}
mangle = {}
input: {
var a, c;
console.log(function(undefined) {
return function() {
if (a)
return b;
if (c)
return d;
};
}()());
}
expect: {
var a, c;
console.log(function(n) {
return function() {
return a ? b : c ? d : n;
};
}()());
}
expect_stdout: true
}
runtime_error: {
input: {
const a = 1;
console.log(a++);
}
expect: {
const a = 1;
console.log(a++);
}
expect_stdout: true
}

View File

@@ -0,0 +1,56 @@
chained_evaluation_1: {
options = {
collapse_vars: true,
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
var a = 1;
(function() {
var b = a, c;
c = f(b);
c.bar = b;
})();
})();
}
expect: {
(function() {
(function() {
var c;
c = f(1);
c.bar = 1;
})();
})();
}
}
chained_evaluation_2: {
options = {
collapse_vars: true,
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
var a = "long piece of string";
(function() {
var b = a, c;
c = f(b);
c.bar = b;
})();
})();
}
expect: {
(function() {
var a = "long piece of string";
(function() {
var c;
c = f(a);
c.bar = a;
})();
})();
}
}

View File

@@ -48,6 +48,7 @@ dead_code_const_annotation_regex: {
var CONST_FOO_ANN = !1;
if (CONST_FOO_ANN) console.log('reachable');
}
expect_stdout: true
}
drop_console_2: {
@@ -225,6 +226,7 @@ issue_1254_negate_iife_true: {
})()();
}
expect_exact: '(function(){return function(){console.log("test")}})()();'
expect_stdout: true
}
issue_1254_negate_iife_nested: {
@@ -240,6 +242,7 @@ issue_1254_negate_iife_nested: {
})()()()()();
}
expect_exact: '(function(){return function(){console.log("test")}})()()()()();'
expect_stdout: true
}
conditional: {

View File

@@ -29,4 +29,5 @@ dont_mangle_arguments: {
})(5,6,7);
}
expect_exact: "(function(){var arguments=arguments,o=9;console.log(o,arguments)})(5,6,7);"
expect_stdout: true
}

View File

@@ -50,6 +50,7 @@ this_binding_conditionals: {
this_binding_collapse_vars: {
options = {
collapse_vars: true,
toplevel: true,
};
input: {
var c = a; c();

View File

@@ -42,6 +42,7 @@ eval_collapse_vars: {
eval("console.log(a);");
})(eval);
}
expect_stdout: true
}
eval_unused: {

View File

@@ -9,6 +9,7 @@ labels_1: {
expect: {
foo || console.log("bar");
}
expect_stdout: true
}
labels_2: {
@@ -40,6 +41,7 @@ labels_3: {
for (var i = 0; i < 5; ++i)
i < 3 || console.log(i);
}
expect_stdout: true
}
labels_4: {
@@ -54,6 +56,7 @@ labels_4: {
for (var i = 0; i < 5; ++i)
i < 3 || console.log(i);
}
expect_stdout: true
}
labels_5: {

View File

@@ -166,6 +166,7 @@ keep_collapse_const_in_own_block_scope: {
console.log(i);
console.log(c);
}
expect_stdout: true
}
keep_collapse_const_in_own_block_scope_2: {
@@ -186,6 +187,7 @@ keep_collapse_const_in_own_block_scope_2: {
console.log(i);
console.log(c);
}
expect_stdout: true
}
evaluate: {
@@ -295,7 +297,15 @@ issue_186_beautify: {
else
bar();
}
expect_exact: 'var x = 3;\n\nif (foo()) do {\n do {\n alert(x);\n } while (--x);\n} while (x); else bar();'
expect_exact: [
'var x = 3;',
'',
'if (foo()) do {',
' do {',
' alert(x);',
' } while (--x);',
'} while (x); else bar();',
]
}
issue_186_beautify_ie8: {
@@ -314,7 +324,17 @@ issue_186_beautify_ie8: {
else
bar();
}
expect_exact: 'var x = 3;\n\nif (foo()) {\n do {\n do {\n alert(x);\n } while (--x);\n } while (x);\n} else bar();'
expect_exact: [
'var x = 3;',
'',
'if (foo()) {',
' do {',
' do {',
' alert(x);',
' } while (--x);',
' } while (x);',
'} else bar();',
]
}
issue_186_bracketize: {
@@ -374,7 +394,19 @@ issue_186_beautify_bracketize: {
else
bar();
}
expect_exact: 'var x = 3;\n\nif (foo()) {\n do {\n do {\n alert(x);\n } while (--x);\n } while (x);\n} else {\n bar();\n}'
expect_exact: [
'var x = 3;',
'',
'if (foo()) {',
' do {',
' do {',
' alert(x);',
' } while (--x);',
' } while (x);',
'} else {',
' bar();',
'}',
]
}
issue_186_beautify_bracketize_ie8: {
@@ -394,5 +426,17 @@ issue_186_beautify_bracketize_ie8: {
else
bar();
}
expect_exact: 'var x = 3;\n\nif (foo()) {\n do {\n do {\n alert(x);\n } while (--x);\n } while (x);\n} else {\n bar();\n}'
expect_exact: [
'var x = 3;',
'',
'if (foo()) {',
' do {',
' do {',
' alert(x);',
' } while (--x);',
' } while (x);',
'} else {',
' bar();',
'}',
]
}

View File

@@ -7,7 +7,13 @@ too_short: {
return { c: 42, d: a(), e: "foo"};
}
}
expect_exact: 'function f(a){\nreturn{\nc:42,\nd:a(),\ne:"foo"}}'
expect_exact: [
'function f(a){',
'return{',
'c:42,',
'd:a(),',
'e:"foo"}}',
]
expect_warnings: [
"WARN: Output exceeds 10 characters"
]
@@ -22,7 +28,12 @@ just_enough: {
return { c: 42, d: a(), e: "foo"};
}
}
expect_exact: 'function f(a){\nreturn{c:42,\nd:a(),e:"foo"}\n}'
expect_exact: [
'function f(a){',
'return{c:42,',
'd:a(),e:"foo"}',
'}',
]
expect_warnings: [
]
}

View File

@@ -70,6 +70,7 @@ negate_iife_3_evaluate: {
expect: {
console.log(true);
}
expect_stdout: true
}
negate_iife_3_side_effects: {
@@ -111,6 +112,7 @@ negate_iife_3_off_evaluate: {
expect: {
console.log(true);
}
expect_stdout: true
}
negate_iife_4: {
@@ -243,6 +245,7 @@ negate_iife_nested: {
}(7);
}).f();
}
expect_stdout: true
}
negate_iife_nested_off: {
@@ -275,6 +278,7 @@ negate_iife_nested_off: {
})(7);
}).f();
}
expect_stdout: true
}
negate_iife_issue_1073: {
@@ -299,6 +303,7 @@ negate_iife_issue_1073: {
};
}(7))();
}
expect_stdout: true
}
issue_1254_negate_iife_false: {
@@ -313,6 +318,7 @@ issue_1254_negate_iife_false: {
})()();
}
expect_exact: '(function(){return function(){console.log("test")}})()();'
expect_stdout: true
}
issue_1254_negate_iife_true: {
@@ -327,6 +333,7 @@ issue_1254_negate_iife_true: {
})()();
}
expect_exact: '!function(){return function(){console.log("test")}}()();'
expect_stdout: true
}
issue_1254_negate_iife_nested: {
@@ -341,6 +348,7 @@ issue_1254_negate_iife_nested: {
})()()()()();
}
expect_exact: '!function(){return function(){console.log("test")}}()()()()();'
expect_stdout: true
}
issue_1288: {

View File

@@ -157,16 +157,20 @@ computed_property_names_evaluated_2: {
shorthand_properties: {
mangle = true;
input: (function() {
var prop = 1;
const value = {prop};
return value;
})();
expect: (function() {
var n = 1;
const r = {prop:n};
return r;
})();
input: {
(function() {
var prop = 1;
const value = {prop};
return value;
})();
}
expect: {
(function() {
var n = 1;
const r = {prop:n};
return r;
})();
}
}
concise_methods: {
@@ -233,9 +237,7 @@ concise_methods_with_computed_property2: {
};
doSomething(foo[[1]]());
}
expect_exact: {
'var foo={[[1]](){return"success"}};doSomething(foo[[1]]());'
}
expect_exact: 'var foo={[[1]](){return"success"}};doSomething(foo[[1]]());'
}
concise_methods_with_various_property_names: {
@@ -507,4 +509,4 @@ variable_as_computed_property: {
}
}
expect_exact: "function getLine(header){return{[header]:{}}}"
}
}

View File

@@ -58,6 +58,7 @@ reduce_vars: {
})();
console.log(2);
}
expect_stdout: true
}
modified: {
@@ -166,7 +167,7 @@ modified: {
console.log(A ? 'yes' : 'no');
console.log(B ? 'yes' : 'no');
}
}
}
}
unsafe_evaluate: {
@@ -401,6 +402,7 @@ iife: {
console.log(0, 1 * b, 5);
}(1, 2, 3);
}
expect_stdout: true
}
iife_new: {
@@ -420,6 +422,7 @@ iife_new: {
console.log(0, 1 * b, 5);
}(1, 2, 3);
}
expect_stdout: true
}
multi_def: {
@@ -707,6 +710,7 @@ toplevel_on: {
expect: {
console.log(3);
}
expect_stdout: true
}
toplevel_off: {
@@ -724,6 +728,7 @@ toplevel_off: {
var x = 3;
console.log(x);
}
expect_stdout: true
}
toplevel_on_loops_1: {
@@ -751,6 +756,7 @@ toplevel_on_loops_1: {
})();
while (x);
}
expect_stdout: true
}
toplevel_off_loops_1: {
@@ -779,6 +785,7 @@ toplevel_off_loops_1: {
bar();
while (x);
}
expect_stdout: true
}
toplevel_on_loops_2: {
@@ -1121,6 +1128,7 @@ defun_label: {
}(2));
}();
}
expect_stdout: true
}
double_reference: {
@@ -1164,6 +1172,7 @@ iife_arguments_1: {
return f;
});
}
expect_stdout: true
}
iife_arguments_2: {
@@ -1186,6 +1195,7 @@ iife_arguments_2: {
}() === arguments[0]);
})();
}
expect_stdout: true
}
iife_eval_1: {
@@ -1207,6 +1217,7 @@ iife_eval_1: {
return f;
});
}
expect_stdout: true
}
iife_eval_2: {
@@ -1230,6 +1241,7 @@ iife_eval_2: {
console.log(x() === eval("x"));
})();
}
expect_stdout: true
}
iife_func_side_effects: {
@@ -1252,3 +1264,103 @@ iife_func_side_effects: {
})(x(), 0, z());
}
}
issue_1595_1: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
(function f(a) {
return f(a + 1);
})(2);
}
expect: {
(function f(a) {
return f(a + 1);
})(2);
}
}
issue_1595_2: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
(function f(a) {
return g(a + 1);
})(2);
}
expect: {
(function(a) {
return g(a + 1);
})(2);
}
}
issue_1595_3: {
options = {
evaluate: true,
passes: 2,
reduce_vars: true,
unused: true,
}
input: {
(function f(a) {
return g(a + 1);
})(2);
}
expect: {
(function(a) {
return g(3);
})();
}
}
issue_1595_4: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
(function iife(a, b, c) {
console.log(a, b, c);
if (a) iife(a - 1, b, c);
})(3, 4, 5);
}
expect: {
(function iife(a, b, c) {
console.log(a, b, c);
if (a) iife(a - 1, b, c);
})(3, 4, 5);
}
expect_stdout: true
}
issue_1606: {
options = {
evaluate: true,
hoist_vars: true,
reduce_vars: true,
}
input: {
function f() {
var a;
function g(){};
var b = 2;
x(b);
}
}
expect: {
function f() {
var a, b;
function g(){};
b = 2;
x(b);
}
}
}

View File

@@ -1,20 +1,29 @@
do_screw: {
options = { screw_ie8: true };
options = {
screw_ie8: true,
}
beautify = {
screw_ie8: true,
ascii_only: true
};
input: f("\v");
expect_exact: 'f("\\v");';
ascii_only: true,
}
input: {
f("\v");
}
expect_exact: 'f("\\v");'
}
dont_screw: {
options = { screw_ie8: false };
beautify = { screw_ie8: false, ascii_only: true };
input: f("\v");
expect_exact: 'f("\\x0B");';
options = {
screw_ie8: false,
}
beautify = {
screw_ie8: false,
ascii_only: true,
}
input: {
f("\v");
}
expect_exact: 'f("\\x0B");'
}
do_screw_constants: {
@@ -119,6 +128,7 @@ do_screw_try_catch_undefined: {
return void 0===o
}
}
expect_stdout: true
}
dont_screw_try_catch_undefined: {
@@ -147,6 +157,7 @@ dont_screw_try_catch_undefined: {
return n === undefined
}
}
expect_stdout: true
}
reduce_vars: {
@@ -199,6 +210,7 @@ issue_1586_1: {
}
}
expect_exact: "function f(){try{}catch(c){console.log(c.message)}}"
expect_stdout: true
}
issue_1586_2: {
@@ -217,4 +229,5 @@ issue_1586_2: {
}
}
expect_exact: "function f(){try{}catch(c){console.log(c.message)}}"
expect_stdout: true
}

View File

@@ -86,6 +86,7 @@ make_sequences_4: {
switch (x = 5, y) {}
with (x = 5, obj);
}
expect_stdout: true
}
lift_sequences_1: {
@@ -103,15 +104,18 @@ lift_sequences_1: {
lift_sequences_2: {
options = { sequences: true, evaluate: true };
input: {
var foo, bar;
var foo = 1, bar;
foo.x = (foo = {}, 10);
bar = (bar = {}, 10);
console.log(foo, bar);
}
expect: {
var foo, bar;
var foo = 1, bar;
foo.x = (foo = {}, 10),
bar = {}, bar = 10;
bar = {}, bar = 10,
console.log(foo, bar);
}
expect_stdout: true
}
lift_sequences_3: {
@@ -138,6 +142,23 @@ lift_sequences_4: {
}
}
lift_sequences_5: {
options = {
sequences: true,
}
input: {
var a = 2, b;
a *= (b, a = 4, 3);
console.log(a);
}
expect: {
var a = 2, b;
b, a *= (a = 4, 3),
console.log(a);
}
expect_stdout: "6"
}
for_sequences: {
options = { sequences: true };
input: {
@@ -230,6 +251,7 @@ negate_iife_for: {
for (!function() {}(), i = 0; i < 5; i++) console.log(i);
for (function() {}(); i < 5; i++) console.log(i);
}
expect_stdout: true
}
iife: {

131
test/compress/transform.js Normal file
View File

@@ -0,0 +1,131 @@
booleans_evaluate: {
options = {
booleans: true,
evaluate: true,
}
input: {
console.log(typeof void 0 != "undefined");
console.log(1 == 1, 1 === 1)
console.log(1 != 1, 1 !== 1)
}
expect: {
console.log(!1);
console.log(!0, !0);
console.log(!1, !1);
}
expect_stdout: true
}
booleans_global_defs: {
options = {
booleans: true,
evaluate: true,
global_defs: {
A: true,
},
}
input: {
console.log(A == 1);
}
expect: {
console.log(!0);
}
expect_stdout: true
}
condition_evaluate: {
options = {
booleans: true,
dead_code: false,
evaluate: true,
loops: false,
}
input: {
while (1 === 2);
for (; 1 == true;);
if (void 0 == null);
}
expect: {
while (!1);
for (; !0;);
if (!0);
}
}
if_else_empty: {
options = {
conditionals: true,
}
input: {
if ({} ? a : b); else {}
}
expect: {
!{} ? b : a;
}
}
label_if_break: {
options = {
conditionals: true,
dead_code: true,
evaluate: true,
}
input: {
L: if (true) {
a;
break L;
}
}
expect: {
a;
}
}
while_if_break: {
options = {
conditionals: true,
loops: true,
sequences: true,
}
input: {
while (a) {
if (b) if(c) d;
if (e) break;
}
}
expect: {
for(; a && (b && c && d, !e););
}
}
if_return: {
options = {
booleans: true,
conditionals: true,
if_return: true,
sequences: true,
}
input: {
function f(w, x, y, z) {
if (x) return;
if (w) {
if (y) return;
} else if (z) return;
if (x == y) return true;
if (x) w();
if (y) z();
return true;
}
}
expect: {
function f(w, x, y, z) {
if (!x) {
if (w) {
if (y) return;
} else if (z) return;
return x == y || (x && w(), y && z(), !0);
}
}
}
}

View File

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

View File

@@ -152,7 +152,7 @@ describe("bin/uglifyjs", function () {
});
});
it("Should process inline source map", function(done) {
var command = uglifyjscmd + ' test/input/issue-520/input.js -cm toplevel --in-source-map inline --source-map-inline';
var command = uglifyjscmd + ' test/input/issue-520/input.js -mc toplevel --in-source-map inline --source-map-inline';
exec(command, function (err, stdout) {
if (err) throw err;

View File

@@ -397,7 +397,7 @@ describe("Directives", function() {
if (node instanceof uglify.AST_Symbol && node.name === "_check_") {
checked = true;
for (var j = 0; j < tests[i].directives.length; j++) {
assert.equal(checkWalker.has_directive(tests[i].directives[j]), true,
assert.ok(checkWalker.has_directive(tests[i].directives[j]),
"Did not found directive '" + tests[i].directives[j] + "' in test " + tests[i].input)
}
for (var k = 0; k < tests[i].non_directives.length; k++) {

View File

@@ -1,10 +1,11 @@
var Uglify = require('../../');
var assert = require("assert");
var path = require("path");
describe("minify() with input file globs", function() {
it("minify() with one input file glob string.", function() {
var result = Uglify.minify("test/input/issue-1242/foo.*");
assert.strictEqual(result.code, 'function foo(o){print("Foo:",2*o)}var print=console.log.bind(console);');
assert.strictEqual(result.code, 'function foo(o){var n=2*o;print("Foo:",n)}var print=console.log.bind(console);');
});
it("minify() with an array of one input file glob.", function() {
var result = Uglify.minify([
@@ -19,6 +20,39 @@ describe("minify() with input file globs", function() {
], {
compress: { toplevel: true }
});
assert.strictEqual(result.code, 'var print=console.log.bind(console);print("qux",function(n){return 3*n}(3),function(n){return n/2}(12)),function(n){print("Foo:",2*n)}(11);');
assert.strictEqual(result.code, 'var print=console.log.bind(console),a=function(n){return 3*n}(3),b=function(n){return n/2}(12);print("qux",a,b),function(n){var o=2*n;print("Foo:",o)}(11);');
});
it("should throw with non-matching glob string", function() {
var glob = "test/input/issue-1242/blah.*";
assert.strictEqual(Uglify.simple_glob(glob).length, 1);
assert.strictEqual(Uglify.simple_glob(glob)[0], glob);
assert.throws(function() {
Uglify.minify(glob);
}, "should throw file not found");
});
it('"?" in glob string should not match "/"', function() {
var glob = "test/input?issue-1242/foo.*";
assert.strictEqual(Uglify.simple_glob(glob).length, 1);
assert.strictEqual(Uglify.simple_glob(glob)[0], glob);
assert.throws(function() {
Uglify.minify(glob);
}, "should throw file not found");
});
it("should handle special characters in glob string", function() {
var result = Uglify.minify("test/input/issue-1632/^{*}[???](*)+$.??");
assert.strictEqual(result.code, "console.log(x);");
});
it("should handle array of glob strings - matching and otherwise", function() {
var dir = "test/input/issue-1242";
var matches = Uglify.simple_glob([
path.join(dir, "b*.es5"),
path.join(dir, "z*.es5"),
path.join(dir, "*.js"),
]);
assert.strictEqual(matches.length, 4);
assert.strictEqual(matches[0], path.join(dir, "bar.es5"));
assert.strictEqual(matches[1], path.join(dir, "baz.es5"));
assert.strictEqual(matches[2], path.join(dir, "z*.es5"));
assert.strictEqual(matches[3], path.join(dir, "qux.js"));
});
});

View File

@@ -78,6 +78,7 @@ describe("minify", function() {
});
it("Should process inline source map", function() {
var code = Uglify.minify("./test/input/issue-520/input.js", {
compress: { toplevel: true },
inSourceMap: "inline",
sourceMapInline: true
}).code + "\n";

View File

@@ -5,7 +5,7 @@ var UglifyJS = require(".."),
escodegen = require("escodegen"),
esfuzz = require("esfuzz"),
estraverse = require("estraverse"),
prefix = Array(20).join("\b") + " ";
prefix = "\r ";
// Normalizes input AST for UglifyJS in order to get correct comparison.
@@ -62,7 +62,7 @@ module.exports = function(options) {
var ast1 = normalizeInput(esfuzz.generate({
maxDepth: options.maxDepth
}));
var ast2 =
UglifyJS
.AST_Node

View File

@@ -6,10 +6,22 @@ var U = require("../tools/node");
var path = require("path");
var fs = require("fs");
var assert = require("assert");
var vm = require("vm");
var tests_dir = path.dirname(module.filename);
var failures = 0;
var failed_files = {};
var same_stdout = ~process.version.lastIndexOf("v0.12.", 0) ? function(expected, actual) {
if (typeof expected != typeof actual) return false;
if (typeof expected != "string") {
if (expected.name != actual.name) return false;
expected = expected.message.slice(expected.message.lastIndexOf("\n") + 1);
actual = actual.message.slice(actual.message.lastIndexOf("\n") + 1);
}
return expected == actual;
} : function(expected, actual) {
return typeof expected == typeof actual && expected.toString() == actual.toString();
};
run_compress_tests();
if (failures) {
@@ -71,10 +83,15 @@ function test_directory(dir) {
}
function as_toplevel(input, mangle_options) {
if (input instanceof U.AST_BlockStatement) input = input.body;
else if (input instanceof U.AST_Statement) input = [ input ];
else throw new Error("Unsupported input syntax");
var toplevel = new U.AST_Toplevel({ body: input });
if (!(input instanceof U.AST_BlockStatement))
throw new Error("Unsupported input syntax");
for (var i = 0; i < input.body.length; i++) {
var stat = input.body[i];
if (stat instanceof U.AST_SimpleStatement && stat.body instanceof U.AST_String)
input.body[i] = new U.AST_Directive(stat.body);
else break;
}
var toplevel = new U.AST_Toplevel(input);
toplevel.figure_out_scope(mangle_options);
return toplevel;
}
@@ -97,7 +114,7 @@ function run_compress_tests() {
U.AST_Node.warn_function = function(text) {
warnings_emitted.push("WARN: " + text);
};
options.warnings = true;
if (!options.warnings) options.warnings = true;
}
var cmp = new U.Compressor(options, true);
var output_options = test.beautify || {};
@@ -165,6 +182,36 @@ function run_compress_tests() {
failed_files[file] = 1;
}
}
if (test.expect_stdout) {
var stdout = run_code(make_code(input, output_options));
if (test.expect_stdout === true) {
test.expect_stdout = stdout;
}
if (!same_stdout(test.expect_stdout, stdout)) {
log("!!! Invalid input or expected stdout\n---INPUT---\n{input}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
input: input_code,
expected_type: typeof test.expect_stdout == "string" ? "STDOUT" : "ERROR",
expected: test.expect_stdout,
actual_type: typeof stdout == "string" ? "STDOUT" : "ERROR",
actual: stdout,
});
failures++;
failed_files[file] = 1;
} else {
stdout = run_code(output);
if (!same_stdout(test.expect_stdout, stdout)) {
log("!!! failed\n---INPUT---\n{input}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
input: input_code,
expected_type: typeof test.expect_stdout == "string" ? "STDOUT" : "ERROR",
expected: test.expect_stdout,
actual_type: typeof stdout == "string" ? "STDOUT" : "ERROR",
actual: stdout,
});
failures++;
failed_files[file] = 1;
}
}
}
}
}
var tests = parse_test(path.resolve(dir, file));
@@ -214,6 +261,23 @@ function parse_test(file) {
}));
}
function read_string(stat) {
if (stat.TYPE == "SimpleStatement") {
var body = stat.body;
switch(body.TYPE) {
case "String":
return body.value;
case "Array":
return body.elements.map(function(element) {
if (element.TYPE !== "String")
throw new Error("Should be array of strings");
return element.value;
}).join("\n");
}
}
throw new Error("Should be string or array of strings");
}
function get_one_test(name, block) {
var test = { name: name, options: {} };
var tw = new U.TreeWalker(function(node, descend){
@@ -226,28 +290,26 @@ function parse_test(file) {
return true;
}
if (node instanceof U.AST_LabeledStatement) {
var label = node.label;
assert.ok(
["input", "expect", "expect_exact", "expect_warnings"].indexOf(node.label.name) >= 0,
["input", "expect", "expect_exact", "expect_warnings", "expect_stdout"].indexOf(label.name) >= 0,
tmpl("Unsupported label {name} [{line},{col}]", {
name: node.label.name,
line: node.label.start.line,
col: node.label.start.col
name: label.name,
line: label.start.line,
col: label.start.col
})
);
var stat = node.body;
if (stat instanceof U.AST_BlockStatement) {
if (stat.body.length == 1) stat = stat.body[0];
else if (stat.body.length == 0) stat = new U.AST_EmptyStatement();
}
if (node.label.name === "expect_exact") {
if (!(stat.TYPE === "SimpleStatement" && stat.body.TYPE === "String")) {
throw new Error(
"The value of the expect_exact clause should be a string, " +
"like `expect_exact: \"some.exact.javascript;\"`");
if (label.name == "expect_exact") {
test[label.name] = read_string(stat);
} else if (label.name == "expect_stdout") {
if (stat.TYPE == "SimpleStatement" && stat.body instanceof U.AST_Boolean) {
test[label.name] = stat.body.value;
} else {
test[label.name] = read_string(stat) + "\n";
}
test[node.label.name] = stat.body.start.value
} else {
test[node.label.name] = stat;
test[label.name] = stat;
}
return true;
}
@@ -269,3 +331,19 @@ function evaluate(code) {
code = make_code(code, { beautify: true });
return new Function("return(" + code + ")")();
}
function run_code(code) {
var stdout = "";
var original_write = process.stdout.write;
process.stdout.write = function(chunk) {
stdout += chunk;
};
try {
new vm.Script(code).runInNewContext({ console: console }, { timeout: 5000 });
return stdout;
} catch (ex) {
return ex;
} finally {
process.stdout.write = original_write;
}
}

View File

@@ -18,6 +18,6 @@ exports["tokenizer"] = tokenizer;
exports["is_identifier"] = is_identifier;
exports["SymbolDef"] = SymbolDef;
if (typeof DEBUG !== "undefined" && DEBUG) {
if (global.UGLIFY_DEBUG) {
exports["EXPECT_DIRECTIVE"] = EXPECT_DIRECTIVE;
}

View File

@@ -7,7 +7,8 @@
var path = require("path");
var fs = require("fs");
var FILES = exports.FILES = [
var UglifyJS = exports;
var FILES = UglifyJS.FILES = [
"../lib/utils.js",
"../lib/ast.js",
"../lib/parse.js",
@@ -20,17 +21,14 @@ var FILES = exports.FILES = [
"../lib/propmangle.js",
"./exports.js",
].map(function(file){
return fs.realpathSync(path.join(path.dirname(__filename), file));
return require.resolve(file);
});
var UglifyJS = exports;
new Function("MOZ_SourceMap", "exports", "DEBUG", FILES.map(function(file){
new Function("MOZ_SourceMap", "exports", FILES.map(function(file){
return fs.readFileSync(file, "utf8");
}).join("\n\n"))(
require("source-map"),
UglifyJS,
!!global.UGLIFY_DEBUG
UglifyJS
);
UglifyJS.AST_Node.warn_function = function(txt) {
@@ -46,7 +44,7 @@ function read_source_map(code) {
return JSON.parse(new Buffer(match[2], "base64"));
}
exports.minify = function(files, options) {
UglifyJS.minify = function(files, options) {
options = UglifyJS.defaults(options, {
spidermonkey : false,
outSourceMap : null,
@@ -181,7 +179,7 @@ exports.minify = function(files, options) {
};
};
// exports.describe_ast = function() {
// UglifyJS.describe_ast = function() {
// function doitem(ctor) {
// var sub = {};
// ctor.SUBCLASSES.forEach(function(ctor){
@@ -195,7 +193,7 @@ exports.minify = function(files, options) {
// return doitem(UglifyJS.AST_Node).sub;
// }
exports.describe_ast = function() {
UglifyJS.describe_ast = function() {
var out = UglifyJS.OutputStream({ beautify: true });
function doitem(ctor) {
out.print("AST_" + ctor.TYPE);
@@ -249,13 +247,13 @@ function readReservedFile(filename, reserved) {
return reserved;
}
exports.readReservedFile = readReservedFile;
UglifyJS.readReservedFile = readReservedFile;
exports.readDefaultReservedFile = function(reserved) {
return readReservedFile(path.join(__dirname, "domprops.json"), reserved);
UglifyJS.readDefaultReservedFile = function(reserved) {
return readReservedFile(require.resolve("./domprops.json"), reserved);
};
exports.readNameCache = function(filename, key) {
UglifyJS.readNameCache = function(filename, key) {
var cache = null;
if (filename) {
try {
@@ -273,7 +271,7 @@ exports.readNameCache = function(filename, key) {
return cache;
};
exports.writeNameCache = function(filename, key, cache) {
UglifyJS.writeNameCache = function(filename, key, cache) {
if (filename) {
var data;
try {
@@ -294,13 +292,9 @@ exports.writeNameCache = function(filename, key, cache) {
// Example: "foo/bar/*baz??.*.js"
// Argument `glob` may be a string or an array of strings.
// Returns an array of strings. Garbage in, garbage out.
exports.simple_glob = function simple_glob(glob) {
var results = [];
UglifyJS.simple_glob = function simple_glob(glob) {
if (Array.isArray(glob)) {
glob.forEach(function(elem) {
results = results.concat(simple_glob(elem));
});
return results;
return [].concat.apply([], glob.map(simple_glob));
}
if (glob.match(/\*|\?/)) {
var dir = path.dirname(glob);
@@ -308,28 +302,19 @@ exports.simple_glob = function simple_glob(glob) {
var entries = fs.readdirSync(dir);
} catch (ex) {}
if (entries) {
var pattern = "^" + (path.basename(glob)
.replace(/\(/g, "\\(")
.replace(/\)/g, "\\)")
.replace(/\{/g, "\\{")
.replace(/\}/g, "\\}")
.replace(/\[/g, "\\[")
.replace(/\]/g, "\\]")
.replace(/\+/g, "\\+")
.replace(/\^/g, "\\^")
.replace(/\$/g, "\\$")
var pattern = "^" + path.basename(glob)
.replace(/[.+^$[\]\\(){}]/g, "\\$&")
.replace(/\*/g, "[^/\\\\]*")
.replace(/\./g, "\\.")
.replace(/\?/g, ".")) + "$";
.replace(/\?/g, "[^/\\\\]") + "$";
var mod = process.platform === "win32" ? "i" : "";
var rx = new RegExp(pattern, mod);
for (var i in entries) {
if (rx.test(entries[i]))
results.push(dir + "/" + entries[i]);
}
var results = entries.filter(function(name) {
return rx.test(name);
}).map(function(name) {
return path.join(dir, name);
});
if (results.length) return results;
}
}
if (results.length === 0)
results = [ glob ];
return results;
return [ glob ];
};