Compare commits

..

38 Commits

Author SHA1 Message Date
Alex Lam S.L
38bfb73f06 v3.1.8 2017-11-07 03:55:16 +08:00
Alex Lam S.L
bbedbf4ea0 handle circular function reference gracefully (#2446)
fixes #2442
2017-11-07 02:37:23 +08:00
Alex Lam S.L
2cfb5aa7da account for eval & with in reduce_vars (#2441)
fixes #2440
2017-11-06 16:10:57 +08:00
Alex Lam S.L
6c45101870 consolidate & enhance unused (#2439)
- defer declaration removal in `collapse_vars`
- account for `AST_SymbolFunarg` in deduplication
- private accounting for `collapse_vars`
- avoid issues with identity reference due to deep cloning

fixes #2437
2017-11-06 14:25:10 +08:00
Alex Lam S.L
2c2fd89e34 inline single-use functions that are not constant expressions (#2434)
fixes #2428
2017-11-05 22:14:11 +08:00
Alex Lam S.L
f46281e2b7 v3.1.7 2017-11-05 15:03:19 +08:00
Alex Lam S.L
25a18883f5 tweak #2424 (#2432) 2017-11-05 12:49:14 +08:00
Alex Lam S.L
5b4b07e9a7 extend function inlining safety checks (#2430) 2017-11-05 06:18:45 +08:00
Alex Lam S.L
a8aa28a7a6 consolidate single-use function reduction (#2427)
fixes #2423
2017-11-05 04:27:01 +08:00
Alex Lam S.L
fe5a68f9d5 maintain call argument order in collapse_vars (#2426)
fixes #2425
2017-11-05 00:00:18 +08:00
Alex Lam S.L
71e61153b1 improve variations on call arguments for ufuzz (#2424) 2017-11-04 16:29:42 +08:00
Alex Lam S.L
c8b6f4733d reduce this within functions (#2421)
- only replace same-scope usages
- augment `test/ufuzz.js` to test for `this`


fixes #2420
2017-11-04 00:31:37 +08:00
Alex Lam S.L
a48f87abf2 compress new function containing this (#2417) 2017-10-30 23:19:27 +08:00
Alex Lam S.L
2fd927a7cc v3.1.6 2017-10-29 12:38:10 +08:00
Alex Lam S.L
8428326ea1 enhance properties (#2412)
- trim array items only if `side_effects`
- extend to non-identifier properties
2017-10-29 04:11:26 +08:00
Alex Lam S.L
31f8209193 remove dead code (#2405) 2017-10-27 14:28:09 +08:00
Alex Lam S.L
9b0f86f5a1 fix reduce_vars on AST_Array.length (#2404) 2017-10-27 02:33:37 +08:00
Alex Lam S.L
ee082ace1b compress self comparisons (#2398) 2017-10-26 01:16:12 +08:00
kzc
ae67a49850 document compress option hoist_props (#2399) 2017-10-25 14:03:43 +08:00
Alex Lam S.L
4178289c38 implement hoist_props (#2396)
fixes #2377
2017-10-25 03:38:11 +08:00
Alex Lam S.L
74ae16f9f8 fix unsafe reduce_vars on arrays & objects (#2397) 2017-10-24 22:10:36 +08:00
Tom MacWright
1968203d83 docs: Fix spelling and style (#2395) 2017-10-24 04:59:12 +08:00
Alex Lam S.L
86ea38a259 enhance unsafe evaluate of arrays & objects (#2394) 2017-10-24 02:58:30 +08:00
Alex Lam S.L
8a713e449f deduplicate declarations regardless of toplevel (#2393) 2017-10-23 01:00:50 +08:00
Alex Lam S.L
24aa07855b safer properties transform (#2391)
`{ a: x, b: y }.a` => `[ x, y ][0]`
- `x` cannot be function containing `this`

`[ x, y, z ][1]` => `(x, z, y)`
- only if `z` is side-effect-free
2017-10-22 20:10:13 +08:00
Alex Lam S.L
5fd723f143 fix unsafe expansion of object literals (#2390) 2017-10-22 15:00:36 +08:00
Alex Lam S.L
516eaef50c fix unsafe evaluation of AST_Sub (#2389) 2017-10-22 13:14:15 +08:00
Alex Lam S.L
4ae1fb3ed8 fix unsafe evaluation of objects (#2388) 2017-10-22 04:19:40 +08:00
Alex Lam S.L
011123223b fix unsafe escape analysis in reduce_vars (#2387) 2017-10-22 03:23:31 +08:00
Alex Lam S.L
96439ca246 v3.1.5 2017-10-22 00:27:26 +08:00
Alex Lam S.L
c927cea632 unsafe fix-ups for #2351 (#2379) 2017-10-21 04:08:26 +08:00
Alex Lam S.L
9f4b98f8e4 backport #2374 (#2376) 2017-10-19 23:02:27 +08:00
Alex Lam S.L
0f2ef3367c enhance collapse_vars around lazy operations (#2369) 2017-10-19 04:52:00 +08:00
Alex Lam S.L
7e5b5cac97 fix AST_PropAccess in collapse_vars (take 3) (#2375)
Suppress scanning beyond assignment to `a.b`
2017-10-18 02:54:51 +08:00
Alex Lam S.L
c1346e06b7 clean up lazy operator detection (#2373) 2017-10-17 23:25:45 +08:00
Alex Lam S.L
0d2fe8e3ef fix AST_PropAccess in collapse_vars (take 2) (#2372)
fixes #2364
2017-10-17 22:59:15 +08:00
Alex Lam S.L
f2b9c11e2a fix AST_PropAccess in collapse_vars (#2370)
fixes #2364
2017-10-17 18:33:03 +08:00
Alex Lam S.L
fe647b083e account for side-effects from AST_This in collapse_vars (#2365) 2017-10-17 01:18:55 +08:00
16 changed files with 2886 additions and 408 deletions

View File

@@ -221,7 +221,7 @@ to prevent the `require`, `exports` and `$` names from being changed.
is a separate step, different from variable name mangling. Pass is a separate step, different from variable name mangling. Pass
`--mangle-props` to enable it. It will mangle all properties in the `--mangle-props` to enable it. It will mangle all properties in the
input code with the exception of built in DOM properties and properties input code with the exception of built in DOM properties and properties
in core javascript classes. For example: in core JavaScript classes. For example:
```javascript ```javascript
// example.js // example.js
@@ -236,7 +236,7 @@ x.bar_ = 2;
x["baz_"] = 3; x["baz_"] = 3;
console.log(x.calc()); console.log(x.calc());
``` ```
Mangle all properties (except for javascript `builtins`): Mangle all properties (except for JavaScript `builtins`):
```bash ```bash
$ uglifyjs example.js -c -m --mangle-props $ uglifyjs example.js -c -m --mangle-props
``` ```
@@ -515,7 +515,6 @@ if (result.error) throw result.error;
```javascript ```javascript
{ {
warnings: false,
parse: { parse: {
// parse options // parse options
}, },
@@ -538,6 +537,7 @@ if (result.error) throw result.error;
nameCache: null, // or specify a name cache object nameCache: null, // or specify a name cache object
toplevel: false, toplevel: false,
ie8: false, ie8: false,
warnings: false,
} }
``` ```
@@ -632,6 +632,12 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `hoist_funs` (default: `true`) -- hoist function declarations - `hoist_funs` (default: `true`) -- hoist function declarations
- `hoist_props` (default: `false`) -- hoist properties from constant object and
array literals into regular variables subject to a set of constraints. For example:
`var o={p:1, q:2}; f(o.p, o.q);` is converted to `f(1, 2);`. Note: `hoist_props`
works best with `mangle` enabled, the `compress` option `passes` set to `2` or higher,
and the `compress` option `toplevel` enabled.
- `hoist_vars` (default: `false`) -- hoist `var` declarations (this is `false` - `hoist_vars` (default: `false`) -- hoist `var` declarations (this is `false`
by default because it seems to increase the size of the output in general) by default because it seems to increase the size of the output in general)
@@ -645,6 +651,10 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
compressor from discarding unused function arguments. You need this compressor from discarding unused function arguments. You need this
for code which relies on `Function.length`. for code which relies on `Function.length`.
- `keep_fnames` (default: `false`) -- Pass `true` to prevent the
compressor from discarding function names. Useful for code relying on
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
- `keep_infinity` (default: `false`) -- default `false`. Pass `true` to prevent `Infinity` from - `keep_infinity` (default: `false`) -- default `false`. Pass `true` to prevent `Infinity` from
being compressed into `1/0`, which may cause performance issues on Chrome. being compressed into `1/0`, which may cause performance issues on Chrome.
@@ -709,6 +719,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
`foo === void 0`. Note: recommend to set this value to `false` for IE10 and `foo === void 0`. Note: recommend to set this value to `false` for IE10 and
earlier versions due to known issues. earlier versions due to known issues.
- `unsafe` (default: `false`) -- apply "unsafe" transformations (discussion below)
- `unsafe_comps` (default: `false`) -- Reverse `<` and `<=` to `>` and `>=` to - `unsafe_comps` (default: `false`) -- Reverse `<` and `<=` to `>` and `>=` to
allow improved compression. This might be unsafe when an at least one of two allow improved compression. This might be unsafe when an at least one of two
operands is an object with computed values due the use of methods like `get`, operands is an object with computed values due the use of methods like `get`,
@@ -716,8 +728,6 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
comparison are switching. Compression only works if both `comparisons` and comparison are switching. Compression only works if both `comparisons` and
`unsafe_comps` are both set to true. `unsafe_comps` are both set to true.
- `unsafe` (default: `false`) -- apply "unsafe" transformations (discussion below)
- `unsafe_Func` (default: `false`) -- compress and mangle `Function(args, code)` - `unsafe_Func` (default: `false`) -- compress and mangle `Function(args, code)`
when both `args` and `code` are string literals. when both `args` and `code` are string literals.
@@ -738,15 +748,19 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
## Mangle options ## Mangle options
- `eval` (default `false`). Pass `true` to mangle names visible in scopes
where `eval` or `with` are used.
- `keep_fnames` (default `false`). Pass `true` to not mangle function names.
Useful for code relying on `Function.prototype.name`. See also: the `keep_fnames`
[compress option](#compress-options).
- `reserved` (default `[]`). Pass an array of identifiers that should be - `reserved` (default `[]`). Pass an array of identifiers that should be
excluded from mangling. Example: `["foo", "bar"]`. excluded from mangling. Example: `["foo", "bar"]`.
- `toplevel` (default `false`). Pass `true` to mangle names declared in the - `toplevel` (default `false`). Pass `true` to mangle names declared in the
top level scope. top level scope.
- `eval` (default `false`). Pass `true` to mangle names visible in scopes
where `eval` or `with` are used.
Examples: Examples:
```javascript ```javascript
@@ -1052,7 +1066,7 @@ in total it's a bit more than just using UglifyJS's own parser.
### Uglify Fast Minify Mode ### Uglify Fast Minify Mode
It's not well known, but whitespace removal and symbol mangling accounts It's not well known, but whitespace removal and symbol mangling accounts
for 95% of the size reduction in minified code for most javascript - not for 95% of the size reduction in minified code for most JavaScript - not
elaborate code transforms. One can simply disable `compress` to speed up elaborate code transforms. One can simply disable `compress` to speed up
Uglify builds by 3 to 4 times. In this fast `mangle`-only mode Uglify has Uglify builds by 3 to 4 times. In this fast `mangle`-only mode Uglify has
comparable minify speeds and gzip sizes to comparable minify speeds and gzip sizes to

File diff suppressed because it is too large Load Diff

View File

@@ -137,11 +137,9 @@ function minify(files, options) {
if (options.wrap) { if (options.wrap) {
toplevel = toplevel.wrap_commonjs(options.wrap); toplevel = toplevel.wrap_commonjs(options.wrap);
} }
if (timings) timings.scope1 = Date.now();
if (options.compress) toplevel.figure_out_scope(options.mangle);
if (timings) timings.compress = Date.now(); if (timings) timings.compress = Date.now();
if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel); if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
if (timings) timings.scope2 = Date.now(); if (timings) timings.scope = Date.now();
if (options.mangle) toplevel.figure_out_scope(options.mangle); if (options.mangle) toplevel.figure_out_scope(options.mangle);
if (timings) timings.mangle = Date.now(); if (timings) timings.mangle = Date.now();
if (options.mangle) { if (options.mangle) {
@@ -199,9 +197,9 @@ function minify(files, options) {
if (timings) { if (timings) {
timings.end = Date.now(); timings.end = Date.now();
result.timings = { result.timings = {
parse: 1e-3 * (timings.scope1 - timings.parse), parse: 1e-3 * (timings.compress - timings.parse),
scope: 1e-3 * (timings.compress - timings.scope1 + timings.mangle - timings.scope2), compress: 1e-3 * (timings.scope - timings.compress),
compress: 1e-3 * (timings.scope2 - timings.compress), scope: 1e-3 * (timings.mangle - timings.scope),
mangle: 1e-3 * (timings.properties - timings.mangle), mangle: 1e-3 * (timings.properties - timings.mangle),
properties: 1e-3 * (timings.output - timings.properties), properties: 1e-3 * (timings.output - timings.properties),
output: 1e-3 * (timings.end - timings.output), output: 1e-3 * (timings.end - timings.output),

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": "3.1.4", "version": "3.1.8",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=0.8.0"
}, },

View File

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

View File

@@ -1388,6 +1388,7 @@ issue_1605_1: {
options = { options = {
collapse_vars: true, collapse_vars: true,
toplevel: false, toplevel: false,
unused: true,
} }
input: { input: {
function foo(x) { function foo(x) {
@@ -1410,6 +1411,7 @@ issue_1605_2: {
options = { options = {
collapse_vars: true, collapse_vars: true,
toplevel: "vars", toplevel: "vars",
unused: true,
} }
input: { input: {
function foo(x) { function foo(x) {
@@ -1537,6 +1539,7 @@ issue_1631_3: {
var_side_effects_1: { var_side_effects_1: {
options = { options = {
collapse_vars: true, collapse_vars: true,
unused: true,
} }
input: { input: {
var print = console.log.bind(console); var print = console.log.bind(console);
@@ -1559,6 +1562,7 @@ var_side_effects_1: {
var_side_effects_2: { var_side_effects_2: {
options = { options = {
collapse_vars: true, collapse_vars: true,
unused: true,
} }
input: { input: {
var print = console.log.bind(console); var print = console.log.bind(console);
@@ -1584,6 +1588,7 @@ var_side_effects_3: {
collapse_vars: true, collapse_vars: true,
pure_getters: true, pure_getters: true,
unsafe: true, unsafe: true,
unused: true,
} }
input: { input: {
var print = console.log.bind(console); var print = console.log.bind(console);
@@ -1659,6 +1664,7 @@ iife_2: {
}(foo); }(foo);
} }
expect: { expect: {
var foo;
!function(x) { !function(x) {
console.log(x); console.log(x);
}(bar()); }(bar());
@@ -1945,6 +1951,7 @@ ref_scope: {
chained_1: { chained_1: {
options = { options = {
collapse_vars: true, collapse_vars: true,
unused: true,
} }
input: { input: {
var a = 2; var a = 2;
@@ -1961,6 +1968,7 @@ chained_1: {
chained_2: { chained_2: {
options = { options = {
collapse_vars: true, collapse_vars: true,
unused: true,
} }
input: { input: {
var a; var a;
@@ -2051,7 +2059,7 @@ inner_lvalues: {
console.log(null, a, b); console.log(null, a, b);
} }
expect: { expect: {
var a, b = 10; var b = 10;
var a = (--b || a || 3).toString(), c = --b + -a; var a = (--b || a || 3).toString(), c = --b + -a;
console.log(null, a, b); console.log(null, a, b);
} }
@@ -2061,6 +2069,7 @@ inner_lvalues: {
double_def: { double_def: {
options = { options = {
collapse_vars: true, collapse_vars: true,
unused: true,
} }
input: { input: {
var a = x, a = a && y; var a = x, a = a && y;
@@ -2075,6 +2084,7 @@ double_def: {
toplevel_single_reference: { toplevel_single_reference: {
options = { options = {
collapse_vars: true, collapse_vars: true,
unused: true,
} }
input: { input: {
var a; var a;
@@ -2084,9 +2094,10 @@ toplevel_single_reference: {
} }
} }
expect: { expect: {
var a; for (var b in x) {
for (var b in x) var a;
b(a = b); b(a = b);
}
} }
} }
@@ -2534,69 +2545,535 @@ issue_2319_3: {
expect_stdout: "true" expect_stdout: "true"
} }
prop_side_effects_1: { issue_2365: {
options = { options = {
collapse_vars: true, collapse_vars: true,
evaluate: true, pure_getters: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
} }
input: { input: {
var C = 1; console.log(function(a) {
console.log(C); var b = a.f;
var obj = { a.f++;
bar: function() { return b;
return C + C; }({ f: 1 }));
console.log(function() {
var a = { f: 1 }, b = a.f;
a.f++;
return b;
}());
console.log({
f: 1,
g: function() {
var b = this.f;
this.f++;
return b;
} }
}; }.g());
console.log(obj.bar());
} }
expect: { expect: {
console.log(1); console.log(function(a) {
var b = a.f;
a.f++;
return b;
}({ f: 1 }));
console.log(function() {
var a = { f: 1 }, b = a.f;
a.f++;
return b;
}());
console.log({ console.log({
bar: function() { f: 1,
return 2; g: function() {
var b = this.f;
this.f++;
return b;
} }
}.bar()); }.g());
} }
expect_stdout: [ expect_stdout: [
"1", "1",
"2", "1",
"1",
] ]
} }
prop_side_effects_2: { issue_2364_1: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
function inc(obj) {
return obj.count++;
}
function foo() {
var first = arguments[0];
var result = inc(first);
return foo.amount = first.count, result;
}
var data = {
count: 0,
};
var answer = foo(data);
console.log(foo.amount, answer);
}
expect: {
function inc(obj) {
return obj.count++;
}
function foo() {
var first = arguments[0];
var result = inc(first);
return foo.amount = first.count, result;
}
var data = {
count: 0
};
var answer = foo(data);
console.log(foo.amount, answer);
}
expect_stdout: "1 0"
}
issue_2364_2: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
function callValidate() {
var validate = compilation.validate;
var result = validate.apply(null, arguments);
return callValidate.errors = validate.errors, result;
}
}
expect: {
function callValidate() {
var validate = compilation.validate;
var result = validate.apply(null, arguments);
return callValidate.errors = validate.errors, result;
}
}
}
issue_2364_3: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
function inc(obj) {
return obj.count++;
}
function foo(bar) {
var result = inc(bar);
return foo.amount = bar.count, result;
}
var data = {
count: 0,
};
var answer = foo(data);
console.log(foo.amount, answer);
}
expect: {
function inc(obj) {
return obj.count++;
}
function foo(bar) {
var result = inc(bar);
return foo.amount = bar.count, result;
}
var data = {
count: 0,
};
var answer = foo(data);
console.log(foo.amount, answer);
}
expect_stdout: "1 0"
}
issue_2364_4: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
function inc(obj) {
return obj.count++;
}
function foo(bar, baz) {
var result = inc(bar);
return foo.amount = baz.count, result;
}
var data = {
count: 0,
};
var answer = foo(data, data);
console.log(foo.amount, answer);
}
expect: {
function inc(obj) {
return obj.count++;
}
function foo(bar, baz) {
var result = inc(bar);
return foo.amount = baz.count, result;
}
var data = {
count: 0,
};
var answer = foo(data, data);
console.log(foo.amount, answer);
}
expect_stdout: "1 0"
}
issue_2364_5: {
options = { options = {
collapse_vars: true, collapse_vars: true,
evaluate: true, evaluate: true,
inline: true, pure_getters: true,
passes: 2, properties: true,
pure_getters: "strict",
reduce_vars: true, reduce_vars: true,
side_effects: true,
toplevel: true,
unsafe: true,
unused: true, unused: true,
} }
input: { input: {
var C = 1; function f0(o, a, h) {
console.log(C); var b = 3 - a;
var obj = { var obj = o;
bar: function() { var seven = 7;
return C + C; var prop = 'run';
} var t = obj[prop](b)[seven] = h;
}; return t;
console.log(obj.bar()); }
} }
expect: { expect: {
console.log(1); function f0(o, a, h) {
console.log(2); return o.run(3 - a)[7] = h;
}
}
}
issue_2364_6: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
function f(a, b) {
var c = a.p;
b.p = "FAIL";
return c;
}
var o = {
p: "PASS"
}
console.log(f(o, o));
}
expect: {
function f(a, b) {
var c = a.p;
b.p = "FAIL";
return c;
}
var o = {
p: "PASS"
}
console.log(f(o, o));
}
expect_stdout: "PASS"
}
issue_2364_7: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
function f(a, b) {
var c = a.p;
b.f();
return c;
}
var o = {
p: "PASS",
f: function() {
this.p = "FAIL";
}
}
console.log(f(o, o));
}
expect: {
function f(a, b) {
var c = a.p;
b.f();
return c;
}
var o = {
p: "PASS",
f: function() {
this.p = "FAIL";
}
}
console.log(f(o, o));
}
expect_stdout: "PASS"
}
issue_2364_8: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
function f(a, b, c) {
var d = a[b.f = function() {
return "PASS";
}];
return c.f(d);
}
var o = {
f: function() {
return "FAIL";
}
};
console.log(f({}, o, o));
}
expect: {
function f(a, b, c) {
var d = a[b.f = function() {
return "PASS";
}];
return c.f(d);
}
var o = {
f: function() {
return "FAIL";
}
};
console.log(f({}, o, o));
}
expect_stdout: "PASS"
}
issue_2364_9: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
function f(a, b) {
var d = a();
return b.f(d);
}
var o = {
f: function() {
return "FAIL";
}
};
console.log(f(function() {
o.f = function() {
return "PASS";
};
}, o));
}
expect: {
function f(a, b) {
var d = a();
return b.f(d);
}
var o = {
f: function() {
return "FAIL";
}
};
console.log(f(function() {
o.f = function() {
return "PASS";
};
}, o));
}
expect_stdout: "PASS"
}
pure_getters_chain: {
options = {
collapse_vars: true,
pure_getters: true,
unused: true,
}
input: {
function o(t, r) {
var a = t[1], s = t[2], o = t[3], i = t[5];
return a <= 23 && s <= 59 && o <= 59 && (!r || i);
}
console.log(o([ , 23, 59, 59, , 42], 1));
}
expect: {
function o(t, r) {
return t[1] <= 23 && t[2] <= 59 && t[3] <= 59 && (!r || t[5]);
}
console.log(o([ , 23, 59, 59, , 42], 1));
}
expect_stdout: "42"
}
conditional_1: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f(a, b) {
var c = "";
var d = b ? ">" : "<";
if (a) c += "=";
return c += d;
}
console.log(f(0, 0), f(0, 1), f(1, 0), f(1, 1));
}
expect: {
function f(a, b) {
var c = "";
if (a) c += "=";
return c += b ? ">" : "<";
}
console.log(f(0, 0), f(0, 1), f(1, 0), f(1, 1));
}
expect_stdout: "< > =< =>"
}
conditional_2: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f(a, b) {
var c = a + 1, d = a + 2;
return b ? c : d;
}
console.log(f(3, 0), f(4, 1));
}
expect: {
function f(a, b) {
return b ? a + 1 : a + 2;
}
console.log(f(3, 0), f(4, 1));
}
expect_stdout: "5 5"
}
issue_2425_1: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var a = 8;
(function(b) {
b.toString();
})(--a, a |= 10);
console.log(a);
}
expect: {
var a = 8;
(function(b) {
b.toString();
})(--a, a |= 10);
console.log(a);
}
expect_stdout: "15"
}
issue_2425_2: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var a = 8;
(function(b, c) {
b.toString();
})(--a, a |= 10);
console.log(a);
}
expect: {
var a = 8;
(function(b, c) {
b.toString();
})(--a, a |= 10);
console.log(a);
}
expect_stdout: "15"
}
issue_2425_3: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var a = 8;
(function(b, b) {
b.toString();
})(--a, a |= 10);
console.log(a);
}
expect: {
var a = 8;
(function(b, b) {
(a |= 10).toString();
})(--a);
console.log(a);
}
expect_stdout: "15"
}
issue_2437: {
options = {
collapse_vars: true,
conditionals: true,
inline: true,
join_vars: true,
reduce_vars: true,
side_effects: true,
sequences: true,
toplevel: true,
unused: true,
}
input: {
function foo() {
bar();
}
function bar() {
if (xhrDesc) {
var req = new XMLHttpRequest();
var result = !!req.onreadystatechange;
Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {});
return result;
}
else {
var req = new XMLHttpRequest();
var detectFunc = function () { };
req.onreadystatechange = detectFunc;
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
req.onreadystatechange = null;
return result;
}
}
foo();
}
expect: {
!function() {
if (xhrDesc)
return result = !!(req = new XMLHttpRequest()).onreadystatechange,
Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
result;
var req = new XMLHttpRequest(), detectFunc = function() {};
req.onreadystatechange = detectFunc;
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
req.onreadystatechange = null;
}();
} }
expect_stdout: [
"1",
"2",
]
} }

View File

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

View File

@@ -1109,11 +1109,11 @@ var_catch_toplevel: {
} }
} }
issue_2105: { issue_2105_1: {
options = { options = {
collapse_vars: true, collapse_vars: true,
inline: true, inline: true,
passes: 3, passes: 2,
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
unused: true, unused: true,
@@ -1139,17 +1139,50 @@ issue_2105: {
}); });
} }
expect: { expect: {
(function() { ({
var quux = function() { prop: function() {
console.log;
console.log("PASS"); console.log("PASS");
}; }
return { }).prop();
prop: function() { }
console.log; expect_stdout: "PASS"
quux(); }
issue_2105_2: {
options = {
collapse_vars: true,
inline: true,
passes: 2,
properties: true,
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
unsafe: true,
unused: true,
}
input: {
!function(factory) {
factory();
}( function() {
return function(fn) {
fn()().prop();
}( function() {
function bar() {
var quux = function() {
console.log("PASS");
}, foo = function() {
console.log;
quux();
};
return { prop: foo };
} }
}; return bar;
})().prop(); } );
});
}
expect: {
console.log("PASS");
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }

View File

@@ -386,10 +386,11 @@ unsafe_object_accessor: {
} }
} }
unsafe_function: { prop_function: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true properties: true,
side_effects: true,
} }
input: { input: {
console.log( console.log(
@@ -402,9 +403,9 @@ unsafe_function: {
expect: { expect: {
console.log( console.log(
({a:{b:1},b:function(){}}) + 1, ({a:{b:1},b:function(){}}) + 1,
({b:function(){}}, {b:1}) + 1, ({b:1}) + 1,
({a:{b:1}}, function(){}) + 1, function(){} + 1,
({b:function(){}}, {b:1}).b + 1 2
); );
} }
expect_stdout: true expect_stdout: true
@@ -630,10 +631,11 @@ unsafe_string_bad_index: {
expect_stdout: true expect_stdout: true
} }
unsafe_prototype_function: { prototype_function: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true properties: true,
side_effects: true,
} }
input: { input: {
var a = ({valueOf: 0}) < 1; var a = ({valueOf: 0}) < 1;
@@ -652,8 +654,8 @@ unsafe_prototype_function: {
var d = ({toString: 0}) + ""; var d = ({toString: 0}) + "";
var e = (({valueOf: 0}) + "")[2]; var e = (({valueOf: 0}) + "")[2];
var f = (({toString: 0}) + "")[2]; var f = (({toString: 0}) + "")[2];
var g = ({}, 0)(); var g = 0();
var h = ({}, 0)(); var h = 0();
} }
} }
@@ -1195,3 +1197,40 @@ issue_2231_2: {
} }
expect_stdout: true expect_stdout: true
} }
self_comparison_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var o = { n: NaN };
console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n);
}
expect: {
console.log(false, false, true, true, "number");
}
expect_stdout: "false false true true 'number'"
}
self_comparison_2: {
options = {
evaluate: true,
hoist_props: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = { n: NaN };
console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n);
}
expect: {
console.log(false, false, true, true, "number");
}
expect_stdout: "false false true true 'number'"
}

View File

@@ -151,13 +151,13 @@ issue_1841_2: {
function_returning_constant_literal: { function_returning_constant_literal: {
options = { options = {
reduce_vars: true,
unsafe: true,
toplevel: true,
evaluate: true,
cascade: true,
unused: true,
inline: true, inline: true,
passes: 2,
properties: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
} }
input: { input: {
function greeter() { function greeter() {
@@ -508,3 +508,41 @@ issue_2114_2: {
} }
expect_stdout: "2" expect_stdout: "2"
} }
issue_2428: {
options = {
collapse_vars: true,
inline: true,
passes: 2,
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
function bar(k) {
console.log(k);
}
function foo(x) {
return bar(x);
}
function baz(a) {
foo(a);
}
baz(42);
baz("PASS");
}
expect: {
function baz(a) {
console.log(a);
}
baz(42);
baz("PASS");
}
expect_stdout: [
"42",
"PASS",
]
}

View File

@@ -0,0 +1,399 @@
issue_2377_1: {
options = {
evaluate: true,
inline: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var obj = {
foo: 1,
bar: 2,
square: function(x) {
return x * x;
},
cube: function(x) {
return x * x * x;
},
};
console.log(obj.foo, obj.cube(3));
}
expect: {
var obj_foo = 1, obj_cube = function(x) {
return x * x * x;
};
console.log(obj_foo, obj_cube(3));
}
expect_stdout: "1 27"
}
issue_2377_2: {
options = {
evaluate: true,
inline: true,
hoist_props: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var obj = {
foo: 1,
bar: 2,
square: function(x) {
return x * x;
},
cube: function(x) {
return x * x * x;
},
};
console.log(obj.foo, obj.cube(3));
}
expect: {
console.log(1, function(x) {
return x * x * x;
}(3));
}
expect_stdout: "1 27"
}
issue_2377_3: {
options = {
evaluate: true,
inline: true,
hoist_props: true,
passes: 3,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var obj = {
foo: 1,
bar: 2,
square: function(x) {
return x * x;
},
cube: function(x) {
return x * x * x;
},
};
console.log(obj.foo, obj.cube(3));
}
expect: {
console.log(1, 27);
}
expect_stdout: "1 27"
}
direct_access_1: {
options = {
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 0;
var obj = {
a: 1,
b: 2,
};
for (var k in obj) a++;
console.log(a, obj.a);
}
expect: {
var a = 0;
var obj = {
a: 1,
b: 2,
};
for (var k in obj) a++;
console.log(a, obj.a);
}
expect_stdout: "2 1"
}
direct_access_2: {
options = {
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = { a: 1 };
var f = function(k) {
if (o[k]) return "PASS";
};
console.log(f("a"));
}
expect: {
var o = { a: 1 };
console.log(function(k) {
if (o[k]) return "PASS";
}("a"));
}
expect_stdout: "PASS"
}
direct_access_3: {
options = {
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = { a: 1 };
o.b;
console.log(o.a);
}
expect: {
var o = { a: 1 };
o.b;
console.log(o.a);
}
expect_stdout: "1"
}
single_use: {
options = {
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var obj = {
bar: function() {
return 42;
},
};
console.log(obj.bar());
}
expect: {
console.log({
bar: function() {
return 42;
},
}.bar());
}
}
name_collision_1: {
options = {
hoist_props: true,
reduce_vars: true,
toplevel: true,
}
input: {
var obj_foo = 1;
var obj_bar = 2;
function f() {
var obj = {
foo: 3,
bar: 4,
"b-r": 5,
"b+r": 6,
"b!r": 7,
};
console.log(obj_foo, obj.foo, obj.bar, obj["b-r"], obj["b+r"], obj["b!r"]);
}
f();
}
expect: {
var obj_foo = 1;
var obj_bar = 2;
function f() {
var obj_foo$0 = 3,
obj_bar = 4,
obj_b_r = 5,
obj_b_r$0 = 6,
obj_b_r$1 = 7;
console.log(obj_foo, obj_foo$0, obj_bar, obj_b_r, obj_b_r$0, obj_b_r$1);
}
f();
}
expect_stdout: "1 3 4 5 6 7"
}
name_collision_2: {
options = {
hoist_props: true,
reduce_vars: true,
toplevel: true,
}
input: {
var o = {
p: 1,
0: function(x) {
return x;
},
1: function(x) {
return x + 1;
}
}, o__$0 = 2, o__$1 = 3;
console.log(o.p === o.p, o[0](4), o[1](5), o__$0, o__$1);
}
expect: {
var o_p = 1,
o__ = function(x) {
return x;
},
o__$2 = function(x) {
return x + 1;
},
o__$0 = 2,
o__$1 = 3;
console.log(o_p === o_p, o__(4), o__$2(5), o__$0, o__$1);
}
expect_stdout: "true 4 6 2 3"
}
name_collision_3: {
options = {
hoist_props: true,
reduce_vars: true,
toplevel: true,
}
input: {
var o = {
p: 1,
0: function(x) {
return x;
},
1: function(x) {
return x + 1;
}
}, o__$0 = 2, o__$1 = 3;
console.log(o.p === o.p, o[0](4), o[1](5));
}
expect: {
var o_p = 1,
o__ = function(x) {
return x;
},
o__$2 = function(x) {
return x + 1;
},
o__$0 = 2,
o__$1 = 3;
console.log(o_p === o_p, o__(4), o__$2(5));
}
expect_stdout: "true 4 6"
}
contains_this_1: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
u: function() {
return this === this;
},
p: 1
};
console.log(o.p, o.p);
}
expect: {
console.log(1, 1);
}
expect_stdout: "1 1"
}
contains_this_2: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
u: function() {
return this === this;
},
p: 1
};
console.log(o.p, o.p, o.u);
}
expect: {
console.log(1, 1, function() {
return this === this;
});
}
expect_stdout: true
}
contains_this_3: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
u: function() {
return this === this;
},
p: 1
};
console.log(o.p, o.p, o.u());
}
expect: {
var o = {
u: function() {
return this === this;
},
p: 1
};
console.log(o.p, o.p, o.u());
}
expect_stdout: "1 1 true"
}
new_this: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: 1,
b: 2,
f: function(a) {
this.b = a;
}
};
console.log(new o.f(o.a).b, o.b);
}
expect: {
console.log(new function(a) {
this.b = a;
}(1).b, 2);
}
expect_stdout: "1 2"
}

View File

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

View File

@@ -1,7 +1,8 @@
keep_properties: { keep_properties: {
options = { options = {
properties: false evaluate: true,
}; properties: false,
}
input: { input: {
a["foo"] = "bar"; a["foo"] = "bar";
} }
@@ -12,6 +13,7 @@ keep_properties: {
dot_properties: { dot_properties: {
options = { options = {
evaluate: true,
properties: true, properties: true,
} }
beautify = { beautify = {
@@ -37,6 +39,7 @@ dot_properties: {
dot_properties_es5: { dot_properties_es5: {
options = { options = {
evaluate: true,
properties: true, properties: true,
} }
beautify = { beautify = {
@@ -61,8 +64,8 @@ dot_properties_es5: {
sub_properties: { sub_properties: {
options = { options = {
evaluate: true, evaluate: true,
properties: true properties: true,
}; }
input: { input: {
a[0] = 0; a[0] = 0;
a["0"] = 1; a["0"] = 1;
@@ -81,18 +84,18 @@ sub_properties: {
a[3.14] = 3; a[3.14] = 3;
a.if = 4; a.if = 4;
a["foo bar"] = 5; a["foo bar"] = 5;
a[NaN] = 6; a.NaN = 6;
a[null] = 7; a.null = 7;
a[void 0] = 8; a[void 0] = 8;
} }
} }
evaluate_array_length: { evaluate_array_length: {
options = { options = {
evaluate: true,
properties: true, properties: true,
unsafe: true, unsafe: true,
evaluate: true }
};
input: { input: {
a = [1, 2, 3].length; a = [1, 2, 3].length;
a = [1, 2, 3].join()["len" + "gth"]; a = [1, 2, 3].join()["len" + "gth"];
@@ -109,10 +112,10 @@ evaluate_array_length: {
evaluate_string_length: { evaluate_string_length: {
options = { options = {
evaluate: true,
properties: true, properties: true,
unsafe: true, unsafe: true,
evaluate: true }
};
input: { input: {
a = "foo".length; a = "foo".length;
a = ("foo" + "bar")["len" + "gth"]; a = ("foo" + "bar")["len" + "gth"];
@@ -151,7 +154,8 @@ mangle_properties: {
mangle_unquoted_properties: { mangle_unquoted_properties: {
options = { options = {
properties: false evaluate: true,
properties: false,
} }
mangle = { mangle = {
properties: { properties: {
@@ -249,7 +253,8 @@ mangle_debug_suffix: {
mangle_debug_suffix_keep_quoted: { mangle_debug_suffix_keep_quoted: {
options = { options = {
properties: false evaluate: true,
properties: false,
} }
mangle = { mangle = {
properties: { properties: {
@@ -677,8 +682,8 @@ accessor_this: {
issue_2208_1: { issue_2208_1: {
options = { options = {
inline: true, inline: true,
properties: true,
side_effects: true, side_effects: true,
unsafe: true,
} }
input: { input: {
console.log({ console.log({
@@ -696,8 +701,8 @@ issue_2208_1: {
issue_2208_2: { issue_2208_2: {
options = { options = {
inline: true, inline: true,
properties: true,
side_effects: true, side_effects: true,
unsafe: true,
} }
input: { input: {
console.log({ console.log({
@@ -721,8 +726,8 @@ issue_2208_2: {
issue_2208_3: { issue_2208_3: {
options = { options = {
inline: true, inline: true,
properties: true,
side_effects: true, side_effects: true,
unsafe: true,
} }
input: { input: {
a = 42; a = 42;
@@ -746,8 +751,8 @@ issue_2208_3: {
issue_2208_4: { issue_2208_4: {
options = { options = {
inline: true, inline: true,
properties: true,
side_effects: true, side_effects: true,
unsafe: true,
} }
input: { input: {
function foo() {} function foo() {}
@@ -770,8 +775,8 @@ issue_2208_4: {
issue_2208_5: { issue_2208_5: {
options = { options = {
inline: true, inline: true,
properties: true,
side_effects: true, side_effects: true,
unsafe: true,
} }
input: { input: {
console.log({ console.log({
@@ -804,3 +809,219 @@ issue_2256: {
g.keep = g.g; g.keep = g.g;
} }
} }
lhs_prop_1: {
options = {
evaluate: true,
properties: true,
}
input: {
console.log(++{
a: 1
}.a);
}
expect: {
console.log(++{
a: 1
}.a);
}
expect_stdout: "2"
}
lhs_prop_2: {
options = {
evaluate: true,
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
[1][0] = 42;
(function(a) {
a.b = "g";
})("abc");
(function(a) {
a[2] = "g";
})("def");
(function(a) {
a[""] = "g";
})("ghi");
}
expect: {
[1][0] = 42;
"abc".b = "g";
"def"[2] = "g";
"ghi"[""] = "g";
}
}
literal_duplicate_key_side_effects: {
options = {
properties: true,
side_effects: true,
}
input: {
console.log({
a: "FAIL",
a: console.log ? "PASS" : "FAIL"
}.a);
}
expect: {
console.log(console.log ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
}
prop_side_effects_1: {
options = {
evaluate: true,
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var C = 1;
console.log(C);
var obj = {
bar: function() {
return C + C;
}
};
console.log(obj.bar());
}
expect: {
console.log(1);
var obj = {
bar: function() {
return 2;
}
};
console.log(obj.bar());
}
expect_stdout: [
"1",
"2",
]
}
prop_side_effects_2: {
options = {
evaluate: true,
inline: true,
passes: 2,
properties: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var C = 1;
console.log(C);
var obj = {
"": function() {
return C + C;
}
};
console.log(obj[""]());
}
expect: {
console.log(1);
console.log(2);
}
expect_stdout: [
"1",
"2",
]
}
accessor_1: {
options = {
properties: true,
}
input: {
console.log({
a: "FAIL",
get a() {
return "PASS";
}
}.a);
}
expect: {
console.log({
a: "FAIL",
get a() {
return "PASS";
}
}.a);
}
expect_stdout: "PASS"
node_version: ">=4"
}
accessor_2: {
options = {
properties: true,
}
input: {
console.log({
get a() {
return "PASS";
},
set a(v) {},
a: "FAIL"
}.a);
}
expect: {
console.log({
get a() {
return "PASS";
},
set a(v) {},
a: "FAIL"
}.a);
}
expect_stdout: true
}
array_hole: {
options = {
properties: true,
side_effects: true,
}
input: {
console.log(
[ 1, 2, , 3][1],
[ 1, 2, , 3][2],
[ 1, 2, , 3][3]
);
}
expect: {
console.log(2, void 0, 3);
}
expect_stdout: "2 undefined 3"
}
new_this: {
options = {
properties: true,
side_effects: true,
}
input: {
new {
f: function(a) {
this.a = a;
}
}.f(42);
}
expect: {
new function(a) {
this.a = a;
}(42);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -162,6 +162,7 @@ var VALUES = [
'"object"', '"object"',
'"number"', '"number"',
'"function"', '"function"',
'this',
]; ];
var BINARY_OPS_NO_COMMA = [ var BINARY_OPS_NO_COMMA = [
@@ -349,10 +350,10 @@ function createParams() {
return params.join(', '); return params.join(', ');
} }
function createArgs() { function createArgs(recurmax, stmtDepth, canThrow) {
var args = []; var args = [];
for (var n = rng(4); --n >= 0;) { for (var n = rng(4); --n >= 0;) {
args.push(createValue()); args.push(rng(2) ? createValue() : createExpression(recurmax - 1, COMMA_OK, stmtDepth, canThrow));
} }
return args.join(', '); return args.join(', ');
} }
@@ -390,9 +391,10 @@ function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
VAR_NAMES.length = namesLenBefore; VAR_NAMES.length = namesLenBefore;
if (noDecl) s = 'var ' + createVarName(MANDATORY) + ' = ' + s + '(' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ');'; if (noDecl) s = 'var ' + createVarName(MANDATORY) + ' = ' + s;
// avoid "function statements" (decl inside statements) // avoid "function statements" (decl inside statements)
else if (inGlobal || rng(10) > 0) s += 'var ' + createVarName(MANDATORY) + ' = ' + name + '(' + createArgs() + ');'; else if (inGlobal || rng(10) > 0) s += 'var ' + createVarName(MANDATORY) + ' = ' + name;
s += '(' + createArgs(recurmax, stmtDepth, canThrow) + ');';
return s; return s;
} }
@@ -626,6 +628,9 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
case p++: case p++:
case p++: case p++:
return createValue(); return createValue();
case p++:
case p++:
return getVarName();
case p++: case p++:
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow); return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);
case p++: case p++:

View File

@@ -16,11 +16,9 @@
{}, {},
{ {
"compress": { "compress": {
"toplevel": true "hoist_props": true
}, },
"mangle": { "toplevel": true
"toplevel": true
}
}, },
{ {
"compress": { "compress": {