Compare commits

..

59 Commits

Author SHA1 Message Date
Alex Lam S.L
94b19a9c46 harmony-v3.1.8 2017-11-07 06:05:40 +08:00
alexlamsl
bcf95ac02c update tests 2017-11-07 04:49:57 +08:00
alexlamsl
e11cec1ab8 Merge branch 'master' into harmony 2017-11-07 04:30:40 +08:00
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
0c43519097 harmony-v3.1.7 2017-11-05 17:25:57 +08:00
alexlamsl
352a7de204 update tests 2017-11-05 16:48:00 +08:00
alexlamsl
df9c8dfd72 Merge branch 'master' into harmony-v3.1.7 2017-11-05 15:47:40 +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
kzc
29bbc41dfe hoist_props: implement limited hoisting of class expressions (#2415) 2017-10-30 23:20:54 +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
d535daa2c7 harmony-v3.1.6 2017-10-29 18:58:58 +08:00
alexlamsl
0a9cdb6c73 handle computed properties correctly 2017-10-29 17:46:25 +08:00
alexlamsl
3ae34177a6 merge #2391 & #2393 2017-10-29 17:14:52 +08:00
alexlamsl
086cb33163 Merge branch 'master' into harmony-v3.1.6 2017-10-29 13:23:39 +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
6371e2ee63 consistently reduce const safe literals (#2411)
fixes #2406
2017-10-28 11:36:44 +08:00
Alex Lam S.L
6ab73c7bd5 fix & improve AST_TemplateString (#2410)
- resolve `semicolons:false` ambiguity with tagged literals
- allow `side_effects` to work on template literals
- traverse `AST_TemplateString` properly

fixes #2401
2017-10-28 11:36:09 +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
Tom MacWright
2848596280 docs: Fix spelling and style (#2395) 2017-10-24 04:53:56 +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
7d9a8596a9 fix dead_code on AST_Destructuring (#2392)
fixes #2383
2017-10-23 00:34:34 +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
44352eb26a harmony-v3.1.5 2017-10-22 01:49:55 +08:00
alexlamsl
9f1c72ae28 update test
Sub-optimal result due to block scope.
2017-10-22 00:38:16 +08:00
alexlamsl
c60fa67827 Merge branch 'master' into harmony-v3.1.5 2017-10-22 00:35:00 +08:00
Alex Lam S.L
96439ca246 v3.1.5 2017-10-22 00:27:26 +08:00
Thomas Sauer
f9c57dfee0 Allow 'yield' as method name (#2382)
fixes #2381
2017-10-21 14:22:39 +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
kzc
6bf5fea008 option formatting in docs (#2374)
- reintroduce compress documentation for keep_fnames and unsafe_methods
- reintroduce keep_fnames in mangle option docs
- order compress & mangle options
2017-10-18 05:23:53 +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
b6a7ca292e deduplicate AST_Super & AST_This logic (#2366) 2017-10-17 04:19:53 +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
27 changed files with 3430 additions and 503 deletions

View File

@@ -102,7 +102,7 @@ a double dash to prevent input files being used as option arguments:
sequences. sequences.
--config-file <file> Read `minify()` options from JSON file. --config-file <file> Read `minify()` options from JSON file.
-d, --define <expr>[=value] Global definitions. -d, --define <expr>[=value] Global definitions.
--ecma <version> Specifiy ECMAScript release: 5, 6, 7 or 8. --ecma <version> Specify ECMAScript release: 5, 6, 7 or 8.
--ie8 Support non-standard Internet Explorer 8. --ie8 Support non-standard Internet Explorer 8.
Equivalent to setting `ie8: true` in `minify()` Equivalent to setting `ie8: true` in `minify()`
for `compress`, `mangle` and `output` options. for `compress`, `mangle` and `output` options.
@@ -219,7 +219,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
@@ -234,7 +234,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
``` ```
@@ -604,7 +604,7 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
## Compress options ## Compress options
- `arrows` (default `true`) -- Converts `()=>{return x}` to `()=>x`. Class - `arrows` (default: `true`) -- Converts `()=>{return x}` to `()=>x`. Class
and object literal methods will also be converted to arrow expressions if and object literal methods will also be converted to arrow expressions if
the resultant code is shorter: `m(){return x}` becomes `m:()=>x`. the resultant code is shorter: `m(){return x}` becomes `m:()=>x`.
This transform requires that the `ecma` compress option is set to `6` or greater. This transform requires that the `ecma` compress option is set to `6` or greater.
@@ -622,8 +622,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
`!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary `!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary
nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
- `computed_props` -- default `true`. Transforms constant computed properties - `computed_props` (default: `true`) -- Transforms constant computed properties
into regular ones: `{["computed"]: 1}` is converted into `{computed: 1}`. into regular ones: `{["computed"]: 1}` is converted to `{computed: 1}`.
- `conditionals` (default: `true`) -- apply optimizations for `if`-s and conditional - `conditionals` (default: `true`) -- apply optimizations for `if`-s and conditional
expressions expressions
@@ -637,7 +637,7 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `drop_debugger` (default: `true`) -- remove `debugger;` statements - `drop_debugger` (default: `true`) -- remove `debugger;` statements
- `ecma` -- default `5`. Pass `6` or greater to enable `compress` options that - `ecma` (default: `5`) -- Pass `6` or greater to enable `compress` options that
will transform ES5 code into smaller ES6+ equivalent forms. will transform ES5 code into smaller ES6+ equivalent forms.
- `evaluate` (default: `true`) -- attempt to evaluate constant expressions - `evaluate` (default: `true`) -- attempt to evaluate constant expressions
@@ -649,6 +649,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)
@@ -662,6 +668,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.
@@ -726,7 +736,9 @@ 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_arrows` (default `false`) -- Convert ES5 style anonymous function - `unsafe` (default: `false`) -- apply "unsafe" transformations (discussion below)
- `unsafe_arrows` (default: `false`) -- Convert ES5 style anonymous function
expressions to arrow functions if the function body does not reference `this`. expressions to arrow functions if the function body does not reference `this`.
Note: it is not always safe to perform this conversion if code relies on the Note: it is not always safe to perform this conversion if code relies on the
the function having a `prototype`, which arrow functions lack. the function having a `prototype`, which arrow functions lack.
@@ -739,14 +751,19 @@ 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.
- `unsafe_math` (default: `false`) -- optimize numerical expressions like - `unsafe_math` (default: `false`) -- optimize numerical expressions like
`2 * x * 3` into `6 * x`, which may give imprecise floating point results. `2 * x * 3` into `6 * x`, which may give imprecise floating point results.
- `unsafe_methods` (default: false) -- Converts `{ m: function(){} }` to
`{ m(){} }`. `ecma` must be set to `6` or greater to enable this transform.
If `unsafe_methods` is a RegExp then key/value pairs with keys matching the
RegExp will be converted to concise methods.
Note: if enabled there is a risk of getting a "`<method name>` is not a
constructor" TypeError should any code try to `new` the former function.
- `unsafe_proto` (default: `false`) -- optimize expressions like - `unsafe_proto` (default: `false`) -- optimize expressions like
`Array.prototype.slice.call(a)` into `[].slice.call(a)` `Array.prototype.slice.call(a)` into `[].slice.call(a)`
@@ -761,17 +778,21 @@ 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_classnames` (default `false`). Pass `true` to not mangle class names. - `keep_classnames` (default `false`). Pass `true` to not mangle class names.
- `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.
- `safari10` (default `false`). Pass `true` to work around the Safari 10 loop - `safari10` (default `false`). Pass `true` to work around the Safari 10 loop
iterator [bug](https://bugs.webkit.org/show_bug.cgi?id=171041) iterator [bug](https://bugs.webkit.org/show_bug.cgi?id=171041)
"Cannot declare a let variable twice". "Cannot declare a let variable twice".
@@ -1088,7 +1109,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

View File

@@ -44,7 +44,7 @@ program.option("-o, --output <file>", "Output file (default STDOUT).");
program.option("--comments [filter]", "Preserve copyright comments in the output."); program.option("--comments [filter]", "Preserve copyright comments in the output.");
program.option("--config-file <file>", "Read minify() options from JSON file."); program.option("--config-file <file>", "Read minify() options from JSON file.");
program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("define")); program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("define"));
program.option("--ecma <version>", "Specifiy ECMAScript release: 5, 6, 7 or 8."); program.option("--ecma <version>", "Specify ECMAScript release: 5, 6, 7 or 8.");
program.option("--ie8", "Support non-standard Internet Explorer 8."); program.option("--ie8", "Support non-standard Internet Explorer 8.");
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name."); program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
program.option("--name-cache <file>", "File to hold mangled name mappings."); program.option("--name-cache <file>", "File to hold mangled name mappings.");

View File

@@ -448,10 +448,8 @@ var AST_TemplateString = DEFNODE("TemplateString", "segments", {
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function(){
this.segments.forEach(function(seg, i){ this.segments.forEach(function(seg){
if (i % 2 !== 0) { seg._walk(visitor);
seg._walk(visitor);
}
}); });
}); });
} }
@@ -1042,7 +1040,7 @@ var AST_This = DEFNODE("This", null, {
var AST_Super = DEFNODE("Super", null, { var AST_Super = DEFNODE("Super", null, {
$documentation: "The `super` symbol", $documentation: "The `super` symbol",
}, AST_Symbol); }, AST_This);
var AST_Constant = DEFNODE("Constant", null, { var AST_Constant = DEFNODE("Constant", null, {
$documentation: "Base class for all constants", $documentation: "Base class for all constants",

File diff suppressed because it is too large Load Diff

View File

@@ -141,11 +141,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) {
@@ -203,9 +201,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

@@ -262,7 +262,7 @@ function OutputStream(options) {
} }
} : noop; } : noop;
var requireSemicolonChars = makePredicate("( [ + * / - , ."); var requireSemicolonChars = makePredicate("( [ + * / - , . `");
function print(str) { function print(str) {
str = String(str); str = String(str);
@@ -1685,9 +1685,6 @@ function OutputStream(options) {
DEFPRINT(AST_Symbol, function (self, output) { DEFPRINT(AST_Symbol, function (self, output) {
self._do_print(output); self._do_print(output);
}); });
DEFPRINT(AST_SymbolDeclaration, function(self, output){
self._do_print(output);
});
DEFPRINT(AST_Hole, noop); DEFPRINT(AST_Hole, noop);
DEFPRINT(AST_This, function(self, output){ DEFPRINT(AST_This, function(self, output){
output.print("this"); output.print("this");

View File

@@ -2565,7 +2565,7 @@ function parse($TEXT, options) {
unexpected(tmp); unexpected(tmp);
} }
case "name": case "name":
if (tmp.value == "yield" && !is_token(peek(), "punc", ":") if (tmp.value == "yield" && !is_token(peek(), "punc", ":") && !is_token(peek(), "punc", "(")
&& S.input.has_directive("use strict") && !is_in_generator()) { && S.input.has_directive("use strict") && !is_in_generator()) {
token_error(tmp, "Unexpected yield identifier inside strict mode"); token_error(tmp, "Unexpected yield identifier inside strict mode");
} }

View File

@@ -262,11 +262,7 @@ TreeTransformer.prototype = new TreeWalker;
}); });
_(AST_TemplateString, function(self, tw) { _(AST_TemplateString, function(self, tw) {
for (var i = 0; i < self.segments.length; i++) { self.segments = do_list(self.segments, tw);
if (!(self.segments[i] instanceof AST_TemplateSegment)) {
self.segments[i] = self.segments[i].transform(tw);
}
}
}); });
_(AST_PrefixedTemplateString, function(self, tw) { _(AST_PrefixedTemplateString, function(self, tw) {

View File

@@ -4,7 +4,7 @@
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony", "homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
"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

@@ -203,50 +203,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

@@ -314,17 +314,12 @@ issue_2105_1: {
}); });
} }
expect: { expect: {
(() => { ({
var quux = () => { prop() {
console.log;
console.log("PASS"); console.log("PASS");
}; }
return { }).prop();
prop() {
console.log;
quux();
}
};
})().prop();
} }
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=4" node_version: ">=4"
@@ -360,17 +355,12 @@ issue_2105_2: {
}); });
} }
expect: { expect: {
(() => { ({
var quux = () => { prop: () => {
console.log;
console.log("PASS"); console.log("PASS");
}; }
return { }).prop();
prop: () => {
console.log;
quux();
}
};
})().prop();
} }
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=6" node_version: ">=6"
@@ -631,3 +621,31 @@ issue_2271: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
concise_method_with_super: {
options = {
arrows: true,
}
input: {
var o = {
f: "FAIL",
g() {
return super.f;
}
}
Object.setPrototypeOf(o, { f: "PASS" });
console.log(o.g());
}
expect: {
var o = {
f: "FAIL",
g() {
return super.f;
}
}
Object.setPrototypeOf(o, { f: "PASS" });
console.log(o.g());
}
expect_stdout: "PASS"
node_version: ">=4"
}

View File

@@ -1487,6 +1487,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) {
@@ -1509,6 +1510,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) {
@@ -1636,6 +1638,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);
@@ -1658,6 +1661,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);
@@ -1683,6 +1687,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);
@@ -1758,6 +1763,7 @@ iife_2: {
}(foo); }(foo);
} }
expect: { expect: {
var foo;
!function(x) { !function(x) {
console.log(x); console.log(x);
}(bar()); }(bar());
@@ -2044,6 +2050,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;
@@ -2060,6 +2067,7 @@ chained_1: {
chained_2: { chained_2: {
options = { options = {
collapse_vars: true, collapse_vars: true,
unused: true,
} }
input: { input: {
var a; var a;
@@ -2150,7 +2158,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);
} }
@@ -2160,6 +2168,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;
@@ -2174,6 +2183,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;
@@ -2183,9 +2193,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);
}
} }
} }
@@ -2215,10 +2226,11 @@ unused_orig: {
expect: { expect: {
var a = 1; var a = 1;
console.log(function(b) { console.log(function(b) {
var a;
var c = b; var c = b;
for (var d in c) for (var d in c) {
var a;
return --b + (a = c[0]); return --b + (a = c[0]);
}
a && a.NaN; a && a.NaN;
}([2]), a); }([2]), a);
} }
@@ -2565,7 +2577,9 @@ issue_2250_1: {
options = { options = {
collapse_vars: true, collapse_vars: true,
conditionals: true, conditionals: true,
passes: 2,
reduce_vars: true, reduce_vars: true,
unused: true,
} }
input: { input: {
function f(x) { function f(x) {
@@ -2607,6 +2621,7 @@ issue_2250_2: {
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
toplevel: true, toplevel: true,
unused: true,
} }
input: { input: {
{ {
@@ -2808,69 +2823,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

@@ -560,3 +560,64 @@ global_fns: {
"RangeError", "RangeError",
] ]
} }
issue_2383_1: {
options = {
conditionals: true,
dead_code: true,
evaluate: true,
}
input: {
if (0) {
var {x, y} = foo();
}
}
expect: {
var x, y;
}
}
issue_2383_2: {
options = {
conditionals: true,
dead_code: true,
evaluate: true,
}
input: {
if (0) {
var {
x = 0,
y: [ w, , { z, p: q = 7 } ] = [ 1, 2, { z: 3 } ]
} = {};
}
console.log(x, q, w, z);
}
expect: {
var x, w, z, q;
console.log(x, q, w, z);
}
expect_stdout: "undefined undefined undefined undefined"
node_version: ">=6"
}
issue_2383_3: {
options = {
conditionals: true,
dead_code: true,
evaluate: true,
}
input: {
var b = 7, y = 8;
if (0) {
var a = 1, [ x, y, z ] = [ 2, 3, 4 ], b = 5;
}
console.log(a, x, y, z, b);
}
expect: {
var b = 7, y = 8;
var a, x, y, z, b;
console.log(a, x, y, z, b);
}
expect_stdout: "undefined undefined 8 undefined 7"
node_version: ">=6"
}

View File

@@ -1291,15 +1291,14 @@ issue_2063: {
} }
expect: { expect: {
var a; var a;
var a;
} }
} }
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,
@@ -1325,17 +1324,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

@@ -480,10 +480,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(
@@ -496,9 +497,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
@@ -724,10 +725,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;
@@ -746,8 +748,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();
} }
} }
@@ -1288,3 +1290,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

