Compare commits
35 Commits
harmony-v3
...
v3.1.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
f81ff10a9b | ||
|
|
16d40915b4 | ||
|
|
e7c21e87e3 | ||
|
|
c4c2ef44d0 | ||
|
|
a845897758 | ||
|
|
32ea2c5530 | ||
|
|
bc61deeca9 | ||
|
|
6a5e74b44e | ||
|
|
54446341ee |
9
.github/ISSUE_TEMPLATE.md
vendored
9
.github/ISSUE_TEMPLATE.md
vendored
@@ -8,7 +8,14 @@
|
|||||||
|
|
||||||
**Uglify version (`uglifyjs -V`)**
|
**Uglify version (`uglifyjs -V`)**
|
||||||
|
|
||||||
**JavaScript input** <!-- ideally as small as possible -->
|
**JavaScript input**
|
||||||
|
|
||||||
|
<!--
|
||||||
|
A complete parsable JS program exhibiting the issue with
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
**The `uglifyjs` CLI command executed or `minify()` options used.**
|
**The `uglifyjs` CLI command executed or `minify()` options used.**
|
||||||
|
|
||||||
|
|||||||
261
README.md
261
README.md
@@ -150,19 +150,19 @@ debugging your compressed JavaScript. To get a source map, pass
|
|||||||
|
|
||||||
Additional options:
|
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
|
Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
|
||||||
`//# sourceMappingURL=` directive.
|
`//# sourceMappingURL=` directive.
|
||||||
|
|
||||||
- `--source-map url=<URL>` to specify the URL where the source map can be found.
|
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
uglifyjs js/file1.js js/file2.js \
|
uglifyjs js/file1.js js/file2.js \
|
||||||
-o foo.min.js -c -m \
|
-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
|
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
|
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
|
compressed JS by mapping every token in the compiled JS to its original
|
||||||
location.
|
location.
|
||||||
|
|
||||||
To use this feature pass `--source-map content="/path/to/input/source.map"`
|
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
|
or `--source-map "content=inline"` if the source map is included inline with
|
||||||
the sources.
|
the sources.
|
||||||
|
|
||||||
## CLI compress options
|
## CLI compress options
|
||||||
@@ -203,17 +203,15 @@ Example:
|
|||||||
To enable the mangler you need to pass `--mangle` (`-m`). The following
|
To enable the mangler you need to pass `--mangle` (`-m`). The following
|
||||||
(comma-separated) options are supported:
|
(comma-separated) options are supported:
|
||||||
|
|
||||||
- `toplevel` — mangle names declared in the top level scope (disabled by
|
- `toplevel` (default `false`) -- mangle names declared in the top level scope.
|
||||||
default).
|
|
||||||
|
|
||||||
- `eval` — mangle names visible in scopes where `eval` or `with` are used
|
- `eval` (default `false`) -- mangle names visible in scopes where `eval` or `with` are used.
|
||||||
(disabled by default).
|
|
||||||
|
|
||||||
When mangling is enabled but you want to prevent certain names from being
|
When mangling is enabled but you want to prevent certain names from being
|
||||||
mangled, you can declare those names with `--mangle reserved` — pass a
|
mangled, you can declare those names with `--mangle reserved` — pass a
|
||||||
comma-separated list of names. For example:
|
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.
|
to prevent the `require`, `exports` and `$` names from being changed.
|
||||||
|
|
||||||
@@ -510,6 +508,9 @@ if (result.error) throw result.error;
|
|||||||
|
|
||||||
- `ie8` (default `false`) - set to `true` to support IE8.
|
- `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
|
## Minify options structure
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@@ -590,111 +591,78 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
## Parse options
|
## Parse options
|
||||||
|
|
||||||
- `bare_returns` (default `false`) -- support top level `return` statements
|
- `bare_returns` (default `false`) -- support top level `return` statements
|
||||||
|
|
||||||
- `html5_comments` (default `true`)
|
- `html5_comments` (default `true`)
|
||||||
|
|
||||||
- `shebang` (default `true`) -- support `#!command` as the first line
|
- `shebang` (default `true`) -- support `#!command` as the first line
|
||||||
|
|
||||||
## Compress options
|
## Compress options
|
||||||
|
|
||||||
- `sequences` (default: true) -- join consecutive simple statements using the
|
- `booleans` (default: `true`) -- various optimizations for boolean context, for example `!!a
|
||||||
comma operator. May be set to a positive integer to specify the maximum number
|
? b : c → a ? b : c`
|
||||||
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.
|
|
||||||
|
|
||||||
- `properties` -- rewrite property access using the dot notation, for
|
- `cascade` (default: `true`) -- small optimization for sequences, transform `x, x` into `x`
|
||||||
example `foo["bar"] → foo.bar`
|
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
|
- `comparisons` (default: `true`) -- apply certain optimizations to binary nodes, for example:
|
||||||
|
|
||||||
- `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:
|
|
||||||
`!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary
|
`!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary
|
||||||
nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
|
nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
|
||||||
|
|
||||||
- `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
|
- `dead_code` (default: `true`) -- remove unreachable code
|
||||||
? b : c → a ? b : c`
|
|
||||||
|
|
||||||
- `typeofs` -- default `true`. Transforms `typeof foo == "undefined"` into
|
- `drop_console` (default: `false`) -- default `false`. Pass `true` to discard calls to
|
||||||
`foo === void 0`. Note: recommend to set this value to `false` for IE10 and
|
`console.*` functions. If you wish to drop a specific function call
|
||||||
earlier versions due to known issues.
|
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
|
- `drop_debugger` (default: `true`) -- remove `debugger;` statements
|
||||||
statically determine the condition
|
|
||||||
|
|
||||||
- `unused` -- drop unreferenced functions and variables (simple direct variable
|
- `evaluate` (default: `true`) -- attempt to evaluate constant expressions
|
||||||
assignments do not count as references unless set to `"keep_assign"`)
|
|
||||||
|
|
||||||
- `toplevel` -- drop unreferenced functions (`"funcs"`) and/or variables (`"vars"`)
|
- `expression` (default: `false`) -- default `false`. Pass `true` to preserve completion values
|
||||||
in the top level scope (`false` by default, `true` to drop both unreferenced
|
from terminal statements without `return`, e.g. in bookmarklets.
|
||||||
functions and variables)
|
|
||||||
|
|
||||||
- `top_retain` -- prevent specific toplevel functions and variables from `unused`
|
- `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation)
|
||||||
removal (can be array, comma-separated, RegExp or function. Implies `toplevel`)
|
|
||||||
|
|
||||||
- `hoist_funs` -- hoist function declarations
|
- `hoist_funs` (default: `true`) -- hoist function declarations
|
||||||
|
|
||||||
- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false`
|
- `hoist_vars` (default: `false`) -- hoist `var` declarations (this is `false`
|
||||||
by default because it seems to increase the size of the output in general)
|
by default because it seems to increase the size of the output in general)
|
||||||
|
|
||||||
- `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`
|
- `keep_fargs` (default: `true`) -- default `true`. Prevents the
|
||||||
and `x = something(), x` into `x = something()`
|
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
|
- `keep_infinity` (default: `false`) -- default `false`. Pass `true` to prevent `Infinity` from
|
||||||
effects permitting.
|
being compressed into `1/0`, which may cause performance issues on Chrome.
|
||||||
|
|
||||||
- `reduce_vars` -- Improve optimization on variables assigned with and
|
- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops when we can
|
||||||
used as constant values.
|
statically determine the condition
|
||||||
|
|
||||||
- `warnings` -- display warnings when dropping unreachable code or unused
|
- `negate_iife` (default: `true`) -- negate "Immediately-Called Function Expressions"
|
||||||
declarations etc.
|
|
||||||
|
|
||||||
- `negate_iife` -- negate "Immediately-Called Function Expressions"
|
|
||||||
where the return value is discarded, to avoid the parens that the
|
where the return value is discarded, to avoid the parens that the
|
||||||
code generator would insert.
|
code generator would insert.
|
||||||
|
|
||||||
- `pure_getters` -- the default is `false`. If you pass `true` for
|
- `passes` (default: `1`) -- The maximum number of times to run compress.
|
||||||
this, UglifyJS will assume that object property access
|
In some cases more than one pass leads to further compressed code. Keep in
|
||||||
(e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects.
|
mind more passes will take more time.
|
||||||
Specify `"strict"` to treat `foo.bar` as side-effect-free only when
|
|
||||||
`foo` is certain to not throw, i.e. not `null` or `undefined`.
|
|
||||||
|
|
||||||
- `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
|
UglifyJS will assume that those functions do not produce side
|
||||||
effects. DANGER: will not check if the name is redefined in scope.
|
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
|
An example case here, for instance `var q = Math.floor(a/b)`. If
|
||||||
@@ -705,34 +673,69 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
statement would get discarded. The current implementation adds some
|
statement would get discarded. The current implementation adds some
|
||||||
overhead (compression will be slower).
|
overhead (compression will be slower).
|
||||||
|
|
||||||
- `drop_console` -- default `false`. Pass `true` to discard calls to
|
- `pure_getters` (default: `"strict"`) -- If you pass `true` for
|
||||||
`console.*` functions. If you wish to drop a specific function call
|
this, UglifyJS will assume that object property access
|
||||||
such as `console.info` and/or retain side effects from function arguments
|
(e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects.
|
||||||
after dropping the function call then use `pure_funcs` instead.
|
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
|
- `reduce_vars` (default: `true`) -- Improve optimization on variables assigned with and
|
||||||
from terminal statements without `return`, e.g. in bookmarklets.
|
used as constant values.
|
||||||
|
|
||||||
- `keep_fargs` -- default `true`. Prevents the
|
- `sequences` (default: `true`) -- join consecutive simple statements using the
|
||||||
compressor from discarding unused function arguments. You need this
|
comma operator. May be set to a positive integer to specify the maximum number
|
||||||
for code which relies on `Function.length`.
|
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
|
- `side_effects` (default: `true`) -- default `true`. Pass `false` to disable potentially dropping
|
||||||
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
|
|
||||||
functions marked as "pure". A function call is marked as "pure" if a comment
|
functions marked as "pure". A function call is marked as "pure" if a comment
|
||||||
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
|
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
|
||||||
example: `/*@__PURE__*/foo();`
|
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_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` (default: `false`) -- apply "unsafe" transformations (discussion below)
|
||||||
|
|
||||||
|
- `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
|
## Mangle options
|
||||||
|
|
||||||
- `reserved` (default `[]`). Pass an array of identifiers that should be
|
- `reserved` (default `[]`). Pass an array of identifiers that should be
|
||||||
@@ -741,10 +744,6 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
- `toplevel` (default `false`). Pass `true` to mangle names declared in the
|
- `toplevel` (default `false`). Pass `true` to mangle names declared in the
|
||||||
top level scope.
|
top level scope.
|
||||||
|
|
||||||
- `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
|
- `eval` (default `false`). Pass `true` to mangle names visible in scopes
|
||||||
where `eval` or `with` are used.
|
where `eval` or `with` are used.
|
||||||
|
|
||||||
@@ -772,16 +771,20 @@ UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
|
|||||||
|
|
||||||
### Mangle properties options
|
### 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
|
- `builtins` (default: `false`) -- Use `true` to allow the mangling of builtin
|
||||||
DOM properties. Not recommended to override this setting.
|
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
|
## Output options
|
||||||
|
|
||||||
The code generator tries to output shortest code possible by default. In
|
The code generator tries to output shortest code possible by default. In
|
||||||
@@ -790,31 +793,43 @@ can pass additional arguments that control the code output:
|
|||||||
|
|
||||||
- `ascii_only` (default `false`) -- escape Unicode characters in strings and
|
- `ascii_only` (default `false`) -- escape Unicode characters in strings and
|
||||||
regexps (affects directives with non-ascii characters becoming invalid)
|
regexps (affects directives with non-ascii characters becoming invalid)
|
||||||
|
|
||||||
- `beautify` (default `true`) -- whether to actually beautify the output.
|
- `beautify` (default `true`) -- whether to actually beautify the output.
|
||||||
Passing `-b` will set this to true, but you might need to pass `-b` even
|
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
|
when you want to generate minified code, in order to specify additional
|
||||||
arguments, so you can use `-b beautify=false` to override it.
|
arguments, so you can use `-b beautify=false` to override it.
|
||||||
|
|
||||||
- `bracketize` (default `false`) -- always insert brackets in `if`, `for`,
|
- `bracketize` (default `false`) -- always insert brackets in `if`, `for`,
|
||||||
`do`, `while` or `with` statements, even if their body is a single
|
`do`, `while` or `with` statements, even if their body is a single
|
||||||
statement.
|
statement.
|
||||||
|
|
||||||
- `comments` (default `false`) -- pass `true` or `"all"` to preserve all
|
- `comments` (default `false`) -- pass `true` or `"all"` to preserve all
|
||||||
comments, `"some"` to preserve some comments, a regular expression string
|
comments, `"some"` to preserve some comments, a regular expression string
|
||||||
(e.g. `/^!/`) or a function.
|
(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
|
- `inline_script` (default `false`) -- escape the slash in occurrences of
|
||||||
`</script` in strings
|
`</script` in strings
|
||||||
|
|
||||||
- `keep_quoted_props` (default `false`) -- when turned on, prevents stripping
|
- `keep_quoted_props` (default `false`) -- when turned on, prevents stripping
|
||||||
quotes from property names in object literals.
|
quotes from property names in object literals.
|
||||||
|
|
||||||
- `max_line_len` (default `false`) -- maximum line length (for uglified code)
|
- `max_line_len` (default `false`) -- maximum line length (for uglified code)
|
||||||
|
|
||||||
- `preamble` (default `null`) -- when passed it must be a string and
|
- `preamble` (default `null`) -- when passed it must be a string and
|
||||||
it will be prepended to the output literally. The source map will
|
it will be prepended to the output literally. The source map will
|
||||||
adjust for this text. Can be used to insert a comment containing
|
adjust for this text. Can be used to insert a comment containing
|
||||||
licensing information, for example.
|
licensing information, for example.
|
||||||
|
|
||||||
- `preserve_line` (default `false`) -- pass `true` to preserve lines, but it
|
- `preserve_line` (default `false`) -- pass `true` to preserve lines, but it
|
||||||
only works if `beautify` is set to `false`.
|
only works if `beautify` is set to `false`.
|
||||||
|
|
||||||
- `quote_keys` (default `false`) -- pass `true` to quote all keys in literal
|
- `quote_keys` (default `false`) -- pass `true` to quote all keys in literal
|
||||||
objects
|
objects
|
||||||
|
|
||||||
- `quote_style` (default `0`) -- preferred quote style for strings (affects
|
- `quote_style` (default `0`) -- preferred quote style for strings (affects
|
||||||
quoted property names and directives as well):
|
quoted property names and directives as well):
|
||||||
- `0` -- prefers double quotes, switches to single quotes when there are
|
- `0` -- prefers double quotes, switches to single quotes when there are
|
||||||
@@ -822,16 +837,20 @@ can pass additional arguments that control the code output:
|
|||||||
- `1` -- always use single quotes
|
- `1` -- always use single quotes
|
||||||
- `2` -- always use double quotes
|
- `2` -- always use double quotes
|
||||||
- `3` -- always use the original quotes
|
- `3` -- always use the original quotes
|
||||||
|
|
||||||
- `semicolons` (default `true`) -- separate statements with semicolons. If
|
- `semicolons` (default `true`) -- separate statements with semicolons. If
|
||||||
you pass `false` then whenever possible we will use a newline instead of a
|
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
|
semicolon, leading to more readable output of uglified code (size before
|
||||||
gzip could be smaller; size after gzip insignificantly larger).
|
gzip could be smaller; size after gzip insignificantly larger).
|
||||||
|
|
||||||
- `shebang` (default `true`) -- preserve shebang `#!` in preamble (bash scripts)
|
- `shebang` (default `true`) -- preserve shebang `#!` in preamble (bash scripts)
|
||||||
- `width` (default 80) -- only takes effect when beautification is on, this
|
|
||||||
|
- `width` (default `80`) -- only takes effect when beautification is on, this
|
||||||
specifies an (orientative) line width that the beautifier will try to
|
specifies an (orientative) line width that the beautifier will try to
|
||||||
obey. It refers to the width of the line text (excluding indentation).
|
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
|
It doesn't work very well currently, but it does make the code generated
|
||||||
by UglifyJS more readable.
|
by UglifyJS more readable.
|
||||||
|
|
||||||
- `wrap_iife` (default `false`) -- pass `true` to wrap immediately invoked
|
- `wrap_iife` (default `false`) -- pass `true` to wrap immediately invoked
|
||||||
function expressions. See
|
function expressions. See
|
||||||
[#640](https://github.com/mishoo/UglifyJS2/issues/640) for more details.
|
[#640](https://github.com/mishoo/UglifyJS2/issues/640) for more details.
|
||||||
|
|||||||
@@ -134,11 +134,10 @@ var AST_Debugger = DEFNODE("Debugger", null, {
|
|||||||
$documentation: "Represents a debugger statement",
|
$documentation: "Represents a debugger statement",
|
||||||
}, AST_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\";",
|
$documentation: "Represents a directive, like \"use strict\";",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
|
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"
|
quote: "[string] the original quote character"
|
||||||
},
|
},
|
||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
@@ -299,10 +298,9 @@ var AST_With = DEFNODE("With", "expression", {
|
|||||||
|
|
||||||
/* -----[ scope and functions ]----- */
|
/* -----[ 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",
|
$documentation: "Base class for all statements introducing a lexical scope",
|
||||||
$propdoc: {
|
$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",
|
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",
|
functions: "[Object/S] like `variables`, but only lists function declarations",
|
||||||
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
|
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
|
||||||
|
|||||||
110
lib/compress.js
110
lib/compress.js
@@ -285,6 +285,10 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan) {
|
AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan) {
|
||||||
var reduce_vars = rescan && compressor.option("reduce_vars");
|
var reduce_vars = rescan && compressor.option("reduce_vars");
|
||||||
|
// Stack of look-up tables to keep track of whether a `SymbolDef` has been
|
||||||
|
// properly assigned before use:
|
||||||
|
// - `push()` & `pop()` when visiting conditional branches
|
||||||
|
// - backup & restore via `save_ids` when visiting out-of-order sections
|
||||||
var safe_ids = Object.create(null);
|
var safe_ids = Object.create(null);
|
||||||
var suppressor = new TreeWalker(function(node) {
|
var suppressor = new TreeWalker(function(node) {
|
||||||
if (!(node instanceof AST_Symbol)) return;
|
if (!(node instanceof AST_Symbol)) return;
|
||||||
@@ -293,6 +297,8 @@ merge(Compressor.prototype, {
|
|||||||
if (node instanceof AST_SymbolRef) d.references.push(node);
|
if (node instanceof AST_SymbolRef) d.references.push(node);
|
||||||
d.fixed = false;
|
d.fixed = false;
|
||||||
});
|
});
|
||||||
|
var in_loop = null;
|
||||||
|
var loop_ids = Object.create(null);
|
||||||
var tw = new TreeWalker(function(node, descend) {
|
var tw = new TreeWalker(function(node, descend) {
|
||||||
node._squeezed = false;
|
node._squeezed = false;
|
||||||
node._optimized = false;
|
node._optimized = false;
|
||||||
@@ -303,7 +309,7 @@ merge(Compressor.prototype, {
|
|||||||
var d = node.definition();
|
var d = node.definition();
|
||||||
d.references.push(node);
|
d.references.push(node);
|
||||||
if (d.fixed === undefined || !safe_to_read(d)
|
if (d.fixed === undefined || !safe_to_read(d)
|
||||||
|| is_modified(node, 0, is_immutable(node.fixed_value()))) {
|
|| is_modified(node, 0, is_immutable(node))) {
|
||||||
d.fixed = false;
|
d.fixed = false;
|
||||||
} else {
|
} else {
|
||||||
var parent = tw.parent();
|
var parent = tw.parent();
|
||||||
@@ -325,6 +331,7 @@ merge(Compressor.prototype, {
|
|||||||
d.fixed = function() {
|
d.fixed = function() {
|
||||||
return node.value;
|
return node.value;
|
||||||
};
|
};
|
||||||
|
loop_ids[d.id] = in_loop;
|
||||||
mark(d, false);
|
mark(d, false);
|
||||||
descend();
|
descend();
|
||||||
} else {
|
} else {
|
||||||
@@ -380,6 +387,7 @@ merge(Compressor.prototype, {
|
|||||||
d.fixed = function() {
|
d.fixed = function() {
|
||||||
return iife.args[i] || make_node(AST_Undefined, iife);
|
return iife.args[i] || make_node(AST_Undefined, iife);
|
||||||
};
|
};
|
||||||
|
loop_ids[d.id] = in_loop;
|
||||||
mark(d, true);
|
mark(d, true);
|
||||||
} else {
|
} else {
|
||||||
d.fixed = false;
|
d.fixed = false;
|
||||||
@@ -391,10 +399,9 @@ merge(Compressor.prototype, {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Accessor) {
|
if (node instanceof AST_Accessor) {
|
||||||
var save_ids = safe_ids;
|
push();
|
||||||
safe_ids = Object.create(null);
|
|
||||||
descend();
|
descend();
|
||||||
safe_ids = save_ids;
|
pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Binary
|
if (node instanceof AST_Binary
|
||||||
@@ -428,10 +435,13 @@ merge(Compressor.prototype, {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_DWLoop) {
|
if (node instanceof AST_DWLoop) {
|
||||||
|
var saved_loop = in_loop;
|
||||||
|
in_loop = node;
|
||||||
push();
|
push();
|
||||||
node.condition.walk(tw);
|
node.condition.walk(tw);
|
||||||
node.body.walk(tw);
|
node.body.walk(tw);
|
||||||
pop();
|
pop();
|
||||||
|
in_loop = saved_loop;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_LabeledStatement) {
|
if (node instanceof AST_LabeledStatement) {
|
||||||
@@ -442,6 +452,8 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_For) {
|
if (node instanceof AST_For) {
|
||||||
if (node.init) node.init.walk(tw);
|
if (node.init) node.init.walk(tw);
|
||||||
|
var saved_loop = in_loop;
|
||||||
|
in_loop = node;
|
||||||
if (node.condition) {
|
if (node.condition) {
|
||||||
push();
|
push();
|
||||||
node.condition.walk(tw);
|
node.condition.walk(tw);
|
||||||
@@ -455,14 +467,18 @@ merge(Compressor.prototype, {
|
|||||||
node.step.walk(tw);
|
node.step.walk(tw);
|
||||||
pop();
|
pop();
|
||||||
}
|
}
|
||||||
|
in_loop = saved_loop;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_ForIn) {
|
if (node instanceof AST_ForIn) {
|
||||||
node.init.walk(suppressor);
|
node.init.walk(suppressor);
|
||||||
node.object.walk(tw);
|
node.object.walk(tw);
|
||||||
|
var saved_loop = in_loop;
|
||||||
|
in_loop = node;
|
||||||
push();
|
push();
|
||||||
node.body.walk(tw);
|
node.body.walk(tw);
|
||||||
pop();
|
pop();
|
||||||
|
in_loop = saved_loop;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Try) {
|
if (node instanceof AST_Try) {
|
||||||
@@ -532,10 +548,23 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
def.references = [];
|
def.references = [];
|
||||||
def.should_replace = undefined;
|
def.should_replace = undefined;
|
||||||
|
def.single_use = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_immutable(value) {
|
function is_immutable(node) {
|
||||||
return value && value.is_constant() || value instanceof AST_Lambda;
|
var value = node.fixed_value();
|
||||||
|
if (!value) return false;
|
||||||
|
if (value.is_constant()) return true;
|
||||||
|
if (compressor.option("unused")) {
|
||||||
|
var d = node.definition();
|
||||||
|
if (d.single_use === undefined) {
|
||||||
|
d.single_use = loop_ids[d.id] === in_loop
|
||||||
|
&& d.scope === node.scope
|
||||||
|
&& value.is_constant_expression();
|
||||||
|
}
|
||||||
|
if (d.references.length == 1 && d.single_use) return true;
|
||||||
|
}
|
||||||
|
return value instanceof AST_Lambda;
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_modified(node, level, immutable) {
|
function is_modified(node, level, immutable) {
|
||||||
@@ -561,6 +590,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function is_lhs_read_only(lhs) {
|
function is_lhs_read_only(lhs) {
|
||||||
|
if (lhs instanceof AST_This) return true;
|
||||||
if (lhs instanceof AST_SymbolRef) return lhs.definition().orig[0] instanceof AST_SymbolLambda;
|
if (lhs instanceof AST_SymbolRef) return lhs.definition().orig[0] instanceof AST_SymbolLambda;
|
||||||
if (lhs instanceof AST_PropAccess) {
|
if (lhs instanceof AST_PropAccess) {
|
||||||
lhs = lhs.expression;
|
lhs = lhs.expression;
|
||||||
@@ -693,7 +723,7 @@ merge(Compressor.prototype, {
|
|||||||
return node instanceof AST_SymbolRef && node.definition().undeclared;
|
return node instanceof AST_SymbolRef && node.definition().undeclared;
|
||||||
}
|
}
|
||||||
|
|
||||||
var global_names = makePredicate("Array Boolean console Error Function Math Number RegExp Object String");
|
var global_names = makePredicate("Array Boolean clearInterval clearTimeout console Date decodeURI decodeURIComponent encodeURI encodeURIComponent Error escape eval EvalError Function isFinite isNaN JSON Math Number parseFloat parseInt RangeError ReferenceError RegExp Object setInterval setTimeout String SyntaxError TypeError unescape URIError");
|
||||||
AST_SymbolRef.DEFMETHOD("is_declared", function(compressor) {
|
AST_SymbolRef.DEFMETHOD("is_declared", function(compressor) {
|
||||||
return !this.definition().undeclared
|
return !this.definition().undeclared
|
||||||
|| compressor.option("unsafe") && global_names(this.name);
|
|| compressor.option("unsafe") && global_names(this.name);
|
||||||
@@ -745,7 +775,7 @@ merge(Compressor.prototype, {
|
|||||||
while (candidates.length > 0) {
|
while (candidates.length > 0) {
|
||||||
var candidate = candidates.pop();
|
var candidate = candidates.pop();
|
||||||
var lhs = get_lhs(candidate);
|
var lhs = get_lhs(candidate);
|
||||||
if (!lhs || is_lhs_read_only(lhs)) continue;
|
if (!lhs || is_lhs_read_only(lhs) || lhs.has_side_effects(compressor)) continue;
|
||||||
// Locate symbols which may execute code outside of scanning range
|
// Locate symbols which may execute code outside of scanning range
|
||||||
var lvalues = get_lvalues(candidate);
|
var lvalues = get_lvalues(candidate);
|
||||||
if (lhs instanceof AST_SymbolRef) lvalues[lhs.name] = false;
|
if (lhs instanceof AST_SymbolRef) lvalues[lhs.name] = false;
|
||||||
@@ -808,7 +838,7 @@ merge(Compressor.prototype, {
|
|||||||
var sym;
|
var sym;
|
||||||
if (node instanceof AST_Call
|
if (node instanceof AST_Call
|
||||||
|| node instanceof AST_Exit
|
|| node instanceof AST_Exit
|
||||||
|| node instanceof AST_PropAccess
|
|| node instanceof AST_PropAccess && node.has_side_effects(compressor)
|
||||||
|| node instanceof AST_SymbolRef
|
|| node instanceof AST_SymbolRef
|
||||||
&& (lvalues[node.name]
|
&& (lvalues[node.name]
|
||||||
|| side_effects && !references_in_scope(node.definition()))
|
|| side_effects && !references_in_scope(node.definition()))
|
||||||
@@ -841,13 +871,15 @@ merge(Compressor.prototype, {
|
|||||||
&& !fn.uses_eval
|
&& !fn.uses_eval
|
||||||
&& (iife = compressor.parent()) instanceof AST_Call
|
&& (iife = compressor.parent()) instanceof AST_Call
|
||||||
&& iife.expression === fn) {
|
&& iife.expression === fn) {
|
||||||
|
var fn_strict = compressor.has_directive("use strict");
|
||||||
|
if (fn_strict && fn.body.indexOf(fn_strict) < 0) fn_strict = false;
|
||||||
var names = Object.create(null);
|
var names = Object.create(null);
|
||||||
for (var i = fn.argnames.length; --i >= 0;) {
|
for (var i = fn.argnames.length; --i >= 0;) {
|
||||||
var sym = fn.argnames[i];
|
var sym = fn.argnames[i];
|
||||||
if (sym.name in names) continue;
|
if (sym.name in names) continue;
|
||||||
names[sym.name] = true;
|
names[sym.name] = true;
|
||||||
var arg = iife.args[i];
|
var arg = iife.args[i];
|
||||||
if (!arg) arg = make_node(AST_Undefined, sym);
|
if (!arg) arg = make_node(AST_Undefined, sym).transform(compressor);
|
||||||
else {
|
else {
|
||||||
var tw = new TreeWalker(function(node) {
|
var tw = new TreeWalker(function(node) {
|
||||||
if (!arg) return true;
|
if (!arg) return true;
|
||||||
@@ -858,7 +890,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
arg = null;
|
arg = null;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_This && !tw.find_parent(AST_Scope)) {
|
if (node instanceof AST_This && (fn_strict || !tw.find_parent(AST_Scope))) {
|
||||||
arg = null;
|
arg = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1980,16 +2012,27 @@ merge(Compressor.prototype, {
|
|||||||
if (!compressor.option("side_effects")) return false;
|
if (!compressor.option("side_effects")) return false;
|
||||||
if (this.pure !== undefined) return this.pure;
|
if (this.pure !== undefined) return this.pure;
|
||||||
var pure = false;
|
var pure = false;
|
||||||
var comments, last_comment;
|
var comments, pure_comment;
|
||||||
if (this.start
|
if (this.start
|
||||||
&& (comments = this.start.comments_before)
|
&& (comments = this.start.comments_before)
|
||||||
&& comments.length
|
&& comments.length
|
||||||
&& /[@#]__PURE__/.test((last_comment = comments[comments.length - 1]).value)) {
|
&& (pure_comment = find_if(function (comment) {
|
||||||
pure = last_comment;
|
return /[@#]__PURE__/.test(comment.value);
|
||||||
|
}, comments))) {
|
||||||
|
pure = pure_comment;
|
||||||
}
|
}
|
||||||
return this.pure = pure;
|
return this.pure = pure;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var global_pure_fns = makePredicate("Boolean decodeURI decodeURIComponent Date encodeURI encodeURIComponent Error escape EvalError isFinite isNaN Number Object parseFloat parseInt RangeError ReferenceError String SyntaxError TypeError unescape URIError");
|
||||||
|
AST_Call.DEFMETHOD("is_expr_pure", function(compressor) {
|
||||||
|
if (compressor.option("unsafe")) {
|
||||||
|
var expr = this.expression;
|
||||||
|
if (is_undeclared_ref(expr) && global_pure_fns(expr.name)) return true;
|
||||||
|
}
|
||||||
|
return this.has_pure_annotation(compressor) || !compressor.pure_funcs(this);
|
||||||
|
});
|
||||||
|
|
||||||
// determine if expression has side effects
|
// determine if expression has side effects
|
||||||
(function(def){
|
(function(def){
|
||||||
def(AST_Node, return_true);
|
def(AST_Node, return_true);
|
||||||
@@ -1999,7 +2042,7 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_This, return_false);
|
def(AST_This, return_false);
|
||||||
|
|
||||||
def(AST_Call, function(compressor){
|
def(AST_Call, function(compressor){
|
||||||
if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) return true;
|
if (!this.is_expr_pure(compressor)) return true;
|
||||||
for (var i = this.args.length; --i >= 0;) {
|
for (var i = this.args.length; --i >= 0;) {
|
||||||
if (this.args[i].has_side_effects(compressor))
|
if (this.args[i].has_side_effects(compressor))
|
||||||
return true;
|
return true;
|
||||||
@@ -2098,6 +2141,22 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
def(AST_Node, return_false);
|
def(AST_Node, return_false);
|
||||||
def(AST_Constant, return_true);
|
def(AST_Constant, return_true);
|
||||||
|
def(AST_Function, function(){
|
||||||
|
var self = this;
|
||||||
|
var result = true;
|
||||||
|
self.walk(new TreeWalker(function(node) {
|
||||||
|
if (!result) return true;
|
||||||
|
if (node instanceof AST_SymbolRef) {
|
||||||
|
var def = node.definition();
|
||||||
|
if (self.enclosed.indexOf(def) >= 0
|
||||||
|
&& self.variables.get(def.name) !== def) {
|
||||||
|
result = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
return result;
|
||||||
|
});
|
||||||
def(AST_Unary, function(){
|
def(AST_Unary, function(){
|
||||||
return this.expression.is_constant_expression();
|
return this.expression.is_constant_expression();
|
||||||
});
|
});
|
||||||
@@ -2423,17 +2482,18 @@ merge(Compressor.prototype, {
|
|||||||
// We fix it at this stage by moving the `var` outside the `for`.
|
// We fix it at this stage by moving the `var` outside the `for`.
|
||||||
if (node instanceof AST_For) {
|
if (node instanceof AST_For) {
|
||||||
descend(node, this);
|
descend(node, this);
|
||||||
|
var block;
|
||||||
if (node.init instanceof AST_BlockStatement) {
|
if (node.init instanceof AST_BlockStatement) {
|
||||||
var block = node.init;
|
block = node.init;
|
||||||
node.init = block.body.pop();
|
node.init = block.body.pop();
|
||||||
block.body.push(node);
|
block.body.push(node);
|
||||||
return in_list ? MAP.splice(block.body) : block;
|
}
|
||||||
} else if (node.init instanceof AST_SimpleStatement) {
|
if (node.init instanceof AST_SimpleStatement) {
|
||||||
node.init = node.init.body;
|
node.init = node.init.body;
|
||||||
} else if (is_empty(node.init)) {
|
} else if (is_empty(node.init)) {
|
||||||
node.init = null;
|
node.init = null;
|
||||||
}
|
}
|
||||||
return node;
|
return !block ? node : in_list ? MAP.splice(block.body) : block;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_LabeledStatement && node.body instanceof AST_For) {
|
if (node instanceof AST_LabeledStatement && node.body instanceof AST_For) {
|
||||||
descend(node, this);
|
descend(node, this);
|
||||||
@@ -2617,7 +2677,7 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Constant, return_null);
|
def(AST_Constant, return_null);
|
||||||
def(AST_This, return_null);
|
def(AST_This, return_null);
|
||||||
def(AST_Call, function(compressor, first_in_statement){
|
def(AST_Call, function(compressor, first_in_statement){
|
||||||
if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) {
|
if (!this.is_expr_pure(compressor)) {
|
||||||
if (this.expression instanceof AST_Function
|
if (this.expression instanceof AST_Function
|
||||||
&& (!this.expression.name || !this.expression.name.definition().references.length)) {
|
&& (!this.expression.name || !this.expression.name.definition().references.length)) {
|
||||||
var node = this.clone();
|
var node = this.clone();
|
||||||
@@ -3112,6 +3172,7 @@ merge(Compressor.prototype, {
|
|||||||
}));
|
}));
|
||||||
if (reduce_vars) name.definition().fixed = false;
|
if (reduce_vars) name.definition().fixed = false;
|
||||||
}
|
}
|
||||||
|
remove(def.name.definition().orig, def.name);
|
||||||
return a;
|
return a;
|
||||||
}, []);
|
}, []);
|
||||||
if (assignments.length == 0) return null;
|
if (assignments.length == 0) return null;
|
||||||
@@ -3483,7 +3544,7 @@ merge(Compressor.prototype, {
|
|||||||
&& (left.operator == "++" || left.operator == "--")) {
|
&& (left.operator == "++" || left.operator == "--")) {
|
||||||
left = left.expression;
|
left = left.expression;
|
||||||
} else left = null;
|
} else left = null;
|
||||||
if (!left || is_lhs_read_only(left)) {
|
if (!left || is_lhs_read_only(left) || left.has_side_effects(compressor)) {
|
||||||
expressions[++i] = cdr;
|
expressions[++i] = cdr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -4059,12 +4120,13 @@ merge(Compressor.prototype, {
|
|||||||
d.fixed = fixed = make_node(AST_Function, fixed, fixed);
|
d.fixed = fixed = make_node(AST_Function, fixed, fixed);
|
||||||
}
|
}
|
||||||
if (compressor.option("unused")
|
if (compressor.option("unused")
|
||||||
&& fixed instanceof AST_Function
|
|
||||||
&& d.references.length == 1
|
&& d.references.length == 1
|
||||||
|
&& (d.single_use || fixed instanceof AST_Function
|
||||||
&& !(d.scope.uses_arguments && d.orig[0] instanceof AST_SymbolFunarg)
|
&& !(d.scope.uses_arguments && d.orig[0] instanceof AST_SymbolFunarg)
|
||||||
&& !d.scope.uses_eval
|
&& !d.scope.uses_eval
|
||||||
&& compressor.find_parent(AST_Scope) === fixed.parent_scope) {
|
&& compressor.find_parent(AST_Scope) === fixed.parent_scope)) {
|
||||||
return fixed.clone(true);
|
var value = fixed.optimize(compressor);
|
||||||
|
return value === fixed ? fixed.clone(true) : value;
|
||||||
}
|
}
|
||||||
if (compressor.option("evaluate") && fixed) {
|
if (compressor.option("evaluate") && fixed) {
|
||||||
if (d.should_replace === undefined) {
|
if (d.should_replace === undefined) {
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ function minify(files, options) {
|
|||||||
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
||||||
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
||||||
set_shorthand("warnings", options, [ "compress" ]);
|
set_shorthand("warnings", options, [ "compress" ]);
|
||||||
|
var quoted_props;
|
||||||
if (options.mangle) {
|
if (options.mangle) {
|
||||||
options.mangle = defaults(options.mangle, {
|
options.mangle = defaults(options.mangle, {
|
||||||
cache: options.nameCache && (options.nameCache.vars || {}),
|
cache: options.nameCache && (options.nameCache.vars || {}),
|
||||||
@@ -78,11 +79,16 @@ function minify(files, options) {
|
|||||||
reserved: [],
|
reserved: [],
|
||||||
toplevel: false,
|
toplevel: false,
|
||||||
}, true);
|
}, true);
|
||||||
if (options.nameCache && options.mangle.properties) {
|
if (options.mangle.properties) {
|
||||||
if (typeof options.mangle.properties != "object") {
|
if (typeof options.mangle.properties != "object") {
|
||||||
options.mangle.properties = {};
|
options.mangle.properties = {};
|
||||||
}
|
}
|
||||||
if (!("cache" in options.mangle.properties)) {
|
if (options.mangle.properties.keep_quoted) {
|
||||||
|
quoted_props = options.mangle.properties.reserved;
|
||||||
|
if (!Array.isArray(quoted_props)) quoted_props = [];
|
||||||
|
options.mangle.properties.reserved = quoted_props;
|
||||||
|
}
|
||||||
|
if (options.nameCache && !("cache" in options.mangle.properties)) {
|
||||||
options.mangle.properties.cache = options.nameCache.props || {};
|
options.mangle.properties.cache = options.nameCache.props || {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,6 +131,9 @@ function minify(files, options) {
|
|||||||
}
|
}
|
||||||
toplevel = options.parse.toplevel;
|
toplevel = options.parse.toplevel;
|
||||||
}
|
}
|
||||||
|
if (quoted_props) {
|
||||||
|
reserve_quoted_keys(toplevel, quoted_props);
|
||||||
|
}
|
||||||
if (options.wrap) {
|
if (options.wrap) {
|
||||||
toplevel = toplevel.wrap_commonjs(options.wrap);
|
toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ function OutputStream(options) {
|
|||||||
var current_pos = 0;
|
var current_pos = 0;
|
||||||
var OUTPUT = "";
|
var OUTPUT = "";
|
||||||
|
|
||||||
function to_ascii(str, identifier) {
|
var to_utf8 = options.ascii_only ? function(str, identifier) {
|
||||||
return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
|
return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
|
||||||
var code = ch.charCodeAt(0).toString(16);
|
var code = ch.charCodeAt(0).toString(16);
|
||||||
if (code.length <= 2 && !identifier) {
|
if (code.length <= 2 && !identifier) {
|
||||||
@@ -120,6 +120,12 @@ function OutputStream(options) {
|
|||||||
return "\\u" + code;
|
return "\\u" + code;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} : function(str) {
|
||||||
|
return str.replace(/[\ud800-\udbff](?![\udc00-\udfff])/g, function(ch) {
|
||||||
|
return "\\u" + ch.charCodeAt(0).toString(16);
|
||||||
|
}).replace(/(^|[^\ud800-\udbff])([\udc00-\udfff])/g, function(match, prefix, ch) {
|
||||||
|
return prefix + "\\u" + ch.charCodeAt(0).toString(16);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function make_string(str, quote) {
|
function make_string(str, quote) {
|
||||||
@@ -140,7 +146,7 @@ function OutputStream(options) {
|
|||||||
case "\u2029": return "\\u2029";
|
case "\u2029": return "\\u2029";
|
||||||
case "\ufeff": return "\\ufeff";
|
case "\ufeff": return "\\ufeff";
|
||||||
case "\0":
|
case "\0":
|
||||||
return /[0-7]/.test(str.charAt(i+1)) ? "\\x00" : "\\0";
|
return /[0-9]/.test(str.charAt(i+1)) ? "\\x00" : "\\0";
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
@@ -150,7 +156,7 @@ function OutputStream(options) {
|
|||||||
function quote_double() {
|
function quote_double() {
|
||||||
return '"' + str.replace(/\x22/g, '\\"') + '"';
|
return '"' + str.replace(/\x22/g, '\\"') + '"';
|
||||||
}
|
}
|
||||||
if (options.ascii_only) str = to_ascii(str);
|
str = to_utf8(str);
|
||||||
switch (options.quote_style) {
|
switch (options.quote_style) {
|
||||||
case 1:
|
case 1:
|
||||||
return quote_single();
|
return quote_single();
|
||||||
@@ -175,8 +181,7 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
function make_name(name) {
|
function make_name(name) {
|
||||||
name = name.toString();
|
name = name.toString();
|
||||||
if (options.ascii_only)
|
name = to_utf8(name, true);
|
||||||
name = to_ascii(name, true);
|
|
||||||
return name;
|
return name;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -433,7 +438,7 @@ function OutputStream(options) {
|
|||||||
last : function() { return last },
|
last : function() { return last },
|
||||||
semicolon : semicolon,
|
semicolon : semicolon,
|
||||||
force_semicolon : force_semicolon,
|
force_semicolon : force_semicolon,
|
||||||
to_ascii : to_ascii,
|
to_utf8 : to_utf8,
|
||||||
print_name : function(name) { print(make_name(name)) },
|
print_name : function(name) { print(make_name(name)) },
|
||||||
print_string : function(str, quote, escape_directive) {
|
print_string : function(str, quote, escape_directive) {
|
||||||
var encoded = encode_string(str, quote);
|
var encoded = encode_string(str, quote);
|
||||||
@@ -477,13 +482,17 @@ function OutputStream(options) {
|
|||||||
nodetype.DEFMETHOD("_codegen", generator);
|
nodetype.DEFMETHOD("_codegen", generator);
|
||||||
};
|
};
|
||||||
|
|
||||||
var use_asm = false;
|
|
||||||
var in_directive = false;
|
var in_directive = false;
|
||||||
|
var active_scope = null;
|
||||||
|
var use_asm = null;
|
||||||
|
|
||||||
AST_Node.DEFMETHOD("print", function(stream, force_parens){
|
AST_Node.DEFMETHOD("print", function(stream, force_parens){
|
||||||
var self = this, generator = self._codegen, prev_use_asm = use_asm;
|
var self = this, generator = self._codegen;
|
||||||
if (self instanceof AST_Directive && self.value == "use asm" && stream.parent() instanceof AST_Scope) {
|
if (self instanceof AST_Scope) {
|
||||||
use_asm = true;
|
active_scope = self;
|
||||||
|
}
|
||||||
|
else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") {
|
||||||
|
use_asm = active_scope;
|
||||||
}
|
}
|
||||||
function doit() {
|
function doit() {
|
||||||
self.add_comments(stream);
|
self.add_comments(stream);
|
||||||
@@ -497,8 +506,8 @@ function OutputStream(options) {
|
|||||||
doit();
|
doit();
|
||||||
}
|
}
|
||||||
stream.pop_node();
|
stream.pop_node();
|
||||||
if (self instanceof AST_Scope) {
|
if (self === use_asm) {
|
||||||
use_asm = prev_use_asm;
|
use_asm = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
|
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
|
||||||
@@ -1104,7 +1113,7 @@ function OutputStream(options) {
|
|||||||
self.expression.print(output);
|
self.expression.print(output);
|
||||||
if (self instanceof AST_New && !need_constructor_parens(self, output))
|
if (self instanceof AST_New && !need_constructor_parens(self, output))
|
||||||
return;
|
return;
|
||||||
if (self.expression instanceof AST_Lambda) {
|
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
|
||||||
output.add_mapping(self.start);
|
output.add_mapping(self.start);
|
||||||
}
|
}
|
||||||
output.with_parens(function(){
|
output.with_parens(function(){
|
||||||
@@ -1318,9 +1327,7 @@ function OutputStream(options) {
|
|||||||
if (regexp.raw_source) {
|
if (regexp.raw_source) {
|
||||||
str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
|
str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
|
||||||
}
|
}
|
||||||
if (output.option("ascii_only")) {
|
str = output.to_utf8(str);
|
||||||
str = output.to_ascii(str);
|
|
||||||
}
|
|
||||||
output.print(str);
|
output.print(str);
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
|
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
|
||||||
|
|||||||
@@ -1054,6 +1054,8 @@ function parse($TEXT, options) {
|
|||||||
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
|
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
|
||||||
if (in_statement && !name)
|
if (in_statement && !name)
|
||||||
unexpected();
|
unexpected();
|
||||||
|
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
|
||||||
|
unexpected(prev());
|
||||||
expect("(");
|
expect("(");
|
||||||
var argnames = [];
|
var argnames = [];
|
||||||
for (var first = true; !is("punc", ")");) {
|
for (var first = true; !is("punc", ")");) {
|
||||||
|
|||||||
@@ -67,6 +67,34 @@ function find_builtins(reserved) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function reserve_quoted_keys(ast, reserved) {
|
||||||
|
function add(name) {
|
||||||
|
push_uniq(reserved, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
ast.walk(new TreeWalker(function(node) {
|
||||||
|
if (node instanceof AST_ObjectKeyVal && node.quote) {
|
||||||
|
add(node.key);
|
||||||
|
} else if (node instanceof AST_Sub) {
|
||||||
|
addStrings(node.property, add);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function addStrings(node, add) {
|
||||||
|
node.walk(new TreeWalker(function(node) {
|
||||||
|
if (node instanceof AST_Sequence) {
|
||||||
|
addStrings(node.expressions[node.expressions.length - 1], add);
|
||||||
|
} else if (node instanceof AST_String) {
|
||||||
|
add(node.value);
|
||||||
|
} else if (node instanceof AST_Conditional) {
|
||||||
|
addStrings(node.consequent, add);
|
||||||
|
addStrings(node.alternative, add);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
function mangle_properties(ast, options) {
|
function mangle_properties(ast, options) {
|
||||||
options = defaults(options, {
|
options = defaults(options, {
|
||||||
builtins: false,
|
builtins: false,
|
||||||
@@ -91,7 +119,6 @@ function mangle_properties(ast, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var regex = options.regex;
|
var regex = options.regex;
|
||||||
var keep_quoted = options.keep_quoted;
|
|
||||||
|
|
||||||
// note debug is either false (disabled), or a string of the debug suffix to use (enabled).
|
// note debug is either false (disabled), or a string of the debug suffix to use (enabled).
|
||||||
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
|
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
|
||||||
@@ -104,12 +131,11 @@ function mangle_properties(ast, options) {
|
|||||||
|
|
||||||
var names_to_mangle = [];
|
var names_to_mangle = [];
|
||||||
var unmangleable = [];
|
var unmangleable = [];
|
||||||
var to_keep = {};
|
|
||||||
|
|
||||||
// step 1: find candidates to mangle
|
// step 1: find candidates to mangle
|
||||||
ast.walk(new TreeWalker(function(node){
|
ast.walk(new TreeWalker(function(node){
|
||||||
if (node instanceof AST_ObjectKeyVal) {
|
if (node instanceof AST_ObjectKeyVal) {
|
||||||
add(node.key, keep_quoted && node.quote);
|
add(node.key);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_ObjectProperty) {
|
else if (node instanceof AST_ObjectProperty) {
|
||||||
// setter or getter, since KeyVal is handled above
|
// setter or getter, since KeyVal is handled above
|
||||||
@@ -119,14 +145,13 @@ function mangle_properties(ast, options) {
|
|||||||
add(node.property);
|
add(node.property);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_Sub) {
|
else if (node instanceof AST_Sub) {
|
||||||
addStrings(node.property, keep_quoted);
|
addStrings(node.property, add);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// step 2: transform the tree, renaming properties
|
// step 2: transform the tree, renaming properties
|
||||||
return ast.transform(new TreeTransformer(function(node){
|
return ast.transform(new TreeTransformer(function(node){
|
||||||
if (node instanceof AST_ObjectKeyVal) {
|
if (node instanceof AST_ObjectKeyVal) {
|
||||||
if (!(keep_quoted && node.quote))
|
|
||||||
node.key = mangle(node.key);
|
node.key = mangle(node.key);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_ObjectProperty) {
|
else if (node instanceof AST_ObjectProperty) {
|
||||||
@@ -136,22 +161,9 @@ function mangle_properties(ast, options) {
|
|||||||
else if (node instanceof AST_Dot) {
|
else if (node instanceof AST_Dot) {
|
||||||
node.property = mangle(node.property);
|
node.property = mangle(node.property);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_Sub) {
|
else if (!options.keep_quoted && node instanceof AST_Sub) {
|
||||||
if (!keep_quoted)
|
|
||||||
node.property = mangleStrings(node.property);
|
node.property = mangleStrings(node.property);
|
||||||
}
|
}
|
||||||
// else if (node instanceof AST_String) {
|
|
||||||
// if (should_mangle(node.value)) {
|
|
||||||
// AST_Node.warn(
|
|
||||||
// "Found \"{prop}\" property candidate for mangling in an arbitrary string [{file}:{line},{col}]", {
|
|
||||||
// file : node.start.file,
|
|
||||||
// line : node.start.line,
|
|
||||||
// col : node.start.col,
|
|
||||||
// prop : node.value
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// only function declarations after this line
|
// only function declarations after this line
|
||||||
@@ -167,19 +179,13 @@ function mangle_properties(ast, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function should_mangle(name) {
|
function should_mangle(name) {
|
||||||
if (keep_quoted && name in to_keep) return false;
|
|
||||||
if (regex && !regex.test(name)) return false;
|
if (regex && !regex.test(name)) return false;
|
||||||
if (reserved.indexOf(name) >= 0) return false;
|
if (reserved.indexOf(name) >= 0) return false;
|
||||||
return cache.props.has(name)
|
return cache.props.has(name)
|
||||||
|| names_to_mangle.indexOf(name) >= 0;
|
|| names_to_mangle.indexOf(name) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function add(name, keep) {
|
function add(name) {
|
||||||
if (keep) {
|
|
||||||
to_keep[name] = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (can_mangle(name))
|
if (can_mangle(name))
|
||||||
push_uniq(names_to_mangle, name);
|
push_uniq(names_to_mangle, name);
|
||||||
|
|
||||||
@@ -199,19 +205,16 @@ function mangle_properties(ast, options) {
|
|||||||
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
|
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
|
||||||
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
|
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
|
||||||
|
|
||||||
if (can_mangle(debug_mangled) && !(keep_quoted && debug_mangled in to_keep)) {
|
if (can_mangle(debug_mangled)) {
|
||||||
mangled = debug_mangled;
|
mangled = debug_mangled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// either debug mode is off, or it is on and we could not use the mangled name
|
// either debug mode is off, or it is on and we could not use the mangled name
|
||||||
if (!mangled) {
|
if (!mangled) {
|
||||||
// Note: `can_mangle()` does not check if the name collides with the `to_keep` set
|
|
||||||
// (filled with quoted properties when `keep_quoted` is set). Make sure we add this
|
|
||||||
// check so we don't collide with a quoted name.
|
|
||||||
do {
|
do {
|
||||||
mangled = base54(++cache.cname);
|
mangled = base54(++cache.cname);
|
||||||
} while (!can_mangle(mangled) || keep_quoted && mangled in to_keep);
|
} while (!can_mangle(mangled));
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.props.set(name, mangled);
|
cache.props.set(name, mangled);
|
||||||
@@ -219,32 +222,6 @@ function mangle_properties(ast, options) {
|
|||||||
return mangled;
|
return mangled;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addStrings(node, keep) {
|
|
||||||
var out = {};
|
|
||||||
try {
|
|
||||||
(function walk(node){
|
|
||||||
node.walk(new TreeWalker(function(node){
|
|
||||||
if (node instanceof AST_Sequence) {
|
|
||||||
walk(node.expressions[node.expressions.length - 1]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node instanceof AST_String) {
|
|
||||||
add(node.value, keep);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node instanceof AST_Conditional) {
|
|
||||||
walk(node.consequent);
|
|
||||||
walk(node.alternative);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
throw out;
|
|
||||||
}));
|
|
||||||
})(node);
|
|
||||||
} catch(ex) {
|
|
||||||
if (ex !== out) throw ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function mangleStrings(node) {
|
function mangleStrings(node) {
|
||||||
return node.transform(new TreeTransformer(function(node){
|
return node.transform(new TreeTransformer(function(node){
|
||||||
if (node instanceof AST_Sequence) {
|
if (node instanceof AST_Sequence) {
|
||||||
|
|||||||
@@ -235,6 +235,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
ref.reference(options);
|
ref.reference(options);
|
||||||
});
|
});
|
||||||
node.thedef = def;
|
node.thedef = def;
|
||||||
|
node.reference(options);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|||||||
12
package.json
12
package.json
@@ -4,7 +4,7 @@
|
|||||||
"homepage": "http://lisperator.net/uglifyjs",
|
"homepage": "http://lisperator.net/uglifyjs",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.0.25",
|
"version": "3.1.4",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
@@ -29,13 +29,13 @@
|
|||||||
"LICENSE"
|
"LICENSE"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"commander": "~2.9.0",
|
"commander": "~2.11.0",
|
||||||
"source-map": "~0.5.1"
|
"source-map": "~0.6.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"acorn": "~5.0.3",
|
"acorn": "~5.1.1",
|
||||||
"mocha": "~2.3.4",
|
"mocha": "~3.5.1",
|
||||||
"semver": "~5.3.0"
|
"semver": "~5.4.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node test/run-tests.js"
|
"test": "node test/run-tests.js"
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ ascii_only_true: {
|
|||||||
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\08\\0"+"\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\v\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}'
|
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\0"+"\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\v\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}'
|
||||||
}
|
}
|
||||||
|
|
||||||
ascii_only_false: {
|
ascii_only_false: {
|
||||||
@@ -31,5 +31,5 @@ ascii_only_false: {
|
|||||||
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\08\\0"+"\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
|
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\0"+"\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;'
|
||||||
|
}
|
||||||
|
|||||||
@@ -1268,22 +1268,21 @@ collapse_vars_short_circuited_conditions: {
|
|||||||
|
|
||||||
collapse_vars_regexp: {
|
collapse_vars_regexp: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
|
||||||
loops: false,
|
|
||||||
sequences: true,
|
|
||||||
dead_code: true,
|
|
||||||
conditionals: true,
|
|
||||||
comparisons: true,
|
|
||||||
evaluate: true,
|
|
||||||
booleans: true,
|
booleans: true,
|
||||||
unused: true,
|
cascade: true,
|
||||||
hoist_funs: true,
|
collapse_vars: true,
|
||||||
keep_fargs: true,
|
comparisons: true,
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
cascade: true,
|
hoist_funs: true,
|
||||||
side_effects: true,
|
keep_fargs: true,
|
||||||
|
loops: false,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f1() {
|
function f1() {
|
||||||
@@ -1292,7 +1291,7 @@ collapse_vars_regexp: {
|
|||||||
return [rx, k];
|
return [rx, k];
|
||||||
}
|
}
|
||||||
function f2() {
|
function f2() {
|
||||||
var rx = /[abc123]+/;
|
var rx = /ab*/g;
|
||||||
return function(s) {
|
return function(s) {
|
||||||
return rx.exec(s);
|
return rx.exec(s);
|
||||||
};
|
};
|
||||||
@@ -1305,13 +1304,21 @@ collapse_vars_regexp: {
|
|||||||
console.log(result[0]);
|
console.log(result[0]);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
(function() {
|
||||||
|
var result;
|
||||||
|
var s = 'acdabcdeabbb';
|
||||||
|
var rx = f2();
|
||||||
|
while (result = rx(s)) {
|
||||||
|
console.log(result[0]);
|
||||||
|
}
|
||||||
|
})();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f1() {
|
function f1() {
|
||||||
return [/[A-Z]+/, 9];
|
return [/[A-Z]+/, 9];
|
||||||
}
|
}
|
||||||
function f2() {
|
function f2() {
|
||||||
var rx = /[abc123]+/;
|
var rx = /ab*/g;
|
||||||
return function(s) {
|
return function(s) {
|
||||||
return rx.exec(s);
|
return rx.exec(s);
|
||||||
};
|
};
|
||||||
@@ -1321,6 +1328,11 @@ collapse_vars_regexp: {
|
|||||||
while (result = rx.exec("acdabcdeabbb"))
|
while (result = rx.exec("acdabcdeabbb"))
|
||||||
console.log(result[0]);
|
console.log(result[0]);
|
||||||
})();
|
})();
|
||||||
|
(function() {
|
||||||
|
var result, rx = f2();
|
||||||
|
while (result = rx("acdabcdeabbb"))
|
||||||
|
console.log(result[0]);
|
||||||
|
})();
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
@@ -1834,9 +1846,9 @@ issue_1858: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function(x) {
|
console.log(function(x) {
|
||||||
var a = {}, b = a.b = x;
|
var a = {}, b = a.b = 1;
|
||||||
return a.b + b;
|
return a.b + b;
|
||||||
}(1));
|
}());
|
||||||
}
|
}
|
||||||
expect_stdout: "2"
|
expect_stdout: "2"
|
||||||
}
|
}
|
||||||
@@ -2342,3 +2354,249 @@ duplicate_argname: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2298: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function() {
|
||||||
|
function f() {
|
||||||
|
var a = undefined;
|
||||||
|
var undefined = a++;
|
||||||
|
try {
|
||||||
|
!function g(b) {
|
||||||
|
b[1] = "foo";
|
||||||
|
}();
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
(function() {
|
||||||
|
var a = undefined;
|
||||||
|
var undefined = a++;
|
||||||
|
try {
|
||||||
|
!function(b) {
|
||||||
|
(void 0)[1] = "foo";
|
||||||
|
}();
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2313_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: 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() {
|
||||||
|
a++;
|
||||||
|
return 42;
|
||||||
|
},
|
||||||
|
set c(c) {
|
||||||
|
b++;
|
||||||
|
},
|
||||||
|
d: function() {
|
||||||
|
this.c++;
|
||||||
|
this.c && console.log(a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foo.d();
|
||||||
|
}
|
||||||
|
expect_stdout: "2 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2313_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
!function a() {
|
||||||
|
a && c++;
|
||||||
|
var a = 0;
|
||||||
|
a && c++;
|
||||||
|
}();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
!function a() {
|
||||||
|
a && c++;
|
||||||
|
var a = 0;
|
||||||
|
a && c++;
|
||||||
|
}();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2319_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
return a;
|
||||||
|
}(!function() {
|
||||||
|
return this;
|
||||||
|
}()));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
return !function() {
|
||||||
|
return this;
|
||||||
|
}();
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2319_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
"use strict";
|
||||||
|
return a;
|
||||||
|
}(!function() {
|
||||||
|
return this;
|
||||||
|
}()));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
"use strict";
|
||||||
|
return a;
|
||||||
|
}(!function() {
|
||||||
|
return this;
|
||||||
|
}()));
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2319_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
console.log(function(a) {
|
||||||
|
return a;
|
||||||
|
}(!function() {
|
||||||
|
return this;
|
||||||
|
}()));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
console.log(function(a) {
|
||||||
|
return !function() {
|
||||||
|
return this;
|
||||||
|
}();
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
prop_side_effects_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: 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);
|
||||||
|
console.log({
|
||||||
|
bar: function() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}.bar());
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
prop_side_effects_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: 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);
|
||||||
|
console.log(2);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ concat_1: {
|
|||||||
var c = 1 + x() + 2 + "boo";
|
var c = 1 + x() + 2 + "boo";
|
||||||
var d = 1 + x() + 2 + 3 + "boo";
|
var d = 1 + x() + 2 + 3 + "boo";
|
||||||
var e = 1 + x() + 2 + "X3boo";
|
var e = 1 + x() + 2 + "X3boo";
|
||||||
var f = "\x00360\08\0";
|
var f = "\x00360\x008\0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -241,18 +241,54 @@ issue_2233_1: {
|
|||||||
Array.isArray;
|
Array.isArray;
|
||||||
Boolean;
|
Boolean;
|
||||||
console.log;
|
console.log;
|
||||||
|
Date;
|
||||||
|
decodeURI;
|
||||||
|
decodeURIComponent;
|
||||||
|
encodeURI;
|
||||||
|
encodeURIComponent;
|
||||||
Error.name;
|
Error.name;
|
||||||
|
escape;
|
||||||
|
eval;
|
||||||
|
EvalError;
|
||||||
Function.length;
|
Function.length;
|
||||||
|
isFinite;
|
||||||
|
isNaN;
|
||||||
|
JSON;
|
||||||
Math.random;
|
Math.random;
|
||||||
Number.isNaN;
|
Number.isNaN;
|
||||||
|
parseFloat;
|
||||||
|
parseInt;
|
||||||
RegExp;
|
RegExp;
|
||||||
Object.defineProperty;
|
Object.defineProperty;
|
||||||
String.fromCharCode;
|
String.fromCharCode;
|
||||||
|
RangeError;
|
||||||
|
ReferenceError;
|
||||||
|
SyntaxError;
|
||||||
|
TypeError;
|
||||||
|
unescape;
|
||||||
|
URIError;
|
||||||
}
|
}
|
||||||
expect: {}
|
expect: {}
|
||||||
expect_stdout: true
|
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: {
|
issue_2233_2: {
|
||||||
options = {
|
options = {
|
||||||
pure_getters: "strict",
|
pure_getters: "strict",
|
||||||
@@ -309,3 +345,71 @@ issue_2233_3: {
|
|||||||
UndeclaredGlobal;
|
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",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -751,12 +751,12 @@ issue_1583: {
|
|||||||
expect: {
|
expect: {
|
||||||
function m(t) {
|
function m(t) {
|
||||||
(function(e) {
|
(function(e) {
|
||||||
t = e();
|
t = function() {
|
||||||
})(function() {
|
|
||||||
return (function(a) {
|
return (function(a) {
|
||||||
return a;
|
return function(a) {};
|
||||||
})(function(a) {});
|
})();
|
||||||
});
|
}();
|
||||||
|
})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1239,3 +1239,25 @@ issue_2226_3: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "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++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1021,6 +1021,7 @@ issue_1964_1: {
|
|||||||
input: {
|
input: {
|
||||||
function f() {
|
function f() {
|
||||||
var long_variable_name = /\s/;
|
var long_variable_name = /\s/;
|
||||||
|
console.log(long_variable_name.source);
|
||||||
return "a b c".split(long_variable_name)[1];
|
return "a b c".split(long_variable_name)[1];
|
||||||
}
|
}
|
||||||
console.log(f());
|
console.log(f());
|
||||||
@@ -1028,11 +1029,15 @@ issue_1964_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
function f() {
|
function f() {
|
||||||
var long_variable_name = /\s/;
|
var long_variable_name = /\s/;
|
||||||
|
console.log(long_variable_name.source);
|
||||||
return "a b c".split(long_variable_name)[1];
|
return "a b c".split(long_variable_name)[1];
|
||||||
}
|
}
|
||||||
console.log(f());
|
console.log(f());
|
||||||
}
|
}
|
||||||
expect_stdout: "b"
|
expect_stdout: [
|
||||||
|
"\\s",
|
||||||
|
"b",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1964_2: {
|
issue_1964_2: {
|
||||||
@@ -1045,17 +1050,22 @@ issue_1964_2: {
|
|||||||
input: {
|
input: {
|
||||||
function f() {
|
function f() {
|
||||||
var long_variable_name = /\s/;
|
var long_variable_name = /\s/;
|
||||||
|
console.log(long_variable_name.source);
|
||||||
return "a b c".split(long_variable_name)[1];
|
return "a b c".split(long_variable_name)[1];
|
||||||
}
|
}
|
||||||
console.log(f());
|
console.log(f());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f() {
|
function f() {
|
||||||
|
console.log(/\s/.source);
|
||||||
return "a b c".split(/\s/)[1];
|
return "a b c".split(/\s/)[1];
|
||||||
}
|
}
|
||||||
console.log(f());
|
console.log(f());
|
||||||
}
|
}
|
||||||
expect_stdout: "b"
|
expect_stdout: [
|
||||||
|
"\\s",
|
||||||
|
"b",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
array_slice_index: {
|
array_slice_index: {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
// comment #__PURE__ comment
|
||||||
bar(), baz(), quux();
|
bar(), baz(), quux();
|
||||||
a.b(), /* @__PURE__ */ c.d.e(), f.g();
|
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 __PURE__ call [test/compress/issue-1261.js:92,37]",
|
||||||
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:92,16]",
|
"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 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:107,8]",
|
||||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:101,31]",
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:108,31]",
|
||||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:84,33]",
|
"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 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();
|
baz();
|
||||||
}
|
}
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,61]",
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,61]",
|
||||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,23]",
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,23]",
|
||||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:128,23]",
|
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:137,23]",
|
||||||
"WARN: Boolean || always true [test/compress/issue-1261.js:129,23]",
|
"WARN: Boolean || always true [test/compress/issue-1261.js:138,23]",
|
||||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:129,23]",
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:138,23]",
|
||||||
"WARN: Condition always true [test/compress/issue-1261.js:129,23]",
|
"WARN: Condition always true [test/compress/issue-1261.js:138,23]",
|
||||||
"WARN: Condition left of || always true [test/compress/issue-1261.js:130,8]",
|
"WARN: Condition left of || always true [test/compress/issue-1261.js:139,8]",
|
||||||
"WARN: Condition always true [test/compress/issue-1261.js:130,8]",
|
"WARN: Condition always true [test/compress/issue-1261.js:139,8]",
|
||||||
"WARN: Boolean && always false [test/compress/issue-1261.js:131,23]",
|
"WARN: Boolean && always false [test/compress/issue-1261.js:140,23]",
|
||||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:131,23]",
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:140,23]",
|
||||||
"WARN: Condition always false [test/compress/issue-1261.js:131,23]",
|
"WARN: Condition always false [test/compress/issue-1261.js:140,23]",
|
||||||
"WARN: Condition left of && always false [test/compress/issue-1261.js:132,8]",
|
"WARN: Condition left of && always false [test/compress/issue-1261.js:141,8]",
|
||||||
"WARN: Condition always false [test/compress/issue-1261.js:132,8]",
|
"WARN: Condition always false [test/compress/issue-1261.js:141,8]",
|
||||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:133,23]",
|
"WARN: + in boolean context always true [test/compress/issue-1261.js:142,23]",
|
||||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:133,23]",
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:142,23]",
|
||||||
"WARN: Condition always true [test/compress/issue-1261.js:133,23]",
|
"WARN: Condition always true [test/compress/issue-1261.js:142,23]",
|
||||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:134,8]",
|
"WARN: + in boolean context always true [test/compress/issue-1261.js:143,8]",
|
||||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:134,31]",
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:143,31]",
|
||||||
"WARN: Condition always true [test/compress/issue-1261.js:134,8]",
|
"WARN: Condition always true [test/compress/issue-1261.js:143,8]",
|
||||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,23]",
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:144,23]",
|
||||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:136,24]",
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:145,24]",
|
||||||
"WARN: Condition always true [test/compress/issue-1261.js:136,8]",
|
"WARN: Condition always true [test/compress/issue-1261.js:145,8]",
|
||||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,31]",
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:146,31]",
|
||||||
"WARN: Condition always false [test/compress/issue-1261.js:137,8]",
|
"WARN: Condition always false [test/compress/issue-1261.js:146,8]",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
issue_1321_no_debug: {
|
issue_1321_no_debug: {
|
||||||
mangle_props = {
|
mangle = {
|
||||||
keep_quoted: true
|
properties: {
|
||||||
|
keep_quoted: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = {};
|
var x = {};
|
||||||
@@ -10,17 +12,19 @@ issue_1321_no_debug: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x = {};
|
var x = {};
|
||||||
x.o = 1;
|
x.x = 1;
|
||||||
x["a"] = 2 * x.o;
|
x["a"] = 2 * x.x;
|
||||||
console.log(x.o, x["a"]);
|
console.log(x.x, x["a"]);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1321_debug: {
|
issue_1321_debug: {
|
||||||
mangle_props = {
|
mangle = {
|
||||||
|
properties: {
|
||||||
|
debug: "",
|
||||||
keep_quoted: true,
|
keep_quoted: true,
|
||||||
debug: ""
|
},
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = {};
|
var x = {};
|
||||||
@@ -30,16 +34,18 @@ issue_1321_debug: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x = {};
|
var x = {};
|
||||||
x.o = 1;
|
x.x = 1;
|
||||||
x["_$foo$_"] = 2 * x.o;
|
x["_$foo$_"] = 2 * x.x;
|
||||||
console.log(x.o, x["_$foo$_"]);
|
console.log(x.x, x["_$foo$_"]);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1321_with_quoted: {
|
issue_1321_with_quoted: {
|
||||||
mangle_props = {
|
mangle = {
|
||||||
keep_quoted: false
|
properties: {
|
||||||
|
keep_quoted: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = {};
|
var x = {};
|
||||||
@@ -49,9 +55,9 @@ issue_1321_with_quoted: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x = {};
|
var x = {};
|
||||||
x.o = 1;
|
x.x = 1;
|
||||||
x["x"] = 2 * x.o;
|
x["o"] = 2 * x.x;
|
||||||
console.log(x.o, x["x"]);
|
console.log(x.x, x["o"]);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
mangle_props: {
|
mangle_props: {
|
||||||
mangle_props = {}
|
mangle = {
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
var obj = {
|
var obj = {
|
||||||
undefined: 1,
|
undefined: 1,
|
||||||
@@ -54,10 +56,12 @@ mangle_props: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
numeric_literal: {
|
numeric_literal: {
|
||||||
|
mangle = {
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
beautify = {
|
beautify = {
|
||||||
beautify: true,
|
beautify: true,
|
||||||
}
|
}
|
||||||
mangle_props = {}
|
|
||||||
input: {
|
input: {
|
||||||
var obj = {
|
var obj = {
|
||||||
0: 0,
|
0: 0,
|
||||||
@@ -105,7 +109,9 @@ numeric_literal: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
identifier: {
|
identifier: {
|
||||||
mangle_props = {}
|
mangle = {
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
var obj = {
|
var obj = {
|
||||||
abstract: 1,
|
abstract: 1,
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
dont_reuse_prop: {
|
dont_reuse_prop: {
|
||||||
mangle_props = {
|
mangle = {
|
||||||
regex: /asd/
|
properties: {
|
||||||
|
regex: /asd/,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
"aaaaaaaaaabbbbb";
|
"aaaaaaaaaabbbbb";
|
||||||
@@ -20,8 +22,10 @@ dont_reuse_prop: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unmangleable_props_should_always_be_reserved: {
|
unmangleable_props_should_always_be_reserved: {
|
||||||
mangle_props = {
|
mangle = {
|
||||||
regex: /asd/
|
properties: {
|
||||||
|
regex: /asd/,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
"aaaaaaaaaabbbbb";
|
"aaaaaaaaaabbbbb";
|
||||||
|
|||||||
@@ -128,9 +128,11 @@ evaluate_string_length: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mangle_properties: {
|
mangle_properties: {
|
||||||
mangle_props = {
|
mangle = {
|
||||||
keep_quoted: false
|
properties: {
|
||||||
};
|
keep_quoted: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
a["foo"] = "bar";
|
a["foo"] = "bar";
|
||||||
a.color = "red";
|
a.color = "red";
|
||||||
@@ -139,11 +141,11 @@ mangle_properties: {
|
|||||||
a['run']({color: "blue", foo: "baz"});
|
a['run']({color: "blue", foo: "baz"});
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
a["o"] = "bar";
|
a["a"] = "bar";
|
||||||
a.a = "red";
|
a.b = "red";
|
||||||
x = {r: 10};
|
x = {o: 10};
|
||||||
a.b(x.r, a.o);
|
a.r(x.o, a.a);
|
||||||
a['b']({a: "blue", o: "baz"});
|
a['r']({b: "blue", a: "baz"});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,8 +153,10 @@ mangle_unquoted_properties: {
|
|||||||
options = {
|
options = {
|
||||||
properties: false
|
properties: false
|
||||||
}
|
}
|
||||||
mangle_props = {
|
mangle = {
|
||||||
keep_quoted: true
|
properties: {
|
||||||
|
keep_quoted: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
beautify = {
|
beautify = {
|
||||||
beautify: false,
|
beautify: false,
|
||||||
@@ -181,24 +185,26 @@ mangle_unquoted_properties: {
|
|||||||
function f1() {
|
function f1() {
|
||||||
a["foo"] = "bar";
|
a["foo"] = "bar";
|
||||||
a.color = "red";
|
a.color = "red";
|
||||||
a.o = 2;
|
a.r = 2;
|
||||||
x = {"bar": 10, f: 7};
|
x = {"bar": 10, b: 7};
|
||||||
a.f = 9;
|
a.b = 9;
|
||||||
}
|
}
|
||||||
function f2() {
|
function f2() {
|
||||||
a.foo = "bar";
|
a.foo = "bar";
|
||||||
a['color'] = "red";
|
a['color'] = "red";
|
||||||
x = {bar: 10, f: 7};
|
x = {bar: 10, b: 7};
|
||||||
a.f = 9;
|
a.b = 9;
|
||||||
a.o = 3;
|
a.r = 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_debug: {
|
mangle_debug: {
|
||||||
mangle_props = {
|
mangle = {
|
||||||
debug: ""
|
properties: {
|
||||||
};
|
debug: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
a.foo = "bar";
|
a.foo = "bar";
|
||||||
x = { baz: "ban" };
|
x = { baz: "ban" };
|
||||||
@@ -210,9 +216,11 @@ mangle_debug: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mangle_debug_true: {
|
mangle_debug_true: {
|
||||||
mangle_props = {
|
mangle = {
|
||||||
debug: true
|
properties: {
|
||||||
};
|
debug: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
a.foo = "bar";
|
a.foo = "bar";
|
||||||
x = { baz: "ban" };
|
x = { baz: "ban" };
|
||||||
@@ -224,9 +232,11 @@ mangle_debug_true: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mangle_debug_suffix: {
|
mangle_debug_suffix: {
|
||||||
mangle_props = {
|
mangle = {
|
||||||
debug: "XYZ"
|
properties: {
|
||||||
};
|
debug: "XYZ",
|
||||||
|
},
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
a.foo = "bar";
|
a.foo = "bar";
|
||||||
x = { baz: "ban" };
|
x = { baz: "ban" };
|
||||||
@@ -241,10 +251,12 @@ mangle_debug_suffix_keep_quoted: {
|
|||||||
options = {
|
options = {
|
||||||
properties: false
|
properties: false
|
||||||
}
|
}
|
||||||
mangle_props = {
|
mangle = {
|
||||||
keep_quoted: true,
|
properties: {
|
||||||
debug: "XYZ",
|
debug: "XYZ",
|
||||||
reserved: []
|
keep_quoted: true,
|
||||||
|
reserved: [],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
beautify = {
|
beautify = {
|
||||||
beautify: false,
|
beautify: false,
|
||||||
@@ -774,3 +786,21 @@ issue_2208_5: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2256: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
properties: {
|
||||||
|
keep_quoted: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({ "keep": 1 });
|
||||||
|
g.keep = g.change;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
g.keep = g.g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -385,3 +385,217 @@ set_mutable_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ unsafe_evaluate: {
|
|||||||
options = {
|
options = {
|
||||||
evaluate : true,
|
evaluate : true,
|
||||||
reduce_vars : true,
|
reduce_vars : true,
|
||||||
|
side_effects : true,
|
||||||
unsafe : true,
|
unsafe : true,
|
||||||
unused : true
|
unused : true
|
||||||
}
|
}
|
||||||
@@ -1898,10 +1899,7 @@ redefine_farg_3: {
|
|||||||
console.log(f([]), g([]), h([]));
|
console.log(f([]), g([]), h([]));
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function(a) {
|
console.log(typeof [], "number", "undefined");
|
||||||
var a;
|
|
||||||
return typeof a;
|
|
||||||
}([]), "number", "undefined");
|
|
||||||
}
|
}
|
||||||
expect_stdout: "object number undefined"
|
expect_stdout: "object number undefined"
|
||||||
}
|
}
|
||||||
@@ -2549,7 +2547,7 @@ issue_1922_2: {
|
|||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
accessor: {
|
accessor_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
@@ -2578,6 +2576,33 @@ accessor: {
|
|||||||
expect_stdout: "1 1"
|
expect_stdout: "1 1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
accessor_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var A = 1;
|
||||||
|
var B = {
|
||||||
|
get c() {
|
||||||
|
console.log(A);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
B.c;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
({
|
||||||
|
get c() {
|
||||||
|
console.log(1);
|
||||||
|
}
|
||||||
|
}).c;
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
for_in_prop: {
|
for_in_prop: {
|
||||||
options = {
|
options = {
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
@@ -2602,3 +2627,270 @@ for_in_prop: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obj_var_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var C = 1;
|
||||||
|
var obj = {
|
||||||
|
bar: function() {
|
||||||
|
return C + C;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log(obj.bar());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log({
|
||||||
|
bar: function() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}.bar());
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
obj_var_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var C = 1;
|
||||||
|
var obj = {
|
||||||
|
bar: function() {
|
||||||
|
return C + C;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log(obj.bar());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(2);
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
obj_arg_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var C = 1;
|
||||||
|
function f(obj) {
|
||||||
|
return obj.bar();
|
||||||
|
}
|
||||||
|
console.log(f({
|
||||||
|
bar: function() {
|
||||||
|
return C + C;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log({
|
||||||
|
bar: function() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}.bar());
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
obj_arg_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var C = 1;
|
||||||
|
function f(obj) {
|
||||||
|
return obj.bar();
|
||||||
|
}
|
||||||
|
console.log(f({
|
||||||
|
bar: function() {
|
||||||
|
return C + C;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(2);
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
func_arg_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 42;
|
||||||
|
!function(a) {
|
||||||
|
console.log(a());
|
||||||
|
}(function() {
|
||||||
|
return a;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(42);
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
func_arg_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 42;
|
||||||
|
!function(a) {
|
||||||
|
console.log(a());
|
||||||
|
}(function(a) {
|
||||||
|
return a;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(void 0);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
regex_loop: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x) {
|
||||||
|
for (var r, s = "acdabcdeabbb"; r = x().exec(s);)
|
||||||
|
console.log(r[0]);
|
||||||
|
}
|
||||||
|
var a = /ab*/g;
|
||||||
|
f(function() {
|
||||||
|
return a;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = /ab*/g;
|
||||||
|
(function(x) {
|
||||||
|
for (var r, s = "acdabcdeabbb"; r = x().exec(s);)
|
||||||
|
console.log(r[0]);
|
||||||
|
})(function() {
|
||||||
|
return a;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
obj_for_1: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = { a: 1 };
|
||||||
|
for (var i = o.a--; i; i--)
|
||||||
|
console.log(i);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var i = { a: 1 }.a--; i; i--)
|
||||||
|
console.log(i);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
obj_for_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = { a: 1 };
|
||||||
|
for (var i; i = o.a--;)
|
||||||
|
console.log(i);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = { a: 1 };
|
||||||
|
for (var i; i = o.a--;)
|
||||||
|
console.log(i);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
array_forin_1: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = [ 1, 2, 3 ];
|
||||||
|
for (var b in a)
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var b in [ 1, 2, 3 ])
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
array_forin_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = [];
|
||||||
|
for (var b in [ 1, 2, 3 ])
|
||||||
|
a.push(b);
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = [];
|
||||||
|
for (var b in [ 1, 2, 3 ])
|
||||||
|
a.push(b);
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
expect_stdout: "3"
|
||||||
|
}
|
||||||
|
|||||||
@@ -325,3 +325,69 @@ issue_2120_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2254_1: {
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"eeeeee";
|
||||||
|
try {
|
||||||
|
console.log(f("PASS"));
|
||||||
|
} catch (e) {}
|
||||||
|
function f(s) {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (e) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"eeeeee";
|
||||||
|
try {
|
||||||
|
console.log(f("PASS"));
|
||||||
|
} catch (e) {}
|
||||||
|
function f(e) {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (t) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2254_2: {
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"eeeeee";
|
||||||
|
try {
|
||||||
|
console.log(f("PASS"));
|
||||||
|
} catch (e) {}
|
||||||
|
function f(s) {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (e) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"eeeeee";
|
||||||
|
try {
|
||||||
|
console.log(f("PASS"));
|
||||||
|
} catch (e) {}
|
||||||
|
function f(t) {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (e) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -739,3 +739,44 @@ issue_2062: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
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"
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,3 +15,43 @@ unicode_parse_variables: {
|
|||||||
var l০ = 3;
|
var l০ = 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2242_1: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||||
|
}
|
||||||
|
expect_exact: 'console.log("\\ud83d","\\ude00","\ud83d\ude00","\\ud83d@\\ude00");'
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2242_2: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||||
|
}
|
||||||
|
expect_exact: 'console.log("\\ud83d","\\ude00","\\ud83d\\ude00","\\ud83d@\\ude00");'
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2242_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||||
|
}
|
||||||
|
expect_exact: 'console.log("\\ud83d"+"\\ude00","\\ud83d"+"@"+"\\ude00");'
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2242_4: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||||
|
}
|
||||||
|
expect_exact: 'console.log("\ud83d\ude00","\\ud83d@\\ude00");'
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ exports["defaults"] = defaults;
|
|||||||
exports["mangle_properties"] = mangle_properties;
|
exports["mangle_properties"] = mangle_properties;
|
||||||
exports["minify"] = minify;
|
exports["minify"] = minify;
|
||||||
exports["parse"] = parse;
|
exports["parse"] = parse;
|
||||||
|
exports["reserve_quoted_keys"] = reserve_quoted_keys;
|
||||||
exports["string_template"] = string_template;
|
exports["string_template"] = string_template;
|
||||||
exports["tokenizer"] = tokenizer;
|
exports["tokenizer"] = tokenizer;
|
||||||
exports["is_identifier"] = is_identifier;
|
exports["is_identifier"] = is_identifier;
|
||||||
|
|||||||
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, '\\"');
|
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) {
|
it("Should dump AST as JSON", function(done) {
|
||||||
var command = uglifyjscmd + " test/input/global_defs/simple.js -mco ast";
|
var command = uglifyjscmd + " test/input/global_defs/simple.js -mco ast";
|
||||||
exec(command, function (err, stdout) {
|
exec(command, function (err, stdout) {
|
||||||
|
|||||||
@@ -73,6 +73,12 @@ describe("minify", function() {
|
|||||||
assert.strictEqual(run_code(compressed), run_code(original));
|
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() {
|
describe("keep_quoted_props", function() {
|
||||||
it("Should preserve quotes in object literals", function() {
|
it("Should preserve quotes in object literals", function() {
|
||||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||||
@@ -124,6 +130,17 @@ describe("minify", function() {
|
|||||||
assert.strictEqual(result.code,
|
assert.strictEqual(result.code,
|
||||||
'a["foo"]="bar",a.a="red",x={"bar":10};');
|
'a["foo"]="bar",a.a="red",x={"bar":10};');
|
||||||
});
|
});
|
||||||
|
it("Should not mangle quoted property within dead code", function() {
|
||||||
|
var result = Uglify.minify('({ "keep": 1 }); g.keep = g.change;', {
|
||||||
|
mangle: {
|
||||||
|
properties: {
|
||||||
|
keep_quoted: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, "g.keep=g.g;");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("inSourceMap", function() {
|
describe("inSourceMap", function() {
|
||||||
|
|||||||
@@ -61,9 +61,9 @@ describe("String literals", function() {
|
|||||||
var tests = [
|
var tests = [
|
||||||
['"\\76";', ';">";'],
|
['"\\76";', ';">";'],
|
||||||
['"\\0"', '"\\0";'],
|
['"\\0"', '"\\0";'],
|
||||||
['"\\08"', '"\\08";'],
|
['"\\08"', '"\\x008";'],
|
||||||
['"\\008"', '"\\08";'],
|
['"\\008"', '"\\x008";'],
|
||||||
['"\\0008"', '"\\08";'],
|
['"\\0008"', '"\\x008";'],
|
||||||
['"use strict" === "use strict";\n"\\76";', '"use strict"==="use strict";">";'],
|
['"use strict" === "use strict";\n"\\76";', '"use strict"==="use strict";">";'],
|
||||||
['"use\\\n strict";\n"\\07";', ';"use strict";"\07";']
|
['"use\\\n strict";\n"\\07";', ';"use strict";"\07";']
|
||||||
];
|
];
|
||||||
@@ -75,7 +75,44 @@ describe("String literals", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Should not throw error when digit is 8 or 9", function() {
|
it("Should not throw error when digit is 8 or 9", function() {
|
||||||
assert.equal(UglifyJS.parse('"use strict";"\\08"').print_to_string(), '"use strict";"\\08";');
|
assert.equal(UglifyJS.parse('"use strict";"\\08"').print_to_string(), '"use strict";"\\x008";');
|
||||||
assert.equal(UglifyJS.parse('"use strict";"\\09"').print_to_string(), '"use strict";"\\09";');
|
assert.equal(UglifyJS.parse('"use strict";"\\09"').print_to_string(), '"use strict";"\\x009";');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should not unescape unpaired surrogates", function() {
|
||||||
|
var code = [];
|
||||||
|
for (var i = 0; i <= 0xF; i++) {
|
||||||
|
code.push("\\u000" + i.toString(16));
|
||||||
|
}
|
||||||
|
for (;i <= 0xFF; i++) {
|
||||||
|
code.push("\\u00" + i.toString(16));
|
||||||
|
}
|
||||||
|
for (;i <= 0xFFF; i++) {
|
||||||
|
code.push("\\u0" + i.toString(16));
|
||||||
|
}
|
||||||
|
for (; i <= 0xFFFF; i++) {
|
||||||
|
code.push("\\u" + i.toString(16));
|
||||||
|
}
|
||||||
|
code = '"' + code.join() + '"';
|
||||||
|
var normal = UglifyJS.minify(code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
ascii_only: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (normal.error) throw normal.error;
|
||||||
|
assert.ok(code.length > normal.code.length);
|
||||||
|
assert.strictEqual(eval(code), eval(normal.code));
|
||||||
|
var ascii = UglifyJS.minify(code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
ascii_only: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (ascii.error) throw ascii.error;
|
||||||
|
assert.ok(code.length > ascii.code.length);
|
||||||
|
assert.strictEqual(eval(code), eval(ascii.code));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -111,18 +111,22 @@ function run_compress_tests() {
|
|||||||
};
|
};
|
||||||
if (!options.warnings) options.warnings = true;
|
if (!options.warnings) options.warnings = true;
|
||||||
}
|
}
|
||||||
|
if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) {
|
||||||
|
var quoted_props = test.mangle.properties.reserved;
|
||||||
|
if (!Array.isArray(quoted_props)) quoted_props = [];
|
||||||
|
test.mangle.properties.reserved = quoted_props;
|
||||||
|
U.reserve_quoted_keys(input, quoted_props);
|
||||||
|
}
|
||||||
var cmp = new U.Compressor(options, true);
|
var cmp = new U.Compressor(options, true);
|
||||||
var output = cmp.compress(input);
|
var output = cmp.compress(input);
|
||||||
output.figure_out_scope(test.mangle);
|
output.figure_out_scope(test.mangle);
|
||||||
if (test.mangle || test.mangle_props) {
|
if (test.mangle) {
|
||||||
U.base54.reset();
|
U.base54.reset();
|
||||||
output.compute_char_frequency(test.mangle);
|
output.compute_char_frequency(test.mangle);
|
||||||
}
|
|
||||||
if (test.mangle) {
|
|
||||||
output.mangle_names(test.mangle);
|
output.mangle_names(test.mangle);
|
||||||
|
if (test.mangle.properties) {
|
||||||
|
output = U.mangle_properties(output, test.mangle.properties);
|
||||||
}
|
}
|
||||||
if (test.mangle_props) {
|
|
||||||
output = U.mangle_properties(output, test.mangle_props);
|
|
||||||
}
|
}
|
||||||
output = make_code(output, output_options);
|
output = make_code(output, output_options);
|
||||||
if (expect != output) {
|
if (expect != output) {
|
||||||
|
|||||||
Reference in New Issue
Block a user