Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
667fc4d08b | ||
|
|
6142117cdd | ||
|
|
ae28a24c7f | ||
|
|
ebe761cad0 | ||
|
|
fa7a7c5c5a | ||
|
|
557636f3b7 | ||
|
|
49fbe9c5ac | ||
|
|
2ac5086831 | ||
|
|
c6cfa04d10 | ||
|
|
346fa12e0e | ||
|
|
cda27b0970 | ||
|
|
3c74047368 | ||
|
|
94525d859f | ||
|
|
1127a2caf3 | ||
|
|
246d9d4e83 | ||
|
|
4c0b0177b6 | ||
|
|
38bfb73f06 | ||
|
|
bbedbf4ea0 | ||
|
|
2cfb5aa7da | ||
|
|
6c45101870 | ||
|
|
2c2fd89e34 | ||
|
|
f46281e2b7 | ||
|
|
25a18883f5 | ||
|
|
5b4b07e9a7 | ||
|
|
a8aa28a7a6 | ||
|
|
fe5a68f9d5 | ||
|
|
71e61153b1 | ||
|
|
c8b6f4733d | ||
|
|
a48f87abf2 | ||
|
|
2fd927a7cc | ||
|
|
8428326ea1 | ||
|
|
31f8209193 | ||
|
|
9b0f86f5a1 | ||
|
|
ee082ace1b | ||
|
|
ae67a49850 | ||
|
|
4178289c38 | ||
|
|
74ae16f9f8 | ||
|
|
1968203d83 | ||
|
|
86ea38a259 | ||
|
|
8a713e449f | ||
|
|
24aa07855b | ||
|
|
5fd723f143 | ||
|
|
516eaef50c | ||
|
|
4ae1fb3ed8 | ||
|
|
011123223b | ||
|
|
96439ca246 | ||
|
|
c927cea632 | ||
|
|
9f4b98f8e4 | ||
|
|
0f2ef3367c | ||
|
|
7e5b5cac97 | ||
|
|
c1346e06b7 | ||
|
|
0d2fe8e3ef | ||
|
|
f2b9c11e2a | ||
|
|
fe647b083e | ||
|
|
dfe4f6c6de | ||
|
|
a09c8ad666 | ||
|
|
ec598c351b | ||
|
|
eba0f93bc0 | ||
|
|
99800d4aa9 | ||
|
|
70d56c951a | ||
|
|
b810e2f8da | ||
|
|
1abe14296e | ||
|
|
6920e898d1 | ||
|
|
dd71639264 | ||
|
|
2dcc552ce0 | ||
|
|
55387e8fd0 | ||
|
|
7e3e9da860 | ||
|
|
00f509405b | ||
|
|
aceb0af36b | ||
|
|
4f0953f7e9 | ||
|
|
182a47bfb1 | ||
|
|
cd27f4ec38 | ||
|
|
8158b1bdcf | ||
|
|
aacf3edc68 | ||
|
|
8b89072190 | ||
|
|
395a17ccda | ||
|
|
3f355866cf | ||
|
|
71d52f147d | ||
|
|
eb7adaa6fc | ||
|
|
e5cf7972ea |
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@@ -15,6 +15,8 @@
|
||||
UglifyJS alone - without third party tools or libraries.
|
||||
Ideally the input should be as small as possible.
|
||||
Post a link to a gist if necessary.
|
||||
|
||||
Issues without a reproducible test case will be closed.
|
||||
-->
|
||||
|
||||
**The `uglifyjs` CLI command executed or `minify()` options used.**
|
||||
|
||||
296
README.md
296
README.md
@@ -150,19 +150,19 @@ debugging your compressed JavaScript. To get a source map, pass
|
||||
|
||||
Additional options:
|
||||
|
||||
- `--source-map filename=<NAME>` to specify the name of the source map.
|
||||
- `--source-map "filename='<NAME>'"` to specify the name of the source map.
|
||||
|
||||
- `--source-map root=<URL>` to pass the URL where the original files can be found.
|
||||
- `--source-map "root='<URL>'"` to pass the URL where the original files can be found.
|
||||
|
||||
- `--source-map "url='<URL>'"` to specify the URL where the source map can be found.
|
||||
Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
|
||||
`//# sourceMappingURL=` directive.
|
||||
|
||||
- `--source-map url=<URL>` to specify the URL where the source map can be found.
|
||||
|
||||
For example:
|
||||
|
||||
uglifyjs js/file1.js js/file2.js \
|
||||
-o foo.min.js -c -m \
|
||||
--source-map root="http://foo.com/src",url=foo.min.js.map
|
||||
--source-map "root='http://foo.com/src',url='foo.min.js.map'"
|
||||
|
||||
The above will compress and mangle `file1.js` and `file2.js`, will drop the
|
||||
output in `foo.min.js` and the source map in `foo.min.js.map`. The source
|
||||
@@ -181,8 +181,8 @@ CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →
|
||||
compressed JS by mapping every token in the compiled JS to its original
|
||||
location.
|
||||
|
||||
To use this feature pass `--source-map content="/path/to/input/source.map"`
|
||||
or `--source-map content=inline` if the source map is included inline with
|
||||
To use this feature pass `--source-map "content='/path/to/input/source.map'"`
|
||||
or `--source-map "content=inline"` if the source map is included inline with
|
||||
the sources.
|
||||
|
||||
## CLI compress options
|
||||
@@ -203,17 +203,15 @@ Example:
|
||||
To enable the mangler you need to pass `--mangle` (`-m`). The following
|
||||
(comma-separated) options are supported:
|
||||
|
||||
- `toplevel` — mangle names declared in the top level scope (disabled by
|
||||
default).
|
||||
- `toplevel` (default `false`) -- mangle names declared in the top level scope.
|
||||
|
||||
- `eval` — mangle names visible in scopes where `eval` or `with` are used
|
||||
(disabled by default).
|
||||
- `eval` (default `false`) -- mangle names visible in scopes where `eval` or `with` are used.
|
||||
|
||||
When mangling is enabled but you want to prevent certain names from being
|
||||
mangled, you can declare those names with `--mangle reserved` — pass a
|
||||
comma-separated list of names. For example:
|
||||
|
||||
uglifyjs ... -m reserved=[$,require,exports]
|
||||
uglifyjs ... -m reserved=['$','require','exports']
|
||||
|
||||
to prevent the `require`, `exports` and `$` names from being changed.
|
||||
|
||||
@@ -223,7 +221,7 @@ to prevent the `require`, `exports` and `$` names from being changed.
|
||||
is a separate step, different from variable name mangling. Pass
|
||||
`--mangle-props` to enable it. It will mangle all properties in the
|
||||
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
|
||||
// example.js
|
||||
@@ -238,7 +236,7 @@ x.bar_ = 2;
|
||||
x["baz_"] = 3;
|
||||
console.log(x.calc());
|
||||
```
|
||||
Mangle all properties (except for javascript `builtins`):
|
||||
Mangle all properties (except for JavaScript `builtins`):
|
||||
```bash
|
||||
$ uglifyjs example.js -c -m --mangle-props
|
||||
```
|
||||
@@ -510,11 +508,13 @@ if (result.error) throw result.error;
|
||||
|
||||
- `ie8` (default `false`) - set to `true` to support IE8.
|
||||
|
||||
- `keep_fnames` (default: `false`) - pass `true` to prevent discarding or mangling
|
||||
of function names. Useful for code relying on `Function.prototype.name`.
|
||||
|
||||
## Minify options structure
|
||||
|
||||
```javascript
|
||||
{
|
||||
warnings: false,
|
||||
parse: {
|
||||
// parse options
|
||||
},
|
||||
@@ -537,6 +537,7 @@ if (result.error) throw result.error;
|
||||
nameCache: null, // or specify a name cache object
|
||||
toplevel: false,
|
||||
ie8: false,
|
||||
warnings: false,
|
||||
}
|
||||
```
|
||||
|
||||
@@ -590,111 +591,88 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
## Parse options
|
||||
|
||||
- `bare_returns` (default `false`) -- support top level `return` statements
|
||||
|
||||
- `html5_comments` (default `true`)
|
||||
|
||||
- `shebang` (default `true`) -- support `#!command` as the first line
|
||||
|
||||
## Compress options
|
||||
|
||||
- `sequences` (default: true) -- join consecutive simple statements using the
|
||||
comma operator. May be set to a positive integer to specify the maximum number
|
||||
of consecutive comma sequences that will be generated. If this option is set to
|
||||
`true` then the default `sequences` limit is `200`. Set option to `false` or `0`
|
||||
to disable. The smallest `sequences` length is `2`. A `sequences` value of `1`
|
||||
is grandfathered to be equivalent to `true` and as such means `200`. On rare
|
||||
occasions the default sequences limit leads to very slow compress times in which
|
||||
case a value of `20` or less is recommended.
|
||||
- `booleans` (default: `true`) -- various optimizations for boolean context, for example `!!a
|
||||
? b : c → a ? b : c`
|
||||
|
||||
- `properties` -- rewrite property access using the dot notation, for
|
||||
example `foo["bar"] → foo.bar`
|
||||
- `cascade` (default: `true`) -- small optimization for sequences, transform `x, x` into `x`
|
||||
and `x = something(), x` into `x = something()`
|
||||
|
||||
- `dead_code` -- remove unreachable code
|
||||
- `collapse_vars` (default: `true`) -- Collapse single-use non-constant variables - side
|
||||
effects permitting.
|
||||
|
||||
- `drop_debugger` -- remove `debugger;` statements
|
||||
|
||||
- `unsafe` (default: false) -- apply "unsafe" transformations (discussion below)
|
||||
|
||||
- `unsafe_comps` (default: false) -- Reverse `<` and `<=` to `>` and `>=` to
|
||||
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`,
|
||||
or `valueOf`. This could cause change in execution order after operands in the
|
||||
comparison are switching. Compression only works if both `comparisons` and
|
||||
`unsafe_comps` are both set to true.
|
||||
|
||||
- `unsafe_Func` (default: false) -- compress and mangle `Function(args, code)`
|
||||
when both `args` and `code` are string literals.
|
||||
|
||||
- `unsafe_math` (default: false) -- optimize numerical expressions like
|
||||
`2 * x * 3` into `6 * x`, which may give imprecise floating point results.
|
||||
|
||||
- `unsafe_proto` (default: false) -- optimize expressions like
|
||||
`Array.prototype.slice.call(a)` into `[].slice.call(a)`
|
||||
|
||||
- `unsafe_regexp` (default: false) -- enable substitutions of variables with
|
||||
`RegExp` values the same way as if they are constants.
|
||||
|
||||
- `conditionals` -- apply optimizations for `if`-s and conditional
|
||||
expressions
|
||||
|
||||
- `comparisons` -- apply certain optimizations to binary nodes, for example:
|
||||
- `comparisons` (default: `true`) -- apply certain optimizations to binary nodes, for example:
|
||||
`!(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.
|
||||
|
||||
- `evaluate` -- attempt to evaluate constant expressions
|
||||
- `conditionals` (default: `true`) -- apply optimizations for `if`-s and conditional
|
||||
expressions
|
||||
|
||||
- `booleans` -- various optimizations for boolean context, for example `!!a
|
||||
? b : c → a ? b : c`
|
||||
- `dead_code` (default: `true`) -- remove unreachable code
|
||||
|
||||
- `typeofs` -- default `true`. Transforms `typeof foo == "undefined"` into
|
||||
`foo === void 0`. Note: recommend to set this value to `false` for IE10 and
|
||||
earlier versions due to known issues.
|
||||
- `drop_console` (default: `false`) -- default `false`. Pass `true` to discard calls to
|
||||
`console.*` functions. If you wish to drop a specific function call
|
||||
such as `console.info` and/or retain side effects from function arguments
|
||||
after dropping the function call then use `pure_funcs` instead.
|
||||
|
||||
- `loops` -- optimizations for `do`, `while` and `for` loops when we can
|
||||
statically determine the condition
|
||||
- `drop_debugger` (default: `true`) -- remove `debugger;` statements
|
||||
|
||||
- `unused` -- drop unreferenced functions and variables (simple direct variable
|
||||
assignments do not count as references unless set to `"keep_assign"`)
|
||||
- `evaluate` (default: `true`) -- attempt to evaluate constant expressions
|
||||
|
||||
- `toplevel` -- drop unreferenced functions (`"funcs"`) and/or variables (`"vars"`)
|
||||
in the top level scope (`false` by default, `true` to drop both unreferenced
|
||||
functions and variables)
|
||||
- `expression` (default: `false`) -- default `false`. Pass `true` to preserve completion values
|
||||
from terminal statements without `return`, e.g. in bookmarklets.
|
||||
|
||||
- `top_retain` -- prevent specific toplevel functions and variables from `unused`
|
||||
removal (can be array, comma-separated, RegExp or function. Implies `toplevel`)
|
||||
- `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation)
|
||||
|
||||
- `hoist_funs` -- hoist function declarations
|
||||
- `hoist_funs` (default: `true`) -- hoist function declarations
|
||||
|
||||
- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false`
|
||||
- `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`
|
||||
by default because it seems to increase the size of the output in general)
|
||||
|
||||
- `if_return` -- optimizations for if/return and if/continue
|
||||
- `if_return` (default: `true`) -- optimizations for if/return and if/continue
|
||||
|
||||
- `inline` -- embed simple functions
|
||||
- `inline` (default: `true`) -- embed simple functions
|
||||
|
||||
- `join_vars` -- join consecutive `var` statements
|
||||
- `join_vars` (default: `true`) -- join consecutive `var` statements
|
||||
|
||||
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
||||
and `x = something(), x` into `x = something()`
|
||||
- `keep_fargs` (default: `true`) -- default `true`. Prevents the
|
||||
compressor from discarding unused function arguments. You need this
|
||||
for code which relies on `Function.length`.
|
||||
|
||||
- `collapse_vars` -- Collapse single-use non-constant variables - side
|
||||
effects permitting.
|
||||
- `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).
|
||||
|
||||
- `reduce_vars` -- Improve optimization on variables assigned with and
|
||||
used as constant values.
|
||||
- `keep_infinity` (default: `false`) -- default `false`. Pass `true` to prevent `Infinity` from
|
||||
being compressed into `1/0`, which may cause performance issues on Chrome.
|
||||
|
||||
- `warnings` -- display warnings when dropping unreachable code or unused
|
||||
declarations etc.
|
||||
- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops when we can
|
||||
statically determine the condition
|
||||
|
||||
- `negate_iife` -- negate "Immediately-Called Function Expressions"
|
||||
- `negate_iife` (default: `true`) -- negate "Immediately-Called Function Expressions"
|
||||
where the return value is discarded, to avoid the parens that the
|
||||
code generator would insert.
|
||||
|
||||
- `pure_getters` -- the default is `false`. If you pass `true` for
|
||||
this, UglifyJS will assume that object property access
|
||||
(e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects.
|
||||
Specify `"strict"` to treat `foo.bar` as side-effect-free only when
|
||||
`foo` is certain to not throw, i.e. not `null` or `undefined`.
|
||||
- `passes` (default: `1`) -- The maximum number of times to run compress.
|
||||
In some cases more than one pass leads to further compressed code. Keep in
|
||||
mind more passes will take more time.
|
||||
|
||||
- `pure_funcs` -- default `null`. You can pass an array of names and
|
||||
- `properties` (default: `true`) -- rewrite property access using the dot notation, for
|
||||
example `foo["bar"] → foo.bar`
|
||||
|
||||
- `pure_funcs` (default: `null`) -- You can pass an array of names and
|
||||
UglifyJS will assume that those functions do not produce side
|
||||
effects. DANGER: will not check if the name is redefined in scope.
|
||||
An example case here, for instance `var q = Math.floor(a/b)`. If
|
||||
@@ -705,49 +683,90 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
statement would get discarded. The current implementation adds some
|
||||
overhead (compression will be slower).
|
||||
|
||||
- `drop_console` -- default `false`. Pass `true` to discard calls to
|
||||
`console.*` functions. If you wish to drop a specific function call
|
||||
such as `console.info` and/or retain side effects from function arguments
|
||||
after dropping the function call then use `pure_funcs` instead.
|
||||
- `pure_getters` (default: `"strict"`) -- If you pass `true` for
|
||||
this, UglifyJS will assume that object property access
|
||||
(e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects.
|
||||
Specify `"strict"` to treat `foo.bar` as side-effect-free only when
|
||||
`foo` is certain to not throw, i.e. not `null` or `undefined`.
|
||||
|
||||
- `expression` -- default `false`. Pass `true` to preserve completion values
|
||||
from terminal statements without `return`, e.g. in bookmarklets.
|
||||
- `reduce_funcs` (default: `true`) -- Allows single-use functions to be
|
||||
inlined as function expressions when permissible allowing further
|
||||
optimization. Enabled by default. Option depends on `reduce_vars`
|
||||
being enabled. Some code runs faster in the Chrome V8 engine if this
|
||||
option is disabled. Does not negatively impact other major browsers.
|
||||
|
||||
- `reduce_vars` (default: `true`) -- Improve optimization on variables assigned with and
|
||||
used as constant values.
|
||||
|
||||
- `keep_fargs` -- default `true`. Prevents the
|
||||
compressor from discarding unused function arguments. You need this
|
||||
for code which relies on `Function.length`.
|
||||
- `sequences` (default: `true`) -- join consecutive simple statements using the
|
||||
comma operator. May be set to a positive integer to specify the maximum number
|
||||
of consecutive comma sequences that will be generated. If this option is set to
|
||||
`true` then the default `sequences` limit is `200`. Set option to `false` or `0`
|
||||
to disable. The smallest `sequences` length is `2`. A `sequences` value of `1`
|
||||
is grandfathered to be equivalent to `true` and as such means `200`. On rare
|
||||
occasions the default sequences limit leads to very slow compress times in which
|
||||
case a value of `20` or less is recommended.
|
||||
|
||||
- `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).
|
||||
|
||||
- `passes` -- default `1`. The maximum number of times to run compress.
|
||||
In some cases more than one pass leads to further compressed code. Keep in
|
||||
mind more passes will take more time.
|
||||
|
||||
- `keep_infinity` -- default `false`. Pass `true` to prevent `Infinity` from
|
||||
being compressed into `1/0`, which may cause performance issues on Chrome.
|
||||
|
||||
- `side_effects` -- default `true`. Pass `false` to disable potentially dropping
|
||||
- `side_effects` (default: `true`) -- default `true`. Pass `false` to disable potentially dropping
|
||||
functions marked as "pure". A function call is marked as "pure" if a comment
|
||||
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
|
||||
example: `/*@__PURE__*/foo();`
|
||||
|
||||
- `switches` (default: `true`) -- de-duplicate and remove unreachable `switch` branches
|
||||
|
||||
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or variables (`"vars"`)
|
||||
in the top level scope (`false` by default, `true` to drop both unreferenced
|
||||
functions and variables)
|
||||
|
||||
- `top_retain` (default: `null`) -- prevent specific toplevel functions and variables from `unused`
|
||||
removal (can be array, comma-separated, RegExp or function. Implies `toplevel`)
|
||||
|
||||
- `typeofs` (default: `true`) -- default `true`. Transforms `typeof foo == "undefined"` into
|
||||
`foo === void 0`. Note: recommend to set this value to `false` for IE10 and
|
||||
earlier versions due to known issues.
|
||||
|
||||
- `unsafe` (default: `false`) -- apply "unsafe" transformations (discussion below)
|
||||
|
||||
- `unsafe_comps` (default: `false`) -- Reverse `<` and `<=` to `>` and `>=` to
|
||||
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`,
|
||||
or `valueOf`. This could cause change in execution order after operands in the
|
||||
comparison are switching. Compression only works if both `comparisons` and
|
||||
`unsafe_comps` are both set to true.
|
||||
|
||||
- `unsafe_Func` (default: `false`) -- compress and mangle `Function(args, code)`
|
||||
when both `args` and `code` are string literals.
|
||||
|
||||
- `unsafe_math` (default: `false`) -- optimize numerical expressions like
|
||||
`2 * x * 3` into `6 * x`, which may give imprecise floating point results.
|
||||
|
||||
- `unsafe_proto` (default: `false`) -- optimize expressions like
|
||||
`Array.prototype.slice.call(a)` into `[].slice.call(a)`
|
||||
|
||||
- `unsafe_regexp` (default: `false`) -- enable substitutions of variables with
|
||||
`RegExp` values the same way as if they are constants.
|
||||
|
||||
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple direct variable
|
||||
assignments do not count as references unless set to `"keep_assign"`)
|
||||
|
||||
- `warnings` (default: `false`) -- display warnings when dropping unreachable code or unused
|
||||
declarations etc.
|
||||
|
||||
## 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
|
||||
excluded from mangling. Example: `["foo", "bar"]`.
|
||||
|
||||
- `toplevel` (default `false`). Pass `true` to mangle names declared in the
|
||||
top level scope.
|
||||
|
||||
- `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).
|
||||
|
||||
- `eval` (default `false`). Pass `true` to mangle names visible in scopes
|
||||
where `eval` or `with` are used.
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
@@ -772,16 +791,20 @@ UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
|
||||
|
||||
### Mangle properties options
|
||||
|
||||
- `reserved` (default: `[]`) -- Do not mangle property names listed in the
|
||||
`reserved` array.
|
||||
- `regex` (default: `null`) -— Pass a RegExp literal to only mangle property
|
||||
names matching the regular expression.
|
||||
- `keep_quoted` (default: `false`) -— Only mangle unquoted property names.
|
||||
- `debug` (default: `false`) -— Mangle names with the original name still present.
|
||||
Pass an empty string `""` to enable, or a non-empty string to set the debug suffix.
|
||||
- `builtins` (default: `false`) -- Use `true` to allow the mangling of builtin
|
||||
DOM properties. Not recommended to override this setting.
|
||||
|
||||
- `debug` (default: `false`) -— Mangle names with the original name still present.
|
||||
Pass an empty string `""` to enable, or a non-empty string to set the debug suffix.
|
||||
|
||||
- `keep_quoted` (default: `false`) -— Only mangle unquoted property names.
|
||||
|
||||
- `regex` (default: `null`) -— Pass a RegExp literal to only mangle property
|
||||
names matching the regular expression.
|
||||
|
||||
- `reserved` (default: `[]`) -- Do not mangle property names listed in the
|
||||
`reserved` array.
|
||||
|
||||
## Output options
|
||||
|
||||
The code generator tries to output shortest code possible by default. In
|
||||
@@ -790,31 +813,43 @@ can pass additional arguments that control the code output:
|
||||
|
||||
- `ascii_only` (default `false`) -- escape Unicode characters in strings and
|
||||
regexps (affects directives with non-ascii characters becoming invalid)
|
||||
|
||||
- `beautify` (default `true`) -- whether to actually beautify the output.
|
||||
Passing `-b` will set this to true, but you might need to pass `-b` even
|
||||
when you want to generate minified code, in order to specify additional
|
||||
arguments, so you can use `-b beautify=false` to override it.
|
||||
|
||||
- `bracketize` (default `false`) -- always insert brackets in `if`, `for`,
|
||||
`do`, `while` or `with` statements, even if their body is a single
|
||||
statement.
|
||||
|
||||
- `comments` (default `false`) -- pass `true` or `"all"` to preserve all
|
||||
comments, `"some"` to preserve some comments, a regular expression string
|
||||
(e.g. `/^!/`) or a function.
|
||||
- `indent_level` (default 4)
|
||||
- `indent_start` (default 0) -- prefix all lines by that many spaces
|
||||
|
||||
- `indent_level` (default `4`)
|
||||
|
||||
- `indent_start` (default `0`) -- prefix all lines by that many spaces
|
||||
|
||||
- `inline_script` (default `false`) -- escape the slash in occurrences of
|
||||
`</script` in strings
|
||||
|
||||
- `keep_quoted_props` (default `false`) -- when turned on, prevents stripping
|
||||
quotes from property names in object literals.
|
||||
|
||||
- `max_line_len` (default `false`) -- maximum line length (for uglified code)
|
||||
|
||||
- `preamble` (default `null`) -- when passed it must be a string and
|
||||
it will be prepended to the output literally. The source map will
|
||||
adjust for this text. Can be used to insert a comment containing
|
||||
licensing information, for example.
|
||||
|
||||
- `preserve_line` (default `false`) -- pass `true` to preserve lines, but it
|
||||
only works if `beautify` is set to `false`.
|
||||
|
||||
- `quote_keys` (default `false`) -- pass `true` to quote all keys in literal
|
||||
objects
|
||||
|
||||
- `quote_style` (default `0`) -- preferred quote style for strings (affects
|
||||
quoted property names and directives as well):
|
||||
- `0` -- prefers double quotes, switches to single quotes when there are
|
||||
@@ -822,16 +857,23 @@ can pass additional arguments that control the code output:
|
||||
- `1` -- always use single quotes
|
||||
- `2` -- always use double quotes
|
||||
- `3` -- always use the original quotes
|
||||
|
||||
- `semicolons` (default `true`) -- separate statements with semicolons. If
|
||||
you pass `false` then whenever possible we will use a newline instead of a
|
||||
semicolon, leading to more readable output of uglified code (size before
|
||||
gzip could be smaller; size after gzip insignificantly larger).
|
||||
|
||||
- `shebang` (default `true`) -- preserve shebang `#!` in preamble (bash scripts)
|
||||
- `width` (default 80) -- only takes effect when beautification is on, this
|
||||
|
||||
- `webkit` (default `false`) -- enable workarounds for WebKit bugs.
|
||||
PhantomJS users should set this option to `true`.
|
||||
|
||||
- `width` (default `80`) -- only takes effect when beautification is on, this
|
||||
specifies an (orientative) line width that the beautifier will try to
|
||||
obey. It refers to the width of the line text (excluding indentation).
|
||||
It doesn't work very well currently, but it does make the code generated
|
||||
by UglifyJS more readable.
|
||||
|
||||
- `wrap_iife` (default `false`) -- pass `true` to wrap immediately invoked
|
||||
function expressions. See
|
||||
[#640](https://github.com/mishoo/UglifyJS2/issues/640) for more details.
|
||||
@@ -1033,7 +1075,7 @@ in total it's a bit more than just using UglifyJS's own parser.
|
||||
### Uglify Fast Minify Mode
|
||||
|
||||
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
|
||||
Uglify builds by 3 to 4 times. In this fast `mangle`-only mode Uglify has
|
||||
comparable minify speeds and gzip sizes to
|
||||
|
||||
@@ -15,7 +15,7 @@ var path = require("path");
|
||||
var program = require("commander");
|
||||
var UglifyJS = require("../tools/node");
|
||||
|
||||
var skip_keys = [ "cname", "enclosed", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ];
|
||||
var skip_keys = [ "cname", "enclosed", "inlined", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ];
|
||||
var files = {};
|
||||
var options = {
|
||||
compress: false,
|
||||
|
||||
10
lib/ast.js
10
lib/ast.js
@@ -134,11 +134,10 @@ var AST_Debugger = DEFNODE("Debugger", null, {
|
||||
$documentation: "Represents a debugger statement",
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_Directive = DEFNODE("Directive", "value scope quote", {
|
||||
var AST_Directive = DEFNODE("Directive", "value quote", {
|
||||
$documentation: "Represents a directive, like \"use strict\";",
|
||||
$propdoc: {
|
||||
value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
|
||||
scope: "[AST_Scope/S] The scope that this directive affects",
|
||||
quote: "[string] the original quote character"
|
||||
},
|
||||
}, AST_Statement);
|
||||
@@ -299,10 +298,9 @@ var AST_With = DEFNODE("With", "expression", {
|
||||
|
||||
/* -----[ scope and functions ]----- */
|
||||
|
||||
var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
|
||||
var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent_scope enclosed cname", {
|
||||
$documentation: "Base class for all statements introducing a lexical scope",
|
||||
$propdoc: {
|
||||
directives: "[string*/S] an array of directives declared in this scope",
|
||||
variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
|
||||
functions: "[Object/S] like `variables`, but only lists function declarations",
|
||||
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
|
||||
@@ -354,11 +352,11 @@ var AST_Accessor = DEFNODE("Accessor", null, {
|
||||
$documentation: "A setter/getter function. The `name` property is always null."
|
||||
}, AST_Lambda);
|
||||
|
||||
var AST_Function = DEFNODE("Function", null, {
|
||||
var AST_Function = DEFNODE("Function", "inlined", {
|
||||
$documentation: "A function expression"
|
||||
}, AST_Lambda);
|
||||
|
||||
var AST_Defun = DEFNODE("Defun", null, {
|
||||
var AST_Defun = DEFNODE("Defun", "inlined", {
|
||||
$documentation: "A function definition"
|
||||
}, AST_Lambda);
|
||||
|
||||
|
||||
1225
lib/compress.js
1225
lib/compress.js
File diff suppressed because it is too large
Load Diff
@@ -137,11 +137,9 @@ function minify(files, options) {
|
||||
if (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 (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 (timings) timings.mangle = Date.now();
|
||||
if (options.mangle) {
|
||||
@@ -199,9 +197,9 @@ function minify(files, options) {
|
||||
if (timings) {
|
||||
timings.end = Date.now();
|
||||
result.timings = {
|
||||
parse: 1e-3 * (timings.scope1 - timings.parse),
|
||||
scope: 1e-3 * (timings.compress - timings.scope1 + timings.mangle - timings.scope2),
|
||||
compress: 1e-3 * (timings.scope2 - timings.compress),
|
||||
parse: 1e-3 * (timings.compress - timings.parse),
|
||||
compress: 1e-3 * (timings.scope - timings.compress),
|
||||
scope: 1e-3 * (timings.mangle - timings.scope),
|
||||
mangle: 1e-3 * (timings.properties - timings.mangle),
|
||||
properties: 1e-3 * (timings.output - timings.properties),
|
||||
output: 1e-3 * (timings.end - timings.output),
|
||||
|
||||
@@ -482,13 +482,17 @@ function OutputStream(options) {
|
||||
nodetype.DEFMETHOD("_codegen", generator);
|
||||
};
|
||||
|
||||
var use_asm = false;
|
||||
var in_directive = false;
|
||||
var active_scope = null;
|
||||
var use_asm = null;
|
||||
|
||||
AST_Node.DEFMETHOD("print", function(stream, force_parens){
|
||||
var self = this, generator = self._codegen, prev_use_asm = use_asm;
|
||||
if (self instanceof AST_Directive && self.value == "use asm" && stream.parent() instanceof AST_Scope) {
|
||||
use_asm = true;
|
||||
var self = this, generator = self._codegen;
|
||||
if (self instanceof AST_Scope) {
|
||||
active_scope = self;
|
||||
}
|
||||
else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") {
|
||||
use_asm = active_scope;
|
||||
}
|
||||
function doit() {
|
||||
self.add_comments(stream);
|
||||
@@ -502,8 +506,8 @@ function OutputStream(options) {
|
||||
doit();
|
||||
}
|
||||
stream.pop_node();
|
||||
if (self instanceof AST_Scope) {
|
||||
use_asm = prev_use_asm;
|
||||
if (self === use_asm) {
|
||||
use_asm = null;
|
||||
}
|
||||
});
|
||||
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
|
||||
@@ -1109,7 +1113,7 @@ function OutputStream(options) {
|
||||
self.expression.print(output);
|
||||
if (self instanceof AST_New && !need_constructor_parens(self, output))
|
||||
return;
|
||||
if (self.expression instanceof AST_Lambda) {
|
||||
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
|
||||
output.add_mapping(self.start);
|
||||
}
|
||||
output.with_parens(function(){
|
||||
|
||||
@@ -1054,6 +1054,8 @@ function parse($TEXT, options) {
|
||||
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
|
||||
if (in_statement && !name)
|
||||
unexpected();
|
||||
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
|
||||
unexpected(prev());
|
||||
expect("(");
|
||||
var argnames = [];
|
||||
for (var first = true; !is("punc", ")");) {
|
||||
|
||||
@@ -46,8 +46,10 @@
|
||||
function SymbolDef(scope, index, orig) {
|
||||
this.name = orig.name;
|
||||
this.orig = [ orig ];
|
||||
this.eliminated = 0;
|
||||
this.scope = scope;
|
||||
this.references = [];
|
||||
this.replaced = 0;
|
||||
this.global = false;
|
||||
this.mangled_name = null;
|
||||
this.undeclared = false;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"homepage": "http://lisperator.net/uglifyjs",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.0.28",
|
||||
"version": "3.1.10",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
@@ -30,12 +30,12 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"commander": "~2.11.0",
|
||||
"source-map": "~0.5.1"
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"acorn": "~5.1.1",
|
||||
"mocha": "~3.4.2",
|
||||
"semver": "~5.3.0"
|
||||
"mocha": "~3.5.1",
|
||||
"semver": "~5.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node test/run-tests.js"
|
||||
|
||||
@@ -128,50 +128,114 @@ constant_join_3: {
|
||||
|
||||
for_loop: {
|
||||
options = {
|
||||
unsafe : true,
|
||||
unused : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
};
|
||||
input: {
|
||||
function f0() {
|
||||
var a = [1, 2, 3];
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
console.log(a[i]);
|
||||
}
|
||||
var b = 0;
|
||||
for (var i = 0; i < a.length; i++)
|
||||
b += a[i];
|
||||
return b;
|
||||
}
|
||||
|
||||
function f1() {
|
||||
var a = [1, 2, 3];
|
||||
for (var i = 0, len = a.length; i < len; i++) {
|
||||
console.log(a[i]);
|
||||
}
|
||||
var b = 0;
|
||||
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() {
|
||||
var a = [1, 2, 3];
|
||||
for (var i = 0; i < a.length; 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_funcs: 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_funcs: 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_funcs: 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"
|
||||
}
|
||||
|
||||
@@ -104,3 +104,65 @@ asm_mixed: {
|
||||
}
|
||||
}
|
||||
|
||||
asm_toplevel: {
|
||||
options = {}
|
||||
input: {
|
||||
"use asm";
|
||||
0.0;
|
||||
function f() {
|
||||
0.0;
|
||||
(function(){
|
||||
0.0;
|
||||
});
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
expect_exact: '"use asm";0.0;function f(){0.0;(function(){0.0})}0.0;'
|
||||
}
|
||||
|
||||
asm_function_expression: {
|
||||
options = {}
|
||||
input: {
|
||||
0.0;
|
||||
var a = function() {
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
function f() {
|
||||
0.0;
|
||||
return function(){
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
expect_exact: '0;var a=function(){"use asm";0.0};function f(){0;return function(){"use asm";0.0};0}0;'
|
||||
}
|
||||
|
||||
asm_nested_functions: {
|
||||
options = {}
|
||||
input: {
|
||||
0.0;
|
||||
function a() {
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
function b() {
|
||||
0.0;
|
||||
function c(){
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
function d(){
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
expect_exact: '0;function a(){"use asm";0.0}0;function b(){0;function c(){"use asm";0.0}0;function d(){0}0}0;'
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -73,4 +73,42 @@ dont_change_in_or_instanceof_expressions: {
|
||||
1 instanceof 1;
|
||||
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_funcs: 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"
|
||||
}
|
||||
|
||||
@@ -241,21 +241,58 @@ issue_2233_1: {
|
||||
Array.isArray;
|
||||
Boolean;
|
||||
console.log;
|
||||
Date;
|
||||
decodeURI;
|
||||
decodeURIComponent;
|
||||
encodeURI;
|
||||
encodeURIComponent;
|
||||
Error.name;
|
||||
escape;
|
||||
eval;
|
||||
EvalError;
|
||||
Function.length;
|
||||
isFinite;
|
||||
isNaN;
|
||||
JSON;
|
||||
Math.random;
|
||||
Number.isNaN;
|
||||
parseFloat;
|
||||
parseInt;
|
||||
RegExp;
|
||||
Object.defineProperty;
|
||||
String.fromCharCode;
|
||||
RangeError;
|
||||
ReferenceError;
|
||||
SyntaxError;
|
||||
TypeError;
|
||||
unescape;
|
||||
URIError;
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
global_timeout_and_interval_symbols: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
// These global symbols do not exist in the test sandbox
|
||||
// and must be tested separately.
|
||||
clearInterval;
|
||||
clearTimeout;
|
||||
setInterval;
|
||||
setTimeout;
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2233_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
@@ -287,6 +324,7 @@ issue_2233_2: {
|
||||
issue_2233_3: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -309,3 +347,71 @@ issue_2233_3: {
|
||||
UndeclaredGlobal;
|
||||
}
|
||||
}
|
||||
|
||||
global_fns: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
Boolean(1, 2);
|
||||
decodeURI(1, 2);
|
||||
decodeURIComponent(1, 2);
|
||||
Date(1, 2);
|
||||
encodeURI(1, 2);
|
||||
encodeURIComponent(1, 2);
|
||||
Error(1, 2);
|
||||
escape(1, 2);
|
||||
EvalError(1, 2);
|
||||
isFinite(1, 2);
|
||||
isNaN(1, 2);
|
||||
Number(1, 2);
|
||||
Object(1, 2);
|
||||
parseFloat(1, 2);
|
||||
parseInt(1, 2);
|
||||
RangeError(1, 2);
|
||||
ReferenceError(1, 2);
|
||||
String(1, 2);
|
||||
SyntaxError(1, 2);
|
||||
TypeError(1, 2);
|
||||
unescape(1, 2);
|
||||
URIError(1, 2);
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect_stdout: [
|
||||
"SyntaxError",
|
||||
"SyntaxError",
|
||||
"RangeError",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -673,6 +673,7 @@ issue_1539: {
|
||||
vardef_value: {
|
||||
options = {
|
||||
keep_fnames: false,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -734,6 +735,7 @@ assign_chain: {
|
||||
issue_1583: {
|
||||
options = {
|
||||
keep_fargs: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -751,12 +753,12 @@ issue_1583: {
|
||||
expect: {
|
||||
function m(t) {
|
||||
(function(e) {
|
||||
t = e();
|
||||
})(function() {
|
||||
return (function(a) {
|
||||
return a;
|
||||
})(function(a) {});
|
||||
});
|
||||
t = function() {
|
||||
return (function(a) {
|
||||
return function(a) {};
|
||||
})();
|
||||
}();
|
||||
})();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1080,6 +1082,7 @@ var_catch_toplevel: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -1109,11 +1112,12 @@ var_catch_toplevel: {
|
||||
}
|
||||
}
|
||||
|
||||
issue_2105: {
|
||||
issue_2105_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
passes: 3,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -1139,17 +1143,51 @@ issue_2105: {
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var quux = function() {
|
||||
({
|
||||
prop: function() {
|
||||
console.log;
|
||||
console.log("PASS");
|
||||
};
|
||||
return {
|
||||
prop: function() {
|
||||
console.log;
|
||||
quux();
|
||||
}
|
||||
}).prop();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2105_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
passes: 3,
|
||||
properties: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
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 };
|
||||
}
|
||||
};
|
||||
})().prop();
|
||||
return bar;
|
||||
} );
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
@@ -1239,3 +1277,25 @@ issue_2226_3: {
|
||||
}
|
||||
expect_stdout: "3"
|
||||
}
|
||||
|
||||
issue_2288: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
input: {
|
||||
function foo(o) {
|
||||
for (var j = o.a, i = 0; i < 0; i++);
|
||||
for (var i = 0; i < 0; i++);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(o) {
|
||||
o.a;
|
||||
for (i = 0; i < 0; i++);
|
||||
for (var i = 0; i < 0; i++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,6 +251,7 @@ unsafe_constant: {
|
||||
unsafe_object: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
@@ -279,6 +280,7 @@ unsafe_object: {
|
||||
unsafe_object_nested: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
@@ -307,6 +309,7 @@ unsafe_object_nested: {
|
||||
unsafe_object_complex: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
@@ -335,6 +338,7 @@ unsafe_object_complex: {
|
||||
unsafe_object_repeated: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
@@ -363,6 +367,7 @@ unsafe_object_repeated: {
|
||||
unsafe_object_accessor: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
@@ -386,10 +391,11 @@ unsafe_object_accessor: {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_function: {
|
||||
prop_function: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -402,9 +408,9 @@ unsafe_function: {
|
||||
expect: {
|
||||
console.log(
|
||||
({a:{b:1},b:function(){}}) + 1,
|
||||
({b:function(){}}, {b:1}) + 1,
|
||||
({a:{b:1}}, function(){}) + 1,
|
||||
({b:function(){}}, {b:1}).b + 1
|
||||
({b:1}) + 1,
|
||||
function(){} + 1,
|
||||
2
|
||||
);
|
||||
}
|
||||
expect_stdout: true
|
||||
@@ -630,10 +636,11 @@ unsafe_string_bad_index: {
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
unsafe_prototype_function: {
|
||||
prototype_function: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a = ({valueOf: 0}) < 1;
|
||||
@@ -652,8 +659,8 @@ unsafe_prototype_function: {
|
||||
var d = ({toString: 0}) + "";
|
||||
var e = (({valueOf: 0}) + "")[2];
|
||||
var f = (({toString: 0}) + "")[2];
|
||||
var g = ({}, 0)();
|
||||
var h = ({}, 0)();
|
||||
var g = 0();
|
||||
var h = 0();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,6 +668,7 @@ call_args: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
@@ -684,6 +692,7 @@ call_args_drop_param: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
keep_fargs: false,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -1014,6 +1023,7 @@ Infinity_NaN_undefined_LHS: {
|
||||
issue_1964_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unsafe_regexp: false,
|
||||
unused: true,
|
||||
@@ -1021,6 +1031,7 @@ issue_1964_1: {
|
||||
input: {
|
||||
function f() {
|
||||
var long_variable_name = /\s/;
|
||||
console.log(long_variable_name.source);
|
||||
return "a b c".split(long_variable_name)[1];
|
||||
}
|
||||
console.log(f());
|
||||
@@ -1028,16 +1039,21 @@ issue_1964_1: {
|
||||
expect: {
|
||||
function f() {
|
||||
var long_variable_name = /\s/;
|
||||
console.log(long_variable_name.source);
|
||||
return "a b c".split(long_variable_name)[1];
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect_stdout: "b"
|
||||
expect_stdout: [
|
||||
"\\s",
|
||||
"b",
|
||||
]
|
||||
}
|
||||
|
||||
issue_1964_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unsafe_regexp: true,
|
||||
unused: true,
|
||||
@@ -1045,17 +1061,22 @@ issue_1964_2: {
|
||||
input: {
|
||||
function f() {
|
||||
var long_variable_name = /\s/;
|
||||
console.log(long_variable_name.source);
|
||||
return "a b c".split(long_variable_name)[1];
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
console.log(/\s/.source);
|
||||
return "a b c".split(/\s/)[1];
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect_stdout: "b"
|
||||
expect_stdout: [
|
||||
"\\s",
|
||||
"b",
|
||||
]
|
||||
}
|
||||
|
||||
array_slice_index: {
|
||||
@@ -1185,3 +1206,42 @@ issue_2231_2: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
self_comparison_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: 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_funcs: true,
|
||||
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'"
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ iifes_returning_constants_keep_fargs_true: {
|
||||
booleans : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
reduce_funcs : true,
|
||||
reduce_vars : true,
|
||||
cascade : true,
|
||||
inline : true,
|
||||
@@ -55,6 +56,7 @@ iifes_returning_constants_keep_fargs_false: {
|
||||
booleans : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
reduce_funcs : true,
|
||||
reduce_vars : true,
|
||||
cascade : true,
|
||||
inline : true,
|
||||
@@ -101,6 +103,7 @@ issue_1841_1: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -127,6 +130,7 @@ issue_1841_2: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
pure_getters: false,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -151,13 +155,14 @@ issue_1841_2: {
|
||||
|
||||
function_returning_constant_literal: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
toplevel: true,
|
||||
evaluate: true,
|
||||
cascade: true,
|
||||
unused: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function greeter() {
|
||||
@@ -305,6 +310,7 @@ issue_2084: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -340,6 +346,7 @@ issue_2084: {
|
||||
issue_2097: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -508,3 +515,42 @@ issue_2114_2: {
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
issue_2428: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
passes: 3,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
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",
|
||||
]
|
||||
}
|
||||
|
||||
502
test/compress/hoist_props.js
Normal file
502
test/compress/hoist_props.js
Normal file
@@ -0,0 +1,502 @@
|
||||
issue_2377_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
hoist_props: true,
|
||||
reduce_funcs: 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_funcs: 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: {
|
||||
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_funcs: 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: {
|
||||
console.log(1, 27);
|
||||
}
|
||||
expect_stdout: "1 27"
|
||||
}
|
||||
|
||||
direct_access_1: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: 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_funcs: 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_funcs: 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_funcs: 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_funcs: 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_funcs: 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_funcs: 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_funcs: true,
|
||||
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_funcs: true,
|
||||
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_funcs: true,
|
||||
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_funcs: true,
|
||||
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"
|
||||
}
|
||||
|
||||
issue_2473_1: {
|
||||
options = {
|
||||
hoist_props: false,
|
||||
reduce_vars: true,
|
||||
top_retain: [ "x", "y" ],
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
var y = [];
|
||||
var z = {};
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
var y = [];
|
||||
}
|
||||
}
|
||||
|
||||
issue_2473_2: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
top_retain: [ "x", "y" ],
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
var y = [];
|
||||
var z = {};
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
var y = [];
|
||||
}
|
||||
}
|
||||
|
||||
issue_2473_3: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
top_retain: "o",
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
};
|
||||
console.log(o.a, o.b);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
};
|
||||
console.log(o.a, o.b);
|
||||
}
|
||||
expect_stdout: "1 2"
|
||||
}
|
||||
|
||||
issue_2473_4: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
top_retain: "o",
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
};
|
||||
console.log(o.a, o.b);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var o_a = 1, o_b = 2;
|
||||
console.log(o_a, o_b);
|
||||
})();
|
||||
}
|
||||
expect_stdout: "1 2"
|
||||
}
|
||||
@@ -88,3 +88,24 @@ sequences_funs: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2295: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
function foo(o) {
|
||||
var a = o.a;
|
||||
if (a) return a;
|
||||
var a = 1;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(o) {
|
||||
var a = o.a;
|
||||
if (a) return a;
|
||||
a = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const_pragma: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
};
|
||||
|
||||
@@ -16,6 +17,7 @@ const_pragma: {
|
||||
not_const: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
};
|
||||
|
||||
|
||||
@@ -96,6 +96,13 @@ pure_function_calls_toplevel: {
|
||||
})();
|
||||
})();
|
||||
|
||||
// pure top-level calls will be dropped regardless of the leading comments position
|
||||
var MyClass = /*#__PURE__*//*@class*/(function(){
|
||||
function MyClass() {}
|
||||
MyClass.prototype.method = function() {};
|
||||
return MyClass;
|
||||
})();
|
||||
|
||||
// comment #__PURE__ comment
|
||||
bar(), baz(), quux();
|
||||
a.b(), /* @__PURE__ */ c.d.e(), f.g();
|
||||
@@ -110,10 +117,12 @@ pure_function_calls_toplevel: {
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:92,37]",
|
||||
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:92,16]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:90,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:100,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:101,31]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:107,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:108,31]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:84,33]",
|
||||
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:84,12]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:100,45]",
|
||||
"WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:100,12]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -148,29 +157,29 @@ should_warn: {
|
||||
baz();
|
||||
}
|
||||
expect_warnings: [
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,61]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,23]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:128,23]",
|
||||
"WARN: Boolean || always true [test/compress/issue-1261.js:129,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:129,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:129,23]",
|
||||
"WARN: Condition left of || always true [test/compress/issue-1261.js:130,8]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:130,8]",
|
||||
"WARN: Boolean && always false [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Condition left of && always false [test/compress/issue-1261.js:132,8]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:132,8]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:133,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:133,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:133,23]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:134,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:134,31]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:134,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:136,24]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:136,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,31]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:137,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,61]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,23]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:137,23]",
|
||||
"WARN: Boolean || always true [test/compress/issue-1261.js:138,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:138,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:138,23]",
|
||||
"WARN: Condition left of || always true [test/compress/issue-1261.js:139,8]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:139,8]",
|
||||
"WARN: Boolean && always false [test/compress/issue-1261.js:140,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:140,23]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:140,23]",
|
||||
"WARN: Condition left of && always false [test/compress/issue-1261.js:141,8]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:141,8]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:142,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:142,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:142,23]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:143,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:143,31]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:143,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:144,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:145,24]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:145,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:146,31]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:146,8]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ chained_evaluation_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -28,6 +29,7 @@ chained_evaluation_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ f7: {
|
||||
negate_iife: true,
|
||||
passes: 3,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
side_effects_catch: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -34,6 +35,7 @@ side_effects_catch: {
|
||||
|
||||
side_effects_else: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -62,6 +64,7 @@ side_effects_else: {
|
||||
|
||||
side_effects_finally: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -98,6 +101,7 @@ side_effects_finally: {
|
||||
|
||||
side_effects_label: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -130,6 +134,7 @@ side_effects_label: {
|
||||
|
||||
side_effects_switch: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
|
||||
@@ -2,6 +2,7 @@ unary_prefix: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
iife_for: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -26,6 +27,7 @@ iife_for: {
|
||||
iife_for_in: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -51,6 +53,7 @@ iife_for_in: {
|
||||
iife_do: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -80,6 +83,7 @@ iife_do: {
|
||||
iife_while: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
|
||||
@@ -3,6 +3,7 @@ collapse_vars_constants: {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -240,6 +241,7 @@ negate_iife_issue_1073: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
unused: true,
|
||||
@@ -267,6 +269,7 @@ issue_1288_side_effects: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -299,6 +302,7 @@ inner_var_for_in_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
@@ -330,6 +334,7 @@ issue_1595_3: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ this_binding_collapse_vars: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
};
|
||||
input: {
|
||||
var c = a; c();
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
keep_properties: {
|
||||
options = {
|
||||
properties: false
|
||||
};
|
||||
evaluate: true,
|
||||
properties: false,
|
||||
}
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
}
|
||||
@@ -12,6 +13,7 @@ keep_properties: {
|
||||
|
||||
dot_properties: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
}
|
||||
beautify = {
|
||||
@@ -37,6 +39,7 @@ dot_properties: {
|
||||
|
||||
dot_properties_es5: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
}
|
||||
beautify = {
|
||||
@@ -61,8 +64,8 @@ dot_properties_es5: {
|
||||
sub_properties: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
properties: true
|
||||
};
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
a[0] = 0;
|
||||
a["0"] = 1;
|
||||
@@ -81,18 +84,18 @@ sub_properties: {
|
||||
a[3.14] = 3;
|
||||
a.if = 4;
|
||||
a["foo bar"] = 5;
|
||||
a[NaN] = 6;
|
||||
a[null] = 7;
|
||||
a.NaN = 6;
|
||||
a.null = 7;
|
||||
a[void 0] = 8;
|
||||
}
|
||||
}
|
||||
|
||||
evaluate_array_length: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
unsafe: true,
|
||||
evaluate: true
|
||||
};
|
||||
}
|
||||
input: {
|
||||
a = [1, 2, 3].length;
|
||||
a = [1, 2, 3].join()["len" + "gth"];
|
||||
@@ -109,10 +112,10 @@ evaluate_array_length: {
|
||||
|
||||
evaluate_string_length: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
unsafe: true,
|
||||
evaluate: true
|
||||
};
|
||||
}
|
||||
input: {
|
||||
a = "foo".length;
|
||||
a = ("foo" + "bar")["len" + "gth"];
|
||||
@@ -151,7 +154,8 @@ mangle_properties: {
|
||||
|
||||
mangle_unquoted_properties: {
|
||||
options = {
|
||||
properties: false
|
||||
evaluate: true,
|
||||
properties: false,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
@@ -249,7 +253,8 @@ mangle_debug_suffix: {
|
||||
|
||||
mangle_debug_suffix_keep_quoted: {
|
||||
options = {
|
||||
properties: false
|
||||
evaluate: true,
|
||||
properties: false,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
@@ -677,8 +682,8 @@ accessor_this: {
|
||||
issue_2208_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
@@ -696,8 +701,8 @@ issue_2208_1: {
|
||||
issue_2208_2: {
|
||||
options = {
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
@@ -721,8 +726,8 @@ issue_2208_2: {
|
||||
issue_2208_3: {
|
||||
options = {
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
a = 42;
|
||||
@@ -746,8 +751,8 @@ issue_2208_3: {
|
||||
issue_2208_4: {
|
||||
options = {
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
function foo() {}
|
||||
@@ -770,8 +775,8 @@ issue_2208_4: {
|
||||
issue_2208_5: {
|
||||
options = {
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
@@ -804,3 +809,222 @@ issue_2256: {
|
||||
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_funcs: 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_funcs: 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_funcs: 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
strict: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: false,
|
||||
reduce_vars: false,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -30,6 +31,7 @@ strict: {
|
||||
strict_reduce_vars: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -58,6 +60,7 @@ strict_reduce_vars: {
|
||||
unsafe: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
reduce_funcs: false,
|
||||
reduce_vars: false,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -84,6 +87,7 @@ unsafe: {
|
||||
unsafe_reduce_vars: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -185,6 +189,7 @@ issue_2110_1: {
|
||||
pure_getters: "strict",
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -215,6 +220,7 @@ issue_2110_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -247,6 +253,7 @@ set_immutable_1: {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -270,6 +277,7 @@ set_immutable_2: {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -293,6 +301,7 @@ set_immutable_3: {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -318,6 +327,7 @@ set_immutable_4: {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -343,6 +353,7 @@ set_mutable_1: {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -367,6 +378,7 @@ set_mutable_2: {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -385,3 +397,217 @@ set_mutable_2: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2313_1: {
|
||||
options = {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
pure_getters: "strict",
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
if (x().y().z) {
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
return console.log(1), {
|
||||
y: function() {
|
||||
return console.log(2), {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++,
|
||||
x().y().z && console.log(3);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2313_2: {
|
||||
options = {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
pure_getters: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
if (x().y().z) {
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
return console.log(1), {
|
||||
y: function() {
|
||||
return console.log(2), {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++,
|
||||
x().y().z && console.log(3);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2313_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
pure_getters: "strict",
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
if (x().y().z) {
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
x().y().z && console.log(3);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2313_4: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
pure_getters: true,
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
if (x().y().z) {
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
x().y().z && console.log(3);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2313_5: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
x().y++;
|
||||
x().y;
|
||||
}
|
||||
expect: {
|
||||
x().y++;
|
||||
x().y;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2313_6: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
x().y++;
|
||||
x().y;
|
||||
}
|
||||
expect: {
|
||||
x().y++;
|
||||
x();
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -187,6 +187,7 @@ dont_screw_try_catch_undefined: {
|
||||
reduce_vars: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
ie8: true,
|
||||
unused: true,
|
||||
|
||||
@@ -739,3 +739,44 @@ issue_2062: {
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_2313: {
|
||||
options = {
|
||||
cascade: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b = 0;
|
||||
var foo = {
|
||||
get c() {
|
||||
a++;
|
||||
return 42;
|
||||
},
|
||||
set c(c) {
|
||||
b++;
|
||||
},
|
||||
d: function() {
|
||||
this.c++;
|
||||
if (this.c) console.log(a, b);
|
||||
}
|
||||
}
|
||||
foo.d();
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b = 0;
|
||||
var foo = {
|
||||
get c() {
|
||||
return a++, 42;
|
||||
},
|
||||
set c(c) {
|
||||
b++;
|
||||
},
|
||||
d: function() {
|
||||
if (this.c++, this.c) console.log(a, b);
|
||||
}
|
||||
}
|
||||
foo.d();
|
||||
}
|
||||
expect_stdout: "2 1"
|
||||
}
|
||||
|
||||
@@ -714,6 +714,7 @@ issue_1705_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
|
||||
10
test/input/issue-2310/input.js
Normal file
10
test/input/issue-2310/input.js
Normal file
@@ -0,0 +1,10 @@
|
||||
function foo() {
|
||||
return function() {
|
||||
console.log("PASS");
|
||||
};
|
||||
}
|
||||
|
||||
(function() {
|
||||
var f = foo();
|
||||
f();
|
||||
})();
|
||||
@@ -573,6 +573,25 @@ describe("bin/uglifyjs", function () {
|
||||
return JSON.stringify(map).replace(/"/g, '\\"');
|
||||
}
|
||||
});
|
||||
it("Should include function calls in source map", function(done) {
|
||||
var command = [
|
||||
uglifyjscmd,
|
||||
"test/input/issue-2310/input.js",
|
||||
"-c",
|
||||
"--source-map", "url=inline",
|
||||
].join(" ");
|
||||
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, [
|
||||
'function foo(){return function(){console.log("PASS")}}foo()();',
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIiwiZiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsTUFDTCxPQUFPLFdBQ0hDLFFBQVFDLElBQUksU0FLUkYsS0FDUkcifQ==",
|
||||
""
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should dump AST as JSON", function(done) {
|
||||
var command = uglifyjscmd + " test/input/global_defs/simple.js -mco ast";
|
||||
exec(command, function (err, stdout) {
|
||||
|
||||
@@ -73,6 +73,12 @@ describe("minify", function() {
|
||||
assert.strictEqual(run_code(compressed), run_code(original));
|
||||
});
|
||||
|
||||
it("should not parse invalid use of reserved words", function() {
|
||||
assert.strictEqual(Uglify.minify("function enum(){}").error, undefined);
|
||||
assert.strictEqual(Uglify.minify("function static(){}").error, undefined);
|
||||
assert.strictEqual(Uglify.minify("function this(){}").error.message, "Unexpected token: name (this)");
|
||||
});
|
||||
|
||||
describe("keep_quoted_props", function() {
|
||||
it("Should preserve quotes in object literals", function() {
|
||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||
@@ -291,4 +297,36 @@ describe("minify", function() {
|
||||
assert.strictEqual(result.code, "alert({bar:42});");
|
||||
});
|
||||
});
|
||||
|
||||
describe("collapse_vars", function() {
|
||||
it("Should not produce invalid AST", function() {
|
||||
var code = [
|
||||
"function f(a) {",
|
||||
" a = x();",
|
||||
" return a;",
|
||||
"}",
|
||||
"f();",
|
||||
].join("\n");
|
||||
var ast = Uglify.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ast: true
|
||||
},
|
||||
}).ast;
|
||||
assert.strictEqual(ast.TYPE, "Toplevel");
|
||||
assert.strictEqual(ast.body.length, 2);
|
||||
assert.strictEqual(ast.body[0].TYPE, "Defun");
|
||||
assert.strictEqual(ast.body[0].body.length, 2);
|
||||
assert.strictEqual(ast.body[0].body[0].TYPE, "SimpleStatement");
|
||||
var stat = ast.body[0].body[0];
|
||||
Uglify.minify(ast, {
|
||||
compress: {
|
||||
sequences: false
|
||||
}
|
||||
});
|
||||
assert.ok(stat.body);
|
||||
assert.strictEqual(stat.print_to_string(), "a=x()");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -162,6 +162,7 @@ var VALUES = [
|
||||
'"object"',
|
||||
'"number"',
|
||||
'"function"',
|
||||
'this',
|
||||
];
|
||||
|
||||
var BINARY_OPS_NO_COMMA = [
|
||||
@@ -349,10 +350,10 @@ function createParams() {
|
||||
return params.join(', ');
|
||||
}
|
||||
|
||||
function createArgs() {
|
||||
function createArgs(recurmax, stmtDepth, canThrow) {
|
||||
var args = [];
|
||||
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(', ');
|
||||
}
|
||||
@@ -390,9 +391,10 @@ function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
||||
|
||||
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)
|
||||
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;
|
||||
}
|
||||
@@ -626,6 +628,9 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||
case p++:
|
||||
case p++:
|
||||
return createValue();
|
||||
case p++:
|
||||
case p++:
|
||||
return getVarName();
|
||||
case p++:
|
||||
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);
|
||||
case p++:
|
||||
|
||||
@@ -16,11 +16,9 @@
|
||||
{},
|
||||
{
|
||||
"compress": {
|
||||
"toplevel": true
|
||||
"hoist_props": true
|
||||
},
|
||||
"mangle": {
|
||||
"toplevel": true
|
||||
}
|
||||
"toplevel": true
|
||||
},
|
||||
{
|
||||
"compress": {
|
||||
|
||||
Reference in New Issue
Block a user