Compare commits

...

30 Commits

Author SHA1 Message Date
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
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
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
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
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
Alex Lam S.L
cf45e2f79b fixup for #1585 (#1589)
As patched on `harmony`, `statement()` is the only user of `embed_tokens()` with a missing error branch.

Updated test case and match up with `harmony` to facilitate future merging.
2017-03-10 10:49:41 +08:00
Alex Lam S.L
8354758f30 v2.8.11 2017-03-10 04:17:21 +08:00
Alex Lam S.L
9e6b128374 fix catch variable reference in IE8 (#1587)
`AST_Scope.def_variable()` will overwrite `AST_Symbol.thedef`, so save a copy before calling.

fixes #1586
2017-03-10 03:15:21 +08:00
Michael Mior
93cdb194f4 Correctly raise a parse exception with a missing loop body (#1585) 2017-03-10 03:08:43 +08:00
Alex Lam S.L
b633706ce4 fix & improve function argument compression (#1584)
- one-use function call => IIFE should take `eval()` & `arguments` into account
- if unused parameter cannot be eliminated, replace it with `0`

fixes #1583
2017-03-09 19:11:05 +08:00
Alex Lam S.L
e9920f7ca1 v2.8.10 2017-03-09 05:48:06 +08:00
Alex Lam S.L
7e465d4a01 scan RHS of dropped assignments (#1581)
- similar case as #1578 but against #1450 instead
- fix `this` binding in #1450 as well

closes #1580
2017-03-09 05:22:27 +08:00
Alex Lam S.L
aa80ee349d remove checkboxes from Issues template 2017-03-08 19:19:54 +08:00
Alex Lam S.L
80e81765cf explain how to make a proper bug report (#1579)
fixes #1574
2017-03-08 18:56:01 +08:00
Alex Lam S.L
711f88dcb4 scan assignment value in drop_unused() (#1578)
those were not optimised for `unused` before, which made it necessary for `reduce_vars` to have separate steps for `keep_fnames`

docs update by @kzc

closes #1577
2017-03-08 18:37:32 +08:00
38 changed files with 1415 additions and 310 deletions

7
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,7 @@
- Bug report or feature request?
- `uglify-js` version (`uglifyjs -V`)
- JavaScript input - ideally as small as possible.
- The `uglifyjs` CLI command executed or `minify()` options used.
- An example of JavaScript output produced and/or the error or warning.
Note: the release version of `uglify-js` only supports ES5. Those wishing to minify ES6 should use the experimental [`harmony`](https://github.com/mishoo/UglifyJS2#harmony) branch.

View File

@@ -68,7 +68,8 @@ The available options are:
--source-map-inline Write base64-encoded source map to the end of js output. --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 --in-source-map Input source map, useful if you're compressing
JS that was generated from some other original 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 --screw-ie8 Use this flag if you don't wish to support
Internet Explorer 6/7/8. Internet Explorer 6/7/8.
By default UglifyJS will not try to be IE-proof. By default UglifyJS will not try to be IE-proof.
@@ -200,9 +201,10 @@ compressed JS by mapping every token in the compiled JS to its original
location. location.
To use this feature you need to pass `--in-source-map To use this feature you need to pass `--in-source-map
/path/to/input/source.map`. Normally the input source map should also point /path/to/input/source.map` or `--in-source-map inline` if the source map is
to the file containing the generated JS, so if that's correct you can omit included inline with the sources. Normally the input source map should also
input files from the command line. point to the file containing the generated JS, so if that's correct you can
omit input files from the command line.
## Mangler options ## Mangler options
@@ -391,11 +393,11 @@ to set `true`; it's effectively a shortcut for `foo=true`).
- `cascade` -- small optimization for sequences, transform `x, x` into `x` - `cascade` -- small optimization for sequences, transform `x, x` into `x`
and `x = something(), x` into `x = something()` and `x = something(), x` into `x = something()`
- `collapse_vars` -- default `false`. Collapse single-use `var` and `const` - `collapse_vars` -- Collapse single-use `var` and `const` definitions
definitions when possible. when possible.
- `reduce_vars` -- default `false`. Improve optimization on variables assigned - `reduce_vars` -- Improve optimization on variables assigned with and
with and used as constant values. used as constant values.
- `warnings` -- display warnings when dropping unreachable code or unused - `warnings` -- display warnings when dropping unreachable code or unused
declarations etc. declarations etc.

View File

@@ -984,8 +984,8 @@ TreeWalker.prototype = {
push: function (node) { push: function (node) {
if (node instanceof AST_Lambda) { if (node instanceof AST_Lambda) {
this.directives = Object.create(this.directives); this.directives = Object.create(this.directives);
} else if (node instanceof AST_Directive) { } else if (node instanceof AST_Directive && !this.directives[node.value]) {
this.directives[node.value] = this.directives[node.value] ? "up" : true; this.directives[node.value] = node;
} }
this.stack.push(node); this.stack.push(node);
}, },
@@ -1013,7 +1013,7 @@ TreeWalker.prototype = {
for (var i = 0; i < node.body.length; ++i) { for (var i = 0; i < node.body.length; ++i) {
var st = node.body[i]; var st = node.body[i];
if (!(st instanceof AST_Directive)) break; 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

@@ -928,11 +928,9 @@ function parse($TEXT, options) {
expression : parenthesised(), expression : parenthesised(),
body : statement() body : statement()
}); });
default:
unexpected();
} }
} }
unexpected();
}); });
function labeled_statement() { function labeled_statement() {

View File

@@ -212,9 +212,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
self.walk(new TreeWalker(function(node, descend) { self.walk(new TreeWalker(function(node, descend) {
if (node instanceof AST_SymbolCatch) { if (node instanceof AST_SymbolCatch) {
var name = node.name; var name = node.name;
var refs = node.thedef.references;
var scope = node.thedef.scope.parent_scope; var scope = node.thedef.scope.parent_scope;
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node); var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
node.thedef.references.forEach(function(ref) { refs.forEach(function(ref) {
ref.thedef = def; ref.thedef = def;
ref.reference(options); ref.reference(options);
}); });

View File

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

View File

@@ -4,7 +4,7 @@
"homepage": "http://lisperator.net/uglifyjs", "homepage": "http://lisperator.net/uglifyjs",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)", "author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"version": "2.8.9", "version": "2.8.14",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=0.8.0"
}, },

View File

@@ -43,6 +43,7 @@ collapse_vars_side_effects_1: {
z = i += 4; z = i += 4;
log(x, z, y, i); log(x, z, y, i);
} }
f1(), f2(), f3(), f4();
} }
expect: { expect: {
function f1() { function f1() {
@@ -73,7 +74,9 @@ collapse_vars_side_effects_1: {
y = i += 3; y = i += 3;
log(x, i += 4, y, i); log(x, i += 4, y, i);
} }
f1(), f2(), f3(), f4();
} }
expect_stdout: true
} }
collapse_vars_side_effects_2: { collapse_vars_side_effects_2: {
@@ -823,6 +826,7 @@ collapse_vars_repeated: {
console.log(e + "!"); console.log(e + "!");
})("!"); })("!");
} }
expect_stdout: true
} }
collapse_vars_closures: { collapse_vars_closures: {
@@ -1109,6 +1113,7 @@ collapse_vars_eval_and_with: {
return function() { with (o) console.log(a) }; return function() { with (o) console.log(a) };
})()(); })()();
} }
expect_stdout: true
} }
collapse_vars_constants: { collapse_vars_constants: {
@@ -1152,7 +1157,8 @@ collapse_vars_arguments: {
options = { options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true, 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, 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: { input: {
var outer = function() { var outer = function() {
@@ -1167,6 +1173,7 @@ collapse_vars_arguments: {
(function(){console.log(arguments);})(7, 1); (function(){console.log(arguments);})(7, 1);
})(); })();
} }
expect_stdout: true
} }
collapse_vars_short_circuit: { collapse_vars_short_circuit: {
@@ -1316,6 +1323,7 @@ collapse_vars_regexp: {
console.log(result[0]); console.log(result[0]);
})(); })();
} }
expect_stdout: true
} }
issue_1537: { issue_1537: {
@@ -1335,6 +1343,7 @@ issue_1537: {
issue_1562: { issue_1562: {
options = { options = {
collapse_vars: true, collapse_vars: true,
toplevel: true,
} }
input: { input: {
var v = 1, B = 2; var v = 1, B = 2;
@@ -1363,3 +1372,46 @@ issue_1562: {
for (; f(z + 2) ;) bar(30); 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;
}
}

View File

@@ -51,6 +51,7 @@ concat_2: {
"1" + "2" + "3" "1" + "2" + "3"
); );
} }
expect_stdout: true
} }
concat_3: { concat_3: {
@@ -79,6 +80,7 @@ concat_3: {
1 + 2 + "3" + "4" + "5" 1 + 2 + "3" + "4" + "5"
); );
} }
expect_stdout: true
} }
concat_4: { concat_4: {
@@ -107,6 +109,7 @@ concat_4: {
1 + "2" + "3" + "4" + "5" 1 + "2" + "3" + "4" + "5"
); );
} }
expect_stdout: true
} }
concat_5: { concat_5: {
@@ -135,6 +138,7 @@ concat_5: {
"1" + 2 + "3" + "4" + "5" "1" + 2 + "3" + "4" + "5"
); );
} }
expect_stdout: true
} }
concat_6: { concat_6: {
@@ -163,6 +167,7 @@ concat_6: {
"1" + "2" + "3" + "4" + "5" "1" + "2" + "3" + "4" + "5"
); );
} }
expect_stdout: true
} }
concat_7: { concat_7: {
@@ -188,6 +193,7 @@ concat_7: {
x += "foo" x += "foo"
); );
} }
expect_stdout: true
} }
concat_8: { concat_8: {
@@ -213,4 +219,5 @@ concat_8: {
x += "foo" 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]); 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 x = 10, y;
var moo; var moo;
} }
expect_stdout: true
} }
dead_code_const_declaration: { dead_code_const_declaration: {
@@ -113,6 +114,7 @@ dead_code_const_declaration: {
var moo; var moo;
function bar() {} function bar() {}
} }
expect_stdout: true
} }
dead_code_const_annotation: { dead_code_const_annotation: {
@@ -140,6 +142,7 @@ dead_code_const_annotation: {
var moo; var moo;
function bar() {} function bar() {}
} }
expect_stdout: true
} }
dead_code_const_annotation_regex: { dead_code_const_annotation_regex: {
@@ -163,6 +166,7 @@ dead_code_const_annotation_regex: {
var CONST_FOO_ANN = !1; var CONST_FOO_ANN = !1;
CONST_FOO_ANN && console.log('reachable'); CONST_FOO_ANN && console.log('reachable');
} }
expect_stdout: true
} }
dead_code_const_annotation_complex_scope: { dead_code_const_annotation_complex_scope: {
@@ -208,4 +212,5 @@ dead_code_const_annotation_complex_scope: {
var meat = 'beef'; var meat = 'beef';
var pork = 'bad'; var pork = 'bad';
} }
expect_stdout: true
} }

