Compare commits
30 Commits
harmony-v3
...
harmony-v3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a89f126db6 | ||
|
|
d8ee2de95c | ||
|
|
58a5608b66 | ||
|
|
f496ac5c85 | ||
|
|
dfe4f6c6de | ||
|
|
a09c8ad666 | ||
|
|
ec598c351b | ||
|
|
f79f737fb2 | ||
|
|
eba0f93bc0 | ||
|
|
99800d4aa9 | ||
|
|
70d56c951a | ||
|
|
b810e2f8da | ||
|
|
1abe14296e | ||
|
|
336b1add4f | ||
|
|
873755b35c | ||
|
|
744032755d | ||
|
|
4fac8076b8 | ||
|
|
6920e898d1 | ||
|
|
dd71639264 | ||
|
|
2dcc552ce0 | ||
|
|
a020d2ead3 | ||
|
|
68645b28d3 | ||
|
|
aaa8212837 | ||
|
|
bd84007cf4 | ||
|
|
55387e8fd0 | ||
|
|
1241600013 | ||
|
|
7e3e9da860 | ||
|
|
a784717fe2 | ||
|
|
00f509405b | ||
|
|
e8235657e4 |
302
README.md
302
README.md
@@ -151,10 +151,10 @@ 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.
|
||||||
Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
|
|
||||||
`//# sourceMappingURL=` directive.
|
|
||||||
|
|
||||||
- `--source-map "url='<URL>'"` to specify the URL where the source map can be found.
|
- `--source-map "url='<URL>'"` to specify the URL where the source map can be found.
|
||||||
|
Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
|
||||||
|
`//# sourceMappingURL=` directive.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
@@ -201,11 +201,9 @@ 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
|
||||||
@@ -511,6 +509,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
|
||||||
@@ -592,125 +593,93 @@ 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
|
||||||
|
|
||||||
- `ecma` (default: `8`) -- specify one of `5`, `6`, `7` or `8`. Note: this setting
|
- `ecma` (default: `8`) -- specify one of `5`, `6`, `7` or `8`. Note: this setting
|
||||||
is not presently enforced except for ES8 optional trailing commas in function
|
is not presently enforced except for ES8 optional trailing commas in function
|
||||||
parameter lists and calls with `ecma` `8`.
|
parameter lists and calls with `ecma` `8`.
|
||||||
|
|
||||||
- `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
|
|
||||||
comma operator. May be set to a positive integer to specify the maximum number
|
|
||||||
of consecutive comma sequences that will be generated. If this option is set to
|
|
||||||
`true` then the default `sequences` limit is `200`. Set option to `false` or `0`
|
|
||||||
to disable. The smallest `sequences` length is `2`. A `sequences` value of `1`
|
|
||||||
is grandfathered to be equivalent to `true` and as such means `200`. On rare
|
|
||||||
occasions the default sequences limit leads to very slow compress times in which
|
|
||||||
case a value of `20` or less is recommended.
|
|
||||||
|
|
||||||
- `properties` -- rewrite property access using the dot notation, for
|
|
||||||
example `foo["bar"] → foo.bar`
|
|
||||||
|
|
||||||
- `dead_code` -- remove unreachable code
|
|
||||||
|
|
||||||
- `drop_debugger` -- remove `debugger;` statements
|
|
||||||
|
|
||||||
- `unsafe` (default: false) -- apply "unsafe" transformations (discussion below)
|
|
||||||
|
|
||||||
- `unsafe_comps` (default: false) -- Reverse `<` and `<=` to `>` and `>=` to
|
|
||||||
allow improved compression. This might be unsafe when an at least one of two
|
|
||||||
operands is an object with computed values due the use of methods like `get`,
|
|
||||||
or `valueOf`. This could cause change in execution order after operands in the
|
|
||||||
comparison are switching. Compression only works if both `comparisons` and
|
|
||||||
`unsafe_comps` are both set to true.
|
|
||||||
|
|
||||||
- `unsafe_Func` (default: false) -- compress and mangle `Function(args, code)`
|
|
||||||
when both `args` and `code` are string literals.
|
|
||||||
|
|
||||||
- `unsafe_math` (default: false) -- optimize numerical expressions like
|
|
||||||
`2 * x * 3` into `6 * x`, which may give imprecise floating point results.
|
|
||||||
|
|
||||||
- `unsafe_proto` (default: false) -- optimize expressions like
|
|
||||||
`Array.prototype.slice.call(a)` into `[].slice.call(a)`
|
|
||||||
|
|
||||||
- `unsafe_regexp` (default: false) -- enable substitutions of variables with
|
|
||||||
`RegExp` values the same way as if they are constants.
|
|
||||||
|
|
||||||
- `conditionals` -- apply optimizations for `if`-s and conditional
|
|
||||||
expressions
|
|
||||||
|
|
||||||
- `comparisons` -- apply certain optimizations to binary nodes, for example:
|
|
||||||
`!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary
|
|
||||||
nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
|
|
||||||
|
|
||||||
- `evaluate` -- attempt to evaluate constant expressions
|
|
||||||
|
|
||||||
- `arrows` (default `true`) -- Converts `()=>{return x}` to `()=>x`. Class
|
- `arrows` (default `true`) -- Converts `()=>{return x}` to `()=>x`. Class
|
||||||
and object literal methods will also be converted to arrow expressions if
|
and object literal methods will also be converted to arrow expressions if
|
||||||
the resultant code is shorter: `m(){return x}` becomes `m:()=>x`.
|
the resultant code is shorter: `m(){return x}` becomes `m:()=>x`.
|
||||||
This transform requires that the `ecma` compress option is set to `6` or greater.
|
This transform requires that the `ecma` compress option is set to `6` or greater.
|
||||||
|
|
||||||
- `unsafe_arrows` (default `false`) -- Convert ES5 style anonymous function
|
- `booleans` (default: `true`) -- various optimizations for boolean context, for example `!!a
|
||||||
expressions to arrow functions if the function body does not reference `this`.
|
|
||||||
Note: it is not always safe to perform this conversion if code relies on the
|
|
||||||
the function having a `prototype`, which arrow functions lack.
|
|
||||||
This transform requires that the `ecma` compress option is set to `6` or greater.
|
|
||||||
|
|
||||||
- `booleans` -- various optimizations for boolean context, for example `!!a
|
|
||||||
? b : c → a ? b : c`
|
? b : c → a ? b : c`
|
||||||
|
|
||||||
- `typeofs` -- default `true`. Transforms `typeof foo == "undefined"` into
|
- `cascade` (default: `true`) -- small optimization for sequences, transform `x, x` into `x`
|
||||||
`foo === void 0`. Note: recommend to set this value to `false` for IE10 and
|
|
||||||
earlier versions due to known issues.
|
|
||||||
|
|
||||||
- `loops` -- optimizations for `do`, `while` and `for` loops when we can
|
|
||||||
statically determine the condition
|
|
||||||
|
|
||||||
- `unused` -- drop unreferenced functions and variables (simple direct variable
|
|
||||||
assignments do not count as references unless set to `"keep_assign"`)
|
|
||||||
|
|
||||||
- `toplevel` -- drop unreferenced functions (`"funcs"`) and/or variables (`"vars"`)
|
|
||||||
in the top level scope (`false` by default, `true` to drop both unreferenced
|
|
||||||
functions and variables)
|
|
||||||
|
|
||||||
- `top_retain` -- prevent specific toplevel functions and variables from `unused`
|
|
||||||
removal (can be array, comma-separated, RegExp or function. Implies `toplevel`)
|
|
||||||
|
|
||||||
- `hoist_funs` -- hoist function declarations
|
|
||||||
|
|
||||||
- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false`
|
|
||||||
by default because it seems to increase the size of the output in general)
|
|
||||||
|
|
||||||
- `if_return` -- optimizations for if/return and if/continue
|
|
||||||
|
|
||||||
- `inline` -- embed simple functions
|
|
||||||
|
|
||||||
- `join_vars` -- join consecutive `var` statements
|
|
||||||
|
|
||||||
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
|
||||||
and `x = something(), x` into `x = something()`
|
and `x = something(), x` into `x = something()`
|
||||||
|
|
||||||
- `collapse_vars` -- Collapse single-use non-constant variables - side
|
- `collapse_vars` (default: `true`) -- Collapse single-use non-constant variables - side
|
||||||
effects permitting.
|
effects permitting.
|
||||||
|
|
||||||
- `reduce_vars` -- Improve optimization on variables assigned with and
|
- `comparisons` (default: `true`) -- apply certain optimizations to binary nodes, for example:
|
||||||
used as constant values.
|
`!(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.
|
||||||
|
|
||||||
- `warnings` -- display warnings when dropping unreachable code or unused
|
- `computed_props` -- default `true`. Transforms constant computed properties
|
||||||
declarations etc.
|
into regular ones: `{["computed"]: 1}` is converted into `{computed: 1}`.
|
||||||
|
|
||||||
- `negate_iife` -- negate "Immediately-Called Function Expressions"
|
- `conditionals` (default: `true`) -- apply optimizations for `if`-s and conditional
|
||||||
|
expressions
|
||||||
|
|
||||||
|
- `dead_code` (default: `true`) -- remove unreachable code
|
||||||
|
|
||||||
|
- `drop_console` (default: `false`) -- default `false`. Pass `true` to discard calls to
|
||||||
|
`console.*` functions. If you wish to drop a specific function call
|
||||||
|
such as `console.info` and/or retain side effects from function arguments
|
||||||
|
after dropping the function call then use `pure_funcs` instead.
|
||||||
|
|
||||||
|
- `drop_debugger` (default: `true`) -- remove `debugger;` statements
|
||||||
|
|
||||||
|
- `ecma` -- default `5`. Pass `6` or greater to enable `compress` options that
|
||||||
|
will transform ES5 code into smaller ES6+ equivalent forms.
|
||||||
|
|
||||||
|
- `evaluate` (default: `true`) -- attempt to evaluate constant expressions
|
||||||
|
|
||||||
|
- `expression` (default: `false`) -- default `false`. Pass `true` to preserve completion values
|
||||||
|
from terminal statements without `return`, e.g. in bookmarklets.
|
||||||
|
|
||||||
|
- `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation)
|
||||||
|
|
||||||
|
- `hoist_funs` (default: `true`) -- hoist function declarations
|
||||||
|
|
||||||
|
- `hoist_vars` (default: `false`) -- hoist `var` declarations (this is `false`
|
||||||
|
by default because it seems to increase the size of the output in general)
|
||||||
|
|
||||||
|
- `if_return` (default: `true`) -- optimizations for if/return and if/continue
|
||||||
|
|
||||||
|
- `inline` (default: `true`) -- embed simple functions
|
||||||
|
|
||||||
|
- `join_vars` (default: `true`) -- join consecutive `var` statements
|
||||||
|
|
||||||
|
- `keep_fargs` (default: `true`) -- default `true`. Prevents the
|
||||||
|
compressor from discarding unused function arguments. You need this
|
||||||
|
for code which relies on `Function.length`.
|
||||||
|
|
||||||
|
- `keep_infinity` (default: `false`) -- default `false`. Pass `true` to prevent `Infinity` from
|
||||||
|
being compressed into `1/0`, which may cause performance issues on Chrome.
|
||||||
|
|
||||||
|
- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops when we can
|
||||||
|
statically determine the condition
|
||||||
|
|
||||||
|
- `negate_iife` (default: `true`) -- 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
|
||||||
@@ -721,51 +690,85 @@ 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();`
|
||||||
|
|
||||||
- `ecma` -- default `5`. Pass `6` or greater to enable `compress` options that
|
- `switches` (default: `true`) -- de-duplicate and remove unreachable `switch` branches
|
||||||
will transform ES5 code into smaller ES6+ equivalent forms.
|
|
||||||
|
- `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_arrows` (default `false`) -- Convert ES5 style anonymous function
|
||||||
|
expressions to arrow functions if the function body does not reference `this`.
|
||||||
|
Note: it is not always safe to perform this conversion if code relies on the
|
||||||
|
the function having a `prototype`, which arrow functions lack.
|
||||||
|
This transform requires that the `ecma` compress option is set to `6` or greater.
|
||||||
|
|
||||||
|
- `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
|
||||||
|
|
||||||
|
- `keep_classnames` (default `false`). Pass `true` to not mangle class names.
|
||||||
|
|
||||||
- `reserved` (default `[]`). Pass an array of identifiers that should be
|
- `reserved` (default `[]`). Pass an array of identifiers that should be
|
||||||
excluded from mangling. Example: `["foo", "bar"]`.
|
excluded from mangling. Example: `["foo", "bar"]`.
|
||||||
|
|
||||||
- `toplevel` (default `false`). Pass `true` to mangle names declared in the
|
- `toplevel` (default `false`). Pass `true` to mangle names declared in the
|
||||||
top level scope.
|
top level scope.
|
||||||
|
|
||||||
- `keep_classnames` (default `false`). Pass `true` to not mangle class names.
|
|
||||||
|
|
||||||
- `keep_fnames` (default `false`). Pass `true` to not mangle function names.
|
|
||||||
Useful for code relying on `Function.prototype.name`. See also: the `keep_fnames`
|
|
||||||
[compress option](#compress-options).
|
|
||||||
|
|
||||||
- `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.
|
||||||
|
|
||||||
@@ -797,16 +800,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
|
||||||
@@ -815,37 +822,50 @@ 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.
|
||||||
|
|
||||||
- `ecma` (default `5`) -- set output printing mode. Set `ecma` to `6` or
|
- `ecma` (default `5`) -- set output printing mode. Set `ecma` to `6` or
|
||||||
greater to emit shorthand object properties - i.e.: `{a}` instead of `{a: a}`.
|
greater to emit shorthand object properties - i.e.: `{a}` instead of `{a: a}`.
|
||||||
The `ecma` option will only change the output in direct control of the
|
The `ecma` option will only change the output in direct control of the
|
||||||
beautifier. Non-compatible features in the abstract syntax tree will still
|
beautifier. Non-compatible features in the abstract syntax tree will still
|
||||||
be output as is. For example: an `ecma` setting of `5` will **not** convert
|
be output as is. For example: an `ecma` setting of `5` will **not** convert
|
||||||
ES6+ code to ES5.
|
ES6+ code to ES5.
|
||||||
- `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
|
||||||
@@ -853,16 +873,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);
|
||||||
@@ -303,10 +302,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",
|
||||||
|
|||||||
105
lib/compress.js
105
lib/compress.js
@@ -53,6 +53,7 @@ function Compressor(options, false_by_default) {
|
|||||||
cascade : !false_by_default,
|
cascade : !false_by_default,
|
||||||
collapse_vars : !false_by_default,
|
collapse_vars : !false_by_default,
|
||||||
comparisons : !false_by_default,
|
comparisons : !false_by_default,
|
||||||
|
computed_props: !false_by_default,
|
||||||
conditionals : !false_by_default,
|
conditionals : !false_by_default,
|
||||||
dead_code : !false_by_default,
|
dead_code : !false_by_default,
|
||||||
drop_console : false,
|
drop_console : false,
|
||||||
@@ -88,6 +89,7 @@ function Compressor(options, false_by_default) {
|
|||||||
unsafe_comps : false,
|
unsafe_comps : false,
|
||||||
unsafe_Func : false,
|
unsafe_Func : false,
|
||||||
unsafe_math : false,
|
unsafe_math : false,
|
||||||
|
unsafe_methods: false,
|
||||||
unsafe_proto : false,
|
unsafe_proto : false,
|
||||||
unsafe_regexp : false,
|
unsafe_regexp : false,
|
||||||
unused : !false_by_default,
|
unused : !false_by_default,
|
||||||
@@ -289,6 +291,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;
|
||||||
@@ -297,6 +303,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;
|
||||||
@@ -308,7 +316,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();
|
||||||
@@ -333,6 +341,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 {
|
||||||
@@ -392,6 +401,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;
|
||||||
@@ -404,10 +414,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
|
||||||
@@ -441,10 +450,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) {
|
||||||
@@ -455,6 +467,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);
|
||||||
@@ -468,14 +482,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) {
|
||||||
@@ -546,10 +564,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) {
|
||||||
@@ -849,7 +880,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()))
|
||||||
@@ -874,7 +905,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function has_overlapping_symbol(fn, arg) {
|
function has_overlapping_symbol(fn, arg, fn_strict) {
|
||||||
var found = false, scan_this = !(fn instanceof AST_Arrow);
|
var found = false, scan_this = !(fn instanceof AST_Arrow);
|
||||||
arg.walk(new TreeWalker(function(node, descend) {
|
arg.walk(new TreeWalker(function(node, descend) {
|
||||||
if (found) return true;
|
if (found) return true;
|
||||||
@@ -885,7 +916,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return found = true;
|
return found = true;
|
||||||
}
|
}
|
||||||
if (scan_this && node instanceof AST_This) {
|
if ((fn_strict || scan_this) && node instanceof AST_This) {
|
||||||
return found = true;
|
return found = true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Scope && !(node instanceof AST_Arrow)) {
|
if (node instanceof AST_Scope && !(node instanceof AST_Arrow)) {
|
||||||
@@ -910,6 +941,8 @@ merge(Compressor.prototype, {
|
|||||||
&& all(iife.args, function(arg) {
|
&& all(iife.args, function(arg) {
|
||||||
return !(arg instanceof AST_Expansion);
|
return !(arg instanceof AST_Expansion);
|
||||||
})) {
|
})) {
|
||||||
|
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];
|
||||||
@@ -918,7 +951,7 @@ merge(Compressor.prototype, {
|
|||||||
if (sym instanceof AST_Expansion) {
|
if (sym instanceof AST_Expansion) {
|
||||||
var elements = iife.args.slice(i);
|
var elements = iife.args.slice(i);
|
||||||
if (all(elements, function(arg) {
|
if (all(elements, function(arg) {
|
||||||
return !has_overlapping_symbol(fn, arg);
|
return !has_overlapping_symbol(fn, arg, fn_strict);
|
||||||
})) {
|
})) {
|
||||||
candidates.unshift(make_node(AST_VarDef, sym, {
|
candidates.unshift(make_node(AST_VarDef, sym, {
|
||||||
name: sym.expression,
|
name: sym.expression,
|
||||||
@@ -930,7 +963,7 @@ merge(Compressor.prototype, {
|
|||||||
} else {
|
} else {
|
||||||
var arg = iife.args[i];
|
var arg = iife.args[i];
|
||||||
if (!arg) arg = make_node(AST_Undefined, sym).transform(compressor);
|
if (!arg) arg = make_node(AST_Undefined, sym).transform(compressor);
|
||||||
else if (has_overlapping_symbol(fn, arg)) arg = null;
|
else if (has_overlapping_symbol(fn, arg, fn_strict)) arg = null;
|
||||||
if (arg) candidates.unshift(make_node(AST_VarDef, sym, {
|
if (arg) candidates.unshift(make_node(AST_VarDef, sym, {
|
||||||
name: sym,
|
name: sym,
|
||||||
value: arg
|
value: arg
|
||||||
@@ -2219,6 +2252,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();
|
||||||
});
|
});
|
||||||
@@ -3431,7 +3480,9 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
var elements = [];
|
var elements = [];
|
||||||
var consts = [];
|
var consts = [];
|
||||||
exp.expression.elements.forEach(function(el) {
|
for (var i = 0, len = exp.expression.elements.length; i < len; i++) {
|
||||||
|
var el = exp.expression.elements[i];
|
||||||
|
if (el instanceof AST_Expansion) break EXIT;
|
||||||
var value = el.evaluate(compressor);
|
var value = el.evaluate(compressor);
|
||||||
if (value !== el) {
|
if (value !== el) {
|
||||||
consts.push(value);
|
consts.push(value);
|
||||||
@@ -3444,7 +3495,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
elements.push(el);
|
elements.push(el);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
if (consts.length > 0) {
|
if (consts.length > 0) {
|
||||||
elements.push(make_node(AST_String, self, {
|
elements.push(make_node(AST_String, self, {
|
||||||
value: consts.join(separator)
|
value: consts.join(separator)
|
||||||
@@ -4297,12 +4348,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")
|
||||||
&& is_func_expr(fixed)
|
|
||||||
&& d.references.length == 1
|
&& d.references.length == 1
|
||||||
&& !(d.scope.uses_arguments && d.orig[0] instanceof AST_SymbolFunarg)
|
&& (d.single_use || is_func_expr(fixed)
|
||||||
&& !d.scope.uses_eval
|
&& !(d.scope.uses_arguments && d.orig[0] instanceof AST_SymbolFunarg)
|
||||||
&& compressor.find_parent(AST_Scope) === fixed.parent_scope) {
|
&& !d.scope.uses_eval
|
||||||
return fixed.clone(true);
|
&& compressor.find_parent(AST_Scope) === fixed.parent_scope)) {
|
||||||
|
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) {
|
||||||
@@ -4861,12 +4913,27 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_ObjectKeyVal, function(self, compressor){
|
OPT(AST_ObjectKeyVal, function(self, compressor){
|
||||||
|
// ["p"]:1 ---> p:1
|
||||||
|
// [42]:1 ---> 42:1
|
||||||
|
if (compressor.option("computed_props")
|
||||||
|
&& self.key instanceof AST_Constant // save a comparison in the typical case
|
||||||
|
&& (
|
||||||
|
// whitelist acceptable props as not all AST_Constants are true constants
|
||||||
|
self.key instanceof AST_String
|
||||||
|
|| self.key instanceof AST_Number
|
||||||
|
)) {
|
||||||
|
self.key = self.key.value;
|
||||||
|
// fallthrough - `return self` not needed as transformed tree in good form
|
||||||
|
}
|
||||||
// p:function(){} ---> p(){}
|
// p:function(){} ---> p(){}
|
||||||
// p:function*(){} ---> *p(){}
|
// p:function*(){} ---> *p(){}
|
||||||
// p:async function(){} ---> async p(){}
|
// p:async function(){} ---> async p(){}
|
||||||
// p:()=>{} ---> p(){}
|
// p:()=>{} ---> p(){}
|
||||||
// p:async()=>{} ---> async p(){}
|
// p:async()=>{} ---> async p(){}
|
||||||
if (compressor.option("ecma") >= 6) {
|
var unsafe_methods = compressor.option("unsafe_methods");
|
||||||
|
if (unsafe_methods
|
||||||
|
&& compressor.option("ecma") >= 6
|
||||||
|
&& (!(unsafe_methods instanceof RegExp) || unsafe_methods.test(self.key + ""))) {
|
||||||
var key = self.key;
|
var key = self.key;
|
||||||
var value = self.value;
|
var value = self.value;
|
||||||
var is_arrow_with_block = value instanceof AST_Arrow
|
var is_arrow_with_block = value instanceof AST_Arrow
|
||||||
|
|||||||
@@ -506,13 +506,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);
|
||||||
@@ -526,8 +530,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);
|
||||||
|
|||||||
31
lib/parse.js
31
lib/parse.js
@@ -44,9 +44,9 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var KEYWORDS = 'break case catch class const continue debugger default delete do else export extends finally for function if in instanceof new return switch throw try typeof var let void while with import';
|
var KEYWORDS = 'break case catch class const continue debugger default delete do else export extends finally for function if in instanceof let new return switch throw try typeof var void while with';
|
||||||
var KEYWORDS_ATOM = 'false null true';
|
var KEYWORDS_ATOM = 'false null true';
|
||||||
var RESERVED_WORDS = 'enum implements interface package private protected public static super this ' + KEYWORDS_ATOM + " " + KEYWORDS;
|
var RESERVED_WORDS = 'enum implements import interface package private protected public static super this ' + KEYWORDS_ATOM + " " + KEYWORDS;
|
||||||
var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case yield await';
|
var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case yield await';
|
||||||
|
|
||||||
KEYWORDS = makePredicate(KEYWORDS);
|
KEYWORDS = makePredicate(KEYWORDS);
|
||||||
@@ -1013,6 +1013,12 @@ function parse($TEXT, options) {
|
|||||||
next();
|
next();
|
||||||
return function_(AST_Defun, false, true);
|
return function_(AST_Defun, false, true);
|
||||||
}
|
}
|
||||||
|
if (S.token.value == "import" && !is_token(peek(), "punc", "(")) {
|
||||||
|
next();
|
||||||
|
var node = import_();
|
||||||
|
semicolon();
|
||||||
|
return node;
|
||||||
|
}
|
||||||
return is_token(peek(), "punc", ":")
|
return is_token(peek(), "punc", ":")
|
||||||
? labeled_statement()
|
? labeled_statement()
|
||||||
: simple_statement();
|
: simple_statement();
|
||||||
@@ -1149,15 +1155,11 @@ function parse($TEXT, options) {
|
|||||||
body : statement()
|
body : statement()
|
||||||
});
|
});
|
||||||
|
|
||||||
case "import":
|
|
||||||
next();
|
|
||||||
var node = import_();
|
|
||||||
semicolon();
|
|
||||||
return node;
|
|
||||||
|
|
||||||
case "export":
|
case "export":
|
||||||
next();
|
if (!is_token(peek(), "punc", "(")) {
|
||||||
return export_();
|
next();
|
||||||
|
return export_();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unexpected();
|
unexpected();
|
||||||
@@ -1320,6 +1322,9 @@ function parse($TEXT, options) {
|
|||||||
if (in_statement && !name)
|
if (in_statement && !name)
|
||||||
unexpected();
|
unexpected();
|
||||||
|
|
||||||
|
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
|
||||||
|
unexpected(prev());
|
||||||
|
|
||||||
var args = parameters();
|
var args = parameters();
|
||||||
var body = _function_body(true, is_generator || is_generator_property, is_async, name, args);
|
var body = _function_body(true, is_generator || is_generator_property, is_async, name, args);
|
||||||
return new ctor({
|
return new ctor({
|
||||||
@@ -1875,7 +1880,8 @@ function parse($TEXT, options) {
|
|||||||
: !no_in && kind === "const" && S.input.has_directive("use strict")
|
: !no_in && kind === "const" && S.input.has_directive("use strict")
|
||||||
? croak("Missing initializer in const declaration") : null,
|
? croak("Missing initializer in const declaration") : null,
|
||||||
end : prev()
|
end : prev()
|
||||||
})
|
});
|
||||||
|
if (def.name.name == "import") croak("Unexpected token: import");
|
||||||
}
|
}
|
||||||
a.push(def);
|
a.push(def);
|
||||||
if (!is("punc", ","))
|
if (!is("punc", ","))
|
||||||
@@ -1994,9 +2000,6 @@ function parse($TEXT, options) {
|
|||||||
names: ex.properties.map(to_fun_args)
|
names: ex.properties.map(to_fun_args)
|
||||||
}), default_seen_above);
|
}), default_seen_above);
|
||||||
} else if (ex instanceof AST_ObjectKeyVal) {
|
} else if (ex instanceof AST_ObjectKeyVal) {
|
||||||
if (ex.key instanceof AST_SymbolRef) {
|
|
||||||
ex.key = to_fun_args(ex.key, 0, [ex.key]);
|
|
||||||
}
|
|
||||||
ex.value = to_fun_args(ex.value, 0, [ex.key]);
|
ex.value = to_fun_args(ex.value, 0, [ex.key]);
|
||||||
return insert_default(ex, default_seen_above);
|
return insert_default(ex, default_seen_above);
|
||||||
} else if (ex instanceof AST_Hole) {
|
} else if (ex instanceof AST_Hole) {
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
|||||||
var mangle_with_block_scope =
|
var mangle_with_block_scope =
|
||||||
(!options.ie8 && node instanceof AST_SymbolCatch) ||
|
(!options.ie8 && node instanceof AST_SymbolCatch) ||
|
||||||
node instanceof AST_SymbolBlockDeclaration;
|
node instanceof AST_SymbolBlockDeclaration;
|
||||||
if (mangle_with_block_scope) {
|
if (mangle_with_block_scope && options.reserved.indexOf(node.name) < 0) {
|
||||||
to_mangle.push(node.definition());
|
to_mangle.push(node.definition());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.1.1",
|
"version": "3.1.4",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"commander": "~2.11.0",
|
"commander": "~2.11.0",
|
||||||
"source-map": "~0.5.1"
|
"source-map": "~0.6.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"acorn": "~5.1.1",
|
"acorn": "~5.1.1",
|
||||||
|
|||||||
@@ -290,6 +290,7 @@ issue_2105_1: {
|
|||||||
passes: 3,
|
passes: 3,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
|
unsafe_methods: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
@@ -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,12 +1291,12 @@ 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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
(function(){
|
(function() {
|
||||||
var result;
|
var result;
|
||||||
var s = 'acdabcdeabbb';
|
var s = 'acdabcdeabbb';
|
||||||
var rx = /ab*/g;
|
var rx = /ab*/g;
|
||||||
@@ -1305,22 +1304,35 @@ 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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
(function(){
|
(function() {
|
||||||
var result, rx = /ab*/g;
|
var result, rx = /ab*/g;
|
||||||
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
|
||||||
}
|
}
|
||||||
@@ -1933,9 +1945,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"
|
||||||
}
|
}
|
||||||
@@ -2725,3 +2737,140 @@ issue_2313_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "0"
|
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",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -863,12 +863,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 function(a) {};
|
||||||
return a;
|
})();
|
||||||
})(function(a) {});
|
}();
|
||||||
});
|
})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1114,6 +1114,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());
|
||||||
@@ -1121,11 +1122,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: {
|
||||||
@@ -1138,17 +1143,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: {
|
||||||
|
|||||||
@@ -226,3 +226,27 @@ keyword_valid_3: {
|
|||||||
export { default as default } from "module.js";
|
export { default as default } from "module.js";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dynamic_import: {
|
||||||
|
mangle = {
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
import traditional from './traditional.js';
|
||||||
|
function imp(x) {
|
||||||
|
return import(x);
|
||||||
|
}
|
||||||
|
import("module_for_side_effects.js");
|
||||||
|
let dynamic = import("some/module.js");
|
||||||
|
dynamic.foo();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
import o from "./traditional.js";
|
||||||
|
function t(o) {
|
||||||
|
return import(o);
|
||||||
|
}
|
||||||
|
import("module_for_side_effects.js");
|
||||||
|
let r = import("some/module.js");
|
||||||
|
r.foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -804,3 +804,134 @@ object_spread_of_sequence: {
|
|||||||
console.log({ ...o || o });
|
console.log({ ...o || o });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// issue 2316
|
||||||
|
class_name_can_be_preserved_with_reserved: {
|
||||||
|
mangle = {
|
||||||
|
reserved: [ "Foo" ],
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function x() {
|
||||||
|
class Foo {}
|
||||||
|
Foo.bar;
|
||||||
|
class Bar {}
|
||||||
|
Bar.foo;
|
||||||
|
}
|
||||||
|
function y() {
|
||||||
|
var Foo = class Foo {};
|
||||||
|
Foo.bar;
|
||||||
|
var Bar = class Bar {};
|
||||||
|
Bar.bar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function x() {
|
||||||
|
class Foo {}
|
||||||
|
Foo.bar;
|
||||||
|
class a {}
|
||||||
|
a.foo;
|
||||||
|
}
|
||||||
|
function y() {
|
||||||
|
var Foo = class Foo {};
|
||||||
|
Foo.bar;
|
||||||
|
var a = class a {};
|
||||||
|
a.bar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2345: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log([...[3, 2, 1]].join("-"));
|
||||||
|
var a = [3, 2, 1];
|
||||||
|
console.log([...a].join("-"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log([...[3, 2, 1]].join("-"));
|
||||||
|
var a = [3, 2, 1];
|
||||||
|
console.log([...a].join("-"));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"3-2-1",
|
||||||
|
"3-2-1",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2349: {
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
function foo(boo, key) {
|
||||||
|
const value = boo.get();
|
||||||
|
return value.map(({[key]: bar}) => bar);
|
||||||
|
}
|
||||||
|
console.log(foo({
|
||||||
|
get: () => [ {
|
||||||
|
blah: 42
|
||||||
|
} ]
|
||||||
|
}, "blah"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo(o, n) {
|
||||||
|
const t = o.get();
|
||||||
|
return t.map(({[n]: o}) => o);
|
||||||
|
}
|
||||||
|
console.log(foo({
|
||||||
|
get: () => [ {
|
||||||
|
blah: 42
|
||||||
|
} ]
|
||||||
|
}, "blah"));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"[ 42 ]",
|
||||||
|
]
|
||||||
|
node_version: ">=7"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2349b: {
|
||||||
|
options = {
|
||||||
|
arrows: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
ecma: 6,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 3,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
unsafe_arrows: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo(boo, key) {
|
||||||
|
const value = boo.get();
|
||||||
|
return value.map(function({[key]: bar}){ return bar; });
|
||||||
|
}
|
||||||
|
console.log(foo({
|
||||||
|
get: function() {
|
||||||
|
return [ {
|
||||||
|
blah: 42
|
||||||
|
} ];
|
||||||
|
}
|
||||||
|
}, "blah"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log([ {
|
||||||
|
blah: 42
|
||||||
|
} ].map(({["blah"]: l}) => l));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"[ 42 ]",
|
||||||
|
]
|
||||||
|
node_version: ">=7"
|
||||||
|
}
|
||||||
|
|||||||
@@ -126,6 +126,67 @@ computed_property_names: {
|
|||||||
expect_exact: 'obj({["x"+"x"]:6});'
|
expect_exact: 'obj({["x"+"x"]:6});'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
convert_computed_props_to_regular_ones: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
computed_props: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {
|
||||||
|
["hi"]: 0,
|
||||||
|
["A" + 1]: 1,
|
||||||
|
[/B/]: 2,
|
||||||
|
[100 + 23]: 3,
|
||||||
|
[1 + .5]: 4,
|
||||||
|
[Math.PI]: 5,
|
||||||
|
[undefined]: 6,
|
||||||
|
[true]: 7,
|
||||||
|
[false]: 8,
|
||||||
|
[null]: 9,
|
||||||
|
[Infinity]: 10,
|
||||||
|
[NaN]: 11,
|
||||||
|
};
|
||||||
|
for (var k in o) {
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
hi: 0,
|
||||||
|
A1: 1,
|
||||||
|
[/B/]: 2,
|
||||||
|
123: 3,
|
||||||
|
1.5: 4,
|
||||||
|
[Math.PI]: 5,
|
||||||
|
|
||||||
|
// leave these problematic cases as is
|
||||||
|
[void 0]: 6,
|
||||||
|
[!0]: 7,
|
||||||
|
[!1]: 8,
|
||||||
|
[null]: 9,
|
||||||
|
[1 / 0]: 10,
|
||||||
|
[NaN]: 11
|
||||||
|
};
|
||||||
|
for (var k in o) console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"123 3",
|
||||||
|
"hi 0",
|
||||||
|
"A1 1",
|
||||||
|
"/B/ 2",
|
||||||
|
"1.5 4",
|
||||||
|
"3.141592653589793 5",
|
||||||
|
"undefined 6",
|
||||||
|
"true 7",
|
||||||
|
"false 8",
|
||||||
|
"null 9",
|
||||||
|
"Infinity 10",
|
||||||
|
"NaN 11",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
computed_property_names_evaluated_1: {
|
computed_property_names_evaluated_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true
|
evaluate: true
|
||||||
@@ -516,6 +577,7 @@ variable_as_computed_property: {
|
|||||||
prop_func_to_concise_method: {
|
prop_func_to_concise_method: {
|
||||||
options = {
|
options = {
|
||||||
ecma: 6,
|
ecma: 6,
|
||||||
|
unsafe_methods: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
({
|
({
|
||||||
@@ -544,6 +606,7 @@ prop_func_to_concise_method: {
|
|||||||
prop_arrow_to_concise_method: {
|
prop_arrow_to_concise_method: {
|
||||||
options = {
|
options = {
|
||||||
ecma: 6,
|
ecma: 6,
|
||||||
|
unsafe_methods: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
({
|
({
|
||||||
@@ -592,6 +655,7 @@ concise_method_to_prop_arrow: {
|
|||||||
prop_func_to_async_concise_method: {
|
prop_func_to_async_concise_method: {
|
||||||
options = {
|
options = {
|
||||||
ecma: 8,
|
ecma: 8,
|
||||||
|
unsafe_methods: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
({
|
({
|
||||||
@@ -614,6 +678,7 @@ prop_func_to_async_concise_method: {
|
|||||||
prop_func_to_concise_method_various: {
|
prop_func_to_concise_method_various: {
|
||||||
options = {
|
options = {
|
||||||
ecma: 6,
|
ecma: 6,
|
||||||
|
unsafe_methods: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
({
|
({
|
||||||
@@ -646,6 +711,7 @@ prop_func_to_concise_method_various: {
|
|||||||
prop_arrows_to_concise_method_various: {
|
prop_arrows_to_concise_method_various: {
|
||||||
options = {
|
options = {
|
||||||
ecma: 6,
|
ecma: 6,
|
||||||
|
unsafe_methods: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
({
|
({
|
||||||
@@ -674,6 +740,7 @@ prop_arrows_to_concise_method_various: {
|
|||||||
prop_arrow_with_this: {
|
prop_arrow_with_this: {
|
||||||
options = {
|
options = {
|
||||||
ecma: 6,
|
ecma: 6,
|
||||||
|
unsafe_methods: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function run(arg) {
|
function run(arg) {
|
||||||
@@ -711,6 +778,7 @@ prop_arrow_with_this: {
|
|||||||
prop_arrow_with_nested_this: {
|
prop_arrow_with_nested_this: {
|
||||||
options = {
|
options = {
|
||||||
ecma: 6,
|
ecma: 6,
|
||||||
|
unsafe_methods: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function run(arg) {
|
function run(arg) {
|
||||||
|
|||||||
@@ -887,6 +887,7 @@ methods_keep_quoted_true: {
|
|||||||
options = {
|
options = {
|
||||||
arrows: true,
|
arrows: true,
|
||||||
ecma: 6,
|
ecma: 6,
|
||||||
|
unsafe_methods: true,
|
||||||
}
|
}
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
@@ -906,6 +907,7 @@ methods_keep_quoted_false: {
|
|||||||
options = {
|
options = {
|
||||||
arrows: true,
|
arrows: true,
|
||||||
ecma: 6,
|
ecma: 6,
|
||||||
|
unsafe_methods: true,
|
||||||
}
|
}
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
@@ -931,6 +933,7 @@ methods_keep_quoted_from_dead_code: {
|
|||||||
evaluate: true,
|
evaluate: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
|
unsafe_methods: true,
|
||||||
}
|
}
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
@@ -964,3 +967,88 @@ issue_2256: {
|
|||||||
g.keep = g.g;
|
g.keep = g.g;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2321: {
|
||||||
|
options = {
|
||||||
|
ecma: 6,
|
||||||
|
unsafe_methods: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var f = {
|
||||||
|
foo: function(){ console.log("foo") },
|
||||||
|
bar() { console.log("bar") }
|
||||||
|
};
|
||||||
|
var foo = new f.foo();
|
||||||
|
var bar = f.bar();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var f = {
|
||||||
|
foo: function() {
|
||||||
|
console.log("foo");
|
||||||
|
},
|
||||||
|
bar() {
|
||||||
|
console.log("bar");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var foo = new f.foo();
|
||||||
|
var bar = f.bar();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_methods_regex: {
|
||||||
|
options = {
|
||||||
|
ecma: 6,
|
||||||
|
unsafe_methods: /^[A-Z1]/,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var f = {
|
||||||
|
123: function(){ console.log("123") },
|
||||||
|
foo: function(){ console.log("foo") },
|
||||||
|
bar() { console.log("bar") },
|
||||||
|
Baz: function(){ console.log("baz") },
|
||||||
|
BOO: function(){ console.log("boo") },
|
||||||
|
null: function(){ console.log("null") },
|
||||||
|
undefined: function(){ console.log("undefined") },
|
||||||
|
};
|
||||||
|
f[123]();
|
||||||
|
new f.foo();
|
||||||
|
f.bar();
|
||||||
|
f.Baz();
|
||||||
|
f.BOO();
|
||||||
|
new f.null();
|
||||||
|
new f.undefined();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var f = {
|
||||||
|
123() { console.log("123") },
|
||||||
|
foo: function(){ console.log("foo") },
|
||||||
|
bar() { console.log("bar"); },
|
||||||
|
Baz() { console.log("baz") },
|
||||||
|
BOO() { console.log("boo") },
|
||||||
|
null: function(){ console.log("null") },
|
||||||
|
undefined: function(){ console.log("undefined") },
|
||||||
|
};
|
||||||
|
f[123]();
|
||||||
|
new f.foo();
|
||||||
|
f.bar();
|
||||||
|
f.Baz();
|
||||||
|
f.BOO();
|
||||||
|
new f.null();
|
||||||
|
new f.undefined();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"123",
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"baz",
|
||||||
|
"boo",
|
||||||
|
"null",
|
||||||
|
"undefined",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|||||||
@@ -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,89 @@ 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"
|
||||||
|
}
|
||||||
|
|
||||||
|
method_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
console.log(new class {
|
||||||
|
a() {
|
||||||
|
a = 2;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}().a(), a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
console.log(new class {
|
||||||
|
a() {
|
||||||
|
a = 2;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}().a(), a);
|
||||||
|
}
|
||||||
|
expect_stdout: "2 2"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
method_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var A = 1;
|
||||||
|
var B = class {
|
||||||
|
c() {
|
||||||
|
console.log(A);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
new B().c();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
new class {
|
||||||
|
c() {
|
||||||
|
console.log(1);
|
||||||
|
}
|
||||||
|
}().c();
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
issue_2090_1: {
|
issue_2090_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -2652,3 +2733,321 @@ 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: {
|
||||||
|
// TODO make this work on harmony
|
||||||
|
var o = { a: 1 };
|
||||||
|
for (var i = o.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: {
|
||||||
|
// TODO make this work on harmony
|
||||||
|
var a = [ 1, 2, 3 ];
|
||||||
|
for (var b in a)
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
array_forof_1: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = [ 1, 2, 3 ];
|
||||||
|
for (var b of a)
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
// TODO make this work on harmony
|
||||||
|
var a = [ 1, 2, 3 ];
|
||||||
|
for (var b of a)
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
]
|
||||||
|
node_version: ">=0.12"
|
||||||
|
}
|
||||||
|
|
||||||
|
array_forof_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = [];
|
||||||
|
for (var b of [ 1, 2, 3 ])
|
||||||
|
a.push(b);
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = [];
|
||||||
|
for (var b of [ 1, 2, 3 ])
|
||||||
|
a.push(b);
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
expect_stdout: "3"
|
||||||
|
node_version: ">=0.12"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var uglify = require("../node");
|
var uglify = require("../node");
|
||||||
|
|
||||||
describe("Export", function() {
|
describe("Export/Import", function() {
|
||||||
it("Should parse export directives", function() {
|
it("Should parse export directives", function() {
|
||||||
var inputs = [
|
var inputs = [
|
||||||
['export * from "a.js"', ['*'], "a.js"],
|
['export * from "a.js"', ['*'], "a.js"],
|
||||||
@@ -36,4 +36,22 @@ describe("Export", function() {
|
|||||||
assert.equal(st.module_name.value, filename);
|
assert.equal(st.module_name.value, filename);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should not parse invalid uses of export", function() {
|
||||||
|
assert.equal(uglify.minify("export").error.message, "Unexpected token: eof (undefined)");
|
||||||
|
assert.equal(uglify.minify("export;").error.message, "Unexpected token: punc (;)");
|
||||||
|
assert.equal(uglify.minify("export();").error.message, "Unexpected token: keyword (export)");
|
||||||
|
assert.equal(uglify.minify("export(1);").error.message, "Unexpected token: keyword (export)");
|
||||||
|
assert.equal(uglify.minify("var export;").error.message, "Name expected");
|
||||||
|
assert.equal(uglify.minify("var export = 1;").error.message, "Name expected");
|
||||||
|
assert.equal(uglify.minify("function f(export){}").error.message, "Invalid function parameter");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should not parse invalid uses of import", function() {
|
||||||
|
assert.equal(uglify.minify("import").error.message, "Unexpected token: eof (undefined)");
|
||||||
|
assert.equal(uglify.minify("import;").error.message, "Unexpected token: punc (;)");
|
||||||
|
assert.equal(uglify.minify("var import;").error.message, "Unexpected token: import");
|
||||||
|
assert.equal(uglify.minify("var import = 1;").error.message, "Unexpected token: import");
|
||||||
|
assert.equal(uglify.minify("function f(import){}").error.message, "Unexpected token: name (import)");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -73,6 +73,13 @@ 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 super(){}").error.message, "Unexpected token: name (super)");
|
||||||
|
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};';
|
||||||
|
|||||||
Reference in New Issue
Block a user