@@ -902,10 +902,10 @@ issue_2349b: {
evaluate: true, evaluate: true,
inline: true, inline: true,
passes: 3, passes: 3,
properties: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
side_effects: true, side_effects: true,
unsafe: true,
unsafe_arrows: true, unsafe_arrows: true,
unused: true, unused: true,
} }

View File

@@ -0,0 +1,513 @@
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"
}
hoist_class: {
options = {
comparisons: true,
evaluate: true,
hoist_props: true,
inline: true,
keep_fnames: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function run(c, v) {
return new c(v).value;
}
var o = {
p: class Foo {
constructor(value) {
this.value = value * 10;
}
},
x: 1,
y: 2,
};
console.log(o.p.name, o.p === o.p, run(o.p, o.x), run(o.p, o.y));
}
expect: {
function run(c, v) {
return new c(v).value;
}
var o_p = class Foo {
constructor(value) {
this.value = 10 * value;
}
};
console.log(o_p.name, true, run(o_p, 1), run(o_p, 2));
}
node_version: ">=6"
expect_stdout: "Foo true 10 20"
}
hoist_class_with_new: {
options = {
comparisons: true,
evaluate: true,
hoist_props: true,
inline: true,
keep_fnames: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
p: class Foo {
constructor(value) {
this.value = value * 10;
}
},
x: 1,
y: 2,
};
console.log(o.p.name, o.p === o.p, new o.p(o.x).value, new o.p(o.y).value);
}
expect: {
// FIXME: class `o.p` not hoisted due to `new`
var o = {
p: class Foo {
constructor(value) {
this.value = 10 * value;
}
},
x: 1,
y: 2
};
console.log(o.p.name, o.p == o.p, new o.p(o.x).value, new o.p(o.y).value);
}
node_version: ">=6"
expect_stdout: "Foo true 10 20"
}
hoist_function_with_call: {
options = {
comparisons: true,
evaluate: true,
hoist_props: true,
inline: true,
keep_fnames: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
p: function Foo(value) {
return 10 * value;
},
x: 1,
y: 2
};
console.log(o.p.name, o.p === o.p, o.p(o.x), o.p(o.y));
}
expect: {
var o_p = function Foo(value){
return 10 * value
};
console.log(o_p.name, true, o_p(1), o_p(2));
}
expect_stdout: "Foo true 10 20"
}
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