View File

@@ -700,3 +700,94 @@ issue_1539: {
} }
} }
} }
vardef_value: {
options = {
keep_fnames: false,
reduce_vars: true,
unused: true,
}
input: {
function f() {
function g(){
return x();
}
var a = g();
return a(42);
}
}
expect: {
function f() {
var a = function(){
return x();
}();
return a(42);
}
}
}
assign_binding: {
options = {
cascade: true,
side_effects: true,
unused: true,
}
input: {
function f() {
var a;
a = f.g, a();
}
}
expect: {
function f() {
(0, f.g)();
}
}
}
assign_chain: {
options = {
unused: true,
}
input: {
function f() {
var a, b;
x = a = y = b = 42;
}
}
expect: {
function f() {
x = y = 42;
}
}
}
issue_1583: {
options = {
keep_fargs: true,
reduce_vars: true,
unused: true,
}
input: {
function m(t) {
(function(e) {
t = e();
})(function() {
return (function(a) {
return a;
})(function(a) {});
});
}
}
expect: {
function m(t) {
(function(e) {
t = (function() {
return (function(a) {
return a;
})(function(a) {});
})();
})();
}
}
}

View File

@@ -200,6 +200,7 @@ negative_zero: {
1 / (-0) 1 / (-0)
); );
} }
expect_stdout: true
} }
positive_zero: { positive_zero: {
@@ -220,6 +221,7 @@ positive_zero: {
1 / (0) 1 / (0)
); );
} }
expect_stdout: true
} }
unsafe_constant: { unsafe_constant: {
@@ -243,6 +245,7 @@ unsafe_constant: {
(void 0).a (void 0).a
); );
} }
expect_stdout: true
} }
unsafe_object: { unsafe_object: {
@@ -266,6 +269,7 @@ unsafe_object: {
1..b + 1 1..b + 1
); );
} }
expect_stdout: true
} }
unsafe_object_nested: { unsafe_object_nested: {
@@ -289,6 +293,7 @@ unsafe_object_nested: {
2 2
); );
} }
expect_stdout: true
} }
unsafe_object_complex: { unsafe_object_complex: {
@@ -312,6 +317,7 @@ unsafe_object_complex: {
2 2
); );
} }
expect_stdout: true
} }
unsafe_object_repeated: { unsafe_object_repeated: {
@@ -335,6 +341,7 @@ unsafe_object_repeated: {
1..b + 1 1..b + 1
); );
} }
expect_stdout: true
} }
unsafe_object_accessor: { unsafe_object_accessor: {
@@ -384,6 +391,7 @@ unsafe_function: {
({a:{b:1},b:function(){}}).a.b + 1 ({a:{b:1},b:function(){}}).a.b + 1
); );
} }
expect_stdout: true
} }
unsafe_integer_key: { unsafe_integer_key: {
@@ -411,6 +419,7 @@ unsafe_integer_key: {
1["1"] + 1 1["1"] + 1
); );
} }
expect_stdout: true
} }
unsafe_integer_key_complex: { unsafe_integer_key_complex: {
@@ -438,6 +447,7 @@ unsafe_integer_key_complex: {
2 2
); );
} }
expect_stdout: true
} }
unsafe_float_key: { unsafe_float_key: {
@@ -465,6 +475,7 @@ unsafe_float_key: {
1["3.14"] + 1 1["3.14"] + 1
); );
} }
expect_stdout: true
} }
unsafe_float_key_complex: { unsafe_float_key_complex: {
@@ -492,6 +503,7 @@ unsafe_float_key_complex: {
2 2
); );
} }
expect_stdout: true
} }
unsafe_array: { unsafe_array: {
@@ -527,6 +539,7 @@ unsafe_array: {
(void 0)[1] + 1 (void 0)[1] + 1
); );
} }
expect_stdout: true
} }
unsafe_string: { unsafe_string: {
@@ -554,6 +567,7 @@ unsafe_string: {
"11" "11"
); );
} }
expect_stdout: true
} }
unsafe_array_bad_index: { unsafe_array_bad_index: {
@@ -575,6 +589,7 @@ unsafe_array_bad_index: {
[1, 2, 3, 4][3.14] + 1 [1, 2, 3, 4][3.14] + 1
); );
} }
expect_stdout: true
} }
unsafe_string_bad_index: { unsafe_string_bad_index: {
@@ -596,6 +611,7 @@ unsafe_string_bad_index: {
"1234"[3.14] + 1 "1234"[3.14] + 1
); );
} }
expect_stdout: true
} }
unsafe_prototype_function: { unsafe_prototype_function: {
@@ -642,6 +658,7 @@ call_args: {
console.log(1); console.log(1);
+(1, 1); +(1, 1);
} }
expect_stdout: true
} }
call_args_drop_param: { call_args_drop_param: {
@@ -663,6 +680,7 @@ call_args_drop_param: {
console.log(1); console.log(1);
+(b, 1); +(b, 1);
} }
expect_stdout: true
} }
in_boolean_context: { in_boolean_context: {
@@ -700,4 +718,74 @@ in_boolean_context: {
(foo(), !1) (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(6);
console.log((a(), b(), 6)); console.log((a(), b(), 6));
} }
expect_stdout: true
} }
iifes_returning_constants_keep_fargs_false: { iifes_returning_constants_keep_fargs_false: {
@@ -73,6 +74,7 @@ iifes_returning_constants_keep_fargs_false: {
console.log(6); console.log(6);
console.log((a(), b(), 6)); console.log((a(), b(), 6));
} }
expect_stdout: true
} }
issue_485_crashing_1530: { issue_485_crashing_1530: {

View File

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

View File

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

View File

@@ -14,6 +14,7 @@ issue_1321_no_debug: {
x["a"] = 2 * x.b; x["a"] = 2 * x.b;
console.log(x.b, x["a"]); console.log(x.b, x["a"]);
} }
expect_stdout: true
} }
issue_1321_debug: { issue_1321_debug: {
@@ -33,6 +34,7 @@ issue_1321_debug: {
x["_$foo$_"] = 2 * x.a; x["_$foo$_"] = 2 * x.a;
console.log(x.a, x["_$foo$_"]); console.log(x.a, x["_$foo$_"]);
} }
expect_stdout: true
} }
issue_1321_with_quoted: { issue_1321_with_quoted: {
@@ -51,4 +53,5 @@ issue_1321_with_quoted: {
x["b"] = 2 * x.a; x["b"] = 2 * x.a;
console.log(x.a, x["b"]); 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_exact: "for(var i=1;i<=4;++i)if(!(i<=2))console.log(i);"
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; var CONST_FOO_ANN = !1;
if (CONST_FOO_ANN) console.log('reachable'); if (CONST_FOO_ANN) console.log('reachable');
} }
expect_stdout: true
} }
drop_console_2: { drop_console_2: {
@@ -225,6 +226,7 @@ issue_1254_negate_iife_true: {
})()(); })()();
} }
expect_exact: '(function(){return function(){console.log("test")}})()();' expect_exact: '(function(){return function(){console.log("test")}})()();'
expect_stdout: true
} }
issue_1254_negate_iife_nested: { issue_1254_negate_iife_nested: {
@@ -240,6 +242,7 @@ issue_1254_negate_iife_nested: {
})()()()()(); })()()()()();
} }
expect_exact: '(function(){return function(){console.log("test")}})()()()()();' expect_exact: '(function(){return function(){console.log("test")}})()()()()();'
expect_stdout: true
} }
conditional: { conditional: {

View File

@@ -29,4 +29,5 @@ dont_mangle_arguments: {
})(5,6,7); })(5,6,7);
} }
expect_exact: "(function(){var arguments=arguments,o=9;console.log(o,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: { this_binding_collapse_vars: {
options = { options = {
collapse_vars: true, collapse_vars: true,
toplevel: true,
}; };
input: { input: {
var c = a; c(); var c = a; c();

View File

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

View File

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

View File

@@ -166,6 +166,7 @@ keep_collapse_const_in_own_block_scope: {
console.log(i); console.log(i);
console.log(c); console.log(c);
} }
expect_stdout: true
} }
keep_collapse_const_in_own_block_scope_2: { 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(i);
console.log(c); console.log(c);
} }
expect_stdout: true
} }
evaluate: { evaluate: {
@@ -295,7 +297,15 @@ issue_186_beautify: {
else else
bar(); 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: { issue_186_beautify_ie8: {
@@ -314,7 +324,17 @@ issue_186_beautify_ie8: {
else else
bar(); 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: { issue_186_bracketize: {
@@ -374,7 +394,19 @@ issue_186_beautify_bracketize: {
else else
bar(); 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: { issue_186_beautify_bracketize_ie8: {
@@ -394,5 +426,17 @@ issue_186_beautify_bracketize_ie8: {
else else
bar(); 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"}; 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: [ expect_warnings: [
"WARN: Output exceeds 10 characters" "WARN: Output exceeds 10 characters"
] ]
@@ -22,7 +28,12 @@ just_enough: {
return { c: 42, d: a(), e: "foo"}; 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: [ expect_warnings: [
] ]
} }

View File

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

View File

@@ -58,6 +58,7 @@ reduce_vars: {
})(); })();
console.log(2); console.log(2);
} }
expect_stdout: true
} }
modified: { modified: {
@@ -166,7 +167,7 @@ modified: {
console.log(A ? 'yes' : 'no'); console.log(A ? 'yes' : 'no');
console.log(B ? 'yes' : 'no'); console.log(B ? 'yes' : 'no');
} }
} }
} }
unsafe_evaluate: { unsafe_evaluate: {
@@ -401,6 +402,7 @@ iife: {
console.log(0, 1 * b, 5); console.log(0, 1 * b, 5);
}(1, 2, 3); }(1, 2, 3);
} }
expect_stdout: true
} }
iife_new: { iife_new: {
@@ -420,6 +422,7 @@ iife_new: {
console.log(0, 1 * b, 5); console.log(0, 1 * b, 5);
}(1, 2, 3); }(1, 2, 3);
} }
expect_stdout: true
} }
multi_def: { multi_def: {
@@ -707,6 +710,7 @@ toplevel_on: {
expect: { expect: {
console.log(3); console.log(3);
} }
expect_stdout: true
} }
toplevel_off: { toplevel_off: {
@@ -724,6 +728,7 @@ toplevel_off: {
var x = 3; var x = 3;
console.log(x); console.log(x);
} }
expect_stdout: true
} }
toplevel_on_loops_1: { toplevel_on_loops_1: {
@@ -751,6 +756,7 @@ toplevel_on_loops_1: {
})(); })();
while (x); while (x);
} }
expect_stdout: true
} }
toplevel_off_loops_1: { toplevel_off_loops_1: {
@@ -779,6 +785,7 @@ toplevel_off_loops_1: {
bar(); bar();
while (x); while (x);
} }
expect_stdout: true
} }
toplevel_on_loops_2: { toplevel_on_loops_2: {
@@ -1121,6 +1128,7 @@ defun_label: {
}(2)); }(2));
}(); }();
} }
expect_stdout: true
} }
double_reference: { double_reference: {
@@ -1144,3 +1152,215 @@ double_reference: {
} }
} }
} }
iife_arguments_1: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function(x) {
console.log(x() === arguments[0]);
})(function f() {
return f;
});
}
expect: {
(function(x) {
console.log(x() === arguments[0]);
})(function f() {
return f;
});
}
expect_stdout: true
}
iife_arguments_2: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function() {
var x = function f() {
return f;
};
console.log(x() === arguments[0]);
})();
}
expect: {
(function() {
console.log(function f() {
return f;
}() === arguments[0]);
})();
}
expect_stdout: true
}
iife_eval_1: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function(x) {
console.log(x() === eval("x"));
})(function f() {
return f;
});
}
expect: {
(function(x) {
console.log(x() === eval("x"));
})(function f() {
return f;
});
}
expect_stdout: true
}
iife_eval_2: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function() {
var x = function f() {
return f;
};
console.log(x() === eval("x"));
})();
}
expect: {
(function() {
var x = function f() {
return f;
};
console.log(x() === eval("x"));
})();
}
expect_stdout: true
}
iife_func_side_effects: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function(a, b, c) {
return b();
})(x(), function() {
return y();
}, z());
}
expect: {
(function(a, b, c) {
return function() {
return y();
}();
})(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: { do_screw: {
options = { screw_ie8: true }; options = {
screw_ie8: true,
}
beautify = { beautify = {
screw_ie8: true, screw_ie8: true,
ascii_only: true ascii_only: true,
}; }
input: {
input: f("\v"); f("\v");
expect_exact: 'f("\\v");'; }
expect_exact: 'f("\\v");'
} }
dont_screw: { dont_screw: {
options = { screw_ie8: false }; options = {
beautify = { screw_ie8: false, ascii_only: true }; screw_ie8: false,
}
input: f("\v"); beautify = {
expect_exact: 'f("\\x0B");'; screw_ie8: false,
ascii_only: true,
}
input: {
f("\v");
}
expect_exact: 'f("\\x0B");'
} }
do_screw_constants: { do_screw_constants: {
@@ -119,6 +128,7 @@ do_screw_try_catch_undefined: {
return void 0===o return void 0===o
} }
} }
expect_stdout: true
} }
dont_screw_try_catch_undefined: { dont_screw_try_catch_undefined: {
@@ -147,6 +157,7 @@ dont_screw_try_catch_undefined: {
return n === undefined return n === undefined
} }
} }
expect_stdout: true
} }
reduce_vars: { reduce_vars: {
@@ -182,3 +193,41 @@ reduce_vars: {
} }
} }
} }
issue_1586_1: {
options = {
screw_ie8: false,
}
mangle = {
screw_ie8: false,
}
input: {
function f() {
try {
} catch (err) {
console.log(err.message);
}
}
}
expect_exact: "function f(){try{}catch(c){console.log(c.message)}}"
expect_stdout: true
}
issue_1586_2: {
options = {
screw_ie8: true,
}
mangle = {
screw_ie8: true,
}
input: {
function f() {
try {
} catch (err) {
console.log(err.message);
}
}
}
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) {} switch (x = 5, y) {}
with (x = 5, obj); with (x = 5, obj);
} }
expect_stdout: true
} }
lift_sequences_1: { lift_sequences_1: {
@@ -103,15 +104,18 @@ lift_sequences_1: {
lift_sequences_2: { lift_sequences_2: {
options = { sequences: true, evaluate: true }; options = { sequences: true, evaluate: true };
input: { input: {
var foo, bar; var foo = 1, bar;
foo.x = (foo = {}, 10); foo.x = (foo = {}, 10);
bar = (bar = {}, 10); bar = (bar = {}, 10);
console.log(foo, bar);
} }
expect: { expect: {
var foo, bar; var foo = 1, bar;
foo.x = (foo = {}, 10), foo.x = (foo = {}, 10),
bar = {}, bar = 10; bar = {}, bar = 10,
console.log(foo, bar);
} }
expect_stdout: true
} }
lift_sequences_3: { 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: { for_sequences: {
options = { sequences: true }; options = { sequences: true };
input: { input: {
@@ -230,6 +251,7 @@ negate_iife_for: {
for (!function() {}(), i = 0; i < 5; i++) console.log(i); for (!function() {}(), i = 0; i < 5; i++) console.log(i);
for (function() {}(); i < 5; i++) console.log(i); for (function() {}(); i < 5; i++) console.log(i);
} }
expect_stdout: true
} }
iife: { 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 @@
for (var i = 0; i < 1; i++)

View File

@@ -152,7 +152,7 @@ describe("bin/uglifyjs", function () {
}); });
}); });
it("Should process inline source map", function(done) { 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) { exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
@@ -238,4 +238,17 @@ describe("bin/uglifyjs", function () {
done(); done();
}); });
}); });
it("Should fail with a missing loop body", function(done) {
var command = uglifyjscmd + ' test/input/invalid/loop-no-body.js';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/loop-no-body.js:2,0");
assert.strictEqual(lines[1], "for (var i = 0; i < 1; i++) ");
assert.strictEqual(lines[2], " ^");
assert.strictEqual(lines[3], "SyntaxError: Unexpected token: eof (undefined)");
done();
});
});
}); });

