Compare commits

...

140 Commits

Author SHA1 Message Date
Alex Lam S.L
fdee083465 v3.4.3 2018-07-02 06:03:18 +00:00
alexlamsl
5ffc17d4aa fix corner case in unused 2018-07-01 14:34:42 +08:00
alexlamsl
6aa750010f update dependencies
- acorn@5.7.1
- commander@2.16.0
2018-07-01 01:49:43 +08:00
Alex Lam S.L
76df77c08c implement directives (#3203)
fixes #3166
2018-06-28 18:16:49 +08:00
Alex Lam S.L
957d5537a8 improve unsafe comparisons (#3200) 2018-06-28 03:46:19 +08:00
Alex Lam S.L
88c8f4e363 v3.4.2 2018-06-26 01:29:48 +08:00
Alex Lam S.L
ab36b9b10a fix corner case in ie8 (#3198)
fixes #3197
2018-06-24 04:00:36 +08:00
Alex Lam S.L
28330913d8 improve mocha tests (#3195) 2018-06-24 04:00:36 +08:00
Alex Lam S.L
766a4147d4 enhance arguments (#3193)
fixes #3192
2018-06-24 04:00:21 +08:00
Alex Lam S.L
915c7e234d v3.4.1 2018-06-19 18:35:48 +00:00
Alex Lam S.L
e54ddcbb8a fix corner cases in properties (#3189)
fixes #3188
2018-06-19 18:20:11 +08:00
Alex Lam S.L
9e19e63551 general clean-ups (#3175) 2018-06-06 17:50:56 +08:00
Alex Lam S.L
bce7ee5f6a v3.4.0 2018-06-02 05:57:10 +00:00
Jiavan
b39043f3ab re-introduce enclose (#3163)
fixes #2443
2018-06-01 16:47:11 +08:00
Alex Lam S.L
caf96acb08 handle asynchronous test failures (#3164) 2018-05-31 20:21:39 +08:00
Alex Lam S.L
c76749084b update JetStream URL (#3165) 2018-05-31 16:23:49 +08:00
Alex Lam S.L
5843494ee2 v3.3.28 2018-05-29 12:25:42 +00:00
Alex Lam S.L
efa21ae3e6 fix corner case in reduce_vars (#3151) 2018-05-26 05:45:44 +08:00
Alex Lam S.L
24d9633a35 fix corner cases with eval() (#3147)
fixes #3146
2018-05-24 14:29:30 +08:00
Alex Lam S.L
7963b96681 augment tests for inline source maps (#3145) 2018-05-24 02:37:51 +08:00
Alex Lam S.L
8c62d854ce augment tests for RegExp (#3144) 2018-05-23 17:24:13 +08:00
Alex Lam S.L
69931574e1 v3.3.27 2018-05-22 17:09:12 +00:00
Alex Lam S.L
b5af8a1914 fix corner case in reduce_vars (#3141)
fixes #3140
2018-05-21 15:53:51 +08:00
Alex Lam S.L
c14d09ba84 v3.3.26 2018-05-20 17:32:32 +00:00
Alex Lam S.L
4fc39d8dad fix corner case in collapse_vars (#3139) 2018-05-19 05:45:14 +08:00
exvisory
0b7c70f726 Update README.md to clarify --source-map filename option (#3137)
Clarify that the --source-map filename option does NOT change the source map output filename but does set the 'file' attribute within the output source map. This was already documented in the API section of the README so I just copied that to the CLI options section, and a fragment to the CLI summary.
2018-05-18 15:50:36 +08:00
Alex Lam S.L
f72d3029dd v3.3.25 2018-05-12 23:50:40 +00:00
Alex Lam S.L
1a0d6edc81 remove colors dependency (#3133) 2018-05-13 07:50:02 +08:00
Alex Lam S.L
7b59b2f5b2 replace mocha dependency (#3131) 2018-05-11 20:15:34 +08:00
Alex Lam S.L
7bc7704edf fix corner case in reduce_vars (#3129) 2018-05-10 18:45:20 +08:00
Alex Lam S.L
14e712ee80 fix corner case in call binding (#3128)
fixes #3127
2018-05-10 06:16:35 +08:00
Alex Lam S.L
f83adcc995 v3.3.24 2018-05-07 20:17:34 +00:00
Alex Lam S.L
df8a99439a fix various corner cases (#3126)
- augment ufuzz/reminify test options

fixes #3125
2018-05-07 07:36:25 +08:00
Alex Lam S.L
6b91d12ec3 fix corner case in reduce_vars (#3124) 2018-05-06 16:42:35 +08:00
Alex Lam S.L
f37b91879f fix various corner cases (#3123) 2018-05-05 13:17:50 +08:00
Alex Lam S.L
d835c72c80 speed up collapse_vars (#3119) 2018-05-04 18:38:13 +08:00
Alex Lam S.L
c4cebb4b01 fix reduce_vars on nested invocations (#3118) 2018-05-04 06:05:38 +08:00
Alex Lam S.L
d51a00a450 compress AST_Sequence within AST_Call (#3117) 2018-05-03 19:14:56 +08:00
Alex Lam S.L
fc0f168a0c better fix for #3113 (#3115) 2018-05-03 15:51:51 +08:00
Alex Lam S.L
a0ca595c2c fix TreeWalker scan order (#3114)
fixes #3113
2018-05-03 00:27:45 +08:00
Alex Lam S.L
1a314e9f60 improve reduce_vars (#3112)
fixes #3110
2018-05-02 15:11:45 +08:00
Alex Lam S.L
6fcbd5e217 v3.3.23 2018-04-28 17:14:52 +00:00
Alex Lam S.L
22cea023d1 improve numeral compression (#3108) 2018-04-28 02:47:49 +08:00
Alex Lam S.L
70d4477e05 workaround vm context issue in node-chakracore (#3106) 2018-04-27 07:40:34 +08:00
Alex Lam S.L
838f837379 improve general performance (#3104) 2018-04-27 04:30:29 +08:00
Alex Lam S.L
82a8b6f612 improve collapse_vars (#3103) 2018-04-26 19:26:01 +08:00
Alex Lam S.L
69fc7ca8da workaround test failures in Node.js 10 (#3102) 2018-04-26 17:44:37 +08:00
Alex Lam S.L
0a79496e0a workaround stack overflow in ChakraCore (#3101) 2018-04-26 15:02:17 +08:00
Alex Lam S.L
9e87edfc2e better fix for #2506 (#3099) 2018-04-25 04:46:07 +08:00
Alex Lam S.L
27211cf2d5 handle RHS side-effects in collapse_vars (#3097)
fixes #3096
2018-04-24 20:31:50 +08:00
Alex Lam S.L
b5ce199711 improve max_line_len (#3095)
fixes #304
2018-04-24 15:19:45 +08:00
Alex Lam S.L
c71ed91e63 update AST documentation (#3094)
fixes #2622
2018-04-24 14:39:12 +08:00
alexlamsl
f7545d0f1c remove unsupported platform 2018-04-24 13:32:54 +08:00
Alex Lam S.L
59eecb6bf5 v3.3.22 2018-04-20 19:50:16 +00:00
Alex Lam S.L
d83c6490ab fix corner case in strip_func_ids() (#3090) 2018-04-19 04:51:42 +08:00
Alex Lam S.L
7362f57966 improve performance when handling unused variables in collapse_vars (#3084)
fixes #3082
2018-04-15 12:38:31 +08:00
Alex Lam S.L
eaa2c1f6af v3.3.21 2018-04-12 07:08:53 +00:00
Alex Lam S.L
6a916523d4 fix inline of catch-scoped variables (#3077)
fixes #3076
2018-04-11 15:44:43 +08:00
Alex Lam S.L
ba7069d52b suppress hoist_props for embedded assignments (#3074) 2018-04-11 05:19:16 +08:00
Alex Lam S.L
4dd7d0e39b extend hoist_props (#3073)
- handle `AST_Assign` the same way as `AST_VarDef`
- inject `AST_Var` as succeeding statement

fixes #3071
2018-04-11 02:48:15 +08:00
Alex Lam S.L
90199d0a96 extend join_vars on object assignments (#3072) 2018-04-11 01:35:42 +08:00
Alex Lam S.L
b82fd0ad41 handle flow control in loops with reduce_vars (#3069)
fixes #3068
2018-04-10 06:51:03 +08:00
Alex Lam S.L
183da16896 handle pure_funcs under inline & reduce_vars correctly (#3066)
fixes #3065
2018-04-10 02:46:38 +08:00
Alex Lam S.L
87857b0f1b v3.3.20 2018-04-08 03:06:15 +08:00
Alex Lam S.L
e5f6a88233 fix corner case in reuse of mangle options (#3062) 2018-04-08 02:29:37 +08:00
Alex Lam S.L
8d0b00317e v3.3.19 2018-04-07 22:27:55 +08:00
Alex Lam S.L
db49daf365 mangle Object.defineProperty() (#3059)
fixes #869
2018-04-06 17:10:36 +08:00
Alex Lam S.L
923deeff35 support inline source map from multiple files (#3058)
fixes #145
2018-04-06 16:04:15 +08:00
Alex Lam S.L
0b62a28b47 improve usability of includeSources (#3057)
Exclude source contents from input source map if `includeSources=false`

fixes #3041
2018-04-06 13:32:26 +08:00
Alex Lam S.L
44116c6d2b fix AST corruption during inline of simple return (#3056)
fixes #3054
2018-04-06 05:39:07 +08:00
Alex Lam S.L
b5bab254ce speed up has_parens() (take 2) (#3052)
fixes #3050
2018-04-05 04:12:04 +08:00
Alex Lam S.L
81603ecd15 improve performance through makePredicate() (#3048) 2018-04-03 15:15:01 +08:00
Alex Lam S.L
e67553fa55 fix tree traversal on AST_Do (#3047)
fixes #3046
2018-04-02 22:31:23 +08:00
Alex Lam S.L
fcf542f262 v3.3.18 2018-04-02 04:26:28 +00:00
b-fuze
8adfc29f91 Don't load source map until the JS source is fully received (#3040) 2018-03-31 20:26:40 +09:00
Alex Lam S.L
02f47e1713 give sensible error against invalid input source map (#3044) 2018-03-31 18:48:20 +09:00
Alex Lam S.L
07f64d4050 fix escape analysis on AST_New (#3043)
fixes #3042
2018-03-31 15:03:46 +09:00
Alex Lam S.L
6982a0554c v3.3.17 2018-03-31 04:13:45 +00:00
Alex Lam S.L
fa3250199a mangle unused nested AST_SymbolCatch correctly (#3038)
fixes #3035
2018-03-30 16:23:09 +09:00
Alex Lam S.L
06b9894c19 handle modifications to this correctly (#3036)
fixes #3032
2018-03-30 15:07:36 +09:00
Alex Lam S.L
9f9db504d7 improve test for #3023 (#3031) 2018-03-29 23:36:40 +09:00
Alex Lam S.L
82ae95c334 improve source map granularity (#3030)
fixes #3023
2018-03-29 14:47:55 +09:00
Fábio Santos
9a5e2052c4 fix extra regex slash when going through mozilla AST I/O (#3025)
This relates to #1929, but in the context of mozilla AST input/output.
2018-03-27 03:22:01 +09:00
Alex Lam S.L
b1410be443 speed up has_parens() (#3014) 2018-03-24 04:05:28 +08:00
Alex Lam S.L
12985d86c2 fix corner case in hoist_props (#3022)
fixes #3021
2018-03-23 07:27:35 +08:00
Alex Lam S.L
49bfc6b555 improve performance (#3020)
- replace `find_if()` with `all()` wherever possible
- move ESTree-specific logic out of `figure_out_scope()`
2018-03-23 03:43:52 +08:00
Alex Lam S.L
d1c6bb8c7c fix nested inline within loop (#3019)
fixes #3018
2018-03-23 02:31:59 +08:00
Alex Lam S.L
5c169615a8 fix corner case in inline (#3017)
fixes #3016
2018-03-22 23:46:26 +08:00
Alex Lam S.L
73d77f4f64 v3.3.16 2018-03-19 06:53:51 +00:00
Alex Lam S.L
ccf0e2ef4f extend fuzzy RHS folding (#3006)
- `a = []; if (1) x();` => `if (a = []) x();`
2018-03-17 03:10:21 +08:00
Alex Lam S.L
20ca0f5906 improve truthy compression (#3009) 2018-03-16 06:12:59 +08:00
Alex Lam S.L
b29d435bb5 refactor brackets to braces (#3005) 2018-03-15 15:46:45 +08:00
Alex Lam S.L
90585e29c2 v3.3.15 2018-03-14 16:45:38 +00:00
Alex Lam S.L
d8fc281915 update dependencies (#3002)
acorn 5.5.3
commander 2.15.0

Miscellaneous
- drop unmaintained package from README
2018-03-14 15:54:41 +08:00
Alex Lam S.L
188c39e8d5 retain comments within brackets (#2999)
fixes #2998
2018-03-13 18:44:21 +08:00
Alex Lam S.L
5429234138 preserve non-constant value assignments with modifications (#2997)
fixes #2995
2018-03-13 17:35:34 +08:00
Alex Lam S.L
b9f72a4a81 handle case correctly under reduce_vars (#2993)
fixes #2992
2018-03-11 15:54:43 +08:00
Alex Lam S.L
fc6ebd04a5 preserve case when inline_script (#2991)
fixes #2989
2018-03-11 05:11:12 +08:00
Alex Lam S.L
7e00a12741 v3.3.14 2018-03-10 13:20:14 +00:00
Alex Lam S.L
10b3752b1e fix mangle of AST_SymbolLambda under ie8 (#2978)
fixes #2976
2018-03-07 17:20:38 +08:00
Alex Lam S.L
fe51a91395 handle negated constants correctly in collapse_vars (#2975)
fixes #2974
2018-03-06 00:45:58 +08:00
Alex Lam S.L
951d87ca94 v3.3.13 2018-03-04 07:38:49 +00:00
Alex Lam S.L
798fc21530 improve test/run-test.js performance (#2971)
- allow reuse of contextified sandbox
- minimise bottleneck from `vm.createContext()`
2018-03-04 04:50:00 +08:00
Alex Lam S.L
a75a046abb compress arguments[index] (#2967)
- always replace with existing parameter
- only introduce new parameter if `keep_fargs` is disabled
2018-03-02 11:22:09 +08:00
Alex Lam S.L
38f2b4579f fix value reference caching in evaluate (#2969)
fixes #2968
2018-03-02 04:04:29 +08:00
Alex Lam S.L
56e2a369d0 enhance conditionals (#2966)
- `x ? (y, w) : (z, w)` => `x ? y : z, w`
2018-02-28 23:34:48 +08:00
Alex Lam S.L
0daa199fa8 migrate safe transformations out of unsafe_comps (#2962)
fixes #2959
2018-02-28 22:02:24 +08:00
Alex Lam S.L
73e98dcda4 drop side_effects-free return values (#2965) 2018-02-28 19:59:19 +08:00
Alex Lam S.L
36bca6934d enhance collapse_vars (#2952)
- `a = b, b` => `a = b`
- `a.b = c, c()` => `(a.b = c)()`
2018-02-28 15:19:32 +08:00
Alex Lam S.L
ace5811691 drop lone "use strict" in function body (#2963)
fixes #2961
2018-02-26 15:22:52 +08:00
Dan
ba7bad0dbd show benchmark subtotal (#2960)
At the end of the benchmark, sums of the input, output and
gzip values are shown, such as:

    Subtotal

    Original: 7785102 bytes
    Uglified: 2283862 bytes
    GZipped:  662354 bytes
2018-02-26 11:46:26 +08:00
Alex Lam S.L
b8b2ac5230 improve fix for #2954 (#2958) 2018-02-26 03:14:22 +08:00
Alex Lam S.L
ea2359381b fix collapse_vars on nested exception (#2955)
fixes #2954
2018-02-25 15:39:00 +08:00
Alex Lam S.L
52de64cf16 deduplicate parenthesis around object and function literals (#2953) 2018-02-25 02:14:33 +08:00
Alex Lam S.L
455790202a minor clean-ups (#2951) 2018-02-24 02:24:47 +08:00
Alex Lam S.L
f40f5eb228 improve mangle (#2948) 2018-02-23 23:51:49 +08:00
Alex Lam S.L
604caa09e7 v3.3.12 2018-02-22 08:14:29 +00:00
Alex Lam S.L
29a71d3aae more tests for #2938 (#2940) 2018-02-21 04:19:42 +08:00
Alex Lam S.L
39a907bde3 workaround pure_getters=true when dropping unused assignments (#2939)
fixes #2938
2018-02-20 17:38:40 +08:00
Alex Lam S.L
70474310f3 improve unsafe evaluate of function (#2936)
Miscellaneous
- simplify `run_code()` hack
2018-02-19 18:47:02 +08:00
Alex Lam S.L
b5f0f4f3a1 reduce false positives from object literals (#2935) 2018-02-19 06:21:07 +08:00
Alex Lam S.L
2905fd625a reduce false positives from labels (#2934) 2018-02-19 03:55:33 +08:00
Alex Lam S.L
4facd94029 reduce false positives from noop (#2933) 2018-02-19 01:15:05 +08:00
Alex Lam S.L
4b5993ff15 fix crash in may_throw() (#2932)
fixes #2931
2018-02-18 21:51:27 +08:00
Alex Lam S.L
2351a672ea fix dead_code on exceptional return (#2930)
fixes #2929
2018-02-18 04:36:00 +08:00
Alex Lam S.L
4a528c469c reduce false positives from function.toString() (#2928) 2018-02-18 02:13:26 +08:00
Alex Lam S.L
82d1ef0242 fix unsafe evaluate of function property (#2927)
fixes #2926
2018-02-17 21:33:36 +08:00
Alex Lam S.L
7fdd2082a6 drop unused "class" definition IIFEs (#2923)
fixes #805
2018-02-17 05:11:31 +08:00
Alex Lam S.L
e529f54e90 reduce function-related false positives (#2925) 2018-02-17 04:35:03 +08:00
Alex Lam S.L
d626e9bf19 improve inline efficiency (#2924) 2018-02-17 02:37:13 +08:00
Alex Lam S.L
a2a9459684 fix unsafe evaluate of AST_Function (#2920)
fixes #2919
2018-02-16 17:21:46 +08:00
Alex Lam S.L
a3dfeea144 v3.3.11 2018-02-15 19:24:35 +00:00
Alex Lam S.L
d316fb139d fix unsafe evaluate on type-converting operators (#2917)
fixes #2916
2018-02-14 16:48:47 +08:00
Alex Lam S.L
83d8aa8b12 fix collapse_vars within loops (#2915)
fixes #2914
2018-02-14 05:15:52 +08:00
Alex Lam S.L
4f1c12b6fd report options upon reminify input error (#2911) 2018-02-13 07:29:39 +08:00
Alex Lam S.L
d8e0e34354 collapse within unary expressions (#2910) 2018-02-13 07:10:37 +08:00
Alex Lam S.L
0c4f315c02 fix corner case in collapse_vars (#2909)
fixes #2908
2018-02-13 01:41:22 +08:00
Alex Lam S.L
0809699bdc simplify do-while into for (#2907)
fixes #2904
2018-02-12 23:28:28 +08:00
Alex Lam S.L
2088e1c19d fix AST corruption due to collapse_vars & inline (#2899)
fixes #2898
2018-02-09 06:54:37 +08:00
Alex Lam S.L
bf1d47180c fix join_vars on property accessors (#2895)
fixes #2893
2018-02-09 01:52:39 +08:00
128 changed files with 9863 additions and 3988 deletions

View File

@@ -1,11 +1,7 @@
**Bug report or feature request?** **Bug report or feature request?**
<!-- Note: sub-optimal but correct code is not a bug --> <!-- Note: sub-optimal but correct code is not a bug -->
**ES5 or ES6+ input?**
<!-- Note: for ES6 see: https://github.com/mishoo/UglifyJS2/tree/harmony#harmony -->
**Uglify version (`uglifyjs -V`)** **Uglify version (`uglifyjs -V`)**
**JavaScript input** **JavaScript input**
@@ -24,6 +20,6 @@
**JavaScript output or error produced.** **JavaScript output or error produced.**
<!-- <!--
Note: `uglify-js` only supports ES5. Note: `uglify-js` only supports JavaScript.
Those wishing to minify ES6 should use `uglify-es`. Those wishing to minify ES6+ should transpile first.
--> -->

View File

@@ -6,9 +6,8 @@ UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.
#### Note: #### Note:
- **`uglify-js@3` has a simplified [API](#api-reference) and [CLI](#command-line-usage) that is not backwards compatible with [`uglify-js@2`](https://github.com/mishoo/UglifyJS2/tree/v2.x)**. - **`uglify-js@3` has a simplified [API](#api-reference) and [CLI](#command-line-usage) that is not backwards compatible with [`uglify-js@2`](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
- **Documentation for UglifyJS `2.x` releases can be found [here](https://github.com/mishoo/UglifyJS2/tree/v2.x)**. - **Documentation for UglifyJS `2.x` releases can be found [here](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
- `uglify-js` only supports ECMAScript 5 (ES5). - `uglify-js` only supports JavaScript (ECMAScript 5).
- Those wishing to minify - To minify ECMAScript 2015 or above, transpile using tools like [Babel](https://babeljs.io/).
ES2015+ (ES6+) should use the `npm` package [**uglify-es**](https://github.com/mishoo/UglifyJS2/tree/harmony).
Install Install
------- -------
@@ -105,6 +104,8 @@ a double dash to prevent input files being used as option arguments:
sequences. sequences.
--config-file <file> Read `minify()` options from JSON file. --config-file <file> Read `minify()` options from JSON file.
-d, --define <expr>[=value] Global definitions. -d, --define <expr>[=value] Global definitions.
-e, --enclose [arg[:value]] Embed everything in a big function, with configurable
argument(s) & value(s).
--ie8 Support non-standard Internet Explorer 8. --ie8 Support non-standard Internet Explorer 8.
Equivalent to setting `ie8: true` in `minify()` Equivalent to setting `ie8: true` in `minify()`
for `compress`, `mangle` and `output` options. for `compress`, `mangle` and `output` options.
@@ -119,7 +120,8 @@ a double dash to prevent input files being used as option arguments:
JS that was generated from some other original JS that was generated from some other original
code. Specify "inline" if the source map is code. Specify "inline" if the source map is
included within the sources. included within the sources.
`filename` Name and/or location of the output source. `filename` Filename and/or location of the output source
(sets `file` attribute in source map).
`includeSources` Pass this flag if you want to include `includeSources` Pass this flag if you want to include
the content of source files in the the content of source files in the
source map as sourcesContent property. source map as sourcesContent property.
@@ -150,7 +152,9 @@ debugging your compressed JavaScript. To get a source map, pass
Additional options: Additional options:
- `--source-map "filename='<NAME>'"` to specify the name of the source map. - `--source-map "filename='<NAME>'"` to specify the name of the source map. The value of
`filename` is only used to set `file` attribute (see [the spec][sm-spec])
in source map file.
- `--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.
@@ -598,6 +602,9 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
## Compress options ## Compress options
- `arguments` (default: `true`) -- replace `arguments[index]` with function
parameter name whenever possible.
- `booleans` (default: `true`) -- various optimizations for boolean context, - `booleans` (default: `true`) -- various optimizations for boolean context,
for example `!!a ? b : c → a ? b : c` for example `!!a ? b : c → a ? b : c`
@@ -605,14 +612,16 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
side effects permitting. side effects permitting.
- `comparisons` (default: `true`) -- apply certain optimizations to binary nodes, - `comparisons` (default: `true`) -- apply certain optimizations to binary nodes,
e.g. `!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary e.g. `!(a <= b) → a > b`, attempts to negate binary nodes, e.g.
nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
- `conditionals` (default: `true`) -- apply optimizations for `if`-s and conditional - `conditionals` (default: `true`) -- apply optimizations for `if`-s and conditional
expressions expressions
- `dead_code` (default: `true`) -- remove unreachable code - `dead_code` (default: `true`) -- remove unreachable code
- `directives` (default: `true`) -- remove redundant or non-standard directives
- `drop_console` (default: `false`) -- Pass `true` to discard calls to - `drop_console` (default: `false`) -- Pass `true` to discard calls to
`console.*` functions. If you wish to drop a specific function call `console.*` functions. If you wish to drop a specific function call
such as `console.info` and/or retain side effects from function arguments such as `console.info` and/or retain side effects from function arguments
@@ -683,7 +692,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
pass `pure_funcs: [ 'Math.floor' ]` to let it know that this pass `pure_funcs: [ 'Math.floor' ]` to let it know that this
function won't produce any side effect, in which case the whole function won't produce any side effect, in which case the whole
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). Make sure symbols under `pure_funcs`
are also under `mangle.reserved` to avoid mangling.
- `pure_getters` (default: `"strict"`) -- If you pass `true` for - `pure_getters` (default: `"strict"`) -- If you pass `true` for
this, UglifyJS will assume that object property access this, UglifyJS will assume that object property access
@@ -730,12 +740,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `unsafe` (default: `false`) -- apply "unsafe" transformations (discussion below) - `unsafe` (default: `false`) -- apply "unsafe" transformations (discussion below)
- `unsafe_comps` (default: `false`) -- Reverse `<` and `<=` to `>` and `>=` to - `unsafe_comps` (default: `false`) -- compress expressions like `a <= b` assuming
allow improved compression. This might be unsafe when an at least one of two none of the operands can be (coerced to) `NaN`.
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_Function` (default: `false`) -- compress and mangle `Function(args, code)` - `unsafe_Function` (default: `false`) -- compress and mangle `Function(args, code)`
when both `args` and `code` are string literals. when both `args` and `code` are string literals.
@@ -826,7 +832,7 @@ can pass additional arguments that control the code output:
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`, - `braces` (default `false`) -- always insert braces 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.
@@ -838,8 +844,8 @@ can pass additional arguments that control the code output:
- `indent_start` (default `0`) -- prefix all lines by that many spaces - `indent_start` (default `0`) -- prefix all lines by that many spaces
- `inline_script` (default `false`) -- escape the slash in occurrences of - `inline_script` (default `true`) -- escape HTML comments and the slash in
`</script` in strings occurrences of `</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.
@@ -1042,8 +1048,9 @@ var result = UglifyJS.minify(ast, {
### Working with Uglify AST ### Working with Uglify AST
Transversal and transformation of the native AST can be performed through Transversal and transformation of the native AST can be performed through
[`TreeWalker`](http://lisperator.net/uglifyjs/walk) and [`TreeWalker`](https://github.com/mishoo/UglifyJS2/blob/master/lib/ast.js) and
[`TreeTransformer`](http://lisperator.net/uglifyjs/transform) respectively. [`TreeTransformer`](https://github.com/mishoo/UglifyJS2/blob/master/lib/transform.js)
respectively.
### ESTree / SpiderMonkey AST ### ESTree / SpiderMonkey AST

View File

@@ -40,14 +40,15 @@ program.option("-o, --output <file>", "Output file (default STDOUT).");
program.option("--comments [filter]", "Preserve copyright comments in the output."); program.option("--comments [filter]", "Preserve copyright comments in the output.");
program.option("--config-file <file>", "Read minify() options from JSON file."); program.option("--config-file <file>", "Read minify() options from JSON file.");
program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("define")); program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("define"));
program.option("-e, --enclose [arg[,...][:value[,...]]]", "Embed everything in a big function, with configurable argument(s) & value(s).");
program.option("--ie8", "Support non-standard Internet Explorer 8."); program.option("--ie8", "Support non-standard Internet Explorer 8.");
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name."); program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
program.option("--name-cache <file>", "File to hold mangled name mappings."); program.option("--name-cache <file>", "File to hold mangled name mappings.");
program.option("--rename", "Force symbol expansion."); program.option("--rename", "Force symbol expansion.");
program.option("--no-rename", "Disable symbol expansion."); program.option("--no-rename", "Disable symbol expansion.");
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)"); program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_source_map()); program.option("--source-map [options]", "Enable source map/specify source map options.", parse_js());
program.option("--timings", "Display operations run time on STDERR.") program.option("--timings", "Display operations run time on STDERR.");
program.option("--toplevel", "Compress and/or mangle variables in toplevel scope."); program.option("--toplevel", "Compress and/or mangle variables in toplevel scope.");
program.option("--verbose", "Print diagnostic messages."); program.option("--verbose", "Print diagnostic messages.");
program.option("--warn", "Print warning messages."); program.option("--warn", "Print warning messages.");
@@ -61,6 +62,7 @@ if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
} }
[ [
"compress", "compress",
"enclose",
"ie8", "ie8",
"mangle", "mangle",
"sourceMap", "sourceMap",
@@ -176,6 +178,11 @@ function run() {
UglifyJS.AST_Node.warn_function = function(msg) { UglifyJS.AST_Node.warn_function = function(msg) {
print_error("WARN: " + msg); print_error("WARN: " + msg);
}; };
var content = program.sourceMap && program.sourceMap.content;
if (content && content != "inline") {
print_error("INFO: Using input source map: " + content);
options.sourceMap.content = read_file(content, content);
}
if (program.timings) options.timings = true; if (program.timings) options.timings = true;
try { try {
if (program.parse) { if (program.parse) {
@@ -377,19 +384,6 @@ function parse_js(flag) {
} }
} }
function parse_source_map() {
var parse = parse_js();
return function(value, options) {
var hasContent = options && "content" in options;
var settings = parse(value, options);
if (!hasContent && settings.content && settings.content != "inline") {
print_error("INFO: Using input source map: " + settings.content);
settings.content = read_file(settings.content, settings.content);
}
return settings;
}
}
function skip_key(key) { function skip_key(key) {
return skip_keys.indexOf(key) >= 0; return skip_keys.indexOf(key) >= 0;
} }

View File

@@ -44,21 +44,21 @@
"use strict"; "use strict";
function DEFNODE(type, props, methods, base) { function DEFNODE(type, props, methods, base) {
if (arguments.length < 4) base = AST_Node; if (typeof base === "undefined") base = AST_Node;
if (!props) props = []; props = props ? props.split(/\s+/) : [];
else props = props.split(/\s+/);
var self_props = props; var self_props = props;
if (base && base.PROPS) if (base && base.PROPS) props = props.concat(base.PROPS);
props = props.concat(base.PROPS); var code = [
var code = "return function AST_" + type + "(props){ if (props) { "; "return function AST_", type, "(props){",
for (var i = props.length; --i >= 0;) { "if(props){",
code += "this." + props[i] + " = props." + props[i] + ";"; ];
} props.forEach(function(prop) {
code.push("this.", prop, "=props.", prop, ";");
});
var proto = base && new base; var proto = base && new base;
if (proto && proto.initialize || (methods && methods.initialize)) if (proto && proto.initialize || methods && methods.initialize) code.push("this.initialize();");
code += "this.initialize();"; code.push("}}");
code += "}}"; var ctor = new Function(code.join(""))();
var ctor = new Function(code)();
if (proto) { if (proto) {
ctor.prototype = proto; ctor.prototype = proto;
ctor.BASE = base; ctor.BASE = base;
@@ -71,11 +71,11 @@ function DEFNODE(type, props, methods, base) {
if (type) { if (type) {
ctor.prototype.TYPE = ctor.TYPE = type; ctor.prototype.TYPE = ctor.TYPE = type;
} }
if (methods) for (i in methods) if (HOP(methods, i)) { if (methods) for (var name in methods) if (HOP(methods, name)) {
if (/^\$/.test(i)) { if (/^\$/.test(name)) {
ctor[i.substr(1)] = methods[i]; ctor[name.substr(1)] = methods[name];
} else { } else {
ctor.prototype[i] = methods[i]; ctor.prototype[name] = methods[name];
} }
} }
ctor.DEFMETHOD = function(name, method) { ctor.DEFMETHOD = function(name, method) {
@@ -85,7 +85,7 @@ function DEFNODE(type, props, methods, base) {
exports["AST_" + type] = ctor; exports["AST_" + type] = ctor;
} }
return ctor; return ctor;
}; }
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before comments_after file raw", { var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before comments_after file raw", {
}, null); }, null);
@@ -148,7 +148,7 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
body: "[AST_Node] an expression node (should not be instanceof AST_Statement)" body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.body._walk(visitor); this.body._walk(visitor);
}); });
} }
@@ -158,19 +158,18 @@ function walk_body(node, visitor) {
var body = node.body; var body = node.body;
if (body instanceof AST_Statement) { if (body instanceof AST_Statement) {
body._walk(visitor); body._walk(visitor);
} } else body.forEach(function(node) {
else for (var i = 0, len = body.length; i < len; i++) { node._walk(visitor);
body[i]._walk(visitor); });
} }
};
var AST_Block = DEFNODE("Block", "body", { var AST_Block = DEFNODE("Block", "body", {
$documentation: "A body of statements (usually bracketed)", $documentation: "A body of statements (usually braced)",
$propdoc: { $propdoc: {
body: "[AST_Statement*] an array of statements" body: "[AST_Statement*] an array of statements"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
walk_body(this, visitor); walk_body(this, visitor);
}); });
} }
@@ -197,7 +196,7 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
label: "[AST_Label] a label definition" label: "[AST_Label] a label definition"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.label._walk(visitor); this.label._walk(visitor);
this.body._walk(visitor); this.body._walk(visitor);
}); });
@@ -233,7 +232,7 @@ var AST_DWLoop = DEFNODE("DWLoop", "condition", {
var AST_Do = DEFNODE("Do", null, { var AST_Do = DEFNODE("Do", null, {
$documentation: "A `do` statement", $documentation: "A `do` statement",
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.body._walk(visitor); this.body._walk(visitor);
this.condition._walk(visitor); this.condition._walk(visitor);
}); });
@@ -243,7 +242,7 @@ var AST_Do = DEFNODE("Do", null, {
var AST_While = DEFNODE("While", null, { var AST_While = DEFNODE("While", null, {
$documentation: "A `while` statement", $documentation: "A `while` statement",
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.condition._walk(visitor); this.condition._walk(visitor);
this.body._walk(visitor); this.body._walk(visitor);
}); });
@@ -258,7 +257,7 @@ var AST_For = DEFNODE("For", "init condition step", {
step: "[AST_Node?] the `for` update clause, or null if empty" step: "[AST_Node?] the `for` update clause, or null if empty"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
if (this.init) this.init._walk(visitor); if (this.init) this.init._walk(visitor);
if (this.condition) this.condition._walk(visitor); if (this.condition) this.condition._walk(visitor);
if (this.step) this.step._walk(visitor); if (this.step) this.step._walk(visitor);
@@ -274,7 +273,7 @@ var AST_ForIn = DEFNODE("ForIn", "init object", {
object: "[AST_Node] the object that we're looping through" object: "[AST_Node] the object that we're looping through"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.init._walk(visitor); this.init._walk(visitor);
this.object._walk(visitor); this.object._walk(visitor);
this.body._walk(visitor); this.body._walk(visitor);
@@ -288,7 +287,7 @@ var AST_With = DEFNODE("With", "expression", {
expression: "[AST_Node] the `with` expression" expression: "[AST_Node] the `with` expression"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expression._walk(visitor); this.expression._walk(visitor);
this.body._walk(visitor); this.body._walk(visitor);
}); });
@@ -314,6 +313,9 @@ var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent
if (this.functions) node.functions = this.functions.clone(); if (this.functions) node.functions = this.functions.clone();
if (this.enclosed) node.enclosed = this.enclosed.slice(); if (this.enclosed) node.enclosed = this.enclosed.slice();
return node; return node;
},
pinned: function() {
return this.uses_eval || this.uses_with;
} }
}, AST_Block); }, AST_Block);
@@ -326,12 +328,29 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
var body = this.body; var body = this.body;
var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");"; var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
wrapped_tl = parse(wrapped_tl); wrapped_tl = parse(wrapped_tl);
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ wrapped_tl = wrapped_tl.transform(new TreeTransformer(function(node) {
if (node instanceof AST_Directive && node.value == "$ORIG") { if (node instanceof AST_Directive && node.value == "$ORIG") {
return MAP.splice(body); return MAP.splice(body);
} }
})); }));
return wrapped_tl; return wrapped_tl;
},
wrap_enclose: function(args_values) {
if (typeof args_values != "string") args_values = "";
var index = args_values.indexOf(":");
if (index < 0) index = args_values.length;
var body = this.body;
return parse([
"(function(",
args_values.slice(0, index),
'){"$ORIG"})(',
args_values.slice(index + 1),
")"
].join("")).transform(new TreeTransformer(function(node) {
if (node instanceof AST_Directive && node.value == "$ORIG") {
return MAP.splice(body);
}
}));
} }
}, AST_Scope); }, AST_Scope);
@@ -343,12 +362,11 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array" uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
if (this.name) this.name._walk(visitor); if (this.name) this.name._walk(visitor);
var argnames = this.argnames; this.argnames.forEach(function(argname) {
for (var i = 0, len = argnames.length; i < len; i++) { argname._walk(visitor);
argnames[i]._walk(visitor); });
}
walk_body(this, visitor); walk_body(this, visitor);
}); });
} }
@@ -378,7 +396,7 @@ var AST_Exit = DEFNODE("Exit", "value", {
value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return" value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, this.value && function(){ return visitor._visit(this, this.value && function() {
this.value._walk(visitor); this.value._walk(visitor);
}); });
} }
@@ -398,7 +416,7 @@ var AST_LoopControl = DEFNODE("LoopControl", "label", {
label: "[AST_LabelRef?] the label, or null if none", label: "[AST_LabelRef?] the label, or null if none",
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, this.label && function(){ return visitor._visit(this, this.label && function() {
this.label._walk(visitor); this.label._walk(visitor);
}); });
} }
@@ -421,7 +439,7 @@ var AST_If = DEFNODE("If", "condition alternative", {
alternative: "[AST_Statement?] the `else` part, or null if not present" alternative: "[AST_Statement?] the `else` part, or null if not present"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.condition._walk(visitor); this.condition._walk(visitor);
this.body._walk(visitor); this.body._walk(visitor);
if (this.alternative) this.alternative._walk(visitor); if (this.alternative) this.alternative._walk(visitor);
@@ -437,7 +455,7 @@ var AST_Switch = DEFNODE("Switch", "expression", {
expression: "[AST_Node] the `switch` “discriminant”" expression: "[AST_Node] the `switch` “discriminant”"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expression._walk(visitor); this.expression._walk(visitor);
walk_body(this, visitor); walk_body(this, visitor);
}); });
@@ -458,7 +476,7 @@ var AST_Case = DEFNODE("Case", "expression", {
expression: "[AST_Node] the `case` expression" expression: "[AST_Node] the `case` expression"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expression._walk(visitor); this.expression._walk(visitor);
walk_body(this, visitor); walk_body(this, visitor);
}); });
@@ -474,7 +492,7 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", {
bfinally: "[AST_Finally?] the finally block, or null if not present" bfinally: "[AST_Finally?] the finally block, or null if not present"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
walk_body(this, visitor); walk_body(this, visitor);
if (this.bcatch) this.bcatch._walk(visitor); if (this.bcatch) this.bcatch._walk(visitor);
if (this.bfinally) this.bfinally._walk(visitor); if (this.bfinally) this.bfinally._walk(visitor);
@@ -488,7 +506,7 @@ var AST_Catch = DEFNODE("Catch", "argname", {
argname: "[AST_SymbolCatch] symbol for the exception" argname: "[AST_SymbolCatch] symbol for the exception"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.argname._walk(visitor); this.argname._walk(visitor);
walk_body(this, visitor); walk_body(this, visitor);
}); });
@@ -507,11 +525,10 @@ var AST_Definitions = DEFNODE("Definitions", "definitions", {
definitions: "[AST_VarDef*] array of variable definitions" definitions: "[AST_VarDef*] array of variable definitions"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
var definitions = this.definitions; this.definitions.forEach(function(defn) {
for (var i = 0, len = definitions.length; i < len; i++) { defn._walk(visitor);
definitions[i]._walk(visitor); });
}
}); });
} }
}, AST_Statement); }, AST_Statement);
@@ -527,7 +544,7 @@ var AST_VarDef = DEFNODE("VarDef", "name value", {
value: "[AST_Node?] initializer, or null of there's no initializer" value: "[AST_Node?] initializer, or null of there's no initializer"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.name._walk(visitor); this.name._walk(visitor);
if (this.value) this.value._walk(visitor); if (this.value) this.value._walk(visitor);
}); });
@@ -543,12 +560,11 @@ var AST_Call = DEFNODE("Call", "expression args", {
args: "[AST_Node*] array of arguments" args: "[AST_Node*] array of arguments"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
var args = this.args;
for (var i = 0, len = args.length; i < len; i++) {
args[i]._walk(visitor);
}
this.expression._walk(visitor); this.expression._walk(visitor);
this.args.forEach(function(node) {
node._walk(visitor);
});
}); });
} }
}); });
@@ -563,7 +579,7 @@ var AST_Sequence = DEFNODE("Sequence", "expressions", {
expressions: "[AST_Node*] array of expressions (at least two)" expressions: "[AST_Node*] array of expressions (at least two)"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expressions.forEach(function(node) { this.expressions.forEach(function(node) {
node._walk(visitor); node._walk(visitor);
}); });
@@ -582,7 +598,7 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
var AST_Dot = DEFNODE("Dot", null, { var AST_Dot = DEFNODE("Dot", null, {
$documentation: "A dotted property access expression", $documentation: "A dotted property access expression",
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expression._walk(visitor); this.expression._walk(visitor);
}); });
} }
@@ -591,7 +607,7 @@ var AST_Dot = DEFNODE("Dot", null, {
var AST_Sub = DEFNODE("Sub", null, { var AST_Sub = DEFNODE("Sub", null, {
$documentation: "Index-style property access, i.e. `a[\"foo\"]`", $documentation: "Index-style property access, i.e. `a[\"foo\"]`",
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expression._walk(visitor); this.expression._walk(visitor);
this.property._walk(visitor); this.property._walk(visitor);
}); });
@@ -605,7 +621,7 @@ var AST_Unary = DEFNODE("Unary", "operator expression", {
expression: "[AST_Node] expression that this unary operator applies to" expression: "[AST_Node] expression that this unary operator applies to"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expression._walk(visitor); this.expression._walk(visitor);
}); });
} }
@@ -627,7 +643,7 @@ var AST_Binary = DEFNODE("Binary", "operator left right", {
right: "[AST_Node] right-hand side expression" right: "[AST_Node] right-hand side expression"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.left._walk(visitor); this.left._walk(visitor);
this.right._walk(visitor); this.right._walk(visitor);
}); });
@@ -642,7 +658,7 @@ var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative",
alternative: "[AST_Node]" alternative: "[AST_Node]"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.condition._walk(visitor); this.condition._walk(visitor);
this.consequent._walk(visitor); this.consequent._walk(visitor);
this.alternative._walk(visitor); this.alternative._walk(visitor);
@@ -662,11 +678,10 @@ var AST_Array = DEFNODE("Array", "elements", {
elements: "[AST_Node*] array of elements" elements: "[AST_Node*] array of elements"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
var elements = this.elements; this.elements.forEach(function(element) {
for (var i = 0, len = elements.length; i < len; i++) { element._walk(visitor);
elements[i]._walk(visitor); });
}
}); });
} }
}); });
@@ -677,11 +692,10 @@ var AST_Object = DEFNODE("Object", "properties", {
properties: "[AST_ObjectProperty*] array of properties" properties: "[AST_ObjectProperty*] array of properties"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
var properties = this.properties; this.properties.forEach(function(prop) {
for (var i = 0, len = properties.length; i < len; i++) { prop._walk(visitor);
properties[i]._walk(visitor); });
}
}); });
} }
}); });
@@ -693,7 +707,7 @@ var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
value: "[AST_Node] property value. For getters and setters this is an AST_Accessor." value: "[AST_Node] property value. For getters and setters this is an AST_Accessor."
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.value._walk(visitor); this.value._walk(visitor);
}); });
} }
@@ -820,12 +834,12 @@ var AST_NaN = DEFNODE("NaN", null, {
var AST_Undefined = DEFNODE("Undefined", null, { var AST_Undefined = DEFNODE("Undefined", null, {
$documentation: "The `undefined` value", $documentation: "The `undefined` value",
value: (function(){}()) value: function(){}()
}, AST_Atom); }, AST_Atom);
var AST_Hole = DEFNODE("Hole", null, { var AST_Hole = DEFNODE("Hole", null, {
$documentation: "A hole in an array", $documentation: "A hole in an array",
value: (function(){}()) value: function(){}()
}, AST_Atom); }, AST_Atom);
var AST_Infinity = DEFNODE("Infinity", null, { var AST_Infinity = DEFNODE("Infinity", null, {
@@ -853,11 +867,11 @@ function TreeWalker(callback) {
this.visit = callback; this.visit = callback;
this.stack = []; this.stack = [];
this.directives = Object.create(null); this.directives = Object.create(null);
}; }
TreeWalker.prototype = { TreeWalker.prototype = {
_visit: function(node, descend) { _visit: function(node, descend) {
this.push(node); this.push(node);
var ret = this.visit(node, descend ? function(){ var ret = this.visit(node, descend ? function() {
descend.call(node); descend.call(node);
} : noop); } : noop);
if (!ret && descend) { if (!ret && descend) {
@@ -916,5 +930,25 @@ TreeWalker.prototype = {
|| node instanceof AST_Break && x instanceof AST_Switch) || node instanceof AST_Break && x instanceof AST_Switch)
return x; return x;
} }
},
in_boolean_context: function() {
var self = this.self();
for (var i = 0, p; p = this.parent(i); i++) {
if (p instanceof AST_SimpleStatement
|| p instanceof AST_Conditional && p.condition === self
|| p instanceof AST_DWLoop && p.condition === self
|| p instanceof AST_For && p.condition === self
|| p instanceof AST_If && p.condition === self
|| p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
return true;
}
if (p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")
|| p instanceof AST_Conditional
|| p.tail_node() === self) {
self = p;
} else {
return false;
}
}
} }
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -7,15 +7,23 @@ var to_base64 = typeof btoa == "undefined" ? function(str) {
return new Buffer(str).toString("base64"); return new Buffer(str).toString("base64");
} : btoa; } : btoa;
function read_source_map(code) { function read_source_map(name, code) {
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code); var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
if (!match) { if (!match) {
AST_Node.warn("inline source map not found"); AST_Node.warn("inline source map not found: " + name);
return null; return null;
} }
return to_ascii(match[2]); return to_ascii(match[2]);
} }
function parse_source_map(content) {
try {
return JSON.parse(content);
} catch (ex) {
throw new Error("invalid input source map: " + content);
}
}
function set_shorthand(name, options, keys) { function set_shorthand(name, options, keys) {
if (options[name]) { if (options[name]) {
keys.forEach(function(key) { keys.forEach(function(key) {
@@ -47,6 +55,7 @@ function minify(files, options) {
try { try {
options = defaults(options, { options = defaults(options, {
compress: {}, compress: {},
enclose: false,
ie8: false, ie8: false,
keep_fnames: false, keep_fnames: false,
mangle: {}, mangle: {},
@@ -113,7 +122,7 @@ function minify(files, options) {
}; };
} }
if (timings) timings.parse = Date.now(); if (timings) timings.parse = Date.now();
var toplevel; var source_maps, toplevel;
if (files instanceof AST_Toplevel) { if (files instanceof AST_Toplevel) {
toplevel = files; toplevel = files;
} else { } else {
@@ -122,13 +131,23 @@ function minify(files, options) {
} }
options.parse = options.parse || {}; options.parse = options.parse || {};
options.parse.toplevel = null; options.parse.toplevel = null;
var source_map_content = options.sourceMap && options.sourceMap.content;
if (typeof source_map_content == "string" && source_map_content != "inline") {
source_map_content = parse_source_map(source_map_content);
}
source_maps = source_map_content && Object.create(null);
for (var name in files) if (HOP(files, name)) { for (var name in files) if (HOP(files, name)) {
options.parse.filename = name; options.parse.filename = name;
options.parse.toplevel = parse(files[name], options.parse); options.parse.toplevel = parse(files[name], options.parse);
if (options.sourceMap && options.sourceMap.content == "inline") { if (source_maps) {
if (Object.keys(files).length > 1) if (source_map_content == "inline") {
throw new Error("inline source map only works with singular input"); var inlined_content = read_source_map(name, files[name]);
options.sourceMap.content = read_source_map(files[name]); if (inlined_content) {
source_maps[name] = parse_source_map(inlined_content);
}
} else {
source_maps[name] = source_map_content;
}
} }
} }
toplevel = options.parse.toplevel; toplevel = options.parse.toplevel;
@@ -139,6 +158,9 @@ function minify(files, options) {
if (options.wrap) { if (options.wrap) {
toplevel = toplevel.wrap_commonjs(options.wrap); toplevel = toplevel.wrap_commonjs(options.wrap);
} }
if (options.enclose) {
toplevel = toplevel.wrap_enclose(options.enclose);
}
if (timings) timings.rename = Date.now(); if (timings) timings.rename = Date.now();
if (options.rename) { if (options.rename) {
toplevel.figure_out_scope(options.mangle); toplevel.figure_out_scope(options.mangle);
@@ -150,7 +172,6 @@ function minify(files, options) {
if (options.mangle) toplevel.figure_out_scope(options.mangle); if (options.mangle) toplevel.figure_out_scope(options.mangle);
if (timings) timings.mangle = Date.now(); if (timings) timings.mangle = Date.now();
if (options.mangle) { if (options.mangle) {
base54.reset();
toplevel.compute_char_frequency(options.mangle); toplevel.compute_char_frequency(options.mangle);
toplevel.mangle_names(options.mangle); toplevel.mangle_names(options.mangle);
} }
@@ -165,12 +186,9 @@ function minify(files, options) {
} }
if (!HOP(options.output, "code") || options.output.code) { if (!HOP(options.output, "code") || options.output.code) {
if (options.sourceMap) { if (options.sourceMap) {
if (typeof options.sourceMap.content == "string") {
options.sourceMap.content = JSON.parse(options.sourceMap.content);
}
options.output.source_map = SourceMap({ options.output.source_map = SourceMap({
file: options.sourceMap.filename, file: options.sourceMap.filename,
orig: options.sourceMap.content, orig: source_maps,
root: options.sourceMap.root root: options.sourceMap.root
}); });
if (options.sourceMap.includeSources) { if (options.sourceMap.includeSources) {
@@ -179,6 +197,8 @@ function minify(files, options) {
} else for (var name in files) if (HOP(files, name)) { } else for (var name in files) if (HOP(files, name)) {
options.output.source_map.get().setSourceContent(name, files[name]); options.output.source_map.get().setSourceContent(name, files[name]);
} }
} else {
options.output.source_map.get()._sourcesContents = null;
} }
} }
delete options.output.ast; delete options.output.ast;

View File

@@ -43,11 +43,9 @@
"use strict"; "use strict";
(function(){ (function() {
function normalize_directives(body) {
var normalize_directives = function(body) {
var in_directive = true; var in_directive = true;
for (var i = 0; i < body.length; i++) { for (var i = 0; i < body.length; i++) {
if (in_directive && body[i] instanceof AST_Statement && body[i].body instanceof AST_String) { if (in_directive && body[i] instanceof AST_Statement && body[i].body instanceof AST_String) {
body[i] = new AST_Directive({ body[i] = new AST_Directive({
@@ -59,9 +57,8 @@
in_directive = false; in_directive = false;
} }
} }
return body; return body;
}; }
var MOZ_TO_ME = { var MOZ_TO_ME = {
Program: function(M) { Program: function(M) {
@@ -129,7 +126,7 @@
return new AST_Array({ return new AST_Array({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
elements : M.elements.map(function(elem){ elements : M.elements.map(function(elem) {
return elem === null ? new AST_Hole() : from_moz(elem); return elem === null ? new AST_Hole() : from_moz(elem);
}) })
}); });
@@ -138,7 +135,7 @@
return new AST_Object({ return new AST_Object({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
properties : M.properties.map(function(prop){ properties : M.properties.map(function(prop) {
prop.type = "Property"; prop.type = "Property";
return from_moz(prop) return from_moz(prop)
}) })
@@ -180,6 +177,17 @@
end : my_end_token(M) end : my_end_token(M)
}; };
if (val === null) return new AST_Null(args); if (val === null) return new AST_Null(args);
var rx = M.regex;
if (rx && rx.pattern) {
// RegExpLiteral as per ESTree AST spec
args.value = new RegExp(rx.pattern, rx.flags);
args.value.raw_source = rx.pattern;
return new AST_RegExp(args);
} else if (rx) {
// support legacy RegExp
args.value = M.regex && M.raw ? M.raw : val;
return new AST_RegExp(args);
}
switch (typeof val) { switch (typeof val) {
case "string": case "string":
args.value = val; args.value = val;
@@ -189,16 +197,6 @@
return new AST_Number(args); return new AST_Number(args);
case "boolean": case "boolean":
return new (val ? AST_True : AST_False)(args); return new (val ? AST_True : AST_False)(args);
default:
var rx = M.regex;
if (rx && rx.pattern) {
// RegExpLiteral as per ESTree AST spec
args.value = new RegExp(rx.pattern, rx.flags).toString();
} else {
// support legacy RegExp
args.value = M.regex && M.raw ? M.raw : val;
}
return new AST_RegExp(args);
} }
}, },
Identifier: function(M) { Identifier: function(M) {
@@ -410,14 +408,15 @@
}); });
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) { def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
var value = M.value; var flags = M.value.toString().match(/[gimuy]*$/)[0];
var value = "/" + M.value.raw_source + "/" + flags;
return { return {
type: "Literal", type: "Literal",
value: value, value: value,
raw: value.toString(), raw: value,
regex: { regex: {
pattern: value.source, pattern: M.value.raw_source,
flags: value.toString().match(/[gimuy]*$/)[0] flags: flags
} }
}; };
}); });
@@ -478,7 +477,7 @@
endpos : range ? range[0] : moznode.start, endpos : range ? range[0] : moznode.start,
raw : raw_token(moznode), raw : raw_token(moznode),
}); });
}; }
function my_end_token(moznode) { function my_end_token(moznode) {
var loc = moznode.loc, end = loc && loc.end; var loc = moznode.loc, end = loc && loc.end;
@@ -493,7 +492,7 @@
endpos : range ? range[1] : moznode.end, endpos : range ? range[1] : moznode.end,
raw : raw_token(moznode), raw : raw_token(moznode),
}); });
}; }
function map(moztype, mytype, propmap) { function map(moztype, mytype, propmap) {
var moz_to_me = "function From_Moz_" + moztype + "(M){\n"; var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
@@ -505,7 +504,7 @@
me_to_moz += "return {\n" + me_to_moz += "return {\n" +
"type: " + JSON.stringify(moztype); "type: " + JSON.stringify(moztype);
if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){ if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop) {
var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop); var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
if (!m) throw new Error("Can't understand property map: " + prop); if (!m) throw new Error("Can't understand property map: " + prop);
var moz = m[1], how = m[2], my = m[3]; var moz = m[1], how = m[2], my = m[3];
@@ -548,7 +547,7 @@
); );
MOZ_TO_ME[moztype] = moz_to_me; MOZ_TO_ME[moztype] = moz_to_me;
def_to_moz(mytype, me_to_moz); def_to_moz(mytype, me_to_moz);
}; }
var FROM_MOZ_STACK = null; var FROM_MOZ_STACK = null;
@@ -557,13 +556,28 @@
var ret = node != null ? MOZ_TO_ME[node.type](node) : null; var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
FROM_MOZ_STACK.pop(); FROM_MOZ_STACK.pop();
return ret; return ret;
}; }
AST_Node.from_mozilla_ast = function(node){ AST_Node.from_mozilla_ast = function(node) {
var save_stack = FROM_MOZ_STACK; var save_stack = FROM_MOZ_STACK;
FROM_MOZ_STACK = []; FROM_MOZ_STACK = [];
var ast = from_moz(node); var ast = from_moz(node);
FROM_MOZ_STACK = save_stack; FROM_MOZ_STACK = save_stack;
ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_LabelRef) {
for (var level = 0, parent; parent = this.parent(level); level++) {
if (parent instanceof AST_Scope) break;
if (parent instanceof AST_LabeledStatement && parent.label.name == node.name) {
node.thedef = parent.label;
break;
}
}
if (!node.thedef) {
var s = node.start;
js_error("Undefined label " + node.name, s.file, s.line, s.col, s.pos);
}
}
}));
return ast; return ast;
}; };
@@ -583,24 +597,24 @@
} }
} }
return moznode; return moznode;
}; }
function def_to_moz(mytype, handler) { function def_to_moz(mytype, handler) {
mytype.DEFMETHOD("to_mozilla_ast", function() { mytype.DEFMETHOD("to_mozilla_ast", function() {
return set_moz_loc(this, handler(this)); return set_moz_loc(this, handler(this));
}); });
}; }
function to_moz(node) { function to_moz(node) {
return node != null ? node.to_mozilla_ast() : null; return node != null ? node.to_mozilla_ast() : null;
}; }
function to_moz_block(node) { function to_moz_block(node) {
return { return {
type: "BlockStatement", type: "BlockStatement",
body: node.body.map(to_moz) body: node.body.map(to_moz)
}; };
}; }
function to_moz_scope(type, node) { function to_moz_scope(type, node) {
var body = node.body.map(to_moz); var body = node.body.map(to_moz);
@@ -611,5 +625,5 @@
type: type, type: type,
body: body body: body
}; };
}; }
})(); })();

File diff suppressed because it is too large Load Diff

View File

@@ -130,7 +130,7 @@ function is_letter(code) {
return (code >= 97 && code <= 122) return (code >= 97 && code <= 122)
|| (code >= 65 && code <= 90) || (code >= 65 && code <= 90)
|| (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code))); || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code)));
}; }
function is_surrogate_pair_head(code) { function is_surrogate_pair_head(code) {
if (typeof code == "string") if (typeof code == "string")
@@ -146,11 +146,11 @@ function is_surrogate_pair_tail(code) {
function is_digit(code) { function is_digit(code) {
return code >= 48 && code <= 57; return code >= 48 && code <= 57;
}; }
function is_alphanumeric_char(code) { function is_alphanumeric_char(code) {
return is_digit(code) || is_letter(code); return is_digit(code) || is_letter(code);
}; }
function is_unicode_digit(code) { function is_unicode_digit(code) {
return UNICODE.digit.test(String.fromCharCode(code)); return UNICODE.digit.test(String.fromCharCode(code));
@@ -158,19 +158,19 @@ function is_unicode_digit(code) {
function is_unicode_combining_mark(ch) { function is_unicode_combining_mark(ch) {
return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
}; }
function is_unicode_connector_punctuation(ch) { function is_unicode_connector_punctuation(ch) {
return UNICODE.connector_punctuation.test(ch); return UNICODE.connector_punctuation.test(ch);
}; }
function is_identifier(name) { function is_identifier(name) {
return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name); return !RESERVED_WORDS[name] && /^[a-z_$][a-z0-9_$]*$/i.test(name);
}; }
function is_identifier_start(code) { function is_identifier_start(code) {
return code == 36 || code == 95 || is_letter(code); return code == 36 || code == 95 || is_letter(code);
}; }
function is_identifier_char(ch) { function is_identifier_char(ch) {
var code = ch.charCodeAt(0); var code = ch.charCodeAt(0);
@@ -182,11 +182,11 @@ function is_identifier_char(ch) {
|| is_unicode_connector_punctuation(ch) || is_unicode_connector_punctuation(ch)
|| is_unicode_digit(code) || is_unicode_digit(code)
; ;
}; }
function is_identifier_string(str){ function is_identifier_string(str) {
return /^[a-z_$][a-z0-9_$]*$/i.test(str); return /^[a-z_$][a-z0-9_$]*$/i.test(str);
}; }
function parse_js_number(num) { function parse_js_number(num) {
if (RE_HEX_NUMBER.test(num)) { if (RE_HEX_NUMBER.test(num)) {
@@ -197,7 +197,7 @@ function parse_js_number(num) {
var val = parseFloat(num); var val = parseFloat(num);
if (val == num) return val; if (val == num) return val;
} }
}; }
function JS_Parse_Error(message, filename, line, col, pos) { function JS_Parse_Error(message, filename, line, col, pos) {
this.message = message; this.message = message;
@@ -205,7 +205,7 @@ function JS_Parse_Error(message, filename, line, col, pos) {
this.line = line; this.line = line;
this.col = col; this.col = col;
this.pos = pos; this.pos = pos;
}; }
JS_Parse_Error.prototype = Object.create(Error.prototype); JS_Parse_Error.prototype = Object.create(Error.prototype);
JS_Parse_Error.prototype.constructor = JS_Parse_Error; JS_Parse_Error.prototype.constructor = JS_Parse_Error;
JS_Parse_Error.prototype.name = "SyntaxError"; JS_Parse_Error.prototype.name = "SyntaxError";
@@ -213,11 +213,11 @@ configure_error_stack(JS_Parse_Error);
function js_error(message, filename, line, col, pos) { function js_error(message, filename, line, col, pos) {
throw new JS_Parse_Error(message, filename, line, col, pos); throw new JS_Parse_Error(message, filename, line, col, pos);
}; }
function is_token(token, type, val) { function is_token(token, type, val) {
return token.type == type && (val == null || token.value == val); return token.type == type && (val == null || token.value == val);
}; }
var EX_EOF = {}; var EX_EOF = {};
@@ -239,13 +239,15 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
directive_stack : [] directive_stack : []
}; };
function peek() { return S.text.charAt(S.pos); }; function peek() {
return S.text.charAt(S.pos);
}
function next(signal_eof, in_string) { function next(signal_eof, in_string) {
var ch = S.text.charAt(S.pos++); var ch = S.text.charAt(S.pos++);
if (signal_eof && !ch) if (signal_eof && !ch)
throw EX_EOF; throw EX_EOF;
if (NEWLINE_CHARS(ch)) { if (NEWLINE_CHARS[ch]) {
S.newline_before = S.newline_before || !in_string; S.newline_before = S.newline_before || !in_string;
++S.line; ++S.line;
S.col = 0; S.col = 0;
@@ -258,43 +260,43 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
++S.col; ++S.col;
} }
return ch; return ch;
}; }
function forward(i) { function forward(i) {
while (i-- > 0) next(); while (i-- > 0) next();
}; }
function looking_at(str) { function looking_at(str) {
return S.text.substr(S.pos, str.length) == str; return S.text.substr(S.pos, str.length) == str;
}; }
function find_eol() { function find_eol() {
var text = S.text; var text = S.text;
for (var i = S.pos, n = S.text.length; i < n; ++i) { for (var i = S.pos, n = S.text.length; i < n; ++i) {
var ch = text[i]; var ch = text[i];
if (NEWLINE_CHARS(ch)) if (NEWLINE_CHARS[ch])
return i; return i;
} }
return -1; return -1;
}; }
function find(what, signal_eof) { function find(what, signal_eof) {
var pos = S.text.indexOf(what, S.pos); var pos = S.text.indexOf(what, S.pos);
if (signal_eof && pos == -1) throw EX_EOF; if (signal_eof && pos == -1) throw EX_EOF;
return pos; return pos;
}; }
function start_token() { function start_token() {
S.tokline = S.line; S.tokline = S.line;
S.tokcol = S.col; S.tokcol = S.col;
S.tokpos = S.pos; S.tokpos = S.pos;
}; }
var prev_was_dot = false; var prev_was_dot = false;
function token(type, value, is_comment) { function token(type, value, is_comment) {
S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX(value)) || S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) ||
(type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) || (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION[value]) ||
(type == "punc" && PUNC_BEFORE_EXPRESSION(value))); (type == "punc" && PUNC_BEFORE_EXPRESSION[value]));
if (type == "punc" && value == ".") { if (type == "punc" && value == ".") {
prev_was_dot = true; prev_was_dot = true;
} else if (!is_comment) { } else if (!is_comment) {
@@ -321,27 +323,27 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
} }
S.newline_before = false; S.newline_before = false;
return new AST_Token(ret); return new AST_Token(ret);
}; }
function skip_whitespace() { function skip_whitespace() {
while (WHITESPACE_CHARS(peek())) while (WHITESPACE_CHARS[peek()])
next(); next();
}; }
function read_while(pred) { function read_while(pred) {
var ret = "", ch, i = 0; var ret = "", ch, i = 0;
while ((ch = peek()) && pred(ch, i++)) while ((ch = peek()) && pred(ch, i++))
ret += next(); ret += next();
return ret; return ret;
}; }
function parse_error(err) { function parse_error(err) {
js_error(err, filename, S.tokline, S.tokcol, S.tokpos); js_error(err, filename, S.tokline, S.tokcol, S.tokpos);
}; }
function read_num(prefix) { function read_num(prefix) {
var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
var num = read_while(function(ch, i){ var num = read_while(function(ch, i) {
var code = ch.charCodeAt(0); var code = ch.charCodeAt(0);
switch (code) { switch (code) {
case 120: case 88: // xX case 120: case 88: // xX
@@ -367,7 +369,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
} else { } else {
parse_error("Invalid syntax: " + num); parse_error("Invalid syntax: " + num);
} }
}; }
function read_escaped_char(in_string) { function read_escaped_char(in_string) {
var ch = next(true, in_string); var ch = next(true, in_string);
@@ -390,7 +392,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
if (ch >= "0" && ch <= "7") if (ch >= "0" && ch <= "7")
return read_octal_escape_sequence(ch); return read_octal_escape_sequence(ch);
return ch; return ch;
}; }
function read_octal_escape_sequence(ch) { function read_octal_escape_sequence(ch) {
// Read // Read
@@ -417,14 +419,14 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
num = (num << 4) | digit; num = (num << 4) | digit;
} }
return num; return num;
}; }
var read_string = with_eof_error("Unterminated string constant", function(quote_char){ var read_string = with_eof_error("Unterminated string constant", function(quote_char) {
var quote = next(), ret = ""; var quote = next(), ret = "";
for (;;) { for (;;) {
var ch = next(true, true); var ch = next(true, true);
if (ch == "\\") ch = read_escaped_char(true); if (ch == "\\") ch = read_escaped_char(true);
else if (NEWLINE_CHARS(ch)) parse_error("Unterminated string constant"); else if (NEWLINE_CHARS[ch]) parse_error("Unterminated string constant");
else if (ch == quote) break; else if (ch == quote) break;
ret += ch; ret += ch;
} }
@@ -447,9 +449,9 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
S.comments_before.push(token(type, ret, true)); S.comments_before.push(token(type, ret, true));
S.regex_allowed = regex_allowed; S.regex_allowed = regex_allowed;
return next_token; return next_token;
}; }
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function(){ var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function() {
var regex_allowed = S.regex_allowed; var regex_allowed = S.regex_allowed;
var i = find("*/", true); var i = find("*/", true);
var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, '\n'); var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, '\n');
@@ -476,16 +478,16 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
backslash = false; backslash = false;
} }
} }
if (KEYWORDS(name) && escaped) { if (KEYWORDS[name] && escaped) {
hex = name.charCodeAt(0).toString(16).toUpperCase(); hex = name.charCodeAt(0).toString(16).toUpperCase();
name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
} }
return name; return name;
}; }
var read_regexp = with_eof_error("Unterminated regular expression", function(source) { var read_regexp = with_eof_error("Unterminated regular expression", function(source) {
var prev_backslash = false, ch, in_class = false; var prev_backslash = false, ch, in_class = false;
while ((ch = next(true))) if (NEWLINE_CHARS(ch)) { while ((ch = next(true))) if (NEWLINE_CHARS[ch]) {
parse_error("Unexpected line terminator"); parse_error("Unexpected line terminator");
} else if (prev_backslash) { } else if (prev_backslash) {
source += "\\" + ch; source += "\\" + ch;
@@ -517,15 +519,15 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
function grow(op) { function grow(op) {
if (!peek()) return op; if (!peek()) return op;
var bigger = op + peek(); var bigger = op + peek();
if (OPERATORS(bigger)) { if (OPERATORS[bigger]) {
next(); next();
return grow(bigger); return grow(bigger);
} else { } else {
return op; return op;
} }
}; }
return token("operator", grow(prefix || next())); return token("operator", grow(prefix || next()));
}; }
function handle_slash() { function handle_slash() {
next(); next();
@@ -538,23 +540,23 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
return skip_multiline_comment(); return skip_multiline_comment();
} }
return S.regex_allowed ? read_regexp("") : read_operator("/"); return S.regex_allowed ? read_regexp("") : read_operator("/");
}; }
function handle_dot() { function handle_dot() {
next(); next();
return is_digit(peek().charCodeAt(0)) return is_digit(peek().charCodeAt(0))
? read_num(".") ? read_num(".")
: token("punc", "."); : token("punc", ".");
}; }
function read_word() { function read_word() {
var word = read_name(); var word = read_name();
if (prev_was_dot) return token("name", word); if (prev_was_dot) return token("name", word);
return KEYWORDS_ATOM(word) ? token("atom", word) return KEYWORDS_ATOM[word] ? token("atom", word)
: !KEYWORDS(word) ? token("name", word) : !KEYWORDS[word] ? token("name", word)
: OPERATORS(word) ? token("operator", word) : OPERATORS[word] ? token("operator", word)
: token("keyword", word); : token("keyword", word);
}; }
function with_eof_error(eof_error, cont) { function with_eof_error(eof_error, cont) {
return function(x) { return function(x) {
@@ -565,7 +567,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
else throw ex; else throw ex;
} }
}; };
}; }
function next_token(force_regexp) { function next_token(force_regexp) {
if (force_regexp != null) if (force_regexp != null)
@@ -603,13 +605,13 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
} }
} }
if (is_digit(code)) return read_num(); if (is_digit(code)) return read_num();
if (PUNC_CHARS(ch)) return token("punc", next()); if (PUNC_CHARS[ch]) return token("punc", next());
if (OPERATOR_CHARS(ch)) return read_operator(); if (OPERATOR_CHARS[ch]) return read_operator();
if (code == 92 || is_identifier_start(code)) return read_word(); if (code == 92 || is_identifier_start(code)) return read_word();
break; break;
} }
parse_error("Unexpected character '" + ch + "'"); parse_error("Unexpected character '" + ch + "'");
}; }
next_token.context = function(nc) { next_token.context = function(nc) {
if (nc) S = nc; if (nc) S = nc;
@@ -645,8 +647,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
} }
return next_token; return next_token;
}
};
/* -----[ Parser (constants) ]----- */ /* -----[ Parser (constants) ]----- */
@@ -666,7 +667,7 @@ var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]); var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
var PRECEDENCE = (function(a, ret){ var PRECEDENCE = function(a, ret) {
for (var i = 0; i < a.length; ++i) { for (var i = 0; i < a.length; ++i) {
var b = a[i]; var b = a[i];
for (var j = 0; j < b.length; ++j) { for (var j = 0; j < b.length; ++j) {
@@ -674,28 +675,24 @@ var PRECEDENCE = (function(a, ret){
} }
} }
return ret; return ret;
})( }([
[ ["||"],
["||"], ["&&"],
["&&"], ["|"],
["|"], ["^"],
["^"], ["&"],
["&"], ["==", "===", "!=", "!=="],
["==", "===", "!=", "!=="], ["<", ">", "<=", ">=", "in", "instanceof"],
["<", ">", "<=", ">=", "in", "instanceof"], [">>", "<<", ">>>"],
[">>", "<<", ">>>"], ["+", "-"],
["+", "-"], ["*", "/", "%"]
["*", "/", "%"] ], {});
],
{}
);
var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "string", "regexp", "name" ]); var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "string", "regexp", "name" ]);
/* -----[ Parser ]----- */ /* -----[ Parser ]----- */
function parse($TEXT, options) { function parse($TEXT, options) {
options = defaults(options, { options = defaults(options, {
bare_returns : false, bare_returns : false,
expression : false, expression : false,
@@ -724,9 +721,11 @@ function parse($TEXT, options) {
function is(type, value) { function is(type, value) {
return is_token(S.token, type, value); return is_token(S.token, type, value);
}; }
function peek() { return S.peeked || (S.peeked = S.input()); }; function peek() {
return S.peeked || (S.peeked = S.input());
}
function next() { function next() {
S.prev = S.token; S.prev = S.token;
@@ -740,11 +739,11 @@ function parse($TEXT, options) {
S.token.type == "string" || is("punc", ";") S.token.type == "string" || is("punc", ";")
); );
return S.token; return S.token;
}; }
function prev() { function prev() {
return S.prev; return S.prev;
}; }
function croak(msg, line, col, pos) { function croak(msg, line, col, pos) {
var ctx = S.input.context(); var ctx = S.input.context();
@@ -753,26 +752,28 @@ function parse($TEXT, options) {
line != null ? line : ctx.tokline, line != null ? line : ctx.tokline,
col != null ? col : ctx.tokcol, col != null ? col : ctx.tokcol,
pos != null ? pos : ctx.tokpos); pos != null ? pos : ctx.tokpos);
}; }
function token_error(token, msg) { function token_error(token, msg) {
croak(msg, token.line, token.col); croak(msg, token.line, token.col);
}; }
function unexpected(token) { function unexpected(token) {
if (token == null) if (token == null)
token = S.token; token = S.token;
token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
}; }
function expect_token(type, val) { function expect_token(type, val) {
if (is(type, val)) { if (is(type, val)) {
return next(); return next();
} }
token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»"); token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
}; }
function expect(punc) { return expect_token("punc", punc); }; function expect(punc) {
return expect_token("punc", punc);
}
function has_newline_before(token) { function has_newline_before(token) {
return token.nlb || !all(token.comments_before, function(comment) { return token.nlb || !all(token.comments_before, function(comment) {
@@ -783,19 +784,19 @@ function parse($TEXT, options) {
function can_insert_semicolon() { function can_insert_semicolon() {
return !options.strict return !options.strict
&& (is("eof") || is("punc", "}") || has_newline_before(S.token)); && (is("eof") || is("punc", "}") || has_newline_before(S.token));
}; }
function semicolon(optional) { function semicolon(optional) {
if (is("punc", ";")) next(); if (is("punc", ";")) next();
else if (!optional && !can_insert_semicolon()) unexpected(); else if (!optional && !can_insert_semicolon()) unexpected();
}; }
function parenthesised() { function parenthesised() {
expect("("); expect("(");
var exp = expression(true); var exp = expression(true);
expect(")"); expect(")");
return exp; return exp;
}; }
function embed_tokens(parser) { function embed_tokens(parser) {
return function() { return function() {
@@ -806,14 +807,14 @@ function parse($TEXT, options) {
expr.end = end; expr.end = end;
return expr; return expr;
}; };
}; }
function handle_regexp() { function handle_regexp() {
if (is("operator", "/") || is("operator", "/=")) { if (is("operator", "/") || is("operator", "/=")) {
S.peeked = null; S.peeked = null;
S.token = S.input(S.token.value.substr(1)); // force regexp S.token = S.input(S.token.value.substr(1)); // force regexp
} }
}; }
var statement = embed_tokens(function(strict_defun) { var statement = embed_tokens(function(strict_defun) {
handle_regexp(); handle_regexp();
@@ -969,7 +970,9 @@ function parse($TEXT, options) {
function labeled_statement() { function labeled_statement() {
var label = as_symbol(AST_Label); var label = as_symbol(AST_Label);
if (find_if(function(l){ return l.name == label.name }, S.labels)) { if (!all(S.labels, function(l) {
return l.name != label.name;
})) {
// ECMA-262, 12.12: An ECMAScript program is considered // ECMA-262, 12.12: An ECMAScript program is considered
// syntactically incorrect if it contains a // syntactically incorrect if it contains a
// LabelledStatement that is enclosed by a // LabelledStatement that is enclosed by a
@@ -984,7 +987,7 @@ function parse($TEXT, options) {
// check for `continue` that refers to this label. // check for `continue` that refers to this label.
// those should be reported as syntax errors. // those should be reported as syntax errors.
// https://github.com/mishoo/UglifyJS2/issues/287 // https://github.com/mishoo/UglifyJS2/issues/287
label.references.forEach(function(ref){ label.references.forEach(function(ref) {
if (ref instanceof AST_Continue) { if (ref instanceof AST_Continue) {
ref = ref.label.start; ref = ref.label.start;
croak("Continue label `" + label.name + "` refers to non-IterationStatement.", croak("Continue label `" + label.name + "` refers to non-IterationStatement.",
@@ -993,11 +996,11 @@ function parse($TEXT, options) {
}); });
} }
return new AST_LabeledStatement({ body: stat, label: label }); return new AST_LabeledStatement({ body: stat, label: label });
}; }
function simple_statement(tmp) { function simple_statement(tmp) {
return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) }); return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) });
}; }
function break_cont(type) { function break_cont(type) {
var label = null, ldef; var label = null, ldef;
@@ -1005,18 +1008,17 @@ function parse($TEXT, options) {
label = as_symbol(AST_LabelRef, true); label = as_symbol(AST_LabelRef, true);
} }
if (label != null) { if (label != null) {
ldef = find_if(function(l){ return l.name == label.name }, S.labels); ldef = find_if(function(l) {
if (!ldef) return l.name == label.name;
croak("Undefined label " + label.name); }, S.labels);
if (!ldef) croak("Undefined label " + label.name);
label.thedef = ldef; label.thedef = ldef;
} } else if (S.in_loop == 0) croak(type.TYPE + " not inside a loop or switch");
else if (S.in_loop == 0)
croak(type.TYPE + " not inside a loop or switch");
semicolon(); semicolon();
var stat = new type({ label: label }); var stat = new type({ label: label });
if (ldef) ldef.references.push(stat); if (ldef) ldef.references.push(stat);
return stat; return stat;
}; }
function for_() { function for_() {
expect("("); expect("(");
@@ -1037,7 +1039,7 @@ function parse($TEXT, options) {
} }
} }
return regular_for(init); return regular_for(init);
}; }
function regular_for(init) { function regular_for(init) {
expect(";"); expect(";");
@@ -1051,7 +1053,7 @@ function parse($TEXT, options) {
step : step, step : step,
body : in_loop(statement) body : in_loop(statement)
}); });
}; }
function for_in(init) { function for_in(init) {
var obj = expression(true); var obj = expression(true);
@@ -1061,7 +1063,7 @@ function parse($TEXT, options) {
object : obj, object : obj,
body : in_loop(statement) body : in_loop(statement)
}); });
}; }
var function_ = function(ctor) { var function_ = function(ctor) {
var in_statement = ctor === AST_Defun; var in_statement = ctor === AST_Defun;
@@ -1111,7 +1113,7 @@ function parse($TEXT, options) {
body : body, body : body,
alternative : belse alternative : belse
}); });
}; }
function block_(strict_defun) { function block_(strict_defun) {
expect("{"); expect("{");
@@ -1122,7 +1124,7 @@ function parse($TEXT, options) {
} }
next(); next();
return a; return a;
}; }
function switch_body_() { function switch_body_() {
expect("{"); expect("{");
@@ -1157,7 +1159,7 @@ function parse($TEXT, options) {
if (branch) branch.end = prev(); if (branch) branch.end = prev();
next(); next();
return a; return a;
}; }
function try_() { function try_() {
var body = block_(), bcatch = null, bfinally = null; var body = block_(), bcatch = null, bfinally = null;
@@ -1190,7 +1192,7 @@ function parse($TEXT, options) {
bcatch : bcatch, bcatch : bcatch,
bfinally : bfinally bfinally : bfinally
}); });
}; }
function vardefs(no_in) { function vardefs(no_in) {
var a = []; var a = [];
@@ -1206,7 +1208,7 @@ function parse($TEXT, options) {
next(); next();
} }
return a; return a;
}; }
var var_ = function(no_in) { var var_ = function(no_in) {
return new AST_Var({ return new AST_Var({
@@ -1272,7 +1274,7 @@ function parse($TEXT, options) {
} }
next(); next();
return ret; return ret;
}; }
var expr_atom = function(allow_calls) { var expr_atom = function(allow_calls) {
if (is("operator", "new")) { if (is("operator", "new")) {
@@ -1319,7 +1321,7 @@ function parse($TEXT, options) {
func.end = prev(); func.end = prev();
return subscripts(func, allow_calls); return subscripts(func, allow_calls);
} }
if (ATOMIC_START_TOKEN(S.token.type)) { if (ATOMIC_START_TOKEN[S.token.type]) {
return subscripts(as_atom_node(), allow_calls); return subscripts(as_atom_node(), allow_calls);
} }
unexpected(); unexpected();
@@ -1338,7 +1340,7 @@ function parse($TEXT, options) {
} }
next(); next();
return a; return a;
}; }
var array_ = embed_tokens(function() { var array_ = embed_tokens(function() {
expect("["); expect("[");
@@ -1404,7 +1406,7 @@ function parse($TEXT, options) {
var tmp = S.token; var tmp = S.token;
switch (tmp.type) { switch (tmp.type) {
case "operator": case "operator":
if (!KEYWORDS(tmp.value)) unexpected(); if (!KEYWORDS[tmp.value]) unexpected();
case "num": case "num":
case "string": case "string":
case "name": case "name":
@@ -1415,14 +1417,14 @@ function parse($TEXT, options) {
default: default:
unexpected(); unexpected();
} }
}; }
function as_name() { function as_name() {
var tmp = S.token; var tmp = S.token;
if (tmp.type != "name") unexpected(); if (tmp.type != "name") unexpected();
next(); next();
return tmp.value; return tmp.value;
}; }
function _make_symbol(type) { function _make_symbol(type) {
var name = S.token.value; var name = S.token.value;
@@ -1431,7 +1433,7 @@ function parse($TEXT, options) {
start : S.token, start : S.token,
end : S.token end : S.token
}); });
}; }
function strict_verify_symbol(sym) { function strict_verify_symbol(sym) {
if (sym.name == "arguments" || sym.name == "eval") if (sym.name == "arguments" || sym.name == "eval")
@@ -1449,7 +1451,7 @@ function parse($TEXT, options) {
} }
next(); next();
return sym; return sym;
}; }
function mark_pure(call) { function mark_pure(call) {
var start = call.start; var start = call.start;
@@ -1502,7 +1504,7 @@ function parse($TEXT, options) {
var maybe_unary = function(allow_calls) { var maybe_unary = function(allow_calls) {
var start = S.token; var start = S.token;
if (is("operator") && UNARY_PREFIX(start.value)) { if (is("operator") && UNARY_PREFIX[start.value]) {
next(); next();
handle_regexp(); handle_regexp();
var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(allow_calls)); var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(allow_calls));
@@ -1511,7 +1513,7 @@ function parse($TEXT, options) {
return ex; return ex;
} }
var val = expr_atom(allow_calls); var val = expr_atom(allow_calls);
while (is("operator") && UNARY_POSTFIX(S.token.value) && !has_newline_before(S.token)) { while (is("operator") && UNARY_POSTFIX[S.token.value] && !has_newline_before(S.token)) {
val = make_unary(AST_UnaryPostfix, S.token, val); val = make_unary(AST_UnaryPostfix, S.token, val);
val.start = start; val.start = start;
val.end = S.token; val.end = S.token;
@@ -1534,7 +1536,7 @@ function parse($TEXT, options) {
break; break;
} }
return new ctor({ operator: op, expression: expr }); return new ctor({ operator: op, expression: expr });
}; }
var expr_op = function(left, min_prec, no_in) { var expr_op = function(left, min_prec, no_in) {
var op = is("operator") ? S.token.value : null; var op = is("operator") ? S.token.value : null;
@@ -1556,7 +1558,7 @@ function parse($TEXT, options) {
function expr_ops(no_in) { function expr_ops(no_in) {
return expr_op(maybe_unary(true), 0, no_in); return expr_op(maybe_unary(true), 0, no_in);
}; }
var maybe_conditional = function(no_in) { var maybe_conditional = function(no_in) {
var start = S.token; var start = S.token;
@@ -1578,12 +1580,12 @@ function parse($TEXT, options) {
function is_assignable(expr) { function is_assignable(expr) {
return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef; return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef;
}; }
var maybe_assign = function(no_in) { var maybe_assign = function(no_in) {
var start = S.token; var start = S.token;
var left = maybe_conditional(no_in), val = S.token.value; var left = maybe_conditional(no_in), val = S.token.value;
if (is("operator") && ASSIGNMENT(val)) { if (is("operator") && ASSIGNMENT[val]) {
if (is_assignable(left)) { if (is_assignable(left)) {
next(); next();
return new AST_Assign({ return new AST_Assign({
@@ -1620,13 +1622,13 @@ function parse($TEXT, options) {
var ret = cont(); var ret = cont();
--S.in_loop; --S.in_loop;
return ret; return ret;
}; }
if (options.expression) { if (options.expression) {
return expression(true); return expression(true);
} }
return (function(){ return function() {
var start = S.token; var start = S.token;
var body = []; var body = [];
S.input.push_directives_stack(); S.input.push_directives_stack();
@@ -1642,6 +1644,5 @@ function parse($TEXT, options) {
toplevel = new AST_Toplevel({ start: start, body: body, end: end }); toplevel = new AST_Toplevel({ start: start, body: body, end: end });
} }
return toplevel; return toplevel;
})(); }();
}
};

View File

@@ -56,7 +56,7 @@ function find_builtins(reserved) {
[ Object, Array, Function, Number, [ Object, Array, Function, Number,
String, Boolean, Error, Math, String, Boolean, Error, Math,
Date, RegExp Date, RegExp
].forEach(function(ctor){ ].forEach(function(ctor) {
Object.getOwnPropertyNames(ctor).map(add); Object.getOwnPropertyNames(ctor).map(add);
if (ctor.prototype) { if (ctor.prototype) {
Object.getOwnPropertyNames(ctor.prototype).map(add); Object.getOwnPropertyNames(ctor.prototype).map(add);
@@ -136,7 +136,7 @@ function mangle_properties(ast, options) {
var unmangleable = []; var unmangleable = [];
// step 1: find candidates to mangle // step 1: find candidates to mangle
ast.walk(new TreeWalker(function(node){ ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ObjectKeyVal) { if (node instanceof AST_ObjectKeyVal) {
add(node.key); add(node.key);
} }
@@ -150,10 +150,14 @@ function mangle_properties(ast, options) {
else if (node instanceof AST_Sub) { else if (node instanceof AST_Sub) {
addStrings(node.property, add); addStrings(node.property, add);
} }
else if (node instanceof AST_Call
&& node.expression.print_to_string() == "Object.defineProperty") {
addStrings(node.args[1], add);
}
})); }));
// step 2: transform the tree, renaming properties // step 2: transform the tree, renaming properties
return ast.transform(new TreeTransformer(function(node){ return ast.transform(new TreeTransformer(function(node) {
if (node instanceof AST_ObjectKeyVal) { if (node instanceof AST_ObjectKeyVal) {
node.key = mangle(node.key); node.key = mangle(node.key);
} }
@@ -167,6 +171,10 @@ function mangle_properties(ast, options) {
else if (!options.keep_quoted && node instanceof AST_Sub) { else if (!options.keep_quoted && node instanceof AST_Sub) {
node.property = mangleStrings(node.property); node.property = mangleStrings(node.property);
} }
else if (node instanceof AST_Call
&& node.expression.print_to_string() == "Object.defineProperty") {
node.args[1] = mangleStrings(node.args[1]);
}
})); }));
// only function declarations after this line // only function declarations after this line
@@ -226,7 +234,7 @@ function mangle_properties(ast, options) {
} }
function mangleStrings(node) { function mangleStrings(node) {
return node.transform(new TreeTransformer(function(node){ return node.transform(new TreeTransformer(function(node) {
if (node instanceof AST_Sequence) { if (node instanceof AST_Sequence) {
var last = node.expressions.length - 1; var last = node.expressions.length - 1;
node.expressions[last] = mangleStrings(node.expressions[last]); node.expressions[last] = mangleStrings(node.expressions[last]);

View File

@@ -55,7 +55,7 @@ function SymbolDef(scope, orig, init) {
this.mangled_name = null; this.mangled_name = null;
this.undeclared = false; this.undeclared = false;
this.id = SymbolDef.next_id++; this.id = SymbolDef.next_id++;
}; }
SymbolDef.next_id = 1; SymbolDef.next_id = 1;
@@ -63,28 +63,24 @@ SymbolDef.prototype = {
unmangleable: function(options) { unmangleable: function(options) {
if (!options) options = {}; if (!options) options = {};
return (this.global && !options.toplevel) return this.global && !options.toplevel
|| this.undeclared || this.undeclared
|| (!options.eval && (this.scope.uses_eval || this.scope.uses_with)) || !options.eval && this.scope.pinned()
|| (options.keep_fnames || options.keep_fnames
&& (this.orig[0] instanceof AST_SymbolLambda && (this.orig[0] instanceof AST_SymbolLambda
|| this.orig[0] instanceof AST_SymbolDefun)); || this.orig[0] instanceof AST_SymbolDefun);
}, },
mangle: function(options) { mangle: function(options) {
var cache = options.cache && options.cache.props; var cache = options.cache && options.cache.props;
if (this.global && cache && cache.has(this.name)) { if (this.global && cache && cache.has(this.name)) {
this.mangled_name = cache.get(this.name); this.mangled_name = cache.get(this.name);
} } else if (!this.mangled_name && !this.unmangleable(options)) {
else if (!this.mangled_name && !this.unmangleable(options)) {
var s = this.scope;
var sym = this.orig[0];
if (options.ie8 && sym instanceof AST_SymbolLambda)
s = s.parent_scope;
var def; var def;
if (def = this.redefined()) { if (def = this.redefined()) {
this.mangled_name = def.mangled_name || def.name; this.mangled_name = def.mangled_name || def.name;
} else } else {
this.mangled_name = s.next_mangled(options, this); this.mangled_name = next_mangled_name(this.scope, options, this);
}
if (this.global && cache) { if (this.global && cache) {
cache.set(this.name, this.mangled_name); cache.set(this.name, this.mangled_name);
} }
@@ -95,7 +91,7 @@ SymbolDef.prototype = {
} }
}; };
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
options = defaults(options, { options = defaults(options, {
cache: null, cache: null,
ie8: false, ie8: false,
@@ -104,9 +100,8 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
// pass 1: setup scope chaining and handle definitions // pass 1: setup scope chaining and handle definitions
var self = this; var self = this;
var scope = self.parent_scope = null; var scope = self.parent_scope = null;
var labels = new Dictionary();
var defun = null; var defun = null;
var tw = new TreeWalker(function(node, descend){ var tw = new TreeWalker(function(node, descend) {
if (node instanceof AST_Catch) { if (node instanceof AST_Catch) {
var save_scope = scope; var save_scope = scope;
scope = new AST_Scope(node); scope = new AST_Scope(node);
@@ -119,25 +114,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
node.init_scope_vars(scope); node.init_scope_vars(scope);
var save_scope = scope; var save_scope = scope;
var save_defun = defun; var save_defun = defun;
var save_labels = labels;
defun = scope = node; defun = scope = node;
labels = new Dictionary();
descend(); descend();
scope = save_scope; scope = save_scope;
defun = save_defun; defun = save_defun;
labels = save_labels;
return true; // don't descend again in TreeWalker return true; // don't descend again in TreeWalker
} }
if (node instanceof AST_LabeledStatement) {
var l = node.label;
if (labels.has(l.name)) {
throw new Error(string_template("Label {name} defined twice", l));
}
labels.set(l.name, l);
descend();
labels.del(l.name);
return true; // no descend again
}
if (node instanceof AST_With) { if (node instanceof AST_With) {
for (var s = scope; s; s = s.parent_scope) for (var s = scope; s; s = s.parent_scope)
s.uses_with = true; s.uses_with = true;
@@ -150,10 +132,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
node.thedef = node; node.thedef = node;
node.references = []; node.references = [];
} }
if (node instanceof AST_SymbolLambda) { if (node instanceof AST_SymbolDefun || options.ie8 && node instanceof AST_SymbolLambda) {
defun.def_function(node, node.name == "arguments" ? undefined : defun);
}
else if (node instanceof AST_SymbolDefun) {
// Careful here, the scope where this should be defined is // Careful here, the scope where this should be defined is
// the parent scope. The reason is that we enter a new // the parent scope. The reason is that we enter a new
// scope when we encounter the AST_Defun node (which is // scope when we encounter the AST_Defun node (which is
@@ -161,6 +140,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
// later. // later.
(node.scope = defun.parent_scope).def_function(node, defun); (node.scope = defun.parent_scope).def_function(node, defun);
} }
else if (node instanceof AST_SymbolLambda) {
defun.def_function(node, node.name == "arguments" ? undefined : defun);
}
else if (node instanceof AST_SymbolVar) { else if (node instanceof AST_SymbolVar) {
defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined); defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
if (defun !== scope) { if (defun !== scope) {
@@ -168,28 +150,19 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
var def = scope.find_variable(node); var def = scope.find_variable(node);
if (node.thedef !== def) { if (node.thedef !== def) {
node.thedef = def; node.thedef = def;
node.reference(options);
} }
node.reference(options);
} }
} }
else if (node instanceof AST_SymbolCatch) { else if (node instanceof AST_SymbolCatch) {
scope.def_variable(node).defun = defun; scope.def_variable(node).defun = defun;
} }
else if (node instanceof AST_LabelRef) {
var sym = labels.get(node.name);
if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
name: node.name,
line: node.start.line,
col: node.start.col
}));
node.thedef = sym;
}
}); });
self.walk(tw); self.walk(tw);
// pass 2: find back references and eval // pass 2: find back references and eval
self.globals = new Dictionary(); self.globals = new Dictionary();
var tw = new TreeWalker(function(node, descend){ var tw = new TreeWalker(function(node, descend) {
if (node instanceof AST_LoopControl && node.label) { if (node instanceof AST_LoopControl && node.label) {
node.label.thedef.references.push(node); node.label.thedef.references.push(node);
return true; return true;
@@ -244,7 +217,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
} }
}); });
AST_Toplevel.DEFMETHOD("def_global", function(node){ AST_Toplevel.DEFMETHOD("def_global", function(node) {
var globals = this.globals, name = node.name; var globals = this.globals, name = node.name;
if (globals.has(name)) { if (globals.has(name)) {
return globals.get(name); return globals.get(name);
@@ -257,7 +230,7 @@ AST_Toplevel.DEFMETHOD("def_global", function(node){
} }
}); });
AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){ AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
@@ -267,7 +240,7 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){
this.cname = -1; // the current index for mangling functions/variables this.cname = -1; // the current index for mangling functions/variables
}); });
AST_Lambda.DEFMETHOD("init_scope_vars", function(){ AST_Lambda.DEFMETHOD("init_scope_vars", function() {
AST_Scope.prototype.init_scope_vars.apply(this, arguments); AST_Scope.prototype.init_scope_vars.apply(this, arguments);
this.uses_arguments = false; this.uses_arguments = false;
this.def_variable(new AST_SymbolFunarg({ this.def_variable(new AST_SymbolFunarg({
@@ -297,20 +270,20 @@ AST_Symbol.DEFMETHOD("reference", function(options) {
this.mark_enclosed(options); this.mark_enclosed(options);
}); });
AST_Scope.DEFMETHOD("find_variable", function(name){ AST_Scope.DEFMETHOD("find_variable", function(name) {
if (name instanceof AST_Symbol) name = name.name; if (name instanceof AST_Symbol) name = name.name;
return this.variables.get(name) return this.variables.get(name)
|| (this.parent_scope && this.parent_scope.find_variable(name)); || (this.parent_scope && this.parent_scope.find_variable(name));
}); });
AST_Scope.DEFMETHOD("def_function", function(symbol, init){ AST_Scope.DEFMETHOD("def_function", function(symbol, init) {
var def = this.def_variable(symbol, init); var def = this.def_variable(symbol, init);
if (!def.init || def.init instanceof AST_Defun) def.init = init; if (!def.init || def.init instanceof AST_Defun) def.init = init;
this.functions.set(symbol.name, def); this.functions.set(symbol.name, def);
return def; return def;
}); });
AST_Scope.DEFMETHOD("def_variable", function(symbol, init){ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
var def = this.variables.get(symbol.name); var def = this.variables.get(symbol.name);
if (def) { if (def) {
def.orig.push(symbol); def.orig.push(symbol);
@@ -325,58 +298,61 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init){
return symbol.thedef = def; return symbol.thedef = def;
}); });
function next_mangled(scope, options) { function names_in_use(scope, options) {
var ext = scope.enclosed; var names = scope.names_in_use;
out: while (true) { if (!names) {
var m = base54(++scope.cname); scope.names_in_use = names = Object.create(scope.mangled_names || null);
if (!is_identifier(m)) continue; // skip over "do" scope.cname_holes = [];
scope.enclosed.forEach(function(def) {
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not if (def.unmangleable(options)) names[def.name] = true;
// shadow a name reserved from mangling. });
if (member(m, options.reserved)) continue;
// we must ensure that the mangled name does not shadow a name
// from some parent scope that is referenced in this or in
// inner scopes.
for (var i = ext.length; --i >= 0;) {
var sym = ext[i];
var name = sym.mangled_name || (sym.unmangleable(options) && sym.name);
if (m == name) continue out;
}
return m;
} }
return names;
} }
AST_Scope.DEFMETHOD("next_mangled", function(options){ function next_mangled_name(scope, options, def) {
return next_mangled(this, options); var in_use = names_in_use(scope, options);
}); var holes = scope.cname_holes;
var names = Object.create(null);
AST_Toplevel.DEFMETHOD("next_mangled", function(options){
var name;
do {
name = next_mangled(this, options);
} while (member(name, this.mangled_names));
return name;
});
AST_Function.DEFMETHOD("next_mangled", function(options, def){
// #179, #326 // #179, #326
// in Safari strict mode, something like (function x(x){...}) is a syntax error; // in Safari strict mode, something like (function x(x){...}) is a syntax error;
// a function expression's argument cannot shadow the function expression's name // a function expression's argument cannot shadow the function expression's name
if (scope instanceof AST_Function && scope.name && def.orig[0] instanceof AST_SymbolFunarg) {
var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition(); var tricky_def = scope.name.definition();
// the function's mangled_name is null when keep_fnames is true
// the function's mangled_name is null when keep_fnames is true names[tricky_def.mangled_name || tricky_def.name] = true;
var tricky_name = tricky_def ? tricky_def.mangled_name || tricky_def.name : null;
while (true) {
var name = next_mangled(this, options);
if (!tricky_name || tricky_name != name)
return name;
} }
}); var scopes = [ scope ];
def.references.forEach(function(sym) {
var scope = sym.scope;
do {
if (scopes.indexOf(scope) < 0) {
for (var name in names_in_use(scope, options)) {
names[name] = true;
}
scopes.push(scope);
} else break;
} while (scope = scope.parent_scope);
});
var name;
for (var i = 0, len = holes.length; i < len; i++) {
name = base54(holes[i]);
if (names[name]) continue;
holes.splice(i, 1);
scope.names_in_use[name] = true;
return name;
}
while (true) {
name = base54(++scope.cname);
if (in_use[name] || !is_identifier(name) || options.reserved.has[name]) continue;
if (!names[name]) break;
holes.push(scope.cname);
}
scope.names_in_use[name] = true;
return name;
}
AST_Symbol.DEFMETHOD("unmangleable", function(options){ AST_Symbol.DEFMETHOD("unmangleable", function(options) {
var def = this.definition(); var def = this.definition();
return !def || def.unmangleable(options); return !def || def.unmangleable(options);
}); });
@@ -384,20 +360,19 @@ AST_Symbol.DEFMETHOD("unmangleable", function(options){
// labels are always mangleable // labels are always mangleable
AST_Label.DEFMETHOD("unmangleable", return_false); AST_Label.DEFMETHOD("unmangleable", return_false);
AST_Symbol.DEFMETHOD("unreferenced", function(){ AST_Symbol.DEFMETHOD("unreferenced", function() {
return this.definition().references.length == 0 return !this.definition().references.length && !this.scope.pinned();
&& !(this.scope.uses_eval || this.scope.uses_with);
}); });
AST_Symbol.DEFMETHOD("definition", function(){ AST_Symbol.DEFMETHOD("definition", function() {
return this.thedef; return this.thedef;
}); });
AST_Symbol.DEFMETHOD("global", function(){ AST_Symbol.DEFMETHOD("global", function() {
return this.definition().global; return this.definition().global;
}); });
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) { function _default_mangler_options(options) {
options = defaults(options, { options = defaults(options, {
eval : false, eval : false,
ie8 : false, ie8 : false,
@@ -408,30 +383,28 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) {
if (!Array.isArray(options.reserved)) options.reserved = []; if (!Array.isArray(options.reserved)) options.reserved = [];
// Never mangle arguments // Never mangle arguments
push_uniq(options.reserved, "arguments"); push_uniq(options.reserved, "arguments");
options.reserved.has = makePredicate(options.reserved);
return options; return options;
}); }
AST_Toplevel.DEFMETHOD("mangle_names", function(options){ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
options = this._default_mangler_options(options); options = _default_mangler_options(options);
// We only need to mangle declaration nodes. Special logic wired // We only need to mangle declaration nodes. Special logic wired
// into the code generator will display the mangled name if it's // into the code generator will display the mangled name if it's
// present (and for AST_SymbolRef-s it'll use the mangled name of // present (and for AST_SymbolRef-s it'll use the mangled name of
// the AST_SymbolDeclaration that it points to). // the AST_SymbolDeclaration that it points to).
var lname = -1; var lname = -1;
var to_mangle = [];
var mangled_names = this.mangled_names = []; if (options.cache && options.cache.props) {
if (options.cache) { var mangled_names = this.mangled_names = Object.create(null);
this.globals.each(collect); options.cache.props.each(function(mangled_name) {
if (options.cache.props) { mangled_names[mangled_name] = true;
options.cache.props.each(function(mangled_name) { });
push_uniq(mangled_names, mangled_name);
});
}
} }
var tw = new TreeWalker(function(node, descend){ var redefined = [];
var tw = new TreeWalker(function(node, descend) {
if (node instanceof AST_LabeledStatement) { if (node instanceof AST_LabeledStatement) {
// lname is incremented when we get to the AST_Label // lname is incremented when we get to the AST_Label
var save_nesting = lname; var save_nesting = lname;
@@ -440,8 +413,12 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
return true; // don't descend again in TreeWalker return true; // don't descend again in TreeWalker
} }
if (node instanceof AST_Scope) { if (node instanceof AST_Scope) {
node.variables.each(collect); descend();
return; if (options.cache && node instanceof AST_Toplevel) {
node.globals.each(mangle);
}
node.variables.each(mangle);
return true;
} }
if (node instanceof AST_Label) { if (node instanceof AST_Label) {
var name; var name;
@@ -449,18 +426,31 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
node.mangled_name = name; node.mangled_name = name;
return true; return true;
} }
if (!options.ie8 && node instanceof AST_SymbolCatch) { if (!options.ie8 && node instanceof AST_Catch) {
to_mangle.push(node.definition()); var def = node.argname.definition();
return; var redef = def.redefined();
if (redef) {
redefined.push(def);
reference(node.argname);
def.references.forEach(reference);
}
descend();
if (!redef) mangle(def);
return true;
}
function reference(sym) {
sym.thedef = redef;
sym.reference(options);
sym.thedef = def;
} }
}); });
this.walk(tw); this.walk(tw);
to_mangle.forEach(function(def){ def.mangle(options) }); redefined.forEach(mangle);
function collect(symbol) { function mangle(def) {
if (!member(symbol.name, options.reserved)) { if (options.reserved.has[def.name]) return;
to_mangle.push(symbol); def.mangle(options);
}
} }
}); });
@@ -490,7 +480,7 @@ AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
AST_Toplevel.DEFMETHOD("expand_names", function(options) { AST_Toplevel.DEFMETHOD("expand_names", function(options) {
base54.reset(); base54.reset();
base54.sort(); base54.sort();
options = this._default_mangler_options(options); options = _default_mangler_options(options);
var avoid = this.find_colliding_names(options); var avoid = this.find_colliding_names(options);
var cname = 0; var cname = 0;
this.globals.each(rename); this.globals.each(rename);
@@ -510,7 +500,7 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
function rename(def) { function rename(def) {
if (def.global && options.cache) return; if (def.global && options.cache) return;
if (def.unmangleable(options)) return; if (def.unmangleable(options)) return;
if (member(def.name, options.reserved)) return; if (options.reserved.has[def.name]) return;
var d = def.redefined(); var d = def.redefined();
def.name = d ? d.name : next_name(); def.name = d ? d.name : next_name();
def.orig.forEach(function(sym) { def.orig.forEach(function(sym) {
@@ -527,8 +517,9 @@ AST_Sequence.DEFMETHOD("tail_node", function() {
return this.expressions[this.expressions.length - 1]; return this.expressions[this.expressions.length - 1];
}); });
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){ AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
options = this._default_mangler_options(options); options = _default_mangler_options(options);
base54.reset();
try { try {
AST_Node.prototype.print = function(stream, force_parens) { AST_Node.prototype.print = function(stream, force_parens) {
this._print(stream, force_parens); this._print(stream, force_parens);
@@ -561,17 +552,21 @@ AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
}); });
var base54 = (function() { var base54 = (function() {
var leading = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_".split(""); var freq = Object.create(null);
var digits = "0123456789".split(""); function init(chars) {
var array = [];
for (var i = 0, len = chars.length; i < len; i++) {
var ch = chars[i];
array.push(ch);
freq[ch] = -1e-2 * i;
}
return array;
}
var digits = init("0123456789");
var leading = init("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_");
var chars, frequency; var chars, frequency;
function reset() { function reset() {
frequency = Object.create(null); frequency = Object.create(freq);
leading.forEach(function(ch) {
frequency[ch] = 0;
});
digits.forEach(function(ch) {
frequency[ch] = 0;
});
} }
base54.consider = function(str, delta) { base54.consider = function(str, delta) {
for (var i = str.length; --i >= 0;) { for (var i = str.length; --i >= 0;) {
@@ -582,7 +577,7 @@ var base54 = (function() {
return frequency[b] - frequency[a]; return frequency[b] - frequency[a];
} }
base54.sort = function() { base54.sort = function() {
chars = mergeSort(leading, compare).concat(mergeSort(digits, compare)); chars = leading.sort(compare).concat(digits.sort(compare));
}; };
base54.reset = reset; base54.reset = reset;
reset(); reset();
@@ -596,6 +591,6 @@ var base54 = (function() {
base = 64; base = 64;
} while (num > 0); } while (num > 0);
return ret; return ret;
}; }
return base54; return base54;
})(); })();

View File

@@ -46,52 +46,59 @@
// a small wrapper around fitzgen's source-map library // a small wrapper around fitzgen's source-map library
function SourceMap(options) { function SourceMap(options) {
options = defaults(options, { options = defaults(options, {
file : null, file: null,
root : null, root: null,
orig : null, orig: null,
orig_line_diff: 0,
orig_line_diff : 0, dest_line_diff: 0,
dest_line_diff : 0, }, true);
});
var generator = new MOZ_SourceMap.SourceMapGenerator({ var generator = new MOZ_SourceMap.SourceMapGenerator({
file : options.file, file: options.file,
sourceRoot : options.root sourceRoot: options.root
}); });
var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig); var maps = options.orig && Object.create(null);
if (maps) for (var source in options.orig) {
if (orig_map && Array.isArray(options.orig.sources)) { var map = new MOZ_SourceMap.SourceMapConsumer(options.orig[source]);
orig_map._sources.toArray().forEach(function(source) { if (Array.isArray(options.orig[source].sources)) {
var sourceContent = orig_map.sourceContentFor(source, true); map._sources.toArray().forEach(function(source) {
if (sourceContent) { var sourceContent = map.sourceContentFor(source, true);
generator.setSourceContent(source, sourceContent); if (sourceContent) generator.setSourceContent(source, sourceContent);
}
});
}
function add(source, gen_line, gen_col, orig_line, orig_col, name) {
if (orig_map) {
var info = orig_map.originalPositionFor({
line: orig_line,
column: orig_col
}); });
if (info.source === null) {
return;
}
source = info.source;
orig_line = info.line;
orig_col = info.column;
name = info.name || name;
} }
generator.addMapping({ maps[source] = map;
generated : { line: gen_line + options.dest_line_diff, column: gen_col }, }
original : { line: orig_line + options.orig_line_diff, column: orig_col },
source : source,
name : name
});
};
return { return {
add : add, add: function(source, gen_line, gen_col, orig_line, orig_col, name) {
get : function() { return generator }, var map = maps && maps[source];
toString : function() { return JSON.stringify(generator.toJSON()); } if (map) {
var info = map.originalPositionFor({
line: orig_line,
column: orig_col
});
if (info.source === null) return;
source = info.source;
orig_line = info.line;
orig_col = info.column;
name = info.name || name;
}
generator.addMapping({
name: name,
source: source,
generated: {
line: gen_line + options.dest_line_diff,
column: gen_col
},
original: {
line: orig_line + options.orig_line_diff,
column: orig_col
}
});
},
get: function() {
return generator;
},
toString: function() {
return JSON.stringify(generator.toJSON());
}
}; };
}; }

View File

@@ -43,8 +43,6 @@
"use strict"; "use strict";
// Tree transformer helpers.
function TreeTransformer(before, after) { function TreeTransformer(before, after) {
TreeWalker.call(this); TreeWalker.call(this);
this.before = before; this.before = before;
@@ -52,163 +50,136 @@ function TreeTransformer(before, after) {
} }
TreeTransformer.prototype = new TreeWalker; TreeTransformer.prototype = new TreeWalker;
(function(undefined){ (function(DEF) {
function _(node, descend) {
node.DEFMETHOD("transform", function(tw, in_list){
var x, y;
tw.push(this);
if (tw.before) x = tw.before(this, descend, in_list);
if (x === undefined) {
x = this;
descend(x, tw);
if (tw.after) {
y = tw.after(x, in_list);
if (y !== undefined) x = y;
}
}
tw.pop();
return x;
});
};
function do_list(list, tw) { function do_list(list, tw) {
return MAP(list, function(node){ return MAP(list, function(node) {
return node.transform(tw, true); return node.transform(tw, true);
}); });
}; }
_(AST_Node, noop); DEF(AST_Node, noop);
DEF(AST_LabeledStatement, function(self, tw) {
_(AST_LabeledStatement, function(self, tw){
self.label = self.label.transform(tw); self.label = self.label.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_SimpleStatement, function(self, tw) {
_(AST_SimpleStatement, function(self, tw){
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_Block, function(self, tw) {
_(AST_Block, function(self, tw){
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Do, function(self, tw) {
_(AST_DWLoop, function(self, tw){ self.body = self.body.transform(tw);
self.condition = self.condition.transform(tw);
});
DEF(AST_While, function(self, tw) {
self.condition = self.condition.transform(tw); self.condition = self.condition.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_For, function(self, tw) {
_(AST_For, function(self, tw){
if (self.init) self.init = self.init.transform(tw); if (self.init) self.init = self.init.transform(tw);
if (self.condition) self.condition = self.condition.transform(tw); if (self.condition) self.condition = self.condition.transform(tw);
if (self.step) self.step = self.step.transform(tw); if (self.step) self.step = self.step.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_ForIn, function(self, tw) {
_(AST_ForIn, function(self, tw){
self.init = self.init.transform(tw); self.init = self.init.transform(tw);
self.object = self.object.transform(tw); self.object = self.object.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_With, function(self, tw) {
_(AST_With, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_Exit, function(self, tw) {
_(AST_Exit, function(self, tw){
if (self.value) self.value = self.value.transform(tw); if (self.value) self.value = self.value.transform(tw);
}); });
DEF(AST_LoopControl, function(self, tw) {
_(AST_LoopControl, function(self, tw){
if (self.label) self.label = self.label.transform(tw); if (self.label) self.label = self.label.transform(tw);
}); });
DEF(AST_If, function(self, tw) {
_(AST_If, function(self, tw){
self.condition = self.condition.transform(tw); self.condition = self.condition.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
if (self.alternative) self.alternative = self.alternative.transform(tw); if (self.alternative) self.alternative = self.alternative.transform(tw);
}); });
DEF(AST_Switch, function(self, tw) {
_(AST_Switch, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Case, function(self, tw) {
_(AST_Case, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Try, function(self, tw) {
_(AST_Try, function(self, tw){
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
if (self.bcatch) self.bcatch = self.bcatch.transform(tw); if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
if (self.bfinally) self.bfinally = self.bfinally.transform(tw); if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
}); });
DEF(AST_Catch, function(self, tw) {
_(AST_Catch, function(self, tw){
self.argname = self.argname.transform(tw); self.argname = self.argname.transform(tw);
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Definitions, function(self, tw) {
_(AST_Definitions, function(self, tw){
self.definitions = do_list(self.definitions, tw); self.definitions = do_list(self.definitions, tw);
}); });
DEF(AST_VarDef, function(self, tw) {
_(AST_VarDef, function(self, tw){
self.name = self.name.transform(tw); self.name = self.name.transform(tw);
if (self.value) self.value = self.value.transform(tw); if (self.value) self.value = self.value.transform(tw);
}); });
DEF(AST_Lambda, function(self, tw) {
_(AST_Lambda, function(self, tw){
if (self.name) self.name = self.name.transform(tw); if (self.name) self.name = self.name.transform(tw);
self.argnames = do_list(self.argnames, tw); self.argnames = do_list(self.argnames, tw);
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Call, function(self, tw) {
_(AST_Call, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.args = do_list(self.args, tw); self.args = do_list(self.args, tw);
}); });
DEF(AST_Sequence, function(self, tw) {
_(AST_Sequence, function(self, tw){
self.expressions = do_list(self.expressions, tw); self.expressions = do_list(self.expressions, tw);
}); });
DEF(AST_Dot, function(self, tw) {
_(AST_Dot, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
}); });
DEF(AST_Sub, function(self, tw) {
_(AST_Sub, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.property = self.property.transform(tw); self.property = self.property.transform(tw);
}); });
DEF(AST_Unary, function(self, tw) {
_(AST_Unary, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
}); });
DEF(AST_Binary, function(self, tw) {
_(AST_Binary, function(self, tw){
self.left = self.left.transform(tw); self.left = self.left.transform(tw);
self.right = self.right.transform(tw); self.right = self.right.transform(tw);
}); });
DEF(AST_Conditional, function(self, tw) {
_(AST_Conditional, function(self, tw){
self.condition = self.condition.transform(tw); self.condition = self.condition.transform(tw);
self.consequent = self.consequent.transform(tw); self.consequent = self.consequent.transform(tw);
self.alternative = self.alternative.transform(tw); self.alternative = self.alternative.transform(tw);
}); });
DEF(AST_Array, function(self, tw) {
_(AST_Array, function(self, tw){
self.elements = do_list(self.elements, tw); self.elements = do_list(self.elements, tw);
}); });
DEF(AST_Object, function(self, tw) {
_(AST_Object, function(self, tw){
self.properties = do_list(self.properties, tw); self.properties = do_list(self.properties, tw);
}); });
DEF(AST_ObjectProperty, function(self, tw) {
_(AST_ObjectProperty, function(self, tw){
self.value = self.value.transform(tw); self.value = self.value.transform(tw);
}); });
})(function(node, descend) {
})(); node.DEFMETHOD("transform", function(tw, in_list) {
var x, y;
tw.push(this);
if (tw.before) x = tw.before(this, descend, in_list);
if (typeof x === "undefined") {
x = this;
descend(x, tw);
if (tw.after) {
y = tw.after(x, in_list);
if (typeof y !== "undefined") x = y;
}
}
tw.pop();
return x;
});
});

View File

@@ -45,27 +45,23 @@
function characters(str) { function characters(str) {
return str.split(""); return str.split("");
}; }
function member(name, array) { function member(name, array) {
return array.indexOf(name) >= 0; return array.indexOf(name) >= 0;
}; }
function find_if(func, array) { function find_if(func, array) {
for (var i = 0, n = array.length; i < n; ++i) { for (var i = array.length; --i >= 0;) if (func(array[i])) return array[i];
if (func(array[i])) }
return array[i];
}
};
function repeat_string(str, i) { function repeat_string(str, i) {
if (i <= 0) return ""; if (i <= 0) return "";
if (i == 1) return str; if (i == 1) return str;
var d = repeat_string(str, i >> 1); var d = repeat_string(str, i >> 1);
d += d; d += d;
if (i & 1) d += str; return i & 1 ? d + str : d;
return d; }
};
function configure_error_stack(fn) { function configure_error_stack(fn) {
Object.defineProperty(fn.prototype, "stack", { Object.defineProperty(fn.prototype, "stack", {
@@ -84,27 +80,23 @@ function configure_error_stack(fn) {
function DefaultsError(msg, defs) { function DefaultsError(msg, defs) {
this.message = msg; this.message = msg;
this.defs = defs; this.defs = defs;
}; }
DefaultsError.prototype = Object.create(Error.prototype); DefaultsError.prototype = Object.create(Error.prototype);
DefaultsError.prototype.constructor = DefaultsError; DefaultsError.prototype.constructor = DefaultsError;
DefaultsError.prototype.name = "DefaultsError"; DefaultsError.prototype.name = "DefaultsError";
configure_error_stack(DefaultsError); configure_error_stack(DefaultsError);
DefaultsError.croak = function(msg, defs) {
throw new DefaultsError(msg, defs);
};
function defaults(args, defs, croak) { function defaults(args, defs, croak) {
if (args === true) if (args === true) args = {};
args = {};
var ret = args || {}; var ret = args || {};
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i)) if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
DefaultsError.croak("`" + i + "` is not a supported option", defs); throw new DefaultsError("`" + i + "` is not a supported option", defs);
}
for (var i in defs) if (HOP(defs, i)) { for (var i in defs) if (HOP(defs, i)) {
ret[i] = (args && HOP(args, i)) ? args[i] : defs[i]; ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
} }
return ret; return ret;
}; }
function merge(obj, ext) { function merge(obj, ext) {
var count = 0; var count = 0;
@@ -113,7 +105,7 @@ function merge(obj, ext) {
count++; count++;
} }
return count; return count;
}; }
function noop() {} function noop() {}
function return_false() { return false; } function return_false() { return false; }
@@ -121,7 +113,7 @@ function return_true() { return true; }
function return_this() { return this; } function return_this() { return this; }
function return_null() { return null; } function return_null() { return null; }
var MAP = (function(){ var MAP = (function() {
function MAP(a, f, backwards) { function MAP(a, f, backwards) {
var ret = [], top = [], i; var ret = [], top = [], i;
function doit() { function doit() {
@@ -144,8 +136,8 @@ var MAP = (function(){
} }
} }
return is_last; return is_last;
}; }
if (a instanceof Array) { if (Array.isArray(a)) {
if (backwards) { if (backwards) {
for (i = a.length; --i >= 0;) if (doit()) break; for (i = a.length; --i >= 0;) if (doit()) break;
ret.reverse(); ret.reverse();
@@ -158,115 +150,54 @@ var MAP = (function(){
for (i in a) if (HOP(a, i)) if (doit()) break; for (i in a) if (HOP(a, i)) if (doit()) break;
} }
return top.concat(ret); return top.concat(ret);
}; }
MAP.at_top = function(val) { return new AtTop(val) }; MAP.at_top = function(val) { return new AtTop(val) };
MAP.splice = function(val) { return new Splice(val) }; MAP.splice = function(val) { return new Splice(val) };
MAP.last = function(val) { return new Last(val) }; MAP.last = function(val) { return new Last(val) };
var skip = MAP.skip = {}; var skip = MAP.skip = {};
function AtTop(val) { this.v = val }; function AtTop(val) { this.v = val }
function Splice(val) { this.v = val }; function Splice(val) { this.v = val }
function Last(val) { this.v = val }; function Last(val) { this.v = val }
return MAP; return MAP;
})(); })();
function push_uniq(array, el) { function push_uniq(array, el) {
if (array.indexOf(el) < 0) if (array.indexOf(el) < 0)
array.push(el); array.push(el);
}; }
function string_template(text, props) { function string_template(text, props) {
return text.replace(/\{(.+?)\}/g, function(str, p){ return text.replace(/\{(.+?)\}/g, function(str, p) {
return props && props[p]; return props && props[p];
}); });
}; }
function remove(array, el) { function remove(array, el) {
for (var i = array.length; --i >= 0;) { for (var i = array.length; --i >= 0;) {
if (array[i] === el) array.splice(i, 1); if (array[i] === el) array.splice(i, 1);
} }
}; }
function mergeSort(array, cmp) {
if (array.length < 2) return array.slice();
function merge(a, b) {
var r = [], ai = 0, bi = 0, i = 0;
while (ai < a.length && bi < b.length) {
cmp(a[ai], b[bi]) <= 0
? r[i++] = a[ai++]
: r[i++] = b[bi++];
}
if (ai < a.length) r.push.apply(r, a.slice(ai));
if (bi < b.length) r.push.apply(r, b.slice(bi));
return r;
};
function _ms(a) {
if (a.length <= 1)
return a;
var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
left = _ms(left);
right = _ms(right);
return merge(left, right);
};
return _ms(array);
};
// this function is taken from Acorn [1], written by Marijn Haverbeke
// [1] https://github.com/marijnh/acorn
function makePredicate(words) { function makePredicate(words) {
if (!(words instanceof Array)) words = words.split(" "); if (!Array.isArray(words)) words = words.split(" ");
var f = "", cats = []; var map = Object.create(null);
out: for (var i = 0; i < words.length; ++i) { words.forEach(function(word) {
for (var j = 0; j < cats.length; ++j) map[word] = true;
if (cats[j][0].length == words[i].length) { });
cats[j].push(words[i]); return map;
continue out; }
}
cats.push([words[i]]);
}
function quote(word) {
return JSON.stringify(word).replace(/[\u2028\u2029]/g, function(s) {
switch (s) {
case "\u2028": return "\\u2028";
case "\u2029": return "\\u2029";
}
return s;
});
}
function compareTo(arr) {
if (arr.length == 1) return f += "return str === " + quote(arr[0]) + ";";
f += "switch(str){";
for (var i = 0; i < arr.length; ++i) f += "case " + quote(arr[i]) + ":";
f += "return true}return false;";
}
// When there are more than three length categories, an outer
// switch first dispatches on the lengths, to save on comparisons.
if (cats.length > 3) {
cats.sort(function(a, b) {return b.length - a.length;});
f += "switch(str.length){";
for (var i = 0; i < cats.length; ++i) {
var cat = cats[i];
f += "case " + cat[0].length + ":";
compareTo(cat);
}
f += "}";
// Otherwise, simply generate a flat `switch` statement.
} else {
compareTo(words);
}
return new Function("str", f);
};
function all(array, predicate) { function all(array, predicate) {
for (var i = array.length; --i >= 0;) for (var i = array.length; --i >= 0;)
if (!predicate(array[i])) if (!predicate(array[i]))
return false; return false;
return true; return true;
}; }
function Dictionary() { function Dictionary() {
this._values = Object.create(null); this._values = Object.create(null);
this._size = 0; this._size = 0;
}; }
Dictionary.prototype = { Dictionary.prototype = {
set: function(key, val) { set: function(key, val) {
if (!this.has(key)) ++this._size; if (!this.has(key)) ++this._size;
@@ -327,20 +258,22 @@ function HOP(obj, prop) {
// a statement. // a statement.
function first_in_statement(stack) { function first_in_statement(stack) {
var node = stack.parent(-1); var node = stack.parent(-1);
for (var i = 0, p; p = stack.parent(i); i++) { for (var i = 0, p; p = stack.parent(i++); node = p) {
if (p instanceof AST_Statement && p.body === node) if (p.TYPE == "Call") {
return true; if (p.expression === node) continue;
if ((p instanceof AST_Sequence && p.expressions[0] === node) || } else if (p instanceof AST_Binary) {
(p.TYPE == "Call" && p.expression === node ) || if (p.left === node) continue;
(p instanceof AST_Dot && p.expression === node ) || } else if (p instanceof AST_Conditional) {
(p instanceof AST_Sub && p.expression === node ) || if (p.condition === node) continue;
(p instanceof AST_Conditional && p.condition === node ) || } else if (p instanceof AST_PropAccess) {
(p instanceof AST_Binary && p.left === node ) || if (p.expression === node) continue;
(p instanceof AST_UnaryPostfix && p.expression === node )) } else if (p instanceof AST_Sequence) {
{ if (p.expressions[0] === node) continue;
node = p; } else if (p instanceof AST_Statement) {
} else { return p.body === node;
return false; } else if (p instanceof AST_UnaryPostfix) {
if (p.expression === node) continue;
} }
return false;
} }
} }

View File

@@ -1,10 +1,9 @@
{ {
"name": "uglify-js", "name": "uglify-js",
"description": "JavaScript parser, mangler/compressor and beautifier toolkit", "description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"homepage": "http://lisperator.net/uglifyjs",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)", "author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"version": "3.3.10", "version": "3.4.3",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=0.8.0"
}, },
@@ -24,16 +23,38 @@
"LICENSE" "LICENSE"
], ],
"dependencies": { "dependencies": {
"commander": "~2.14.1", "commander": "~2.16.0",
"source-map": "~0.6.1" "source-map": "~0.6.1"
}, },
"devDependencies": { "devDependencies": {
"acorn": "~5.4.1", "acorn": "~5.7.1",
"mocha": "~3.5.1",
"semver": "~5.5.0" "semver": "~5.5.0"
}, },
"scripts": { "scripts": {
"test": "node test/run-tests.js" "test": "node test/run-tests.js"
}, },
"keywords": ["uglify", "uglify-js", "minify", "minifier", "es5"] "keywords": [
"cli",
"compress",
"compressor",
"ecma",
"ecmascript",
"es",
"es5",
"javascript",
"js",
"jsmin",
"min",
"minification",
"minifier",
"minify",
"optimize",
"optimizer",
"pack",
"packer",
"parse",
"parser",
"uglifier",
"uglify"
]
} }

View File

@@ -28,6 +28,7 @@ var remaining = 2 * urls.length;
function done() { function done() {
if (!--remaining) { if (!--remaining) {
var failures = []; var failures = [];
var sum = { input: 0, output: 0, gzip: 0 };
urls.forEach(function(url) { urls.forEach(function(url) {
var info = results[url]; var info = results[url];
console.log(); console.log();
@@ -40,6 +41,9 @@ function done() {
if (info.code) { if (info.code) {
failures.push(url); failures.push(url);
} }
sum.input += info.input;
sum.output += info.output;
sum.gzip += info.gzip;
}); });
if (failures.length) { if (failures.length) {
console.error("Benchmark failed:"); console.error("Benchmark failed:");
@@ -47,6 +51,13 @@ function done() {
console.error(url); console.error(url);
}); });
process.exit(1); process.exit(1);
} else {
console.log();
console.log("Subtotal");
console.log();
console.log("Original:", sum.input, "bytes");
console.log("Uglified:", sum.output, "bytes");
console.log("GZipped: ", sum.gzip, "bytes");
} }
} }
} }

239
test/compress/arguments.js Normal file
View File

@@ -0,0 +1,239 @@
replace_index: {
options = {
arguments: true,
evaluate: true,
properties: true,
}
input: {
var arguments = [];
console.log(arguments[0]);
(function() {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(arguments) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function() {
var arguments;
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
}
expect: {
var arguments = [];
console.log(arguments[0]);
(function() {
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
(function(a, b) {
console.log(b, b, arguments.foo);
})("bar", 42);
(function(arguments) {
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
(function() {
var arguments;
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
}
expect_stdout: [
"undefined",
"42 42 undefined",
"42 42 undefined",
"a a undefined",
"42 42 undefined",
]
}
replace_index_strict: {
options = {
arguments: true,
evaluate: true,
properties: true,
reduce_vars: true,
}
input: {
"use strict";
(function() {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
}
expect: {
"use strict";
(function() {
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
(function(a, b) {
console.log(b, b, arguments.foo);
})("bar", 42);
}
expect_stdout: [
"42 42 undefined",
"42 42 undefined",
]
}
replace_index_keep_fargs: {
options = {
arguments: true,
evaluate: true,
keep_fargs: false,
properties: true,
}
input: {
var arguments = [];
console.log(arguments[0]);
(function() {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(arguments) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function() {
var arguments;
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
}
expect: {
var arguments = [];
console.log(arguments[0]);
(function(argument_0, argument_1) {
console.log(argument_1, argument_1, arguments.foo);
})("bar", 42);
(function(a, b) {
console.log(b, b, arguments.foo);
})("bar", 42);
(function(arguments) {
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
(function() {
var arguments;
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
}
expect_stdout: [
"undefined",
"42 42 undefined",
"42 42 undefined",
"a a undefined",
"42 42 undefined",
]
}
replace_index_keep_fargs_strict: {
options = {
arguments: true,
evaluate: true,
keep_fargs: false,
properties: true,
reduce_vars: true,
}
input: {
"use strict";
(function() {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
}
expect: {
"use strict";
(function(argument_0, argument_1) {
console.log(argument_1, argument_1, arguments.foo);
})("bar", 42);
(function(a, b) {
console.log(b, b, arguments.foo);
})("bar", 42);
}
expect_stdout: [
"42 42 undefined",
"42 42 undefined",
]
}
modified: {
options = {
arguments: true,
}
input: {
(function(a, b) {
var c = arguments[0];
var d = arguments[1];
var a = "foo";
b++;
arguments[0] = "moo";
arguments[1] *= 2;
console.log(a, b, c, d, arguments[0], arguments[1]);
})("bar", 42);
}
expect: {
(function(a, b) {
var c = a;
var d = b;
var a = "foo";
b++;
a = "moo";
b *= 2;
console.log(a, b, c, d, a, b);
})("bar", 42);
}
expect_stdout: "moo 86 bar 42 moo 86"
}
modified_strict: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
"use strict";
(function(a, b) {
var c = arguments[0];
var d = arguments[1];
var a = "foo";
b++;
arguments[0] = "moo";
arguments[1] *= 2;
console.log(a, b, c, d, arguments[0], arguments[1]);
})("bar", 42);
}
expect: {
"use strict";
(function(a, b) {
var c = arguments[0];
var d = arguments[1];
var a = "foo";
b++;
arguments[0] = "moo";
arguments[1] *= 2;
console.log(a, b, c, d, arguments[0], arguments[1]);
})("bar", 42);
}
expect_stdout: "foo 43 bar 42 moo 84"
}
duplicate_argname: {
options = {
arguments: true,
}
input: {
(function(a, b, a) {
console.log(a, b, arguments[0], arguments[1], arguments[2]);
})("foo", 42, "bar");
}
expect: {
(function(a, b, a) {
console.log(a, b, arguments[0], b, a);
})("foo", 42, "bar");
}
expect_stdout: "bar 42 foo 42 bar"
}

View File

@@ -15,9 +15,9 @@ holes_and_undefined: {
constant_join: { constant_join: {
options = { options = {
unsafe : true, evaluate: true,
evaluate : true unsafe: true,
}; }
input: { input: {
var a = [ "foo", "bar", "baz" ].join(""); var a = [ "foo", "bar", "baz" ].join("");
var a1 = [ "foo", "bar", "baz" ].join(); var a1 = [ "foo", "bar", "baz" ].join();
@@ -64,9 +64,9 @@ constant_join: {
constant_join_2: { constant_join_2: {
options = { options = {
unsafe : true, evaluate: true,
evaluate : true unsafe: true,
}; }
input: { input: {
var a = [ "foo", "bar", boo(), "baz", "x", "y" ].join(""); var a = [ "foo", "bar", boo(), "baz", "x", "y" ].join("");
var b = [ "foo", "bar", boo(), "baz", "x", "y" ].join("-"); var b = [ "foo", "bar", boo(), "baz", "x", "y" ].join("-");
@@ -93,9 +93,9 @@ constant_join_2: {
constant_join_3: { constant_join_3: {
options = { options = {
unsafe: true,
evaluate: true, evaluate: true,
}; unsafe: true,
}
input: { input: {
var a = [ null ].join(); var a = [ null ].join();
var b = [ , ].join(); var b = [ , ].join();
@@ -133,7 +133,7 @@ for_loop: {
reduce_vars: true, reduce_vars: true,
unsafe: true, unsafe: true,
unused: true, unused: true,
}; }
input: { input: {
function f0() { function f0() {
var a = [1, 2, 3]; var a = [1, 2, 3];

View File

@@ -1,24 +1,24 @@
asm_mixed: { asm_mixed: {
options = { options = {
sequences : true, booleans: true,
properties : true, comparisons: true,
dead_code : true, conditionals: true,
drop_debugger : true, dead_code: true,
conditionals : true, drop_debugger: true,
comparisons : true, evaluate: true,
evaluate : true, hoist_funs: true,
booleans : true, hoist_vars: true,
loops : true, if_return: true,
unused : true, join_vars: true,
hoist_funs : true, keep_fargs: true,
keep_fargs : true, keep_fnames: false,
keep_fnames : false, loops: true,
hoist_vars : true, negate_iife: true,
if_return : true, properties: true,
join_vars : true, sequences: true,
side_effects : true, side_effects: true,
negate_iife : true unused: true,
}; }
input: { input: {
// adapted from http://asmjs.org/spec/latest/ // adapted from http://asmjs.org/spec/latest/
function asm_GeometricMean(stdlib, foreign, buffer) { function asm_GeometricMean(stdlib, foreign, buffer) {

File diff suppressed because it is too large Load Diff

View File

@@ -1,62 +1,42 @@
keep_comparisons: { comparisons: {
options = { options = {
comparisons: true, comparisons: true,
unsafe_comps: false
} }
input: { input: {
var obj1 = { var obj1, obj2;
valueOf: function() {triggeredFirst();}
}
var obj2 = {
valueOf: function() {triggeredSecond();}
}
var result1 = obj1 <= obj2; var result1 = obj1 <= obj2;
var result2 = obj1 < obj2; var result2 = obj1 < obj2;
var result3 = obj1 >= obj2; var result3 = obj1 >= obj2;
var result4 = obj1 > obj2; var result4 = obj1 > obj2;
} }
expect: { expect: {
var obj1 = { var obj1, obj2;
valueOf: function() {triggeredFirst();}
}
var obj2 = {
valueOf: function() {triggeredSecond();}
}
var result1 = obj1 <= obj2; var result1 = obj1 <= obj2;
var result2 = obj1 < obj2; var result2 = obj1 < obj2;
var result3 = obj1 >= obj2; var result3 = obj2 <= obj1;
var result4 = obj1 > obj2; var result4 = obj2 < obj1;
} }
} }
keep_comparisons_with_unsafe_comps: { unsafe_comps: {
options = { options = {
comparisons: true, comparisons: true,
unsafe_comps: true conditionals: true,
unsafe_comps: true,
} }
input: { input: {
var obj1 = { var obj1, obj2;
valueOf: function() {triggeredFirst();} obj1 <= obj2 ? f1() : g1();
} obj1 < obj2 ? f2() : g2();
var obj2 = { obj1 >= obj2 ? f3() : g3();
valueOf: function() {triggeredSecond();} obj1 > obj2 ? f4() : g4();
}
var result1 = obj1 <= obj2;
var result2 = obj1 < obj2;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
} }
expect: { expect: {
var obj1 = { var obj1, obj2;
valueOf: function() {triggeredFirst();} obj2 < obj1 ? g1() : f1();
} obj1 < obj2 ? f2() : g2();
var obj2 = { obj1 < obj2 ? g3() : f3();
valueOf: function() {triggeredSecond();} obj2 < obj1 ? f4() : g4();
}
var result1 = obj2 >= obj1;
var result2 = obj2 > obj1;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
} }
} }
@@ -315,3 +295,31 @@ issue_2857_6: {
} }
expect_stdout: "true" expect_stdout: "true"
} }
is_boolean_unsafe: {
options = {
comparisons: true,
unsafe: true,
}
input: {
console.log(/foo/.test("bar") === [].isPrototypeOf({}));
}
expect: {
console.log(/foo/.test("bar") == [].isPrototypeOf({}));
}
expect_stdout: "true"
}
is_number_unsafe: {
options = {
comparisons: true,
unsafe: true,
}
input: {
console.log(Math.acos(42) !== "foo".charCodeAt(4));
}
expect: {
console.log(Math.acos(42) != "foo".charCodeAt(4));
}
expect_stdout: "true"
}

View File

@@ -1,7 +1,7 @@
concat_1: { concat_1: {
options = { options = {
evaluate: true evaluate: true,
}; }
input: { input: {
var a = "foo" + "bar" + x() + "moo" + "foo" + y() + "x" + "y" + "z" + q(); var a = "foo" + "bar" + x() + "moo" + "foo" + y() + "x" + "y" + "z" + q();
var b = "foo" + 1 + x() + 2 + "boo"; var b = "foo" + 1 + x() + 2 + "boo";
@@ -26,7 +26,7 @@ concat_1: {
} }
concat_2: { concat_2: {
options = {}; options = {}
input: { input: {
console.log( console.log(
1 + (2 + 3), 1 + (2 + 3),
@@ -55,7 +55,7 @@ concat_2: {
} }
concat_3: { concat_3: {
options = {}; options = {}
input: { input: {
console.log( console.log(
1 + 2 + (3 + 4 + 5), 1 + 2 + (3 + 4 + 5),
@@ -84,7 +84,7 @@ concat_3: {
} }
concat_4: { concat_4: {
options = {}; options = {}
input: { input: {
console.log( console.log(
1 + "2" + (3 + 4 + 5), 1 + "2" + (3 + 4 + 5),
@@ -113,7 +113,7 @@ concat_4: {
} }
concat_5: { concat_5: {
options = {}; options = {}
input: { input: {
console.log( console.log(
"1" + 2 + (3 + 4 + 5), "1" + 2 + (3 + 4 + 5),
@@ -142,7 +142,7 @@ concat_5: {
} }
concat_6: { concat_6: {
options = {}; options = {}
input: { input: {
console.log( console.log(
"1" + "2" + (3 + 4 + 5), "1" + "2" + (3 + 4 + 5),

View File

@@ -1,7 +1,7 @@
ifs_1: { ifs_1: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
if (foo) bar(); if (foo) bar();
if (!foo); else bar(); if (!foo); else bar();
@@ -18,8 +18,8 @@ ifs_1: {
ifs_2: { ifs_2: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
if (foo) { if (foo) {
x(); x();
@@ -47,12 +47,12 @@ ifs_2: {
ifs_3_should_warn: { ifs_3_should_warn: {
options = { options = {
conditionals : true, booleans: true,
dead_code : true, conditionals: true,
evaluate : true, dead_code: true,
booleans : true, evaluate: true,
side_effects : true, side_effects: true,
}; }
input: { input: {
var x, y; var x, y;
if (x && !(x + "1") && y) { // 1 if (x && !(x + "1") && y) { // 1
@@ -78,8 +78,8 @@ ifs_3_should_warn: {
ifs_4: { ifs_4: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
if (foo && bar) { if (foo && bar) {
x(foo)[10].bar.baz = something(); x(foo)[10].bar.baz = something();
@@ -95,10 +95,10 @@ ifs_4: {
ifs_5: { ifs_5: {
options = { options = {
if_return: true,
conditionals: true,
comparisons: true, comparisons: true,
}; conditionals: true,
if_return: true,
}
input: { input: {
function f() { function f() {
if (foo) return; if (foo) return;
@@ -132,9 +132,9 @@ ifs_5: {
ifs_6: { ifs_6: {
options = { options = {
comparisons: true,
conditionals: true, conditionals: true,
comparisons: true }
};
input: { input: {
var x, y; var x, y;
if (!foo && !bar && !baz && !boo) { if (!foo && !bar && !baz && !boo) {
@@ -163,8 +163,8 @@ ifs_6: {
cond_1: { cond_1: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
function foo(do_something, some_condition) { function foo(do_something, some_condition) {
if (some_condition) { if (some_condition) {
@@ -189,8 +189,8 @@ cond_1: {
cond_2: { cond_2: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
function foo(x, FooBar, some_condition) { function foo(x, FooBar, some_condition) {
if (some_condition) { if (some_condition) {
@@ -209,8 +209,8 @@ cond_2: {
cond_3: { cond_3: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
var FooBar; var FooBar;
if (some_condition()) { if (some_condition()) {
@@ -227,8 +227,8 @@ cond_3: {
cond_4: { cond_4: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
var do_something; var do_something;
if (some_condition()) { if (some_condition()) {
@@ -251,8 +251,8 @@ cond_4: {
cond_5: { cond_5: {
options = { options = {
conditionals: true conditionals: true,
}; }
input: { input: {
if (some_condition()) { if (some_condition()) {
if (some_other_condition()) { if (some_other_condition()) {
@@ -279,9 +279,9 @@ cond_5: {
cond_7: { cond_7: {
options = { options = {
conditionals: true, conditionals: true,
evaluate : true, evaluate: true,
side_effects: true, side_effects: true,
}; }
input: { input: {
var x, y, z, a, b; var x, y, z, a, b;
// compress these // compress these
@@ -332,7 +332,7 @@ cond_7: {
x = 'foo'; x = 'foo';
x = 'foo'; x = 'foo';
x = (condition(), 20); x = (condition(), 20);
x = z ? 'fuji' : (condition(), 'fuji'); x = (z || condition(), 'fuji');
x = (condition(), 'foobar'); x = (condition(), 'foobar');
x = y ? a : b; x = y ? a : b;
x = y ? 'foo' : 'fo'; x = y ? 'foo' : 'fo';
@@ -342,8 +342,8 @@ cond_7: {
cond_7_1: { cond_7_1: {
options = { options = {
conditionals: true, conditionals: true,
evaluate : true evaluate: true,
}; }
input: { input: {
var x; var x;
// access to global should be assumed to have side effects // access to global should be assumed to have side effects
@@ -361,10 +361,10 @@ cond_7_1: {
cond_8: { cond_8: {
options = { options = {
booleans: false,
conditionals: true, conditionals: true,
evaluate : true, evaluate: true,
booleans : false }
};
input: { input: {
var a; var a;
// compress these // compress these
@@ -445,10 +445,10 @@ cond_8: {
cond_8b: { cond_8b: {
options = { options = {
booleans: true,
conditionals: true, conditionals: true,
evaluate : true, evaluate: true,
booleans : true }
};
input: { input: {
var a; var a;
// compress these // compress these
@@ -528,10 +528,10 @@ cond_8b: {
cond_8c: { cond_8c: {
options = { options = {
booleans: false,
conditionals: true, conditionals: true,
evaluate : false, evaluate: false,
booleans : false }
};
input: { input: {
var a; var a;
// compress these // compress these
@@ -647,9 +647,21 @@ cond_9: {
ternary_boolean_consequent: { ternary_boolean_consequent: {
options = { options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true, booleans: true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true, collapse_vars: true,
keep_fargs:true, if_return:true, join_vars:true, side_effects:true comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: true,
side_effects: true,
unused: true,
} }
input: { input: {
function f1() { return a == b ? true : x; } function f1() { return a == b ? true : x; }
@@ -675,9 +687,21 @@ ternary_boolean_consequent: {
ternary_boolean_alternative: { ternary_boolean_alternative: {
options = { options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true, booleans: true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true, collapse_vars: true,
keep_fargs:true, if_return:true, join_vars:true, side_effects:true comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: true,
side_effects: true,
unused: true,
} }
input: { input: {
function f1() { return a == b ? x : true; } function f1() { return a == b ? x : true; }
@@ -703,10 +727,11 @@ ternary_boolean_alternative: {
trivial_boolean_ternary_expressions : { trivial_boolean_ternary_expressions : {
options = { options = {
booleans: true,
conditionals: true, conditionals: true,
evaluate : true, evaluate: true,
booleans : true side_effects: true,
}; }
input: { input: {
f('foo' in m ? true : false); f('foo' in m ? true : false);
f('foo' in m ? false : true); f('foo' in m ? false : true);
@@ -777,11 +802,11 @@ trivial_boolean_ternary_expressions : {
issue_1154: { issue_1154: {
options = { options = {
booleans: true,
conditionals: true, conditionals: true,
evaluate : true, evaluate: true,
booleans : true,
side_effects: true, side_effects: true,
}; }
input: { input: {
function f1(x) { return x ? -1 : -1; } function f1(x) { return x ? -1 : -1; }
function f2(x) { return x ? +2 : +2; } function f2(x) { return x ? +2 : +2; }
@@ -817,7 +842,7 @@ issue_1154: {
no_evaluate: { no_evaluate: {
options = { options = {
conditionals: true, conditionals: true,
evaluate : false, evaluate: false,
side_effects: true, side_effects: true,
} }
input: { input: {

View File

@@ -1,7 +1,7 @@
dead_code_1: { dead_code_1: {
options = { options = {
dead_code: true dead_code: true,
}; }
input: { input: {
function f() { function f() {
a(); a();
@@ -25,8 +25,8 @@ dead_code_1: {
dead_code_2_should_warn: { dead_code_2_should_warn: {
options = { options = {
dead_code: true dead_code: true,
}; }
input: { input: {
function f() { function f() {
g(); g();
@@ -64,13 +64,13 @@ dead_code_2_should_warn: {
dead_code_constant_boolean_should_warn_more: { dead_code_constant_boolean_should_warn_more: {
options = { options = {
dead_code : true, booleans: true,
loops : true, conditionals: true,
booleans : true, dead_code: true,
conditionals : true, evaluate: true,
evaluate : true, loops: true,
side_effects : true, side_effects: true,
}; }
input: { input: {
while (!((foo && bar) || (x + "0"))) { while (!((foo && bar) || (x + "0"))) {
console.log("unreachable"); console.log("unreachable");
@@ -917,3 +917,28 @@ issue_2860_2: {
} }
expect_stdout: "1" expect_stdout: "1"
} }
issue_2929: {
options = {
dead_code: true,
}
input: {
console.log(function(a) {
try {
return null.p = a = 1;
} catch (e) {
return a ? "PASS" : "FAIL";
}
}());
}
expect: {
console.log(function(a) {
try {
return null.p = a = 1;
} catch (e) {
return a ? "PASS" : "FAIL";
}
}());
}
expect_stdout: "PASS"
}

View File

@@ -1,7 +1,7 @@
keep_debugger: { keep_debugger: {
options = { options = {
drop_debugger: false drop_debugger: false,
}; }
input: { input: {
debugger; debugger;
} }
@@ -12,8 +12,8 @@ keep_debugger: {
drop_debugger: { drop_debugger: {
options = { options = {
drop_debugger: true drop_debugger: true,
}; }
input: { input: {
debugger; debugger;
if (foo) debugger; if (foo) debugger;

View File

@@ -1,5 +1,5 @@
drop_console_1: { drop_console_1: {
options = {}; options = {}
input: { input: {
console.log('foo'); console.log('foo');
console.log.apply(console, arguments); console.log.apply(console, arguments);
@@ -11,7 +11,9 @@ drop_console_1: {
} }
drop_console_2: { drop_console_2: {
options = { drop_console: true }; options = {
drop_console: true,
}
input: { input: {
console.log('foo'); console.log('foo');
console.log.apply(console, arguments); console.log.apply(console, arguments);

View File

@@ -1,5 +1,8 @@
unused_funarg_1: { unused_funarg_1: {
options = { unused: true, keep_fargs: false }; options = {
keep_fargs: false,
unused: true,
}
input: { input: {
function f(a, b, c, d, e) { function f(a, b, c, d, e) {
return a + b; return a + b;
@@ -13,7 +16,10 @@ unused_funarg_1: {
} }
unused_funarg_2: { unused_funarg_2: {
options = { unused: true, keep_fargs: false }; options = {
keep_fargs: false,
unused: true,
}
input: { input: {
function f(a, b, c, d, e) { function f(a, b, c, d, e) {
return a + c; return a + c;
@@ -27,7 +33,9 @@ unused_funarg_2: {
} }
unused_nested_function: { unused_nested_function: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function f(x, y) { function f(x, y) {
function g() { function g() {
@@ -44,7 +52,9 @@ unused_nested_function: {
} }
unused_circular_references_1: { unused_circular_references_1: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function f(x, y) { function f(x, y) {
// circular reference // circular reference
@@ -65,7 +75,9 @@ unused_circular_references_1: {
} }
unused_circular_references_2: { unused_circular_references_2: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function f(x, y) { function f(x, y) {
var foo = 1, bar = baz, baz = foo + bar, qwe = moo(); var foo = 1, bar = baz, baz = foo + bar, qwe = moo();
@@ -81,7 +93,9 @@ unused_circular_references_2: {
} }
unused_circular_references_3: { unused_circular_references_3: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function f(x, y) { function f(x, y) {
var g = function() { return h() }; var g = function() { return h() };
@@ -97,7 +111,9 @@ unused_circular_references_3: {
} }
unused_keep_setter_arg: { unused_keep_setter_arg: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
var x = { var x = {
_foo: null, _foo: null,
@@ -121,7 +137,9 @@ unused_keep_setter_arg: {
} }
unused_var_in_catch: { unused_var_in_catch: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function foo() { function foo() {
try { try {
@@ -141,7 +159,9 @@ unused_var_in_catch: {
} }
used_var_in_catch: { used_var_in_catch: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function foo() { function foo() {
try { try {
@@ -165,7 +185,11 @@ used_var_in_catch: {
} }
keep_fnames: { keep_fnames: {
options = { unused: true, keep_fnames: true, unsafe: true }; options = {
keep_fnames: true,
unsafe: true,
unused: true,
}
input: { input: {
function foo() { function foo() {
return function bar(baz) {}; return function bar(baz) {};
@@ -367,7 +391,7 @@ drop_toplevel_vars_fargs: {
drop_toplevel_all: { drop_toplevel_all: {
options = { options = {
toplevel: true, toplevel: true,
unused: true unused: true,
} }
input: { input: {
var a, b = 1, c = g; var a, b = 1, c = g;
@@ -418,7 +442,11 @@ drop_toplevel_retain: {
drop_toplevel_retain_array: { drop_toplevel_retain_array: {
options = { options = {
top_retain: [ "f", "a", "o" ], top_retain: [
"f",
"a",
"o"
],
unused: true, unused: true,
} }
input: { input: {
@@ -476,8 +504,8 @@ drop_toplevel_retain_regex: {
drop_toplevel_all_retain: { drop_toplevel_all_retain: {
options = { options = {
toplevel: true,
top_retain: "f,a,o", top_retain: "f,a,o",
toplevel: true,
unused: true, unused: true,
} }
input: { input: {
@@ -506,8 +534,8 @@ drop_toplevel_all_retain: {
drop_toplevel_funcs_retain: { drop_toplevel_funcs_retain: {
options = { options = {
toplevel: "funcs",
top_retain: "f,a,o", top_retain: "f,a,o",
toplevel: "funcs",
unused: true, unused: true,
} }
input: { input: {
@@ -537,8 +565,8 @@ drop_toplevel_funcs_retain: {
drop_toplevel_vars_retain: { drop_toplevel_vars_retain: {
options = { options = {
toplevel: "vars",
top_retain: "f,a,o", top_retain: "f,a,o",
toplevel: "vars",
unused: true, unused: true,
} }
input: { input: {
@@ -1377,9 +1405,9 @@ issue_2516_1: {
issue_2516_2: { issue_2516_2: {
options = { options = {
collapse_vars: true, collapse_vars: true,
passes: 2,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
passes: 2,
unused: true, unused: true,
} }
input: { input: {
@@ -1719,3 +1747,238 @@ issue_2846: {
} }
expect_stdout: "0" expect_stdout: "0"
} }
issue_805_1: {
options = {
inline: true,
passes: 2,
pure_getters: "strict",
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
(function(a) {
var unused = function() {};
unused.prototype[a()] = 42;
(unused.prototype.bar = function() {
console.log("bar");
})();
return unused;
})(function() {
console.log("foo");
return "foo";
});
}
expect: {
console.log("foo"),
console.log("bar");
}
expect_stdout: [
"foo",
"bar",
]
}
issue_805_2: {
options = {
inline: true,
passes: 2,
pure_getters: "strict",
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
(function(a) {
function unused() {}
unused.prototype[a()] = 42;
(unused.prototype.bar = function() {
console.log("bar");
})();
return unused;
})(function() {
console.log("foo");
return "foo";
});
}
expect: {
console.log("foo"),
console.log("bar");
}
expect_stdout: [
"foo",
"bar",
]
}
issue_2995: {
options = {
pure_getters: "strict",
reduce_vars: true,
unused: true,
}
input: {
function f(a) {
var b;
a.b = b = function() {};
b.c = "PASS";
}
var o = {};
f(o);
console.log(o.b.c);
}
expect: {
function f(a) {
var b;
a.b = b = function() {};
b.c = "PASS";
}
var o = {};
f(o);
console.log(o.b.c);
}
expect_stdout: "PASS"
}
issue_3146_1: {
options = {
collapse_vars: true,
unused: true,
}
input: {
(function(f) {
f("g()");
})(function(a) {
eval(a);
function g(b) {
if (!b) b = "PASS";
console.log(b);
}
});
}
expect: {
(function(f) {
f("g()");
})(function(a) {
eval(a);
function g(b) {
if (!b) b = "PASS";
console.log(b);
}
});
}
expect_stdout: "PASS"
}
issue_3146_2: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function(f) {
f("g()");
})(function(a) {
eval(a);
function g(b) {
if (!b) b = "PASS";
console.log(b);
}
});
}
expect: {
(function(f) {
f("g()");
})(function(a) {
eval(a);
function g(b) {
if (!b) b = "PASS";
console.log(b);
}
});
}
expect_stdout: "PASS"
}
issue_3146_3: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var g = "PASS";
(function(f) {
var g = "FAIL";
f("console.log(g)", g[g]);
})(function(a) {
eval(a);
});
}
expect: {
var g = "PASS";
(function(f) {
var g = "FAIL";
f("console.log(g)", g[g]);
})(function(a) {
eval(a);
});
}
expect_stdout: "PASS"
}
issue_3146_4: {
options = {
reduce_vars: true,
unused: true,
}
input: {
var g = "PASS";
(function(f) {
var g = "FAIL";
f("console.log(g)", g[g]);
})(function(a) {
eval(a);
});
}
expect: {
var g = "PASS";
(function(f) {
var g = "FAIL";
f("console.log(g)", g[g]);
})(function(a) {
eval(a);
});
}
expect_stdout: "PASS"
}
issue_3192: {
options = {
unused: true,
}
input: {
(function(a) {
console.log(a = "foo", arguments[0]);
})("bar");
(function(a) {
"use strict";
console.log(a = "foo", arguments[0]);
})("bar");
}
expect: {
(function(a) {
console.log(a = "foo", arguments[0]);
})("bar");
(function(a) {
"use strict";
console.log("foo", arguments[0]);
})("bar");
}
expect_stdout: [
"foo foo",
"foo bar",
]
}

View File

@@ -186,7 +186,9 @@ unary_prefix: {
} }
negative_zero: { negative_zero: {
options = { evaluate: true } options = {
evaluate: true,
}
input: { input: {
console.log( console.log(
-"", -"",
@@ -207,7 +209,9 @@ negative_zero: {
} }
positive_zero: { positive_zero: {
options = { evaluate: true } options = {
evaluate: true,
}
input: { input: {
console.log( console.log(
+"", +"",
@@ -229,8 +233,8 @@ positive_zero: {
unsafe_constant: { unsafe_constant: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -421,8 +425,8 @@ prop_function: {
unsafe_integer_key: { unsafe_integer_key: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -449,8 +453,8 @@ unsafe_integer_key: {
unsafe_integer_key_complex: { unsafe_integer_key_complex: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -477,8 +481,8 @@ unsafe_integer_key_complex: {
unsafe_float_key: { unsafe_float_key: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -505,8 +509,8 @@ unsafe_float_key: {
unsafe_float_key_complex: { unsafe_float_key_complex: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -533,8 +537,8 @@ unsafe_float_key_complex: {
unsafe_array: { unsafe_array: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -569,8 +573,8 @@ unsafe_array: {
unsafe_string: { unsafe_string: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -597,8 +601,8 @@ unsafe_string: {
unsafe_array_bad_index: { unsafe_array_bad_index: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -619,8 +623,8 @@ unsafe_array_bad_index: {
unsafe_string_bad_index: { unsafe_string_bad_index: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -745,7 +749,7 @@ in_boolean_context: {
!b("foo"), !b("foo"),
!b([1, 2]), !b([1, 2]),
!b(/foo/), !b(/foo/),
![1, foo()], (foo(), !1),
(foo(), !1) (foo(), !1)
); );
} }
@@ -754,8 +758,8 @@ in_boolean_context: {
unsafe_charAt: { unsafe_charAt: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -782,8 +786,8 @@ unsafe_charAt: {
unsafe_charAt_bad_index: { unsafe_charAt_bad_index: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -804,8 +808,8 @@ unsafe_charAt_bad_index: {
unsafe_charAt_noop: { unsafe_charAt_noop: {
options = { options = {
evaluate : true, evaluate: true,
unsafe : true unsafe: true,
} }
input: { input: {
console.log( console.log(
@@ -1195,7 +1199,7 @@ issue_2231_1: {
} }
expect_stdout: true expect_stdout: true
expect_warnings: [ expect_warnings: [
"WARN: Error evaluating Object.keys(void 0) [test/compress/evaluate.js:1191,20]", "WARN: Error evaluating Object.keys(void 0) [test/compress/evaluate.js:1195,20]",
] ]
} }
@@ -1212,7 +1216,7 @@ issue_2231_2: {
} }
expect_stdout: true expect_stdout: true
expect_warnings: [ expect_warnings: [
"WARN: Error evaluating Object.getOwnPropertyNames(null) [test/compress/evaluate.js:1208,20]", "WARN: Error evaluating Object.getOwnPropertyNames(null) [test/compress/evaluate.js:1212,20]",
] ]
} }
@@ -1350,14 +1354,14 @@ issue_2535_3: {
} }
expect_stdout: true expect_stdout: true
expect_warnings: [ expect_warnings: [
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1336,20]", "WARN: Dropping side-effect-free && [test/compress/evaluate.js:1340,20]",
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1337,20]", "WARN: Dropping side-effect-free && [test/compress/evaluate.js:1341,20]",
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1338,20]", "WARN: Dropping side-effect-free && [test/compress/evaluate.js:1342,20]",
"WARN: Condition left of && always false [test/compress/evaluate.js:1338,20]", "WARN: Condition left of && always false [test/compress/evaluate.js:1342,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1339,20]", "WARN: Dropping side-effect-free || [test/compress/evaluate.js:1343,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1340,20]", "WARN: Dropping side-effect-free || [test/compress/evaluate.js:1344,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1341,20]", "WARN: Dropping side-effect-free || [test/compress/evaluate.js:1345,20]",
"WARN: Condition left of || always true [test/compress/evaluate.js:1341,20]", "WARN: Condition left of || always true [test/compress/evaluate.js:1345,20]",
] ]
} }
@@ -1429,3 +1433,180 @@ string_case: {
"199", "199",
] ]
} }
issue_2916_1: {
options = {
evaluate: true,
reduce_vars: true,
unsafe: true,
}
input: {
var c = "PASS";
(function(a, b) {
(function(d) {
d[0] = 1;
})(b);
a == b && (c = "FAIL");
})("", []);
console.log(c);
}
expect: {
var c = "PASS";
(function(a, b) {
(function(d) {
d[0] = 1;
})(b);
a == b && (c = "FAIL");
})("", []);
console.log(c);
}
expect_stdout: "PASS"
}
issue_2916_2: {
options = {
collapse_vars: true,
evaluate: true,
inline: true,
reduce_vars: true,
side_effects: true,
unsafe: true,
unused: true,
}
input: {
var c = "FAIL";
(function(b) {
(function(d) {
d[0] = 1;
})(b);
+b && (c = "PASS");
})([]);
console.log(c);
}
expect: {
var c = "FAIL";
(function(b) {
b[0] = 1;
+b && (c = "PASS");
})([]);
console.log(c);
}
expect_stdout: "PASS"
}
issue_2919: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log([ function() {} ].toString());
}
expect: {
console.log("function(){}");
}
}
issue_2926_1: {
options = {
evaluate: true,
reduce_vars: true,
unsafe: true,
}
input: {
(function f(a) {
console.log(f.name.length, f.length);
})();
}
expect: {
(function f(a) {
console.log(1, 1);
})();
}
expect_stdout: "1 1"
}
issue_2926_2: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(typeof function() {}.valueOf());
}
expect: {
console.log("function");
}
expect_stdout: "function"
}
issue_2968: {
options = {
collapse_vars: true,
evaluate: true,
inline: true,
passes: 2,
reduce_vars: true,
unused: true,
}
input: {
var c = "FAIL";
(function() {
(function(a, b) {
a <<= 0;
a && (a[(c = "PASS", 0 >>> (b += 1))] = 0);
})(42, -42);
})();
console.log(c);
}
expect: {
var c = "FAIL";
(function() {
b = -(a = 42),
void ((a <<= 0) && (a[(c = "PASS", 0 >>> (b += 1))] = 0));
var a, b;
})();
console.log(c);
}
expect_stdout: "PASS"
}
truthy_conditionals: {
options = {
conditionals: true,
evaluate: true,
}
input: {
if (a = {}) x();
(b = /foo/) && y();
(c = function() {}) || z();
}
expect: {
a = {}, x();
b = /foo/, y();
c = function() {};
}
}
truthy_loops: {
options = {
evaluate: true,
loops: true,
}
input: {
while ([]) x();
do {
y();
} while(a = {});
}
expect: {
for (;;) {
[];
x();
}
for (;;) {
y();
a = {};
}
}
}

View File

@@ -9,20 +9,20 @@ non_ascii_function_identifier_name: {
iifes_returning_constants_keep_fargs_true: { iifes_returning_constants_keep_fargs_true: {
options = { options = {
keep_fargs : true, booleans: true,
side_effects : true, collapse_vars: true,
evaluate : true, comparisons: true,
unused : true, conditionals: true,
dead_code : true, dead_code: true,
conditionals : true, evaluate: true,
comparisons : true, if_return: true,
booleans : true, inline: true,
if_return : true, join_vars: true,
join_vars : true, keep_fargs: true,
reduce_funcs : true, reduce_funcs: true,
reduce_vars : true, reduce_vars: true,
collapse_vars : true, side_effects: true,
inline : true, unused: true,
} }
input: { input: {
(function(){ return -1.23; }()); (function(){ return -1.23; }());
@@ -46,20 +46,20 @@ iifes_returning_constants_keep_fargs_true: {
iifes_returning_constants_keep_fargs_false: { iifes_returning_constants_keep_fargs_false: {
options = { options = {
keep_fargs : false, booleans: true,
side_effects : true, collapse_vars: true,
evaluate : true, comparisons: true,
unused : true, conditionals: true,
dead_code : true, dead_code: true,
conditionals : true, evaluate: true,
comparisons : true, if_return: true,
booleans : true, inline: true,
if_return : true, join_vars: true,
join_vars : true, keep_fargs: false,
reduce_funcs : true, reduce_funcs: true,
reduce_vars : true, reduce_vars: true,
collapse_vars : true, side_effects: true,
inline : true, unused: true,
} }
input: { input: {
(function(){ return -1.23; }()); (function(){ return -1.23; }());
@@ -292,11 +292,12 @@ issue_2084: {
} }
expect: { expect: {
var c = 0; var c = 0;
!function(c) { !function() {
c = 1 + c, var c;
c = 1 + (c = -1),
c = 1 + (c = 0), c = 1 + (c = 0),
0 !== 23..toString() && (c = 1 + c); 0 !== 23..toString() && (c = 1 + c);
}(-1), }(),
console.log(c); console.log(c);
} }
expect_stdout: "0" expect_stdout: "0"
@@ -1051,11 +1052,9 @@ issue_2616: {
} }
expect: { expect: {
var c = "FAIL"; var c = "FAIL";
(function() { !function(NaN) {
!function(NaN) { (true << NaN) - 0/0 || (c = "PASS");
(true << NaN) - 0/0 || (c = "PASS"); }([]);
}([]);
})();
console.log(c); console.log(c);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -1086,13 +1085,11 @@ issue_2620_1: {
} }
expect: { expect: {
var c = "FAIL"; var c = "FAIL";
(function() { !function(a) {
(function(a) { if (function(a) {
if (function(a) { a && a();
a && a(); }(), a) c = "PASS";
}(), a) c = "PASS"; }(1),
})(1);
})(),
console.log(c); console.log(c);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -1160,18 +1157,16 @@ issue_2620_3: {
} }
expect: { expect: {
var c = "FAIL"; var c = "FAIL";
(function() { !function(a, NaN) {
(function(a, NaN) { (function() {
(function() { switch (a) {
switch (a) { case a:
case a: break;
break; case c = "PASS", NaN:
case c = "PASS", NaN: break;
break; }
} })();
})(); }(NaN);
})(NaN);
})();
console.log(c); console.log(c);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -1180,8 +1175,8 @@ issue_2620_3: {
issue_2620_4: { issue_2620_4: {
rename = true, rename = true,
options = { options = {
evaluate: true,
dead_code: true, dead_code: true,
evaluate: true,
inline: true, inline: true,
passes: 2, passes: 2,
reduce_vars: true, reduce_vars: true,
@@ -1341,11 +1336,9 @@ issue_2630_4: {
} }
expect: { expect: {
var x = 3, a = 1, b = 2; var x = 3, a = 1, b = 2;
(function() { !function() {
(function() { while (--x >= 0 && void (b += ++a));
while (--x >= 0 && void (a++, b += a)); }();
})();
})();
console.log(a); console.log(a);
} }
expect_stdout: "2" expect_stdout: "2"
@@ -1540,7 +1533,7 @@ issue_2663_3: {
unused: true, unused: true,
} }
input: { input: {
(function () { (function() {
var outputs = [ var outputs = [
{ type: 0, target: null, eventName: "ngSubmit", propName: null }, { type: 0, target: null, eventName: "ngSubmit", propName: null },
{ type: 0, target: null, eventName: "submit", propName: null }, { type: 0, target: null, eventName: "submit", propName: null },
@@ -1557,11 +1550,11 @@ issue_2663_3: {
return handlers; return handlers;
} }
function renderEventHandlerClosure(eventName) { function renderEventHandlerClosure(eventName) {
return function () { return function() {
return console.log(eventName); return console.log(eventName);
}; };
} }
listenToElementOutputs(outputs).forEach(function (handler) { listenToElementOutputs(outputs).forEach(function(handler) {
return handler() return handler()
}); });
})(); })();
@@ -1641,7 +1634,7 @@ loop_init_arg: {
} }
input: { input: {
var a = "PASS"; var a = "PASS";
for (var k in "12") (function (b) { for (var k in "12") (function(b) {
(b >>= 1) && (a = "FAIL"), b = 2; (b >>= 1) && (a = "FAIL"), b = 2;
})(); })();
console.log(a); console.log(a);
@@ -1989,3 +1982,362 @@ issue_2783: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_2898: {
options = {
collapse_vars: true,
inline: true,
reduce_vars: true,
sequences: true,
unused: true,
}
input: {
var c = 0;
(function() {
while (f());
function f() {
var b = (c = 1 + c, void (c = 1 + c));
b && b[0];
}
})();
console.log(c);
}
expect: {
var c = 0;
(function() {
while (b = void 0, void ((b = void (c = 1 + (c = 1 + c))) && b[0]));
var b;
})(),
console.log(c);
}
expect_stdout: "2"
}
deduplicate_parenthesis: {
input: {
({}).a = b;
(({}).a = b)();
(function() {}).a = b;
((function() {}).a = b)();
}
expect_exact: "({}).a=b;({}.a=b)();(function(){}).a=b;(function(){}.a=b)();"
}
drop_lone_use_strict: {
options = {
directives: true,
side_effects: true,
}
input: {
function f1() {
"use strict";
}
function f2() {
"use strict";
function f3() {
"use strict";
}
}
(function f4() {
"use strict";
})();
}
expect: {
function f1() {
}
function f2() {
"use strict";
function f3() {
}
}
}
}
issue_3166: {
options = {
directives: true,
}
input: {
"foo";
"use strict";
function f() {
"use strict";
"bar";
"use asm";
}
}
expect: {
"use strict";
function f() {
"use asm";
}
}
}
issue_3016_1: {
options = {
inline: true,
toplevel: true,
}
input: {
var b = 1;
do {
(function(a) {
return a[b];
var a;
})(3);
} while (0);
console.log(b);
}
expect: {
var b = 1;
do {
a = 3,
a[b];
} while(0);
var a;
console.log(b);
}
expect_stdout: "1"
}
issue_3016_2: {
options = {
dead_code: true,
inline: true,
toplevel: true,
}
input: {
var b = 1;
do {
(function(a) {
return a[b];
try {
a = 2;
} catch (a) {
var a;
}
})(3);
} while (0);
console.log(b);
}
expect: {
var b = 1;
do {
a = 3,
a[b];
} while(0);
var a;
console.log(b);
}
expect_stdout: "1"
}
issue_3016_2_ie8: {
options = {
dead_code: true,
ie8: true,
inline: true,
toplevel: true,
}
input: {
var b = 1;
do {
(function(a) {
return a[b];
try {
a = 2;
} catch (a) {
var a;
}
})(3);
} while (0);
console.log(b);
}
expect: {
var b = 1;
do {
a = 3,
a[b];
} while(0);
var a;
console.log(b);
}
expect_stdout: "1"
}
issue_3016_3: {
options = {
dead_code: true,
inline: true,
toplevel: true,
}
input: {
var b = 1;
do {
console.log(function() {
return a ? "FAIL" : a = "PASS";
try {
a = 2;
} catch (a) {
var a;
}
}());
} while (b--);
}
expect: {
var b = 1;
do {
console.log((a = void 0, a ? "FAIL" : a = "PASS"));
} while(b--);
var a;
}
expect_stdout: [
"PASS",
"PASS",
]
}
issue_3016_3_ie8: {
options = {
dead_code: true,
ie8: true,
inline: true,
toplevel: true,
}
input: {
var b = 1;
do {
console.log(function() {
return a ? "FAIL" : a = "PASS";
try {
a = 2;
} catch (a) {
var a;
}
}());
} while (b--);
}
expect: {
var b = 1;
do {
console.log((a = void 0, a ? "FAIL" : a = "PASS"));
} while(b--);
var a;
}
expect_stdout: [
"PASS",
"PASS",
]
}
issue_3018: {
options = {
inline: true,
side_effects: true,
toplevel: true,
}
input: {
var b = 1, c = "PASS";
do {
(function() {
(function(a) {
a = 0 != (a && (c = "FAIL"));
})();
})();
} while (b--);
console.log(c);
}
expect: {
var b = 1, c = "PASS";
do {
a = void 0,
a = 0 != (a && (c = "FAIL"));
} while (b--);
var a;
console.log(c);
}
expect_stdout: "PASS"
}
issue_3054: {
options = {
booleans: true,
collapse_vars: true,
inline: 1,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
function f() {
return { a: true };
}
console.log(function(b) {
b = false;
return f();
}().a, f.call().a);
}
expect: {
"use strict";
function f() {
return { a: !0 };
}
console.log(function(b) {
return { a: !(b = !1) };
}().a, f.call().a);
}
expect_stdout: "true true"
}
issue_3076: {
options = {
dead_code: true,
inline: true,
sequences: true,
unused: true,
}
input: {
var c = "PASS";
(function(b) {
var n = 2;
while (--b + function() {
e && (c = "FAIL");
e = 5;
return 1;
try {
var a = 5;
} catch (e) {
var e;
}
}().toString() && --n > 0);
})(2);
console.log(c);
}
expect: {
var c = "PASS";
(function(b) {
var n = 2;
while (--b + (e = void 0, e && (c = "FAIL"), e = 5, 1).toString() && --n > 0);
var e;
})(2),
console.log(c);
}
expect_stdout: "PASS"
}
issue_3125: {
options = {
inline: true,
unsafe: true,
}
input: {
console.log(function() {
return "PASS";
}.call());
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
}

View File

@@ -2,7 +2,7 @@ must_replace: {
options = { options = {
global_defs: { global_defs: {
D: "foo bar", D: "foo bar",
} },
} }
input: { input: {
console.log(D); console.log(D);
@@ -141,9 +141,9 @@ mixed: {
console.log(CONFIG); console.log(CONFIG);
} }
expect_warnings: [ expect_warnings: [
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]', "WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]",
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:128,22]', "WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:128,22]",
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:130,8]', "WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:130,8]",
] ]
} }

View File

@@ -1,8 +1,8 @@
issue_2377_1: { issue_2377_1: {
options = { options = {
evaluate: true, evaluate: true,
inline: true,
hoist_props: true, hoist_props: true,
inline: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
@@ -33,8 +33,8 @@ issue_2377_1: {
issue_2377_2: { issue_2377_2: {
options = { options = {
evaluate: true, evaluate: true,
inline: true,
hoist_props: true, hoist_props: true,
inline: true,
passes: 2, passes: 2,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
@@ -64,8 +64,8 @@ issue_2377_2: {
issue_2377_3: { issue_2377_3: {
options = { options = {
evaluate: true, evaluate: true,
inline: true,
hoist_props: true, hoist_props: true,
inline: true,
passes: 4, passes: 4,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
@@ -239,14 +239,14 @@ name_collision_2: {
input: { input: {
var o = { var o = {
p: 1, p: 1,
0: function(x) { "+": function(x) {
return x; return x;
}, },
1: function(x) { "-": function(x) {
return x + 1; return x + 1;
} }
}, o__$0 = 2, o__$1 = 3; }, o__$0 = 2, o__$1 = 3;
console.log(o.p === o.p, o[0](4), o[1](5), o__$0, o__$1); console.log(o.p === o.p, o["+"](4), o["-"](5), o__$0, o__$1);
} }
expect: { expect: {
var o_p = 1, var o_p = 1,
@@ -273,14 +273,14 @@ name_collision_3: {
input: { input: {
var o = { var o = {
p: 1, p: 1,
0: function(x) { "+": function(x) {
return x; return x;
}, },
1: function(x) { "-": function(x) {
return x + 1; return x + 1;
} }
}, o__$0 = 2, o__$1 = 3; }, o__$0 = 2, o__$1 = 3;
console.log(o.p === o.p, o[0](4), o[1](5)); console.log(o.p === o.p, o["+"](4), o["-"](5));
} }
expect: { expect: {
var o_p = 1, var o_p = 1,
@@ -416,7 +416,10 @@ issue_2473_1: {
options = { options = {
hoist_props: false, hoist_props: false,
reduce_vars: true, reduce_vars: true,
top_retain: [ "x", "y" ], top_retain: [
"x",
"y"
],
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
@@ -435,7 +438,10 @@ issue_2473_2: {
options = { options = {
hoist_props: true, hoist_props: true,
reduce_vars: true, reduce_vars: true,
top_retain: [ "x", "y" ], top_retain: [
"x",
"y"
],
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
@@ -686,3 +692,173 @@ undefined_key: {
} }
expect_stdout: "3" expect_stdout: "3"
} }
issue_3021: {
options = {
hoist_props: true,
reduce_vars: true,
}
input: {
var a = 1, b = 2;
(function() {
b = a;
if (a++ + b--)
return 1;
return;
var b = {};
})();
console.log(a, b);
}
expect: {
var a = 1, b = 2;
(function() {
b = a;
if (a++ + b--)
return 1;
return;
var b = {};
})();
console.log(a, b);
}
expect_stdout: "2 2"
}
issue_3046: {
options = {
hoist_props: true,
reduce_vars: true,
}
input: {
console.log(function(a) {
do {
var b = {
c: a++
};
} while (b.c && a);
return a;
}(0));
}
expect: {
console.log(function(a) {
do {
var b_c = a++;
} while (b_c && a);
return a;
}(0));
}
expect_stdout: "1"
}
issue_3071_1: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
join_vars: true,
passes: 3,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
(function() {
var obj = {};
obj.one = 1;
obj.two = 2;
console.log(obj.one);
})();
}
expect: {
console.log(1);
}
expect_stdout: "1"
}
issue_3071_2: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
join_vars: true,
passes: 3,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
(function() {
obj = {};
obj.one = 1;
obj.two = 2;
console.log(obj.one);
var obj;
})();
}
expect: {
console.log(1);
}
expect_stdout: "1"
}
issue_3071_2_toplevel: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
join_vars: true,
passes: 3,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
(function() {
obj = {};
obj.one = 1;
obj.two = 2;
console.log(obj.one);
var obj;
})();
}
expect: {
console.log(1);
}
expect_stdout: "1"
}
issue_3071_3: {
options = {
hoist_props: true,
reduce_vars: true,
}
input: {
var c = 0;
(function(a, b) {
(function f(o) {
var n = 2;
while (--b + (o = {
p: c++,
}) && --n > 0);
})();
})();
console.log(c);
}
expect: {
var c = 0;
(function(a, b) {
(function f(o) {
var n = 2;
while (--b + (o = {
p: c++,
}) && --n > 0);
})();
})();
console.log(c);
}
expect_stdout: "2"
}

View File

@@ -102,12 +102,12 @@ dont_screw_try_catch: {
}; };
} }
expect: { expect: {
bad = function(n){ bad = function(t){
return function(t){ return function(n){
try{ try{
n() t()
} catch(n) { } catch(t) {
t(n) n(t)
} }
} }
}; };
@@ -187,9 +187,9 @@ dont_screw_try_catch_undefined: {
reduce_vars: { reduce_vars: {
options = { options = {
evaluate: true, evaluate: true,
ie8: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
ie8: true,
unused: true, unused: true,
} }
mangle = { mangle = {
@@ -349,11 +349,11 @@ issue_2254_1: {
try { try {
console.log(f("PASS")); console.log(f("PASS"));
} catch (e) {} } catch (e) {}
function f(e) { function f(t) {
try { try {
throw "FAIL"; throw "FAIL";
} catch (t) { } catch (e) {
return e; return t;
} }
} }
} }
@@ -392,3 +392,277 @@ issue_2254_2: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_24_1: {
mangle = {
ie8: false,
}
input: {
(function(a) {
console.log(typeof function f(){} === typeof a ? "FAIL" : "PASS");
})();
}
expect: {
(function(o) {
console.log(typeof function o(){} === typeof o ? "FAIL" : "PASS");
})();
}
expect_stdout: "PASS"
}
issue_24_2: {
mangle = {
ie8: true,
}
input: {
(function(a) {
console.log(typeof function f(){} === typeof a ? "FAIL" : "PASS");
})();
}
expect: {
(function(o) {
console.log(typeof function n(){} === typeof o ? "FAIL" : "PASS");
})();
}
expect_stdout: "PASS"
}
issue_2976_1: {
mangle = {
ie8: false,
}
input: {
console.log(function f() {
var a;
return a === f ? "FAIL" : "PASS";
}());
}
expect: {
console.log(function n() {
var o;
return o === n ? "FAIL" : "PASS";
}());
}
expect_stdout: "PASS"
}
issue_2976_2: {
mangle = {
ie8: true,
}
input: {
console.log(function f() {
var a;
return a === f ? "FAIL" : "PASS";
}());
}
expect: {
console.log(function f() {
var n;
return n === f ? "FAIL" : "PASS";
}());
}
expect_stdout: "PASS"
}
issue_2976_3: {
mangle = {
ie8: true,
toplevel: true,
}
input: {
console.log(function f() {
var a;
return a === f ? "FAIL" : "PASS";
}());
}
expect: {
console.log(function o() {
var n;
return n === o ? "FAIL" : "PASS";
}());
}
expect_stdout: "PASS"
}
issue_3035: {
mangle = {
ie8: false,
}
input: {
var c = "FAIL";
(function(a) {
try {
throw 1;
} catch (b) {
try {
throw 0;
} catch (a) {
b && (c = "PASS");
}
}
})();
console.log(c);
}
expect: {
var c = "FAIL";
(function(o) {
try {
throw 1;
} catch (t) {
try {
throw 0;
} catch (o) {
t && (c = "PASS");
}
}
})();
console.log(c);
}
expect_stdout: "PASS"
}
issue_3035_ie8: {
mangle = {
ie8: true,
}
input: {
var c = "FAIL";
(function(a) {
try {
throw 1;
} catch (b) {
try {
throw 0;
} catch (a) {
b && (c = "PASS");
}
}
})();
console.log(c);
}
expect: {
var c = "FAIL";
(function(t) {
try {
throw 1;
} catch (o) {
try {
throw 0;
} catch (t) {
o && (c = "PASS");
}
}
})();
console.log(c);
}
expect_stdout: "PASS"
}
issue_3197_1: {
options = {
ie8: false,
inline: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
mangle = {
ie8: false,
}
input: {
var window = {};
!function() {
function Foo() {
console.log(this instanceof Foo);
}
window.Foo = Foo;
}();
new window.Foo();
}
expect: {
var window = {};
window.Foo = function o() {
console.log(this instanceof o);
};
new window.Foo();
}
expect_stdout: "true"
}
issue_3197_1_ie8: {
options = {
ie8: true,
inline: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
mangle = {
ie8: true,
}
input: {
var window = {};
!function() {
function Foo() {
console.log(this instanceof Foo);
}
window.Foo = Foo;
}();
new window.Foo();
}
expect: {
var window = {};
window.Foo = function Foo() {
console.log(this instanceof Foo);
};
new window.Foo();
}
expect_stdout: "true"
}
issue_3197_2: {
mangle = {
ie8: false,
}
input: {
(function(a) {
var f = function f() {
console.log(this instanceof f);
};
new f(a);
})();
}
expect: {
(function(n) {
var o = function n() {
console.log(this instanceof n);
};
new o(n);
})();
}
expect_stdout: "true"
}
issue_3197_2_ie8: {
mangle = {
ie8: true,
}
input: {
(function(a) {
var f = function f() {
console.log(this instanceof f);
};
new f(a);
})();
}
expect: {
(function(n) {
var o = function o() {
console.log(this instanceof o);
};
new o(n);
})();
}
expect_stdout: "true"
}

View File

@@ -1,14 +1,14 @@
if_return_1: { if_return_1: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f(x) { function f(x) {
@@ -24,15 +24,15 @@ if_return_1: {
if_return_2: { if_return_2: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f(x, y) { function f(x, y) {
@@ -49,15 +49,15 @@ if_return_2: {
if_return_3: { if_return_3: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f(x) { function f(x) {
@@ -75,15 +75,15 @@ if_return_3: {
if_return_4: { if_return_4: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f(x, y) { function f(x, y) {
@@ -100,15 +100,15 @@ if_return_4: {
if_return_5: { if_return_5: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f() { function f() {
@@ -126,15 +126,15 @@ if_return_5: {
if_return_6: { if_return_6: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f(x) { function f(x) {
@@ -150,15 +150,15 @@ if_return_6: {
if_return_7: { if_return_7: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function f(x) { function f(x) {
@@ -176,10 +176,10 @@ if_return_7: {
if_return_8: { if_return_8: {
options = { options = {
if_return: true, conditionals: true,
sequences: true, if_return: true,
conditionals: true, sequences: true,
side_effects : true, side_effects: true,
} }
input: { input: {
function f(e) { function f(e) {
@@ -220,15 +220,15 @@ if_return_8: {
issue_1089: { issue_1089: {
options = { options = {
if_return : true, booleans: true,
sequences : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
evaluate : true, evaluate: true,
booleans : true, if_return: true,
unused : true, sequences: true,
side_effects : true, side_effects: true,
dead_code : true, unused: true,
} }
input: { input: {
function x() { function x() {
@@ -243,7 +243,7 @@ issue_1089: {
expect: { expect: {
function x() { function x() {
var f = document.getElementById("fname"); var f = document.getElementById("fname");
if (f.files[0].size > 12345) if (12345 < f.files[0].size)
return alert("alert"), f.focus(), !1; return alert("alert"), f.focus(), !1;
} }
} }
@@ -251,9 +251,9 @@ issue_1089: {
issue_1437: { issue_1437: {
options = { options = {
if_return : true, conditionals: false,
sequences : true, if_return: true,
conditionals : false sequences: true,
} }
input: { input: {
function x() { function x() {
@@ -281,9 +281,9 @@ issue_1437: {
issue_1437_conditionals: { issue_1437_conditionals: {
options = { options = {
conditionals : true, conditionals: true,
if_return : true, if_return: true,
sequences : true sequences: true,
} }
input: { input: {
function x() { function x() {

View File

@@ -1,8 +1,17 @@
non_hoisted_function_after_return: { non_hoisted_function_after_return: {
options = { options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, booleans: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, comparisons: true,
if_return: true, join_vars: true, side_effects: true conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
} }
input: { input: {
function foo(x) { function foo(x) {
@@ -27,19 +36,30 @@ non_hoisted_function_after_return: {
} }
} }
expect_warnings: [ expect_warnings: [
'WARN: Dropping unreachable code [test/compress/issue-1034.js:11,16]', "WARN: Dropping unreachable code [test/compress/issue-1034.js:20,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:14,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:23,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:17,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:26,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:18,21]" "WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:27,21]"
] ]
} }
non_hoisted_function_after_return_2a: { non_hoisted_function_after_return_2a: {
options = { options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, booleans: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, collapse_vars: false,
if_return: true, join_vars: true, side_effects: true, comparisons: true,
collapse_vars: false, passes: 2, warnings: "verbose" conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
passes: 2,
side_effects: true,
unused: true,
warnings: "verbose",
} }
input: { input: {
function foo(x) { function foo(x) {
@@ -65,28 +85,37 @@ non_hoisted_function_after_return_2a: {
} }
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:48,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:68,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:48,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:68,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:51,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:71,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:51,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:71,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:48,20]", "WARN: Dropping unused variable a [test/compress/issue-1034.js:68,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]", "WARN: Dropping unused function nope [test/compress/issue-1034.js:75,21]",
"WARN: pass 0: last_count: Infinity, count: 37", "WARN: pass 0: last_count: Infinity, count: 37",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:53,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:73,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:73,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:76,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]", "WARN: Dropping unused variable b [test/compress/issue-1034.js:71,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]", "WARN: Dropping unused variable c [test/compress/issue-1034.js:73,16]",
"WARN: pass 1: last_count: 37, count: 18", "WARN: pass 1: last_count: 37, count: 18",
] ]
} }
non_hoisted_function_after_return_2b: { non_hoisted_function_after_return_2b: {
options = { options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, booleans: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, collapse_vars: false,
if_return: true, join_vars: true, side_effects: true, comparisons: true,
collapse_vars: false conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
} }
input: { input: {
function foo(x) { function foo(x) {
@@ -111,19 +140,28 @@ non_hoisted_function_after_return_2b: {
} }
expect_warnings: [ expect_warnings: [
// duplicate warnings no longer emitted // duplicate warnings no longer emitted
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:126,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:126,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:99,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:128,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:99,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:128,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:103,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:132,12]",
] ]
} }
non_hoisted_function_after_return_strict: { non_hoisted_function_after_return_strict: {
options = { options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, booleans: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, comparisons: true,
if_return: true, join_vars: true, side_effects: true conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
} }
input: { input: {
"use strict"; "use strict";
@@ -153,19 +191,30 @@ non_hoisted_function_after_return_strict: {
} }
expect_stdout: "8 7" expect_stdout: "8 7"
expect_warnings: [ expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:133,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:171,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:136,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:174,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:139,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:177,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:140,21]", "WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:178,21]",
] ]
} }
non_hoisted_function_after_return_2a_strict: { non_hoisted_function_after_return_2a_strict: {
options = { options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, booleans: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, collapse_vars: false,
if_return: true, join_vars: true, side_effects: true, comparisons: true,
collapse_vars: false, passes: 2, warnings: "verbose" conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
passes: 2,
side_effects: true,
unused: true,
warnings: "verbose",
} }
input: { input: {
"use strict"; "use strict";
@@ -196,28 +245,37 @@ non_hoisted_function_after_return_2a_strict: {
} }
expect_stdout: "5 6" expect_stdout: "5 6"
expect_warnings: [ expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:175,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:224,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:175,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:224,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:178,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:227,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:178,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:227,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:175,20]", "WARN: Dropping unused variable a [test/compress/issue-1034.js:224,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:182,21]", "WARN: Dropping unused function nope [test/compress/issue-1034.js:231,21]",
"WARN: pass 0: last_count: Infinity, count: 48", "WARN: pass 0: last_count: Infinity, count: 48",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:180,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:229,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:180,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:229,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:183,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:232,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:178,20]", "WARN: Dropping unused variable b [test/compress/issue-1034.js:227,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:180,16]", "WARN: Dropping unused variable c [test/compress/issue-1034.js:229,16]",
"WARN: pass 1: last_count: 48, count: 29", "WARN: pass 1: last_count: 48, count: 29",
] ]
} }
non_hoisted_function_after_return_2b_strict: { non_hoisted_function_after_return_2b_strict: {
options = { options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, booleans: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, collapse_vars: false,
if_return: true, join_vars: true, side_effects: true, comparisons: true,
collapse_vars: false conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
} }
input: { input: {
"use strict"; "use strict";
@@ -247,10 +305,10 @@ non_hoisted_function_after_return_2b_strict: {
expect_stdout: "5 6" expect_stdout: "5 6"
expect_warnings: [ expect_warnings: [
// duplicate warnings no longer emitted // duplicate warnings no longer emitted
"WARN: Dropping unreachable code [test/compress/issue-1034.js:229,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:287,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:229,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:287,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:231,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:289,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:231,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:289,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:235,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:293,12]",
] ]
} }

View File

@@ -3,7 +3,7 @@ const_pragma: {
evaluate: true, evaluate: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
}; }
input: { input: {
/** @const */ var goog = goog || {}; /** @const */ var goog = goog || {};
@@ -19,7 +19,7 @@ not_const: {
evaluate: true, evaluate: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
}; }
input: { input: {
var goog = goog || {}; var goog = goog || {};

View File

@@ -1,6 +1,6 @@
with_in_global_scope: { with_in_global_scope: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
var o = 42; var o = 42;
@@ -18,7 +18,7 @@ with_in_global_scope: {
} }
with_in_function_scope: { with_in_function_scope: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
function foo() { function foo() {
@@ -40,7 +40,7 @@ with_in_function_scope: {
} }
compress_with_with_in_other_scope: { compress_with_with_in_other_scope: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
function foo() { function foo() {
@@ -69,7 +69,7 @@ compress_with_with_in_other_scope: {
} }
with_using_existing_variable_outside_scope: { with_using_existing_variable_outside_scope: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
function f() { function f() {
@@ -99,7 +99,7 @@ with_using_existing_variable_outside_scope: {
} }
check_drop_unused_in_peer_function: { check_drop_unused_in_peer_function: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
function outer() { function outer() {
@@ -148,7 +148,7 @@ check_drop_unused_in_peer_function: {
Infinity_not_in_with_scope: { Infinity_not_in_with_scope: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
var o = { Infinity: 'oInfinity' }; var o = { Infinity: 'oInfinity' };
@@ -164,7 +164,7 @@ Infinity_not_in_with_scope: {
Infinity_in_with_scope: { Infinity_in_with_scope: {
options = { options = {
unused: true unused: true,
} }
input: { input: {
var o = { Infinity: 'oInfinity' }; var o = { Infinity: 'oInfinity' };
@@ -180,19 +180,19 @@ Infinity_in_with_scope: {
assorted_Infinity_NaN_undefined_in_with_scope: { assorted_Infinity_NaN_undefined_in_with_scope: {
options = { options = {
unused: true, booleans: true,
evaluate: true, comparisons: true,
dead_code: true, conditionals: true,
conditionals: true, dead_code: true,
comparisons: true, evaluate: true,
booleans: true, hoist_funs: true,
hoist_funs: true, if_return: true,
keep_fargs: true, join_vars: true,
if_return: true, keep_fargs: true,
join_vars: true,
side_effects: true,
sequences: false,
keep_infinity: false, keep_infinity: false,
sequences: false,
side_effects: true,
unused: true,
} }
input: { input: {
var f = console.log; var f = console.log;
@@ -242,19 +242,19 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
assorted_Infinity_NaN_undefined_in_with_scope_keep_infinity: { assorted_Infinity_NaN_undefined_in_with_scope_keep_infinity: {
options = { options = {
unused: true, booleans: true,
evaluate: true, comparisons: true,
dead_code: true, conditionals: true,
conditionals: true, dead_code: true,
comparisons: true, evaluate: true,
booleans: true, hoist_funs: true,
hoist_funs: true, if_return: true,
keep_fargs: true, join_vars: true,
if_return: true, keep_fargs: true,
join_vars: true,
side_effects: true,
sequences: false,
keep_infinity: true, keep_infinity: true,
sequences: false,
side_effects: true,
unused: true,
} }
input: { input: {
var f = console.log; var f = console.log;

View File

@@ -1,11 +1,15 @@
keep_name_of_getter: { keep_name_of_getter: {
options = { unused: true }; options = {
unused: true,
}
input: { a = { get foo () {} } } input: { a = { get foo () {} } }
expect: { a = { get foo () {} } } expect: { a = { get foo () {} } }
} }
keep_name_of_setter: { keep_name_of_setter: {
options = { unused: true }; options = {
unused: true,
}
input: { a = { set foo () {} } } input: { a = { set foo () {} } }
expect: { a = { set foo () {} } } expect: { a = { set foo () {} } }
} }

View File

@@ -1,7 +1,7 @@
mangle_keep_fnames_false: { mangle_keep_fnames_false: {
options = { options = {
keep_fnames : true, keep_fargs: true,
keep_fargs : true, keep_fnames: true,
} }
mangle = { mangle = {
keep_fnames : false, keep_fnames : false,
@@ -26,8 +26,8 @@ mangle_keep_fnames_false: {
mangle_keep_fnames_true: { mangle_keep_fnames_true: {
options = { options = {
keep_fnames : true, keep_fargs: true,
keep_fargs : true, keep_fnames: true,
} }
mangle = { mangle = {
keep_fnames : true, keep_fnames : true,

View File

@@ -1,14 +1,14 @@
pure_function_calls: { pure_function_calls: {
options = { options = {
evaluate : true, booleans: true,
conditionals : true, comparisons: true,
comparisons : true, conditionals: true,
side_effects : true, evaluate: true,
booleans : true, if_return: true,
unused : true, join_vars: true,
if_return : true, negate_iife: true,
join_vars : true, side_effects: true,
negate_iife : true, unused: true,
} }
input: { input: {
// pure top-level IIFE will be dropped // pure top-level IIFE will be dropped
@@ -60,16 +60,16 @@ pure_function_calls: {
pure_function_calls_toplevel: { pure_function_calls_toplevel: {
options = { options = {
evaluate : true, booleans: true,
conditionals : true, comparisons: true,
comparisons : true, conditionals: true,
side_effects : true, evaluate: true,
booleans : true, if_return: true,
unused : true, join_vars: true,
if_return : true, negate_iife: true,
join_vars : true, side_effects: true,
negate_iife : true, toplevel: true,
toplevel : true, unused: true,
} }
input: { input: {
// pure top-level IIFE will be dropped // pure top-level IIFE will be dropped
@@ -175,8 +175,8 @@ should_warn: {
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:141,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:141,31]",
"WARN: Condition always true [test/compress/issue-1261.js:141,8]", "WARN: Condition always true [test/compress/issue-1261.js:141,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:142,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:142,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:143,24]",
"WARN: Condition always true [test/compress/issue-1261.js:143,8]", "WARN: Condition always true [test/compress/issue-1261.js:143,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:143,24]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:144,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:144,31]",
"WARN: Condition always false [test/compress/issue-1261.js:144,8]", "WARN: Condition always false [test/compress/issue-1261.js:144,8]",
] ]

View File

@@ -1,16 +1,16 @@
string_plus_optimization: { string_plus_optimization: {
options = { options = {
side_effects : true, booleans: true,
evaluate : true, comparisons: true,
conditionals : true, conditionals: true,
comparisons : true, dead_code: true,
dead_code : true, evaluate: true,
booleans : true, hoist_funs: true,
unused : true, if_return: true,
if_return : true, join_vars: true,
join_vars : true, side_effects: true,
hoist_funs : true, unused: true,
}; }
input: { input: {
function foo(anything) { function foo(anything) {
function throwing_function() { function throwing_function() {

View File

@@ -15,7 +15,7 @@
tranformation_sort_order_equal: { tranformation_sort_order_equal: {
options = { options = {
comparisons: true, comparisons: true,
}; }
input: { (a = parseInt('100')) == a } input: { (a = parseInt('100')) == a }
expect: { (a = parseInt('100')) == a } expect: { (a = parseInt('100')) == a }
@@ -24,7 +24,7 @@ tranformation_sort_order_equal: {
tranformation_sort_order_unequal: { tranformation_sort_order_unequal: {
options = { options = {
comparisons: true, comparisons: true,
}; }
input: { (a = parseInt('100')) != a } input: { (a = parseInt('100')) != a }
expect: { (a = parseInt('100')) != a } expect: { (a = parseInt('100')) != a }
@@ -33,7 +33,7 @@ tranformation_sort_order_unequal: {
tranformation_sort_order_lesser_or_equal: { tranformation_sort_order_lesser_or_equal: {
options = { options = {
comparisons: true, comparisons: true,
}; }
input: { (a = parseInt('100')) <= a } input: { (a = parseInt('100')) <= a }
expect: { (a = parseInt('100')) <= a } expect: { (a = parseInt('100')) <= a }
@@ -41,7 +41,7 @@ tranformation_sort_order_lesser_or_equal: {
tranformation_sort_order_greater_or_equal: { tranformation_sort_order_greater_or_equal: {
options = { options = {
comparisons: true, comparisons: true,
}; }
input: { (a = parseInt('100')) >= a } input: { (a = parseInt('100')) >= a }
expect: { (a = parseInt('100')) >= a } expect: { (a = parseInt('100')) >= a }

View File

@@ -1,6 +1,6 @@
level_zero: { level_zero: {
options = { options = {
keep_fnames: true keep_fnames: true,
} }
mangle = { mangle = {
keep_fnames: true keep_fnames: true
@@ -29,7 +29,7 @@ level_zero: {
level_one: { level_one: {
options = { options = {
keep_fnames: true keep_fnames: true,
} }
mangle = { mangle = {
keep_fnames: true keep_fnames: true
@@ -58,7 +58,7 @@ level_one: {
level_two: { level_two: {
options = { options = {
keep_fnames: true keep_fnames: true,
} }
mangle = { mangle = {
keep_fnames: true keep_fnames: true
@@ -97,7 +97,7 @@ level_two: {
level_three: { level_three: {
options = { options = {
keep_fnames: true keep_fnames: true,
} }
mangle = { mangle = {
keep_fnames: true keep_fnames: true

View File

@@ -22,17 +22,17 @@ else_with_empty_statement: {
conditional_false_stray_else_in_loop: { conditional_false_stray_else_in_loop: {
options = { options = {
evaluate : true, booleans: true,
comparisons : true, comparisons: true,
booleans : true, conditionals: false,
unused : true, dead_code: true,
loops : true, evaluate: true,
side_effects : true, hoist_vars: true,
dead_code : true, if_return: true,
hoist_vars : true, join_vars: true,
join_vars : true, loops: true,
if_return : true, side_effects: true,
conditionals : false, unused: true,
} }
input: { input: {
for (var i = 1; i <= 4; ++i) { for (var i = 1; i <= 4; ++i) {

View File

@@ -104,7 +104,7 @@ mangle_catch_toplevel: {
} }
console.log(a); console.log(a);
} }
expect_exact: 'var o="FAIL";try{throw 1}catch(c){o="PASS"}console.log(o);' expect_exact: 'var c="FAIL";try{throw 1}catch(o){c="PASS"}console.log(c);'
expect_stdout: "PASS" expect_stdout: "PASS"
} }
@@ -148,7 +148,7 @@ mangle_catch_var_toplevel: {
} }
console.log(a); console.log(a);
} }
expect_exact: 'var o="FAIL";try{throw 1}catch(r){var o="PASS"}console.log(o);' expect_exact: 'var r="FAIL";try{throw 1}catch(o){var r="PASS"}console.log(r);'
expect_stdout: "PASS" expect_stdout: "PASS"
} }
@@ -345,3 +345,95 @@ mangle_catch_redef_2_ie8_toplevel: {
expect_exact: 'try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);' expect_exact: 'try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
expect_stdout: "undefined" expect_stdout: "undefined"
} }
mangle_catch_redef_3: {
mangle = {
ie8: false,
toplevel: false,
}
input: {
var o = "PASS";
try {
throw 0;
} catch (o) {
(function() {
function f() {
o = "FAIL";
}
f(), f();
})();
}
console.log(o);
}
expect_exact: 'var o="PASS";try{throw 0}catch(o){(function(){function c(){o="FAIL"}c(),c()})()}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_redef_3_toplevel: {
mangle = {
ie8: false,
toplevel: true,
}
input: {
var o = "PASS";
try {
throw 0;
} catch (o) {
(function() {
function f() {
o = "FAIL";
}
f(), f();
})();
}
console.log(o);
}
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
expect_stdout: "PASS"
}
mangle_catch_redef_ie8_3: {
mangle = {
ie8: true,
toplevel: false,
}
input: {
var o = "PASS";
try {
throw 0;
} catch (o) {
(function() {
function f() {
o = "FAIL";
}
f(), f();
})();
}
console.log(o);
}
expect_exact: 'var o="PASS";try{throw 0}catch(o){(function(){function c(){o="FAIL"}c(),c()})()}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_redef_3_ie8_toplevel: {
mangle = {
ie8: true,
toplevel: true,
}
input: {
var o = "PASS";
try {
throw 0;
} catch (o) {
(function() {
function f() {
o = "FAIL";
}
f(), f();
})();
}
console.log(o);
}
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
expect_stdout: "PASS"
}

View File

@@ -15,7 +15,7 @@ function_iife_catch: {
} }
f(); f();
} }
expect_exact: "function f(o){!function(){try{throw 0}catch(c){var o=1;console.log(c,o)}}()}f();" expect_exact: "function f(o){!function(){try{throw 0}catch(o){var c=1;console.log(o,c)}}()}f();"
expect_stdout: "0 1" expect_stdout: "0 1"
} }
@@ -36,7 +36,7 @@ function_iife_catch_ie8: {
} }
f(); f();
} }
expect_exact: "function f(o){!function(){try{throw 0}catch(o){var c=1;console.log(o,c)}}()}f();" expect_exact: "function f(c){!function(){try{throw 0}catch(c){var o=1;console.log(c,o)}}()}f();"
expect_stdout: "0 1" expect_stdout: "0 1"
} }
@@ -61,7 +61,7 @@ function_catch_catch: {
} }
f(); f();
} }
expect_exact: "var o=0;function f(){try{throw 1}catch(c){try{throw 2}catch(o){var o=3;console.log(o)}}console.log(o)}f();" expect_exact: "var o=0;function f(){try{throw 1}catch(o){try{throw 2}catch(c){var c=3;console.log(c)}}console.log(c)}f();"
expect_stdout: [ expect_stdout: [
"3", "3",
"undefined", "undefined",

View File

@@ -125,8 +125,8 @@ label_do: {
label_while: { label_while: {
options = { options = {
evaluate: true,
dead_code: true, dead_code: true,
evaluate: true,
loops: true, loops: true,
} }
input: { input: {

View File

@@ -1,6 +1,8 @@
do_not_update_lhs: { do_not_update_lhs: {
options = { options = {
global_defs: { DEBUG: 0 } global_defs: {
DEBUG: 0,
},
} }
input: { input: {
DEBUG++; DEBUG++;
@@ -16,7 +18,9 @@ do_not_update_lhs: {
do_update_rhs: { do_update_rhs: {
options = { options = {
global_defs: { DEBUG: 0 } global_defs: {
DEBUG: 0,
},
} }
input: { input: {
MY_DEBUG = DEBUG; MY_DEBUG = DEBUG;
@@ -35,7 +39,7 @@ mixed: {
DEBUG: 0, DEBUG: 0,
ENV: 1, ENV: 1,
FOO: 2, FOO: 2,
} },
} }
input: { input: {
var ENV = 3; var ENV = 3;
@@ -60,11 +64,11 @@ mixed: {
x = 0; x = 0;
} }
expect_warnings: [ expect_warnings: [
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,12]', "WARN: global_defs ENV redefined [test/compress/issue-208.js:45,12]",
'WARN: global_defs FOO redefined [test/compress/issue-208.js:42,12]', "WARN: global_defs FOO redefined [test/compress/issue-208.js:46,12]",
'WARN: global_defs FOO redefined [test/compress/issue-208.js:44,10]', "WARN: global_defs FOO redefined [test/compress/issue-208.js:48,10]",
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:45,8]', "WARN: global_defs DEBUG redefined [test/compress/issue-208.js:49,8]",
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:46,8]', "WARN: global_defs DEBUG redefined [test/compress/issue-208.js:50,8]",
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:47,8]', "WARN: global_defs DEBUG redefined [test/compress/issue-208.js:51,8]",
] ]
} }

View File

@@ -1,5 +1,7 @@
return_with_no_value_in_if_body: { return_with_no_value_in_if_body: {
options = { conditionals: true }; options = {
conditionals: true,
}
input: { input: {
function foo(bar) { function foo(bar) {
if (bar) { if (bar) {

View File

@@ -1,5 +1,7 @@
issue_267: { issue_267: {
options = { comparisons: true }; options = {
comparisons: true,
}
input: { input: {
x = a % b / b * c * 2; x = a % b / b * c * 2;
x = a % b * 2 x = a % b * 2

View File

@@ -1,5 +1,7 @@
issue_269_1: { issue_269_1: {
options = {unsafe: true}; options = {
unsafe: true,
}
input: { input: {
f( f(
String(x), String(x),
@@ -20,7 +22,9 @@ issue_269_1: {
} }
issue_269_dangers: { issue_269_dangers: {
options = {unsafe: true}; options = {
unsafe: true,
}
input: { input: {
f( f(
String(x, x), String(x, x),
@@ -34,7 +38,9 @@ issue_269_dangers: {
} }
issue_269_in_scope: { issue_269_in_scope: {
options = {unsafe: true}; options = {
unsafe: true,
}
input: { input: {
var String, Number, Boolean; var String, Number, Boolean;
f( f(
@@ -50,7 +56,9 @@ issue_269_in_scope: {
} }
strings_concat: { strings_concat: {
options = {unsafe: true}; options = {
unsafe: true,
}
input: { input: {
f( f(
String(x + 'str'), String(x + 'str'),
@@ -67,9 +75,9 @@ strings_concat: {
regexp: { regexp: {
options = { options = {
evaluate: true, evaluate: true,
unsafe: true, unsafe: true,
} }
input: { input: {
RegExp("foo"); RegExp("foo");
RegExp("bar", "ig"); RegExp("bar", "ig");
@@ -85,6 +93,6 @@ regexp: {
RegExp("should", "fail"); RegExp("should", "fail");
} }
expect_warnings: [ expect_warnings: [
'WARN: Error converting RegExp("should","fail") [test/compress/issue-269.js:78,2]', 'WARN: Error converting RegExp("should","fail") [test/compress/issue-269.js:86,2]',
] ]
} }

View File

@@ -186,7 +186,7 @@ negate_iife_5_off: {
inline: true, inline: true,
negate_iife: false, negate_iife: false,
sequences: true, sequences: true,
}; }
input: { input: {
if ((function(){ return t })()) { if ((function(){ return t })()) {
foo(true); foo(true);
@@ -245,7 +245,7 @@ negate_iife_issue_1073: {
reduce_vars: true, reduce_vars: true,
sequences: true, sequences: true,
unused: true, unused: true,
}; }
input: { input: {
new (function(a) { new (function(a) {
return function Foo() { return function Foo() {
@@ -273,7 +273,7 @@ issue_1288_side_effects: {
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
unused: true, unused: true,
}; }
input: { input: {
if (w) ; if (w) ;
else { else {
@@ -399,7 +399,7 @@ wrap_iife_in_expression: {
wrap_iife: true, wrap_iife: true,
} }
input: { input: {
foo = (function () { foo = (function() {
return bar(); return bar();
})(); })();
} }

View File

@@ -0,0 +1,21 @@
inline_script_off: {
beautify = {
inline_script: false,
}
input: {
console.log("</sCrIpT>");
}
expect_exact: 'console.log("</sCrIpT>");'
expect_stdout: "</sCrIpT>"
}
inline_script_on: {
beautify = {
inline_script: true,
}
input: {
console.log("</sCrIpT>");
}
expect_exact: 'console.log("<\\/sCrIpT>");'
expect_stdout: "</sCrIpT>"
}

View File

@@ -1,5 +1,7 @@
issue_44_valid_ast_1: { issue_44_valid_ast_1: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function a(b) { function a(b) {
for (var i = 0, e = b.qoo(); ; i++) {} for (var i = 0, e = b.qoo(); ; i++) {}
@@ -14,7 +16,9 @@ issue_44_valid_ast_1: {
} }
issue_44_valid_ast_2: { issue_44_valid_ast_2: {
options = { unused: true }; options = {
unused: true,
}
input: { input: {
function a(b) { function a(b) {
if (foo) for (var i = 0, e = b.qoo(); ; i++) {} if (foo) for (var i = 0, e = b.qoo(); ; i++) {}

View File

@@ -1,8 +1,8 @@
keep_continue: { keep_continue: {
options = { options = {
dead_code: true, dead_code: true,
evaluate: true evaluate: true,
}; }
input: { input: {
while (a) { while (a) {
if (b) { if (b) {

View File

@@ -1,5 +1,5 @@
NaN_and_Infinity_must_have_parens: { NaN_and_Infinity_must_have_parens: {
options = {}; options = {}
input: { input: {
Infinity.toString(); Infinity.toString();
NaN.toString(); NaN.toString();
@@ -11,7 +11,7 @@ NaN_and_Infinity_must_have_parens: {
} }
NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined: { NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined: {
options = {}; options = {}
input: { input: {
var Infinity, NaN; var Infinity, NaN;
Infinity.toString(); Infinity.toString();

View File

@@ -1,8 +1,8 @@
issue_611: { issue_611: {
options = { options = {
sequences: true, sequences: true,
side_effects: true side_effects: true,
}; }
input: { input: {
define(function() { define(function() {
function fn() {} function fn() {}

View File

@@ -1,9 +1,9 @@
wrongly_optimized: { wrongly_optimized: {
options = { options = {
conditionals: true,
booleans: true, booleans: true,
evaluate: true conditionals: true,
}; evaluate: true,
}
input: { input: {
function func() { function func() {
foo(); foo();

View File

@@ -28,12 +28,12 @@ cond_5: {
dead_code_const_annotation_regex: { dead_code_const_annotation_regex: {
options = { options = {
booleans : true, booleans: true,
conditionals : true, conditionals: true,
dead_code : true, dead_code: true,
evaluate : true, evaluate: true,
expression : true, expression: true,
loops : true, loops: true,
} }
input: { input: {
var unused; var unused;
@@ -82,8 +82,8 @@ drop_value: {
wrongly_optimized: { wrongly_optimized: {
options = { options = {
conditionals: true,
booleans: true, booleans: true,
conditionals: true,
evaluate: true, evaluate: true,
expression: true, expression: true,
} }
@@ -195,7 +195,7 @@ negate_iife_5_off: {
expression: true, expression: true,
negate_iife: false, negate_iife: false,
sequences: true, sequences: true,
}; }
input: { input: {
if ((function(){ return t })()) { if ((function(){ return t })()) {
foo(true); foo(true);
@@ -248,7 +248,9 @@ issue_1254_negate_iife_nested: {
conditional: { conditional: {
options = { options = {
expression: true, expression: true,
pure_funcs: [ "pure" ], pure_funcs: [
"pure"
],
side_effects: true, side_effects: true,
} }
input: { input: {

View File

@@ -1,7 +1,7 @@
negate_booleans_1: { negate_booleans_1: {
options = { options = {
comparisons: true comparisons: true,
}; }
input: { input: {
var a = !a || !b || !c || !d || !e || !f; var a = !a || !b || !c || !d || !e || !f;
} }
@@ -12,8 +12,8 @@ negate_booleans_1: {
negate_booleans_2: { negate_booleans_2: {
options = { options = {
comparisons: true comparisons: true,
}; }
input: { input: {
var match = !x && // should not touch this one var match = !x && // should not touch this one
(!z || c) && (!z || c) &&

View File

@@ -1,11 +1,31 @@
remove_redundant_sequence_items: { remove_sequence: {
options = { side_effects: true }; options = {
side_effects: true,
}
input: { input: {
(0, 1, eval)(); (0, 1, eval)();
(0, 1, logThis)(); (0, 1, logThis)();
(0, 1, _decorators.logThis)(); (0, 1, _decorators.logThis)();
} }
expect: { expect: {
eval();
logThis();
(0, _decorators.logThis)();
}
}
remove_redundant_sequence_items: {
options = {
side_effects: true,
}
input: {
"use strict";
(0, 1, eval)();
(0, 1, logThis)();
(0, 1, _decorators.logThis)();
}
expect: {
"use strict";
(0, eval)(); (0, eval)();
logThis(); logThis();
(0, _decorators.logThis)(); (0, _decorators.logThis)();
@@ -13,13 +33,17 @@ remove_redundant_sequence_items: {
} }
dont_remove_this_binding_sequence: { dont_remove_this_binding_sequence: {
options = { side_effects: true }; options = {
side_effects: true,
}
input: { input: {
"use strict";
(0, eval)(); (0, eval)();
(0, logThis)(); (0, logThis)();
(0, _decorators.logThis)(); (0, _decorators.logThis)();
} }
expect: { expect: {
"use strict";
(0, eval)(); (0, eval)();
logThis(); logThis();
(0, _decorators.logThis)(); (0, _decorators.logThis)();

View File

@@ -2,25 +2,25 @@ dont_mangle_arguments: {
mangle = { mangle = {
}; };
options = { options = {
sequences : true, booleans: true,
properties : true, comparisons: true,
dead_code : true, conditionals: true,
drop_debugger : true, dead_code: true,
conditionals : true, drop_debugger: true,
comparisons : true, evaluate: true,
evaluate : true, hoist_funs: true,
booleans : true, hoist_vars: true,
loops : true, if_return: true,
unused : true, join_vars: true,
hoist_funs : true, keep_fargs: true,
keep_fargs : true, keep_fnames: false,
keep_fnames : false, loops: true,
hoist_vars : true, negate_iife: false,
if_return : true, properties: true,
join_vars : true, sequences: true,
side_effects : true, side_effects: true,
negate_iife : false unused: true,
}; }
input: { input: {
(function(){ (function(){
var arguments = arguments, not_arguments = 9; var arguments = arguments, not_arguments = 9;

View File

@@ -1,8 +1,8 @@
keep_var_for_in: { keep_var_for_in: {
options = { options = {
hoist_vars: true, hoist_vars: true,
unused: true unused: true,
}; }
input: { input: {
(function(obj){ (function(obj){
var foo = 5; var foo = 5;

View File

@@ -3,8 +3,9 @@ this_binding_conditionals: {
conditionals: true, conditionals: true,
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
}; }
input: { input: {
"use strict";
(1 && a)(); (1 && a)();
(0 || a)(); (0 || a)();
(0 || 1 && a)(); (0 || 1 && a)();
@@ -26,6 +27,7 @@ this_binding_conditionals: {
(1 ? eval : 0)(); (1 ? eval : 0)();
} }
expect: { expect: {
"use strict";
a(); a();
a(); a();
a(); a();
@@ -53,13 +55,15 @@ this_binding_collapse_vars: {
collapse_vars: true, collapse_vars: true,
toplevel: true, toplevel: true,
unused: true, unused: true,
}; }
input: { input: {
"use strict";
var c = a; c(); var c = a; c();
var d = a.b; d(); var d = a.b; d();
var e = eval; e(); var e = eval; e();
} }
expect: { expect: {
"use strict";
a(); a();
(0, a.b)(); (0, a.b)();
(0, eval)(); (0, eval)();
@@ -68,32 +72,89 @@ this_binding_collapse_vars: {
this_binding_side_effects: { this_binding_side_effects: {
options = { options = {
side_effects : true side_effects: true,
}; }
input: { input: {
(function (foo) { (function(foo) {
(0, foo)(); (0, foo)();
(0, foo.bar)(); (0, foo.bar)();
(0, eval)('console.log(foo);'); (0, eval)("console.log(foo);");
}()); }());
(function (foo) { (function(foo) {
"use strict";
(0, foo)();
(0, foo.bar)();
(0, eval)("console.log(foo);");
}());
(function(foo) {
var eval = console; var eval = console;
(0, foo)(); (0, foo)();
(0, foo.bar)(); (0, foo.bar)();
(0, eval)('console.log(foo);'); (0, eval)("console.log(foo);");
}()); }());
} }
expect: { expect: {
(function (foo) { (function(foo) {
foo(); foo();
(0, foo.bar)(); (0, foo.bar)();
(0, eval)('console.log(foo);'); eval("console.log(foo);");
}()); }());
(function (foo) { (function(foo) {
"use strict";
foo();
(0, foo.bar)();
(0, eval)("console.log(foo);");
}());
(function(foo) {
var eval = console; var eval = console;
foo(); foo();
(0, foo.bar)(); (0, foo.bar)();
(0, eval)('console.log(foo);'); eval("console.log(foo);");
}()); }());
} }
} }
this_binding_sequences: {
options = {
sequences: true,
side_effects: true,
}
input: {
console.log(typeof function() {
return eval("this");
}());
console.log(typeof function() {
"use strict";
return eval("this");
}());
console.log(typeof function() {
return (0, eval)("this");
}());
console.log(typeof function() {
"use strict";
return (0, eval)("this");
}());
}
expect: {
console.log(typeof function() {
return eval("this");
}()),
console.log(typeof function() {
"use strict";
return eval("this");
}()),
console.log(typeof function() {
return eval("this");
}()),
console.log(typeof function() {
"use strict";
return (0, eval)("this");
}());
}
expect_stdout: [
"object",
"undefined",
"object",
"object",
]
}

View File

@@ -1,9 +1,21 @@
eval_collapse_vars: { eval_collapse_vars: {
options = { options = {
collapse_vars:true, sequences:false, properties:true, dead_code:true, conditionals:true, booleans: true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true, collapse_vars: true,
keep_fargs:true, if_return:true, join_vars:true, side_effects:true comparisons: true,
}; conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: false,
side_effects: true,
unused: true,
}
input: { input: {
function f1() { function f1() {
var e = 7; var e = 7;
@@ -46,7 +58,10 @@ eval_collapse_vars: {
} }
eval_unused: { eval_unused: {
options = { unused: true, keep_fargs: false }; options = {
keep_fargs: false,
unused: true,
}
input: { input: {
function f1(a, eval, c, d, e) { function f1(a, eval, c, d, e) {
return a('c') + eval; return a('c') + eval;

View File

@@ -1,8 +1,19 @@
issue979_reported: { issue979_reported: {
options = { options = {
sequences:true, properties:true, dead_code:true, conditionals:true, booleans: true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true, comparisons: true,
keep_fargs:true, if_return:true, join_vars:true, side_effects:true conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: true,
side_effects: true,
unused: true,
} }
input: { input: {
function f1() { function f1() {
@@ -30,9 +41,20 @@ issue979_reported: {
issue979_test_negated_is_best: { issue979_test_negated_is_best: {
options = { options = {
sequences:true, properties:true, dead_code:true, conditionals:true, booleans: true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true, comparisons: true,
keep_fargs:true, if_return:true, join_vars:true, side_effects:true conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: true,
side_effects: true,
unused: true,
} }
input: { input: {
function f3() { function f3() {

View File

@@ -1,5 +1,9 @@
labels_1: { labels_1: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
out: { out: {
if (foo) break out; if (foo) break out;
@@ -13,7 +17,11 @@ labels_1: {
} }
labels_2: { labels_2: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
out: { out: {
if (foo) print("stuff"); if (foo) print("stuff");
@@ -30,7 +38,11 @@ labels_2: {
} }
labels_3: { labels_3: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
for (var i = 0; i < 5; ++i) { for (var i = 0; i < 5; ++i) {
if (i < 3) continue; if (i < 3) continue;
@@ -45,7 +57,11 @@ labels_3: {
} }
labels_4: { labels_4: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
out: for (var i = 0; i < 5; ++i) { out: for (var i = 0; i < 5; ++i) {
if (i < 3) continue out; if (i < 3) continue out;
@@ -60,7 +76,11 @@ labels_4: {
} }
labels_5: { labels_5: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
// should keep the break-s in the following // should keep the break-s in the following
input: { input: {
while (foo) { while (foo) {
@@ -92,7 +112,11 @@ labels_6: {
} }
labels_7: { labels_7: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
while (foo) { while (foo) {
x(); x();
@@ -109,7 +133,11 @@ labels_7: {
} }
labels_8: { labels_8: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
while (foo) { while (foo) {
x(); x();
@@ -127,7 +155,11 @@ labels_8: {
} }
labels_9: { labels_9: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
out: while (foo) { out: while (foo) {
x(); x();
@@ -146,7 +178,11 @@ labels_9: {
} }
labels_10: { labels_10: {
options = { if_return: true, conditionals: true, dead_code: true }; options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: { input: {
out: while (foo) { out: while (foo) {
x(); x();

View File

@@ -1,5 +1,7 @@
while_becomes_for: { while_becomes_for: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
while (foo()) bar(); while (foo()) bar();
} }
@@ -9,7 +11,9 @@ while_becomes_for: {
} }
drop_if_break_1: { drop_if_break_1: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
for (;;) for (;;)
if (foo()) break; if (foo()) break;
@@ -20,7 +24,9 @@ drop_if_break_1: {
} }
drop_if_break_2: { drop_if_break_2: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
for (;bar();) for (;bar();)
if (foo()) break; if (foo()) break;
@@ -31,7 +37,9 @@ drop_if_break_2: {
} }
drop_if_break_3: { drop_if_break_3: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
for (;bar();) { for (;bar();) {
if (foo()) break; if (foo()) break;
@@ -48,7 +56,10 @@ drop_if_break_3: {
} }
drop_if_break_4: { drop_if_break_4: {
options = { loops: true, sequences: true }; options = {
loops: true,
sequences: true,
}
input: { input: {
for (;bar();) { for (;bar();) {
x(); x();
@@ -64,7 +75,9 @@ drop_if_break_4: {
} }
drop_if_else_break_1: { drop_if_else_break_1: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
for (;;) if (foo()) bar(); else break; for (;;) if (foo()) bar(); else break;
} }
@@ -74,7 +87,9 @@ drop_if_else_break_1: {
} }
drop_if_else_break_2: { drop_if_else_break_2: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
for (;bar();) { for (;bar();) {
if (foo()) baz(); if (foo()) baz();
@@ -87,7 +102,9 @@ drop_if_else_break_2: {
} }
drop_if_else_break_3: { drop_if_else_break_3: {
options = { loops: true }; options = {
loops: true,
}
input: { input: {
for (;bar();) { for (;bar();) {
if (foo()) baz(); if (foo()) baz();
@@ -106,7 +123,10 @@ drop_if_else_break_3: {
} }
drop_if_else_break_4: { drop_if_else_break_4: {
options = { loops: true, sequences: true }; options = {
loops: true,
sequences: true,
}
input: { input: {
for (;bar();) { for (;bar();) {
x(); x();
@@ -123,7 +143,9 @@ drop_if_else_break_4: {
} }
parse_do_while_with_semicolon: { parse_do_while_with_semicolon: {
options = { loops: false }; options = {
loops: false,
}
input: { input: {
do { do {
x(); x();
@@ -135,7 +157,9 @@ parse_do_while_with_semicolon: {
} }
parse_do_while_without_semicolon: { parse_do_while_without_semicolon: {
options = { loops: false }; options = {
loops: false,
}
input: { input: {
do { do {
x(); x();
@@ -153,7 +177,7 @@ evaluate: {
loops: true, loops: true,
passes: 2, passes: 2,
side_effects: true, side_effects: true,
}; }
input: { input: {
while (true) { while (true) {
a(); a();
@@ -294,10 +318,10 @@ issue_186_beautify_ie8: {
] ]
} }
issue_186_bracketize: { issue_186_braces: {
beautify = { beautify = {
beautify: false, beautify: false,
bracketize: true, braces: true,
ie8: false, ie8: false,
} }
input: { input: {
@@ -314,10 +338,10 @@ issue_186_bracketize: {
expect_exact: 'var x=3;if(foo()){do{do{alert(x)}while(--x)}while(x)}else{bar()}' expect_exact: 'var x=3;if(foo()){do{do{alert(x)}while(--x)}while(x)}else{bar()}'
} }
issue_186_bracketize_ie8: { issue_186_braces_ie8: {
beautify = { beautify = {
beautify: false, beautify: false,
bracketize: true, braces: true,
ie8: true, ie8: true,
} }
input: { input: {
@@ -334,10 +358,10 @@ issue_186_bracketize_ie8: {
expect_exact: 'var x=3;if(foo()){do{do{alert(x)}while(--x)}while(x)}else{bar()}' expect_exact: 'var x=3;if(foo()){do{do{alert(x)}while(--x)}while(x)}else{bar()}'
} }
issue_186_beautify_bracketize: { issue_186_beautify_braces: {
beautify = { beautify = {
beautify: true, beautify: true,
bracketize: true, braces: true,
ie8: false, ie8: false,
} }
input: { input: {
@@ -366,10 +390,10 @@ issue_186_beautify_bracketize: {
] ]
} }
issue_186_beautify_bracketize_ie8: { issue_186_beautify_braces_ie8: {
beautify = { beautify = {
beautify: true, beautify: true,
bracketize: true, braces: true,
ie8: true, ie8: true,
} }
input: { input: {
@@ -457,7 +481,7 @@ init_side_effects: {
options = { options = {
loops: true, loops: true,
side_effects: true, side_effects: true,
}; }
input: { input: {
for (function() {}(), i = 0; i < 5; i++) console.log(i); for (function() {}(), i = 0; i < 5; i++) console.log(i);
for (function() {}(); i < 10; i++) console.log(i); for (function() {}(); i < 10; i++) console.log(i);
@@ -605,3 +629,20 @@ issue_2740_5: {
} }
expect_stdout: "0 undefined" expect_stdout: "0 undefined"
} }
issue_2904: {
options = {
join_vars: true,
loops: true,
}
input: {
var a = 1;
do {
console.log(a);
} while (--a);
}
expect: {
for (var a = 1; console.log(a), --a;);
}
expect_stdout: "1"
}

View File

@@ -8,14 +8,14 @@ too_short: {
} }
} }
expect_exact: [ expect_exact: [
'function f(a){', "function f(",
'return{', "a){return{",
'c:42,', "c:42,d:a(",
'd:a(),', '),e:"foo"}',
'e:"foo"}}', "}",
] ]
expect_warnings: [ expect_warnings: [
"WARN: Output exceeds 10 characters" "WARN: Output exceeds 10 characters",
] ]
} }
@@ -29,11 +29,25 @@ just_enough: {
} }
} }
expect_exact: [ expect_exact: [
'function f(a){', "function f(a){",
'return{c:42,', "return{c:42,",
'd:a(),e:"foo"}', 'd:a(),e:"foo"}',
'}', "}",
]
expect_warnings: [
] ]
expect_warnings: []
}
issue_304: {
beautify = {
max_line_len: 10,
}
input: {
var a = 0, b = 0, c = 0, d = 0, e = 0;
}
expect_exact: [
"var a=0,",
"b=0,c=0,",
"d=0,e=0;",
]
expect_warnings: []
} }

View File

@@ -1,7 +1,7 @@
negate_iife_1: { negate_iife_1: {
options = { options = {
negate_iife: true negate_iife: true,
}; }
input: { input: {
(function(){ stuff() })(); (function(){ stuff() })();
} }
@@ -13,7 +13,7 @@ negate_iife_1: {
negate_iife_1_off: { negate_iife_1_off: {
options = { options = {
negate_iife: false, negate_iife: false,
}; }
input: { input: {
(function(){ stuff() })(); (function(){ stuff() })();
} }
@@ -24,7 +24,7 @@ negate_iife_2: {
options = { options = {
inline: true, inline: true,
negate_iife: true, negate_iife: true,
}; }
input: { input: {
(function(){ return {} })().x = 10; (function(){ return {} })().x = 10;
} }
@@ -45,9 +45,9 @@ negate_iife_2_side_effects: {
negate_iife_3: { negate_iife_3: {
options = { options = {
conditionals: true,
negate_iife: true, negate_iife: true,
conditionals: true }
};
input: { input: {
(function(){ return t })() ? console.log(true) : console.log(false); (function(){ return t })() ? console.log(true) : console.log(false);
} }
@@ -67,7 +67,7 @@ negate_iife_3_evaluate: {
(function(){ return true })() ? console.log(true) : console.log(false); (function(){ return true })() ? console.log(true) : console.log(false);
} }
expect: { expect: {
console.log(true); true, console.log(true);
} }
expect_stdout: true expect_stdout: true
} }
@@ -88,9 +88,9 @@ negate_iife_3_side_effects: {
negate_iife_3_off: { negate_iife_3_off: {
options = { options = {
negate_iife: false,
conditionals: true, conditionals: true,
}; negate_iife: false,
}
input: { input: {
(function(){ return t })() ? console.log(true) : console.log(false); (function(){ return t })() ? console.log(true) : console.log(false);
} }
@@ -110,17 +110,17 @@ negate_iife_3_off_evaluate: {
(function(){ return true })() ? console.log(true) : console.log(false); (function(){ return true })() ? console.log(true) : console.log(false);
} }
expect: { expect: {
console.log(true); true, console.log(true);
} }
expect_stdout: true expect_stdout: true
} }
negate_iife_4: { negate_iife_4: {
options = { options = {
negate_iife: true,
conditionals: true, conditionals: true,
sequences: true negate_iife: true,
}; sequences: true,
}
input: { input: {
(function(){ return t })() ? console.log(true) : console.log(false); (function(){ return t })() ? console.log(true) : console.log(false);
(function(){ (function(){
@@ -136,11 +136,11 @@ negate_iife_4: {
sequence_off: { sequence_off: {
options = { options = {
negate_iife: false,
conditionals: true, conditionals: true,
sequences: true, negate_iife: false,
passes: 2, passes: 2,
}; sequences: true,
}
input: { input: {
function f() { function f() {
(function(){ return t })() ? console.log(true) : console.log(false); (function(){ return t })() ? console.log(true) : console.log(false);
@@ -171,10 +171,10 @@ sequence_off: {
negate_iife_5: { negate_iife_5: {
options = { options = {
conditionals: true,
negate_iife: true, negate_iife: true,
sequences: true, sequences: true,
conditionals: true, }
};
input: { input: {
if ((function(){ return t })()) { if ((function(){ return t })()) {
foo(true); foo(true);
@@ -194,10 +194,10 @@ negate_iife_5: {
negate_iife_5_off: { negate_iife_5_off: {
options = { options = {
conditionals: true,
negate_iife: false, negate_iife: false,
sequences: true, sequences: true,
conditionals: true, }
};
input: { input: {
if ((function(){ return t })()) { if ((function(){ return t })()) {
foo(true); foo(true);
@@ -217,10 +217,10 @@ negate_iife_5_off: {
negate_iife_nested: { negate_iife_nested: {
options = { options = {
conditionals: true,
negate_iife: true, negate_iife: true,
sequences: true, sequences: true,
conditionals: true, }
};
input: { input: {
function Foo(f) { function Foo(f) {
this.f = f; this.f = f;
@@ -250,10 +250,10 @@ negate_iife_nested: {
negate_iife_nested_off: { negate_iife_nested_off: {
options = { options = {
conditionals: true,
negate_iife: false, negate_iife: false,
sequences: true, sequences: true,
conditionals: true, }
};
input: { input: {
function Foo(f) { function Foo(f) {
this.f = f; this.f = f;
@@ -283,10 +283,10 @@ negate_iife_nested_off: {
negate_iife_issue_1073: { negate_iife_issue_1073: {
options = { options = {
conditionals: true,
negate_iife: true, negate_iife: true,
sequences: true, sequences: true,
conditionals: true, }
};
input: { input: {
new (function(a) { new (function(a) {
return function Foo() { return function Foo() {
@@ -356,7 +356,7 @@ issue_1288: {
conditionals: true, conditionals: true,
negate_iife: true, negate_iife: true,
side_effects: false, side_effects: false,
}; }
input: { input: {
if (w) ; if (w) ;
else { else {

View File

@@ -36,7 +36,9 @@ new_statements_3: {
} }
new_with_rewritten_true_value: { new_with_rewritten_true_value: {
options = { booleans: true } options = {
booleans: true,
}
input: { input: {
new true; new true;
} }

View File

@@ -1,21 +1,49 @@
hex_numbers_in_parentheses_for_prototype_functions: { hex_numbers_in_parentheses_for_prototype_functions: {
input: { beautify = {
(-2); beautify: true,
(-2).toFixed(0);
(2);
(2).toFixed(0);
(0.2);
(0.2).toFixed(0);
(0.00000002);
(0.00000002).toFixed(0);
(1000000000000000128);
(1000000000000000128).toFixed(0);
} }
expect_exact: "-2;(-2).toFixed(0);2;2..toFixed(0);.2;.2.toFixed(0);2e-8;2e-8.toFixed(0);0xde0b6b3a7640080;(0xde0b6b3a7640080).toFixed(0);" input: {
function f() {
(-2);
(-2).toFixed(0);
(2);
(2).toFixed(0);
(0.2);
(0.2).toFixed(0);
(2.34e20);
(2.34e20).toFixed(0);
(0.00000002);
(0.00000002).toFixed(0);
(1000000000000000128);
(1000000000000000128).toFixed(0);
(-1000000000000000128);
(-1000000000000000128).toFixed(0);
}
}
expect_exact: [
"function f() {",
" -2;",
" (-2).toFixed(0);",
" 2;",
" 2..toFixed(0);",
" .2;",
" .2.toFixed(0);",
" 234e18;",
" 234e18.toFixed(0);",
" 2e-8;",
" 2e-8.toFixed(0);",
" 0xde0b6b3a7640080;",
" (0xde0b6b3a7640080).toFixed(0);",
" -0xde0b6b3a7640080;",
" (-0xde0b6b3a7640080).toFixed(0);",
"}",
]
} }
comparisons: { comparisons: {

View File

@@ -1208,6 +1208,37 @@ join_object_assignments_3: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
join_object_assignments_4: {
options = {
join_vars: true,
sequences: true,
}
input: {
var o;
console.log(o);
o = {};
o.a = "foo";
console.log(o.b);
o.b = "bar";
console.log(o.a);
}
expect: {
var o;
console.log(o),
o = {
a: "foo",
},
console.log(o.b),
o.b = "bar",
console.log(o.a);
}
expect_stdout: [
"undefined",
"undefined",
"foo",
]
}
join_object_assignments_return_1: { join_object_assignments_return_1: {
options = { options = {
join_vars: true, join_vars: true,
@@ -1588,3 +1619,216 @@ issue_2816: {
} }
expect_stdout: "3 2 4" expect_stdout: "3 2 4"
} }
issue_2893_1: {
options = {
join_vars: true,
}
input: {
var o = {
get a() {
return "PASS";
},
};
o.a = "FAIL";
console.log(o.a);
}
expect: {
var o = {
get a() {
return "PASS";
},
};
o.a = "FAIL";
console.log(o.a);
}
expect_stdout: "PASS"
}
issue_2893_2: {
options = {
join_vars: true,
}
input: {
var o = {
set a(v) {
this.b = v;
},
b: "FAIL",
};
o.a = "PASS";
console.log(o.b);
}
expect: {
var o = {
set a(v) {
this.b = v;
},
b: "FAIL",
};
o.a = "PASS";
console.log(o.b);
}
expect_stdout: "PASS"
}
issue_869_1: {
mangle = {
properties: {
reserved: [ "get" ]
},
}
input: {
var o = { p: "FAIL" };
Object.defineProperty(o, "p", {
get: function() {
return "PASS";
}
});
console.log(o.p);
}
expect: {
var o = { o: "FAIL" };
Object.defineProperty(o, "o", {
get: function() {
return "PASS";
}
});
console.log(o.o);
}
expect_stdout: "PASS"
}
issue_869_2: {
mangle = {
properties: {
reserved: [ "get" ]
},
}
input: {
var o = { p: "FAIL" };
Object.defineProperties(o, {
p: {
get: function() {
return "PASS";
}
}
});
console.log(o.p);
}
expect: {
var o = { o: "FAIL" };
Object.defineProperties(o, {
o: {
get: function() {
return "PASS";
}
}
});
console.log(o.o);
}
expect_stdout: "PASS"
}
issue_3188_1: {
options = {
collapse_vars: true,
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
}
input: {
(function() {
function f() {
console.log(this.p);
}
(function() {
var o = {
p: "PASS",
f: f
};
o.f();
})();
})();
}
expect: {
(function() {
function f() {
console.log(this.p);
}
({
p: "PASS",
f: f
}).f();
var o;
})();
}
expect_stdout: "PASS"
}
issue_3188_2: {
options = {
collapse_vars: true,
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
(function() {
var f = function() {
console.log(this.p);
};
function g() {
var o = {
p: "PASS",
f: f
};
o.f();
}
g();
})();
}
expect: {
({
p: "PASS",
f: function() {
console.log(this.p);
}
}).f();
}
expect_stdout: "PASS"
}
issue_3188_3: {
options = {
collapse_vars: true,
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
}
input: {
(function() {
function f() {
console.log(this[0]);
}
(function() {
var o = ["PASS", f];
o[1]();
})();
})();
}
expect: {
(function() {
function f() {
console.log(this[0]);
}
["PASS", f][1]();
var o;
})();
}
expect_stdout: "PASS"
}

View File

@@ -535,3 +535,110 @@ issue_2705_6: {
"/* */new(/* */a()||b())(c(),d());", "/* */new(/* */a()||b())(c(),d());",
] ]
} }
issue_3065_1: {
options = {
inline: true,
pure_funcs: [ "pureFunc" ],
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function modifyWrapper(a, f, wrapper) {
wrapper.a = a;
wrapper.f = f;
return wrapper;
}
function pureFunc(fun) {
return modifyWrapper(1, fun, function(a) {
return fun(a);
});
}
var unused = pureFunc(function(x) {
return x;
});
}
expect: {}
}
issue_3065_2: {
rename = true
options = {
inline: true,
pure_funcs: [ "pureFunc" ],
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
mangle = {
reserved: [ "pureFunc" ],
toplevel: true,
}
input: {
function modifyWrapper(a, f, wrapper) {
wrapper.a = a;
wrapper.f = f;
return wrapper;
}
function pureFunc(fun) {
return modifyWrapper(1, fun, function(a) {
return fun(a);
});
}
var unused = pureFunc(function(x) {
return x;
});
}
expect: {}
}
issue_3065_3: {
options = {
pure_funcs: [ "debug" ],
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function debug(msg) {
console.log(msg);
}
debug(function() {
console.log("PASS");
return "FAIL";
}());
}
expect: {
(function() {
console.log("PASS");
})();
}
}
issue_3065_4: {
options = {
pure_funcs: [ "debug" ],
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var debug = function(msg) {
console.log(msg);
};
debug(function() {
console.log("PASS");
return "FAIL";
}());
}
expect: {
(function() {
console.log("PASS");
})();
}
}

View File

@@ -187,10 +187,10 @@ issue_2110_1: {
options = { options = {
collapse_vars: true, collapse_vars: true,
pure_getters: "strict", pure_getters: "strict",
sequences: true,
side_effects: true,
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
sequences: true,
side_effects: true,
unused: true, unused: true,
} }
input: { input: {
@@ -721,3 +721,443 @@ issue_2838: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_2938_1: {
options = {
pure_getters: true,
unused: true,
}
input: {
function f(a) {
a.b = "PASS";
}
var o = {};
f(o);
console.log(o.b);
}
expect: {
function f(a) {
a.b = "PASS";
}
var o = {};
f(o);
console.log(o.b);
}
expect_stdout: "PASS"
}
issue_2938_2: {
options = {
pure_getters: true,
toplevel: true,
unused: true,
}
input: {
var Parser = function Parser() {};
var p = Parser.prototype;
p.initialContext = function initialContext() {
console.log("PASS");
};
p.braceIsBlock = function() {};
(new Parser).initialContext();
}
expect: {
var Parser = function() {};
var p = Parser.prototype;
p.initialContext = function() {
console.log("PASS");
};
p.braceIsBlock = function() {};
(new Parser).initialContext();
}
expect_stdout: "PASS"
}
issue_2938_3: {
options = {
pure_getters: true,
side_effects: true,
unused: true,
}
input: {
function f(a) {
var unused = a.a;
a.b = "PASS";
a.c;
}
var o = {};
o.d;
f(o);
console.log(o.b);
}
expect: {
function f(a) {
a.b = "PASS";
}
var o = {};
f(o);
console.log(o.b);
}
expect_stdout: "PASS"
}
issue_2938_4: {
options = {
pure_getters: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var Parser = function Parser() {};
var p = Parser.prototype;
var unused = p.x;
p.initialContext = function initialContext() {
p.y;
console.log("PASS");
};
p.braceIsBlock = function() {};
(new Parser).initialContext();
}
expect: {
var Parser = function() {};
var p = Parser.prototype;
p.initialContext = function() {
console.log("PASS");
};
p.braceIsBlock = function() {};
(new Parser).initialContext();
}
expect_stdout: "PASS"
}
collapse_vars_1_true: {
options = {
collapse_vars: true,
pure_getters: true,
unused: true,
}
input: {
function f(a, b) {
for (;;) {
var c = a.g();
var d = b.p;
if (c || d) break;
}
}
}
expect: {
function f(a, b) {
for (;;) {
if (a.g() || b.p) break;
}
}
}
}
collapse_vars_1_false: {
options = {
collapse_vars: true,
pure_getters: false,
unused: true,
}
input: {
function f(a, b) {
for (;;) {
var c = a.g();
var d = b.p;
if (c || d) break;
}
}
}
expect: {
function f(a, b) {
for (;;) {
var c = a.g();
var d = b.p;
if (c || d) break;
}
}
}
}
collapse_vars_1_strict: {
options = {
collapse_vars: true,
pure_getters: "strict",
unused: true,
}
input: {
function f(a, b) {
for (;;) {
var c = a.g();
var d = b.p;
if (c || d) break;
}
}
}
expect: {
function f(a, b) {
for (;;) {
var c = a.g();
var d = b.p;
if (c || d) break;
}
}
}
}
collapse_vars_2_true: {
options = {
collapse_vars: true,
pure_getters: true,
reduce_vars: true,
}
input: {
function f() {
function g() {}
g.a = function() {};
g.b = g.a;
return g;
}
}
expect: {
function f() {
function g() {}
g.b = g.a = function() {};
return g;
}
}
}
collapse_vars_2_false: {
options = {
collapse_vars: true,
pure_getters: false,
reduce_vars: true,
}
input: {
function f() {
function g() {}
g.a = function() {};
g.b = g.a;
return g;
}
}
expect: {
function f() {
function g() {}
g.a = function() {};
g.b = g.a;
return g;
}
}
}
collapse_vars_2_strict: {
options = {
collapse_vars: true,
pure_getters: "strict",
reduce_vars: true,
}
input: {
function f() {
function g() {}
g.a = function() {};
g.b = g.a;
return g;
}
}
expect: {
function f() {
function g() {}
g.b = g.a = function() {};
return g;
}
}
}
collapse_rhs_true: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
console.log((42..length = "PASS", "PASS"));
console.log(("foo".length = "PASS", "PASS"));
console.log((false.length = "PASS", "PASS"));
console.log((function() {}.length = "PASS", "PASS"));
console.log(({
get length() {
return "FAIL";
}
}.length = "PASS", "PASS"));
}
expect: {
console.log(42..length = "PASS");
console.log("foo".length = "PASS");
console.log(false.length = "PASS");
console.log(function() {}.length = "PASS");
console.log({
get length() {
return "FAIL";
}
}.length = "PASS");
}
expect_stdout: [
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
]
}
collapse_rhs_false: {
options = {
collapse_vars: true,
pure_getters: false,
}
input: {
console.log((42..length = "PASS", "PASS"));
console.log(("foo".length = "PASS", "PASS"));
console.log((false.length = "PASS", "PASS"));
console.log((function() {}.length = "PASS", "PASS"));
console.log(({
get length() {
return "FAIL";
}
}.length = "PASS", "PASS"));
}
expect: {
console.log(42..length = "PASS");
console.log("foo".length = "PASS");
console.log(false.length = "PASS");
console.log(function() {}.length = "PASS");
console.log({
get length() {
return "FAIL";
}
}.length = "PASS");
}
expect_stdout: [
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
]
}
collapse_rhs_strict: {
options = {
collapse_vars: true,
pure_getters: "strict",
}
input: {
console.log((42..length = "PASS", "PASS"));
console.log(("foo".length = "PASS", "PASS"));
console.log((false.length = "PASS", "PASS"));
console.log((function() {}.length = "PASS", "PASS"));
console.log(({
get length() {
return "FAIL";
}
}.length = "PASS", "PASS"));
}
expect: {
console.log(42..length = "PASS");
console.log("foo".length = "PASS");
console.log(false.length = "PASS");
console.log(function() {}.length = "PASS");
console.log({
get length() {
return "FAIL";
}
}.length = "PASS");
}
expect_stdout: [
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
]
}
collapse_rhs_setter: {
options = {
collapse_vars: true,
pure_getters: "strict",
}
input: {
try {
console.log(({
set length(v) {
throw "PASS";
}
}.length = "FAIL", "FAIL"));
} catch (e) {
console.log(e);
}
}
expect: {
try {
console.log({
set length(v) {
throw "PASS";
}
}.length = "FAIL");
} catch (e) {
console.log(e);
}
}
expect_stdout: "PASS"
}
collapse_rhs_call: {
options = {
collapse_vars: true,
passes: 2,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {};
function f() {
console.log("PASS");
}
o.f = f;
f();
}
expect: {
({}.f = function() {
console.log("PASS");
})();
}
expect_stdout: "PASS"
}
collapse_rhs_lhs: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
function f(a, b) {
a.b = b, b += 2;
console.log(a.b, b);
}
f({}, 1);
}
expect: {
function f(a, b) {
a.b = b, b += 2;
console.log(a.b, b);
}
f({}, 1);
}
expect_stdout: "1 3"
}

File diff suppressed because it is too large Load Diff

37
test/compress/regexp.js Normal file
View File

@@ -0,0 +1,37 @@
regexp_simple: {
input: {
/rx/ig
}
expect_exact: "/rx/gi;"
}
regexp_slashes: {
input: {
/\\\/rx\/\\/ig
}
expect_exact: "/\\\\\\/rx\\/\\\\/gi;"
}
regexp_1: {
input: {
console.log(JSON.stringify("COMPASS? Overpass.".match(/([Sap]+)/ig)));
}
expect: {
console.log(JSON.stringify("COMPASS? Overpass.".match(/([Sap]+)/gi)));
}
expect_stdout: '["PASS","pass"]'
}
regexp_2: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(JSON.stringify("COMPASS? Overpass.".match(new RegExp("([Sap]+)", "ig"))));
}
expect: {
console.log(JSON.stringify("COMPASS? Overpass.".match(/([Sap]+)/gi)));
}
expect_stdout: '["PASS","pass"]'
}

View File

@@ -109,7 +109,7 @@ mangle_catch_toplevel: {
} }
console.log(a); console.log(a);
} }
expect_exact: 'var o="FAIL";try{throw 1}catch(c){o="PASS"}console.log(o);' expect_exact: 'var c="FAIL";try{throw 1}catch(o){c="PASS"}console.log(c);'
expect_stdout: "PASS" expect_stdout: "PASS"
} }
@@ -155,7 +155,7 @@ mangle_catch_var_toplevel: {
} }
console.log(a); console.log(a);
} }
expect_exact: 'var o="FAIL";try{throw 1}catch(r){var o="PASS"}console.log(o);' expect_exact: 'var r="FAIL";try{throw 1}catch(o){var r="PASS"}console.log(r);'
expect_stdout: "PASS" expect_stdout: "PASS"
} }
@@ -451,7 +451,7 @@ function_iife_catch: {
} }
f(); f();
} }
expect_exact: "function f(o){!function(){try{throw 0}catch(c){var o=1;console.log(c,o)}}()}f();" expect_exact: "function f(o){!function(){try{throw 0}catch(o){var c=1;console.log(o,c)}}()}f();"
expect_stdout: "0 1" expect_stdout: "0 1"
} }
@@ -473,7 +473,7 @@ function_iife_catch_ie8: {
} }
f(); f();
} }
expect_exact: "function f(o){!function(){try{throw 0}catch(o){var c=1;console.log(o,c)}}()}f();" expect_exact: "function f(c){!function(){try{throw 0}catch(c){var o=1;console.log(c,o)}}()}f();"
expect_stdout: "0 1" expect_stdout: "0 1"
} }
@@ -499,7 +499,7 @@ function_catch_catch: {
} }
f(); f();
} }
expect_exact: "var o=0;function f(){try{throw 1}catch(c){try{throw 2}catch(o){var o=3;console.log(o)}}console.log(o)}f();" expect_exact: "var o=0;function f(){try{throw 1}catch(o){try{throw 2}catch(c){var c=3;console.log(c)}}console.log(c)}f();"
expect_stdout: [ expect_stdout: [
"3", "3",
"undefined", "undefined",

View File

@@ -1,24 +1,24 @@
return_undefined: { return_undefined: {
options = { options = {
sequences : false, booleans: true,
if_return : true, comparisons: true,
evaluate : true, conditionals: true,
dead_code : true, dead_code: true,
conditionals : true, drop_debugger: true,
comparisons : true, evaluate: true,
booleans : true, hoist_funs: true,
unused : true, hoist_vars: true,
side_effects : true, if_return: true,
properties : true, join_vars: true,
drop_debugger : true, keep_fargs: true,
loops : true, keep_fnames: false,
hoist_funs : true, loops: true,
keep_fargs : true, negate_iife: true,
keep_fnames : false, properties: true,
hoist_vars : true, sequences: false,
join_vars : true, side_effects: true,
negate_iife : true unused: true,
}; }
input: { input: {
function f0() { function f0() {
} }

View File

@@ -1,7 +1,7 @@
make_sequences_1: { make_sequences_1: {
options = { options = {
sequences: true sequences: true,
}; }
input: { input: {
foo(); foo();
bar(); bar();
@@ -14,8 +14,8 @@ make_sequences_1: {
make_sequences_2: { make_sequences_2: {
options = { options = {
sequences: true sequences: true,
}; }
input: { input: {
if (boo) { if (boo) {
foo(); foo();
@@ -35,8 +35,8 @@ make_sequences_2: {
make_sequences_3: { make_sequences_3: {
options = { options = {
sequences: true sequences: true,
}; }
input: { input: {
function f() { function f() {
foo(); foo();
@@ -61,8 +61,8 @@ make_sequences_3: {
make_sequences_4: { make_sequences_4: {
options = { options = {
sequences: true sequences: true,
}; }
input: { input: {
x = 5; x = 5;
if (y) z(); if (y) z();
@@ -90,7 +90,9 @@ make_sequences_4: {
} }
lift_sequences_1: { lift_sequences_1: {
options = { sequences: true }; options = {
sequences: true,
}
input: { input: {
var foo, x, y, bar; var foo, x, y, bar;
foo = !(x(), y(), bar()); foo = !(x(), y(), bar());
@@ -102,7 +104,10 @@ lift_sequences_1: {
} }
lift_sequences_2: { lift_sequences_2: {
options = { sequences: true, evaluate: true }; options = {
evaluate: true,
sequences: true,
}
input: { input: {
var foo = 1, bar; var foo = 1, bar;
foo.x = (foo = {}, 10); foo.x = (foo = {}, 10);
@@ -119,7 +124,10 @@ lift_sequences_2: {
} }
lift_sequences_3: { lift_sequences_3: {
options = { sequences: true, conditionals: true }; options = {
conditionals: true,
sequences: true,
}
input: { input: {
var x, foo, bar, baz; var x, foo, bar, baz;
x = (foo(), bar(), baz()) ? 10 : 20; x = (foo(), bar(), baz()) ? 10 : 20;
@@ -131,7 +139,9 @@ lift_sequences_3: {
} }
lift_sequences_4: { lift_sequences_4: {
options = { side_effects: true }; options = {
side_effects: true,
}
input: { input: {
var x, foo, bar, baz; var x, foo, bar, baz;
x = (foo, bar, baz); x = (foo, bar, baz);
@@ -160,7 +170,9 @@ lift_sequences_5: {
} }
for_sequences: { for_sequences: {
options = { sequences: true }; options = {
sequences: true,
}
input: { input: {
// 1 // 1
foo(); foo();
@@ -203,7 +215,7 @@ for_sequences: {
limit_1: { limit_1: {
options = { options = {
sequences: 3, sequences: 3,
}; }
input: { input: {
a; a;
b; b;
@@ -228,7 +240,7 @@ limit_1: {
limit_2: { limit_2: {
options = { options = {
sequences: 3, sequences: 3,
}; }
input: { input: {
a, b; a, b;
c, d; c, d;
@@ -246,9 +258,9 @@ limit_2: {
negate_iife_for: { negate_iife_for: {
options = { options = {
sequences: true,
negate_iife: true, negate_iife: true,
}; sequences: true,
}
input: { input: {
(function() {})(); (function() {})();
for (i = 0; i < 5; i++) console.log(i); for (i = 0; i < 5; i++) console.log(i);
@@ -265,7 +277,7 @@ negate_iife_for: {
iife: { iife: {
options = { options = {
sequences: true, sequences: true,
}; }
input: { input: {
x = 42; x = 42;
(function a() {})(); (function a() {})();
@@ -668,8 +680,7 @@ side_effects_cascade_2: {
} }
expect: { expect: {
function f(a, b) { function f(a, b) {
b = a, !(b = a) + (b += a) || (b += a),
!a + (b += a) || (b += a),
b = a; b = a;
} }
} }
@@ -877,3 +888,59 @@ forin: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
call: {
options = {
sequences: true,
}
input: {
var a = function() {
return this;
}();
function b() {
console.log("foo");
}
b.c = function() {
console.log(this === b ? "bar" : "baz");
};
(a, b)();
(a, b.c)();
(a, function() {
console.log(this === a);
})();
new (a, b)();
new (a, b.c)();
new (a, function() {
console.log(this === a);
})();
}
expect: {
var a = function() {
return this;
}();
function b() {
console.log("foo");
}
b.c = function() {
console.log(this === b ? "bar" : "baz");
},
a, b(),
(a, b.c)(),
a, function() {
console.log(this === a);
}(),
a, new b(),
a, new b.c(),
a, new function() {
console.log(this === a);
}();
}
expect_stdout: [
"foo",
"baz",
"true",
"foo",
"baz",
"false",
]
}

View File

@@ -14,6 +14,13 @@ issue_1929: {
function f(s) { function f(s) {
return s.split(/[\\/]/); return s.split(/[\\/]/);
} }
console.log(JSON.stringify(f("A/B\\C\\D/E\\F")));
} }
expect_exact: "function f(s){return s.split(/[\\\\/]/)}" expect: {
function f(s) {
return s.split(/[\\/]/);
}
console.log(JSON.stringify(f("A/B\\C\\D/E\\F")));
}
expect_stdout: '["A","B","C","D","E","F"]'
} }

View File

@@ -820,8 +820,8 @@ issue_1758: {
issue_2535: { issue_2535: {
options = { options = {
evaluate: true,
dead_code: true, dead_code: true,
evaluate: true,
switches: true, switches: true,
} }
input: { input: {

View File

@@ -59,7 +59,7 @@ if_else_empty: {
if ({} ? a : b); else {} if ({} ? a : b); else {}
} }
expect: { expect: {
!{} ? b : a; ({}), a;
} }
} }
@@ -104,6 +104,7 @@ if_return: {
conditionals: true, conditionals: true,
if_return: true, if_return: true,
sequences: true, sequences: true,
side_effects: true,
} }
input: { input: {
function f(w, x, y, z) { function f(w, x, y, z) {
@@ -124,7 +125,7 @@ if_return: {
if (w) { if (w) {
if (y) return; if (y) return;
} else if (z) return; } else if (z) return;
return x == y || (x && w(), y && z(), !0); return x == y || (x && w(), y && z()), !0;
} }
} }
} }

View File

@@ -2,7 +2,7 @@ typeof_evaluation: {
options = { options = {
evaluate: true, evaluate: true,
typeofs: true, typeofs: true,
}; }
input: { input: {
a = typeof 1; a = typeof 1;
b = typeof 'test'; b = typeof 'test';
@@ -27,11 +27,11 @@ typeof_evaluation: {
typeof_in_boolean_context: { typeof_in_boolean_context: {
options = { options = {
booleans : true, booleans: true,
evaluate : true, conditionals: true,
conditionals : true, evaluate: true,
side_effects : true, side_effects: true,
}; }
input: { input: {
function f1(x) { return typeof x ? "yes" : "no"; } function f1(x) { return typeof x ? "yes" : "no"; }
function f2() { return typeof g()? "Yes" : "No"; } function f2() { return typeof g()? "Yes" : "No"; }
@@ -90,17 +90,11 @@ typeof_defun_1: {
"function" == typeof h && h(); "function" == typeof h && h();
} }
expect: { expect: {
function g() {
h = 42;
console.log("NOPE");
}
function h() { function h() {
console.log("YUP"); console.log("YUP");
} }
g = 42;
console.log("YES"); console.log("YES");
"function" == typeof g && g(); h();
"function" == typeof h && h();
} }
expect_stdout: [ expect_stdout: [
"YES", "YES",

View File

@@ -1,5 +1,5 @@
unicode_parse_variables: { unicode_parse_variables: {
options = {}; options = {}
input: { input: {
var a = {}; var a = {};
a.你好 = 456; a.你好 = 456;

View File

@@ -23,7 +23,7 @@ wrap_iife_in_expression: {
wrap_iife: true, wrap_iife: true,
} }
input: { input: {
foo = (function () { foo = (function() {
return bar(); return bar();
})(); })();
} }

View File

@@ -1,4 +1,5 @@
var fs = require("fs"); var fs = require("fs");
var parse = require("url").parse;
var path = require("path"); var path = require("path");
try { try {
@@ -19,7 +20,9 @@ module.exports = function(url, callback) {
var result = read(url); var result = read(url);
result.on("error", function(e) { result.on("error", function(e) {
if (e.code != "ENOENT") return callback(e); if (e.code != "ENOENT") return callback(e);
require(url.slice(0, url.indexOf(":"))).get(url, function(res) { var options = parse(url);
options.rejectUnauthorized = false;
require(options.protocol.slice(0, -1)).get(options, function(res) {
if (res.statusCode !== 200) return callback(res); if (res.statusCode !== 200) return callback(res);
res.pipe(fs.createWriteStream(local(url)).on("close", function() { res.pipe(fs.createWriteStream(local(url)).on("close", function() {
callback(null, read(url)); callback(null, read(url));

View File

@@ -0,0 +1,4 @@
function enclose() {
console.log("test enclose");
}
enclose();

View File

@@ -1,4 +1,4 @@
var bar = (function () { var bar = (function() {
function foo (bar) { function foo (bar) {
return bar; return bar;
} }

View File

@@ -1,5 +1,5 @@
function test(a){ function test(a){
"aaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaa"
;a(err,data),a(err,data) ;a(err,data),a(err,
} data)}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7QUFDVjtDQUNBQSxFQUFTQyxJQUFLQyxNQUNkRixFQUFTQyxJQUFLQyJ9 //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7QUFDVjtDQUNBQSxFQUFTQyxJQUFLQyxNQUNkRixFQUFTQztBQUFLQyJ9

View File

@@ -0,0 +1,2 @@
function _toConsumableArray(arr){if(Array.isArray(arr)){for(var i=0,arr2=Array(arr.length);i<arr.length;i++){arr2[i]=arr[i]}return arr2}else{return Array.from(arr)}}var _require=require("bar"),foo=_require.foo;var _require2=require("world"),hello=_require2.hello;foo.x.apply(foo,_toConsumableArray(foo.y(hello.z)));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0Mi5qcyJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiYXJyIl0sIm1hcHBpbmdzIjoiMEpBQWNBLEtBQVFDIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3Qge2Zvb30gPSByZXF1aXJlKFwiYmFyXCIpO1xuY29uc3Qge2hlbGxvfSA9IHJlcXVpcmUoXCJ3b3JsZFwiKTtcblxuZm9vLngoLi4uZm9vLnkoaGVsbG8ueikpO1xuIl19

View File

@@ -0,0 +1,11 @@
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
var _require = require("bar"),
foo = _require.foo;
var _require2 = require("world"),
hello = _require2.hello;
foo.x.apply(foo, _toConsumableArray(foo.y(hello.z)));
//# sourceMappingURL=input.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["input2.js"],"names":["require","foo","hello","x","apply","_toConsumableArray","y","z"],"mappings":"kLAAcA,QAAQ,OAAfC,aAAAA,kBACSD,QAAQ,SAAjBE,gBAAAA,MAEPD,IAAIE,EAAJC,MAAAH,IAAAI,mBAASJ,IAAIK,EAAEJ,MAAMK","sourcesContent":["const {foo} = require(\"bar\");\nconst {hello} = require(\"world\");\n\nfoo.x(...foo.y(hello.z));\n"]}

View File

@@ -3,7 +3,7 @@
"use strict"; "use strict";
var site = "http://browserbench.org/JetStream"; var site = "https://browserbench.org/JetStream";
if (typeof phantom == "undefined") { if (typeof phantom == "undefined") {
require("../tools/exit"); require("../tools/exit");
var args = process.argv.slice(2); var args = process.argv.slice(2);

View File

@@ -1,24 +1,114 @@
var fs = require("fs"); var fs = require("fs");
var Mocha = require("mocha");
var path = require("path");
// Instantiate a Mocha instance var config = {
var mocha = new Mocha({ limit: 5000,
timeout: 5000 timeout: function(limit) {
}); this.limit = limit;
var testDir = __dirname + "/mocha/"; }
};
var tasks = [];
var titles = [];
describe = function(title, fn) {
config = Object.create(config);
titles.push(title);
fn.call(config);
titles.pop();
config = Object.getPrototypeOf(config);
};
it = function(title, fn) {
fn.limit = config.limit;
fn.titles = titles.slice();
fn.titles.push(title);
tasks.push(fn);
};
// Add each .js file to the Mocha instance fs.readdirSync("test/mocha").filter(function(file) {
fs.readdirSync(testDir).filter(function(file) {
return /\.js$/.test(file); return /\.js$/.test(file);
}).forEach(function(file) { }).forEach(function(file) {
mocha.addFile(path.join(testDir, file)); require("./mocha/" + file);
}); });
module.exports = function() { function log_titles(log, current, marker) {
mocha.run(function(failures) { var indent = "";
if (failures) process.on("exit", function() { var writing = false;
process.exit(failures); for (var i = 0; i < current.length; i++, indent += " ") {
if (titles[i] != current[i]) writing = true;
if (writing) log(indent + (i == current.length - 1 && marker || "") + current[i]);
}
titles = current;
}
function red(text) {
return "\u001B[31m" + text + "\u001B[39m";
}
function green(text) {
return "\u001B[32m" + text + "\u001B[39m";
}
var errors = [];
var total = tasks.length;
titles = [];
process.nextTick(function run() {
var task = tasks.shift();
if (task) try {
var elapsed = Date.now();
var timer;
var done = function() {
reset();
elapsed = Date.now() - elapsed;
if (elapsed > task.limit) {
throw new Error("Timed out: " + elapsed + "ms > " + task.limit + "ms");
}
log_titles(console.log, task.titles, green('\u221A '));
process.nextTick(run);
};
if (task.length) {
task.timeout = function(limit) {
clearTimeout(timer);
task.limit = limit;
timer = setTimeout(function() {
raise(new Error("Timed out: exceeds " + limit + "ms"));
}, limit);
};
task.timeout(task.limit);
process.on("uncaughtException", raise);
task.call(task, done);
} else {
task.timeout = config.timeout;
task.call(task);
done();
}
} catch (err) {
raise(err);
} else if (errors.length) {
console.error();
console.log(red(errors.length + " test(s) failed!"));
titles = [];
errors.forEach(function(titles, index) {
console.error();
log_titles(console.error, titles, (index + 1) + ") ");
var lines = titles.error.stack.split('\n');
console.error(red(lines[0]));
console.error(lines.slice(1).join("\n"));
}); });
}); process.exit(1);
}; } else {
console.log();
console.log(green(total + " test(s) passed."));
}
function raise(err) {
reset();
task.titles.error = err;
errors.push(task.titles);
log_titles(console.log, task.titles, red('\u00D7 '));
process.nextTick(run);
}
function reset() {
clearTimeout(timer);
done = function() {};
process.removeListener("uncaughtException", raise);
}
});

View File

@@ -1,17 +1,14 @@
var UglifyJS = require("../node");
var assert = require("assert"); var assert = require("assert");
var UglifyJS = require("../..");
describe("arguments", function() { describe("arguments", function() {
it("Should known that arguments in functions are local scoped", function() { it("Should known that arguments in functions are local scoped", function() {
var ast = UglifyJS.parse("var arguments; var f = function() {arguments.length}"); var ast = UglifyJS.parse("var arguments; var f = function() {arguments.length}");
ast.figure_out_scope(); ast.figure_out_scope();
// Test scope of `var arguments` // Test scope of `var arguments`
assert.strictEqual(ast.find_variable("arguments").global, true); assert.strictEqual(ast.find_variable("arguments").global, true);
// Select arguments symbol in function // Select arguments symbol in function
var symbol = ast.body[1].definitions[0].value.find_variable("arguments"); var symbol = ast.body[1].definitions[0].value.find_variable("arguments");
assert.strictEqual(symbol.global, false); assert.strictEqual(symbol.global, false);
assert.strictEqual(symbol.scope, ast. // From ast assert.strictEqual(symbol.scope, ast. // From ast
body[1]. // Select 2nd statement (equals to `var f ...`) body[1]. // Select 2nd statement (equals to `var f ...`)
@@ -27,4 +24,4 @@ describe("arguments", function() {
assert.strictEqual(ast.body[0].body[0].uses_arguments, true); assert.strictEqual(ast.body[0].body[0].uses_arguments, true);
assert.strictEqual(ast.body[0].body[0].body[0].uses_arguments, false); assert.strictEqual(ast.body[0].body[0].body[0].uses_arguments, false);
}); });
}); });

View File

@@ -1,217 +1,241 @@
var assert = require("assert"); var assert = require("assert");
var exec = require("child_process").exec; var exec = require("child_process").exec;
var readFileSync = require("fs").readFileSync; var fs = require("fs");
function read(path) { function read(path) {
return readFileSync(path, "utf8"); return fs.readFileSync(path, "utf8");
} }
describe("bin/uglifyjs", function () { describe("bin/uglifyjs", function() {
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs'; var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
it("should produce a functional build when using --self", function (done) { it("Should produce a functional build when using --self", function(done) {
this.timeout(30000); this.timeout(30000);
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS'; var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
eval(stdout); eval(stdout);
assert.strictEqual(typeof WrappedUglifyJS, "object");
assert.strictEqual(typeof WrappedUglifyJS, 'object');
var result = WrappedUglifyJS.minify("foo([true,,2+3]);"); var result = WrappedUglifyJS.minify("foo([true,,2+3]);");
assert.strictEqual(result.error, undefined); assert.strictEqual(result.error, undefined);
assert.strictEqual(result.code, "foo([!0,,5]);"); assert.strictEqual(result.code, "foo([!0,,5]);");
done(); done();
}); });
}); });
it("Should be able to filter comments correctly with `--comments all`", function (done) { it("Should be able to filter comments correctly with `--comments all`", function(done) {
var command = uglifyjscmd + ' test/input/comments/filter.js --comments all'; var command = uglifyjscmd + ' test/input/comments/filter.js --comments all';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "// foo\n/*@preserve*/\n// bar\n\n"); assert.strictEqual(stdout, "// foo\n/*@preserve*/\n// bar\n\n");
done(); done();
}); });
}); });
it("Should be able to filter comments correctly with `--comment <RegExp>`", function (done) { it("Should be able to filter comments correctly with `--comment <RegExp>`", function(done) {
var command = uglifyjscmd + ' test/input/comments/filter.js --comments /r/'; var command = uglifyjscmd + ' test/input/comments/filter.js --comments /r/';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "/*@preserve*/\n// bar\n\n"); assert.strictEqual(stdout, "/*@preserve*/\n// bar\n\n");
done(); done();
}); });
}); });
it("Should be able to filter comments correctly with just `--comment`", function (done) { it("Should be able to filter comments correctly with just `--comment`", function(done) {
var command = uglifyjscmd + ' test/input/comments/filter.js --comments'; var command = uglifyjscmd + ' test/input/comments/filter.js --comments';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "/*@preserve*/\n\n"); assert.strictEqual(stdout, "/*@preserve*/\n\n");
done(); done();
}); });
}); });
it("Should append source map to output when using --source-map url=inline", function (done) { it("Should give sensible error against invalid input source map", function(done) {
var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map url=inline"; var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline";
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout) { assert.ok(err);
if (err) throw err; assert.deepEqual(stderr.split(/\n/).slice(0, 2), [
"INFO: Using input source map: blah",
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n" + "ERROR: invalid input source map: blah",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==\n"); ]);
done(); done();
}); });
}); });
it("should not append source map to output when not using --source-map url=inline", function (done) { it("Should append source map to output when using --source-map url=inline", function(done) {
var command = uglifyjscmd + ' test/input/issue-1323/sample.js'; var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map url=inline";
exec(command, function(err, stdout) {
exec(command, function (err, stdout) { if (err) throw err;
assert.strictEqual(stdout, [
"var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
"",
].join("\n"));
done();
});
});
it("Should not append source map to output when not using --source-map url=inline", function(done) {
var command = uglifyjscmd + ' test/input/issue-1323/sample.js';
exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n"); assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n");
done(); done();
}); });
}); });
it("should not consider source map file content as source map file name (issue #2082)", function (done) { it("Should not consider source map file content as source map file name (issue #2082)", function(done) {
var command = [ var command = [
uglifyjscmd, uglifyjscmd,
"test/input/issue-2082/sample.js", "test/input/issue-2082/sample.js",
"--source-map", "content=test/input/issue-2082/sample.js.map", "--source-map", "content=test/input/issue-2082/sample.js.map",
"--source-map", "url=inline", "--source-map", "url=inline",
].join(" "); ].join(" ");
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
if (err) throw err; if (err) throw err;
var stderrLines = stderr.split("\n");
var stderrLines = stderr.split('\n'); assert.strictEqual(stderrLines[0], "INFO: Using input source map: test/input/issue-2082/sample.js.map");
assert.strictEqual(stderrLines[0], 'INFO: Using input source map: test/input/issue-2082/sample.js.map');
assert.notStrictEqual(stderrLines[1], 'INFO: Using input source map: {"version": 3,"sources": ["index.js"],"mappings": ";"}'); assert.notStrictEqual(stderrLines[1], 'INFO: Using input source map: {"version": 3,"sources": ["index.js"],"mappings": ";"}');
done(); done();
}); });
}); });
it("Should work with --keep-fnames (mangle only)", function (done) { it("Should not load source map before finish reading from STDIN", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m'; var mapFile = "tmp/input.js.map";
try {
fs.mkdirSync("./tmp");
} catch (e) {
if (e.code != "EEXIST") throw e;
}
try {
fs.unlinkSync(mapFile);
} catch (e) {
if (e.code != "ENOENT") throw e;
}
var command = [
uglifyjscmd,
"--source-map", "content=" + mapFile,
"--source-map", "includeSources=true",
"--source-map", "url=inline",
].join(" ");
exec(command, function (err, stdout) { var child = exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, read("test/input/pr-3040/expect.js"));
done();
});
setTimeout(function() {
fs.writeFileSync(mapFile, read("test/input/pr-3040/input.js.map"));
child.stdin.end(read("test/input/pr-3040/input.js"));
}, 1000);
});
it("Should work with --keep-fnames (mangle only)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n"); assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
done(); done();
}); });
}); });
it("Should work with --keep-fnames (mangle & compress)", function (done) { it("Should work with --keep-fnames (mangle & compress)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c unused=false'; var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c unused=false';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n"); assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n");
done(); done();
}); });
}); });
it("Should work with keep_fnames under mangler options", function (done) { it("Should work with keep_fnames under mangler options", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep_fnames=true'; var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep_fnames=true';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n"); assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
done(); done();
}); });
}); });
it("Should work with --define (simple)", function (done) { it("Should work with --define (simple)", function(done) {
var command = uglifyjscmd + ' test/input/global_defs/simple.js --define D=5 -c'; var command = uglifyjscmd + ' test/input/global_defs/simple.js --define D=5 -c';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "console.log(5);\n"); assert.strictEqual(stdout, "console.log(5);\n");
done(); done();
}); });
}); });
it("Should work with --define (nested)", function (done) { it("Should work with --define (nested)", function(done) {
var command = uglifyjscmd + ' test/input/global_defs/nested.js --define C.D=5,C.V=3 -c'; var command = uglifyjscmd + ' test/input/global_defs/nested.js --define C.D=5,C.V=3 -c';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "console.log(3,5);\n"); assert.strictEqual(stdout, "console.log(3,5);\n");
done(); done();
}); });
}); });
it("Should work with --define (AST_Node)", function (done) { it("Should work with --define (AST_Node)", function(done) {
var command = uglifyjscmd + ' test/input/global_defs/simple.js --define console.log=stdout.println -c'; var command = uglifyjscmd + ' test/input/global_defs/simple.js --define console.log=stdout.println -c';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "stdout.println(D);\n"); assert.strictEqual(stdout, "stdout.println(D);\n");
done(); done();
}); });
}); });
it("Should work with `--beautify`", function (done) { it("Should work with `--beautify`", function(done) {
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b'; var command = uglifyjscmd + ' test/input/issue-1482/input.js -b';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, read("test/input/issue-1482/default.js")); assert.strictEqual(stdout, read("test/input/issue-1482/default.js"));
done(); done();
}); });
}); });
it("Should work with `--beautify bracketize`", function (done) { it("Should work with `--beautify braces`", function(done) {
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b bracketize'; var command = uglifyjscmd + ' test/input/issue-1482/input.js -b braces';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, read("test/input/issue-1482/braces.js"));
assert.strictEqual(stdout, read("test/input/issue-1482/bracketize.js"));
done(); done();
}); });
}); });
it("Should process inline source map", function(done) { it("Should process inline source map", function(done) {
var command = uglifyjscmd + " test/input/issue-520/input.js -mc toplevel --source-map content=inline,url=inline"; var command = [
uglifyjscmd,
exec(command, function (err, stdout) { "test/input/issue-520/input.js",
"-mc", "toplevel",
"--source-map", "content=inline",
"--source-map", "includeSources=true",
"--source-map", "url=inline",
].join(" ");
exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, read("test/input/issue-520/output.js")); assert.strictEqual(stdout, read("test/input/issue-520/output.js"));
done(); done();
}); });
}); });
it("Should warn for missing inline source map", function(done) { it("Should warn for missing inline source map", function(done) {
var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map content=inline,url=inline"; var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map content=inline,url=inline";
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, [
"var bar=function(){function foo(bar){return bar}return foo}();", "var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
"", "",
].join("\n")); ].join("\n"));
assert.strictEqual(stderr, "WARN: inline source map not found\n"); var stderrLines = stderr.split("\n");
assert.strictEqual(stderrLines[0], "WARN: inline source map not found: test/input/issue-1323/sample.js");
done(); done();
}); });
}); });
it("Should fail with multiple input and inline source map", function(done) { it("Should handle multiple input and inline source map", function(done) {
var command = uglifyjscmd + " test/input/issue-520/input.js test/input/issue-520/output.js --source-map content=inline,url=inline"; var command = [
uglifyjscmd,
exec(command, function (err, stdout, stderr) { "test/input/issue-520/input.js",
assert.ok(err); "test/input/issue-1323/sample.js",
assert.strictEqual(stderr.split(/\n/)[0], "ERROR: inline source map only works with singular input"); "--source-map", "content=inline,url=inline",
].join(" ");
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, [
"var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUFBLE1BQWdCQyxRQUFRQyxJQUFJLEVBQUUsSUFBTyxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
"",
].join("\n"));
var stderrLines = stderr.split("\n");
assert.strictEqual(stderrLines[0], "WARN: inline source map not found: test/input/issue-1323/sample.js");
done(); done();
}); });
}); });
it("Should fail with acorn and inline source map", function(done) { it("Should fail with acorn and inline source map", function(done) {
var command = uglifyjscmd + " test/input/issue-520/input.js --source-map content=inline,url=inline -p acorn"; var command = uglifyjscmd + " test/input/issue-520/input.js --source-map content=inline,url=inline -p acorn";
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stderr, "ERROR: inline source map only works with built-in parser\n"); assert.strictEqual(stderr, "ERROR: inline source map only works with built-in parser\n");
done(); done();
@@ -219,8 +243,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should fail with SpiderMonkey and inline source map", function(done) { it("Should fail with SpiderMonkey and inline source map", function(done) {
var command = uglifyjscmd + " test/input/issue-520/input.js --source-map content=inline,url=inline -p spidermonkey"; var command = uglifyjscmd + " test/input/issue-520/input.js --source-map content=inline,url=inline -p spidermonkey";
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stderr, "ERROR: inline source map only works with built-in parser\n"); assert.strictEqual(stderr, "ERROR: inline source map only works with built-in parser\n");
done(); done();
@@ -228,8 +251,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should fail with invalid syntax", function(done) { it("Should fail with invalid syntax", function(done) {
var command = uglifyjscmd + ' test/input/invalid/simple.js'; var command = uglifyjscmd + ' test/input/invalid/simple.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
var lines = stderr.split(/\n/); var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/simple.js:1,12"); assert.strictEqual(lines[0], "Parse error at test/input/invalid/simple.js:1,12");
@@ -241,8 +263,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should fail with correct marking of tabs", function(done) { it("Should fail with correct marking of tabs", function(done) {
var command = uglifyjscmd + ' test/input/invalid/tab.js'; var command = uglifyjscmd + ' test/input/invalid/tab.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
var lines = stderr.split(/\n/); var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/tab.js:1,12"); assert.strictEqual(lines[0], "Parse error at test/input/invalid/tab.js:1,12");
@@ -254,8 +275,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should fail with correct marking at start of line", function(done) { it("Should fail with correct marking at start of line", function(done) {
var command = uglifyjscmd + ' test/input/invalid/eof.js'; var command = uglifyjscmd + ' test/input/invalid/eof.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
var lines = stderr.split(/\n/); var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/eof.js:2,0"); assert.strictEqual(lines[0], "Parse error at test/input/invalid/eof.js:2,0");
@@ -267,8 +287,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should fail with a missing loop body", function(done) { it("Should fail with a missing loop body", function(done) {
var command = uglifyjscmd + ' test/input/invalid/loop-no-body.js'; var command = uglifyjscmd + ' test/input/invalid/loop-no-body.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
var lines = stderr.split(/\n/); var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/loop-no-body.js:2,0"); assert.strictEqual(lines[0], "Parse error at test/input/invalid/loop-no-body.js:2,0");
@@ -280,8 +299,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (5--)", function(done) { it("Should throw syntax error (5--)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/assign_1.js'; var command = uglifyjscmd + ' test/input/invalid/assign_1.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -295,8 +313,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (Math.random() /= 2)", function(done) { it("Should throw syntax error (Math.random() /= 2)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/assign_2.js'; var command = uglifyjscmd + ' test/input/invalid/assign_2.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -310,8 +327,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (++this)", function(done) { it("Should throw syntax error (++this)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/assign_3.js'; var command = uglifyjscmd + ' test/input/invalid/assign_3.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -325,8 +341,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (++null)", function(done) { it("Should throw syntax error (++null)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/assign_4.js'; var command = uglifyjscmd + ' test/input/invalid/assign_4.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -340,8 +355,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (a.=)", function(done) { it("Should throw syntax error (a.=)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/dot_1.js'; var command = uglifyjscmd + ' test/input/invalid/dot_1.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -355,8 +369,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (%.a)", function(done) { it("Should throw syntax error (%.a)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/dot_2.js'; var command = uglifyjscmd + ' test/input/invalid/dot_2.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -370,8 +383,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (a./();)", function(done) { it("Should throw syntax error (a./();)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/dot_3.js'; var command = uglifyjscmd + ' test/input/invalid/dot_3.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -385,8 +397,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error ({%: 1})", function(done) { it("Should throw syntax error ({%: 1})", function(done) {
var command = uglifyjscmd + ' test/input/invalid/object.js'; var command = uglifyjscmd + ' test/input/invalid/object.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -400,8 +411,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (delete x)", function(done) { it("Should throw syntax error (delete x)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/delete.js'; var command = uglifyjscmd + ' test/input/invalid/delete.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -415,8 +425,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (function g(arguments))", function(done) { it("Should throw syntax error (function g(arguments))", function(done) {
var command = uglifyjscmd + ' test/input/invalid/function_1.js'; var command = uglifyjscmd + ' test/input/invalid/function_1.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -430,8 +439,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (function eval())", function(done) { it("Should throw syntax error (function eval())", function(done) {
var command = uglifyjscmd + ' test/input/invalid/function_2.js'; var command = uglifyjscmd + ' test/input/invalid/function_2.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -445,8 +453,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (iife arguments())", function(done) { it("Should throw syntax error (iife arguments())", function(done) {
var command = uglifyjscmd + ' test/input/invalid/function_3.js'; var command = uglifyjscmd + ' test/input/invalid/function_3.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -460,8 +467,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (catch(eval))", function(done) { it("Should throw syntax error (catch(eval))", function(done) {
var command = uglifyjscmd + ' test/input/invalid/try.js'; var command = uglifyjscmd + ' test/input/invalid/try.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -475,8 +481,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (var eval)", function(done) { it("Should throw syntax error (var eval)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/var.js'; var command = uglifyjscmd + ' test/input/invalid/var.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -490,8 +495,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (else)", function(done) { it("Should throw syntax error (else)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/else.js'; var command = uglifyjscmd + ' test/input/invalid/else.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -505,8 +509,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (return)", function(done) { it("Should throw syntax error (return)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/return.js'; var command = uglifyjscmd + ' test/input/invalid/return.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -520,8 +523,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (for-in init)", function(done) { it("Should throw syntax error (for-in init)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/for-in_1.js'; var command = uglifyjscmd + ' test/input/invalid/for-in_1.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -535,8 +537,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should throw syntax error (for-in var)", function(done) { it("Should throw syntax error (for-in var)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/for-in_2.js'; var command = uglifyjscmd + ' test/input/invalid/for-in_2.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -555,10 +556,8 @@ describe("bin/uglifyjs", function () {
"--source-map", "--source-map",
'content="' + read_map() + '",url=inline' 'content="' + read_map() + '",url=inline'
].join(" "); ].join(" ");
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, [
'"use strict";var foo=function foo(x){return"foo "+x};console.log(foo("bar"));', '"use strict";var foo=function foo(x){return"foo "+x};console.log(foo("bar"));',
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiYUFBQSxJQUFJQSxJQUFNLFNBQU5BLElBQU1DLEdBQUEsTUFBSyxPQUFTQSxHQUN4QkMsUUFBUUMsSUFBSUgsSUFBSSJ9", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiYUFBQSxJQUFJQSxJQUFNLFNBQU5BLElBQU1DLEdBQUEsTUFBSyxPQUFTQSxHQUN4QkMsUUFBUUMsSUFBSUgsSUFBSSJ9",
@@ -580,10 +579,8 @@ describe("bin/uglifyjs", function () {
"-c", "-c",
"--source-map", "url=inline", "--source-map", "url=inline",
].join(" "); ].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, [
'function foo(){return function(){console.log("PASS")}}foo()();', 'function foo(){return function(){console.log("PASS")}}foo()();',
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIiwiZiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsTUFDTCxPQUFPLFdBQ0hDLFFBQVFDLElBQUksU0FLUkYsS0FDUkcifQ==", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIiwiZiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsTUFDTCxPQUFPLFdBQ0hDLFFBQVFDLElBQUksU0FLUkYsS0FDUkcifQ==",
@@ -594,9 +591,8 @@ describe("bin/uglifyjs", function () {
}); });
it("Should dump AST as JSON", function(done) { it("Should dump AST as JSON", function(done) {
var command = uglifyjscmd + " test/input/global_defs/simple.js -mco ast"; var command = uglifyjscmd + " test/input/global_defs/simple.js -mco ast";
exec(command, function (err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
var ast = JSON.parse(stdout); var ast = JSON.parse(stdout);
assert.strictEqual(ast._class, "AST_Toplevel"); assert.strictEqual(ast._class, "AST_Toplevel");
assert.ok(Array.isArray(ast.body)); assert.ok(Array.isArray(ast.body));
@@ -605,7 +601,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should print supported options on invalid option syntax", function(done) { it("Should print supported options on invalid option syntax", function(done) {
var command = uglifyjscmd + " test/input/comments/filter.js -b ascii-only"; var command = uglifyjscmd + " test/input/comments/filter.js -b ascii-only";
exec(command, function (err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `ascii-only` is not a supported option/.test(stderr), stderr); assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `ascii-only` is not a supported option/.test(stderr), stderr);
@@ -614,27 +610,23 @@ describe("bin/uglifyjs", function () {
}); });
it("Should work with --mangle reserved=[]", function(done) { it("Should work with --mangle reserved=[]", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=[callback]"; var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=[callback]";
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'function test(callback){"aaaaaaaaaaaaaaaa";callback(err,data);callback(err,data)}\n'); assert.strictEqual(stdout, 'function test(callback){"aaaaaaaaaaaaaaaa";callback(err,data);callback(err,data)}\n');
done(); done();
}); });
}); });
it("Should work with --mangle reserved=false", function(done) { it("Should work with --mangle reserved=false", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=false"; var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=false";
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'function test(a){"aaaaaaaaaaaaaaaa";a(err,data);a(err,data)}\n'); assert.strictEqual(stdout, 'function test(a){"aaaaaaaaaaaaaaaa";a(err,data);a(err,data)}\n');
done(); done();
}); });
}); });
it("Should fail with --mangle-props reserved=[in]", function(done) { it("Should fail with --mangle-props reserved=[in]", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js --mangle-props reserved=[in]"; var command = uglifyjscmd + " test/input/issue-505/input.js --mangle-props reserved=[in]";
exec(command, function (err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `reserved=\[in]` is not a supported option/.test(stderr), stderr); assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `reserved=\[in]` is not a supported option/.test(stderr), stderr);
@@ -643,7 +635,7 @@ describe("bin/uglifyjs", function () {
}); });
it("Should fail with --define a-b", function(done) { it("Should fail with --define a-b", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b"; var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b";
exec(command, function (err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr, "Error parsing arguments for 'define': a-b\n"); assert.strictEqual(stderr, "Error parsing arguments for 'define': a-b\n");
@@ -682,4 +674,36 @@ describe("bin/uglifyjs", function () {
done(); done();
}); });
}); });
it("Should work with --enclose", function(done) {
var command = uglifyjscmd + " test/input/enclose/input.js --enclose";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, '(function(){function enclose(){console.log("test enclose")}enclose()})();\n');
done();
});
});
it("Should work with --enclose arg", function(done) {
var command = uglifyjscmd + " test/input/enclose/input.js --enclose undefined";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, '(function(undefined){function enclose(){console.log("test enclose")}enclose()})();\n');
done();
});
});
it("Should work with --enclose arg:value", function(done) {
var command = uglifyjscmd + " test/input/enclose/input.js --enclose window,undefined:window";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, '(function(window,undefined){function enclose(){console.log("test enclose")}enclose()})(window);\n');
done();
});
});
it("Should work with --enclose & --wrap", function(done) {
var command = uglifyjscmd + " test/input/enclose/input.js --enclose window,undefined:window --wrap exports";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, '(function(window,undefined){(function(exports){function enclose(){console.log("test enclose")}enclose()})(typeof exports=="undefined"?exports={}:exports)})(window);\n');
done();
});
});
}); });

View File

@@ -1,89 +0,0 @@
var UglifyJS = require("../node");
var assert = require("assert");
describe("comment filters", function() {
it("Should be able to filter comments by passing regexp", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
assert.strictEqual(ast.print_to_string({comments: /^!/}), "/*!test1*/\n//!test3\n//!test6\n//!test8\n");
});
it("Should be able to filter comments with the 'all' option", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
assert.strictEqual(ast.print_to_string({comments: "all"}), "/*!test1*/\n/*test2*/\n//!test3\n//test4\n//test5\n//!test6\n//test7\n//!test8\n");
});
it("Should be able to filter commments with the 'some' option", function() {
var ast = UglifyJS.parse("// foo\n/*@preserve*/\n// bar\n/*@license*/\n//@license with the wrong comment type\n/*@cc_on something*/");
assert.strictEqual(ast.print_to_string({comments: "some"}), "/*@preserve*/\n/*@license*/\n/*@cc_on something*/");
});
it("Should be able to filter comments by passing a function", function() {
var ast = UglifyJS.parse("/*TEST 123*/\n//An other comment\n//8 chars.");
var f = function(node, comment) {
return comment.value.length === 8;
};
assert.strictEqual(ast.print_to_string({comments: f}), "/*TEST 123*/\n//8 chars.\n");
});
it("Should be able to filter comments by passing regex in string format", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
assert.strictEqual(ast.print_to_string({comments: "/^!/"}), "/*!test1*/\n//!test3\n//!test6\n//!test8\n");
});
it("Should be able to get the comment and comment type when using a function", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
var f = function(node, comment) {
return comment.type == "comment1" || comment.type == "comment3";
};
assert.strictEqual(ast.print_to_string({comments: f}), "//!test3\n//test4\n//test5\n//!test6\n");
});
it("Should be able to filter comments by passing a boolean", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
assert.strictEqual(ast.print_to_string({comments: true}), "/*!test1*/\n/*test2*/\n//!test3\n//test4\n//test5\n//!test6\n//test7\n//!test8\n");
assert.strictEqual(ast.print_to_string({comments: false}), "");
});
it("Should never be able to filter comment5 (shebangs)", function() {
var ast = UglifyJS.parse("#!Random comment\n//test1\n/*test2*/");
var f = function(node, comment) {
assert.strictEqual(comment.type === "comment5", false);
return true;
};
assert.strictEqual(ast.print_to_string({comments: f}), "#!Random comment\n//test1\n/*test2*/");
});
it("Should never be able to filter comment5 when using 'some' as filter", function() {
var ast = UglifyJS.parse("#!foo\n//foo\n/*@preserve*/\n/* please hide me */");
assert.strictEqual(ast.print_to_string({comments: "some"}), "#!foo\n/*@preserve*/");
});
it("Should have no problem on multiple calls", function() {
const options = {
comments: /ok/
};
assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}");
assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}");
assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}");
});
it("Should handle shebang and preamble correctly", function() {
var code = UglifyJS.minify("#!/usr/bin/node\nvar x = 10;", {
output: { preamble: "/* Build */" }
}).code;
assert.strictEqual(code, "#!/usr/bin/node\n/* Build */\nvar x=10;");
});
it("Should handle preamble without shebang correctly", function() {
var code = UglifyJS.minify("var x = 10;", {
output: { preamble: "/* Build */" }
}).code;
assert.strictEqual(code, "/* Build */\nvar x=10;");
});
});

View File

@@ -1,242 +0,0 @@
var assert = require("assert");
var uglify = require("../node");
describe("Comment", function() {
it("Should recognize eol of single line comments", function() {
var tests = [
"//Some comment 1\n>",
"//Some comment 2\r>",
"//Some comment 3\r\n>",
"//Some comment 4\u2028>",
"//Some comment 5\u2029>"
];
var fail = function(e) {
return e instanceof uglify.JS_Parse_Error &&
e.message === "Unexpected token: operator (>)" &&
e.line === 2 &&
e.col === 0;
}
for (var i = 0; i < tests.length; i++) {
assert.throws(function() {
uglify.parse(tests[i]);
}, fail, tests[i]);
}
});
it("Should update the position of a multiline comment correctly", function() {
var tests = [
"/*Some comment 1\n\n\n*/\n>\n\n\n\n\n\n",
"/*Some comment 2\r\n\r\n\r\n*/\r\n>\n\n\n\n\n\n",
"/*Some comment 3\r\r\r*/\r>\n\n\n\n\n\n",
"/*Some comment 4\u2028\u2028\u2028*/\u2028>\n\n\n\n\n\n",
"/*Some comment 5\u2029\u2029\u2029*/\u2029>\n\n\n\n\n\n"
];
var fail = function(e) {
return e instanceof uglify.JS_Parse_Error &&
e.message === "Unexpected token: operator (>)" &&
e.line === 5 &&
e.col === 0;
}
for (var i = 0; i < tests.length; i++) {
assert.throws(function() {
uglify.parse(tests[i]);
}, fail, tests[i]);
}
});
it("Should handle comment within return correctly", function() {
var result = uglify.minify([
"function unequal(x, y) {",
" return (",
" // Either one",
" x < y",
" ||",
" y < x",
" );",
"}",
].join("\n"), {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"function unequal(x, y) {",
" // Either one",
" return x < y || y < x;",
"}",
].join("\n"));
});
it("Should handle comment folded into return correctly", function() {
var result = uglify.minify([
"function f() {",
" /* boo */ x();",
" return y();",
"}",
].join("\n"), {
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"function f() {",
" /* boo */",
" return x(), y();",
"}",
].join("\n"));
});
it("Should not drop comments after first OutputStream", function() {
var code = "/* boo */\nx();";
var ast = uglify.parse(code);
var out1 = uglify.OutputStream({
beautify: true,
comments: "all",
});
ast.print(out1);
var out2 = uglify.OutputStream({
beautify: true,
comments: "all",
});
ast.print(out2);
assert.strictEqual(out1.get(), code);
assert.strictEqual(out2.get(), out1.get());
});
it("Should retain trailing comments", function() {
var code = [
"if (foo /* lost comment */ && bar /* lost comment */) {",
" // this one is kept",
" {/* lost comment */}",
" !function() {",
" // lost comment",
" }();",
" function baz() {/* lost comment */}",
" // lost comment",
"}",
"// comments right before EOF are lost as well",
].join("\n");
var result = uglify.minify(code, {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
it("Should correctly preserve new lines around comments", function() {
var tests = [
[
"// foo",
"// bar",
"x();",
].join("\n"),
[
"// foo",
"/* bar */",
"x();",
].join("\n"),
[
"// foo",
"/* bar */ x();",
].join("\n"),
[
"/* foo */",
"// bar",
"x();",
].join("\n"),
[
"/* foo */ // bar",
"x();",
].join("\n"),
[
"/* foo */",
"/* bar */",
"x();",
].join("\n"),
[
"/* foo */",
"/* bar */ x();",
].join("\n"),
[
"/* foo */ /* bar */",
"x();",
].join("\n"),
"/* foo */ /* bar */ x();",
].forEach(function(code) {
var result = uglify.minify(code, {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
});
it("Should preserve new line before comment without beautify", function() {
var code = [
"function f(){",
"/* foo */bar()}",
].join("\n");
var result = uglify.minify(code, {
compress: false,
mangle: false,
output: {
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
it("Should preserve comments around IIFE", function() {
var result = uglify.minify("/*a*/(/*b*/function(){/*c*/}/*d*/)/*e*/();", {
compress: false,
mangle: false,
output: {
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, "/*a*/ /*b*/(function(){/*c*/}/*d*/ /*e*/)();");
});
it("Should output line comments after statements", function() {
var result = uglify.minify([
"x()//foo",
"{y()//bar",
"}",
].join("\n"), {
compress: false,
mangle: false,
output: {
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"x();//foo",
"{y();//bar",
"}",
].join("\n"));
});
});

View File

@@ -1,22 +0,0 @@
var Uglify = require('../../');
var assert = require("assert");
describe("comment before constant", function() {
var js = 'function f() { /*c1*/ var /*c2*/ foo = /*c3*/ false; return foo; }';
it("Should test comment before constant is retained and output after mangle.", function() {
var result = Uglify.minify(js, {
compress: { collapse_vars: false, reduce_vars: false },
output: { comments: true },
});
assert.strictEqual(result.code, 'function f(){/*c1*/var/*c2*/n=/*c3*/!1;return n}');
});
it("Should test code works when comments disabled.", function() {
var result = Uglify.minify(js, {
compress: { collapse_vars: false, reduce_vars: false },
output: { comments: false },
});
assert.strictEqual(result.code, 'function f(){var n=!1;return n}');
});
});

Some files were not shown because too many files have changed in this diff Show More