Compare commits

..

305 Commits

Author SHA1 Message Date
Alex Lam S.L
fd788590f6 v3.5.0 2019-03-20 18:43:54 +08:00
Alex Lam S.L
143f9054da fix corner case in sequences (#3350) 2019-03-20 14:54:26 +08:00
Alex Lam S.L
f2286c33f1 enhance unsafe for Array (#3349) 2019-03-20 06:37:51 +08:00
Alex Lam S.L
b9615f7a62 improve compress performance (#3348)
fixes #3174
2019-03-20 02:53:04 +08:00
Alex Lam S.L
c520e99eda enhance comparisons (#3347) 2019-03-19 01:34:25 +08:00
Alex Lam S.L
615ae37ca3 introduce assignments (#3345) 2019-03-18 21:28:41 +08:00
Alex Lam S.L
7aa7f21872 fix corner case in evaluate (#3344) 2019-03-18 21:24:42 +08:00
Alex Lam S.L
4430a436eb fix corner case in inline (#3343) 2019-03-17 05:31:40 +08:00
Alex Lam S.L
9707ccdc9f v3.4.10 2019-03-16 00:16:21 +08:00
Alex Lam S.L
cb8f3a2a31 add Node.js 10 to CI tests (#3342) 2019-03-15 16:45:12 +08:00
Alex Lam S.L
8b3259e0c2 fix corner case in reduce_vars (#3341) 2019-03-15 16:06:47 +08:00
Alex Lam S.L
b66f47b8dd update dependencies
- acorn@6.1.1
- commander@2.19.0
- semver@5.6.0
2019-03-15 14:49:48 +08:00
Alex Lam S.L
8d2e6f333e fix function inlining after reduce_vars (#3340)
fixes #3297
2019-03-15 05:45:46 +08:00
Alex Lam S.L
b3ef5e514d enhance evaluate (#3339)
fixes #3299
2019-03-15 02:48:23 +08:00
Alex Lam S.L
627f5fb41e fix corner case with nameCache (#3338)
fixes #3301
2019-03-15 01:15:50 +08:00
Alex Lam S.L
d90777b724 parse mangle.properties.regex in --config-file properly (#3337)
fixes #3315
2019-03-15 00:20:20 +08:00
Alex Lam S.L
e49297e5eb improve usability of pure_funcs (#3336)
fixes #3325
2019-03-14 21:36:45 +08:00
Alex Lam S.L
ebd82b3fb6 fix corner case in collapse_vars (#3334)
fixes #3274
2019-03-14 16:05:56 +08:00
Alex Lam S.L
d074aa6e27 fix corner case in collapse_vars (#3333)
fixes #3247
fixes #3305
fixes #3314
fixes #3327
2019-03-13 23:48:52 +08:00
Alex Lam S.L
b052f62710 fix corner case in reduce_vars (#3332)
fixes #3267
2019-03-13 21:56:38 +08:00
Alex Lam S.L
d4ac84b255 fix corner case in arguments & reduce_vars (#3331)
fixes #3282
2019-03-13 08:46:03 +08:00
Alex Lam S.L
e250396d7e fix corner case in arguments (#3330)
Track modifications to `arguments[i]` under Strict Mode.

fixes #3273
2019-03-13 06:59:53 +08:00
Seul-gi Choi(Chase)
c6fa39b482 Update README.md (#3311)
fix anchor for mangle-options
2019-03-13 05:31:04 +08:00
silverwind
9aae4f2424 make tests compatible with Node.js 12 (#3304)
In Node.js 12, the formatting of console arguments will change slightly.
Previously, a string other than the first argument was formatted using
single quotes if the first argument was non-string. Now, quotes are
never added regardless of position of a string argument.

To make test compatible in all Node.js versions, I work around by
ensuring the first argument to console.log is a string which prevents
the quotes from being added on older versions of Node.js.

Ref: https://github.com/nodejs/node/pull/23162
2019-03-13 04:55:04 +08:00
Alex Lam S.L
008c236137 fix corner case in conditionals (#3329)
fixes #3245
fixes #3257
fixes #3260
fixes #3269
fixes #3271
fixes #3278
fixes #3309
fixes #3319
fixes #3321
2019-03-13 04:28:21 +08:00
Ed S
b1c0664066 Fix typo in warning (#3324)
protoype -> prototype
2019-03-13 02:15:54 +08:00
Alex Lam S.L
ea999b0e92 v3.4.9 2018-08-31 04:28:21 +00:00
Alex Lam S.L
ce7e220de4 fix corner case in conditionals (#3244) 2018-08-30 15:59:05 +08:00
Alex Lam S.L
2bdaca10ae enhance conditionals (#3243) 2018-08-30 01:06:34 +08:00
Alex Lam S.L
aa0029204e fix corner case in reduce_vars (#3241)
fixes #3240
2018-08-29 22:14:25 +08:00
Alex Lam S.L
f352bcec3a fix corner case in collapse_vars (#3239)
fixes #3238
2018-08-29 11:34:34 +08:00
Alex Lam S.L
08514030f4 v3.4.8 2018-08-23 15:27:34 +08:00
Alex Lam S.L
694ca5d045 fix corner case in unused (#3234)
fixes #3233
2018-08-23 06:03:39 +08:00
Alex Lam S.L
57fb58b263 enhance if_return (#3232) 2018-08-21 18:34:16 +08:00
alexlamsl
18c1c9b38a update dependencies
- commander@2.17.1
2018-08-14 17:06:09 +08:00
Alex Lam S.L
5c1ae3662d v3.4.7 2018-08-09 14:47:24 +00:00
Alex Lam S.L
cfebeb2f63 fix corner case in mangle workaround for Safari (#3230)
fixes #3227
2018-08-09 17:34:28 +08:00
Alex Lam S.L
fc78423f1d clean up webkit quirks (#3229) 2018-08-08 16:15:45 +08:00
Alex Lam S.L
2a5277b391 v3.4.6 2018-07-27 11:35:26 +00:00
Alex Lam S.L
d47547dc71 fix corner case in join_vars (#3224) 2018-07-27 19:34:44 +08:00
Alex Lam S.L
304db15a20 fix corner case in ie8 & rename (#3223) 2018-07-26 16:35:43 +08:00
Alex Lam S.L
7cf72b8d66 fix corner case in global_defs (#3218)
fixes #3217
2018-07-19 18:14:36 +08:00
Alex Lam S.L
cea685f8d9 fix corner case in ie8 (#3216)
fixes #3215
2018-07-19 14:45:36 +08:00
Alex Lam S.L
8d4b5344f4 v3.4.5 2018-07-16 18:43:30 +00:00
alexlamsl
34a0ab6f2c improve fuzzing on Travis CI 2018-07-13 02:05:52 +08:00
Alex Lam S.L
bcebacbb9e fix corner cases in preserve_line (#3212) 2018-07-13 01:51:10 +08:00
Alex Lam S.L
018a5a750a v3.4.4 2018-07-09 01:09:56 +00:00
alexlamsl
b468103f26 use nvs for CI testing 2018-07-05 18:49:29 +08:00
Alex Lam S.L
66c126ffde fix corner case in ie8 (#3207)
fixes #3206
2018-07-03 16:44:23 +08:00
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
Alex Lam S.L
0cfbd79aa1 v3.3.10 2018-02-08 10:16:16 +00:00
Alex Lam S.L
d66d86f20b account for exceptions in AST_Assign.left (#2892)
fixes #2891
2018-02-08 03:31:51 +08:00
Alex Lam S.L
905325d3e2 update dependencies (#2889)
acorn 5.4.1
commander 2.14.1
semver 5.5.0
2018-02-07 18:13:18 +08:00
Alex Lam S.L
dea0cc0662 mention file encoding (#2887) 2018-02-06 16:48:49 +08:00
Alex Lam S.L
d69d8007d6 evaluate to{Low,Upp}erCase() under unsafe (#2886) 2018-02-06 15:57:15 +08:00
Dan
c0b8f2a16d add information on testing and code style (#2885)
fixes #2884
2018-02-06 14:19:28 +08:00
Dan
cb0257dbbf describe a few compiler assumptions (#2883) 2018-02-06 14:19:03 +08:00
Dan
9637f51b68 change undefined == x to null == x (#2882)
fixes #2871
2018-02-05 15:00:23 +08:00
Alex Lam S.L
3026bd8975 improve exceptional flow compression by collapse_vars (#2880) 2018-02-04 04:18:22 +08:00
Alex Lam S.L
78a44d5ab0 maintain order between side-effects and externally observable assignments (#2879)
fixes #2878
2018-02-04 03:58:49 +08:00
Alex Lam S.L
7e13c0db40 handle break & continue in collapse_vars (#2875)
fixes #2873
2018-02-03 07:58:43 +08:00
Alex Lam S.L
e6a2e9e4d0 allow collapse_vars across conditional branches (#2867) 2018-02-03 02:44:40 +08:00
Alex Lam S.L
e773f03927 fix assignment logic in reduce_vars (#2872)
fixes #2869
2018-02-03 01:33:09 +08:00
Alex Lam S.L
b16380d669 fix missing corner case in #2855 (#2868) 2018-02-02 18:08:56 +08:00
Ryan Gunn
334b07a3db Update License Copyright Year to 2018 (#2866) 2018-02-02 16:30:01 +08:00
Alex Lam S.L
3cc1527f00 always test for rename (#2865) 2018-02-01 21:42:55 +08:00
Alex Lam S.L
525a61fb55 better fix for #2858 (#2864) 2018-02-01 20:06:36 +08:00
Alex Lam S.L
c3a002ff97 account for side-effects in comparisons of null & undefined (#2863) 2018-02-01 19:15:17 +08:00
Alex Lam S.L
fad6766a90 simplify comparisons with undefined & null (#2862)
fixes #2857
2018-02-01 16:50:54 +08:00
Alex Lam S.L
aa664dea0a avoid evaluate of compound assignment after dead_code transform (#2861)
fixes #2860
2018-02-01 16:18:29 +08:00
Alex Lam S.L
102f994b9d account for declaration assignment in collapse_vars (#2859)
fixes #2858
2018-02-01 15:09:53 +08:00
Alex Lam S.L
2a4c68be4f relax collapse_vars on AST_Exit (#2855)
First introduced in #1862 to stop assignments to migrate beyond `return` or `throw`. Since then `collapse_vars` has been improved to handle various side-effect-related corner cases.
2018-01-31 23:49:59 +08:00
Alex Lam S.L
541e6011af improve symbol replacement heuristic (#2851) 2018-01-29 17:41:15 +08:00
Alex Lam S.L
6fa3fbeae8 compress chained compound assignments (#2850) 2018-01-29 15:13:25 +08:00
Alex Lam S.L
4eb4cb656c v3.3.9 2018-01-27 12:56:34 +00:00
Alex Lam S.L
193612ac67 fix accounting after conversion to assignment (#2847)
Missing reference to `AST_SymbolRef` created by `unused` causes `collapse_vars` to misbehave.

fixes #2846
2018-01-26 14:21:11 +08:00
Alex Lam S.L
95cfce68ea backport of #2835 (#2841) 2018-01-23 05:45:45 +08:00
Alex Lam S.L
ec4202590d drop assignments to constant expressions only (#2839)
fixes #2838
2018-01-23 02:49:54 +08:00
Alex Lam S.L
5e2cd07d6f handle duplicate function declarations correctly (#2837)
fixes #2836
2018-01-23 01:28:09 +08:00
Alex Lam S.L
06166df999 v3.3.8 2018-01-21 07:08:01 +00:00
Alex Lam S.L
e2dc9cf091 fix unsafe evaluate of AST_Array (#2825)
fixes #2822
2018-01-21 01:39:44 +08:00
Alex Lam S.L
069df27bf1 enable unsafe for test/ufuzz.js (#2819)
- introduce `unsafe_undefined`
- safer `.toString()` compression

Miscellaneous
- rename `unsafe_Function`
2018-01-19 23:47:42 +08:00
Alex Lam S.L
3e7873217c improve unused on built-in functions (#2817) 2018-01-19 20:41:57 +08:00
Alex Lam S.L
e21bab7ce6 avoid duplicate property names in object literals under "use strict" (#2818)
fixes #2816
2018-01-19 20:13:50 +08:00
Alex Lam S.L
ac9a168fba fix & improve test/ufuzz.js (#2815)
- use correct `options` when testing `rename`
- mask arbitrarily assigned function IDs to reduce rate of false positives
2018-01-19 16:51:59 +08:00
Alex Lam S.L
81b64549ce fix time-out for respawned test/ufuzz.js (#2814) 2018-01-19 06:11:19 +08:00
Alex Lam S.L
082e004b87 compress undefined property names (#2811)
- enforce property names as string
- handle `void 0` as `undefined` in `hoist_props` & `reduce_vars`
2018-01-19 00:36:30 +08:00
kzc
983e69128b fix join_vars property assignment for negative array index (#2810)
fixes #2790
2018-01-18 21:52:54 +08:00
Alex Lam S.L
b335912e86 enhance test/ufuzz.js (#2808)
- standalone test for `rename`
- handle `keep_fargs` & `rename` upon failure
2018-01-18 14:08:05 +08:00
Alex Lam S.L
cc07f3b806 faster output of comments (#2806) 2018-01-18 02:57:33 +08:00
Alex Lam S.L
07e4b64f3a fix AST_Scope.clone() (#2803)
fixes #2799
2018-01-17 21:33:13 +08:00
Alex Lam S.L
d3ce2bc9e7 suppress unsafe_proto for LHS expressions (#2804) 2018-01-17 20:41:51 +08:00
Alex Lam S.L
cff3bf4914 configure rename with CLI (#2802) 2018-01-17 15:12:22 +08:00
Alex Lam S.L
79cfac77bd extend join_vars & sequences (#2798) 2018-01-17 13:58:27 +08:00
Alex Lam S.L
224c14d49d improve mocha tests (#2797)
- workaround sporadic delays from Travis CI
2018-01-16 17:51:25 +08:00
Alex Lam S.L
7857354d85 improve test/travis-ufuzz.js (#2795)
- print usage
- support concurrent jobs
- improve instance utilisation
- resume after V8 self-destruct
2018-01-16 17:33:21 +08:00
Alex Lam S.L
b4aef753e7 general improvements around AST_ForIn (#2796)
- compress using `collapse_vars`
- remove unused `name`
- simplify `loop_body`
2018-01-16 17:03:12 +08:00
Joël Galeran
424173d311 fix typo in README (#2792) 2018-01-16 10:29:38 +08:00
Alex Lam S.L
ec7cd1dcf7 handle VM failure gracefully (#2791) 2018-01-15 23:41:39 +08:00
Alex Lam S.L
7def684730 improve test/travis-ufuzz.js (#2789)
- wait for instance to boot
- run on forked repositories
- workaround `request_limit_reached`
2018-01-15 19:18:21 +08:00
Alex Lam S.L
10f961c27b enhance collapse_vars (#2788) 2018-01-15 18:47:23 +08:00
Alex Lam S.L
b483678ca7 avoid suboptimal termination in passes (#2787) 2018-01-15 16:42:31 +08:00
Alex Lam S.L
cbbe6fad60 avoid double counting within single-use functions (#2785)
fixes #2783
2018-01-15 16:42:15 +08:00
Alex Lam S.L
f96929c031 improve test/travis-ufuzz.js (#2786)
- use more RAM
- show progress in console
- report failure as job status
2018-01-15 15:08:35 +08:00
Alex Lam S.L
2b6657e967 run test/ufuzz.js when Travis CI is idle (#2784) 2018-01-15 08:52:11 +08:00
Alex Lam S.L
7c0c92943f v3.3.7 2018-01-14 09:13:26 +00:00
Alex Lam S.L
62a66dfff4 fix & extend join_vars for object assigments (#2781) 2018-01-14 17:11:31 +08:00
kzc
2cab348341 improve SymbolDef info in --output ast (#2778)
* SymbolDef info (a.k.a. `thedef`) is now represented as a string containing `"ID name [mangled_name]"`. 
* Enhance display of `globals`, `variables`, `functions` and `enclosed`.
* `SymbolDef.next_id` starts at `1` and the `id` is adjusted for `-o ast` display.
2018-01-14 01:40:51 +08:00
Alex Lam S.L
460218a3f8 v3.3.6 2018-01-13 05:37:42 +00:00
Alex Lam S.L
e49416e4aa fix reduce_vars on AST_Accessor (#2776)
fixes #2774
2018-01-13 02:46:14 +08:00
kzc
d4d7d99b70 add SymbolDef IDs to --output ast (#2772) 2018-01-12 15:41:09 +08:00
Alex Lam S.L
6a696d0a7b fix output of imported AST (#2771) 2018-01-12 01:05:49 +08:00
Alex Lam S.L
1c9e13f47d update dependencies (#2770)
- acorn@5.3.0
- commander@2.13.0
2018-01-12 00:32:17 +08:00
Alex Lam S.L
b757450cd8 fix nested unused assignments (#2769)
fixes #2768
2018-01-11 23:13:44 +08:00
Alex Lam S.L
23ec484806 fix corner case in #2763 (#2766) 2018-01-11 21:18:08 +08:00
Alex Lam S.L
f1e1bb419a join object assignments (#2763) 2018-01-11 17:08:21 +08:00
Alex Lam S.L
6a0af85c8b skip only vars in if_return (#2759)
fixes #2747
2018-01-10 19:08:46 +08:00
Alex Lam S.L
09269be974 enhance conditionals (#2758)
`x ? y || z : z` --> `x && y || z`
2018-01-10 16:59:57 +08:00
Alex Lam S.L
bf832cde16 improve synergy between compress and rename (#2755) 2018-01-09 17:55:41 +08:00
Alex Lam S.L
2972d58dbb patch variable declaractions extracted within catch (#2753)
fixes #2749
2018-01-09 13:54:35 +08:00
Alex Lam S.L
2e22d38a02 improve rename reproducibility (#2754)
fixes #2752
2018-01-09 13:53:05 +08:00
Alex Lam S.L
ce27bcd69a compress loops with immediate break (#2746)
fixes #2740
2018-01-08 14:30:18 +08:00
Alex Lam S.L
9336cc8247 v3.3.5 2018-01-07 11:51:36 +00:00
Alex Lam S.L
9809567dfc improve process.exit() workaround (#2741)
- use public API
- fix issue with Node.js 0.10 on WIndows
2018-01-07 17:53:50 +08:00
Alex Lam S.L
1ee8be8d91 fix recursive function inline (#2738)
fixes #2737
2018-01-07 15:31:24 +08:00
Alex Lam S.L
8430c2f9f8 enable AppVeyor CI (#2739) 2018-01-07 14:14:58 +08:00
Alex Lam S.L
659c8a7632 handle trailing line comments correctly (#2736)
fixes #2734
2018-01-06 21:05:21 +08:00
Alex Lam S.L
3564b4f20d compress RegExp() in unsafe (#2735) 2018-01-06 21:04:47 +08:00
Alex Lam S.L
3505a3604a enhance unsafe_proto (#2733) 2018-01-06 06:16:51 +08:00
kzc
9b1bc6c014 ufuzz: add strings "a", "b", "c" to VALUES (#2732) 2018-01-06 05:54:53 +08:00
Alex Lam S.L
9f23185f2b fix corner case with arguments as function name (#2729)
fixes #2728
2018-01-05 22:21:18 +08:00
Alex Lam S.L
b82feb9302 improve if_return (#2727) 2018-01-05 20:24:30 +08:00
Alex Lam S.L
7f2a591c7e warn on deprecated features (#2726)
- `function.arguments`
- `function.callers`

fixes #2719
2018-01-05 19:36:02 +08:00
Alex Lam S.L
afbcebddf6 fix mangle name collision across files (#2722) 2018-01-05 05:08:09 +08:00
Alex Lam S.L
484e484571 fix corner case in inline (#2720) 2018-01-04 23:38:37 +08:00
Alex Lam S.L
6f3f21233f reminify tests upon expect_stdout (#2716) 2018-01-04 20:13:05 +08:00
Alex Lam S.L
a6873a3859 forbid block-scoped AST_Defun in strict mode (#2718) 2018-01-04 18:45:51 +08:00
Alex Lam S.L
7a6d452b54 preserve constant modification under strict mode (#2717) 2018-01-04 15:53:53 +08:00
Alex Lam S.L
9b58b54e2d extend inline (#2714)
- compress `function` with variables within loops
- restrict to `AST_Var` for better compatibility with ES6+
2018-01-04 12:58:40 +08:00
Alex Lam S.L
c598a12af9 apply collapse_vars to loop conditions (#2712) 2018-01-04 03:18:28 +08:00
Alex Lam S.L
cfe3a98ce5 drop unused assignment based on reduce_vars (#2709) 2018-01-04 01:03:33 +08:00
Alex Lam S.L
14778e049b fix reduce_vars on AST_Defun (#2708) 2018-01-03 17:18:38 +08:00
Alex Lam S.L
446fb0198b extend __PURE__ to AST_New (#2706)
fixes #2705
2018-01-03 04:48:07 +08:00
Alex Lam S.L
7d3cddf9d6 inline functions with AST_Var (#2688) 2018-01-03 01:54:44 +08:00
Alex Lam S.L
6dead95eb3 enhance collapse_vars (#2704) 2018-01-02 18:42:15 +08:00
Alex Lam S.L
cc931b3ad8 enhance if_return (#2703) 2018-01-02 15:09:51 +08:00
Alex Lam S.L
d838b4b52e reset argument value within loop after inline (#2699) 2018-01-02 01:24:53 +08:00
Alex Lam S.L
2f3bddbaca scan within IIFEs of assigned values (#2702)
fixes #2701
2018-01-02 01:24:23 +08:00
Alex Lam S.L
673b071637 enhance join_vars & sequences (#2697)
- nudge declarations without assignments
  - within `AST_BlockStatement`
  - across `AST_If`
2018-01-01 00:09:26 +08:00
Alex Lam S.L
da82fa59a7 fix inline on duplicate argument names (#2698) 2017-12-31 20:59:58 +08:00
Alex Lam S.L
333792352e reduce hoisting declarations (#2687) 2017-12-31 16:15:00 +08:00
Alex Lam S.L
e2ec270b04 v3.3.4 2017-12-31 00:01:14 +08:00
Alex Lam S.L
ed7a0a454e fix dead_code on escaped return assignment (#2693)
fixes #2692
2017-12-30 15:20:25 +08:00
Alex Lam S.L
d819559a01 minor clean-ups (#2686) 2017-12-29 14:04:52 +08:00
Alex Lam S.L
8ca49155a8 v3.3.3 2017-12-29 03:07:39 +08:00
Alex Lam S.L
b95e3338d9 fix pure_getters on AST_Binary (#2681)
fixes #2678
2017-12-28 17:01:01 +08:00
Alex Lam S.L
e40a0ee9c6 improve assignment variations (#2671) 2017-12-28 15:36:55 +08:00
Alex Lam S.L
cb62bd98d3 fix function inlining within loops (#2675)
fixes #2663
2017-12-28 02:53:14 +08:00
Alex Lam S.L
f30790b11b fix dead_code on return assignments (#2668)
fixes #2666
2017-12-27 07:40:34 +08:00
Alex Lam S.L
5205dbcbf4 retain recursive function names (#2667)
fixes #2665
2017-12-27 07:00:12 +08:00
Alex Lam S.L
3ff625de7e fix bugs on substituted AST_Defun (#2661)
fixes #2660
2017-12-27 05:31:37 +08:00
Alex Lam S.L
4832bc5d88 replace single-use recursive functions (#2659)
fixes #2628
2017-12-26 21:25:35 +08:00
Alex Lam S.L
7f342cb3e3 suppress inline within substituted AST_Scope (#2658)
fixes #2657
2017-12-26 18:56:59 +08:00
Alex Lam S.L
05e7d34ed4 improve unused over duplicate variable names (#2656) 2017-12-26 18:29:28 +08:00
Alex Lam S.L
86607156e3 v3.3.2 2017-12-26 01:38:56 +08:00
Alex Lam S.L
0fe259e9c5 parse LF & comment correctly (#2653)
fixes #2652
2017-12-26 01:38:01 +08:00
151 changed files with 19348 additions and 5962 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

@@ -1,14 +1,35 @@
language: node_js addons:
node_js: apt:
- "0.10" sources:
- "0.12" - ubuntu-toolchain-r-test
- "4" packages:
- "6" - libstdc++-4.9-dev
- "8" cache:
env: directories: tmp
- UGLIFYJS_TEST_ALL=1 language: generic
matrix: matrix:
fast_finish: true fast_finish: true
sudo: false sudo: false
cache: env:
directories: tmp global:
- UGLIFYJS_TEST_ALL=1
matrix:
- NODEJS_VER=node/0.10
- NODEJS_VER=node/0.12
- NODEJS_VER=node/4
- NODEJS_VER=node/6
- NODEJS_VER=node/8
- NODEJS_VER=node/10
- NODEJS_VER=node/latest
before_install:
- git clone --branch v1.4.2 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
- . ~/.nvs/nvs.sh
- nvs --version
install:
- nvs add $NODEJS_VER
- nvs use $NODEJS_VER
- node --version
- npm --version --no-update-notifier
- npm install --no-optional --no-save --no-update-notifier
script:
- npm test --no-update-notifier

61
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,61 @@
Contributing
============
## Documentation
Every new feature and API change should be accompanied by a README additon.
## Testing
All features and bugs should have tests that verify the fix. You can run all
tests using `npm test`.
The most common type of test are tests that verify input and output of the
Uglify transforms. These tests exist in `test/compress`. New tests can be added
either to an existing file or in a new file `issue-xxx.js`.
Tests that cannot be expressed as a simple AST can be found in `test/mocha`.
## Code style
- File encoding must be `UTF-8`.
- `LF` is always used as a line ending.
- Statements end with semicolons.
- Indentation uses 4 spaces, switch `case` 2 spaces.
- Identifiers use `snake_case`.
- Strings use double quotes (`"`).
- Use a trailing comma for multiline array and object literals to minimize diffs.
- The Uglify code only uses ES5, even in the `harmony` branch.
- Line length should be at most 80 cols, except when it is easier to read a
longer line.
- If both sides of a comparison are of the same type, `==` and `!=` are used.
- Multiline conditions place `&&` and `||` first on the line.
**Example feature**
```js
OPT(AST_Debugger, function(self, compressor) {
if (compressor.option("drop_debugger"))
return make_node(AST_EmptyStatement, self);
return self;
});
```
**Example test case**
```js
drop_debugger: {
options = {
drop_debugger: true,
}
input: {
debugger;
if (foo) debugger;
}
expect: {
if (foo);
}
}
```

View File

@@ -1,6 +1,6 @@
UglifyJS is released under the BSD license: UglifyJS is released under the BSD license:
Copyright 2012-2013 (c) Mihai Bazon <mihai.bazon@gmail.com> Copyright 2012-2018 (c) Mihai Bazon <mihai.bazon@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions

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
------- -------
@@ -70,7 +69,7 @@ a double dash to prevent input files being used as option arguments:
`debug` Add debug prefix and suffix. `debug` Add debug prefix and suffix.
`domprops` Mangle property names that overlaps `domprops` Mangle property names that overlaps
with DOM properties. with DOM properties.
`keep_quoted` Only mangle unquoted properies. `keep_quoted` Only mangle unquoted properties.
`regex` Only mangle matched property names. `regex` Only mangle matched property names.
`reserved` List of names that should not be mangled. `reserved` List of names that should not be mangled.
-b, --beautify [options] Beautify output/specify output options: -b, --beautify [options] Beautify output/specify output options:
@@ -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,11 @@ 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.
- `assignments` (default: `true`) -- apply optimizations to assignment expressions.
- `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 +614,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
@@ -640,7 +651,13 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `if_return` (default: `true`) -- optimizations for if/return and if/continue - `if_return` (default: `true`) -- optimizations for if/return and if/continue
- `inline` (default: `true`) -- embed simple functions - `inline` (default: `true`) -- inline calls to function with simple/`return` statement:
- `false` -- same as `0`
- `0` -- disabled inlining
- `1` -- inline simple functions
- `2` -- inline functions with arguments
- `3` -- inline functions with arguments and variables
- `true` -- same as `3`
- `join_vars` (default: `true`) -- join consecutive `var` statements - `join_vars` (default: `true`) -- join consecutive `var` statements
@@ -649,7 +666,7 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `keep_fnames` (default: `false`) -- Pass `true` to prevent the - `keep_fnames` (default: `false`) -- Pass `true` to prevent the
compressor from discarding function names. Useful for code relying on compressor from discarding function names. Useful for code relying on
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle). `Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle-options).
- `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from - `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from
being compressed into `1/0`, which may cause performance issues on Chrome. being compressed into `1/0`, which may cause performance issues on Chrome.
@@ -677,7 +694,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
@@ -724,14 +742,10 @@ 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_Func` (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.
- `unsafe_math` (default: `false`) -- optimize numerical expressions like - `unsafe_math` (default: `false`) -- optimize numerical expressions like
@@ -743,6 +757,10 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `unsafe_regexp` (default: `false`) -- enable substitutions of variables with - `unsafe_regexp` (default: `false`) -- enable substitutions of variables with
`RegExp` values the same way as if they are constants. `RegExp` values the same way as if they are constants.
- `unsafe_undefined` (default: `false`) -- substitute `void 0` if there is a
variable named `undefined` in scope (variable name will be mangled, typically
reduced to a single character)
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple - `unused` (default: `true`) -- drop unreferenced functions and variables (simple
direct variable assignments do not count as references unless set to `"keep_assign"`) direct variable assignments do not count as references unless set to `"keep_assign"`)
@@ -816,7 +834,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.
@@ -828,8 +846,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.
@@ -841,8 +859,8 @@ can pass additional arguments that control the code output:
adjust for this text. Can be used to insert a comment containing adjust for this text. Can be used to insert a comment containing
licensing information, for example. licensing information, for example.
- `preserve_line` (default `false`) -- pass `true` to preserve lines, but it - `preserve_line` (default `false`) -- pass `true` to retain line numbering on
only works if `beautify` is set to `false`. a best effort basis.
- `quote_keys` (default `false`) -- pass `true` to quote all keys in literal - `quote_keys` (default `false`) -- pass `true` to quote all keys in literal
objects objects
@@ -916,9 +934,6 @@ when this flag is on:
- `new Object()``{}` - `new Object()``{}`
- `String(exp)` or `exp.toString()``"" + exp` - `String(exp)` or `exp.toString()``"" + exp`
- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new` - `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
- `void 0``undefined` (if there is a variable named "undefined" in
scope; we do it because the variable name will be mangled, typically
reduced to a single character)
### Conditional compilation ### Conditional compilation
@@ -1035,8 +1050,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
@@ -1095,3 +1111,27 @@ To enable fast minify mode with the API use:
```js ```js
UglifyJS.minify(code, { compress: false, mangle: true }); UglifyJS.minify(code, { compress: false, mangle: true });
``` ```
#### Source maps and debugging
Various `compress` transforms that simplify, rearrange, inline and remove code
are known to have an adverse effect on debugging with source maps. This is
expected as code is optimized and mappings are often simply not possible as
some code no longer exists. For highest fidelity in source map debugging
disable the Uglify `compress` option and just use `mangle`.
### Compiler assumptions
To allow for better optimizations, the compiler makes various assumptions:
- `.toString()` and `.valueOf()` don't have side effects, and for built-in
objects they have not been overridden.
- `undefined`, `NaN` and `Infinity` have not been externally redefined.
- `arguments.callee`, `arguments.caller` and `Function.prototype.caller` are not used.
- The code doesn't expect the contents of `Function.prototype.toString()` or
`Error.prototype.stack` to be anything in particular.
- Getting and setting properties on a plain object does not cause other side effects
(using `.watch()` or `Proxy`).
- Object properties can be added, removed and modified (not prevented with
`Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
`Object.preventExtensions()` or `Object.seal()`).

View File

@@ -1,24 +1,26 @@
environment: environment:
UGLIFYJS_TEST_ALL: 1
matrix: matrix:
- nodejs_version: "0.10" - NODEJS_VER: node/0.10
- nodejs_version: "0.12" - NODEJS_VER: node/0.12
- nodejs_version: "4.0" - NODEJS_VER: node/4
- nodejs_version: "6.0" - NODEJS_VER: node/6
- NODEJS_VER: node/8
- NODEJS_VER: node/10
- NODEJS_VER: node/latest
install:
- git clone --branch v1.4.2 --depth 1 https://github.com/jasongin/nvs.git %LOCALAPPDATA%\nvs
- set PATH=%LOCALAPPDATA%\nvs;%PATH%
- nvs --version
- nvs add %NODEJS_VER%
- nvs use %NODEJS_VER%
- node --version
- npm --version --no-update-notifier
- npm install --no-optional --no-save --no-update-notifier
build: off
cache:
- tmp
matrix: matrix:
fast_finish: true fast_finish: true
platform:
- x86
- x64
install:
- ps: Install-Product node $env:nodejs_version $env:platform
- npm install
test_script: test_script:
- node --version - npm test --no-update-notifier
- npm --version
- npm test
build: off

View File

@@ -3,11 +3,7 @@
"use strict"; "use strict";
// workaround for tty output truncation upon process.exit() require("../tools/exit");
[process.stdout, process.stderr].forEach(function(stream){
if (stream._handle && stream._handle.setBlocking)
stream._handle.setBlocking(true);
});
var fs = require("fs"); var fs = require("fs");
var info = require("../package.json"); var info = require("../package.json");
@@ -15,7 +11,7 @@ var path = require("path");
var program = require("commander"); var program = require("commander");
var UglifyJS = require("../tools/node"); var UglifyJS = require("../tools/node");
var skip_keys = [ "cname", "enclosed", "inlined", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ]; var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
var files = {}; var files = {};
var options = { var options = {
compress: false, compress: false,
@@ -44,13 +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("--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.");
@@ -58,21 +56,25 @@ program.option("--wrap <name>", "Embed everything as a function with “exports
program.arguments("[files...]").parseArgv(process.argv); program.arguments("[files...]").parseArgv(process.argv);
if (program.configFile) { if (program.configFile) {
options = JSON.parse(read_file(program.configFile)); options = JSON.parse(read_file(program.configFile));
if (options.mangle && options.mangle.properties && options.mangle.properties.regex) {
options.mangle.properties.regex = UglifyJS.parse(options.mangle.properties.regex, {
expression: true
}).getValue();
}
} }
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") { if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
fatal("ERROR: cannot write source map to STDOUT"); fatal("ERROR: cannot write source map to STDOUT");
} }
[ [
"compress", "compress",
"enclose",
"ie8", "ie8",
"mangle", "mangle",
"rename",
"sourceMap", "sourceMap",
"toplevel", "toplevel",
"wrap" "wrap"
].forEach(function(name) { ].forEach(function(name) {
if (name in program) { if (name in program) {
if (name == "rename" && program[name]) return;
options[name] = program[name]; options[name] = program[name];
} }
}); });
@@ -103,7 +105,7 @@ if (program.mangleProps) {
if (typeof program.mangleProps != "object") program.mangleProps = {}; if (typeof program.mangleProps != "object") program.mangleProps = {};
if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = []; if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
require("../tools/domprops").forEach(function(name) { require("../tools/domprops").forEach(function(name) {
UglifyJS._push_uniq(program.mangleProps.reserved, name); UglifyJS.push_uniq(program.mangleProps.reserved, name);
}); });
} }
if (typeof options.mangle != "object") options.mangle = {}; if (typeof options.mangle != "object") options.mangle = {};
@@ -125,6 +127,11 @@ if (program.parse) {
fatal("ERROR: inline source map only works with built-in parser"); fatal("ERROR: inline source map only works with built-in parser");
} }
} }
if (~program.rawArgs.indexOf("--rename")) {
options.rename = true;
} else if (!program.rename) {
options.rename = false;
}
var convert_path = function(name) { var convert_path = function(name) {
return name; return name;
}; };
@@ -176,6 +183,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) {
@@ -227,7 +239,20 @@ function run() {
} }
fatal(ex); fatal(ex);
} else if (program.output == "ast") { } else if (program.output == "ast") {
if (!options.compress && !options.mangle) {
result.ast.figure_out_scope({});
}
print(JSON.stringify(result.ast, function(key, value) { print(JSON.stringify(result.ast, function(key, value) {
if (value) switch (key) {
case "thedef":
return symdef(value);
case "enclosed":
return value.length ? value.map(symdef) : undefined;
case "variables":
case "functions":
case "globals":
return value.size() ? value.map(symdef) : undefined;
}
if (skip_key(key)) return; if (skip_key(key)) return;
if (value instanceof UglifyJS.AST_Token) return; if (value instanceof UglifyJS.AST_Token) return;
if (value instanceof UglifyJS.Dictionary) return; if (value instanceof UglifyJS.Dictionary) return;
@@ -317,17 +342,9 @@ function parse_js(flag) {
return function(value, options) { return function(value, options) {
options = options || {}; options = options || {};
try { try {
UglifyJS.minify(value, { UglifyJS.parse(value, {
parse: { expression: true
expression: true }).walk(new UglifyJS.TreeWalker(function(node) {
},
compress: false,
mangle: false,
output: {
ast: true,
code: false
}
}).ast.walk(new UglifyJS.TreeWalker(function(node) {
if (node instanceof UglifyJS.AST_Assign) { if (node instanceof UglifyJS.AST_Assign) {
var name = node.left.print_to_string(); var name = node.left.print_to_string();
var value = node.right; var value = node.right;
@@ -364,23 +381,16 @@ 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;
} }
function symdef(def) {
var ret = (1e6 + def.id) + " " + def.name;
if (def.mangled_name) ret += " " + def.mangled_name;
return ret;
}
function format_object(obj) { function format_object(obj) {
var lines = []; var lines = [];
var padding = ""; var padding = "";

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);
@@ -118,10 +118,8 @@ var AST_Node = DEFNODE("Node", "start end", {
} }
}, null); }, null);
AST_Node.warn_function = null;
AST_Node.warn = function(txt, props) { AST_Node.warn = function(txt, props) {
if (AST_Node.warn_function) if (AST_Node.warn_function) AST_Node.warn_function(string_template(txt, props));
AST_Node.warn_function(string_template(txt, props));
}; };
/* -----[ statements ]----- */ /* -----[ statements ]----- */
@@ -148,7 +146,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 +156,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 +194,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);
}); });
@@ -208,8 +205,7 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
var label = node.label; var label = node.label;
var def = this.label; var def = this.label;
node.walk(new TreeWalker(function(node) { node.walk(new TreeWalker(function(node) {
if (node instanceof AST_LoopControl if (node instanceof AST_LoopControl && node.label && node.label.thedef === def) {
&& node.label && node.label.thedef === def) {
node.label.thedef = label; node.label.thedef = label;
label.references.push(node); label.references.push(node);
} }
@@ -233,7 +229,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 +239,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 +254,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);
@@ -267,15 +263,14 @@ var AST_For = DEFNODE("For", "init condition step", {
} }
}, AST_IterationStatement); }, AST_IterationStatement);
var AST_ForIn = DEFNODE("ForIn", "init name object", { var AST_ForIn = DEFNODE("ForIn", "init object", {
$documentation: "A `for ... in` statement", $documentation: "A `for ... in` statement",
$propdoc: { $propdoc: {
init: "[AST_Node] the `for/in` initialization code", init: "[AST_Node] the `for/in` initialization code",
name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
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);
@@ -289,7 +284,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);
}); });
@@ -309,6 +304,16 @@ var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes", enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
cname: "[integer/S] current index for mangling variables (used internally by the mangler)", cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
}, },
clone: function(deep) {
var node = this._clone(deep);
if (this.variables) node.variables = this.variables.clone();
if (this.functions) node.functions = this.functions.clone();
if (this.enclosed) node.enclosed = this.enclosed.slice();
return node;
},
pinned: function() {
return this.uses_eval || this.uses_with;
}
}, AST_Block); }, AST_Block);
var AST_Toplevel = DEFNODE("Toplevel", "globals", { var AST_Toplevel = DEFNODE("Toplevel", "globals", {
@@ -320,12 +325,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);
@@ -337,12 +359,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);
}); });
} }
@@ -372,7 +393,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);
}); });
} }
@@ -392,7 +413,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);
}); });
} }
@@ -415,7 +436,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);
@@ -431,7 +452,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);
}); });
@@ -452,7 +473,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);
}); });
@@ -468,7 +489,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);
@@ -482,7 +503,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);
}); });
@@ -501,11 +522,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);
@@ -521,7 +541,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);
}); });
@@ -537,12 +557,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);
});
}); });
} }
}); });
@@ -557,7 +576,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);
}); });
@@ -576,7 +595,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);
}); });
} }
@@ -585,7 +604,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);
}); });
@@ -599,7 +618,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);
}); });
} }
@@ -621,7 +640,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);
}); });
@@ -636,7 +655,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);
@@ -656,11 +675,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); });
}
}); });
} }
}); });
@@ -671,11 +689,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); });
}
}); });
} }
}); });
@@ -683,11 +700,11 @@ var AST_Object = DEFNODE("Object", "properties", {
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", { var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
$documentation: "Base class for literal object properties", $documentation: "Base class for literal object properties",
$propdoc: { $propdoc: {
key: "[string] the property name converted to a string for ObjectKeyVal. For setters and getters this is an AST_SymbolAccessor.", key: "[string|AST_SymbolAccessor] property name. For ObjectKeyVal this is a string. For getters and setters this is an AST_SymbolAccessor.",
value: "[AST_Node] property value. For setters and getters 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);
}); });
} }
@@ -814,12 +831,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, {
@@ -847,11 +864,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) {
@@ -910,5 +927,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) {
@@ -29,7 +37,6 @@ function set_shorthand(name, options, keys) {
function init_cache(cache) { function init_cache(cache) {
if (!cache) return; if (!cache) return;
if (!("cname" in cache)) cache.cname = -1;
if (!("props" in cache)) { if (!("props" in cache)) {
cache.props = new Dictionary(); cache.props = new Dictionary();
} else if (!(cache.props instanceof Dictionary)) { } else if (!(cache.props instanceof Dictionary)) {
@@ -39,7 +46,6 @@ function init_cache(cache) {
function to_json(cache) { function to_json(cache) {
return { return {
cname: cache.cname,
props: cache.props.toObject() props: cache.props.toObject()
}; };
} }
@@ -49,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: {},
@@ -115,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 {
@@ -124,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;
@@ -141,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);
@@ -152,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);
} }
@@ -167,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) {
@@ -181,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,74 +752,85 @@ 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 token_to_string(type, value) {
return type + (value === undefined ? "" : " «" + value + "»");
}
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_to_string(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: " + token_to_string(S.token.type, S.token.value) + ", expected: " + token_to_string(type, val));
}; }
function expect(punc) { return expect_token("punc", punc); }; function expect(punc) {
return expect_token("punc", punc);
}
function has_newline_before(token) {
return token.nlb || !all(token.comments_before, function(comment) {
return !comment.nlb;
});
}
function can_insert_semicolon() { function can_insert_semicolon() {
return !options.strict && ( return !options.strict
S.token.nlb || is("eof") || is("punc", "}") && (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()) expect_token("punc", ";");
}; }
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() {
var start = S.token; var start = S.token;
var expr = parser(); var expr = parser.apply(null, arguments);
var end = prev(); var end = prev();
expr.start = start; expr.start = start;
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() { var statement = embed_tokens(function(strict_defun) {
handle_regexp(); handle_regexp();
switch (S.token.type) { switch (S.token.type) {
case "string": case "string":
if (S.in_directives) { if (S.in_directives) {
var token = peek(); var token = peek();
if (S.token.raw.indexOf("\\") == -1 if (S.token.raw.indexOf("\\") == -1
&& (token.nlb && (is_token(token, "punc", ";")
|| is_token(token, "eof") || is_token(token, "punc", "}")
|| is_token(token, "punc", ";") || has_newline_before(token)
|| is_token(token, "punc", "}"))) { || is_token(token, "eof"))) {
S.input.add_directive(S.token.value); S.input.add_directive(S.token.value);
} else { } else {
S.in_directives = false; S.in_directives = false;
@@ -896,6 +906,9 @@ function parse($TEXT, options) {
return for_(); return for_();
case "function": case "function":
if (!strict_defun && S.input.has_directive("use strict")) {
croak("In strict mode code, functions can only be declared at top level or immediately within another function.");
}
next(); next();
return function_(AST_Defun); return function_(AST_Defun);
@@ -927,7 +940,7 @@ function parse($TEXT, options) {
case "throw": case "throw":
next(); next();
if (S.token.nlb) if (has_newline_before(S.token))
croak("Illegal newline after 'throw'"); croak("Illegal newline after 'throw'");
var value = expression(true); var value = expression(true);
semicolon(); semicolon();
@@ -961,7 +974,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
@@ -976,7 +991,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.",
@@ -985,11 +1000,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;
@@ -997,18 +1012,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("(");
@@ -1029,7 +1043,7 @@ function parse($TEXT, options) {
} }
} }
return regular_for(init); return regular_for(init);
}; }
function regular_for(init) { function regular_for(init) {
expect(";"); expect(";");
@@ -1043,25 +1057,23 @@ 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 lhs = init instanceof AST_Var ? init.definitions[0].name : null;
var obj = expression(true); var obj = expression(true);
expect(")"); expect(")");
return new AST_ForIn({ return new AST_ForIn({
init : init, init : init,
name : lhs,
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;
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null; var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
if (in_statement && !name) if (in_statement && !name)
unexpected(); expect_token("name");
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration)) if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
unexpected(prev()); unexpected(prev());
expect("("); expect("(");
@@ -1078,7 +1090,7 @@ function parse($TEXT, options) {
S.input.push_directives_stack(); S.input.push_directives_stack();
S.in_loop = 0; S.in_loop = 0;
S.labels = []; S.labels = [];
var body = block_(); var body = block_(true);
if (S.input.has_directive("use strict")) { if (S.input.has_directive("use strict")) {
if (name) strict_verify_symbol(name); if (name) strict_verify_symbol(name);
argnames.forEach(strict_verify_symbol); argnames.forEach(strict_verify_symbol);
@@ -1105,24 +1117,24 @@ function parse($TEXT, options) {
body : body, body : body,
alternative : belse alternative : belse
}); });
}; }
function block_() { function block_(strict_defun) {
expect("{"); expect("{");
var a = []; var a = [];
while (!is("punc", "}")) { while (!is("punc", "}")) {
if (is("eof")) unexpected(); if (is("eof")) expect_token("punc", "}");
a.push(statement()); a.push(statement(strict_defun));
} }
next(); next();
return a; return a;
}; }
function switch_body_() { function switch_body_() {
expect("{"); expect("{");
var a = [], cur = null, branch = null, tmp; var a = [], cur = null, branch = null, tmp;
while (!is("punc", "}")) { while (!is("punc", "}")) {
if (is("eof")) unexpected(); if (is("eof")) expect_token("punc", "}");
if (is("keyword", "case")) { if (is("keyword", "case")) {
if (branch) branch.end = prev(); if (branch) branch.end = prev();
cur = []; cur = [];
@@ -1133,8 +1145,7 @@ function parse($TEXT, options) {
}); });
a.push(branch); a.push(branch);
expect(":"); expect(":");
} } else if (is("keyword", "default")) {
else if (is("keyword", "default")) {
if (branch) branch.end = prev(); if (branch) branch.end = prev();
cur = []; cur = [];
branch = new AST_Default({ branch = new AST_Default({
@@ -1142,8 +1153,7 @@ function parse($TEXT, options) {
body : cur body : cur
}); });
a.push(branch); a.push(branch);
} } else {
else {
if (!cur) unexpected(); if (!cur) unexpected();
cur.push(statement()); cur.push(statement());
} }
@@ -1151,7 +1161,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;
@@ -1184,7 +1194,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 = [];
@@ -1200,7 +1210,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({
@@ -1220,12 +1230,14 @@ function parse($TEXT, options) {
} else { } else {
args = []; args = [];
} }
return subscripts(new AST_New({ var call = new AST_New({
start : start, start : start,
expression : newexp, expression : newexp,
args : args, args : args,
end : prev() end : prev()
}), allow_calls); });
mark_pure(call);
return subscripts(call, allow_calls);
}; };
function as_atom_node() { function as_atom_node() {
@@ -1264,7 +1276,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")) {
@@ -1311,7 +1323,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();
@@ -1330,7 +1342,7 @@ function parse($TEXT, options) {
} }
next(); next();
return a; return a;
}; }
var array_ = embed_tokens(function() { var array_ = embed_tokens(function() {
expect("["); expect("[");
@@ -1357,7 +1369,7 @@ function parse($TEXT, options) {
if (type == "name" && !is("punc", ":")) { if (type == "name" && !is("punc", ":")) {
var key = new AST_SymbolAccessor({ var key = new AST_SymbolAccessor({
start: S.token, start: S.token,
name: as_property_name(), name: "" + as_property_name(),
end: prev() end: prev()
}); });
if (name == "get") { if (name == "get") {
@@ -1383,7 +1395,7 @@ function parse($TEXT, options) {
a.push(new AST_ObjectKeyVal({ a.push(new AST_ObjectKeyVal({
start : start, start : start,
quote : start.quote, quote : start.quote,
key : name, key : "" + name,
value : expression(false), value : expression(false),
end : prev() end : prev()
})); }));
@@ -1396,7 +1408,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":
@@ -1407,14 +1419,14 @@ function parse($TEXT, options) {
default: default:
unexpected(); unexpected();
} }
}; }
function as_name() { function as_name() {
var tmp = S.token; if (!is("name")) expect_token("name");
if (tmp.type != "name") unexpected(); var name = S.token.value;
next(); next();
return tmp.value; return name;
}; }
function _make_symbol(type) { function _make_symbol(type) {
var name = S.token.value; var name = S.token.value;
@@ -1423,7 +1435,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")
@@ -1441,7 +1453,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;
@@ -1494,7 +1506,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));
@@ -1503,7 +1515,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) && !S.token.nlb) { 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;
@@ -1526,7 +1538,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;
@@ -1548,7 +1560,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;
@@ -1570,12 +1582,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({
@@ -1612,18 +1624,19 @@ 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) {
handle_regexp();
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();
while (!is("eof")) while (!is("eof"))
body.push(statement()); body.push(statement(true));
S.input.pop_directives_stack(); S.input.pop_directives_stack();
var end = prev(); var end = prev();
var toplevel = options.toplevel; var toplevel = options.toplevel;
@@ -1634,6 +1647,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

@@ -53,25 +53,30 @@ function find_builtins(reserved) {
"-Infinity", "-Infinity",
"undefined", "undefined",
].forEach(add); ].forEach(add);
[ Object, Array, Function, Number, [
String, Boolean, Error, Math, Array,
Date, RegExp Boolean,
].forEach(function(ctor){ Date,
Error,
Function,
Math,
Number,
Object,
RegExp,
String,
].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);
} }
}); });
function add(name) { function add(name) {
push_uniq(reserved, name); push_uniq(reserved, name);
} }
} }
function reserve_quoted_keys(ast, reserved) { function reserve_quoted_keys(ast, reserved) {
function add(name) {
push_uniq(reserved, name);
}
ast.walk(new TreeWalker(function(node) { ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ObjectKeyVal && node.quote) { if (node instanceof AST_ObjectKeyVal && node.quote) {
add(node.key); add(node.key);
@@ -79,6 +84,10 @@ function reserve_quoted_keys(ast, reserved) {
addStrings(node.property, add); addStrings(node.property, add);
} }
})); }));
function add(name) {
push_uniq(reserved, name);
}
} }
function addStrings(node, add) { function addStrings(node, add) {
@@ -110,12 +119,15 @@ function mangle_properties(ast, options) {
if (!Array.isArray(reserved)) reserved = []; if (!Array.isArray(reserved)) reserved = [];
if (!options.builtins) find_builtins(reserved); if (!options.builtins) find_builtins(reserved);
var cache = options.cache; var cname = -1;
if (cache == null) { var cache;
cache = { if (options.cache) {
cname: -1, cache = options.cache.props;
props: new Dictionary() cache.each(function(mangled_name) {
}; push_uniq(reserved, mangled_name);
});
} else {
cache = new Dictionary();
} }
var regex = options.regex; var regex = options.regex;
@@ -124,45 +136,43 @@ function mangle_properties(ast, options) {
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true' // note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
// the same as passing an empty string. // the same as passing an empty string.
var debug = options.debug !== false; var debug = options.debug !== false;
var debug_name_suffix; var debug_suffix;
if (debug) { if (debug) debug_suffix = options.debug === true ? "" : options.debug;
debug_name_suffix = (options.debug === true ? "" : options.debug);
}
var names_to_mangle = []; var names_to_mangle = [];
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);
} } else if (node instanceof AST_ObjectProperty) {
else if (node instanceof AST_ObjectProperty) {
// setter or getter, since KeyVal is handled above // setter or getter, since KeyVal is handled above
add(node.key.name); add(node.key.name);
} } else if (node instanceof AST_Dot) {
else if (node instanceof AST_Dot) {
add(node.property); add(node.property);
} } 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);
} } else if (node instanceof AST_ObjectProperty) {
else if (node instanceof AST_ObjectProperty) {
// setter or getter // setter or getter
node.key.name = mangle(node.key.name); node.key.name = mangle(node.key.name);
} } else if (node instanceof AST_Dot) {
else if (node instanceof AST_Dot) {
node.property = mangle(node.property); node.property = mangle(node.property);
} } 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]);
} }
})); }));
@@ -171,9 +181,7 @@ function mangle_properties(ast, options) {
function can_mangle(name) { function can_mangle(name) {
if (unmangleable.indexOf(name) >= 0) return false; if (unmangleable.indexOf(name) >= 0) return false;
if (reserved.indexOf(name) >= 0) return false; if (reserved.indexOf(name) >= 0) return false;
if (options.only_cache) { if (options.only_cache) return cache.has(name);
return cache.props.has(name);
}
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false; if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
return true; return true;
} }
@@ -181,57 +189,42 @@ function mangle_properties(ast, options) {
function should_mangle(name) { function should_mangle(name) {
if (regex && !regex.test(name)) return false; if (regex && !regex.test(name)) return false;
if (reserved.indexOf(name) >= 0) return false; if (reserved.indexOf(name) >= 0) return false;
return cache.props.has(name) return cache.has(name) || names_to_mangle.indexOf(name) >= 0;
|| names_to_mangle.indexOf(name) >= 0;
} }
function add(name) { function add(name) {
if (can_mangle(name)) if (can_mangle(name)) push_uniq(names_to_mangle, name);
push_uniq(names_to_mangle, name); if (!should_mangle(name)) push_uniq(unmangleable, name);
if (!should_mangle(name)) {
push_uniq(unmangleable, name);
}
} }
function mangle(name) { function mangle(name) {
if (!should_mangle(name)) { if (!should_mangle(name)) {
return name; return name;
} }
var mangled = cache.get(name);
var mangled = cache.props.get(name);
if (!mangled) { if (!mangled) {
if (debug) { if (debug) {
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_. // debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_"; var debug_mangled = "_$" + name + "$" + debug_suffix + "_";
if (can_mangle(debug_mangled)) mangled = debug_mangled;
if (can_mangle(debug_mangled)) {
mangled = debug_mangled;
}
} }
// either debug mode is off, or it is on and we could not use the mangled name // either debug mode is off, or it is on and we could not use the mangled name
if (!mangled) { if (!mangled) do {
do { mangled = base54(++cname);
mangled = base54(++cache.cname); } while (!can_mangle(mangled));
} while (!can_mangle(mangled)); cache.set(name, mangled);
}
cache.props.set(name, mangled);
} }
return mangled; return mangled;
} }
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]);
} } else if (node instanceof AST_String) {
else if (node instanceof AST_String) {
node.value = mangle(node.value); node.value = mangle(node.value);
} } else if (node instanceof AST_Conditional) {
else if (node instanceof AST_Conditional) {
node.consequent = mangleStrings(node.consequent); node.consequent = mangleStrings(node.consequent);
node.alternative = mangleStrings(node.alternative); node.alternative = mangleStrings(node.alternative);
} }

View File

@@ -43,9 +43,10 @@
"use strict"; "use strict";
function SymbolDef(scope, orig) { function SymbolDef(scope, orig, init) {
this.name = orig.name; this.name = orig.name;
this.orig = [ orig ]; this.orig = [ orig ];
this.init = init;
this.eliminated = 0; this.eliminated = 0;
this.scope = scope; this.scope = scope;
this.references = []; this.references = [];
@@ -54,7 +55,7 @@ function SymbolDef(scope, orig) {
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;
@@ -62,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);
} }
@@ -94,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,
@@ -103,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);
@@ -118,28 +114,14 @@ 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;
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;
return; return;
} }
if (node instanceof AST_Symbol) { if (node instanceof AST_Symbol) {
@@ -149,48 +131,34 @@ 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) {
defun.def_function(node); // This should be defined in the parent scope, as we encounter the
} // AST_Defun node before getting to its AST_Symbol.
else if (node instanceof AST_SymbolDefun) { (node.scope = defun.parent_scope.resolve()).def_function(node, defun);
// Careful here, the scope where this should be defined is } else if (node instanceof AST_SymbolLambda) {
// the parent scope. The reason is that we enter a new var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
// scope when we encounter the AST_Defun node (which is if (options.ie8) def.defun = defun.parent_scope.resolve();
// instanceof AST_Scope) but we get to the symbol a bit } else if (node instanceof AST_SymbolVar) {
// later. defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
(node.scope = defun.parent_scope).def_function(node);
}
else if (node instanceof AST_SymbolVar) {
defun.def_variable(node);
if (defun !== scope) { if (defun !== scope) {
node.mark_enclosed(options); node.mark_enclosed(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) {
if (node instanceof AST_LoopControl && node.label) { if (node instanceof AST_LoopControl) {
node.label.thedef.references.push(node); if (node.label) node.label.thedef.references.push(node);
return true; return true;
} }
if (node instanceof AST_SymbolRef) { if (node instanceof AST_SymbolRef) {
@@ -211,43 +179,47 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
return true; return true;
} }
// ensure mangling works if catch reuses a scope variable // ensure mangling works if catch reuses a scope variable
var def; if (node instanceof AST_SymbolCatch) {
if (node instanceof AST_SymbolCatch && (def = node.definition().redefined())) { var def = node.definition().redefined();
var s = node.scope; if (def) for (var s = node.scope; s; s = s.parent_scope) {
while (s) {
push_uniq(s.enclosed, def); push_uniq(s.enclosed, def);
if (s === def.scope) break; if (s === def.scope) break;
s = s.parent_scope;
} }
return true;
} }
}); });
self.walk(tw); self.walk(tw);
// pass 3: fix up any scoping issue with IE8 // pass 3: fix up any scoping issue with IE8
if (options.ie8) { if (options.ie8) self.walk(new TreeWalker(function(node) {
self.walk(new TreeWalker(function(node, descend) { if (node instanceof AST_SymbolCatch) {
if (node instanceof AST_SymbolCatch) { redefine(node, node.thedef.defun);
var name = node.name; return true;
var refs = node.thedef.references; }
var scope = node.thedef.defun; if (node instanceof AST_SymbolLambda) {
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node); var def = node.thedef;
refs.forEach(function(ref) { if (def.orig.length == 1) {
ref.thedef = def; redefine(node, node.scope.parent_scope);
ref.reference(options); node.thedef.init = def.init;
});
node.thedef = def;
node.reference(options);
return true;
} }
})); return true;
} }
}));
if (options.cache) { function redefine(node, scope) {
this.cname = options.cache.cname; var name = node.name;
var refs = node.thedef.references;
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
refs.forEach(function(ref) {
ref.thedef = def;
ref.reference(options);
});
node.thedef = def;
node.reference(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);
@@ -260,7 +232,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
@@ -270,7 +242,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({
@@ -282,8 +254,7 @@ AST_Lambda.DEFMETHOD("init_scope_vars", function(){
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) { AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
var def = this.definition(); var def = this.definition();
var s = this.scope; for (var s = this.scope; s; s = s.parent_scope) {
while (s) {
push_uniq(s.enclosed, def); push_uniq(s.enclosed, def);
if (options.keep_fnames) { if (options.keep_fnames) {
s.functions.each(function(d) { s.functions.each(function(d) {
@@ -291,7 +262,6 @@ AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
}); });
} }
if (s === def.scope) break; if (s === def.scope) break;
s = s.parent_scope;
} }
}); });
@@ -300,69 +270,91 @@ 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){ AST_Scope.DEFMETHOD("def_function", function(symbol, init) {
this.functions.set(symbol.name, this.def_variable(symbol)); var def = this.def_variable(symbol, init);
if (!def.init || def.init instanceof AST_Defun) def.init = init;
this.functions.set(symbol.name, def);
return def;
}); });
AST_Scope.DEFMETHOD("def_variable", function(symbol){ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
var def; var def = this.variables.get(symbol.name);
if (!this.variables.has(symbol.name)) { if (def) {
def = new SymbolDef(this, symbol); def.orig.push(symbol);
if (def.init && (def.scope !== symbol.scope || def.init instanceof AST_Function)) {
def.init = init;
}
} else {
def = new SymbolDef(this, symbol, init);
this.variables.set(symbol.name, def); this.variables.set(symbol.name, def);
def.global = !this.parent_scope; def.global = !this.parent_scope;
} else {
def = this.variables.get(symbol.name);
def.orig.push(symbol);
} }
return symbol.thedef = def; return symbol.thedef = def;
}); });
AST_Scope.DEFMETHOD("next_mangled", function(options){ AST_Lambda.DEFMETHOD("resolve", return_this);
var ext = this.enclosed; AST_Scope.DEFMETHOD("resolve", function() {
out: while (true) { return this.parent_scope;
var m = base54(++this.cname);
if (!is_identifier(m)) continue; // skip over "do"
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not
// 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;
}
}); });
AST_Toplevel.DEFMETHOD("resolve", return_this);
AST_Function.DEFMETHOD("next_mangled", function(options, def){ function names_in_use(scope, options) {
// #179, #326 var names = scope.names_in_use;
// in Safari strict mode, something like (function x(x){...}) is a syntax error; if (!names) {
// a function expression's argument cannot shadow the function expression's name scope.names_in_use = names = Object.create(scope.mangled_names || null);
scope.cname_holes = [];
var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition(); var cache = options.cache && options.cache.props;
scope.enclosed.forEach(function(def) {
// the function's mangled_name is null when keep_fnames is true if (def.unmangleable(options)) names[def.name] = true;
var tricky_name = tricky_def ? tricky_def.mangled_name || tricky_def.name : null; if (def.global && cache && cache.has(def.name)) {
names[cache.get(def.name)] = true;
}
});
}
return names;
}
function next_mangled_name(scope, options, def) {
var in_use = names_in_use(scope, options);
var holes = scope.cname_holes;
var names = Object.create(null);
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) { while (true) {
var name = AST_Lambda.prototype.next_mangled.call(this, options, def); name = base54(++scope.cname);
if (!tricky_name || tricky_name != name) if (in_use[name] || !is_identifier(name) || options.reserved.has[name]) continue;
return name; 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);
}); });
@@ -370,20 +362,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,
@@ -394,113 +385,128 @@ 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 = [];
if (options.cache) { if (options.cache && options.cache.props) {
this.globals.each(collect); var mangled_names = this.mangled_names = Object.create(null);
options.cache.props.each(function(mangled_name) {
mangled_names[mangled_name] = true;
});
} }
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;
descend(); descend();
lname = save_nesting; lname = save_nesting;
return true; // don't descend again in TreeWalker return true;
} }
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;
do name = base54(++lname); while (!is_identifier(name)); do {
name = base54(++lname);
} while (!is_identifier(name));
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);
if (options.cache) { function mangle(def) {
options.cache.cname = this.cname; if (options.reserved.has[def.name]) return;
} def.mangle(options);
function collect(symbol) {
if (!member(symbol.name, options.reserved)) {
to_mangle.push(symbol);
}
} }
}); });
AST_Toplevel.DEFMETHOD("find_unique_prefix", function(options) { AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
var cache = options.cache && options.cache.props; var cache = options.cache && options.cache.props;
var prefixes = Object.create(null); var avoid = Object.create(null);
options.reserved.forEach(add_prefix); options.reserved.forEach(to_avoid);
this.globals.each(add_def); this.globals.each(add_def);
this.walk(new TreeWalker(function(node) { this.walk(new TreeWalker(function(node) {
if (node instanceof AST_Scope) node.variables.each(add_def); if (node instanceof AST_Scope) node.variables.each(add_def);
if (node instanceof AST_SymbolCatch) add_def(node.definition()); if (node instanceof AST_SymbolCatch) add_def(node.definition());
})); }));
var prefix, i = 0; return avoid;
do {
prefix = create_name(i++);
} while (prefixes[prefix]);
return prefix;
function add_prefix(name) { function to_avoid(name) {
if (/[0-9]$/.test(name)) { avoid[name] = true;
prefixes[name.replace(/[0-9]+$/, "")] = true;
}
} }
function add_def(def) { function add_def(def) {
var name = def.name; var name = def.name;
if (def.global && cache && cache.has(name)) name = cache.get(name); if (def.global && cache && cache.has(name)) name = cache.get(name);
else if (!def.unmangleable(options)) return; else if (!def.unmangleable(options)) return;
add_prefix(name); to_avoid(name);
}
function create_name(num) {
var name = "";
do {
name += letters[num % letters.length];
num = Math.floor(num / letters.length);
} while (num);
return name;
} }
}); });
AST_Toplevel.DEFMETHOD("expand_names", function(options) { AST_Toplevel.DEFMETHOD("expand_names", function(options) {
options = this._default_mangler_options(options); base54.reset();
var prefix = this.find_unique_prefix(options); base54.sort();
options = _default_mangler_options(options);
var avoid = this.find_colliding_names(options);
var cname = 0;
this.globals.each(rename); this.globals.each(rename);
this.walk(new TreeWalker(function(node) { this.walk(new TreeWalker(function(node) {
if (node instanceof AST_Scope) node.variables.each(rename); if (node instanceof AST_Scope) node.variables.each(rename);
if (node instanceof AST_SymbolCatch) rename(node.definition()); if (node instanceof AST_SymbolCatch) rename(node.definition());
})); }));
function next_name() {
var name;
do {
name = base54(cname++);
} while (avoid[name] || !is_identifier(name));
return name;
}
function rename(def) { function rename(def) {
if (def.global || def.unmangleable(options)) return; if (def.global && options.cache) return;
if (member(def.name, options.reserved)) return; if (def.unmangleable(options)) return;
if (options.reserved.has[def.name]) return;
var d = def.redefined(); var d = def.redefined();
def.name = d ? d.name : prefix + def.id; def.name = d ? d.name : next_name();
def.orig.forEach(function(sym) { def.orig.forEach(function(sym) {
sym.name = def.name; sym.name = def.name;
}); });
@@ -515,8 +521,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);
@@ -549,17 +556,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;) {
@@ -570,7 +581,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();
@@ -584,6 +595,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,52 @@ 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) return 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;) { var index = array.indexOf(el);
if (array[i] === el) array.splice(i, 1); if (index >= 0) array.splice(index, 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;
@@ -303,6 +232,13 @@ Dictionary.prototype = {
ret.push(f(this._values[i], i.substr(1))); ret.push(f(this._values[i], i.substr(1)));
return ret; return ret;
}, },
clone: function() {
var ret = new Dictionary();
for (var i in this._values)
ret._values[i] = this._values[i];
ret._size = this._size;
return ret;
},
toObject: function() { return this._values } toObject: function() { return this._values }
}; };
Dictionary.fromObject = function(obj) { Dictionary.fromObject = function(obj) {
@@ -320,20 +256,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,23 +1,17 @@
{ {
"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.1", "version": "3.5.0",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=0.8.0"
}, },
"maintainers": [ "maintainers": [
"Alex Lam <alexlamsl@gmail.com>",
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)" "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
], ],
"repository": { "repository": "mishoo/UglifyJS2",
"type": "git",
"url": "https://github.com/mishoo/UglifyJS2.git"
},
"bugs": {
"url": "https://github.com/mishoo/UglifyJS2/issues"
},
"main": "tools/node.js", "main": "tools/node.js",
"bin": { "bin": {
"uglifyjs": "bin/uglifyjs" "uglifyjs": "bin/uglifyjs"
@@ -29,16 +23,38 @@
"LICENSE" "LICENSE"
], ],
"dependencies": { "dependencies": {
"commander": "~2.12.1", "commander": "~2.19.0",
"source-map": "~0.6.1" "source-map": "~0.6.1"
}, },
"devDependencies": { "devDependencies": {
"acorn": "~5.2.1", "acorn": "~6.1.1",
"mocha": "~3.5.1", "semver": "~5.6.0"
"semver": "~5.4.1"
}, },
"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");
} }
} }
} }

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