View File

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

View File

@@ -6,10 +6,22 @@ var U = require("../tools/node");
var path = require("path"); var path = require("path");
var fs = require("fs"); var fs = require("fs");
var assert = require("assert"); var assert = require("assert");
var vm = require("vm");
var tests_dir = path.dirname(module.filename); var tests_dir = path.dirname(module.filename);
var failures = 0; var failures = 0;
var failed_files = {}; 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(); run_compress_tests();
if (failures) { if (failures) {
@@ -71,10 +83,15 @@ function test_directory(dir) {
} }
function as_toplevel(input, mangle_options) { function as_toplevel(input, mangle_options) {
if (input instanceof U.AST_BlockStatement) input = input.body; if (!(input instanceof U.AST_BlockStatement))
else if (input instanceof U.AST_Statement) input = [ input ]; throw new Error("Unsupported input syntax");
else throw new Error("Unsupported input syntax"); for (var i = 0; i < input.body.length; i++) {
var toplevel = new U.AST_Toplevel({ body: input }); 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); toplevel.figure_out_scope(mangle_options);
return toplevel; return toplevel;
} }
@@ -165,6 +182,36 @@ function run_compress_tests() {
failed_files[file] = 1; 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)); 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) { function get_one_test(name, block) {
var test = { name: name, options: {} }; var test = { name: name, options: {} };
var tw = new U.TreeWalker(function(node, descend){ var tw = new U.TreeWalker(function(node, descend){
@@ -226,28 +290,26 @@ function parse_test(file) {
return true; return true;
} }
if (node instanceof U.AST_LabeledStatement) { if (node instanceof U.AST_LabeledStatement) {
var label = node.label;
assert.ok( 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}]", { tmpl("Unsupported label {name} [{line},{col}]", {
name: node.label.name, name: label.name,
line: node.label.start.line, line: label.start.line,
col: node.label.start.col col: label.start.col
}) })
); );
var stat = node.body; var stat = node.body;
if (stat instanceof U.AST_BlockStatement) { if (label.name == "expect_exact") {
if (stat.body.length == 1) stat = stat.body[0]; test[label.name] = read_string(stat);
else if (stat.body.length == 0) stat = new U.AST_EmptyStatement(); } else if (label.name == "expect_stdout") {
} if (stat.TYPE == "SimpleStatement" && stat.body instanceof U.AST_Boolean) {
if (node.label.name === "expect_exact") { test[label.name] = stat.body.value;
if (!(stat.TYPE === "SimpleStatement" && stat.body.TYPE === "String")) { } else {
throw new Error( test[label.name] = read_string(stat) + "\n";
"The value of the expect_exact clause should be a string, " +
"like `expect_exact: \"some.exact.javascript;\"`");
} }
test[node.label.name] = stat.body.start.value
} else { } else {
test[node.label.name] = stat; test[label.name] = stat;
} }
return true; return true;
} }
@@ -269,3 +331,19 @@ function evaluate(code) {
code = make_code(code, { beautify: true }); code = make_code(code, { beautify: true });
return new Function("return(" + code + ")")(); 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;
}
}