@@ -177,6 +177,7 @@ export_mangle_2: {
export_mangle_3: { export_mangle_3: {
options = { options = {
collapse_vars: true, collapse_vars: true,
unused: true,
} }
mangle = { mangle = {
toplevel: true, toplevel: true,
@@ -195,6 +196,7 @@ export_mangle_3: {
export_mangle_4: { export_mangle_4: {
options = { options = {
collapse_vars: true, collapse_vars: true,
unused: true,
} }
mangle = { mangle = {
toplevel: true, toplevel: true,

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: {
@@ -250,7 +254,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: {
@@ -679,8 +684,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({
@@ -698,8 +703,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({
@@ -723,8 +728,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;
@@ -748,8 +753,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() {}
@@ -772,8 +777,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({
@@ -792,8 +797,8 @@ issue_2208_5: {
issue_2208_6: { issue_2208_6: {
options = { options = {
inline: true, inline: true,
properties: true,
side_effects: true, side_effects: true,
unsafe: true,
} }
input: { input: {
console.log({ console.log({
@@ -809,9 +814,11 @@ issue_2208_6: {
issue_2208_7: { issue_2208_7: {
options = { options = {
ecma: 6,
inline: true, inline: true,
properties: true,
side_effects: true, side_effects: true,
unsafe: true, unsafe_arrows: true,
} }
input: { input: {
console.log({ console.log({
@@ -829,9 +836,11 @@ issue_2208_7: {
issue_2208_8: { issue_2208_8: {
options = { options = {
ecma: 6,
inline: true, inline: true,
properties: true,
side_effects: true, side_effects: true,
unsafe: true, unsafe_arrows: true,
} }
input: { input: {
console.log({ console.log({
@@ -851,17 +860,17 @@ issue_2208_8: {
return x(); return x();
} }
}.p()); }.p());
console.log(async function() { console.log((async () => {
return await x(); return await x();
}()); })());
} }
} }
issue_2208_9: { issue_2208_9: {
options = { options = {
inline: true, inline: true,
properties: true,
side_effects: true, side_effects: true,
unsafe: true,
} }
input: { input: {
a = 42; a = 42;
@@ -1052,3 +1061,243 @@ unsafe_methods_regex: {
] ]
node_version: ">=6" node_version: ">=6"
} }
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"
}
computed_property: {
options = {
properties: true,
side_effects: true,
}
input: {
console.log({
a: "bar",
[console.log("foo")]: 42,
}.a);
}
expect: {
console.log([
"bar",
console.log("foo")
][0]);
}
expect_stdout: [
"foo",
"bar"
]
node_version: ">=4"
}
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

@@ -59,7 +59,7 @@ template_string_with_constant_expression: {
var foo = `${4 + 4} equals 4 + 4`; var foo = `${4 + 4} equals 4 + 4`;
} }
expect: { expect: {
var foo = `8 equals 4 + 4`; var foo = "8 equals 4 + 4";
} }
} }
@@ -89,21 +89,21 @@ template_string_with_predefined_constants: {
var c = `${4**14}`; // 8 in template vs 9 chars - 268435456 var c = `${4**14}`; // 8 in template vs 9 chars - 268435456
} }
expect: { expect: {
var foo = `This is undefined`; var foo = "This is undefined";
var bar = `This is NaN`; var bar = "This is NaN";
var baz = `This is null`; var baz = "This is null";
var foofoo = `This is ${1/0}`; var foofoo = `This is ${1/0}`;
var foobar = "This is ${1/0}"; var foobar = "This is ${1/0}";
var foobaz = 'This is ${1/0}'; var foobaz = 'This is ${1/0}';
var barfoo = "This is ${NaN}"; var barfoo = "This is ${NaN}";
var bazfoo = "This is ${null}"; var bazfoo = "This is ${null}";
var bazbaz = `This is ${1/0}`; var bazbaz = `This is ${1/0}`;
var barbar = `This is NaN`; var barbar = "This is NaN";
var barbar = "This is ${0/0}"; var barbar = "This is ${0/0}";
var barber = 'This is ${0/0}'; var barber = 'This is ${0/0}';
var a = `4194304`; var a = "4194304";
var b = `16777216`; // Potential for further concatentation var b = "16777216"; // Potential for further concatentation
var c = `${4**14}`; // Not worth converting var c = `${4**14}`; // Not worth converting
} }
} }
@@ -123,7 +123,7 @@ template_string_evaluate_with_many_segments: {
} }
expect: { expect: {
var foo = `Hello ${guest()}, welcome to ${location()}.`; var foo = `Hello ${guest()}, welcome to ${location()}.`;
var bar = `1234567890`; var bar = "1234567890";
var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`; var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`;
var buzz = `1${foobar()}2${foobar()}3${foobar()}`; var buzz = `1${foobar()}2${foobar()}3${foobar()}`;
} }
@@ -159,7 +159,7 @@ template_string_to_normal_string: {
var bar = "Decimals " + `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`; var bar = "Decimals " + `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`;
} }
expect: { expect: {
var foo = `This is undefined`; var foo = "This is undefined";
var bar = "Decimals 1234567890"; var bar = "Decimals 1234567890";
} }
} }
@@ -192,7 +192,7 @@ evaluate_nested_templates: {
var baz = `${`${`${`foo`}`}`}`; var baz = `${`${`${`foo`}`}`}`;
} }
expect: { expect: {
var baz = `foo`; var baz = "foo";
} }
} }
@@ -241,8 +241,8 @@ enforce_double_quotes_and_evaluate: {
var baz = `Hello ${world()}`; var baz = `Hello ${world()}`;
} }
expect: { expect: {
var foo = `Hello world`; var foo = "Hello world";
var bar = `Hello world`; var bar = "Hello world";
var baz = `Hello ${world()}`; var baz = `Hello ${world()}`;
} }
} }
@@ -260,8 +260,8 @@ enforce_single_quotes_and_evaluate: {
var baz = `Hello ${world()}`; var baz = `Hello ${world()}`;
} }
expect: { expect: {
var foo = `Hello world`; var foo = "Hello world";
var bar = `Hello world`; var bar = "Hello world";
var baz = `Hello ${world()}`; var baz = `Hello ${world()}`;
} }
} }
@@ -339,7 +339,7 @@ escape_dollar_curly: {
console.log(`${1-0}\${2-0}$\{3-0}${4-0}`) console.log(`${1-0}\${2-0}$\{3-0}${4-0}`)
console.log(`$${""}{not an expression}`) console.log(`$${""}{not an expression}`)
} }
expect_exact: "console.log(`\\${ beep }`);console.log(`1\\${2-0}\\${3-0}4`);console.log(`\\${not an expression}`);" expect_exact: 'console.log("${ beep }");console.log("1${2-0}${3-0}4");console.log("${not an expression}");'
} }
template_starting_with_newline: { template_starting_with_newline: {
@@ -400,3 +400,61 @@ issue_1856_ascii_only: {
} }
expect_exact: "console.log(`\\\\n\\\\r\\\\u2028\\\\u2029\\n\\r\\u2028\\u2029`);" expect_exact: "console.log(`\\\\n\\\\r\\\\u2028\\\\u2029\\n\\r\\u2028\\u2029`);"
} }
side_effects: {
options = {
evaluate: true,
side_effects: true,
}
input: {
`t1`;
tag`t2`;
`t${3}`;
tag`t${4}`;
console.log(`
t${5}`);
function f(a) {
`t6${a}`;
a = `t7${a}` & a;
a = `t8${b}` | a;
a = f`t9${a}` ^ a;
}
}
expect: {
tag`t2`;
tag`t${4}`;
console.log("\nt5");
function f(a) {
a &= `t7${a}`;
a = `t8${b}` | a;
a = f`t9${a}` ^ a;
}
}
}
simple_string: {
options = {
computed_props: true,
evaluate: true,
properties: true,
}
input: {
console.log({[`foo`]: 1}[`foo`], `hi` == "hi", `world`);
}
expect: {
console.log([ 1 ][0], true, "world");
}
expect_stdout: "1 true 'world'"
node_version: ">=4"
}
semicolons: {
beautify = {
semicolons: false,
}
input: {
foo;
`bar`;
}
expect_exact: "foo;`bar`\n"
}

View File

@@ -102,4 +102,15 @@ describe("Yield", function() {
assert.throws(test(tests[i]), fail, tests[i]); assert.throws(test(tests[i]), fail, tests[i]);
} }
}); });
it("Should allow yield to be used as class/object property name", function() {
var input = [
'"use strict";',
"({yield:42});",
"({yield(){}});",
"(class{yield(){}});",
"class C{yield(){}}",
].join("");
assert.strictEqual(UglifyJS.minify(input, { compress: false }).code, input);
});
}); });

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": {