@@ -0,0 +1,578 @@
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"
}
issue_3273: {
options = {
arguments: true,
}
input: {
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
function f(a) {
console.log(a, a);
a++;
console.log(a, a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 1",
]
}
issue_3273_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
function f(a) {
console.log(a, a);
a++;
console.log(a, a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 1",
]
}
issue_3273_local_strict: {
options = {
arguments: true,
}
input: {
function f(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
function f(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_local_strict_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
function f(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
function f(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_global_strict: {
options = {
arguments: true,
}
input: {
"use strict";
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
"use strict";
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_global_strict_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
"use strict";
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect: {
"use strict";
function f(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
}
f(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3282_1: {
options = {
arguments: true,
reduce_funcs: true,
reduce_vars: true,
keep_fargs: false,
unused: true,
}
input: {
(function(t) {
return function() {
t();
};
})(function() {
'use strict';
function e() {
return arguments[0];
}
e();
e();
})();
}
expect: {
(function() {
return function() {
(function() {
"use strict";
function e() {
return arguments[0];
}
e();
e();
})();
};
})()();
}
expect_stdout: true
}
issue_3282_1_passes: {
options = {
arguments: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
keep_fargs: false,
unused: true,
}
input: {
(function(t) {
return function() {
t();
};
})(function() {
'use strict';
function e() {
return arguments[0];
}
e();
e();
})();
}
expect: {
(function() {
return function() {
(function() {
"use strict";
function e(argument_0) {
return argument_0;
}
e();
e();
})();
};
})()();
}
expect_stdout: true
}
issue_3282_2: {
options = {
arguments: true,
reduce_vars: true,
keep_fargs: false,
unused: true,
}
input: {
(function(f) {
f();
})(function() {
return (function(t) {
return function() {
t();
};
})(function() {
'use strict';
function e() {
return arguments[0];
}
e();
e();
})();
});
}
expect: {
(function() {
(function() {
return function(t) {
return function() {
t();
};
}(function() {
"use strict";
function e() {
return arguments[0];
}
e();
e();
})();
})();
})();
}
expect_stdout: true
}
issue_3282_2_passes: {
options = {
arguments: true,
passes: 2,
reduce_vars: true,
keep_fargs: false,
unused: true,
}
input: {
(function(f) {
f();
})(function() {
return (function(t) {
return function() {
t();
};
})(function() {
'use strict';
function e() {
return arguments[0];
}
e();
e();
})();
});
}
expect: {
(function() {
(function() {
return function(t) {
return function() {
t();
};
}(function() {
"use strict";
function e(argument_0) {
return argument_0;
}
e();
e();
})();
})();
})();
}
expect_stdout: true
}

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];
@@ -239,3 +239,113 @@ index_length: {
} }
expect_stdout: "1 2" expect_stdout: "1 2"
} }
constructor_bad: {
options = {
unsafe: true
}
input: {
try {
Array(NaN);
console.log("FAIL1");
} catch (ex) {
try {
new Array(NaN);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
try {
Array(3.14);
console.log("FAIL1");
} catch (ex) {
try {
new Array(3.14);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
}
expect: {
try {
Array(NaN);
console.log("FAIL1");
} catch (ex) {
try {
Array(NaN);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
try {
Array(3.14);
console.log("FAIL1");
} catch (ex) {
try {
Array(3.14);
console.log("FAIL2");
} catch (ex) {
console.log("PASS");
}
}
}
expect_stdout: [
"PASS",
"PASS",
]
expect_warnings: [
"WARN: Invalid array length: 3.14 [test/compress/arrays.js:13,12]",
"WARN: Invalid array length: 3.14 [test/compress/arrays.js:17,16]",
]
}
constructor_good: {
options = {
unsafe: true
}
input: {
console.log(Array());
console.log(Array(0));
console.log(Array(1));
console.log(Array(6));
console.log(Array(7));
console.log(Array(1, 2));
console.log(Array(false));
console.log(Array("foo"));
console.log(Array(Array));
console.log(new Array());
console.log(new Array(0));
console.log(new Array(1));
console.log(new Array(6));
console.log(new Array(7));
console.log(new Array(1, 2));
console.log(new Array(false));
console.log(new Array("foo"));
console.log(new Array(Array));
}
expect: {
console.log([]);
console.log([]);
console.log([,]);
console.log([,,,,,,]);
console.log(Array(7));
console.log([ 1, 2 ]);
console.log([ false ]);
console.log([ "foo" ]);
console.log(Array(Array));
console.log([]);
console.log([]);
console.log([,]);
console.log([,,,,,,]);
console.log(Array(7));
console.log([ 1, 2 ]);
console.log([ false ]);
console.log([ "foo" ]);
console.log(Array(Array));
}
expect_stdout: true
expect_warnings: []
}

View File

@@ -1,24 +1,25 @@
asm_mixed: { asm_mixed: {
options = { options = {
sequences : true, assignments: true,
properties : true, booleans: true,
dead_code : true, comparisons: true,
drop_debugger : true, conditionals: true,
conditionals : true, dead_code: true,
comparisons : true, drop_debugger: true,
evaluate : true, evaluate: true,
booleans : true, hoist_funs: true,
loops : true, hoist_vars: true,
unused : true, if_return: true,
hoist_funs : true, join_vars: true,
keep_fargs : true, keep_fargs: true,
keep_fnames : false, keep_fnames: false,
hoist_vars : true, loops: true,
if_return : true, negate_iife: true,
join_vars : true, properties: true,
side_effects : true, sequences: true,
negate_iife : true side_effects: 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) {

View File

@@ -1,5 +1,6 @@
op_equals_left_local_var: { op_equals_left_local_var: {
options = { options = {
assignments: true,
evaluate: true, evaluate: true,
} }
input: { input: {
@@ -60,6 +61,7 @@ op_equals_left_local_var: {
op_equals_right_local_var: { op_equals_right_local_var: {
options = { options = {
assignments: true,
evaluate: true, evaluate: true,
} }
input: { input: {
@@ -123,6 +125,7 @@ op_equals_right_local_var: {
} }
op_equals_left_global_var: { op_equals_left_global_var: {
options = { options = {
assignments: true,
evaluate: true, evaluate: true,
} }
input: { input: {
@@ -179,6 +182,7 @@ op_equals_left_global_var: {
op_equals_right_global_var: { op_equals_right_global_var: {
options = { options = {
assignments: true,
evaluate: true, evaluate: true,
} }
input: { input: {
@@ -236,3 +240,52 @@ op_equals_right_global_var: {
x = g() & x; x = g() & x;
} }
} }
increment_decrement_1: {
options = {
assignments: true,
reduce_vars: true,
}
input: {
console.log(function(a) {
a += 1;
a -= 1;
return a;
}(42));
}
expect: {
console.log(function(a){
++a;
--a;
return a;
}(42));
}
expect_stdout: "42"
}
increment_decrement_2: {
options = {
assignments: true,
passes: 2,
reduce_vars: true,
}
input: {
console.log(function(a) {
a = a + 1;
a = a - 1;
a += 1;
a -= 1;
return a;
}(42));
}
expect: {
console.log(function(a){
++a;
--a;
++a;
--a;
return a;
}(42));
}
expect_stdout: "42"
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,114 +0,0 @@
keep_comparisons: {
options = {
comparisons: true,
unsafe_comps: false
}
input: {
var obj1 = {
valueOf: function() {triggeredFirst();}
}
var obj2 = {
valueOf: function() {triggeredSecond();}
}
var result1 = obj1 <= obj2;
var result2 = obj1 < obj2;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
}
expect: {
var obj1 = {
valueOf: function() {triggeredFirst();}
}
var obj2 = {
valueOf: function() {triggeredSecond();}
}
var result1 = obj1 <= obj2;
var result2 = obj1 < obj2;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
}
}
keep_comparisons_with_unsafe_comps: {
options = {
comparisons: true,
unsafe_comps: true
}
input: {
var obj1 = {
valueOf: function() {triggeredFirst();}
}
var obj2 = {
valueOf: function() {triggeredSecond();}
}
var result1 = obj1 <= obj2;
var result2 = obj1 < obj2;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
}
expect: {
var obj1 = {
valueOf: function() {triggeredFirst();}
}
var obj2 = {
valueOf: function() {triggeredSecond();}
}
var result1 = obj2 >= obj1;
var result2 = obj2 > obj1;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
}
}
dont_change_in_or_instanceof_expressions: {
input: {
1 in 1;
null in null;
1 instanceof 1;
null instanceof null;
}
expect: {
1 in 1;
null in null;
1 instanceof 1;
null instanceof null;
}
}
self_comparison_1: {
options = {
comparisons: true,
}
input: {
a === a;
a !== b;
b.c === a.c;
b.c !== b.c;
}
expect: {
a == a;
a !== b;
b.c === a.c;
b.c != b.c;
}
}
self_comparison_2: {
options = {
comparisons: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
input: {
function f() {}
var o = {};
console.log(f != f, o === o);
}
expect: {
function f() {}
var o = {};
console.log(false, true);
}
expect_stdout: "false true"
}

View File

@@ -0,0 +1,347 @@
comparisons: {
options = {
comparisons: true,
}
input: {
var obj1, obj2;
var result1 = obj1 <= obj2;
var result2 = obj1 < obj2;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
}
expect: {
var obj1, obj2;
var result1 = obj1 <= obj2;
var result2 = obj1 < obj2;
var result3 = obj2 <= obj1;
var result4 = obj2 < obj1;
}
}
unsafe_comps: {
options = {
comparisons: true,
conditionals: true,
unsafe_comps: true,
}
input: {
var obj1, obj2;
obj1 <= obj2 ? f1() : g1();
obj1 < obj2 ? f2() : g2();
obj1 >= obj2 ? f3() : g3();
obj1 > obj2 ? f4() : g4();
}
expect: {
var obj1, obj2;
obj2 < obj1 ? g1() : f1();
obj1 < obj2 ? f2() : g2();
obj1 < obj2 ? g3() : f3();
obj2 < obj1 ? f4() : g4();
}
}
dont_change_in_or_instanceof_expressions: {
input: {
1 in 1;
null in null;
1 instanceof 1;
null instanceof null;
}
expect: {
1 in 1;
null in null;
1 instanceof 1;
null instanceof null;
}
}
self_comparison_1: {
options = {
comparisons: true,
}
input: {
a === a;
a !== b;
b.c === a.c;
b.c !== b.c;
}
expect: {
a == a;
a !== b;
b.c === a.c;
b.c != b.c;
}
}
self_comparison_2: {
options = {
comparisons: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
input: {
function f() {}
var o = {};
console.log(f != f, o === o);
}
expect: {
function f() {}
var o = {};
console.log(false, true);
}
expect_stdout: "false true"
}
issue_2857_1: {
options = {
comparisons: true,
}
input: {
function f1(a) {
a === undefined || a === null;
a === undefined || a !== null;
a !== undefined || a === null;
a !== undefined || a !== null;
a === undefined && a === null;
a === undefined && a !== null;
a !== undefined && a === null;
a !== undefined && a !== null;
}
function f2(a) {
a === null || a === undefined;
a === null || a !== undefined;
a !== null || a === undefined;
a !== null || a !== undefined;
a === null && a === undefined;
a === null && a !== undefined;
a !== null && a === undefined;
a !== null && a !== undefined;
}
}
expect: {
function f1(a) {
null == a;
void 0 === a || null !== a;
void 0 !== a || null === a;
void 0 !== a || null !== a;
void 0 === a && null === a;
void 0 === a && null !== a;
void 0 !== a && null === a;
null != a;
}
function f2(a) {
null == a;
null === a || void 0 !== a;
null !== a || void 0 === a;
null !== a || void 0 !== a;
null === a && void 0 === a;
null === a && void 0 !== a;
null !== a && void 0 === a;
null != a;
}
}
}
issue_2857_2: {
options = {
comparisons: true,
}
input: {
function f(a, p) {
a === undefined || a === null || p;
a === undefined || a !== null || p;
a !== undefined || a === null || p;
a !== undefined || a !== null || p;
a === undefined && a === null || p;
a === undefined && a !== null || p;
a !== undefined && a === null || p;
a !== undefined && a !== null || p;
}
}
expect: {
function f(a, p) {
null == a || p;
void 0 === a || null !== a || p;
void 0 !== a || null === a || p;
void 0 !== a || null !== a || p;
void 0 === a && null === a || p;
void 0 === a && null !== a || p;
void 0 !== a && null === a || p;
null != a || p;
}
}
}
issue_2857_3: {
options = {
comparisons: true,
}
input: {
function f(a, p) {
a === undefined || a === null && p;
a === undefined || a !== null && p;
a !== undefined || a === null && p;
a !== undefined || a !== null && p;
a === undefined && a === null && p;
a === undefined && a !== null && p;
a !== undefined && a === null && p;
a !== undefined && a !== null && p;
}
}
expect: {
function f(a, p) {
void 0 === a || null === a && p;
void 0 === a || null !== a && p;
void 0 !== a || null === a && p;
void 0 !== a || null !== a && p;
void 0 === a && null === a && p;
void 0 === a && null !== a && p;
void 0 !== a && null === a && p;
null != a && p;
}
}
}
issue_2857_4: {
options = {
comparisons: true,
}
input: {
function f(a, p) {
p || a === undefined || a === null;
p || a === undefined || a !== null;
p || a !== undefined || a === null;
p || a !== undefined || a !== null;
p || a === undefined && a === null;
p || a === undefined && a !== null;
p || a !== undefined && a === null;
p || a !== undefined && a !== null;
}
}
expect: {
function f(a, p) {
p || null == a;
p || void 0 === a || null !== a;
p || void 0 !== a || null === a;
p || void 0 !== a || null !== a;
p || void 0 === a && null === a;
p || void 0 === a && null !== a;
p || void 0 !== a && null === a;
p || null != a;
}
}
}
issue_2857_5: {
options = {
comparisons: true,
}
input: {
function f(a, p) {
p && a === undefined || a === null;
p && a === undefined || a !== null;
p && a !== undefined || a === null;
p && a !== undefined || a !== null;
p && a === undefined && a === null;
p && a === undefined && a !== null;
p && a !== undefined && a === null;
p && a !== undefined && a !== null;
}
}
expect: {
function f(a, p) {
p && void 0 === a || null === a;
p && void 0 === a || null !== a;
p && void 0 !== a || null === a;
p && void 0 !== a || null !== a;
p && void 0 === a && null === a;
p && void 0 === a && null !== a;
p && void 0 !== a && null === a;
p && null != a;
}
}
}
issue_2857_6: {
options = {
comparisons: true,
pure_getters: "strict",
reduce_vars: true,
}
input: {
function f(a) {
if (({}).b === undefined || {}.b === null)
return a.b !== undefined && a.b !== null;
}
console.log(f({
a: [ null ],
get b() {
return this.a.shift();
}
}));
}
expect: {
function f(a) {
if (null == {}.b)
return void 0 !== a.b && null !== a.b;
}
console.log(f({
a: [ null ],
get b() {
return this.a.shift();
}
}));
}
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"
}
is_boolean_var: {
options = {
comparisons: true,
reduce_vars: true,
}
input: {
console.log(function(a, b) {
for (var i = 0, c = !b; i < a.length; i++)
if (!a[i] === c)
return i;
}([ false, true ], 42));
}
expect: {
console.log(function(a, b) {
for (var i = 0, c = !b; i < a.length; i++)
if (!a[i] == c)
return i;
}([ false, true ], 42));
}
expect_stdout: "1"
}

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: {
@@ -1203,3 +1228,191 @@ issue_2560: {
"2", "2",
] ]
} }
hoist_decl: {
options = {
conditionals: true,
join_vars: true,
sequences: true,
}
input: {
if (x()) {
var a;
y();
} else {
z();
var b;
}
}
expect: {
var a, b;
x() ? y() : z();
}
}
to_and_or: {
options = {
conditionals: true,
}
input: {
var values = [
0,
null,
true,
"foo",
false,
-1 / 0,
void 0,
];
values.forEach(function(x) {
values.forEach(function(y) {
values.forEach(function(z) {
console.log(x ? y || z : z);
});
});
});
}
expect: {
var values = [
0,
null,
true,
"foo",
false,
-1 / 0,
void 0,
];
values.forEach(function(x) {
values.forEach(function(y) {
values.forEach(function(z) {
console.log(x && y || z);
});
});
});
}
expect_stdout: true
}
cond_seq_assign_1: {
options = {
conditionals: true,
sequences: true,
}
input: {
function f(a) {
var t;
if (a) {
t = "foo";
t = "bar";
} else {
console.log(t);
t = 42;
}
console.log(t);
}
f(f);
f();
}
expect: {
function f(a) {
var t;
t = a ? (t = "foo", "bar") : (console.log(t), 42),
console.log(t);
}
f(f),
f();
}
expect_stdout: [
"bar",
"undefined",
"42",
]
}
cond_seq_assign_2: {
options = {
conditionals: true,
sequences: true,
}
input: {
function f(a) {
var t;
if (a) {
t = "foo";
a = "bar";
} else {
console.log(t);
t = 42;
}
console.log(t);
}
f(f);
f();
}
expect: {
function f(a) {
var t;
a ? (t = "foo", a = "bar") : (console.log(t), t = 42),
console.log(t);
}
f(f),
f();
}
expect_stdout: [
"foo",
"undefined",
"42",
]
}
cond_seq_assign_3: {
options = {
assignments: true,
conditionals: true,
}
input: {
var c = 0;
if (this)
c = 1 + c, c = c + 1;
else
c = 1 + c, c = c + 1;
console.log(c);
}
expect: {
var c = 0;
this, c = 1 + c, c += 1;
console.log(c);
}
expect_stdout: "2"
}
issue_3271: {
options = {
conditionals: true,
}
input: {
function f(a) {
var i = 0, b = [];
if (a) {
b[i++] = 4,
b[i++] = 1;
} else {
b[i++] = 3,
b[i++] = 2,
b[i++] = 1;
}
return b;
}
console.log(f(0).pop(), f(1).pop());
}
expect: {
function f(a) {
var i = 0, b = [];
a ? b[i++] = 4 : (b[i++] = 3, b[i++] = 2),
b[i++] = 1;
return b;
}
console.log(f(0).pop(), f(1).pop());
}
expect_stdout: "1 1"
}

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();
@@ -62,55 +62,15 @@ dead_code_2_should_warn: {
node_version: "<=4" node_version: "<=4"
} }
dead_code_2_should_warn_strict: {
options = {
dead_code: true
};
input: {
"use strict";
function f() {
g();
x = 10;
throw new Error("foo");
// completely discarding the `if` would introduce some
// bugs. UglifyJS v1 doesn't deal with this issue; in v2
// we copy any declarations to the upper scope.
if (x) {
y();
var x;
function g(){};
// but nested declarations should not be kept.
(function(){
var q;
function y(){};
})();
}
}
f();
}
expect: {
"use strict";
function f() {
g();
x = 10;
throw new Error("foo");
var x;
}
f();
}
expect_stdout: true
node_version: ">=4"
}
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");
@@ -137,42 +97,6 @@ dead_code_constant_boolean_should_warn_more: {
node_version: "<=4" node_version: "<=4"
} }
dead_code_constant_boolean_should_warn_more_strict: {
options = {
dead_code : true,
loops : true,
booleans : true,
conditionals : true,
evaluate : true,
side_effects : true,
};
input: {
"use strict";
while (!((foo && bar) || (x + "0"))) {
console.log("unreachable");
var foo;
function bar() {}
}
for (var x = 10, y; x && (y || x) && (!typeof x); ++x) {
asdf();
foo();
var moo;
}
bar();
}
expect: {
"use strict";
var foo;
// nothing for the while
// as for the for, it should keep:
var moo;
var x = 10, y;
bar();
}
expect_stdout: true
node_version: ">=4"
}
try_catch_finally: { try_catch_finally: {
options = { options = {
conditionals: true, conditionals: true,
@@ -828,3 +752,193 @@ issue_2597: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_2666: {
options = {
dead_code: true,
}
input: {
function f(a) {
return a = {
p: function() {
return a;
}
};
}
console.log(typeof f().p());
}
expect: {
function f(a) {
return a = {
p: function() {
return a;
}
};
}
console.log(typeof f().p());
}
expect_stdout: "object"
}
issue_2692: {
options = {
dead_code: true,
reduce_vars: false,
}
input: {
function f(a) {
return a = g;
function g() {
return a;
}
}
console.log(typeof f()());
}
expect: {
function f(a) {
return a = g;
function g() {
return a;
}
}
console.log(typeof f()());
}
expect_stdout: "function"
}
issue_2701: {
options = {
dead_code: true,
inline: false,
}
input: {
function f(a) {
return a = function() {
return function() {
return a;
};
}();
}
console.log(typeof f()());
}
expect: {
function f(a) {
return a = function() {
return function() {
return a;
};
}();
}
console.log(typeof f()());
}
expect_stdout: "function"
}
issue_2749: {
options = {
dead_code: true,
inline: true,
toplevel: true,
unused: true,
}
input: {
var a = 2, c = "PASS";
while (a--)
(function() {
return b ? c = "FAIL" : b = 1;
try {
} catch (b) {
var b;
}
})();
console.log(c);
}
expect: {
var a = 2, c = "PASS";
while (a--)
b = void 0, b ? c = "FAIL" : b = 1;
var b;
console.log(c);
}
expect_stdout: "PASS"
}
unsafe_builtin: {
options = {
side_effects: true,
unsafe: true,
}
input: {
(!w).constructor(x);
Math.abs(y);
[ 1, 2, z ].valueOf();
}
expect: {
w, x;
y;
z;
}
}
issue_2860_1: {
options = {
dead_code: true,
evaluate: true,
reduce_vars: true,
}
input: {
console.log(function(a) {
return a ^= 1;
}());
}
expect: {
console.log(function(a) {
return 1 ^ a;
}());
}
expect_stdout: "1"
}
issue_2860_2: {
options = {
dead_code: true,
evaluate: true,
inline: true,
passes: 2,
reduce_vars: true,
}
input: {
console.log(function(a) {
return a ^= 1;
}());
}
expect: {
console.log(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: {
@@ -1413,3 +1441,567 @@ issue_2516_2: {
Baz(2); Baz(2);
} }
} }
defun_lambda_same_name: {
options = {
toplevel: true,
unused: true,
}
input: {
function f(n) {
return n ? n * f(n - 1) : 1;
}
console.log(function f(n) {
return n ? n * f(n - 1) : 1;
}(5));
}
expect: {
console.log(function f(n) {
return n ? n * f(n - 1) : 1;
}(5));
}
expect_stdout: "120"
}
issue_2660_1: {
options = {
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = 2;
function f(b) {
return b && f() || a--;
}
f(1);
console.log(a);
}
expect: {
var a = 2;
(function f(b) {
return b && f() || a--;
})(1);
console.log(a);
}
expect_stdout: "1"
}
issue_2660_2: {
options = {
collapse_vars: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = 1;
function f(b) {
b && f();
--a, a.toString();
}
f();
console.log(a);
}
expect: {
var a = 1;
(function f(b) {
b && f(),
(--a).toString();
})(),
console.log(a);
}
expect_stdout: "0"
}
issue_2665: {
options = {
evaluate: true,
inline: true,
keep_fargs: false,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
typeofs: true,
unused: true,
}
input: {
var a = 1;
function g() {
a-- && g();
}
typeof h == "function" && h();
function h() {
typeof g == "function" && g();
}
console.log(a);
}
expect: {
var a = 1;
!function g() {
a-- && g();
}();
console.log(a);
}
expect_stdout: "-1"
}
double_assign_1: {
options = {
passes: 2,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
function f1() {
var a = {};
var a = [];
return a;
}
function f2() {
var a = {};
a = [];
return a;
}
function f3() {
a = {};
var a = [];
return a;
}
function f4(a) {
a = {};
a = [];
return a;
}
function f5(a) {
var a = {};
a = [];
return a;
}
function f6(a) {
a = {};
var a = [];
return a;
}
console.log(f1(), f2(), f3(), f4(), f5(), f6());
}
expect: {
function f1() {
return [];
}
function f2() {
var a;
a = [];
return a;
}
function f3() {
return [];
}
function f4(a) {
a = [];
return a;
}
function f5(a) {
a = [];
return a;
}
function f6(a) {
a = [];
return a;
}
console.log(f1(), f2(), f3(), f4(), f5(), f6());
}
expect_stdout: true
}
double_assign_2: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
for (var i = 0; i < 2; i++)
a = void 0, a = {}, console.log(a);
var a;
}
expect: {
for (var i = 0; i < 2; i++)
void 0, a = {}, console.log(a);
var a;
}
}
double_assign_3: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
for (var i = 0; i < 2; i++)
a = void 0, a = { a: a }, console.log(a);
var a;
}
expect: {
for (var i = 0; i < 2; i++)
a = void 0, a = { a: a }, console.log(a);
var a;
}
}
cascade_drop_assign: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a, b = a = "PASS";
console.log(b);
}
expect: {
var b = "PASS";
console.log(b);
}
expect_stdout: "PASS"
}
chained_3: {
options = {
reduce_vars: true,
unused: true,
}
input: {
console.log(function(a, b) {
var c = a, c = b;
b++;
return c;
}(1, 2));
}
expect: {
console.log(function(a, b) {
var c = b;
b++;
return c;
}(0, 2));
}
expect_stdout: "2"
}
issue_2768: {
options = {
inline: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = "FAIL", c = 1;
var c = function(b) {
var d = b = a;
var e = --b + (d && (a = "PASS"));
}();
console.log(a, typeof c);
}
expect: {
var a = "FAIL";
var c = (d = a, 0, void (d && (a = "PASS")));
var d;
console.log(a, typeof c);
}
expect_stdout: "PASS undefined"
}
issue_2846: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f(a, b) {
var a = 0;
b && b(a);
return a++;
}
var c = f();
console.log(c);
}
expect: {
var c = function(a, b) {
a = 0;
b && b(a);
return a++;
}();
console.log(c);
}
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",
]
}
issue_3233: {
options = {
pure_getters: "strict",
side_effects: true,
unused: true,
}
input: {
var a = function b() {
b.c = "PASS";
};
a();
console.log(a.c);
}
expect: {
var a = function b() {
b.c = "PASS";
};
a();
console.log(a.c);
}
expect_stdout: "PASS"
}

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(
@@ -1194,6 +1198,9 @@ issue_2231_1: {
console.log(Object.keys(void 0)); console.log(Object.keys(void 0));
} }
expect_stdout: true expect_stdout: true
expect_warnings: [
"WARN: Error evaluating Object.keys(void 0) [test/compress/evaluate.js:1,20]",
]
} }
issue_2231_2: { issue_2231_2: {
@@ -1208,6 +1215,23 @@ issue_2231_2: {
console.log(Object.getOwnPropertyNames(null)); console.log(Object.getOwnPropertyNames(null));
} }
expect_stdout: true expect_stdout: true
expect_warnings: [
"WARN: Error evaluating Object.getOwnPropertyNames(null) [test/compress/evaluate.js:1,20]",
]
}
issue_2231_3: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(Object.keys({ foo: "bar" })[0]);
}
expect: {
console.log("foo");
}
expect_stdout: "foo"
} }
self_comparison_1: { self_comparison_1: {
@@ -1221,12 +1245,12 @@ self_comparison_1: {
} }
input: { input: {
var o = { n: NaN }; var o = { n: NaN };
console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n); console.log(typeof o.n, o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n);
} }
expect: { expect: {
console.log(false, false, true, true, "number"); console.log("number", false, false, true, true);
} }
expect_stdout: "false false true true 'number'" expect_stdout: "number false false true true"
} }
self_comparison_2: { self_comparison_2: {
@@ -1241,12 +1265,12 @@ self_comparison_2: {
} }
input: { input: {
var o = { n: NaN }; var o = { n: NaN };
console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n); console.log(typeof o.n, o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n);
} }
expect: { expect: {
console.log(false, false, true, true, "number"); console.log("number", false, false, true, true);
} }
expect_stdout: "false false true true 'number'" expect_stdout: "number false false true true"
} }
issue_2535_1: { issue_2535_1: {
@@ -1330,13 +1354,336 @@ issue_2535_3: {
} }
expect_stdout: true expect_stdout: true
expect_warnings: [ expect_warnings: [
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1316,20]", "WARN: Dropping side-effect-free && [test/compress/evaluate.js:1,20]",
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1317,20]", "WARN: Dropping side-effect-free && [test/compress/evaluate.js:2,20]",
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1318,20]", "WARN: Dropping side-effect-free && [test/compress/evaluate.js:3,20]",
"WARN: Condition left of && always false [test/compress/evaluate.js:1318,20]", "WARN: Condition left of && always false [test/compress/evaluate.js:3,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1319,20]", "WARN: Dropping side-effect-free || [test/compress/evaluate.js:4,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1320,20]", "WARN: Dropping side-effect-free || [test/compress/evaluate.js:5,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1321,20]", "WARN: Dropping side-effect-free || [test/compress/evaluate.js:6,20]",
"WARN: Condition left of || always true [test/compress/evaluate.js:1321,20]", "WARN: Condition left of || always true [test/compress/evaluate.js:6,20]",
] ]
} }
issue_2822: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log([ function() {}, "PASS", "FAIL" ][1]);
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
}
string_case: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log("İ".toLowerCase().charCodeAt(0));
console.log("I".toLowerCase().charCodeAt(0));
console.log("Ş".toLowerCase().charCodeAt(0));
console.log("Ğ".toLowerCase().charCodeAt(0));
console.log("Ü".toLowerCase().charCodeAt(0));
console.log("Ö".toLowerCase().charCodeAt(0));
console.log("Ç".toLowerCase().charCodeAt(0));
console.log("i".toUpperCase().charCodeAt(0));
console.log("ı".toUpperCase().charCodeAt(0));
console.log("ş".toUpperCase().charCodeAt(0));
console.log("ğ".toUpperCase().charCodeAt(0));
console.log("ü".toUpperCase().charCodeAt(0));
console.log("ö".toUpperCase().charCodeAt(0));
console.log("ç".toUpperCase().charCodeAt(0));
}
expect: {
console.log(105);
console.log(105);
console.log(351);
console.log(287);
console.log(252);
console.log(246);
console.log(231);
console.log(73);
console.log(73);
console.log(350);
console.log(286);
console.log(220);
console.log(214);
console.log(199);
}
expect_stdout: [
"105",
"105",
"351",
"287",
"252",
"246",
"231",
"73",
"73",
"350",
"286",
"220",
"214",
"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_1: {
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"
}
issue_2968_2: {
options = {
assignments: true,
collapse_vars: true,
evaluate: true,
inline: true,
passes: 2,
reduce_vars: true,
side_effects: 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() {
a = 42,
((a <<= 0) && (a[(c = "PASS", 0)] = 0));
var a;
})();
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 = {};
}
}
}
if_increment: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function(a) {
if (console)
return ++a;
}(0));
}
expect: {
console.log(function(a) {
if (console)
return 1;
}());
}
expect_stdout: "1"
}
try_increment: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function(a) {
try {
return ++a;
} catch (e) {}
}(0));
}
expect: {
console.log(function(a) {
try {
return 1;
} catch (e) {}
}());
}
expect_stdout: "1"
}

File diff suppressed because it is too large Load Diff

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,8 @@ 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:4,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:7,8]",
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:130,8]',
] ]
} }
@@ -197,3 +196,23 @@ issue_2167: {
doWork(); doWork();
} }
} }
issue_3217: {
options = {
collapse_vars: true,
global_defs: {
"@o": "{fn:function(){var a=42;console.log(a)}}",
},
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
o.fn();
}
expect: {
console.log(42);
}
}

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,
} }
@@ -664,3 +670,195 @@ issue_2519: {
} }
expect_stdout: "5.5" expect_stdout: "5.5"
} }
undefined_key: {
options = {
evaluate: true,
hoist_props: true,
join_vars: true,
passes: 4,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a, o = {};
o[a] = 1;
o.b = 2;
console.log(o[a] + o.b);
}
expect: {
console.log(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"
}

863
test/compress/ie8.js Normal file
View File

@@ -0,0 +1,863 @@
do_screw: {
options = {
ie8: false,
}
beautify = {
ie8: false,
ascii_only: true,
}
input: {
f("\v");
}
expect_exact: 'f("\\v");'
}
dont_screw: {
options = {
ie8: true,
}
beautify = {
ie8: true,
ascii_only: true,
}
input: {
f("\v");
}
expect_exact: 'f("\\x0B");'
}
do_screw_constants: {
options = {
ie8: false,
}
input: {
f(undefined, Infinity);
}
expect_exact: "f(void 0,1/0);"
}
dont_screw_constants: {
options = {
ie8: true,
}
input: {
f(undefined, Infinity);
}
expect_exact: "f(undefined,Infinity);"
}
do_screw_try_catch: {
options = {
ie8: false,
}
mangle = {
ie8: false,
}
beautify = {
ie8: false,
}
input: {
good = function(e){
return function(error){
try{
e()
} catch(e) {
error(e)
}
}
};
}
expect: {
good = function(n){
return function(t){
try{
n()
} catch(n) {
t(n)
}
}
};
}
}
dont_screw_try_catch: {
options = {
ie8: true,
}
mangle = {
ie8: true,
}
beautify = {
ie8: true,
}
input: {
bad = function(e){
return function(error){
try{
e()
} catch(e) {
error(e)
}
}
};
}
expect: {
bad = function(t){
return function(n){
try{
t()
} catch(t) {
n(t)
}
}
};
}
}
do_screw_try_catch_undefined: {
options = {
ie8: false,
}
mangle = {
ie8: false,
}
beautify = {
ie8: false,
}
input: {
function a(b){
try {
throw 'Stuff';
} catch (undefined) {
console.log('caught: ' + undefined);
}
console.log('undefined is ' + undefined);
return b === undefined;
};
}
expect: {
function a(o){
try{
throw "Stuff"
} catch (o) {
console.log("caught: "+o)
}
console.log("undefined is " + void 0);
return void 0===o
}
}
expect_stdout: true
}
dont_screw_try_catch_undefined: {
options = {
ie8: true,
}
mangle = {
ie8: true,
}
beautify = {
ie8: true,
}
input: {
function a(b){
try {
throw 'Stuff';
} catch (undefined) {
console.log('caught: ' + undefined);
}
console.log('undefined is ' + undefined);
return b === undefined;
};
}
expect: {
function a(n){
try{
throw "Stuff"
} catch (undefined) {
console.log("caught: " + undefined)
}
console.log("undefined is " + undefined);
return n === undefined
}
}
expect_stdout: true
}
reduce_vars: {
options = {
evaluate: true,
ie8: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
mangle = {
ie8: true,
}
input: {
function f() {
var a;
try {
x();
} catch (a) {
y();
}
alert(a);
}
}
expect: {
function f() {
var t;
try {
x();
} catch (t) {
y();
}
alert(t);
}
}
}
issue_1586_1: {
options = {
ie8: true,
}
mangle = {
ie8: true,
}
input: {
function f() {
try {
x();
} catch (err) {
console.log(err.message);
}
}
}
expect_exact: "function f(){try{x()}catch(c){console.log(c.message)}}"
}
issue_1586_2: {
options = {
ie8: false,
}
mangle = {
ie8: false,
}
input: {
function f() {
try {
x();
} catch (err) {
console.log(err.message);
}
}
}
expect_exact: "function f(){try{x()}catch(c){console.log(c.message)}}"
}
issue_2120_1: {
mangle = {
ie8: false,
}
input: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (t) {
try {
throw 0;
} catch (a) {
if (t) b = "PASS";
}
}
console.log(b);
}
expect_stdout: "PASS"
}
issue_2120_2: {
mangle = {
ie8: true,
}
input: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect_stdout: "PASS"
}
issue_2254_1: {
mangle = {
ie8: false,
}
input: {
"eeeeee";
try {
console.log(f("PASS"));
} catch (e) {}
function f(s) {
try {
throw "FAIL";
} catch (e) {
return s;
}
}
}
expect: {
"eeeeee";
try {
console.log(f("PASS"));
} catch (e) {}
function f(t) {
try {
throw "FAIL";
} catch (e) {
return t;
}
}
}
expect_stdout: "PASS"
}
issue_2254_2: {
mangle = {
ie8: true,
}
input: {
"eeeeee";
try {
console.log(f("PASS"));
} catch (e) {}
function f(s) {
try {
throw "FAIL";
} catch (e) {
return s;
}
}
}
expect: {
"eeeeee";
try {
console.log(f("PASS"));
} catch (e) {}
function f(t) {
try {
throw "FAIL";
} catch (e) {
return t;
}
}
}
expect_stdout: "PASS"
}
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"
}
issue_3206_1: {
options = {
evaluate: true,
ie8: false,
reduce_vars: true,
typeofs: true,
unused: true,
}
input: {
console.log(function() {
var foo = function bar() {};
var baz = function moo() {};
return "function" == typeof bar;
}());
}
expect: {
console.log(function() {
return "function" == typeof bar;
}());
}
expect_stdout: "false"
}
issue_3206_2: {
options = {
evaluate: true,
ie8: true,
reduce_vars: true,
typeofs: true,
unused: true,
}
input: {
console.log(function() {
var foo = function bar() {};
var baz = function moo() {};
return "function" == typeof bar;
}());
}
expect: {
console.log(function() {
(function bar() {});
return "function" == typeof bar;
}());
}
expect_stdout: "false"
}
issue_3215_1: {
mangle = {
ie8: false,
}
input: {
console.log(function foo() {
var bar = function bar(name) {
return "PASS";
};
try {
"moo";
} catch (e) {
bar = function bar(name) {
return "FAIL";
};
}
return bar;
}()());
}
expect: {
console.log(function n() {
var o = function n(o) {
return "PASS";
};
try {
"moo";
} catch (n) {
o = function n(o) {
return "FAIL";
};
}
return o;
}()());
}
expect_stdout: "PASS"
}
issue_3215_2: {
mangle = {
ie8: true,
}
input: {
console.log(function foo() {
var bar = function bar(name) {
return "PASS";
};
try {
"moo";
} catch (e) {
bar = function bar(name) {
return "FAIL";
};
}
return bar;
}()());
}
expect: {
console.log(function foo() {
var o = function o(n) {
return "PASS";
};
try {
"moo";
} catch (n) {
o = function o(n) {
return "FAIL";
};
}
return o;
}()());
}
expect_stdout: "PASS"
}
issue_3215_3: {
mangle = {
ie8: false,
}
input: {
console.log(function foo() {
var bar = function bar(name) {
return "FAIL";
};
try {
moo;
} catch (e) {
bar = function bar(name) {
return "PASS";
};
}
return bar;
}()());
}
expect: {
console.log(function n() {
var o = function n(o) {
return "FAIL";
};
try {
moo;
} catch (n) {
o = function n(o) {
return "PASS";
};
}
return o;
}()());
}
expect_stdout: "PASS"
}
issue_3215_4: {
mangle = {
ie8: true,
}
input: {
console.log(function foo() {
var bar = function bar(name) {
return "FAIL";
};
try {
moo;
} catch (e) {
bar = function bar(name) {
return "PASS";
};
}
return bar;
}()());
}
expect: {
console.log(function foo() {
var o = function o(n) {
return "FAIL";
};
try {
moo;
} catch (n) {
o = function o(n) {
return "PASS";
};
}
return o;
}()());
}
expect_stdout: "PASS"
}

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() {
@@ -326,3 +326,221 @@ issue_512: {
} }
} }
} }
if_var_return: {
options = {
conditionals: true,
if_return: true,
join_vars: true,
sequences: true,
}
input: {
function f() {
var a;
return;
var b;
}
function g() {
var a;
if (u()) {
var b;
return v();
var c;
}
var d;
if (w()) {
var e;
return x();
var f;
} else {
var g;
y();
var h;
}
var i;
z();
var j;
}
}
expect: {
function f() {
var a, b;
}
function g() {
var a, b, c, d, e, f, g, h, i, j;
return u() ? v() : w() ? x() : (y(), z(), void 0);
}
}
}
if_if_return_return: {
options = {
conditionals: true,
if_return: true,
}
input: {
function f(a, b) {
if (a) {
if (b)
return b;
return;
}
g();
}
}
expect: {
function f(a, b) {
if (a)
return b || void 0;
g();
}
}
}
if_body_return_1: {
options = {
if_return: true,
}
input: {
var c = "PASS";
function f(a, b) {
if (a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect: {
var c = "PASS";
function f(a, b) {
if (a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect_stdout: [
"true",
"true",
"42",
"PASS",
]
}
if_body_return_2: {
options = {
if_return: true,
}
input: {
var c = "PASS";
function f(a, b) {
if (0 + a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect: {
var c = "PASS";
function f(a, b) {
if (0 + a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect_stdout: [
"true",
"true",
"42",
"PASS",
]
}
if_body_return_3: {
options = {
if_return: true,
}
input: {
var c = "PASS";
function f(a, b) {
if (1 == a) {
if (b) throw new Error(c);
return 42;
}
return true;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect: {
var c = "PASS";
function f(a, b) {
if (1 != a) return true;
if (b) throw new Error(c);
return 42;
}
console.log(f(0, 0));
console.log(f(0, 1));
console.log(f(1, 0));
try {
f(1, 1);
console.log("FAIL");
} catch (e) {
console.log(e.message);
}
}
expect_stdout: [
"true",
"true",
"42",
"PASS",
]
}

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:4,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:14,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:17,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:18,21]" "WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:11,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:4,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:48,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:4,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:51,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:51,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:48,20]", "WARN: Dropping unused variable a [test/compress/issue-1034.js:4,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]", "WARN: Dropping unused function nope [test/compress/issue-1034.js:11,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:9,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]", "WARN: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]", "WARN: Dropping unused variable c [test/compress/issue-1034.js:9,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) {
@@ -110,20 +139,28 @@ non_hoisted_function_after_return_2b: {
} }
} }
expect_warnings: [ expect_warnings: [
// duplicate warnings no longer emitted "WARN: Dropping unreachable code [test/compress/issue-1034.js:6,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:6,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:8,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:99,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:99,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:103,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 +190,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:5,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:136,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:8,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:139,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:11,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:140,21]", "WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:12,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 +244,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:5,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:175,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:5,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:178,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:8,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:178,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:175,20]", "WARN: Dropping unused variable a [test/compress/issue-1034.js:5,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:182,21]", "WARN: Dropping unused function nope [test/compress/issue-1034.js:12,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:10,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:180,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:183,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:178,20]", "WARN: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:180,16]", "WARN: Dropping unused variable c [test/compress/issue-1034.js:10,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";
@@ -246,11 +303,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 "WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:229,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:229,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:231,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:231,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:235,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
@@ -48,28 +48,28 @@ pure_function_calls: {
a.b(), f.g(); a.b(), f.g();
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:3,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:16,8]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:3,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:29,37]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:29,16]", "WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:16,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:27,8]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:14,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:37,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:24,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:38,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:25,31]",
] ]
} }
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
@@ -110,17 +110,17 @@ pure_function_calls_toplevel: {
a.b(), f.g(); a.b(), f.g();
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:77,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:3,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:77,8]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:3,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:90,37]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:90,16]", "WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:16,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:88,8]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:14,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:105,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:31,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:106,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:32,31]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:82,33]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:8,33]",
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:82,12]", "WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:8,12]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:98,45]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:24,45]",
"WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:98,12]", "WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:24,12]",
] ]
} }
@@ -155,29 +155,29 @@ should_warn: {
baz(); baz();
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,61]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:1,61]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:1,23]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:135,23]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:1,23]",
"WARN: Boolean || always true [test/compress/issue-1261.js:136,23]", "WARN: Boolean || always true [test/compress/issue-1261.js:2,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:136,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:2,23]",
"WARN: Condition always true [test/compress/issue-1261.js:136,23]", "WARN: Condition always true [test/compress/issue-1261.js:2,23]",
"WARN: Condition left of || always true [test/compress/issue-1261.js:137,8]", "WARN: Condition left of || always true [test/compress/issue-1261.js:3,8]",
"WARN: Condition always true [test/compress/issue-1261.js:137,8]", "WARN: Condition always true [test/compress/issue-1261.js:3,8]",
"WARN: Boolean && always false [test/compress/issue-1261.js:138,23]", "WARN: Boolean && always false [test/compress/issue-1261.js:4,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:138,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:4,23]",
"WARN: Condition always false [test/compress/issue-1261.js:138,23]", "WARN: Condition always false [test/compress/issue-1261.js:4,23]",
"WARN: Condition left of && always false [test/compress/issue-1261.js:139,8]", "WARN: Condition left of && always false [test/compress/issue-1261.js:5,8]",
"WARN: Condition always false [test/compress/issue-1261.js:139,8]", "WARN: Condition always false [test/compress/issue-1261.js:5,8]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:140,23]", "WARN: + in boolean context always true [test/compress/issue-1261.js:6,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:140,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:6,23]",
"WARN: Condition always true [test/compress/issue-1261.js:140,23]", "WARN: Condition always true [test/compress/issue-1261.js:6,23]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:141,8]", "WARN: + in boolean context always true [test/compress/issue-1261.js:7,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:141,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:7,31]",
"WARN: Condition always true [test/compress/issue-1261.js:141,8]", "WARN: Condition always true [test/compress/issue-1261.js:7,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:142,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:8,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:143,24]", "WARN: Condition always true [test/compress/issue-1261.js:9,8]",
"WARN: Condition always true [test/compress/issue-1261.js:143,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:9,24]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:144,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:10,31]",
"WARN: Condition always false [test/compress/issue-1261.js:144,8]", "WARN: Condition always false [test/compress/issue-1261.js:10,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

@@ -4,7 +4,7 @@ unsafe_undefined: {
options = { options = {
conditionals: true, conditionals: true,
if_return: true, if_return: true,
unsafe: true unsafe_undefined: true,
} }
mangle = {} mangle = {}
input: { input: {
@@ -30,7 +30,7 @@ keep_fnames: {
options = { options = {
conditionals: true, conditionals: true,
if_return: true, if_return: true,
unsafe: true unsafe_undefined: 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

@@ -61,7 +61,7 @@ unsafe_undefined: {
options = { options = {
conditionals: true, conditionals: true,
if_return: true, if_return: true,
unsafe: true, unsafe_undefined: true,
} }
mangle = {} mangle = {}
input: { input: {

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

@@ -84,12 +84,12 @@ numeric_literal: {
' 0: 0,', ' 0: 0,',
' "-0": 1,', ' "-0": 1,',
' 42: 2,', ' 42: 2,',
' "42": 3,', ' 42: 3,',
' 37: 4,', ' 37: 4,',
' o: 5,', ' o: 5,',
' 1e42: 6,', ' 1e42: 6,',
' b: 7,', ' b: 7,',
' "1e+42": 8', ' 1e42: 8',
'};', '};',
'', '',
'console.log(obj[-0], obj[-""], obj["-0"]);', 'console.log(obj[-0], obj[-""], obj["-0"]);',

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:1,12]",
'WARN: global_defs FOO redefined [test/compress/issue-208.js:42,12]', "WARN: global_defs FOO redefined [test/compress/issue-208.js:2,12]",
'WARN: global_defs FOO redefined [test/compress/issue-208.js:44,10]', "WARN: global_defs FOO redefined [test/compress/issue-208.js:4,10]",
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:45,8]', "WARN: global_defs DEBUG redefined [test/compress/issue-208.js:5,8]",
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:46,8]', "WARN: global_defs DEBUG redefined [test/compress/issue-208.js:6,8]",
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:47,8]', "WARN: global_defs DEBUG redefined [test/compress/issue-208.js:7,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

@@ -0,0 +1,33 @@
insert_semicolon: {
beautify = {
beautify: true,
comments: "all",
}
input: {
var a
/* foo */ var b
}
expect_exact: [
"var a",
"/* foo */;",
"",
"var b;",
]
}
unary_postfix: {
beautify = {
beautify: true,
comments: "all",
}
input: {
a
/* foo */++b
}
expect_exact: [
"a",
"/* foo */;",
"",
"++b;",
]
}

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'),
@@ -64,3 +72,27 @@ strings_concat: {
); );
} }
} }
regexp: {
options = {
evaluate: true,
unsafe: true,
}
input: {
RegExp("foo");
RegExp("bar", "ig");
RegExp(foo);
RegExp("bar", ig);
RegExp("should", "fail");
}
expect: {
/foo/;
/bar/ig;
RegExp(foo);
RegExp("bar", ig);
RegExp("should", "fail");
}
expect_warnings: [
'WARN: Error converting RegExp("should","fail") [test/compress/issue-269.js:5,2]',
]
}

View File

@@ -0,0 +1,32 @@
warn: {
options = {
evaluate: true,
inline: true,
passes: 2,
properties: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {
return g();
}
function g() {
return g["call" + "er"].arguments;
}
// 3
console.log(f(1, 2, 3).length);
}
expect: {
// TypeError: Cannot read property 'arguments' of null
console.log(function g() {
return g.caller.arguments;
}().length);
}
expect_warnings: [
"WARN: Function.prototype.caller not supported [test/compress/issue-2719.js:5,19]",
"WARN: Function.prototype.arguments not supported [test/compress/issue-2719.js:5,19]",
]
}

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,37 @@
comparison_with_undefined: {
options = {
comparisons: true,
}
input: {
a == undefined;
a != undefined;
a === undefined;
a !== undefined;
undefined == a;
undefined != a;
undefined === a;
undefined !== a;
void 0 == a;
void 0 != a;
void 0 === a;
void 0 !== a;
}
expect: {
null == a;
null != a;
void 0 === a;
void 0 !== a;
null == a;
null != a;
void 0 === a;
void 0 !== a;
null == a;
null != a;
void 0 === a;
void 0 !== a;
}
}

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);
@@ -492,3 +516,133 @@ dead_code_condition: {
} }
expect_stdout: "1" expect_stdout: "1"
} }
issue_2740_1: {
options = {
dead_code: true,
loops: true,
}
input: {
for (; ; ) break;
for (a(); ; ) break;
for (; b(); ) break;
for (c(); d(); ) break;
for (; ; e()) break;
for (f(); ; g()) break;
for (; h(); i()) break;
for (j(); k(); l()) break;
}
expect: {
a();
b();
c();
d();
f();
h();
j();
k();
}
}
issue_2740_2: {
options = {
dead_code: true,
loops: true,
passes: 2,
}
input: {
L1: while (x()) {
break L1;
}
}
expect: {
x();
}
}
issue_2740_3: {
options = {
dead_code: true,
loops: true,
}
input: {
L1: for (var x = 0; x < 3; x++) {
L2: for (var y = 0; y < 2; y++) {
break L1;
}
}
console.log(x, y);
}
expect: {
L1: for (var x = 0; x < 3; x++)
for (var y = 0; y < 2; y++)
break L1;
console.log(x, y);
}
expect_stdout: "0 0"
}
issue_2740_4: {
options = {
dead_code: true,
loops: true,
passes: 2,
}
input: {
L1: for (var x = 0; x < 3; x++) {
L2: for (var y = 0; y < 2; y++) {
break L2;
}
}
console.log(x, y);
}
expect: {
for (var x = 0; x < 3; x++) {
var y = 0;
y < 2;
}
console.log(x, y);
}
expect_stdout: "3 0"
}
issue_2740_5: {
options = {
dead_code: true,
loops: true,
passes: 2,
}
input: {
L1: for (var x = 0; x < 3; x++) {
break L1;
L2: for (var y = 0; y < 2; y++) {
break L2;
}
}
console.log(x, y);
}
expect: {
var x = 0;
x < 3;
var y;
console.log(x,y);
}
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

@@ -0,0 +1,181 @@
return_1: {
beautify = {
beautify: false,
preserve_line: true,
}
input: {
console.log(function f() {
return (
f.toString() != 42
);
}());
}
expect_exact: [
"console.log(function f(){",
"",
"return 42!=f.toString()}());",
]
expect_stdout: "true"
}
return_2: {
beautify = {
beautify: true,
preserve_line: true,
}
input: {
console.log(function f() {
return (
f.toString() != 42
);
}());
}
expect_exact: [
"console.log(function f() {",
"",
" return 42 != f.toString();",
"}());",
]
expect_stdout: "true"
}
return_3: {
options = {}
beautify = {
beautify: false,
preserve_line: true,
}
input: {
console.log(function f() {
return (
f.toString() != 42
);
}());
}
expect_exact: [
"console.log(function f(){",
"",
"return 42!=f.toString()}());",
]
expect_stdout: "true"
}
return_4: {
options = {}
beautify = {
beautify: true,
preserve_line: true,
}
input: {
console.log(function f() {
return (
f.toString() != 42
);
}());
}
expect_exact: [
"console.log(function f() {",
"",
" return 42 != f.toString();",
"}());",
]
expect_stdout: "true"
}
return_5: {
beautify = {
beautify: false,
preserve_line: true,
}
input: {
_is_selected = function(tags, slug) {
var ref;
return (ref = _.find(tags, {
slug: slug
})) != null ? ref.selected : void 0;
};
}
expect_exact: [
"_is_selected=function(tags,slug){",
"var ref",
"",
"",
";return null!=(ref=_.find(tags,{slug:slug}))?ref.selected:void 0};",
]
}
return_6: {
beautify = {
beautify: true,
preserve_line: true,
}
input: {
_is_selected = function(tags, slug) {
var ref;
return (ref = _.find(tags, {
slug: slug
})) != null ? ref.selected : void 0;
};
}
expect_exact: [
"_is_selected = function(tags, slug) {",
" var ref;",
"",
"",
" return null != (ref = _.find(tags, {",
" slug: slug",
" })) ? ref.selected : void 0;",
"};",
]
}
return_7: {
options = {}
mangle = {}
beautify = {
beautify: false,
preserve_line: true,
}
input: {
_is_selected = function(tags, slug) {
var ref;
return (ref = _.find(tags, {
slug: slug
})) != null ? ref.selected : void 0;
};
}
expect_exact: [
"_is_selected=function(e,l){",
"var n",
"",
"",
";return null!=(n=_.find(e,{slug:l}))?n.selected:void 0};",
]
}
return_8: {
options = {}
mangle = {}
beautify = {
beautify: true,
preserve_line: true,
}
input: {
_is_selected = function(tags, slug) {
var ref;
return (ref = _.find(tags, {
slug: slug
})) != null ? ref.selected : void 0;
};
}
expect_exact: [
"_is_selected = function(e, l) {",
" var n;",
"",
"",
" return null != (n = _.find(e, {",
" slug: l",
" })) ? n.selected : void 0;",
"};",
]
}

View File

@@ -567,16 +567,41 @@ native_prototype: {
} }
input: { input: {
Array.prototype.splice.apply(a, [1, 2, b, c]); Array.prototype.splice.apply(a, [1, 2, b, c]);
Function.prototype.call.apply(console.log, console, [ "foo" ]);
Number.prototype.toFixed.call(Math.PI, 2);
Object.prototype.hasOwnProperty.call(d, "foo"); Object.prototype.hasOwnProperty.call(d, "foo");
RegExp.prototype.test.call(/foo/, "bar");
String.prototype.indexOf.call(e, "bar"); String.prototype.indexOf.call(e, "bar");
} }
expect: { expect: {
[].splice.apply(a, [1, 2, b, c]); [].splice.apply(a, [1, 2, b, c]);
(function() {}).call.apply(console.log, console, [ "foo" ]);
0..toFixed.call(Math.PI, 2);
({}).hasOwnProperty.call(d, "foo"); ({}).hasOwnProperty.call(d, "foo");
/t/.test.call(/foo/, "bar");
"".indexOf.call(e, "bar"); "".indexOf.call(e, "bar");
} }
} }
native_prototype_lhs: {
options = {
unsafe_proto: true,
}
input: {
console.log(function() {
Function.prototype.bar = "PASS";
return function() {};
}().bar);
}
expect: {
console.log(function() {
Function.prototype.bar = "PASS";
return function() {};
}().bar);
}
expect_stdout: "PASS"
}
accessor_boolean: { accessor_boolean: {
input: { input: {
var a = 1; var a = 1;
@@ -1094,3 +1119,746 @@ const_prop_assign_pure: {
x(); x();
} }
} }
join_object_assignments_1: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function() {
var x = {
a: 1,
c: (console.log("c"), "C"),
};
x.b = 2;
x[3] = function() {
console.log(x);
},
x["a"] = /foo/,
x.bar = x;
return x;
}());
}
expect: {
console.log(function() {
var x = {
a: 1,
c: (console.log("c"), "C"),
b: 2,
3: function() {
console.log(x);
},
a: /foo/,
};
x.bar = x;
return x;
}());
}
expect_stdout: true
}
join_object_assignments_2: {
options = {
evaluate: true,
hoist_props: true,
join_vars: true,
passes: 3,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
foo: 1,
};
o.bar = 2;
o.baz = 3;
console.log(o.foo, o.bar + o.bar, o.foo * o.bar * o.baz);
}
expect: {
console.log(1, 4, 6);
}
expect_stdout: "1 4 6"
}
join_object_assignments_3: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function() {
var o = {
a: "PASS",
}, a = o.a;
o.a = "FAIL";
return a;
}());
}
expect: {
console.log(function() {
var o = {
a: "PASS",
}, a = o.a;
o.a = "FAIL";
return a;
}());
}
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: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
return o.q = "foo";
}());
}
expect: {
console.log(function() {
var o = {
p: 3,
q: "foo"
};
return o.q;
}());
}
expect_stdout: "foo"
}
join_object_assignments_return_2: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
return o.q = /foo/,
o.r = "bar";
}());
}
expect: {
console.log(function() {
var o = {
p: 3,
q: /foo/,
r: "bar"
};
return o.r;
}());
}
expect_stdout: "bar"
}
join_object_assignments_return_3: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
return o.q = "foo",
o.p += "",
console.log(o.q),
o.p;
}());
}
expect: {
console.log(function() {
var o = {
p: 3,
q: "foo"
};
return o.p += "",
console.log(o.q),
o.p;
}());
}
expect_stdout: [
"foo",
"3",
]
}
join_object_assignments_for: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
for (o.q = "foo"; console.log(o.q););
return o.p;
}());
}
expect: {
console.log(function() {
for (var o = {
p: 3,
q: "foo"
}; console.log(o.q););
return o.p;
}());
}
expect_stdout: [
"foo",
"3",
]
}
join_object_assignments_if: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {};
if (o.a = "PASS") return o.a;
}())
}
expect: {
console.log(function() {
var o = { a: "PASS" };
if (o.a) return o.a;
}());
}
expect_stdout: "PASS"
}
join_object_assignments_forin: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {};
for (var a in o.a = "PASS", o)
return o[a];
}())
}
expect: {
console.log(function() {
var o = { a: "PASS" };
for (var a in o)
return o[a];
}());
}
expect_stdout: "PASS"
}
join_object_assignments_negative: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[0] = 0;
o[-0] = 1;
o[-1] = 2;
console.log(o[0], o[-0], o[-1]);
}
expect: {
var o = {
0: 0,
0: 1,
"-1": 2
};
console.log(o[0], o[-0], o[-1]);
}
expect_stdout: "1 1 2"
}
join_object_assignments_NaN_1: {
options = {
join_vars: true,
}
input: {
var o = {};
o[NaN] = 1;
o[0/0] = 2;
console.log(o[NaN], o[NaN]);
}
expect: {
var o = {};
o[NaN] = 1;
o[0/0] = 2;
console.log(o[NaN], o[NaN]);
}
expect_stdout: "2 2"
}
join_object_assignments_NaN_2: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[NaN] = 1;
o[0/0] = 2;
console.log(o[NaN], o[NaN]);
}
expect: {
var o = {
NaN: 1,
NaN: 2
};
console.log(o.NaN, o.NaN);
}
expect_stdout: "2 2"
}
join_object_assignments_null_0: {
options = {
join_vars: true,
}
input: {
var o = {};
o[null] = 1;
console.log(o[null]);
}
expect: {
var o = {};
o[null] = 1;
console.log(o[null]);
}
expect_stdout: "1"
}
join_object_assignments_null_1: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[null] = 1;
console.log(o[null]);
}
expect: {
var o = {
null: 1
};
console.log(o.null);
}
expect_stdout: "1"
}
join_object_assignments_void_0: {
options = {
evaluate: true,
join_vars: true,
}
input: {
var o = {};
o[void 0] = 1;
console.log(o[void 0]);
}
expect: {
var o = {
undefined: 1
};
console.log(o[void 0]);
}
expect_stdout: "1"
}
join_object_assignments_undefined_1: {
options = {
join_vars: true,
}
input: {
var o = {};
o[undefined] = 1;
console.log(o[undefined]);
}
expect: {
var o = {};
o[void 0] = 1;
console.log(o[void 0]);
}
expect_stdout: "1"
}
join_object_assignments_undefined_2: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[undefined] = 1;
console.log(o[undefined]);
}
expect: {
var o = {
undefined : 1
};
console.log(o[void 0]);
}
expect_stdout: "1"
}
join_object_assignments_Infinity: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[Infinity] = 1;
o[1/0] = 2;
o[-Infinity] = 3;
o[-1/0] = 4;
console.log(o[Infinity], o[1/0], o[-Infinity], o[-1/0]);
}
expect: {
var o = {
Infinity: 1,
Infinity: 2,
"-Infinity": 3,
"-Infinity": 4
};
console.log(o[1/0], o[1/0], o[-1/0], o[-1/0]);
}
expect_stdout: "2 2 4 4"
}
join_object_assignments_regex: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[/rx/] = 1;
console.log(o[/rx/]);
}
expect: {
var o = {
"/rx/": 1
};
console.log(o[/rx/]);
}
expect_stdout: "1"
}
issue_2816: {
options = {
join_vars: true,
}
input: {
"use strict";
var o = {
a: 1
};
o.b = 2;
o.a = 3;
o.c = 4;
console.log(o.a, o.b, o.c);
}
expect: {
"use strict";
var o = {
a: 1,
b: 2
};
o.a = 3;
o.c = 4;
console.log(o.a, o.b, o.c);
}
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"
}
join_expr: {
options = {
evaluate: true,
join_vars: true,
}
input: {
var c = "FAIL";
(function() {
var a = 0;
switch ((a = {}) && (a.b = 0)) {
case 0:
c = "PASS";
}
})();
console.log(c);
}
expect: {
var c = "FAIL";
(function() {
var a = 0;
switch (a = { b: 0 }, a.b) {
case 0:
c = "PASS";
}
})();
console.log(c);
}
expect_stdout: "PASS"
}

View File

@@ -414,3 +414,269 @@ issue_2638: {
"/* */(a()||b())(c(),d());", "/* */(a()||b())(c(),d());",
] ]
} }
issue_2705_1: {
options = {
side_effects: true,
}
beautify = {
comments: "all",
}
input: {
/*@__PURE__*/ new a();
/*@__PURE__*/ (new b());
new (/*@__PURE__*/ c)();
(/*@__PURE__*/ new d());
}
expect_exact: [
"new/* */c;",
]
}
issue_2705_2: {
options = {
side_effects: true,
}
beautify = {
comments: "all",
}
input: {
/*@__PURE__*/ new a(1)(2)(3);
/*@__PURE__*/ new (b(1))(2)(3);
/*@__PURE__*/ new (c(1)(2))(3);
/*@__PURE__*/ new (d(1)(2)(3));
new (/*@__PURE__*/ e)(1)(2)(3);
(/*@__PURE__*/ new f(1))(2)(3);
(/*@__PURE__*/ new g(1)(2))(3);
(/*@__PURE__*/ new h(1)(2)(3));
}
expect_exact: [
"new/* */e(1)(2)(3);",
"/* */new f(1)(2)(3);",
"/* */new g(1)(2)(3);",
]
}
issue_2705_3: {
options = {
side_effects: true,
}
beautify = {
comments: "all",
}
input: {
/*@__PURE__*/ new a.x(1).y(2).z(3);
/*@__PURE__*/ new (b.x)(1).y(2).z(3);
/*@__PURE__*/ new (c.x(1)).y(2).z(3);
/*@__PURE__*/ new (d.x(1).y)(2).z(3);
/*@__PURE__*/ new (e.x(1).y(2)).z(3);
/*@__PURE__*/ new (f.x(1).y(2).z)(3);
/*@__PURE__*/ new (g.x(1).y(2).z(3));
new (/*@__PURE__*/ h).x(1).y(2).z(3);
/* */ new (/*@__PURE__*/ i.x)(1).y(2).z(3);
(/*@__PURE__*/ new j.x(1)).y(2).z(3);
(/*@__PURE__*/ new k.x(1).y)(2).z(3);
(/*@__PURE__*/ new l.x(1).y(2)).z(3);
(/*@__PURE__*/ new m.x(1).y(2).z)(3);
(/*@__PURE__*/ new n.x(1).y(2).z(3));
}
expect_exact: [
"new/* */h.x(1).y(2).z(3);",
"/* */new/* */i.x(1).y(2).z(3);",
"/* */new j.x(1).y(2).z(3);",
"/* */new k.x(1).y(2).z(3);",
"/* */new l.x(1).y(2).z(3);",
"/* */new m.x(1).y(2).z(3);",
]
}
issue_2705_4: {
options = {
side_effects: true,
}
input: {
(/*@__PURE__*/ new x(), y());
(w(), /*@__PURE__*/ new x(), y());
}
expect: {
y();
w(), y();
}
}
issue_2705_5: {
options = {
side_effects: true,
}
input: {
[ /*@__PURE__*/ new x() ];
[ /*@__PURE__*/ new x(), y() ];
[ w(), /*@__PURE__*/ new x(), y() ];
}
expect: {
y();
w(), y();
}
}
issue_2705_6: {
options = {
side_effects: true,
}
beautify = {
comments: "all",
}
input: {
/*@__PURE__*/new (g() || h())(x(), y());
/* */ new (/*@__PURE__*/ (a() || b()))(c(), d());
}
expect_exact: [
"/* */x(),y();",
"/* */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");
})();
}
}
issue_3325_1: {
options = {
pure_funcs: "cb",
side_effects: true,
}
input: {
function cb() {
console.log("PASS");
}
cb();
}
expect: {
function cb() {
console.log("PASS");
}
}
}
issue_3325_2: {
options = {
pure_funcs: "xxxcbxxx",
side_effects: true,
}
input: {
function cb() {
console.log("PASS");
}
cb();
}
expect: {
function cb() {
console.log("PASS");
}
cb();
}
expect_stdout: "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: {
@@ -348,6 +348,57 @@ set_immutable_4: {
expect_stdout: true expect_stdout: true
} }
set_immutable_5: {
options = {
collapse_vars: true,
conditionals: true,
evaluate: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var a = 1;
a.foo += "";
if (a.foo) console.log("FAIL");
else console.log("PASS");
}
expect: {
"use strict";
1..foo += "";
1..foo ? console.log("FAIL") : console.log("PASS");
}
expect_stdout: true
}
set_immutable_6: {
options = {
collapse_vars: true,
conditionals: true,
evaluate: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = 1;
a.foo += "";
if (a.foo) console.log("FAIL");
else console.log("PASS");
}
expect: {
1..foo ? console.log("FAIL") : console.log("PASS");
}
expect_stdout: true
}
set_mutable_1: { set_mutable_1: {
options = { options = {
collapse_vars: true, collapse_vars: true,
@@ -611,3 +662,502 @@ issue_2313_6: {
x(); x();
} }
} }
issue_2678: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
var a = 1, c = "FAIL";
(function f() {
(a-- && f()).p;
return {
get p() {
c = "PASS";
}
};
})();
console.log(c);
}
expect: {
var a = 1, c = "FAIL";
(function f() {
(a-- && f()).p;
return {
get p() {
c = "PASS";
}
};
})();
console.log(c);
}
expect_stdout: "PASS"
}
issue_2838: {
options = {
pure_getters: true,
side_effects: true,
}
input: {
function f(a, b) {
(a || b).c = "PASS";
(function() {
return f(a, b);
}).prototype.foo = "bar";
}
var o = {};
f(null, o);
console.log(o.c);
}
expect: {
function f(a, b) {
(a || b).c = "PASS";
}
var o = {};
f(null, o);
console.log(o.c);
}
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",
@@ -534,3 +534,80 @@ function_catch_catch_ie8: {
"undefined", "undefined",
] ]
} }
function_do_catch_ie8: {
rename = true
options = {
ie8: true,
side_effects: true,
unused: true,
}
mangle = {
ie8: true,
toplevel: true,
}
input: {
var a = 1, b = 1, c = 0;
function d(e) {
var f, g, h, i;
do {
try {
try {
var j = function q(){}();
} catch (r) {
--a && w("ddddddddeeeeeeegggggggggiiiiilllllllnnnnntuuuuuuuuyyyyyyy");
var k, l, m, n, o;
--m;
--n;
--o;
}
try {
i[1];
} catch (s) {
var p;
switch (function t() {
c++;
}()) {
case j + --p:
}
}
} catch (u) {}
} while (--i);
b--;
}
d();
console.log(b, c);
}
expect: {
var t = 1, u = 1, y = 0;
function c(c) {
var d;
do {
try {
try {
var e = void 0;
} catch (i) {
--t && w("ddddddddeeeeeeegggggggggiiiiilllllllnnnnntuuuuuuuuyyyyyyy");
0;
0;
0;
}
try {
d[1];
} catch (l) {
var g;
switch(function x() {
y++;
}()) {
case e + --g:
}
}
} catch (n) {}
} while (--d);
u--;
}
c();
console.log(u, y);
}
expect_stdout: "0 1"
}

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,394 +0,0 @@
do_screw: {
options = {
ie8: false,
}
beautify = {
ie8: false,
ascii_only: true,
}
input: {
f("\v");
}
expect_exact: 'f("\\v");'
}
dont_screw: {
options = {
ie8: true,
}
beautify = {
ie8: true,
ascii_only: true,
}
input: {
f("\v");
}
expect_exact: 'f("\\x0B");'
}
do_screw_constants: {
options = {
ie8: false,
}
input: {
f(undefined, Infinity);
}
expect_exact: "f(void 0,1/0);"
}
dont_screw_constants: {
options = {
ie8: true,
}
input: {
f(undefined, Infinity);
}
expect_exact: "f(undefined,Infinity);"
}
do_screw_try_catch: {
options = {
ie8: false,
}
mangle = {
ie8: false,
}
beautify = {
ie8: false,
}
input: {
good = function(e){
return function(error){
try{
e()
} catch(e) {
error(e)
}
}
};
}
expect: {
good = function(n){
return function(t){
try{
n()
} catch(n) {
t(n)
}
}
};
}
}
dont_screw_try_catch: {
options = {
ie8: true,
}
mangle = {
ie8: true,
}
beautify = {
ie8: true,
}
input: {
bad = function(e){
return function(error){
try{
e()
} catch(e) {
error(e)
}
}
};
}
expect: {
bad = function(n){
return function(t){
try{
n()
} catch(n) {
t(n)
}
}
};
}
}
do_screw_try_catch_undefined: {
options = {
ie8: false,
}
mangle = {
ie8: false,
}
beautify = {
ie8: false,
}
input: {
function a(b){
try {
throw 'Stuff';
} catch (undefined) {
console.log('caught: ' + undefined);
}
console.log('undefined is ' + undefined);
return b === undefined;
};
}
expect: {
function a(o){
try{
throw "Stuff"
} catch (o) {
console.log("caught: "+o)
}
console.log("undefined is " + void 0);
return void 0===o
}
}
expect_stdout: true
}
dont_screw_try_catch_undefined: {
options = {
ie8: true,
}
mangle = {
ie8: true,
}
beautify = {
ie8: true,
}
input: {
function a(b){
try {
throw 'Stuff';
} catch (undefined) {
console.log('caught: ' + undefined);
}
console.log('undefined is ' + undefined);
return b === undefined;
};
}
expect: {
function a(n){
try{
throw "Stuff"
} catch (undefined) {
console.log("caught: " + undefined)
}
console.log("undefined is " + undefined);
return n === undefined
}
}
expect_stdout: true
}
reduce_vars: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
ie8: true,
unused: true,
}
mangle = {
ie8: true,
}
input: {
function f() {
var a;
try {
x();
} catch (a) {
y();
}
alert(a);
}
}
expect: {
function f() {
var t;
try {
x();
} catch (t) {
y();
}
alert(t);
}
}
}
issue_1586_1: {
options = {
ie8: true,
}
mangle = {
ie8: true,
}
input: {
function f() {
try {
x();
} catch (err) {
console.log(err.message);
}
}
}
expect_exact: "function f(){try{x()}catch(c){console.log(c.message)}}"
}
issue_1586_2: {
options = {
ie8: false,
}
mangle = {
ie8: false,
}
input: {
function f() {
try {
x();
} catch (err) {
console.log(err.message);
}
}
}
expect_exact: "function f(){try{x()}catch(c){console.log(c.message)}}"
}
issue_2120_1: {
mangle = {
ie8: false,
}
input: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (t) {
try {
throw 0;
} catch (a) {
if (t) b = "PASS";
}
}
console.log(b);
}
expect_stdout: "PASS"
}
issue_2120_2: {
mangle = {
ie8: true,
}
input: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect_stdout: "PASS"
}
issue_2254_1: {
mangle = {
ie8: false,
}
input: {
"eeeeee";
try {
console.log(f("PASS"));
} catch (e) {}
function f(s) {
try {
throw "FAIL";
} catch (e) {
return s;
}
}
}
expect: {
"eeeeee";
try {
console.log(f("PASS"));
} catch (e) {}
function f(e) {
try {
throw "FAIL";
} catch (t) {
return e;
}
}
}
expect_stdout: "PASS"
}
issue_2254_2: {
mangle = {
ie8: true,
}
input: {
"eeeeee";
try {
console.log(f("PASS"));
} catch (e) {}
function f(s) {
try {
throw "FAIL";
} catch (e) {
return s;
}
}
}
expect: {
"eeeeee";
try {
console.log(f("PASS"));
} catch (e) {}
function f(t) {
try {
throw "FAIL";
} catch (e) {
return t;
}
}
}
expect_stdout: "PASS"
}

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() {})();
@@ -288,7 +300,7 @@ unsafe_undefined: {
if_return: true, if_return: true,
sequences: true, sequences: true,
side_effects: true, side_effects: true,
unsafe: true, unsafe_undefined: true,
} }
input: { input: {
function f(undefined) { function f(undefined) {
@@ -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;
} }
} }
@@ -796,3 +807,160 @@ cascade_assignment_in_return: {
} }
} }
} }
hoist_defun: {
options = {
join_vars: true,
sequences: true,
}
input: {
x();
function f() {}
y();
}
expect: {
function f() {}
x(), y();
}
}
hoist_decl: {
options = {
join_vars: true,
sequences: true,
}
input: {
var a;
w();
var b = x();
y();
for (var c; 0;) z();
var d;
}
expect: {
var a;
w();
var b = x(), c, d;
for (y(); 0;) z();
}
}
for_init_var: {
options = {
join_vars: true,
unused: false,
}
input: {
var a = "PASS";
(function() {
var b = 42;
for (var c = 5; c > 0;) c--;
a = "FAIL";
var a;
})();
console.log(a);
}
expect: {
var a = "PASS";
(function() {
for (var b = 42, c = 5, a; c > 0;) c--;
a = "FAIL";
})();
console.log(a);
}
expect_stdout: "PASS"
}
forin: {
options = {
sequences: true,
}
input: {
var o = [];
o.push("PASS");
for (var a in o)
console.log(o[a]);
}
expect: {
var o = [];
for (var a in o.push("PASS"), o)
console.log(o[a]);
}
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");
},
b(),
(a, b.c)(),
function() {
console.log(this === a);
}(),
new b(),
new b.c(),
new function() {
console.log(this === a);
}();
}
expect_stdout: [
"foo",
"baz",
"true",
"foo",
"baz",
"false",
]
}
missing_link: {
options = {
conditionals: true,
evaluate: true,
sequences: true,
}
input: {
var a = 100;
a;
a++ + (0 ? 2 : 1);
console.log(a);
}
expect: {
var a = 100;
a,
a++,
console.log(a);
}
}

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,16 +90,10 @@ 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(); h();
} }
expect_stdout: [ expect_stdout: [
@@ -138,3 +132,166 @@ typeof_defun_2: {
"2", "2",
] ]
} }
duplicate_defun_arg_name: {
options = {
evaluate: true,
reduce_vars: true,
typeofs: true,
}
input: {
function long_name(long_name) {
return typeof long_name;
}
console.log(typeof long_name, long_name());
}
expect: {
function long_name(long_name) {
return typeof long_name;
}
console.log(typeof long_name, long_name());
}
expect_stdout: "function undefined"
}
duplicate_lambda_arg_name: {
options = {
evaluate: true,
reduce_vars: true,
typeofs: true,
}
input: {
console.log(function long_name(long_name) {
return typeof long_name;
}());
}
expect: {
console.log(function long_name(long_name) {
return typeof long_name;
}());
}
expect_stdout: "undefined"
}
issue_2728_1: {
options = {
evaluate: true,
reduce_vars: true,
typeofs: true,
}
input: {
(function arguments() {
console.log(typeof arguments);
})();
}
expect: {
(function arguments() {
console.log(typeof arguments);
})();
}
expect_stdout: "object"
}
issue_2728_2: {
options = {
evaluate: true,
reduce_vars: true,
typeofs: true,
}
input: {
function arguments() {
return typeof arguments;
}
console.log(typeof arguments, arguments());
}
expect: {
function arguments() {
return typeof arguments;
}
console.log(typeof arguments, arguments());
}
expect_stdout: "function object"
}
issue_2728_3: {
options = {
evaluate: true,
reduce_vars: true,
typeofs: true,
}
input: {
(function() {
function arguments() {
}
console.log(typeof arguments);
})();
}
expect: {
(function() {
function arguments() {
}
console.log("function");
})();
}
expect_stdout: "function"
}
issue_2728_4: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
typeofs: true,
}
input: {
function arguments() {
}
console.log(typeof arguments);
}
expect: {
function arguments() {
}
console.log("function");
}
expect_stdout: "function"
}
issue_2728_5: {
options = {
evaluate: true,
reduce_vars: true,
typeofs: true,
}
input: {
(function arguments(arguments) {
console.log(typeof arguments);
})();
}
expect: {
(function arguments(arguments) {
console.log(typeof arguments);
})();
}
expect_stdout: "undefined"
}
issue_2728_6: {
options = {
evaluate: true,
reduce_vars: true,
typeofs: true,
}
input: {
function arguments(arguments) {
return typeof arguments;
}
console.log(typeof arguments, arguments());
}
expect: {
function arguments(arguments) {
return typeof arguments;
}
console.log(typeof arguments, arguments());
}
expect_stdout: "function undefined"
}

View File

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

109
test/compress/webkit.js Normal file
View File

@@ -0,0 +1,109 @@
lambda_call_dot_assign: {
beautify = {
webkit: false,
}
input: {
console.log(function() {
return {};
}().a = 1);
}
expect_exact: "console.log(function(){return{}}().a=1);"
expect_stdout: "1"
}
lambda_call_dot_assign_webkit: {
beautify = {
webkit: true,
}
input: {
console.log(function() {
return {};
}().a = 1);
}
expect_exact: "console.log((function(){return{}}()).a=1);"
expect_stdout: "1"
}
lambda_dot_assign: {
beautify = {
webkit: false,
}
input: {
console.log(function() {
1 + 1;
}.a = 1);
}
expect_exact: "console.log(function(){1+1}.a=1);"
expect_stdout: "1"
}
lambda_dot_assign_webkit: {
beautify = {
webkit: true,
}
input: {
console.log(function() {
1 + 1;
}.a = 1);
}
expect_exact: "console.log((function(){1+1}).a=1);"
expect_stdout: "1"
}
lambda_name_mangle: {
mangle = {}
input: {
console.log(typeof function foo(bar) {});
}
expect_exact: "console.log(typeof function o(n){});"
expect_stdout: "function"
}
lambda_name_mangle_ie8: {
mangle = {
ie8: true,
toplevel: true,
}
input: {
console.log(typeof function foo(bar) {});
}
expect_exact: "console.log(typeof function n(o){});"
expect_stdout: "function"
}
function_name_mangle: {
options = {
keep_fnames: true,
reduce_vars: true,
unused: true,
}
mangle = {}
input: {
(function() {
function foo(bar) {}
console.log(typeof foo);
})();
}
expect_exact: "(function(){console.log(typeof function o(n){})})();"
expect_stdout: "function"
}
function_name_mangle_ie8: {
options = {
keep_fnames: true,
reduce_vars: true,
unused: true,
}
mangle = {
ie8: true,
toplevel: true,
}
input: {
(function() {
function foo(bar) {}
console.log(typeof foo);
})();
}
expect_exact: "(function(){console.log(typeof function n(o){})})();"
expect_stdout: "function"
}

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();
})(); })();
} }

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