Compare commits

...

631 Commits

Author SHA1 Message Date
Alex Lam S.L
a7a7b1daed v3.5.2 2019-03-23 14:25:14 +08:00
Alex Lam S.L
7436977aa5 fix infinite loop triggered by #3347 (#3354)
fixes #3353
2019-03-23 14:21:54 +08:00
Alex Lam S.L
e3c565b46f v3.5.1 2019-03-21 13:54:14 +08:00
Alex Lam S.L
54b0b49b68 enhance inline (#3352) 2019-03-21 02:58:33 +08:00
Alex Lam S.L
65648d84a5 enhance collapse_vars (#3351) 2019-03-20 23:31:21 +08:00
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
Alex Lam S.L
8701a99a15 v3.3.1 2017-12-25 03:08:28 +08:00
Alex Lam S.L
1476c78b53 add html-minifier to benchmarks (#2646) 2017-12-25 03:07:46 +08:00
Alex Lam S.L
cb6a92892f fix infinite loop during inline (#2645)
fixes #2644
2017-12-25 01:57:11 +08:00
Alex Lam S.L
f1556cb945 v3.3.0 2017-12-24 17:34:56 +08:00
Alex Lam S.L
efffb81735 fix comments output & improve /*@__PURE__*/
- fix whitespace around comments
- fix comment parsing around parentheses
- consider parentheses when parsing `/*@__PURE__*/`
- remove all `/*@__PURE__*/` on output

fixes #2638
2017-12-24 12:38:45 +08:00
Alex Lam S.L
202f90ef8f fix corner cases with collapse_vars, inline & reduce_vars (#2637)
fixes #2630
2017-12-24 01:24:12 +08:00
Alex Lam S.L
c07ea17c01 fix escape analysis on AST_PropAccess (#2636) 2017-12-24 00:36:46 +08:00
Alex Lam S.L
edb4e3bd52 make comments output more robust (#2633)
- improve handling of comments right after `return`
- retain comments after `OutputStream`
- preserve trailing comments
- fix handling of new line before comments
- handle comments around parentheses

fixes #88
fixes #112
fixes #218
fixes #372
fixes #2629
2017-12-22 04:59:54 +08:00
Alex Lam S.L
4113609dd4 extend test/ufuzz.js to inline & reduce_funcs (#2620)
- forward call `fN()`
- allow forward call functions to be single-use
- avoid generating `AST_Defun` within blocks
2017-12-20 23:52:18 +08:00
Alex Lam S.L
7ac7b0872f remove AST hack from inline (#2627) 2017-12-20 17:05:53 +08:00
Alex Lam S.L
86ae5881b7 disable hoist_funs by default (#2626) 2017-12-20 17:05:40 +08:00
Alex Lam S.L
fac003c64f avoid inline of function with special argument names (#2625) 2017-12-20 02:48:04 +08:00
Alex Lam S.L
2273655c17 fix inline after single-use reduce_vars (#2623) 2017-12-19 22:19:33 +08:00
Ondřej Španěl
01057cf76d Transform can be simplified when clone is not done. (#2621) 2017-12-19 17:56:16 +08:00
Alex Lam S.L
032f096b7f add test for #2613 (#2618) 2017-12-19 05:22:05 +08:00
Alex Lam S.L
4b334edf49 handle global constant collision with local variable after inline (#2617)
fixes #2616
2017-12-19 03:05:30 +08:00
Alex Lam S.L
8ddcbc39e6 compress apply() & call() of function (#2613)
- `fn.apply(a, [ ... ])` => `fn.call(a, ...)`
- `fn.call(a, ... )` => `a, fn(...)`

where `fn` can be `function` literal or symbol reference linked through `reduce_vars`
2017-12-18 16:23:39 +08:00
Alex Lam S.L
0b0eac1d5d drop property assignment to constants (#2612) 2017-12-18 12:07:53 +08:00
Alex Lam S.L
b29fc8b27c improve transversal efficiency in collapse_vars (#2611)
fixes #2603
2017-12-18 03:00:05 +08:00
Alex Lam S.L
5de369fa67 export parse() (#2608) 2017-12-17 23:12:23 +08:00
Alex Lam S.L
7918a50d52 improve reset_opt_flags() (#2610) 2017-12-17 23:01:08 +08:00
Alex Lam S.L
21794c9b8d account for catch variable when inline (#2605)
fixes #2604
2017-12-16 15:21:09 +08:00
Alex Lam S.L
6c686ce593 fix nested inline (#2602)
fixes #2601
2017-12-16 02:16:35 +08:00
Alex Lam S.L
db902af4c6 fix escape analysis on || and && (#2600)
fixes #2598
2017-12-15 19:48:14 +08:00
Alex Lam S.L
7d6907cb99 fix dead_code on nested try (#2599)
fixes #2597
2017-12-15 19:41:28 +08:00
Alex Lam S.L
092d9affb8 fix reduce_vars on do...while (#2596) 2017-12-15 16:33:19 +08:00
Alex Lam S.L
8f681b1d17 handle inline of function arguments (#2590)
fixes #2476
2017-12-15 13:28:30 +08:00
Alex Lam S.L
90313875f7 inline single-use function across loop (#2594) 2017-12-14 19:24:54 +08:00
Alex Lam S.L
3f18a61532 fix reduce_vars on single AST_Defun reference across loop (#2593) 2017-12-14 18:47:05 +08:00
Alex Lam S.L
02a6ce07eb improve reduce_vars (#2592)
- account for hoisting nature of `var`
2017-12-14 15:32:13 +08:00
Alex Lam S.L
738fd52bc4 improve collapse_vars (#2591)
- handle single-use assignments other than `AST_VarDef`
- scan `AST_Call` for candidates
2017-12-14 15:31:35 +08:00
kzc
d18979bb23 improve dead_code tests (#2589)
for #2588
2017-12-14 12:12:06 +08:00
Alex Lam S.L
8266993c6e fix dead_code on return/throw within try (#2588) 2017-12-14 04:38:21 +08:00
Alex Lam S.L
9a137e8613 drop local assign-only variable in return (#2587) 2017-12-14 02:59:59 +08:00
Alex Lam S.L
ef618332ea fold cascade functionality into collapse_vars (#2586) 2017-12-14 01:20:36 +08:00
Alex Lam S.L
7f418978c9 recover lost opportunities from #2574 (#2584) 2017-12-13 18:20:53 +08:00
Alex Lam S.L
04cc395c35 improve collapse_vars on side-effect-free replacements (#2583) 2017-12-13 04:52:54 +08:00
Alex Lam S.L
e008dc1bde minor clean-up for IIFE (#2582)
- faster exact type match
- aggressively convert to `!`
2017-12-13 01:27:26 +08:00
Alex Lam S.L
ddf96cfda2 avoid Function.prototype pollution by test/sandbox.js (#2581) 2017-12-12 05:02:01 +08:00
Alex Lam S.L
ebfd5c5c74 fix AST_VarDef.may_throw() (#2580) 2017-12-12 03:30:25 +08:00
Alex Lam S.L
f2ad542679 fix collapse_vars on switch (#2578) 2017-12-11 18:11:09 +08:00
Alex Lam S.L
c43118be4f remove unused code (#2579)
fixes #2577
2017-12-11 17:39:08 +08:00
Alex Lam S.L
93f3b2b114 escape consecutive unpaired surrogates (#2576)
fixes #2569
2017-12-11 01:15:44 +08:00
Alex Lam S.L
bf000beae7 rename tests (#2575) 2017-12-11 00:24:54 +08:00
Alex Lam S.L
0e16d92786 handle exceptional flow correctly in collapse_vars (#2574)
fixes #2571
2017-12-11 00:16:02 +08:00
Alex Lam S.L
2441827408 v3.2.2 2017-12-10 13:46:17 +08:00
Alex Lam S.L
0aff037a35 improve unused on assign-only symbols (#2568) 2017-12-09 06:19:29 +08:00
Alex Lam S.L
74a2f53683 fix escape analysis for AST_Throw (#2564) 2017-12-08 02:54:37 +08:00
Alex Lam S.L
e20935c3f2 fix escape analysis for AST_Conditional & AST_Sequence (#2563)
fixes #2560
2017-12-08 01:50:38 +08:00
Alex Lam S.L
3e34f62a1c account for side-effects in conditional call inversion (#2562)
fixes #2560
2017-12-08 01:15:31 +08:00
Alex Lam S.L
d21cb84696 eliminate noop calls more aggressively (#2559) 2017-12-07 01:22:08 +08:00
Alex Lam S.L
3dd495ecdd improve if_return (#2558)
`return void x()` => `x()`
2017-12-07 01:01:52 +08:00
Alex Lam S.L
b9f3ddfb30 v3.2.1 2017-12-03 11:39:51 +08:00
Alex Lam S.L
77332a0315 fix dead_code on for (#2552) 2017-12-02 15:46:05 +08:00
Alex Lam S.L
85c56adbd1 more tests for #2535 (#2551) 2017-12-02 02:26:56 +08:00
Alex Lam S.L
8da3754e51 improve evaluate on typeof (#2550)
- gated through `typeofs`
2017-12-02 02:18:33 +08:00
Alex Lam S.L
9a6b11f8e6 improve boolean compression (#2548)
fixes #2535
2017-12-01 22:41:35 +08:00
Alex Lam S.L
7ac6fdcc99 improve switch case compression (#2547) 2017-12-01 14:32:00 +08:00
Alex Lam S.L
f6610baaa8 improve AST_For.init & AST_Switch.expression compression (#2546) 2017-12-01 12:53:59 +08:00
Alex Lam S.L
09b320e8a5 convert to number under boolean context (#2545) 2017-12-01 12:52:36 +08:00
Alex Lam S.L
5a1e99d713 improve compression of if conditions (#2544) 2017-12-01 06:18:31 +08:00
Alex Lam S.L
b762f2d6f4 improve compression of loop conditions (#2543) 2017-12-01 05:52:33 +08:00
Alex Lam S.L
172079a47f improve code reuse (#2542) 2017-12-01 03:40:46 +08:00
Alex Lam S.L
c58d3936a3 fix corner case in call binding (#2541) 2017-12-01 03:18:20 +08:00
Alex Lam S.L
18302bf8e9 backport test from #2526 (#2534) 2017-11-29 13:32:00 +08:00
Alex Lam S.L
bc5047c1e7 fix inline on nested substitutions (#2533)
fixes #2531
2017-11-29 13:31:41 +08:00
Alex Lam S.L
206a54a746 fix nested hoist_props substitution (#2523)
fixes #2519
2017-11-28 14:39:00 +08:00
Alex Lam S.L
32def5ebf5 improve synergy between collapse_vars & unused (#2521) 2017-11-28 14:02:39 +08:00
Alex Lam S.L
ecc9f6b770 drop assignment in AST_VarDef.value (#2522)
fixes #2516
2017-11-28 13:08:40 +08:00
Alex Lam S.L
b37a68c84f v3.2.0 2017-11-26 04:08:35 +08:00
Alex Lam S.L
c141ae6f8d fix argument/atom collision by properties (#2514)
fixes #2513
2017-11-25 22:52:46 +08:00
Alex Lam S.L
97c464dbf5 fix wording and formatting (#2512) 2017-11-25 19:07:46 +08:00
Alex Lam S.L
3b28b915eb extend escape analysis on constant expression properties (#2509)
fixes #2508
2017-11-24 14:07:39 +08:00
Alex Lam S.L
eb001dc1d9 fix argument/atom collision by collapse_vars (#2507)
fixes #2506
2017-11-24 07:26:22 +08:00
Alex Lam S.L
aa9bdf416e make AST_Lambda.contains_this() less magical (#2505) 2017-11-24 07:03:37 +08:00
Alex Lam S.L
8987780db6 eliminate invalid state caching in collapse_vars (#2502)
fixes #2497
2017-11-24 04:12:37 +08:00
Alex Lam S.L
30cfea2e7a fix rename (#2501)
- suppress spurious `rename` from `commander`
- handle `AST_SymbolCatch` correctly
2017-11-24 03:05:43 +08:00
Alex Lam S.L
f4e2fb9864 expand symbol space to improve compression (#2460)
- give globally distinct names to distinct variables
- improve ability to compress cross-scoped
- introduce `options.rename` to `minify()`
- default `true` if both `compress` & `mangle`
2017-11-19 19:29:51 +08:00
Alex Lam S.L
b80062c490 enable hoist_props by default (#2492) 2017-11-19 14:56:23 +08:00
Alex Lam S.L
667fc4d08b v3.1.10 2017-11-18 23:56:33 +08:00
kzc
6142117cdd document the webkit output option (#2490)
- workaround for WebKit bugs
- PhantomJS users should enable this output option

closes #2489
2017-11-17 13:46:49 +08:00
Alex Lam S.L
ae28a24c7f fix cross-scope inlining of AST_Functions (#2486)
fixes #2485
2017-11-16 10:04:30 +08:00
Alex Lam S.L
ebe761cad0 minor consolidations (#2484)
- unique symbol generation
- `unsafe` on `AST_Call`
2017-11-16 04:37:37 +08:00
kzc
fa7a7c5c5a Update ISSUE_TEMPLATE.md (#2481) 2017-11-15 06:00:51 +08:00
kzc
557636f3b7 update documentation for reduce_funcs (#2478) 2017-11-14 16:03:25 +08:00
Alex Lam S.L
49fbe9c5ac fix replacement logic in collapse_vars (#2475) 2017-11-13 07:37:42 +08:00
Alex Lam S.L
2ac5086831 fix top_retain on hoist_props (#2474)
fixes #2473
2017-11-13 00:59:41 +08:00
Alex Lam S.L
c6cfa04d10 allow symbol replacement on multiple occurrences (#2472)
- all-or-nothing replacement
- avoid unmangleable names

fixes #2436
2017-11-12 22:31:47 +08:00
Alex Lam S.L
346fa12e0e v3.1.9 2017-11-11 15:31:13 +08:00
Alex Lam S.L
cda27b0970 extend reduce_funcs to cover cross-scope substitutions (#2469)
fixes #2468
2017-11-11 15:30:17 +08:00
Alex Lam S.L
3c74047368 implement compress option reduce_funcs (#2466)
- inline single-use function declarations as expressions when permissible
- depend on `reduce_vars`
- enabled by default
- disable for speed critical code

fixes #2464
2017-11-11 05:59:35 +08:00
Alex Lam S.L
94525d859f fix object literal tracing in reduce_vars (#2461) 2017-11-10 05:47:10 +08:00
Alex Lam S.L
1127a2caf3 fix multiple nested function substitutions (#2458)
fixes #2449
2017-11-09 23:30:00 +08:00
Alex Lam S.L
246d9d4e83 remove hack in collapse_vars (#2457)
fixes #2456
2017-11-09 20:00:58 +08:00
Alex Lam S.L
4c0b0177b6 preserve function identity in reduce_vars (#2451)
fixes #2450
2017-11-08 03:28:46 +08:00
Alex Lam S.L
38bfb73f06 v3.1.8 2017-11-07 03:55:16 +08:00
Alex Lam S.L
bbedbf4ea0 handle circular function reference gracefully (#2446)
fixes #2442
2017-11-07 02:37:23 +08:00
Alex Lam S.L
2cfb5aa7da account for eval & with in reduce_vars (#2441)
fixes #2440
2017-11-06 16:10:57 +08:00
Alex Lam S.L
6c45101870 consolidate & enhance unused (#2439)
- defer declaration removal in `collapse_vars`
- account for `AST_SymbolFunarg` in deduplication
- private accounting for `collapse_vars`
- avoid issues with identity reference due to deep cloning

fixes #2437
2017-11-06 14:25:10 +08:00
Alex Lam S.L
2c2fd89e34 inline single-use functions that are not constant expressions (#2434)
fixes #2428
2017-11-05 22:14:11 +08:00
Alex Lam S.L
f46281e2b7 v3.1.7 2017-11-05 15:03:19 +08:00
Alex Lam S.L
25a18883f5 tweak #2424 (#2432) 2017-11-05 12:49:14 +08:00
Alex Lam S.L
5b4b07e9a7 extend function inlining safety checks (#2430) 2017-11-05 06:18:45 +08:00
Alex Lam S.L
a8aa28a7a6 consolidate single-use function reduction (#2427)
fixes #2423
2017-11-05 04:27:01 +08:00
Alex Lam S.L
fe5a68f9d5 maintain call argument order in collapse_vars (#2426)
fixes #2425
2017-11-05 00:00:18 +08:00
Alex Lam S.L
71e61153b1 improve variations on call arguments for ufuzz (#2424) 2017-11-04 16:29:42 +08:00
Alex Lam S.L
c8b6f4733d reduce this within functions (#2421)
- only replace same-scope usages
- augment `test/ufuzz.js` to test for `this`


fixes #2420
2017-11-04 00:31:37 +08:00
Alex Lam S.L
a48f87abf2 compress new function containing this (#2417) 2017-10-30 23:19:27 +08:00
Alex Lam S.L
2fd927a7cc v3.1.6 2017-10-29 12:38:10 +08:00
Alex Lam S.L
8428326ea1 enhance properties (#2412)
- trim array items only if `side_effects`
- extend to non-identifier properties
2017-10-29 04:11:26 +08:00
Alex Lam S.L
31f8209193 remove dead code (#2405) 2017-10-27 14:28:09 +08:00
Alex Lam S.L
9b0f86f5a1 fix reduce_vars on AST_Array.length (#2404) 2017-10-27 02:33:37 +08:00
Alex Lam S.L
ee082ace1b compress self comparisons (#2398) 2017-10-26 01:16:12 +08:00
kzc
ae67a49850 document compress option hoist_props (#2399) 2017-10-25 14:03:43 +08:00
Alex Lam S.L
4178289c38 implement hoist_props (#2396)
fixes #2377
2017-10-25 03:38:11 +08:00
Alex Lam S.L
74ae16f9f8 fix unsafe reduce_vars on arrays & objects (#2397) 2017-10-24 22:10:36 +08:00
Tom MacWright
1968203d83 docs: Fix spelling and style (#2395) 2017-10-24 04:59:12 +08:00
Alex Lam S.L
86ea38a259 enhance unsafe evaluate of arrays & objects (#2394) 2017-10-24 02:58:30 +08:00
Alex Lam S.L
8a713e449f deduplicate declarations regardless of toplevel (#2393) 2017-10-23 01:00:50 +08:00
Alex Lam S.L
24aa07855b safer properties transform (#2391)
`{ a: x, b: y }.a` => `[ x, y ][0]`
- `x` cannot be function containing `this`

`[ x, y, z ][1]` => `(x, z, y)`
- only if `z` is side-effect-free
2017-10-22 20:10:13 +08:00
Alex Lam S.L
5fd723f143 fix unsafe expansion of object literals (#2390) 2017-10-22 15:00:36 +08:00
Alex Lam S.L
516eaef50c fix unsafe evaluation of AST_Sub (#2389) 2017-10-22 13:14:15 +08:00
Alex Lam S.L
4ae1fb3ed8 fix unsafe evaluation of objects (#2388) 2017-10-22 04:19:40 +08:00
Alex Lam S.L
011123223b fix unsafe escape analysis in reduce_vars (#2387) 2017-10-22 03:23:31 +08:00
Alex Lam S.L
96439ca246 v3.1.5 2017-10-22 00:27:26 +08:00
Alex Lam S.L
c927cea632 unsafe fix-ups for #2351 (#2379) 2017-10-21 04:08:26 +08:00
Alex Lam S.L
9f4b98f8e4 backport #2374 (#2376) 2017-10-19 23:02:27 +08:00
Alex Lam S.L
0f2ef3367c enhance collapse_vars around lazy operations (#2369) 2017-10-19 04:52:00 +08:00
Alex Lam S.L
7e5b5cac97 fix AST_PropAccess in collapse_vars (take 3) (#2375)
Suppress scanning beyond assignment to `a.b`
2017-10-18 02:54:51 +08:00
Alex Lam S.L
c1346e06b7 clean up lazy operator detection (#2373) 2017-10-17 23:25:45 +08:00
Alex Lam S.L
0d2fe8e3ef fix AST_PropAccess in collapse_vars (take 2) (#2372)
fixes #2364
2017-10-17 22:59:15 +08:00
Alex Lam S.L
f2b9c11e2a fix AST_PropAccess in collapse_vars (#2370)
fixes #2364
2017-10-17 18:33:03 +08:00
Alex Lam S.L
fe647b083e account for side-effects from AST_This in collapse_vars (#2365) 2017-10-17 01:18:55 +08:00
Alex Lam S.L
dfe4f6c6de v3.1.4 2017-10-16 02:44:17 +08:00
Alex Lam S.L
a09c8ad666 update dependency (#2362)
- source-map@0.6.1
2017-10-16 02:41:22 +08:00
Alex Lam S.L
ec598c351b fix-ups for #2356 (#2360) 2017-10-15 22:33:55 +08:00
Alex Lam S.L
eba0f93bc0 more tests for #2351 (#2357) 2017-10-12 02:58:25 +08:00
Roger Peppe
99800d4aa9 update README to include defaults (#2356)
fixes #2353
2017-10-12 02:56:02 +08:00
Tim Malone
70d56c951a Update README.md - sourceMappingURL directive note (#2355)
Moves this README note to underneath the 'url' rather than 'root' option.
2017-10-11 19:48:43 +08:00
Alex Lam S.L
b810e2f8da perform reduce_vars on safe literals (#2351)
- constant expression
- single reference
- same scope
- not across loop body
2017-10-09 12:25:06 +08:00
Alex Lam S.L
1abe14296e collapse a.b whenever safe (#2350) 2017-10-08 13:17:48 +08:00
Alex Lam S.L
6920e898d1 v3.1.3 2017-10-01 12:36:07 +08:00
Alex Lam S.L
dd71639264 enhance reduce_vars for AST_Accessor (#2339)
fixes #2336
2017-10-01 03:01:50 +08:00
Alex Lam S.L
2dcc552ce0 trap invalid use of reserved words (#2338)
fixes #2337
2017-10-01 02:10:41 +08:00
Alex Lam S.L
55387e8fd0 v3.1.2 2017-09-24 02:02:04 +08:00
kzc
7e3e9da860 fix "use asm" numeric output (#2328)
fixes #2324
2017-09-21 04:42:40 +08:00
Alex Lam S.L
00f509405b suppress collapse_vars of this into "use strict" (#2326)
fixes #2319
2017-09-20 05:23:20 +08:00
Alex Lam S.L
aceb0af36b v3.1.1 2017-09-17 04:36:27 +08:00
Alex Lam S.L
4f0953f7e9 handle LHS side-effects on cascade & collapse_vars (#2314)
fixes #2313
2017-09-16 11:45:19 +08:00
Alex Lam S.L
182a47bfb1 improve source mapping (#2312)
fixes #2310
2017-09-15 12:46:48 +08:00
Alex Lam S.L
cd27f4ec38 v3.1.0 2017-09-10 15:17:24 +08:00
Mateusz Burzyński
8158b1bdcf Testing all leading comments against being PURE comments (#2305) 2017-09-10 02:08:15 +08:00
Alex Lam S.L
aacf3edc68 extend unsafe on pure global functions (#2303) 2017-09-07 22:08:34 +08:00
kzc
8b89072190 add Date and other known globals to unsafe compress option (#2302) 2017-09-07 02:44:26 +08:00
Alex Lam S.L
395a17ccda fix collapse_vars on default function argument (#2299)
Avoid collision with local variable `undefined` under certain corner cases.

fixes #2298
2017-09-04 02:32:33 +08:00
Alex Lam S.L
3f355866cf correctly count declarations after hoist_vars (#2297)
fixes #2295
2017-09-03 17:23:31 +08:00
David Šanda
71d52f147d Fix CLI example for mangle reserved list of names (#2294) 2017-08-31 00:55:32 +08:00
David Šanda
eb7adaa6fc Fix CLI source-maps examples (#2291)
fixes #2284
2017-08-29 23:49:20 +08:00
Alex Lam S.L
e5cf7972ea fix unused patching of AST_For.init blocks (#2289)
fixes #2288
2017-08-29 01:10:04 +08:00
Alex Lam S.L
f81ff10a9b v3.0.28 2017-08-20 00:27:01 +08:00
Erik Desjardins
16d40915b4 don't escape null characters as \0 when followed by any digit (#2273)
fixes #2272
2017-08-14 12:30:08 +08:00
Alex Lam S.L
e7c21e87e3 fix ie8 mangling of top-level AST_SymbolCatch (#2263)
fixes #2254
2017-08-01 02:38:32 +08:00
Alex Lam S.L
c4c2ef44d0 v3.0.27 2017-07-30 01:50:42 +08:00
Alex Lam S.L
a845897758 improve mangle.properties (#2261)
- include dead code when `keep_quoted`
- unify `keep_quoted` & `reserved`
- make `test/run-tests.js` consistent with `minify()`

fixes #2256
2017-07-29 23:02:04 +08:00
kzc
32ea2c5530 issue template: describe acceptable JS input (#2255) 2017-07-27 21:38:36 +08:00
Alex Lam S.L
bc61deeca9 v3.0.26 2017-07-23 12:39:36 +08:00
Alex Lam S.L
6a5e74b44e unescape surrogate pairs only (#2246)
fixes #2242
2017-07-23 12:38:21 +08:00
Alex Lam S.L
54446341ee update dependencies (#2241)
- acorn@5.1.1
- commander@2.11.0
- mocha@3.4.2
2017-07-16 16:20:40 +08:00
Alex Lam S.L
4e12a6f740 v3.0.25 2017-07-16 11:05:53 +08:00
Alex Lam S.L
b35dfc2599 reject malformed CLI parameters (#2239)
fixes #2237
2017-07-15 23:50:27 +08:00
Alex Lam S.L
9e1da9235e ensure ie8 works with mangled properties (#2238)
fixes #2234
2017-07-15 22:50:59 +08:00
Alex Lam S.L
a5ffe2c23f drop unused builtin globals under unsafe (#2236)
fixes #2233
2017-07-15 15:16:11 +08:00
Alex Lam S.L
9282e7b0c6 fix unsafe evaluate of Object static methods (#2232)
fixes #2231
2017-07-14 19:52:01 +08:00
Alex Lam S.L
5229cb2b1b drop unused compound assignments (#2230)
fixes #2226
2017-07-14 00:39:34 +08:00
Alex Lam S.L
458e3e15f0 enhance passes (#2229)
- remove hardcoded upper limit
- continue based on node count reduction
- emit verbose statistics

fixes #2226
2017-07-13 02:18:59 +08:00
Alex Lam S.L
c615a1e80a fix gzip stream in test/benchmark.js (#2228) 2017-07-12 02:55:57 +08:00
Alex Lam S.L
10a938cb79 enhance source mapping on IIFEs (#2224)
fixes #2213
2017-07-11 02:34:28 +08:00
Alex Lam S.L
4956ad311b benchmark gzipped output (#2220) 2017-07-09 01:44:59 +08:00
kzc
145874e504 docs: update benchmarks using node 8, add babili (#2218) 2017-07-09 01:06:15 +08:00
Alex Lam S.L
bd7be07c38 v3.0.24 2017-07-08 12:53:20 +08:00
Alex Lam S.L
71ee91e716 handle duplicate argument names in collapse_vars (#2215) 2017-07-08 04:42:35 +08:00
Alex Lam S.L
4f70d2e28c inlining of static methods & constants (#2211)
- guard by `unsafe`
- support `Array`, `Math`, `Number`, `Object` & `String`

fixes #2207
2017-07-07 05:35:32 +08:00
Alex Lam S.L
4b6ca5e742 inline property access of object literal (#2209)
- only if property value is side-effect-free
- guard by `unsafe`

fixes #2208
2017-07-06 21:51:58 +08:00
Alex Lam S.L
9306da3c58 suppress collapse_vars of this as call argument (#2204)
fixes #2203
2017-07-06 01:03:52 +08:00
Alex Lam S.L
1ac25fc032 improve compress granularity through typeofs (#2201)
fixes #2198
2017-07-05 19:20:33 +08:00
Alex Lam S.L
5f046c724b minor clean-ups to evaluate (#2197) 2017-07-03 18:52:39 +08:00
Alex Lam S.L
af0262b7e5 improve parenthesis emission (#2196)
- eliminate `throw` usages
- suppress extraneous parenthesis
  - `new function() {foo.bar()}.baz`
  - `for (function() { "foo" in bar; };;);`
2017-07-03 04:17:37 +08:00
Alex Lam S.L
6b3aeff1d8 clean up TreeWalker.pop() (#2195)
Remove superfluous parameter.
2017-07-03 03:23:38 +08:00
Alex Lam S.L
20e4f8277f refactor throw usage within compress (#2193)
Eliminate exceptional constructs from normal control flow.
2017-07-03 02:10:56 +08:00
kzc
f3a487a368 document fast mangle-only minify mode (#2194) 2017-07-03 01:37:04 +08:00
Alex Lam S.L
2dde41615a v3.0.23 2017-07-02 17:24:22 +08:00
Alex Lam S.L
8b69a3d18e drop argument value after collapse_vars (#2190) 2017-07-02 04:28:11 +08:00
Alex Lam S.L
d40950b741 improve inline efficiency (#2188)
... by teaching `collapse_vars` some new tricks.

fixes #2187
2017-07-02 01:05:14 +08:00
Alex Lam S.L
7659ea1d2e v3.0.22 2017-06-30 11:18:34 +08:00
Alex Lam S.L
bdeadffbf5 improve usability of name cache under minify() (#2176)
fixes #2174
2017-06-29 12:48:34 +08:00
Alex Lam S.L
5e6f26445f v3.0.21 2017-06-29 00:49:06 +08:00
Alex Lam S.L
f0a99125ee improve unsafe_Func (#2171)
- minimise disturbance to `compute_char_frequency()`
- remove extraneous quotation marks
2017-06-27 23:53:42 +08:00
Alex Lam S.L
1e4de2e6d3 parse @global_defs as expressions (#2169)
- let parser rejects non-conformant input
- eliminate need for extraneous parenthesis
2017-06-27 10:31:19 +08:00
Alex Lam S.L
8b4dcd8f3e v3.0.20 2017-06-25 15:05:05 +08:00
Alex Lam S.L
285401ced8 more tests for #2158 (#2160) 2017-06-25 14:21:48 +08:00
Alex Lam S.L
9db4c42380 fix cascade & collapse on property access of constants (#2158) 2017-06-24 21:30:06 +08:00
Alex Lam S.L
94e5e00c03 refactor compute_char_frequency() (#2152)
- minimise maintenance when updating AST
- maximise code sharing between `master` & `harmony`
2017-06-23 20:05:31 +08:00
Alex Lam S.L
dc6bcaa18e synchronise mangle.properties for minify() & test/compress (#2151) 2017-06-23 15:53:13 +08:00
Alex Lam S.L
d58b184835 refactor Compressor.toplevel (#2149) 2017-06-23 13:11:40 +08:00
Alex Lam S.L
b3a57ff019 minimise reduce_vars cloning overhead (#2148) 2017-06-23 06:59:53 +08:00
Alex Lam S.L
3d5bc08185 fix reduce_vars on this (#2145)
fixes #2140
2017-06-23 04:44:57 +08:00
Alex Lam S.L
0692435f01 fix for-in loop parsing (#2144) 2017-06-23 04:14:30 +08:00
Alex Lam S.L
f67a6b0e43 v3.0.19 2017-06-22 03:24:22 +08:00
Alex Lam S.L
343ea326c2 ensure mangling works if catch reuses a scope variable (#2123)
fixes #2120
2017-06-20 02:14:05 +08:00
Alex Lam S.L
1c150c632f v3.0.18 2017-06-18 15:01:20 +08:00
Alex Lam S.L
0a0f4f5591 make defensive copies when inline (#2116)
fixes #2114
2017-06-17 14:32:37 +08:00
Alex Lam S.L
931daa85bf fix loss of context in collapse_vars & cascade (#2112)
fixes #2110
2017-06-16 21:18:43 +08:00
Alex Lam S.L
00e4f7b3c1 in-place tigten_body() (#2111)
By reducing copies of `AST_Node` arrays, we should be able to reduce:
- memory pressure
- potential bugs caused by multiple references in AST
- duplicated executions of `OPT()`
2017-06-16 19:19:54 +08:00
Alex Lam S.L
11e63bc335 correctly determine scope of AST_This (#2109)
fixes #2107
2017-06-16 14:54:46 +08:00
Alex Lam S.L
33405bb24b enforce inline scope restriction (#2106)
fixes #2105
2017-06-16 03:21:38 +08:00
Alex Lam S.L
57dc4fb32f v3.0.17 2017-06-15 18:59:37 +08:00
Alex Lam S.L
b85a358deb suppress inline of this (#2103)
fixes #2101
2017-06-15 12:14:16 +08:00
Alex Lam S.L
43697958f3 avoid intermittent test time-out failures (#2100) 2017-06-15 04:47:57 +08:00
Alex Lam S.L
3f961bbba0 compute uses_arguments correctly in figure_out_scope() (#2099)
fixes #2097
2017-06-15 03:28:26 +08:00
Alex Lam S.L
0a1e523cd5 fix parsing of expect_stdout (#2096)
fixes #2095
2017-06-15 01:00:03 +08:00
Alex Lam S.L
4231f7323e v3.0.16 2017-06-14 16:45:09 +08:00
kzc
da2de350c3 add comment about quote_style and gzip (#2092) 2017-06-14 12:23:03 +08:00
Alex Lam S.L
41beae4dd7 cache web assets between CI runs (#2089)
- skip `test/jetstream.js` for `node@0.12`
2017-06-14 11:53:10 +08:00
Ziad El Khoury Hanna
82db9188ac fix CLI parsing of --source-map content (#2088)
fixes #2082
2017-06-13 16:30:46 +08:00
Alex Lam S.L
3dc9e140e4 add Node.js 8 to Travis CI (#2086)
- explicitly terminate `test/jetstream.js` upon completion
- log verbose output from `test/benchmark.js` & `test/jetstream.js`
- remove obsolete workaround for Travis CI
2017-06-13 06:21:16 +08:00
Alex Lam S.L
fed0096556 allow expect_stdout to specify Error (#2087) 2017-06-13 04:57:26 +08:00
Alex Lam S.L
2bdc8802dd fix variable accounting in inline (#2085)
fixes #2084
2017-06-13 01:40:14 +08:00
Alex Lam S.L
5ef7cb372a suppress false positives for-in loops (#2080)
fixes #2079
2017-06-10 13:55:17 +08:00
Alex Lam S.L
4ad7b1dae4 fix portability of sandbox.run_code() on Node.js 0.1x (#2078) 2017-06-10 01:08:58 +08:00
Alex Lam S.L
9186859cb7 fix non-string parameters (#2076)
`Stream.write()` is not as versatile as `console.log()`
2017-06-10 00:11:40 +08:00
Alex Lam S.L
47c0713747 report test/ufuzz.js failures in process.stderr (#2074) 2017-06-09 15:56:28 +08:00
Alex Lam S.L
293c566d6c marshal mangle[.properties].reserved from non-Array values (#2072) 2017-06-09 04:29:12 +08:00
Alex Lam S.L
9c306406f1 fix iteration over object with inherited properties (#2068)
fixes #2055
2017-06-08 03:27:03 +08:00
Alex Lam S.L
9db0695b10 fix cascade on multi-branch evaluations (#2067)
Partially reverts #2059 as this has better coverage and performance.

fixes #2062
2017-06-07 19:52:01 +08:00
Alex Lam S.L
f2af093402 fix CLI output corruption (#2061)
Using `console.error()` & `console.log()` result in inconsistent formatting across Node.js versions.

Avoid this issue by directly writing to `process.stderr` & `process.stdout` instead.

Miscellaneous
- prettify invalid option listing
2017-06-07 04:25:32 +08:00
Alex Lam S.L
b9ad53d1ab fix inline handling of AST_Call.args (#2059) 2017-06-06 22:55:25 +08:00
Alex Lam S.L
b0eab71470 implement test/jetstream.js --debug (#2058) 2017-06-06 19:28:12 +08:00
Alex Lam S.L
3493a182b2 implement function inlining (#2053)
- empty body
- single `AST_Return`
- single `AST_SimpleStatement`
- avoid `/*#__PURE__*/`

Miscellaneous
- enhance single-use function substitution

fixes #281
2017-06-06 05:49:53 +08:00
Alex Lam S.L
27c5284d3d workaround webkit parsing error (#2056)
apply `webkit` to jetstream tests
2017-06-06 04:06:42 +08:00
Alex Lam S.L
540220b91b fix AST_Function scope invariance (#2052)
improve function name hack in `run_code()`
2017-06-04 19:27:43 +08:00
Alex Lam S.L
84634da4b5 add tests for AST_SymbolAccessor (#2049) 2017-06-03 16:08:10 +08:00
Alex Lam S.L
1743621889 clean up lib/parse.js (#2047)
- remove unused definitions
- replace `array_to_hash()`
2017-06-03 14:00:59 +08:00
kzc
f330ab743a better document behavior of unsafe_Func (#2043) 2017-06-02 12:07:17 +08:00
Alex Lam S.L
4377e932ca v3.0.15 2017-06-01 18:12:38 +08:00
Alex Lam S.L
bac14ba881 fix non-identifier getter/setter name (#2041)
fixes #2040
2017-06-01 18:11:16 +08:00
Alex Lam S.L
ec095ed647 whitelist unsafe evaluate candidates (#2039)
- all arguments may accept constant values
- return constant value
- free of side effects
- available & identical across locales and runtime environments
2017-06-01 04:33:05 +08:00
Alex Lam S.L
17e73121fa enhance unsafe evaluate (#2037) 2017-06-01 00:56:28 +08:00
kzc
f71e8fd948 reformat mangle options section of README (#2036) 2017-05-31 21:52:43 +08:00
Alex Lam S.L
3e62faa64f v3.0.14 2017-05-31 11:34:51 +08:00
Alex Lam S.L
e9645e017f introduce unsafe_Func (#2033)
Separate flag for #203 functionality.
2017-05-31 03:38:00 +08:00
Alex Lam S.L
55b5f2a8aa widen CLI parse error code fragment displayed (#2032)
fixes #2030
2017-05-31 01:56:52 +08:00
Alex Lam S.L
4e0a22e5c8 v3.0.13 2017-05-29 10:52:13 +08:00
Alex Lam S.L
1aa38051fb better fix for #512 & #2010 (#2019)
- remove duplicated functionalities
- fix similar issue with `else`
2017-05-29 10:51:41 +08:00
Alex Lam S.L
e62b879b48 display default values in --help options (#2018) 2017-05-28 22:57:20 +08:00
Alex Lam S.L
c6c9f4f5a8 implement --help options (#2017) 2017-05-28 18:21:44 +08:00
Alex Lam S.L
fec14379f6 improve CLI usability (#2016)
Report supported options upon invalid option syntax.

fixes #1883
2017-05-28 04:09:40 +08:00
Alex Lam S.L
79131cd647 extend node_version range on applicable tests (#2015) 2017-05-27 22:18:28 +08:00
Alex Lam S.L
c3f14a1481 v3.0.12 2017-05-27 18:08:09 +08:00
Alex Lam S.L
7b13159cda fix hoist_funs on block-scoped function under "use strict" (#2013)
Technically not part of ES5, but commonly used code exists in the wild.
2017-05-27 17:44:59 +08:00
Alex Lam S.L
95094b9c22 fix if_return on AST_Defun (#2010)
Previous fiix for #1052 perturbs declaration order of functions which leads to incorrect behaviour under "use strict".
2017-05-27 13:41:49 +08:00
kzc
1ff8e9dd38 clarify what --mangle-props does (#2012) 2017-05-27 13:17:30 +08:00
kzc
78309a293d better document mangle properties options (#2009) 2017-05-27 02:28:43 +08:00
kzc
695e182d59 fix and expand --mangle-props documentation (#2008)
fixes #2007
2017-05-27 01:25:51 +08:00
Alex Lam S.L
dc33facfcb fix dead_code on block-scoped function under "use strict" (#2006)
Technically not part of ES5, but commonly used code exists in the wild.
2017-05-26 16:08:51 +08:00
Alex Lam S.L
c70fb60384 clean up lib/scope.js (#2003)
fixes #2004
2017-05-26 03:58:35 +08:00
Alex Lam S.L
793d61499b report timing breakdown (#2000)
fix corner cases with `sourceMap`

fixes #1998
2017-05-25 07:15:55 +08:00
Alex Lam S.L
a277fe168d ensure new line after describe_ast() (#1999) 2017-05-25 02:32:36 +08:00
Alex Lam S.L
7d3b941e6e reinstate describe_ast() on CLI (#1996)
fixes #1995
2017-05-24 02:30:09 +08:00
Alex Lam S.L
e95052a423 v3.0.11 2017-05-23 22:26:59 +08:00
Alex Lam S.L
e667f0acb8 fix source map offset (#1993)
Account for whitespace insertions.

fixes #505
fixes #890
2017-05-23 20:25:48 +08:00
kzc
69ac794bc8 add another minify() options example (#1988) 2017-05-22 12:19:07 +08:00
Alex Lam S.L
efdb65913b improve usability of global_defs in minify() (#1987)
Use `@key` to `parse()` string value as `AST_Node`.

fixes #1986
2017-05-22 01:38:43 +08:00
kzc
a1dedeb3ce more refinement of minify() documentation (#1983) 2017-05-21 04:55:03 +08:00
Alex Lam S.L
d3c4a8e9e7 v3.0.10 2017-05-21 01:30:17 +08:00
kzc
7e164aba8f add "es5" to package.json keywords (#1980) 2017-05-20 22:09:50 +08:00
kzc
22aedef849 document minify() option toplevel (#1979) 2017-05-20 22:09:21 +08:00
Alex Lam S.L
58fae7dc07 enhance if_return to handle return void... (#1977)
fixes #512
2017-05-20 15:58:46 +08:00
kzc
5bf8d7e949 document 3.x minify() does not throw errors (#1975) 2017-05-20 10:49:35 +08:00
kzc
1df9d06f4a document minify warnings and add an error example (#1973) 2017-05-19 17:20:21 +08:00
Alex Lam S.L
3408fc9d32 v3.0.9 2017-05-19 09:35:26 +08:00
Alex Lam S.L
eae26756f1 introduce unsafe_regexp (#1970)
fixes #1964
2017-05-19 09:06:29 +08:00
Alex Lam S.L
43add9416b v3.0.8 2017-05-18 14:49:40 +08:00
Alex Lam S.L
efcf167e5e make expect_stdout node version specific (#1963)
... via semver string on `node_version` label.
2017-05-18 11:28:35 +08:00
Kara
6ed90913ca fix docs for side_effects flag to reflect current behavior (#1966) 2017-05-18 10:51:49 +08:00
Alex Lam S.L
569c21e952 improve RegExp handling (#1959)
- remove `options.output.unescape_regexps`
- preserve original pattern whenever possible

fixes #54
fixes #1929
2017-05-17 20:10:50 +08:00
Alex Lam S.L
87c3a2c0ce remove space_colon (#1960)
Always emit space after colon when `options.output.beautify` is enabled.
2017-05-17 14:07:34 +08:00
Rob Garrison
baef8bf050 update output options in readme (#1958) 2017-05-17 11:54:46 +08:00
alexlamsl
0813c5316f remove Travis CI badge 2017-05-17 10:32:59 +08:00
Alex Lam S.L
c88139492d v3.0.7 2017-05-16 19:59:40 +08:00
Alex Lam S.L
cb45886512 export TreeTransformer (#1950)
- link to existing documentation on `TreeWalker` & `TreeTransformer`
- fix Travis build failures

fixes #1949
2017-05-16 19:59:05 +08:00
Alex Lam S.L
050474ab44 v3.0.6 2017-05-16 06:38:58 +08:00
Alex Lam S.L
f6c805ae1d print package name alongside version in CLI (#1946)
fixes #1945
2017-05-16 06:34:32 +08:00
Alex Lam S.L
9464d3c20f fix parsing of property access after new line (#1944)
Account for comments when detecting property access in `tokenizer`.

fixes #1943
2017-05-16 05:40:49 +08:00
alexlamsl
f18abd1b9c minor fixes to README.md 2017-05-16 01:33:01 +08:00
kzc
3be06ad085 reorg README for 3.x (#1942) 2017-05-16 01:12:00 +08:00
Alex Lam S.L
265008c948 improve keyword-related parser errors (#1941)
fixes #1937
2017-05-15 23:02:55 +08:00
Alex Lam S.L
ff526be61d v3.0.5 2017-05-15 11:37:14 +08:00
Alex Lam S.L
e005099fb1 fix & improve coverage of estree (#1935)
- fix `estree` conversion of getter/setter
- fix non-directive literal in `to_mozilla_ast()`
- revamp `test/mozilla-ast.js`
  - reuse `test/ufuzz.js` for code generation
  - use `acorn.parse()` for creating `estree`
- extend `test/ufuzz.js` for `acorn` workaround
  - catch variable redefinition
  - non-trivial literal as directive
  - adjust options for tolerance

Miscellaneous
- optional semi-colon when parsing directives

fixes #1914
closes #1915
2017-05-15 02:37:53 +08:00
kzc
504a436e9d Tweak README Notes (#1934) 2017-05-14 02:12:14 +08:00
Alex Lam S.L
3ca902258c fix bugs with getter/setter (#1926)
- `reduce_vars`
- `side_effects`
- property access for object
- `AST_SymbolAccessor` as key names

enhance `test/ufuzz.js`
- add object getter & setter
  - property assignment to setter
  - avoid infinite recursion in setter
- fix & adjust assignment operators
  - 50% `=`
  - 25% `+=`
  - 2.5% each for the rest
- avoid "Invalid array length"
- fix `console.log()`
  - bypass getter
  - curb recursive reference
- deprecate `-E`, always report runtime errors
2017-05-14 02:10:34 +08:00
olsonpm
fd0951231c document 3 max passes (#1928) 2017-05-13 12:54:32 +08:00
olsonpm
9e29b6dad2 clarify wording (#1931) 2017-05-13 12:54:01 +08:00
Alex Lam S.L
c391576d52 remove support for const (#1910)
As this is not part of ES5.
2017-05-12 14:57:41 +08:00
Alex Lam S.L
ac73c5d421 avoid arguments and eval in reduce_vars (#1924)
fixes #1922
2017-05-12 12:34:55 +08:00
olsonpm
547f41beba add documentation for side_effects & [#@]__PURE__ (#1925) 2017-05-12 12:29:55 +08:00
Alex Lam S.L
daaefc17b9 v3.0.4 2017-05-12 04:52:39 +08:00
Alex Lam S.L
1d407e761e fix invalid transform on const (#1919)
- preserve (re)assignment to `const` for runtime error
- suppress `cascade` on `const`, as runtime behaviour is ill-defined
2017-05-12 04:51:44 +08:00
kzc
2b44f4ae30 update README (#1918) 2017-05-12 03:36:33 +08:00
Alexis Tyler
e51c3541da fix typo (#1913) 2017-05-11 20:24:33 +08:00
Alex Lam S.L
3bf194684b update documentation (#1909)
- clarify options on `--source-map`
- fix `minify()` examples

fixes #1905
2017-05-11 17:50:50 +08:00
Alex Lam S.L
aae7d49d0c v3.0.3 2017-05-10 11:45:03 +08:00
kzc
0459af2ecc Update issue template: change harmony to uglify-es (#1900) 2017-05-10 11:07:54 +08:00
kzc
04f2344efc Remove unnecessary git clone instructions in README (#1897) 2017-05-10 11:06:50 +08:00
kzc
bad9d5cf88 Change harmony to uglify-es in master README (#1895) 2017-05-10 05:07:45 +08:00
Alex Lam S.L
a0f5f862df gracefully handle non-Error being thrown (#1893) 2017-05-10 04:20:59 +08:00
Alex Lam S.L
41996be86f extend test timeout
Travis has gone a lot slower recently, and most test failures are due to time-out on this particular test.
2017-05-10 02:43:12 +08:00
Alex Lam S.L
5fd8244a2e v3.0.2 2017-05-10 01:52:00 +08:00
Alex Lam S.L
c14e280585 print error stack in CLI (#1890) 2017-05-09 16:36:44 +08:00
Alex Lam S.L
bc3fa78e8c mention minify().error 2017-05-09 16:09:48 +08:00
Alex Lam S.L
8c7c107765 update minify() usage in test/ufuzz.js (#1888)
fixes #1887
2017-05-09 15:58:46 +08:00
kzc
3dd328dce3 [3.x] fix documentation for beautify options (#1882)
- use underscores rather than dashes.
2017-05-08 23:06:56 +08:00
178 changed files with 34434 additions and 7910 deletions

View File

@@ -1,20 +1,25 @@
**Bug report or feature request?**
**Bug report or feature request?**
<!-- Note: sub-optimal but correct code is not a bug -->
**ES5 or ES6+ input?**
**Uglify version (`uglifyjs -V`)**
<!-- Note: for ES6 see: https://github.com/mishoo/UglifyJS2/tree/harmony#harmony -->
**JavaScript input**
**`uglify-js` version (`uglifyjs -V`)**
<!--
A complete parsable JS program exhibiting the issue with
UglifyJS alone - without third party tools or libraries.
Ideally the input should be as small as possible.
Post a link to a gist if necessary.
**JavaScript input - ideally as small as possible.**
Issues without a reproducible test case will be closed.
-->
**The `uglifyjs` CLI command executed or `minify()` options used.**
**JavaScript output produced and/or the error or warning.**
**JavaScript output or error produced.**
<!--
Note: the release version of uglify-js only supports ES5. Those wishing
to minify ES6 should use the experimental harmony branch.
Note: `uglify-js` only supports JavaScript.
Those wishing to minify ES6+ should transpile first.
-->

View File

@@ -1,12 +1,35 @@
language: node_js
before_install: "npm install -g npm"
node_js:
- "0.10"
- "0.12"
- "4"
- "6"
env:
- UGLIFYJS_TEST_ALL=1
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- libstdc++-4.9-dev
cache:
directories: tmp
language: generic
matrix:
fast_finish: true
sudo: false
env:
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:
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
modification, are permitted provided that the following conditions

1138
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,26 @@
environment:
UGLIFYJS_TEST_ALL: 1
matrix:
- nodejs_version: "0.10"
- nodejs_version: "0.12"
- nodejs_version: "4.0"
- nodejs_version: "6.0"
- 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
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:
fast_finish: true
platform:
- x86
- x64
install:
- ps: Install-Product node $env:nodejs_version $env:platform
- npm install
test_script:
- node --version
- npm --version
- npm test
build: off
- npm test --no-update-notifier

View File

@@ -3,11 +3,7 @@
"use strict";
// workaround for tty output truncation upon process.exit()
[process.stdout, process.stderr].forEach(function(stream){
if (stream._handle && stream._handle.setBlocking)
stream._handle.setBlocking(true);
});
require("../tools/exit");
var fs = require("fs");
var info = require("../package.json");
@@ -15,31 +11,44 @@ var path = require("path");
var program = require("commander");
var UglifyJS = require("../tools/node");
var skip_keys = [ "cname", "enclosed", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ];
var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
var files = {};
var options = {
compress: false,
mangle: false
};
program._name = info.name;
program.version(info.version);
program.version(info.name + " " + info.version);
program.parseArgv = program.parse;
program.parse = undefined;
program.option("-p, --parse <options>", "Specify parser options.", parse_js("parse", true));
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js("compress", true));
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js("mangle", true));
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js("mangle-props", true));
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js("beautify", true));
if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
else if (process.argv.indexOf("options") >= 0) program.helpInformation = function() {
var text = [];
var options = UglifyJS.default_options();
for (var option in options) {
text.push("--" + (option == "output" ? "beautify" : option == "sourceMap" ? "source-map" : option) + " options:");
text.push(format_object(options[option]));
text.push("");
}
return text.join("\n");
};
program.option("-p, --parse <options>", "Specify parser options.", parse_js());
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js());
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js());
program.option("-o, --output <file>", "Output file (default STDOUT).");
program.option("--comments [filter]", "Preserve copyright comments in the output.");
program.option("--config-file <file>", "Read minify() options from JSON file.");
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("--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("--rename", "Force symbol expansion.");
program.option("--no-rename", "Disable symbol expansion.");
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("--stats", "Display operations run time on STDERR.")
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("--toplevel", "Compress and/or mangle variables in toplevel scope.");
program.option("--verbose", "Print diagnostic messages.");
program.option("--warn", "Print warning messages.");
@@ -47,12 +56,18 @@ program.option("--wrap <name>", "Embed everything as a function with “exports
program.arguments("[files...]").parseArgv(process.argv);
if (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") {
fatal("ERROR: cannot write source map to STDOUT");
}
[
"compress",
"enclose",
"ie8",
"mangle",
"sourceMap",
@@ -90,23 +105,14 @@ if (program.mangleProps) {
if (typeof program.mangleProps != "object") program.mangleProps = {};
if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
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 = {};
options.mangle.properties = program.mangleProps;
}
var cache;
if (program.nameCache) {
cache = JSON.parse(read_file(program.nameCache, "{}"));
if (options.mangle) {
if (typeof options.mangle != "object") options.mangle = {};
options.mangle.cache = to_cache("vars");
if (options.mangle.properties) {
if (typeof options.mangle.properties != "object") options.mangle.properties = {};
options.mangle.properties.cache = to_cache("props");
}
}
options.nameCache = JSON.parse(read_file(program.nameCache, "{}"));
}
if (program.output == "ast") {
options.output = {
@@ -115,12 +121,17 @@ if (program.output == "ast") {
};
}
if (program.parse) {
if (program.parse.acorn || program.parse.spidermonkey) {
if (program.sourceMap) fatal("ERROR: inline source map only works with built-in parser");
} else {
if (!program.parse.acorn && !program.parse.spidermonkey) {
options.parse = program.parse;
} else if (program.sourceMap && program.sourceMap.content == "inline") {
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) {
return name;
};
@@ -140,7 +151,7 @@ if (program.verbose) {
}
if (program.self) {
if (program.args.length) {
console.error("WARN: Ignoring input files since --self was passed");
print_error("WARN: Ignoring input files since --self was passed");
}
if (!options.wrap) options.wrap = "UglifyJS";
simple_glob(UglifyJS.FILES).forEach(function(name) {
@@ -170,9 +181,14 @@ function convert_ast(fn) {
function run() {
UglifyJS.AST_Node.warn_function = function(msg) {
console.error("WARN:", msg);
print_error("WARN: " + msg);
};
if (program.stats) program.stats = Date.now();
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;
try {
if (program.parse) {
if (program.parse.acorn) {
@@ -193,13 +209,13 @@ function run() {
}
}
} catch (ex) {
fatal("ERROR: " + ex.message);
fatal(ex);
}
var result = UglifyJS.minify(files, options);
if (result.error) {
var ex = result.error;
if (ex.name == "SyntaxError") {
console.error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
print_error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
var col = ex.col;
var lines = files[ex.filename].split(/\r?\n/);
var line = lines[ex.line - 1];
@@ -208,21 +224,35 @@ function run() {
col = line.length;
}
if (line) {
if (col > 40) {
line = line.slice(col - 40);
col = 40;
var limit = 70;
if (col > limit) {
line = line.slice(col - limit);
col = limit;
}
console.error(line.slice(0, 80));
console.error(line.slice(0, col).replace(/\S/g, " ") + "^");
print_error(line.slice(0, 80));
print_error(line.slice(0, col).replace(/\S/g, " ") + "^");
}
}
if (ex.defs) {
console.error("Supported options:");
console.error(ex.defs);
print_error("Supported options:");
print_error(format_object(ex.defs));
}
fatal("ERROR: " + ex.message);
fatal(ex);
} else if (program.output == "ast") {
console.log(JSON.stringify(result.ast, function(key, value) {
if (!options.compress && !options.mangle) {
result.ast.figure_out_scope({});
}
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 (value instanceof UglifyJS.AST_Token) return;
if (value instanceof UglifyJS.Dictionary) return;
@@ -238,7 +268,7 @@ function run() {
return value;
}, 2));
} else if (program.output == "spidermonkey") {
console.log(JSON.stringify(UglifyJS.minify(result.code, {
print(JSON.stringify(UglifyJS.minify(result.code, {
compress: false,
mangle: false,
output: {
@@ -252,18 +282,19 @@ function run() {
fs.writeFileSync(program.output + ".map", result.map);
}
} else {
console.log(result.code);
print(result.code);
}
if (program.nameCache) {
fs.writeFileSync(program.nameCache, JSON.stringify(cache, function(key, value) {
return value instanceof UglifyJS.Dictionary ? value.toObject() : value;
}));
fs.writeFileSync(program.nameCache, JSON.stringify(options.nameCache));
}
if (result.timings) for (var phase in result.timings) {
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
}
if (program.stats) console.error("Elapsed:", Date.now() - program.stats);
}
function fatal(message) {
console.error(message);
if (message instanceof Error) message = message.stack.replace(/^\S*?Error:/, "ERROR:")
print_error(message);
process.exit(1);
}
@@ -303,29 +334,21 @@ function read_file(path, default_value) {
return fs.readFileSync(path, "utf8");
} catch (ex) {
if (ex.code == "ENOENT" && default_value != null) return default_value;
fatal("ERROR: " + ex.message);
fatal(ex);
}
}
function parse_js(flag, constants) {
function parse_js(flag) {
return function(value, options) {
options = options || {};
try {
UglifyJS.minify(value, {
parse: {
expression: true
},
compress: false,
mangle: false,
output: {
ast: true,
code: false
}
}).ast.walk(new UglifyJS.TreeWalker(function(node) {
UglifyJS.parse(value, {
expression: true
}).walk(new UglifyJS.TreeWalker(function(node) {
if (node instanceof UglifyJS.AST_Assign) {
var name = node.left.print_to_string();
var value = node.right;
if (!constants) {
if (flag) {
options[name] = value;
} else if (value instanceof UglifyJS.AST_Array) {
options[name] = value.elements.map(to_string);
@@ -348,37 +371,44 @@ function parse_js(flag, constants) {
}
}));
} catch(ex) {
fatal("Error parsing arguments for '" + flag + "': " + value);
if (flag) {
fatal("Error parsing arguments for '" + flag + "': " + value);
} else {
options[value] = null;
}
}
return options;
}
}
function parse_source_map() {
var parse = parse_js("sourceMap", true);
return function(value, options) {
var hasContent = options && options.sourceMap && "content" in options.sourceMap;
var settings = parse(value, options);
if (!hasContent && settings.content && settings.content != "inline") {
console.error("INFO: Using input source map:", settings.content);
settings.content = read_file(settings.content, settings.content);
}
return settings;
}
}
function to_cache(key) {
if (cache[key]) {
cache[key].props = UglifyJS.Dictionary.fromObject(cache[key].props);
} else {
cache[key] = {
cname: -1,
props: new UglifyJS.Dictionary()
};
}
return cache[key];
}
function skip_key(key) {
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) {
var lines = [];
var padding = "";
Object.keys(obj).map(function(name) {
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
return [ name, JSON.stringify(obj[name]) ];
}).forEach(function(tokens) {
lines.push(" " + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
});
return lines.join("\n");
}
function print_error(msg) {
process.stderr.write(msg);
process.stderr.write("\n");
}
function print(txt) {
process.stdout.write(txt);
process.stdout.write("\n");
}

View File

@@ -44,21 +44,21 @@
"use strict";
function DEFNODE(type, props, methods, base) {
if (arguments.length < 4) base = AST_Node;
if (!props) props = [];
else props = props.split(/\s+/);
if (typeof base === "undefined") base = AST_Node;
props = props ? props.split(/\s+/) : [];
var self_props = props;
if (base && base.PROPS)
props = props.concat(base.PROPS);
var code = "return function AST_" + type + "(props){ if (props) { ";
for (var i = props.length; --i >= 0;) {
code += "this." + props[i] + " = props." + props[i] + ";";
}
if (base && base.PROPS) props = props.concat(base.PROPS);
var code = [
"return function AST_", type, "(props){",
"if(props){",
];
props.forEach(function(prop) {
code.push("this.", prop, "=props.", prop, ";");
});
var proto = base && new base;
if (proto && proto.initialize || (methods && methods.initialize))
code += "this.initialize();";
code += "}}";
var ctor = new Function(code)();
if (proto && proto.initialize || methods && methods.initialize) code.push("this.initialize();");
code.push("}}");
var ctor = new Function(code.join(""))();
if (proto) {
ctor.prototype = proto;
ctor.BASE = base;
@@ -71,11 +71,11 @@ function DEFNODE(type, props, methods, base) {
if (type) {
ctor.prototype.TYPE = ctor.TYPE = type;
}
if (methods) for (i in methods) if (HOP(methods, i)) {
if (/^\$/.test(i)) {
ctor[i.substr(1)] = methods[i];
if (methods) for (var name in methods) if (HOP(methods, name)) {
if (/^\$/.test(name)) {
ctor[name.substr(1)] = methods[name];
} else {
ctor.prototype[i] = methods[i];
ctor.prototype[name] = methods[name];
}
}
ctor.DEFMETHOD = function(name, method) {
@@ -85,9 +85,9 @@ function DEFNODE(type, props, methods, base) {
exports["AST_" + type] = ctor;
}
return ctor;
};
}
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file raw", {
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before comments_after file raw", {
}, null);
var AST_Node = DEFNODE("Node", "start end", {
@@ -118,10 +118,8 @@ var AST_Node = DEFNODE("Node", "start end", {
}
}, null);
AST_Node.warn_function = null;
AST_Node.warn = function(txt, props) {
if (AST_Node.warn_function)
AST_Node.warn_function(string_template(txt, props));
if (AST_Node.warn_function) AST_Node.warn_function(string_template(txt, props));
};
/* -----[ statements ]----- */
@@ -134,11 +132,10 @@ var AST_Debugger = DEFNODE("Debugger", null, {
$documentation: "Represents a debugger statement",
}, AST_Statement);
var AST_Directive = DEFNODE("Directive", "value scope quote", {
var AST_Directive = DEFNODE("Directive", "value quote", {
$documentation: "Represents a directive, like \"use strict\";",
$propdoc: {
value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
scope: "[AST_Scope/S] The scope that this directive affects",
quote: "[string] the original quote character"
},
}, AST_Statement);
@@ -149,7 +146,7 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.body._walk(visitor);
});
}
@@ -159,19 +156,18 @@ function walk_body(node, visitor) {
var body = node.body;
if (body instanceof AST_Statement) {
body._walk(visitor);
}
else for (var i = 0, len = body.length; i < len; i++) {
body[i]._walk(visitor);
}
};
} else body.forEach(function(node) {
node._walk(visitor);
});
}
var AST_Block = DEFNODE("Block", "body", {
$documentation: "A body of statements (usually bracketed)",
$documentation: "A body of statements (usually braced)",
$propdoc: {
body: "[AST_Statement*] an array of statements"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
walk_body(this, visitor);
});
}
@@ -198,7 +194,7 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
label: "[AST_Label] a label definition"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.label._walk(visitor);
this.body._walk(visitor);
});
@@ -209,8 +205,7 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
var label = node.label;
var def = this.label;
node.walk(new TreeWalker(function(node) {
if (node instanceof AST_LoopControl
&& node.label && node.label.thedef === def) {
if (node instanceof AST_LoopControl && node.label && node.label.thedef === def) {
node.label.thedef = label;
label.references.push(node);
}
@@ -234,7 +229,7 @@ var AST_DWLoop = DEFNODE("DWLoop", "condition", {
var AST_Do = DEFNODE("Do", null, {
$documentation: "A `do` statement",
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.body._walk(visitor);
this.condition._walk(visitor);
});
@@ -244,7 +239,7 @@ var AST_Do = DEFNODE("Do", null, {
var AST_While = DEFNODE("While", null, {
$documentation: "A `while` statement",
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.condition._walk(visitor);
this.body._walk(visitor);
});
@@ -259,7 +254,7 @@ var AST_For = DEFNODE("For", "init condition step", {
step: "[AST_Node?] the `for` update clause, or null if empty"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
if (this.init) this.init._walk(visitor);
if (this.condition) this.condition._walk(visitor);
if (this.step) this.step._walk(visitor);
@@ -268,15 +263,14 @@ var AST_For = DEFNODE("For", "init condition step", {
}
}, AST_IterationStatement);
var AST_ForIn = DEFNODE("ForIn", "init name object", {
var AST_ForIn = DEFNODE("ForIn", "init object", {
$documentation: "A `for ... in` statement",
$propdoc: {
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"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.init._walk(visitor);
this.object._walk(visitor);
this.body._walk(visitor);
@@ -290,7 +284,7 @@ var AST_With = DEFNODE("With", "expression", {
expression: "[AST_Node] the `with` expression"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.expression._walk(visitor);
this.body._walk(visitor);
});
@@ -299,10 +293,9 @@ var AST_With = DEFNODE("With", "expression", {
/* -----[ scope and functions ]----- */
var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent_scope enclosed cname", {
$documentation: "Base class for all statements introducing a lexical scope",
$propdoc: {
directives: "[string*/S] an array of directives declared in this scope",
variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
functions: "[Object/S] like `variables`, but only lists function declarations",
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
@@ -311,6 +304,16 @@ var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_
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)",
},
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);
var AST_Toplevel = DEFNODE("Toplevel", "globals", {
@@ -322,12 +325,29 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
var body = this.body;
var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
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") {
return MAP.splice(body);
}
}));
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);
@@ -339,12 +359,11 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
if (this.name) this.name._walk(visitor);
var argnames = this.argnames;
for (var i = 0, len = argnames.length; i < len; i++) {
argnames[i]._walk(visitor);
}
this.argnames.forEach(function(argname) {
argname._walk(visitor);
});
walk_body(this, visitor);
});
}
@@ -354,11 +373,11 @@ var AST_Accessor = DEFNODE("Accessor", null, {
$documentation: "A setter/getter function. The `name` property is always null."
}, AST_Lambda);
var AST_Function = DEFNODE("Function", null, {
var AST_Function = DEFNODE("Function", "inlined", {
$documentation: "A function expression"
}, AST_Lambda);
var AST_Defun = DEFNODE("Defun", null, {
var AST_Defun = DEFNODE("Defun", "inlined", {
$documentation: "A function definition"
}, AST_Lambda);
@@ -374,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"
},
_walk: function(visitor) {
return visitor._visit(this, this.value && function(){
return visitor._visit(this, this.value && function() {
this.value._walk(visitor);
});
}
@@ -394,7 +413,7 @@ var AST_LoopControl = DEFNODE("LoopControl", "label", {
label: "[AST_LabelRef?] the label, or null if none",
},
_walk: function(visitor) {
return visitor._visit(this, this.label && function(){
return visitor._visit(this, this.label && function() {
this.label._walk(visitor);
});
}
@@ -417,7 +436,7 @@ var AST_If = DEFNODE("If", "condition alternative", {
alternative: "[AST_Statement?] the `else` part, or null if not present"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.condition._walk(visitor);
this.body._walk(visitor);
if (this.alternative) this.alternative._walk(visitor);
@@ -433,7 +452,7 @@ var AST_Switch = DEFNODE("Switch", "expression", {
expression: "[AST_Node] the `switch` “discriminant”"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.expression._walk(visitor);
walk_body(this, visitor);
});
@@ -454,7 +473,7 @@ var AST_Case = DEFNODE("Case", "expression", {
expression: "[AST_Node] the `case` expression"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.expression._walk(visitor);
walk_body(this, visitor);
});
@@ -470,7 +489,7 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", {
bfinally: "[AST_Finally?] the finally block, or null if not present"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
walk_body(this, visitor);
if (this.bcatch) this.bcatch._walk(visitor);
if (this.bfinally) this.bfinally._walk(visitor);
@@ -484,7 +503,7 @@ var AST_Catch = DEFNODE("Catch", "argname", {
argname: "[AST_SymbolCatch] symbol for the exception"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.argname._walk(visitor);
walk_body(this, visitor);
});
@@ -495,19 +514,18 @@ var AST_Finally = DEFNODE("Finally", null, {
$documentation: "A `finally` node; only makes sense as part of a `try` statement"
}, AST_Block);
/* -----[ VAR/CONST ]----- */
/* -----[ VAR ]----- */
var AST_Definitions = DEFNODE("Definitions", "definitions", {
$documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
$documentation: "Base class for `var` nodes (variable declarations/initializations)",
$propdoc: {
definitions: "[AST_VarDef*] array of variable definitions"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
var definitions = this.definitions;
for (var i = 0, len = definitions.length; i < len; i++) {
definitions[i]._walk(visitor);
}
return visitor._visit(this, function() {
this.definitions.forEach(function(defn) {
defn._walk(visitor);
});
});
}
}, AST_Statement);
@@ -516,18 +534,14 @@ var AST_Var = DEFNODE("Var", null, {
$documentation: "A `var` statement"
}, AST_Definitions);
var AST_Const = DEFNODE("Const", null, {
$documentation: "A `const` statement"
}, AST_Definitions);
var AST_VarDef = DEFNODE("VarDef", "name value", {
$documentation: "A variable declaration; only appears in a AST_Definitions node",
$propdoc: {
name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
name: "[AST_SymbolVar] name of the variable",
value: "[AST_Node?] initializer, or null of there's no initializer"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.name._walk(visitor);
if (this.value) this.value._walk(visitor);
});
@@ -543,12 +557,11 @@ var AST_Call = DEFNODE("Call", "expression args", {
args: "[AST_Node*] array of arguments"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
var args = this.args;
for (var i = 0, len = args.length; i < len; i++) {
args[i]._walk(visitor);
}
return visitor._visit(this, function() {
this.expression._walk(visitor);
this.args.forEach(function(node) {
node._walk(visitor);
});
});
}
});
@@ -563,7 +576,7 @@ var AST_Sequence = DEFNODE("Sequence", "expressions", {
expressions: "[AST_Node*] array of expressions (at least two)"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.expressions.forEach(function(node) {
node._walk(visitor);
});
@@ -582,7 +595,7 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
var AST_Dot = DEFNODE("Dot", null, {
$documentation: "A dotted property access expression",
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.expression._walk(visitor);
});
}
@@ -591,7 +604,7 @@ var AST_Dot = DEFNODE("Dot", null, {
var AST_Sub = DEFNODE("Sub", null, {
$documentation: "Index-style property access, i.e. `a[\"foo\"]`",
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.expression._walk(visitor);
this.property._walk(visitor);
});
@@ -605,7 +618,7 @@ var AST_Unary = DEFNODE("Unary", "operator expression", {
expression: "[AST_Node] expression that this unary operator applies to"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.expression._walk(visitor);
});
}
@@ -627,7 +640,7 @@ var AST_Binary = DEFNODE("Binary", "operator left right", {
right: "[AST_Node] right-hand side expression"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.left._walk(visitor);
this.right._walk(visitor);
});
@@ -642,7 +655,7 @@ var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative",
alternative: "[AST_Node]"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.condition._walk(visitor);
this.consequent._walk(visitor);
this.alternative._walk(visitor);
@@ -662,11 +675,10 @@ var AST_Array = DEFNODE("Array", "elements", {
elements: "[AST_Node*] array of elements"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
var elements = this.elements;
for (var i = 0, len = elements.length; i < len; i++) {
elements[i]._walk(visitor);
}
return visitor._visit(this, function() {
this.elements.forEach(function(element) {
element._walk(visitor);
});
});
}
});
@@ -677,11 +689,10 @@ var AST_Object = DEFNODE("Object", "properties", {
properties: "[AST_ObjectProperty*] array of properties"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
var properties = this.properties;
for (var i = 0, len = properties.length; i < len; i++) {
properties[i]._walk(visitor);
}
return visitor._visit(this, function() {
this.properties.forEach(function(prop) {
prop._walk(visitor);
});
});
}
});
@@ -689,11 +700,11 @@ var AST_Object = DEFNODE("Object", "properties", {
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
$documentation: "Base class for literal object properties",
$propdoc: {
key: "[string] the property name converted to a string for ObjectKeyVal. For setters and getters this is an arbitrary AST_Node.",
value: "[AST_Node] property value. For setters and getters this is an AST_Function."
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 getters and setters this is an AST_Accessor."
},
_walk: function(visitor) {
return visitor._visit(this, function(){
return visitor._visit(this, function() {
this.value._walk(visitor);
});
}
@@ -728,17 +739,13 @@ var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
}, AST_Symbol);
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
$documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
$documentation: "A declaration symbol (symbol in var, function name or argument, symbol in catch)",
}, AST_Symbol);
var AST_SymbolVar = DEFNODE("SymbolVar", null, {
$documentation: "Symbol defining a variable",
}, AST_SymbolDeclaration);
var AST_SymbolConst = DEFNODE("SymbolConst", null, {
$documentation: "A constant declaration"
}, AST_SymbolDeclaration);
var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
$documentation: "Symbol naming a function argument",
}, AST_SymbolVar);
@@ -824,12 +831,12 @@ var AST_NaN = DEFNODE("NaN", null, {
var AST_Undefined = DEFNODE("Undefined", null, {
$documentation: "The `undefined` value",
value: (function(){}())
value: function(){}()
}, AST_Atom);
var AST_Hole = DEFNODE("Hole", null, {
$documentation: "A hole in an array",
value: (function(){}())
value: function(){}()
}, AST_Atom);
var AST_Infinity = DEFNODE("Infinity", null, {
@@ -857,17 +864,17 @@ function TreeWalker(callback) {
this.visit = callback;
this.stack = [];
this.directives = Object.create(null);
};
}
TreeWalker.prototype = {
_visit: function(node, descend) {
this.push(node);
var ret = this.visit(node, descend ? function(){
var ret = this.visit(node, descend ? function() {
descend.call(node);
} : noop);
if (!ret && descend) {
descend.call(node);
}
this.pop(node);
this.pop();
return ret;
},
parent: function(n) {
@@ -881,9 +888,8 @@ TreeWalker.prototype = {
}
this.stack.push(node);
},
pop: function(node) {
this.stack.pop();
if (node instanceof AST_Lambda) {
pop: function() {
if (this.stack.pop() instanceof AST_Lambda) {
this.directives = Object.getPrototypeOf(this.directives);
}
},
@@ -909,24 +915,6 @@ TreeWalker.prototype = {
}
}
},
in_boolean_context: function() {
var stack = this.stack;
var i = stack.length, self = stack[--i];
while (i > 0) {
var p = stack[--i];
if ((p instanceof AST_If && p.condition === self) ||
(p instanceof AST_Conditional && p.condition === self) ||
(p instanceof AST_DWLoop && p.condition === self) ||
(p instanceof AST_For && p.condition === self) ||
(p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self))
{
return true;
}
if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")))
return false;
self = p;
}
},
loopcontrol_target: function(node) {
var stack = this.stack;
if (node.label) for (var i = stack.length; --i >= 0;) {
@@ -939,5 +927,25 @@ TreeWalker.prototype = {
|| node instanceof AST_Break && x instanceof AST_Switch)
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");
} : btoa;
function read_source_map(code) {
function read_source_map(name, code) {
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
if (!match) {
AST_Node.warn("inline source map not found");
AST_Node.warn("inline source map not found: " + name);
return null;
}
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) {
if (options[name]) {
keys.forEach(function(key) {
@@ -27,31 +35,54 @@ function set_shorthand(name, options, keys) {
}
}
function init_cache(cache) {
if (!cache) return;
if (!("props" in cache)) {
cache.props = new Dictionary();
} else if (!(cache.props instanceof Dictionary)) {
cache.props = Dictionary.fromObject(cache.props);
}
}
function to_json(cache) {
return {
props: cache.props.toObject()
};
}
function minify(files, options) {
var warn_function = AST_Node.warn_function;
try {
if (typeof files == "string") {
files = [ files ];
}
options = defaults(options, {
compress: {},
enclose: false,
ie8: false,
keep_fnames: false,
mangle: {},
nameCache: null,
output: {},
parse: {},
rename: undefined,
sourceMap: false,
timings: false,
toplevel: false,
warnings: false,
wrap: false,
}, true);
var timings = options.timings && {
start: Date.now()
};
if (options.rename === undefined) {
options.rename = options.compress && options.mangle;
}
set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
set_shorthand("warnings", options, [ "compress" ]);
var quoted_props;
if (options.mangle) {
options.mangle = defaults(options.mangle, {
cache: null,
cache: options.nameCache && (options.nameCache.vars || {}),
eval: false,
ie8: false,
keep_fnames: false,
@@ -59,6 +90,21 @@ function minify(files, options) {
reserved: [],
toplevel: false,
}, true);
if (options.mangle.properties) {
if (typeof options.mangle.properties != "object") {
options.mangle.properties = {};
}
if (options.mangle.properties.keep_quoted) {
quoted_props = options.mangle.properties.reserved;
if (!Array.isArray(quoted_props)) quoted_props = [];
options.mangle.properties.reserved = quoted_props;
}
if (options.nameCache && !("cache" in options.mangle.properties)) {
options.mangle.properties.cache = options.nameCache.props || {};
}
}
init_cache(options.mangle.cache);
init_cache(options.mangle.properties.cache);
}
if (options.sourceMap) {
options.sourceMap = defaults(options.sourceMap, {
@@ -75,57 +121,84 @@ function minify(files, options) {
warnings.push(warning);
};
}
var toplevel;
if (timings) timings.parse = Date.now();
var source_maps, toplevel;
if (files instanceof AST_Toplevel) {
toplevel = files;
} else {
if (typeof files == "string") {
files = [ files ];
}
options.parse = options.parse || {};
options.parse.toplevel = null;
for (var name in files) {
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)) {
options.parse.filename = name;
options.parse.toplevel = parse(files[name], options.parse);
if (options.sourceMap && options.sourceMap.content == "inline") {
if (Object.keys(files).length > 1)
throw new Error("inline source map only works with singular input");
options.sourceMap.content = read_source_map(files[name]);
if (source_maps) {
if (source_map_content == "inline") {
var inlined_content = read_source_map(name, files[name]);
if (inlined_content) {
source_maps[name] = parse_source_map(inlined_content);
}
} else {
source_maps[name] = source_map_content;
}
}
}
toplevel = options.parse.toplevel;
}
if (quoted_props) {
reserve_quoted_keys(toplevel, quoted_props);
}
if (options.wrap) {
toplevel = toplevel.wrap_commonjs(options.wrap);
}
if (options.compress) {
toplevel.figure_out_scope(options.mangle);
toplevel = new Compressor(options.compress).compress(toplevel);
if (options.enclose) {
toplevel = toplevel.wrap_enclose(options.enclose);
}
if (options.mangle) {
if (timings) timings.rename = Date.now();
if (options.rename) {
toplevel.figure_out_scope(options.mangle);
base54.reset();
toplevel.expand_names(options.mangle);
}
if (timings) timings.compress = Date.now();
if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
if (timings) timings.scope = Date.now();
if (options.mangle) toplevel.figure_out_scope(options.mangle);
if (timings) timings.mangle = Date.now();
if (options.mangle) {
toplevel.compute_char_frequency(options.mangle);
toplevel.mangle_names(options.mangle);
if (options.mangle.properties) {
toplevel = mangle_properties(toplevel, options.mangle.properties);
}
}
if (timings) timings.properties = Date.now();
if (options.mangle && options.mangle.properties) {
toplevel = mangle_properties(toplevel, options.mangle.properties);
}
if (timings) timings.output = Date.now();
var result = {};
if (options.output.ast) {
result.ast = toplevel;
}
if (!HOP(options.output, "code") || options.output.code) {
if (options.sourceMap) {
if (typeof options.sourceMap.content == "string") {
options.sourceMap.content = JSON.parse(options.sourceMap.content);
}
options.output.source_map = SourceMap({
file: options.sourceMap.filename,
orig: options.sourceMap.content,
orig: source_maps,
root: options.sourceMap.root
});
if (options.sourceMap.includeSources) {
for (var name in files) {
if (files instanceof AST_Toplevel) {
throw new Error("original source content unavailable");
} else for (var name in files) if (HOP(files, name)) {
options.output.source_map.get().setSourceContent(name, files[name]);
}
} else {
options.output.source_map.get()._sourcesContents = null;
}
}
delete options.output.ast;
@@ -142,6 +215,25 @@ function minify(files, options) {
}
}
}
if (options.nameCache && options.mangle) {
if (options.mangle.cache) options.nameCache.vars = to_json(options.mangle.cache);
if (options.mangle.properties && options.mangle.properties.cache) {
options.nameCache.props = to_json(options.mangle.properties.cache);
}
}
if (timings) {
timings.end = Date.now();
result.timings = {
parse: 1e-3 * (timings.rename - timings.parse),
rename: 1e-3 * (timings.compress - timings.rename),
compress: 1e-3 * (timings.scope - timings.compress),
scope: 1e-3 * (timings.mangle - timings.scope),
mangle: 1e-3 * (timings.properties - timings.mangle),
properties: 1e-3 * (timings.output - timings.properties),
output: 1e-3 * (timings.end - timings.output),
total: 1e-3 * (timings.end - timings.start)
}
}
if (warnings.length) {
result.warnings = warnings;
}

View File

@@ -43,11 +43,9 @@
"use strict";
(function(){
var normalize_directives = function(body) {
(function() {
function normalize_directives(body) {
var in_directive = true;
for (var i = 0; i < body.length; i++) {
if (in_directive && body[i] instanceof AST_Statement && body[i].body instanceof AST_String) {
body[i] = new AST_Directive({
@@ -59,9 +57,8 @@
in_directive = false;
}
}
return body;
};
}
var MOZ_TO_ME = {
Program: function(M) {
@@ -111,29 +108,25 @@
},
Property: function(M) {
var key = M.key;
var name = key.type == "Identifier" ? key.name : key.value;
var args = {
start : my_start_token(key),
end : my_end_token(M.value),
key : name,
key : key.type == "Identifier" ? key.name : key.value,
value : from_moz(M.value)
};
switch (M.kind) {
case "init":
return new AST_ObjectKeyVal(args);
case "set":
args.value.name = from_moz(key);
return new AST_ObjectSetter(args);
case "get":
args.value.name = from_moz(key);
return new AST_ObjectGetter(args);
}
if (M.kind == "init") return new AST_ObjectKeyVal(args);
args.key = new AST_SymbolAccessor({
name: args.key
});
args.value = new AST_Accessor(args.value);
if (M.kind == "get") return new AST_ObjectGetter(args);
if (M.kind == "set") return new AST_ObjectSetter(args);
},
ArrayExpression: function(M) {
return new AST_Array({
start : my_start_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);
})
});
@@ -142,7 +135,7 @@
return new AST_Object({
start : my_start_token(M),
end : my_end_token(M),
properties : M.properties.map(function(prop){
properties : M.properties.map(function(prop) {
prop.type = "Property";
return from_moz(prop)
})
@@ -172,7 +165,7 @@
});
},
VariableDeclaration: function(M) {
return new (M.kind === "const" ? AST_Const : AST_Var)({
return new AST_Var({
start : my_start_token(M),
end : my_end_token(M),
definitions : M.declarations.map(from_moz)
@@ -184,6 +177,17 @@
end : my_end_token(M)
};
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) {
case "string":
args.value = val;
@@ -193,22 +197,12 @@
return new AST_Number(args);
case "boolean":
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) {
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
return new ( p.type == "LabeledStatement" ? AST_Label
: p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar)
: p.type == "VariableDeclarator" && p.id === M ? AST_SymbolVar
: p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
: p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
: p.type == "CatchClause" ? AST_SymbolCatch
@@ -260,10 +254,7 @@
map("CallExpression", AST_Call, "callee>expression, arguments@args");
def_to_moz(AST_Toplevel, function To_Moz_Program(M) {
return {
type: "Program",
body: M.body.map(to_moz)
};
return to_moz_scope("Program", M);
});
def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) {
@@ -271,7 +262,7 @@
type: "FunctionDeclaration",
id: to_moz(M.name),
params: M.argnames.map(to_moz),
body: to_moz_block(M)
body: to_moz_scope("BlockStatement", M)
}
});
@@ -280,7 +271,7 @@
type: "FunctionExpression",
id: to_moz(M.name),
params: M.argnames.map(to_moz),
body: to_moz_block(M)
body: to_moz_scope("BlockStatement", M)
}
});
@@ -331,7 +322,7 @@
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
return {
type: "VariableDeclaration",
kind: M instanceof AST_Const ? "const" : "var",
kind: "var",
declarations: M.definitions.map(to_moz)
};
});
@@ -386,11 +377,10 @@
});
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
var key = (
is_identifier(M.key)
? {type: "Identifier", name: M.key}
: {type: "Literal", value: M.key}
);
var key = {
type: "Literal",
value: M.key instanceof AST_SymbolAccessor ? M.key.name : M.key
};
var kind;
if (M instanceof AST_ObjectKeyVal) {
kind = "init";
@@ -418,14 +408,15 @@
});
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 {
type: "Literal",
value: value,
raw: value.toString(),
raw: value,
regex: {
pattern: value.source,
flags: value.toString().match(/[gimuy]*$/)[0]
pattern: M.value.raw_source,
flags: flags
}
};
});
@@ -486,7 +477,7 @@
endpos : range ? range[0] : moznode.start,
raw : raw_token(moznode),
});
};
}
function my_end_token(moznode) {
var loc = moznode.loc, end = loc && loc.end;
@@ -501,7 +492,7 @@
endpos : range ? range[1] : moznode.end,
raw : raw_token(moznode),
});
};
}
function map(moztype, mytype, propmap) {
var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
@@ -513,7 +504,7 @@
me_to_moz += "return {\n" +
"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);
if (!m) throw new Error("Can't understand property map: " + prop);
var moz = m[1], how = m[2], my = m[3];
@@ -551,12 +542,12 @@
moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
exports, my_start_token, my_end_token, from_moz
);
me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(
to_moz, to_moz_block
me_to_moz = new Function("to_moz", "to_moz_block", "to_moz_scope", "return(" + me_to_moz + ")")(
to_moz, to_moz_block, to_moz_scope
);
MOZ_TO_ME[moztype] = moz_to_me;
def_to_moz(mytype, me_to_moz);
};
}
var FROM_MOZ_STACK = null;
@@ -565,13 +556,28 @@
var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
FROM_MOZ_STACK.pop();
return ret;
};
}
AST_Node.from_mozilla_ast = function(node){
AST_Node.from_mozilla_ast = function(node) {
var save_stack = FROM_MOZ_STACK;
FROM_MOZ_STACK = [];
var ast = from_moz(node);
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;
};
@@ -591,23 +597,33 @@
}
}
return moznode;
};
}
function def_to_moz(mytype, handler) {
mytype.DEFMETHOD("to_mozilla_ast", function() {
return set_moz_loc(this, handler(this));
});
};
}
function to_moz(node) {
return node != null ? node.to_mozilla_ast() : null;
};
}
function to_moz_block(node) {
return {
type: "BlockStatement",
body: node.body.map(to_moz)
};
};
}
function to_moz_scope(type, node) {
var body = node.body.map(to_moz);
if (node.body[0] instanceof AST_SimpleStatement && node.body[0].body instanceof AST_String) {
body.unshift(to_moz(new AST_EmptyStatement(node.body[0])));
}
return {
type: type,
body: body
};
}
})();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -53,20 +53,57 @@ function find_builtins(reserved) {
"-Infinity",
"undefined",
].forEach(add);
[ Object, Array, Function, Number,
String, Boolean, Error, Math,
Date, RegExp
].forEach(function(ctor){
[
Array,
Boolean,
Date,
Error,
Function,
Math,
Number,
Object,
RegExp,
String,
].forEach(function(ctor) {
Object.getOwnPropertyNames(ctor).map(add);
if (ctor.prototype) {
Object.getOwnPropertyNames(ctor.prototype).map(add);
}
});
function add(name) {
push_uniq(reserved, name);
}
}
function reserve_quoted_keys(ast, reserved) {
ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ObjectKeyVal && node.quote) {
add(node.key);
} else if (node instanceof AST_Sub) {
addStrings(node.property, add);
}
}));
function add(name) {
push_uniq(reserved, name);
}
}
function addStrings(node, add) {
node.walk(new TreeWalker(function(node) {
if (node instanceof AST_Sequence) {
addStrings(node.tail_node(), add);
} else if (node instanceof AST_String) {
add(node.value);
} else if (node instanceof AST_Conditional) {
addStrings(node.consequent, add);
addStrings(node.alternative, add);
}
return true;
}));
}
function mangle_properties(ast, options) {
options = defaults(options, {
builtins: false,
@@ -76,81 +113,67 @@ function mangle_properties(ast, options) {
only_cache: false,
regex: null,
reserved: null,
});
}, true);
var reserved = options.reserved || [];
var reserved = options.reserved;
if (!Array.isArray(reserved)) reserved = [];
if (!options.builtins) find_builtins(reserved);
var cache = options.cache;
if (cache == null) {
cache = {
cname: -1,
props: new Dictionary()
};
var cname = -1;
var cache;
if (options.cache) {
cache = options.cache.props;
cache.each(function(mangled_name) {
push_uniq(reserved, mangled_name);
});
} else {
cache = new Dictionary();
}
var regex = options.regex;
var keep_quoted = options.keep_quoted;
// note debug is either false (disabled), or a string of the debug suffix to use (enabled).
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
// the same as passing an empty string.
var debug = options.debug !== false;
var debug_name_suffix;
if (debug) {
debug_name_suffix = (options.debug === true ? "" : options.debug);
}
var debug_suffix;
if (debug) debug_suffix = options.debug === true ? "" : options.debug;
var names_to_mangle = [];
var unmangleable = [];
var to_keep = {};
// step 1: find candidates to mangle
ast.walk(new TreeWalker(function(node){
ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ObjectKeyVal) {
add(node.key, keep_quoted && node.quote);
}
else if (node instanceof AST_ObjectProperty) {
add(node.key);
} else if (node instanceof AST_ObjectProperty) {
// setter or getter, since KeyVal is handled above
add(node.key.name);
}
else if (node instanceof AST_Dot) {
} else if (node instanceof AST_Dot) {
add(node.property);
}
else if (node instanceof AST_Sub) {
addStrings(node.property, keep_quoted);
} else if (node instanceof AST_Sub) {
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
return ast.transform(new TreeTransformer(function(node){
return ast.transform(new TreeTransformer(function(node) {
if (node instanceof AST_ObjectKeyVal) {
if (!(keep_quoted && node.quote))
node.key = mangle(node.key);
}
else if (node instanceof AST_ObjectProperty) {
node.key = mangle(node.key);
} else if (node instanceof AST_ObjectProperty) {
// setter or getter
node.key.name = mangle(node.key.name);
}
else if (node instanceof AST_Dot) {
} else if (node instanceof AST_Dot) {
node.property = mangle(node.property);
} else if (!options.keep_quoted && node instanceof AST_Sub) {
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]);
}
else if (node instanceof AST_Sub) {
if (!keep_quoted)
node.property = mangleStrings(node.property);
}
// else if (node instanceof AST_String) {
// if (should_mangle(node.value)) {
// AST_Node.warn(
// "Found \"{prop}\" property candidate for mangling in an arbitrary string [{file}:{line},{col}]", {
// file : node.start.file,
// line : node.start.line,
// col : node.start.col,
// prop : node.value
// }
// );
// }
// }
}));
// only function declarations after this line
@@ -158,102 +181,50 @@ function mangle_properties(ast, options) {
function can_mangle(name) {
if (unmangleable.indexOf(name) >= 0) return false;
if (reserved.indexOf(name) >= 0) return false;
if (options.only_cache) {
return cache.props.has(name);
}
if (options.only_cache) return cache.has(name);
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
return true;
}
function should_mangle(name) {
if (keep_quoted && name in to_keep) return false;
if (regex && !regex.test(name)) return false;
if (reserved.indexOf(name) >= 0) return false;
return cache.props.has(name)
|| names_to_mangle.indexOf(name) >= 0;
return cache.has(name) || names_to_mangle.indexOf(name) >= 0;
}
function add(name, keep) {
if (keep) {
to_keep[name] = true;
return;
}
if (can_mangle(name))
push_uniq(names_to_mangle, name);
if (!should_mangle(name)) {
push_uniq(unmangleable, name);
}
function add(name) {
if (can_mangle(name)) push_uniq(names_to_mangle, name);
if (!should_mangle(name)) push_uniq(unmangleable, name);
}
function mangle(name) {
if (!should_mangle(name)) {
return name;
}
var mangled = cache.props.get(name);
var mangled = cache.get(name);
if (!mangled) {
if (debug) {
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
if (can_mangle(debug_mangled) && !(keep_quoted && debug_mangled in to_keep)) {
mangled = debug_mangled;
}
var debug_mangled = "_$" + name + "$" + debug_suffix + "_";
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
if (!mangled) {
// Note: `can_mangle()` does not check if the name collides with the `to_keep` set
// (filled with quoted properties when `keep_quoted` is set). Make sure we add this
// check so we don't collide with a quoted name.
do {
mangled = base54(++cache.cname);
} while (!can_mangle(mangled) || keep_quoted && mangled in to_keep);
}
cache.props.set(name, mangled);
if (!mangled) do {
mangled = base54(++cname);
} while (!can_mangle(mangled));
cache.set(name, mangled);
}
return mangled;
}
function addStrings(node, keep) {
var out = {};
try {
(function walk(node){
node.walk(new TreeWalker(function(node){
if (node instanceof AST_Sequence) {
walk(node.expressions[node.expressions.length - 1]);
return true;
}
if (node instanceof AST_String) {
add(node.value, keep);
return true;
}
if (node instanceof AST_Conditional) {
walk(node.consequent);
walk(node.alternative);
return true;
}
throw out;
}));
})(node);
} catch(ex) {
if (ex !== out) throw ex;
}
}
function mangleStrings(node) {
return node.transform(new TreeTransformer(function(node){
return node.transform(new TreeTransformer(function(node) {
if (node instanceof AST_Sequence) {
var last = node.expressions.length - 1;
node.expressions[last] = mangleStrings(node.expressions[last]);
}
else if (node instanceof AST_String) {
} else if (node instanceof AST_String) {
node.value = mangle(node.value);
}
else if (node instanceof AST_Conditional) {
} else if (node instanceof AST_Conditional) {
node.consequent = mangleStrings(node.consequent);
node.alternative = mangleStrings(node.alternative);
}

View File

@@ -43,17 +43,19 @@
"use strict";
function SymbolDef(scope, index, orig) {
function SymbolDef(scope, orig, init) {
this.name = orig.name;
this.orig = [ orig ];
this.init = init;
this.eliminated = 0;
this.scope = scope;
this.references = [];
this.replaced = 0;
this.global = false;
this.mangled_name = null;
this.undeclared = false;
this.index = index;
this.id = SymbolDef.next_id++;
};
}
SymbolDef.next_id = 1;
@@ -61,36 +63,35 @@ SymbolDef.prototype = {
unmangleable: function(options) {
if (!options) options = {};
return (this.global && !options.toplevel)
return this.global && !options.toplevel
|| this.undeclared
|| (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
|| (options.keep_fnames
|| !options.eval && this.scope.pinned()
|| options.keep_fnames
&& (this.orig[0] instanceof AST_SymbolLambda
|| this.orig[0] instanceof AST_SymbolDefun));
|| this.orig[0] instanceof AST_SymbolDefun);
},
mangle: function(options) {
var cache = options.cache && options.cache.props;
if (this.global && cache && cache.has(this.name)) {
this.mangled_name = cache.get(this.name);
}
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;
} else if (!this.mangled_name && !this.unmangleable(options)) {
var def;
if (this.defun && (def = this.defun.variables.get(this.name))) {
if (def = this.redefined()) {
this.mangled_name = def.mangled_name || def.name;
} else
this.mangled_name = s.next_mangled(options, this);
} else {
this.mangled_name = next_mangled_name(this.scope, options, this);
}
if (this.global && cache) {
cache.set(this.name, this.mangled_name);
}
}
},
redefined: function() {
return this.defun && this.defun.variables.get(this.name);
}
};
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
options = defaults(options, {
cache: null,
ie8: false,
@@ -99,9 +100,8 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
// pass 1: setup scope chaining and handle definitions
var self = this;
var scope = self.parent_scope = null;
var labels = new Dictionary();
var defun = null;
var tw = new TreeWalker(function(node, descend){
var tw = new TreeWalker(function(node, descend) {
if (node instanceof AST_Catch) {
var save_scope = scope;
scope = new AST_Scope(node);
@@ -114,28 +114,14 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
node.init_scope_vars(scope);
var save_scope = scope;
var save_defun = defun;
var save_labels = labels;
defun = scope = node;
labels = new Dictionary();
descend();
scope = save_scope;
defun = save_defun;
labels = save_labels;
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
return true;
}
if (node instanceof AST_With) {
for (var s = scope; s; s = s.parent_scope)
s.uses_with = true;
for (var s = scope; s; s = s.parent_scope) s.uses_with = true;
return;
}
if (node instanceof AST_Symbol) {
@@ -145,57 +131,34 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
node.thedef = node;
node.references = [];
}
if (node instanceof AST_SymbolLambda) {
defun.def_function(node);
}
else if (node instanceof AST_SymbolDefun) {
// Careful here, the scope where this should be defined is
// the parent scope. The reason is that we enter a new
// scope when we encounter the AST_Defun node (which is
// instanceof AST_Scope) but we get to the symbol a bit
// later.
(node.scope = defun.parent_scope).def_function(node);
}
else if (node instanceof AST_SymbolVar
|| node instanceof AST_SymbolConst) {
defun.def_variable(node);
if (node instanceof AST_SymbolDefun) {
// This should be defined in the parent scope, as we encounter the
// AST_Defun node before getting to its AST_Symbol.
(node.scope = defun.parent_scope.resolve()).def_function(node, defun);
} else if (node instanceof AST_SymbolLambda) {
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
if (options.ie8) def.defun = defun.parent_scope.resolve();
} else if (node instanceof AST_SymbolVar) {
defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
if (defun !== scope) {
node.mark_enclosed(options);
var def = scope.find_variable(node);
if (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;
}
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);
// pass 2: find back references and eval
var func = null;
var globals = self.globals = new Dictionary();
var tw = new TreeWalker(function(node, descend){
if (node instanceof AST_Lambda) {
var prev_func = func;
func = node;
descend();
func = prev_func;
return true;
}
if (node instanceof AST_LoopControl && node.label) {
node.label.thedef.references.push(node);
self.globals = new Dictionary();
var tw = new TreeWalker(function(node) {
if (node instanceof AST_LoopControl) {
if (node.label) node.label.thedef.references.push(node);
return true;
}
if (node instanceof AST_SymbolRef) {
@@ -206,48 +169,62 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
}
}
var sym = node.scope.find_variable(name);
if (node.scope instanceof AST_Lambda && name == "arguments") {
node.scope.uses_arguments = true;
}
if (!sym) {
sym = self.def_global(node);
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
sym.scope.uses_arguments = true;
}
node.thedef = sym;
node.reference(options);
return true;
}
// ensure mangling works if catch reuses a scope variable
if (node instanceof AST_SymbolCatch) {
var def = node.definition().redefined();
if (def) for (var s = node.scope; s; s = s.parent_scope) {
push_uniq(s.enclosed, def);
if (s === def.scope) break;
}
return true;
}
});
self.walk(tw);
// pass 3: fix up any scoping issue with IE8
if (options.ie8) {
self.walk(new TreeWalker(function(node, descend) {
if (node instanceof AST_SymbolCatch) {
var name = node.name;
var refs = node.thedef.references;
var scope = node.thedef.defun;
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;
return true;
if (options.ie8) self.walk(new TreeWalker(function(node) {
if (node instanceof AST_SymbolCatch) {
redefine(node, node.thedef.defun);
return true;
}
if (node instanceof AST_SymbolLambda) {
var def = node.thedef;
if (def.orig.length == 1) {
redefine(node, node.scope.parent_scope);
node.thedef.init = def.init;
}
}));
}
return true;
}
}));
if (options.cache) {
this.cname = options.cache.cname;
function redefine(node, scope) {
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;
if (globals.has(name)) {
return globals.get(name);
} else {
var g = new SymbolDef(this, globals.size(), node);
var g = new SymbolDef(this, node);
g.undeclared = true;
g.global = true;
globals.set(name, g);
@@ -255,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.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
@@ -265,10 +242,10 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){
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);
this.uses_arguments = false;
this.def_variable(new AST_SymbolConst({
this.def_variable(new AST_SymbolFunarg({
name: "arguments",
start: this.start,
end: this.end
@@ -277,8 +254,7 @@ AST_Lambda.DEFMETHOD("init_scope_vars", function(){
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
var def = this.definition();
var s = this.scope;
while (s) {
for (var s = this.scope; s; s = s.parent_scope) {
push_uniq(s.enclosed, def);
if (options.keep_fnames) {
s.functions.each(function(d) {
@@ -286,7 +262,6 @@ AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
});
}
if (s === def.scope) break;
s = s.parent_scope;
}
});
@@ -295,280 +270,331 @@ AST_Symbol.DEFMETHOD("reference", function(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;
return this.variables.get(name)
|| (this.parent_scope && this.parent_scope.find_variable(name));
});
AST_Scope.DEFMETHOD("def_function", function(symbol){
this.functions.set(symbol.name, this.def_variable(symbol));
AST_Scope.DEFMETHOD("def_function", function(symbol, init) {
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){
var def;
if (!this.variables.has(symbol.name)) {
def = new SymbolDef(this, this.variables.size(), symbol);
AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
var def = this.variables.get(symbol.name);
if (def) {
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);
def.global = !this.parent_scope;
} else {
def = this.variables.get(symbol.name);
def.orig.push(symbol);
}
return symbol.thedef = def;
});
AST_Scope.DEFMETHOD("next_mangled", function(options){
var ext = this.enclosed;
out: while (true) {
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 (options.reserved.indexOf(m) >= 0) 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_Lambda.DEFMETHOD("resolve", return_this);
AST_Scope.DEFMETHOD("resolve", function() {
return this.parent_scope;
});
AST_Toplevel.DEFMETHOD("resolve", return_this);
AST_Function.DEFMETHOD("next_mangled", function(options, def){
// #179, #326
// in Safari strict mode, something like (function x(x){...}) is a syntax error;
// a function expression's argument cannot shadow the function expression's name
var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition();
// the function's mangled_name is null when keep_fnames is true
var tricky_name = tricky_def ? tricky_def.mangled_name || tricky_def.name : null;
function names_in_use(scope, options) {
var names = scope.names_in_use;
if (!names) {
scope.names_in_use = names = Object.create(scope.mangled_names || null);
scope.cname_holes = [];
var cache = options.cache && options.cache.props;
scope.enclosed.forEach(function(def) {
if (def.unmangleable(options)) names[def.name] = true;
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) {
var name = AST_Lambda.prototype.next_mangled.call(this, options, def);
if (!tricky_name || tricky_name != name)
return name;
name = base54(++scope.cname);
if (in_use[name] || !is_identifier(name) || options.reserved.has[name]) continue;
if (!names[name]) break;
holes.push(scope.cname);
}
});
scope.names_in_use[name] = true;
return name;
}
AST_Symbol.DEFMETHOD("unmangleable", function(options){
return this.definition().unmangleable(options);
});
// property accessors are not mangleable
AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){
return true;
AST_Symbol.DEFMETHOD("unmangleable", function(options) {
var def = this.definition();
return !def || def.unmangleable(options);
});
// labels are always mangleable
AST_Label.DEFMETHOD("unmangleable", function(){
return false;
AST_Label.DEFMETHOD("unmangleable", return_false);
AST_Symbol.DEFMETHOD("unreferenced", function() {
return !this.definition().references.length && !this.scope.pinned();
});
AST_Symbol.DEFMETHOD("unreferenced", function(){
return this.definition().references.length == 0
&& !(this.scope.uses_eval || this.scope.uses_with);
});
AST_Symbol.DEFMETHOD("undeclared", function(){
return this.definition().undeclared;
});
AST_LabelRef.DEFMETHOD("undeclared", function(){
return false;
});
AST_Label.DEFMETHOD("undeclared", function(){
return false;
});
AST_Symbol.DEFMETHOD("definition", function(){
AST_Symbol.DEFMETHOD("definition", function() {
return this.thedef;
});
AST_Symbol.DEFMETHOD("global", function(){
AST_Symbol.DEFMETHOD("global", function() {
return this.definition().global;
});
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
return defaults(options, {
function _default_mangler_options(options) {
options = defaults(options, {
eval : false,
ie8 : false,
keep_fnames : false,
reserved : [],
toplevel : false,
});
});
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
options = this._default_mangler_options(options);
if (!Array.isArray(options.reserved)) options.reserved = [];
// Never mangle arguments
options.reserved.push('arguments');
push_uniq(options.reserved, "arguments");
options.reserved.has = makePredicate(options.reserved);
return options;
}
AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
options = _default_mangler_options(options);
// We only need to mangle declaration nodes. Special logic wired
// 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
// the AST_SymbolDeclaration that it points to).
var lname = -1;
var to_mangle = [];
if (options.cache) {
this.globals.each(function(symbol){
if (options.reserved.indexOf(symbol.name) < 0) {
to_mangle.push(symbol);
}
if (options.cache && options.cache.props) {
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) {
// lname is incremented when we get to the AST_Label
var save_nesting = lname;
descend();
lname = save_nesting;
return true; // don't descend again in TreeWalker
return true;
}
if (node instanceof AST_Scope) {
var p = tw.parent(), a = [];
node.variables.each(function(symbol){
if (options.reserved.indexOf(symbol.name) < 0) {
a.push(symbol);
}
});
to_mangle.push.apply(to_mangle, a);
return;
descend();
if (options.cache && node instanceof AST_Toplevel) {
node.globals.each(mangle);
}
node.variables.each(mangle);
return true;
}
if (node instanceof AST_Label) {
var name;
do name = base54(++lname); while (!is_identifier(name));
do {
name = base54(++lname);
} while (!is_identifier(name));
node.mangled_name = name;
return true;
}
if (!options.ie8 && node instanceof AST_SymbolCatch) {
to_mangle.push(node.definition());
return;
if (!options.ie8 && node instanceof AST_Catch) {
var def = node.argname.definition();
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);
to_mangle.forEach(function(def){ def.mangle(options) });
redefined.forEach(mangle);
if (options.cache) {
options.cache.cname = this.cname;
function mangle(def) {
if (options.reserved.has[def.name]) return;
def.mangle(options);
}
});
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
options = this._default_mangler_options(options);
var tw = new TreeWalker(function(node){
if (node instanceof AST_Constant)
base54.consider(node.print_to_string());
else if (node instanceof AST_Return)
base54.consider("return");
else if (node instanceof AST_Throw)
base54.consider("throw");
else if (node instanceof AST_Continue)
base54.consider("continue");
else if (node instanceof AST_Break)
base54.consider("break");
else if (node instanceof AST_Debugger)
base54.consider("debugger");
else if (node instanceof AST_Directive)
base54.consider(node.value);
else if (node instanceof AST_While)
base54.consider("while");
else if (node instanceof AST_Do)
base54.consider("do while");
else if (node instanceof AST_If) {
base54.consider("if");
if (node.alternative) base54.consider("else");
}
else if (node instanceof AST_Var)
base54.consider("var");
else if (node instanceof AST_Const)
base54.consider("const");
else if (node instanceof AST_Lambda)
base54.consider("function");
else if (node instanceof AST_For)
base54.consider("for");
else if (node instanceof AST_ForIn)
base54.consider("for in");
else if (node instanceof AST_Switch)
base54.consider("switch");
else if (node instanceof AST_Case)
base54.consider("case");
else if (node instanceof AST_Default)
base54.consider("default");
else if (node instanceof AST_With)
base54.consider("with");
else if (node instanceof AST_ObjectSetter)
base54.consider("set" + node.key);
else if (node instanceof AST_ObjectGetter)
base54.consider("get" + node.key);
else if (node instanceof AST_ObjectKeyVal)
base54.consider(node.key);
else if (node instanceof AST_New)
base54.consider("new");
else if (node instanceof AST_This)
base54.consider("this");
else if (node instanceof AST_Try)
base54.consider("try");
else if (node instanceof AST_Catch)
base54.consider("catch");
else if (node instanceof AST_Finally)
base54.consider("finally");
else if (node instanceof AST_Symbol && node.unmangleable(options))
base54.consider(node.name);
else if (node instanceof AST_Unary || node instanceof AST_Binary)
base54.consider(node.operator);
else if (node instanceof AST_Dot)
base54.consider(node.property);
});
this.walk(tw);
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
var cache = options.cache && options.cache.props;
var avoid = Object.create(null);
options.reserved.forEach(to_avoid);
this.globals.each(add_def);
this.walk(new TreeWalker(function(node) {
if (node instanceof AST_Scope) node.variables.each(add_def);
if (node instanceof AST_SymbolCatch) add_def(node.definition());
}));
return avoid;
function to_avoid(name) {
avoid[name] = true;
}
function add_def(def) {
var name = def.name;
if (def.global && cache && cache.has(name)) name = cache.get(name);
else if (!def.unmangleable(options)) return;
to_avoid(name);
}
});
AST_Toplevel.DEFMETHOD("expand_names", function(options) {
base54.reset();
base54.sort();
options = _default_mangler_options(options);
var avoid = this.find_colliding_names(options);
var cname = 0;
this.globals.each(rename);
this.walk(new TreeWalker(function(node) {
if (node instanceof AST_Scope) node.variables.each(rename);
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) {
if (def.global && options.cache) return;
if (def.unmangleable(options)) return;
if (options.reserved.has[def.name]) return;
var d = def.redefined();
def.name = d ? d.name : next_name();
def.orig.forEach(function(sym) {
sym.name = def.name;
});
def.references.forEach(function(sym) {
sym.name = def.name;
});
}
});
AST_Node.DEFMETHOD("tail_node", return_this);
AST_Sequence.DEFMETHOD("tail_node", function() {
return this.expressions[this.expressions.length - 1];
});
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
options = _default_mangler_options(options);
base54.reset();
try {
AST_Node.prototype.print = function(stream, force_parens) {
this._print(stream, force_parens);
if (this instanceof AST_Symbol && !this.unmangleable(options)) {
base54.consider(this.name, -1);
} else if (options.properties) {
if (this instanceof AST_Dot) {
base54.consider(this.property, -1);
} else if (this instanceof AST_Sub) {
skip_string(this.property);
}
}
};
base54.consider(this.print_to_string(), 1);
} finally {
AST_Node.prototype.print = AST_Node.prototype._print;
}
base54.sort();
function skip_string(node) {
if (node instanceof AST_String) {
base54.consider(node.value, -1);
} else if (node instanceof AST_Conditional) {
skip_string(node.consequent);
skip_string(node.alternative);
} else if (node instanceof AST_Sequence) {
skip_string(node.tail_node());
}
}
});
var base54 = (function() {
var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
var freq = Object.create(null);
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;
function reset() {
frequency = Object.create(null);
chars = string.split("").map(function(ch){ return ch.charCodeAt(0) });
chars.forEach(function(ch){ frequency[ch] = 0 });
frequency = Object.create(freq);
}
base54.consider = function(str){
base54.consider = function(str, delta) {
for (var i = str.length; --i >= 0;) {
var code = str.charCodeAt(i);
if (code in frequency) ++frequency[code];
frequency[str[i]] += delta;
}
};
function compare(a, b) {
return frequency[b] - frequency[a];
}
base54.sort = function() {
chars = mergeSort(chars, function(a, b){
if (is_digit(a) && !is_digit(b)) return 1;
if (is_digit(b) && !is_digit(a)) return -1;
return frequency[b] - frequency[a];
});
chars = leading.sort(compare).concat(digits.sort(compare));
};
base54.reset = reset;
reset();
base54.get = function(){ return chars };
base54.freq = function(){ return frequency };
function base54(num) {
var ret = "", base = 54;
num++;
do {
num--;
ret += String.fromCharCode(chars[num % base]);
ret += chars[num % base];
num = Math.floor(num / base);
base = 64;
} while (num > 0);
return ret;
};
}
return base54;
})();

View File

@@ -46,52 +46,59 @@
// a small wrapper around fitzgen's source-map library
function SourceMap(options) {
options = defaults(options, {
file : null,
root : null,
orig : null,
orig_line_diff : 0,
dest_line_diff : 0,
});
file: null,
root: null,
orig: null,
orig_line_diff: 0,
dest_line_diff: 0,
}, true);
var generator = new MOZ_SourceMap.SourceMapGenerator({
file : options.file,
sourceRoot : options.root
file: options.file,
sourceRoot: options.root
});
var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
if (orig_map && Array.isArray(options.orig.sources)) {
orig_map._sources.toArray().forEach(function(source) {
var sourceContent = orig_map.sourceContentFor(source, true);
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
var maps = options.orig && Object.create(null);
if (maps) for (var source in options.orig) {
var map = new MOZ_SourceMap.SourceMapConsumer(options.orig[source]);
if (Array.isArray(options.orig[source].sources)) {
map._sources.toArray().forEach(function(source) {
var sourceContent = map.sourceContentFor(source, true);
if (sourceContent) generator.setSourceContent(source, sourceContent);
});
if (info.source === null) {
return;
}
source = info.source;
orig_line = info.line;
orig_col = info.column;
name = info.name || name;
}
generator.addMapping({
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
});
};
maps[source] = map;
}
return {
add : add,
get : function() { return generator },
toString : function() { return JSON.stringify(generator.toJSON()); }
add: function(source, gen_line, gen_col, orig_line, orig_col, name) {
var map = maps && maps[source];
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";
// Tree transformer helpers.
function TreeTransformer(before, after) {
TreeWalker.call(this);
this.before = before;
@@ -52,166 +50,136 @@ function TreeTransformer(before, after) {
}
TreeTransformer.prototype = new TreeWalker;
(function(undefined){
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) {
if (!tw.after) {
x = this;
descend(x, tw);
} else {
tw.stack[tw.stack.length - 1] = x = this;
descend(x, tw);
y = tw.after(x, in_list);
if (y !== undefined) x = y;
}
}
tw.pop(this);
return x;
});
};
(function(DEF) {
function do_list(list, tw) {
return MAP(list, function(node){
return MAP(list, function(node) {
return node.transform(tw, true);
});
};
}
_(AST_Node, noop);
_(AST_LabeledStatement, function(self, tw){
DEF(AST_Node, noop);
DEF(AST_LabeledStatement, function(self, tw) {
self.label = self.label.transform(tw);
self.body = self.body.transform(tw);
});
_(AST_SimpleStatement, function(self, tw){
DEF(AST_SimpleStatement, function(self, tw) {
self.body = self.body.transform(tw);
});
_(AST_Block, function(self, tw){
DEF(AST_Block, function(self, tw) {
self.body = do_list(self.body, tw);
});
_(AST_DWLoop, function(self, tw){
DEF(AST_Do, 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.body = self.body.transform(tw);
});
_(AST_For, function(self, tw){
DEF(AST_For, function(self, tw) {
if (self.init) self.init = self.init.transform(tw);
if (self.condition) self.condition = self.condition.transform(tw);
if (self.step) self.step = self.step.transform(tw);
self.body = self.body.transform(tw);
});
_(AST_ForIn, function(self, tw){
DEF(AST_ForIn, function(self, tw) {
self.init = self.init.transform(tw);
self.object = self.object.transform(tw);
self.body = self.body.transform(tw);
});
_(AST_With, function(self, tw){
DEF(AST_With, function(self, tw) {
self.expression = self.expression.transform(tw);
self.body = self.body.transform(tw);
});
_(AST_Exit, function(self, tw){
DEF(AST_Exit, function(self, tw) {
if (self.value) self.value = self.value.transform(tw);
});
_(AST_LoopControl, function(self, tw){
DEF(AST_LoopControl, function(self, tw) {
if (self.label) self.label = self.label.transform(tw);
});
_(AST_If, function(self, tw){
DEF(AST_If, function(self, tw) {
self.condition = self.condition.transform(tw);
self.body = self.body.transform(tw);
if (self.alternative) self.alternative = self.alternative.transform(tw);
});
_(AST_Switch, function(self, tw){
DEF(AST_Switch, function(self, tw) {
self.expression = self.expression.transform(tw);
self.body = do_list(self.body, tw);
});
_(AST_Case, function(self, tw){
DEF(AST_Case, function(self, tw) {
self.expression = self.expression.transform(tw);
self.body = do_list(self.body, tw);
});
_(AST_Try, function(self, tw){
DEF(AST_Try, function(self, tw) {
self.body = do_list(self.body, tw);
if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
});
_(AST_Catch, function(self, tw){
DEF(AST_Catch, function(self, tw) {
self.argname = self.argname.transform(tw);
self.body = do_list(self.body, tw);
});
_(AST_Definitions, function(self, tw){
DEF(AST_Definitions, function(self, tw) {
self.definitions = do_list(self.definitions, tw);
});
_(AST_VarDef, function(self, tw){
DEF(AST_VarDef, function(self, tw) {
self.name = self.name.transform(tw);
if (self.value) self.value = self.value.transform(tw);
});
_(AST_Lambda, function(self, tw){
DEF(AST_Lambda, function(self, tw) {
if (self.name) self.name = self.name.transform(tw);
self.argnames = do_list(self.argnames, tw);
self.body = do_list(self.body, tw);
});
_(AST_Call, function(self, tw){
DEF(AST_Call, function(self, tw) {
self.expression = self.expression.transform(tw);
self.args = do_list(self.args, tw);
});
_(AST_Sequence, function(self, tw){
DEF(AST_Sequence, function(self, tw) {
self.expressions = do_list(self.expressions, tw);
});
_(AST_Dot, function(self, tw){
DEF(AST_Dot, function(self, tw) {
self.expression = self.expression.transform(tw);
});
_(AST_Sub, function(self, tw){
DEF(AST_Sub, function(self, tw) {
self.expression = self.expression.transform(tw);
self.property = self.property.transform(tw);
});
_(AST_Unary, function(self, tw){
DEF(AST_Unary, function(self, tw) {
self.expression = self.expression.transform(tw);
});
_(AST_Binary, function(self, tw){
DEF(AST_Binary, function(self, tw) {
self.left = self.left.transform(tw);
self.right = self.right.transform(tw);
});
_(AST_Conditional, function(self, tw){
DEF(AST_Conditional, function(self, tw) {
self.condition = self.condition.transform(tw);
self.consequent = self.consequent.transform(tw);
self.alternative = self.alternative.transform(tw);
});
_(AST_Array, function(self, tw){
DEF(AST_Array, function(self, tw) {
self.elements = do_list(self.elements, tw);
});
_(AST_Object, function(self, tw){
DEF(AST_Object, function(self, tw) {
self.properties = do_list(self.properties, tw);
});
_(AST_ObjectProperty, function(self, tw){
DEF(AST_ObjectProperty, function(self, 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

@@ -43,40 +43,25 @@
"use strict";
function array_to_hash(a) {
var ret = Object.create(null);
for (var i = 0; i < a.length; ++i)
ret[a[i]] = true;
return ret;
};
function slice(a, start) {
return Array.prototype.slice.call(a, start || 0);
};
function characters(str) {
return str.split("");
};
}
function member(name, array) {
return array.indexOf(name) >= 0;
};
}
function find_if(func, array) {
for (var i = 0, n = array.length; i < n; ++i) {
if (func(array[i]))
return array[i];
}
};
for (var i = array.length; --i >= 0;) if (func(array[i])) return array[i];
}
function repeat_string(str, i) {
if (i <= 0) return "";
if (i == 1) return str;
var d = repeat_string(str, i >> 1);
d += d;
if (i & 1) d += str;
return d;
};
return i & 1 ? d + str : d;
}
function configure_error_stack(fn) {
Object.defineProperty(fn.prototype, "stack", {
@@ -95,27 +80,23 @@ function configure_error_stack(fn) {
function DefaultsError(msg, defs) {
this.message = msg;
this.defs = defs;
};
}
DefaultsError.prototype = Object.create(Error.prototype);
DefaultsError.prototype.constructor = DefaultsError;
DefaultsError.prototype.name = "DefaultsError";
configure_error_stack(DefaultsError);
DefaultsError.croak = function(msg, defs) {
throw new DefaultsError(msg, defs);
};
function defaults(args, defs, croak) {
if (args === true)
args = {};
if (args === true) args = {};
var ret = args || {};
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i))
DefaultsError.croak("`" + i + "` is not a supported option", defs);
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
throw new DefaultsError("`" + i + "` is not a supported option", defs);
}
for (var i in defs) if (HOP(defs, i)) {
ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
}
return ret;
};
}
function merge(obj, ext) {
var count = 0;
@@ -124,7 +105,7 @@ function merge(obj, ext) {
count++;
}
return count;
};
}
function noop() {}
function return_false() { return false; }
@@ -132,7 +113,7 @@ function return_true() { return true; }
function return_this() { return this; }
function return_null() { return null; }
var MAP = (function(){
var MAP = (function() {
function MAP(a, f, backwards) {
var ret = [], top = [], i;
function doit() {
@@ -155,8 +136,8 @@ var MAP = (function(){
}
}
return is_last;
};
if (a instanceof Array) {
}
if (Array.isArray(a)) {
if (backwards) {
for (i = a.length; --i >= 0;) if (doit()) break;
ret.reverse();
@@ -169,127 +150,52 @@ var MAP = (function(){
for (i in a) if (HOP(a, i)) if (doit()) break;
}
return top.concat(ret);
};
}
MAP.at_top = function(val) { return new AtTop(val) };
MAP.splice = function(val) { return new Splice(val) };
MAP.last = function(val) { return new Last(val) };
var skip = MAP.skip = {};
function AtTop(val) { this.v = val };
function Splice(val) { this.v = val };
function Last(val) { this.v = val };
function AtTop(val) { this.v = val }
function Splice(val) { this.v = val }
function Last(val) { this.v = val }
return MAP;
})();
function push_uniq(array, el) {
if (array.indexOf(el) < 0)
array.push(el);
};
if (array.indexOf(el) < 0) return array.push(el);
}
function string_template(text, props) {
return text.replace(/\{(.+?)\}/g, function(str, p){
return text.replace(/\{(.+?)\}/g, function(str, p) {
return props && props[p];
});
};
}
function remove(array, el) {
for (var i = array.length; --i >= 0;) {
if (array[i] === el) array.splice(i, 1);
}
};
var index = array.indexOf(el);
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);
};
function set_difference(a, b) {
return a.filter(function(el){
return b.indexOf(el) < 0;
});
};
function set_intersection(a, b) {
return a.filter(function(el){
return b.indexOf(el) >= 0;
});
};
// this function is taken from Acorn [1], written by Marijn Haverbeke
// [1] https://github.com/marijnh/acorn
function makePredicate(words) {
if (!(words instanceof Array)) words = words.split(" ");
var f = "", cats = [];
out: for (var i = 0; i < words.length; ++i) {
for (var j = 0; j < cats.length; ++j)
if (cats[j][0].length == words[i].length) {
cats[j].push(words[i]);
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);
};
if (!Array.isArray(words)) words = words.split(" ");
var map = Object.create(null);
words.forEach(function(word) {
map[word] = true;
});
return map;
}
function all(array, predicate) {
for (var i = array.length; --i >= 0;)
if (!predicate(array[i]))
return false;
return true;
};
}
function Dictionary() {
this._values = Object.create(null);
this._size = 0;
};
}
Dictionary.prototype = {
set: function(key, val) {
if (!this.has(key)) ++this._size;
@@ -326,6 +232,13 @@ Dictionary.prototype = {
ret.push(f(this._values[i], i.substr(1)));
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 }
};
Dictionary.fromObject = function(obj) {
@@ -343,20 +256,22 @@ function HOP(obj, prop) {
// a statement.
function first_in_statement(stack) {
var node = stack.parent(-1);
for (var i = 0, p; p = stack.parent(i); i++) {
if (p instanceof AST_Statement && p.body === node)
return true;
if ((p instanceof AST_Sequence && p.expressions[0] === node) ||
(p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) ||
(p instanceof AST_Dot && p.expression === node ) ||
(p instanceof AST_Sub && p.expression === node ) ||
(p instanceof AST_Conditional && p.condition === node ) ||
(p instanceof AST_Binary && p.left === node ) ||
(p instanceof AST_UnaryPostfix && p.expression === node ))
{
node = p;
} else {
return false;
for (var i = 0, p; p = stack.parent(i++); node = p) {
if (p.TYPE == "Call") {
if (p.expression === node) continue;
} else if (p instanceof AST_Binary) {
if (p.left === node) continue;
} else if (p instanceof AST_Conditional) {
if (p.condition === node) continue;
} else if (p instanceof AST_PropAccess) {
if (p.expression === node) continue;
} else if (p instanceof AST_Sequence) {
if (p.expressions[0] === node) continue;
} else if (p instanceof AST_Statement) {
return p.body === node;
} else if (p instanceof AST_UnaryPostfix) {
if (p.expression === node) continue;
}
return false;
}
}

View File

@@ -1,23 +1,17 @@
{
"name": "uglify-js",
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"homepage": "http://lisperator.net/uglifyjs",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.0.1",
"version": "3.5.2",
"engines": {
"node": ">=0.8.0"
},
"maintainers": [
"Alex Lam <alexlamsl@gmail.com>",
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
],
"repository": {
"type": "git",
"url": "https://github.com/mishoo/UglifyJS2.git"
},
"bugs": {
"url": "https://github.com/mishoo/UglifyJS2/issues"
},
"repository": "mishoo/UglifyJS2",
"main": "tools/node.js",
"bin": {
"uglifyjs": "bin/uglifyjs"
@@ -29,26 +23,38 @@
"LICENSE"
],
"dependencies": {
"commander": "~2.9.0",
"source-map": "~0.5.1"
"commander": "~2.19.0",
"source-map": "~0.6.1"
},
"devDependencies": {
"acorn": "~0.6.0",
"escodegen": "~1.3.3",
"esfuzz": "~0.3.1",
"estraverse": "~1.5.1",
"mocha": "~2.3.4"
},
"optionalDependencies": {
"uglify-to-browserify": "~1.0.0"
},
"browserify": {
"transform": [
"uglify-to-browserify"
]
"acorn": "~6.1.1",
"semver": "~5.6.0"
},
"scripts": {
"test": "node test/run-tests.js"
},
"keywords": ["uglify", "uglify-js", "minify", "minifier"]
"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

@@ -4,12 +4,14 @@
"use strict";
var createHash = require("crypto").createHash;
var fetch = require("./fetch");
var fork = require("child_process").fork;
var zlib = require("zlib");
var args = process.argv.slice(2);
if (!args.length) {
args.push("-mc");
}
args.push("--stats");
args.push("--timings");
var urls = [
"https://code.jquery.com/jquery-3.2.1.js",
"https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js",
@@ -19,28 +21,29 @@ var urls = [
"http://builds.emberjs.com/tags/v2.11.0/ember.prod.js",
"https://cdn.jsdelivr.net/lodash/4.17.4/lodash.js",
"https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.js",
"https://raw.githubusercontent.com/kangax/html-minifier/v3.5.7/dist/htmlminifier.js",
];
var results = {};
var remaining = 2 * urls.length;
function done() {
if (!--remaining) {
var failures = [];
var sum = { input: 0, output: 0, gzip: 0 };
urls.forEach(function(url) {
var info = results[url];
console.log();
console.log(url);
var elapsed = 0;
console.log(info.log.replace(/Elapsed: ([0-9]+)\s*/g, function(match, time) {
elapsed += 1e-3 * parseInt(time);
return "";
}));
console.log("Run-time:", elapsed.toFixed(3), "s");
console.log(info.log);
console.log("Original:", info.input, "bytes");
console.log("Uglified:", info.output, "bytes");
console.log("GZipped: ", info.gzip, "bytes");
console.log("SHA1 sum:", info.sha1);
if (info.code) {
failures.push(url);
}
sum.input += info.input;
sum.output += info.output;
sum.gzip += info.gzip;
});
if (failures.length) {
console.error("Benchmark failed:");
@@ -48,6 +51,13 @@ function done() {
console.error(url);
});
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");
}
}
}
@@ -55,15 +65,21 @@ urls.forEach(function(url) {
results[url] = {
input: 0,
output: 0,
gzip: 0,
log: ""
};
require(url.slice(0, url.indexOf(":"))).get(url, function(res) {
fetch(url, function(err, res) {
if (err) throw err;
var uglifyjs = fork("bin/uglifyjs", args, { silent: true });
res.on("data", function(data) {
results[url].input += data.length;
}).pipe(uglifyjs.stdin);
uglifyjs.stdout.on("data", function(data) {
results[url].output += data.length;
}).pipe(zlib.createGzip({
level: zlib.Z_BEST_COMPRESSION
})).on("data", function(data) {
results[url].gzip += data.length;
}).pipe(createHash("sha1")).on("data", function(data) {
results[url].sha1 = data.toString("hex");
done();

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: {
options = {
unsafe : true,
evaluate : true
};
evaluate: true,
unsafe: true,
}
input: {
var a = [ "foo", "bar", "baz" ].join("");
var a1 = [ "foo", "bar", "baz" ].join();
@@ -64,9 +64,9 @@ constant_join: {
constant_join_2: {
options = {
unsafe : true,
evaluate : true
};
evaluate: true,
unsafe: true,
}
input: {
var a = [ "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: {
options = {
unsafe: true,
evaluate: true,
};
unsafe: true,
}
input: {
var a = [ null ].join();
var b = [ , ].join();
@@ -128,50 +128,224 @@ constant_join_3: {
for_loop: {
options = {
unsafe : true,
unused : true,
evaluate : true,
reduce_vars : true
};
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unsafe: true,
unused: true,
}
input: {
function f0() {
var a = [1, 2, 3];
for (var i = 0; i < a.length; i++) {
console.log(a[i]);
}
var b = 0;
for (var i = 0; i < a.length; i++)
b += a[i];
return b;
}
function f1() {
var a = [1, 2, 3];
for (var i = 0, len = a.length; i < len; i++) {
console.log(a[i]);
}
var b = 0;
for (var i = 0, len = a.length; i < len; i++)
b += a[i];
return b;
}
function f2() {
var a = [1, 2, 3];
for (var i = 0; i < a.length; i++) {
a[i]++;
}
}
}
expect: {
function f0() {
var a = [1, 2, 3];
for (var i = 0; i < 3; i++)
console.log(a[i]);
}
function f1() {
var a = [1, 2, 3];
for (var i = 0; i < 3; i++)
console.log(a[i]);
}
function f2() {
var a = [1, 2, 3];
for (var i = 0; i < a.length; i++)
a[i]++;
return a[2];
}
console.log(f0(), f1(), f2());
}
expect: {
function f0() {
var a = [1, 2, 3];
var b = 0;
for (var i = 0; i < 3; i++)
b += a[i];
return b;
}
function f1() {
var a = [1, 2, 3];
var b = 0;
for (var i = 0; i < 3; i++)
b += a[i];
return b;
}
function f2() {
var a = [1, 2, 3];
for (var i = 0; i < a.length; i++)
a[i]++;
return a[2];
}
console.log(f0(), f1(), f2());
}
expect_stdout: "6 6 4"
}
index: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var a = [ 1, 2 ];
console.log(a[0], a[1]);
}
expect: {
console.log(1, 2);
}
expect_stdout: "1 2"
}
length: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var a = [ 1, 2 ];
console.log(a.length);
}
expect: {
console.log(2);
}
expect_stdout: "2"
}
index_length: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var a = [ 1, 2 ];
console.log(a[0], a.length);
}
expect: {
console.log(1, 2);
}
expect_stdout: "1 2"
}
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

@@ -13,7 +13,7 @@ ascii_only_true: {
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
}
}
expect_exact: 'function f(){return"\\x000\\x001\\x007\\08\\0"+"\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\v\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}'
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\0"+"\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\v\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}'
}
ascii_only_false: {
@@ -31,5 +31,5 @@ ascii_only_false: {
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
}
}
expect_exact: 'function f(){return"\\x000\\x001\\x007\\08\\0"+"\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\0"+"\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
}

View File

@@ -1,25 +1,25 @@
asm_mixed: {
options = {
sequences : true,
properties : true,
dead_code : true,
drop_debugger : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
loops : true,
unused : true,
hoist_funs : true,
keep_fargs : true,
keep_fnames : false,
hoist_vars : true,
if_return : true,
join_vars : true,
cascade : true,
side_effects : true,
negate_iife : true
};
assignments: true,
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
drop_debugger: true,
evaluate: true,
hoist_funs: true,
hoist_vars: true,
if_return: true,
join_vars: true,
keep_fargs: true,
keep_fnames: false,
loops: true,
negate_iife: true,
properties: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
// adapted from http://asmjs.org/spec/latest/
function asm_GeometricMean(stdlib, foreign, buffer) {
@@ -104,3 +104,65 @@ asm_mixed: {
}
}
asm_toplevel: {
options = {}
input: {
"use asm";
0.0;
function f() {
0.0;
(function(){
0.0;
});
}
0.0;
}
expect_exact: '"use asm";0.0;function f(){0.0;(function(){0.0})}0.0;'
}
asm_function_expression: {
options = {}
input: {
0.0;
var a = function() {
"use asm";
0.0;
}
function f() {
0.0;
return function(){
"use asm";
0.0;
}
0.0;
}
0.0;
}
expect_exact: '0;var a=function(){"use asm";0.0};function f(){0;return function(){"use asm";0.0};0}0;'
}
asm_nested_functions: {
options = {}
input: {
0.0;
function a() {
"use asm";
0.0;
}
0.0;
function b() {
0.0;
function c(){
"use asm";
0.0;
}
0.0;
function d(){
0.0;
}
0.0;
}
0.0;
}
expect_exact: '0;function a(){"use asm";0.0}0;function b(){0;function c(){"use asm";0.0}0;function d(){0}0}0;'
}

View File

@@ -1,5 +1,6 @@
op_equals_left_local_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
@@ -60,6 +61,7 @@ op_equals_left_local_var: {
op_equals_right_local_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
@@ -123,6 +125,7 @@ op_equals_right_local_var: {
}
op_equals_left_global_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
@@ -179,6 +182,7 @@ op_equals_left_global_var: {
op_equals_right_global_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
@@ -236,3 +240,52 @@ op_equals_right_global_var: {
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,76 +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;
}
}

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: {
options = {
evaluate: true
};
evaluate: true,
}
input: {
var a = "foo" + "bar" + x() + "moo" + "foo" + y() + "x" + "y" + "z" + q();
var b = "foo" + 1 + x() + 2 + "boo";
@@ -21,12 +21,12 @@ concat_1: {
var c = 1 + x() + 2 + "boo";
var d = 1 + x() + 2 + 3 + "boo";
var e = 1 + x() + 2 + "X3boo";
var f = "\x00360\08\0";
var f = "\x00360\x008\0";
}
}
concat_2: {
options = {};
options = {}
input: {
console.log(
1 + (2 + 3),
@@ -55,7 +55,7 @@ concat_2: {
}
concat_3: {
options = {};
options = {}
input: {
console.log(
1 + 2 + (3 + 4 + 5),
@@ -84,7 +84,7 @@ concat_3: {
}
concat_4: {
options = {};
options = {}
input: {
console.log(
1 + "2" + (3 + 4 + 5),
@@ -113,7 +113,7 @@ concat_4: {
}
concat_5: {
options = {};
options = {}
input: {
console.log(
"1" + 2 + (3 + 4 + 5),
@@ -142,7 +142,7 @@ concat_5: {
}
concat_6: {
options = {};
options = {}
input: {
console.log(
"1" + "2" + (3 + 4 + 5),

View File

@@ -1,7 +1,7 @@
ifs_1: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
if (foo) bar();
if (!foo); else bar();
@@ -18,8 +18,8 @@ ifs_1: {
ifs_2: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
if (foo) {
x();
@@ -47,12 +47,12 @@ ifs_2: {
ifs_3_should_warn: {
options = {
conditionals : true,
dead_code : true,
evaluate : true,
booleans : true,
side_effects : true,
};
booleans: true,
conditionals: true,
dead_code: true,
evaluate: true,
side_effects: true,
}
input: {
var x, y;
if (x && !(x + "1") && y) { // 1
@@ -78,8 +78,8 @@ ifs_3_should_warn: {
ifs_4: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
if (foo && bar) {
x(foo)[10].bar.baz = something();
@@ -95,10 +95,10 @@ ifs_4: {
ifs_5: {
options = {
if_return: true,
conditionals: true,
comparisons: true,
};
conditionals: true,
if_return: true,
}
input: {
function f() {
if (foo) return;
@@ -132,9 +132,9 @@ ifs_5: {
ifs_6: {
options = {
comparisons: true,
conditionals: true,
comparisons: true
};
}
input: {
var x, y;
if (!foo && !bar && !baz && !boo) {
@@ -163,50 +163,54 @@ ifs_6: {
cond_1: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
var do_something; // if undeclared it's assumed to have side-effects
if (some_condition()) {
do_something(x);
} else {
do_something(y);
}
if (some_condition()) {
side_effects(x);
} else {
side_effects(y);
function foo(do_something, some_condition) {
if (some_condition) {
do_something(x);
} else {
do_something(y);
}
if (some_condition) {
side_effects(x);
} else {
side_effects(y);
}
}
}
expect: {
var do_something;
do_something(some_condition() ? x : y);
some_condition() ? side_effects(x) : side_effects(y);
function foo(do_something, some_condition) {
do_something(some_condition ? x : y);
some_condition ? side_effects(x) : side_effects(y);
}
}
}
cond_2: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
var x, FooBar;
if (some_condition()) {
x = new FooBar(1);
} else {
x = new FooBar(2);
function foo(x, FooBar, some_condition) {
if (some_condition) {
x = new FooBar(1);
} else {
x = new FooBar(2);
}
}
}
expect: {
var x, FooBar;
x = new FooBar(some_condition() ? 1 : 2);
function foo(x, FooBar, some_condition) {
x = new FooBar(some_condition ? 1 : 2);
}
}
}
cond_3: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
var FooBar;
if (some_condition()) {
@@ -223,8 +227,8 @@ cond_3: {
cond_4: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
var do_something;
if (some_condition()) {
@@ -247,8 +251,8 @@ cond_4: {
cond_5: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
if (some_condition()) {
if (some_other_condition()) {
@@ -275,9 +279,9 @@ cond_5: {
cond_7: {
options = {
conditionals: true,
evaluate : true,
evaluate: true,
side_effects: true,
};
}
input: {
var x, y, z, a, b;
// compress these
@@ -328,7 +332,7 @@ cond_7: {
x = 'foo';
x = 'foo';
x = (condition(), 20);
x = z ? 'fuji' : (condition(), 'fuji');
x = (z || condition(), 'fuji');
x = (condition(), 'foobar');
x = y ? a : b;
x = y ? 'foo' : 'fo';
@@ -338,8 +342,8 @@ cond_7: {
cond_7_1: {
options = {
conditionals: true,
evaluate : true
};
evaluate: true,
}
input: {
var x;
// access to global should be assumed to have side effects
@@ -357,10 +361,10 @@ cond_7_1: {
cond_8: {
options = {
booleans: false,
conditionals: true,
evaluate : true,
booleans : false
};
evaluate: true,
}
input: {
var a;
// compress these
@@ -441,10 +445,10 @@ cond_8: {
cond_8b: {
options = {
booleans: true,
conditionals: true,
evaluate : true,
booleans : true
};
evaluate: true,
}
input: {
var a;
// compress these
@@ -524,10 +528,10 @@ cond_8b: {
cond_8c: {
options = {
booleans: false,
conditionals: true,
evaluate : false,
booleans : false
};
evaluate: false,
}
input: {
var a;
// compress these
@@ -605,11 +609,59 @@ cond_8c: {
}
}
cond_9: {
options = {
conditionals: true,
}
input: {
function f(x, y) {
g() ? x(1) : x(2);
x ? (y || x)() : (y || x)();
x ? y(a, b) : y(d, b, c);
x ? y(a, b, c) : y(a, b, c);
x ? y(a, b, c) : y(a, b, f);
x ? y(a, b, c) : y(a, e, c);
x ? y(a, b, c) : y(a, e, f);
x ? y(a, b, c) : y(d, b, c);
x ? y(a, b, c) : y(d, b, f);
x ? y(a, b, c) : y(d, e, c);
x ? y(a, b, c) : y(d, e, f);
}
}
expect: {
function f(x, y) {
g() ? x(1) : x(2);
x, (y || x)();
x ? y(a, b) : y(d, b, c);
x, y(a, b, c);
y(a, b, x ? c : f);
y(a, x ? b : e, c);
x ? y(a, b, c) : y(a, e, f);
y(x ? a : d, b, c);
x ? y(a, b, c) : y(d, b, f);
x ? y(a, b, c) : y(d, e, c);
x ? y(a, b, c) : y(d, e, f);
}
}
}
ternary_boolean_consequent: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
booleans: true,
collapse_vars: 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: {
function f1() { return a == b ? true : x; }
@@ -635,9 +687,21 @@ ternary_boolean_consequent: {
ternary_boolean_alternative: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
booleans: true,
collapse_vars: 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: {
function f1() { return a == b ? x : true; }
@@ -663,10 +727,11 @@ ternary_boolean_alternative: {
trivial_boolean_ternary_expressions : {
options = {
booleans: true,
conditionals: true,
evaluate : true,
booleans : true
};
evaluate: true,
side_effects: true,
}
input: {
f('foo' in m ? true : false);
f('foo' in m ? false : true);
@@ -737,11 +802,11 @@ trivial_boolean_ternary_expressions : {
issue_1154: {
options = {
booleans: true,
conditionals: true,
evaluate : true,
booleans : true,
evaluate: true,
side_effects: true,
};
}
input: {
function f1(x) { return x ? -1 : -1; }
function f2(x) { return x ? +2 : +2; }
@@ -777,7 +842,7 @@ issue_1154: {
no_evaluate: {
options = {
conditionals: true,
evaluate : false,
evaluate: false,
side_effects: true,
}
input: {
@@ -1015,3 +1080,339 @@ delete_conditional_2: {
}
expect_stdout: true
}
issue_2535_1: {
options = {
booleans: true,
conditionals: true,
evaluate: true,
passes: 2,
side_effects: true,
}
input: {
if (true || x()) y();
if (true && x()) y();
if (x() || true) y();
if (x() && true) y();
if (false || x()) y();
if (false && x()) y();
if (x() || false) y();
if (x() && false) y();
}
expect: {
y();
x() && y();
(x(), 1) && y();
x() && y();
x() && y();
x() && y();
(x(), 0) && y();
}
}
issue_2535_2: {
options = {
booleans: true,
conditionals: true,
evaluate: true,
side_effects: true,
}
input: {
function x() {}
function y() {
return "foo";
}
console.log((x() || true) || y());
console.log((y() || true) || x());
console.log((x() || true) && y());
console.log((y() || true) && x());
console.log((x() && true) || y());
console.log((y() && true) || x());
console.log((x() && true) && y());
console.log((y() && true) && x());
console.log((x() || false) || y());
console.log((y() || false) || x());
console.log((x() || false) && y());
console.log((y() || false) && x());
console.log((x() && false) || y());
console.log((y() && false) || x());
console.log((x() && false) && y());
console.log((y() && false) && x());
}
expect: {
function x() {}
function y() {
return "foo";
}
console.log(x() || !0);
console.log(y() || !0);
console.log((x(), y()));
console.log((y(), x()));
console.log(!!x() || y());
console.log(!!y() || x());
console.log(x() && y());
console.log(y() && x());
console.log(x() || y());
console.log(y() || x());
console.log(!!x() && y());
console.log(!!y() && x());
console.log((x(), y()));
console.log((y(), x()));
console.log(x() && !1);
console.log(y() && !1);
}
expect_stdout: [
"true",
"foo",
"foo",
"undefined",
"foo",
"true",
"undefined",
"undefined",
"foo",
"foo",
"false",
"undefined",
"foo",
"undefined",
"undefined",
"false",
]
}
issue_2560: {
options = {
conditionals: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function log(x) {
console.log(x);
}
function foo() {
return log;
}
function bar() {
if (x !== (x = foo())) {
x(1);
} else {
x(2);
}
}
var x = function() {
console.log("init");
};
bar();
bar();
}
expect: {
function log(x) {
console.log(x);
}
function bar() {
x !== (x = log) ? x(1) : x(2);
}
var x = function() {
console.log("init");
};
bar();
bar();
}
expect_stdout: [
"1",
"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,166 +0,0 @@
issue_1191: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_vars : true,
}
input: {
function foo(rot) {
const rotTol = 5;
if (rot < -rotTol || rot > rotTol)
bar();
baz();
}
}
expect: {
function foo(rot) {
(rot < -5 || rot > 5) && bar();
baz();
}
}
}
issue_1194: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_vars : true,
}
input: {
function f1() {const a = "X"; return a + a;}
function f2() {const aa = "X"; return aa + aa;}
function f3() {const aaa = "X"; return aaa + aaa;}
}
expect: {
function f1(){return"XX"}
function f2(){return"XX"}
function f3(){return"XX"}
}
}
issue_1396: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_vars : true,
}
input: {
function foo(a) {
const VALUE = 1;
console.log(2 | VALUE);
console.log(VALUE + 1);
console.log(VALUE);
console.log(a & VALUE);
}
function bar() {
const s = "01234567890123456789";
console.log(s + s + s + s + s);
const CONSTANT = "abc";
console.log(CONSTANT + CONSTANT + CONSTANT + CONSTANT + CONSTANT);
}
}
expect: {
function foo(a) {
console.log(3);
console.log(2);
console.log(1);
console.log(1 & a);
}
function bar() {
const s = "01234567890123456789";
console.log(s + s + s + s + s);
console.log("abcabcabcabcabc");
}
}
}
unused_regexp_literal: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
}
input: {
function f(){ var a = /b/; }
}
expect: {
function f(){}
}
}
regexp_literal_not_const: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_vars : true,
}
input: {
(function(){
var result;
const s = 'acdabcdeabbb';
const REGEXP_LITERAL = /ab*/g;
while (result = REGEXP_LITERAL.exec(s)) {
console.log(result[0]);
}
})();
}
expect: {
(function() {
var result;
const REGEXP_LITERAL = /ab*/g;
while (result = REGEXP_LITERAL.exec("acdabcdeabbb")) console.log(result[0]);
})();
}
expect_stdout: true
}

File diff suppressed because it is too large Load Diff

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@ must_replace: {
options = {
global_defs: {
D: "foo bar",
}
},
}
input: {
console.log(D);
@@ -37,6 +37,7 @@ object: {
VALUE: 42,
},
},
side_effects: true,
unsafe: true,
}
input: {
@@ -120,7 +121,7 @@ mixed: {
properties: true,
}
input: {
const FOO = { BAR: 0 };
var FOO = { BAR: 0 };
console.log(FOO.BAR);
console.log(++CONFIG.DEBUG);
console.log(++CONFIG.VALUE);
@@ -130,7 +131,7 @@ mixed: {
console.log(CONFIG);
}
expect: {
const FOO = { BAR: 0 };
var FOO = { BAR: 0 };
console.log("moo");
console.log(++CONFIG.DEBUG);
console.log(++CONFIG.VALUE);
@@ -140,9 +141,8 @@ mixed: {
console.log(CONFIG);
}
expect_warnings: [
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:126,22]',
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]',
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:129,8]',
"WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:4,22]",
"WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:7,8]",
]
}
@@ -160,3 +160,59 @@ issue_1801: {
console.log(!0);
}
}
issue_1986: {
options = {
global_defs: {
"@alert": "console.log",
},
}
input: {
alert(42);
}
expect: {
console.log(42);
}
}
issue_2167: {
options = {
conditionals: true,
dead_code: true,
evaluate: true,
global_defs: {
"@isDevMode": "function(){}",
},
passes: 2,
side_effects: true,
}
input: {
if (isDevMode()) {
greetOverlord();
}
doWork();
}
expect: {
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

@@ -0,0 +1,864 @@
issue_2377_1: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var obj = {
foo: 1,
bar: 2,
square: function(x) {
return x * x;
},
cube: function(x) {
return x * x * x;
},
};
console.log(obj.foo, obj.cube(3));
}
expect: {
var obj_foo = 1, obj_cube = function(x) {
return x * x * x;
};
console.log(obj_foo, obj_cube(3));
}
expect_stdout: "1 27"
}
issue_2377_2: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var obj = {
foo: 1,
bar: 2,
square: function(x) {
return x * x;
},
cube: function(x) {
return x * x * x;
},
};
console.log(obj.foo, obj.cube(3));
}
expect: {
console.log(1, (x = 3, x * x * x));
var x;
}
expect_stdout: "1 27"
}
issue_2377_3: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 4,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var obj = {
foo: 1,
bar: 2,
square: function(x) {
return x * x;
},
cube: function(x) {
return x * x * x;
},
};
console.log(obj.foo, obj.cube(3));
}
expect: {
console.log(1, 27);
}
expect_stdout: "1 27"
}
direct_access_1: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 0;
var obj = {
a: 1,
b: 2,
};
for (var k in obj) a++;
console.log(a, obj.a);
}
expect: {
var a = 0;
var obj = {
a: 1,
b: 2,
};
for (var k in obj) a++;
console.log(a, obj.a);
}
expect_stdout: "2 1"
}
direct_access_2: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = { a: 1 };
var f = function(k) {
if (o[k]) return "PASS";
};
console.log(f("a"));
}
expect: {
var o = { a: 1 };
console.log(function(k) {
if (o[k]) return "PASS";
}("a"));
}
expect_stdout: "PASS"
}
direct_access_3: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = { a: 1 };
o.b;
console.log(o.a);
}
expect: {
var o = { a: 1 };
o.b;
console.log(o.a);
}
expect_stdout: "1"
}
single_use: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var obj = {
bar: function() {
return 42;
},
};
console.log(obj.bar());
}
expect: {
console.log({
bar: function() {
return 42;
},
}.bar());
}
}
name_collision_1: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
input: {
var obj_foo = 1;
var obj_bar = 2;
function f() {
var obj = {
foo: 3,
bar: 4,
"b-r": 5,
"b+r": 6,
"b!r": 7,
};
console.log(obj_foo, obj.foo, obj.bar, obj["b-r"], obj["b+r"], obj["b!r"]);
}
f();
}
expect: {
var obj_foo = 1;
var obj_bar = 2;
function f() {
var obj_foo$0 = 3,
obj_bar = 4,
obj_b_r = 5,
obj_b_r$0 = 6,
obj_b_r$1 = 7;
console.log(obj_foo, obj_foo$0, obj_bar, obj_b_r, obj_b_r$0, obj_b_r$1);
}
f();
}
expect_stdout: "1 3 4 5 6 7"
}
name_collision_2: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
input: {
var o = {
p: 1,
"+": function(x) {
return x;
},
"-": function(x) {
return x + 1;
}
}, o__$0 = 2, o__$1 = 3;
console.log(o.p === o.p, o["+"](4), o["-"](5), o__$0, o__$1);
}
expect: {
var o_p = 1,
o__ = function(x) {
return x;
},
o__$2 = function(x) {
return x + 1;
},
o__$0 = 2,
o__$1 = 3;
console.log(o_p === o_p, o__(4), o__$2(5), o__$0, o__$1);
}
expect_stdout: "true 4 6 2 3"
}
name_collision_3: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
input: {
var o = {
p: 1,
"+": function(x) {
return x;
},
"-": function(x) {
return x + 1;
}
}, o__$0 = 2, o__$1 = 3;
console.log(o.p === o.p, o["+"](4), o["-"](5));
}
expect: {
var o_p = 1,
o__ = function(x) {
return x;
},
o__$2 = function(x) {
return x + 1;
},
o__$0 = 2,
o__$1 = 3;
console.log(o_p === o_p, o__(4), o__$2(5));
}
expect_stdout: "true 4 6"
}
contains_this_1: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
u: function() {
return this === this;
},
p: 1
};
console.log(o.p, o.p);
}
expect: {
console.log(1, 1);
}
expect_stdout: "1 1"
}
contains_this_2: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
u: function() {
return this === this;
},
p: 1
};
console.log(o.p, o.p, o.u);
}
expect: {
console.log(1, 1, function() {
return this === this;
});
}
expect_stdout: true
}
contains_this_3: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
u: function() {
return this === this;
},
p: 1
};
console.log(o.p, o.p, o.u());
}
expect: {
var o = {
u: function() {
return this === this;
},
p: 1
};
console.log(o.p, o.p, o.u());
}
expect_stdout: "1 1 true"
}
new_this: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: 1,
b: 2,
f: function(a) {
this.b = a;
}
};
console.log(new o.f(o.a).b, o.b);
}
expect: {
console.log(new function(a) {
this.b = a;
}(1).b, 2);
}
expect_stdout: "1 2"
}
issue_2473_1: {
options = {
hoist_props: false,
reduce_vars: true,
top_retain: [
"x",
"y"
],
toplevel: true,
unused: true,
}
input: {
var x = {};
var y = [];
var z = {};
}
expect: {
var x = {};
var y = [];
}
}
issue_2473_2: {
options = {
hoist_props: true,
reduce_vars: true,
top_retain: [
"x",
"y"
],
toplevel: true,
unused: true,
}
input: {
var x = {};
var y = [];
var z = {};
}
expect: {
var x = {};
var y = [];
}
}
issue_2473_3: {
options = {
hoist_props: true,
reduce_vars: true,
top_retain: "o",
toplevel: true,
unused: true,
}
input: {
var o = {
a: 1,
b: 2,
};
console.log(o.a, o.b);
}
expect: {
var o = {
a: 1,
b: 2,
};
console.log(o.a, o.b);
}
expect_stdout: "1 2"
}
issue_2473_4: {
options = {
hoist_props: true,
reduce_vars: true,
top_retain: "o",
toplevel: true,
unused: true,
}
input: {
(function() {
var o = {
a: 1,
b: 2,
};
console.log(o.a, o.b);
})();
}
expect: {
(function() {
var o_a = 1, o_b = 2;
console.log(o_a, o_b);
})();
}
expect_stdout: "1 2"
}
issue_2508_1: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: [ 1 ],
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
(function(x) {
console.log(x);
})([ 1 ]);
}
expect_stdout: true
}
issue_2508_2: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: { b: 2 },
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
(function(x) {
console.log(x);
})({ b: 2 });
}
expect_stdout: true
}
issue_2508_3: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: [ o ],
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
var o = {
a: [ o ],
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect_stdout: true
}
issue_2508_4: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: { b: o },
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
var o = {
a: { b: o },
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect_stdout: true
}
issue_2508_5: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
f: function(x) {
console.log(x);
}
};
o.f(o.f);
}
expect: {
var o_f = function(x) {
console.log(x);
};
o_f(o_f);
}
expect_stdout: true
}
issue_2519: {
options = {
collapse_vars: true,
evaluate: true,
hoist_props: true,
reduce_vars: true,
unused: true,
}
input: {
function testFunc() {
var dimensions = {
minX: 5,
maxX: 6,
};
var scale = 1;
var d = {
x: (dimensions.maxX + dimensions.minX) / 2,
};
return d.x * scale;
}
console.log(testFunc());
}
expect: {
function testFunc() {
return 1 * ((6 + 5) / 2);
}
console.log(testFunc());
}
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"
}

View File

@@ -88,3 +88,24 @@ sequences_funs: {
}
}
}
issue_2295: {
options = {
collapse_vars: true,
hoist_vars: true,
}
input: {
function foo(o) {
var a = o.a;
if (a) return a;
var a = 1;
}
}
expect: {
function foo(o) {
var a = o.a;
if (a) return a;
a = 1;
}
}
}

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: {
options = {
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
function f(x) {
@@ -24,15 +24,15 @@ if_return_1: {
if_return_2: {
options = {
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
function f(x, y) {
@@ -49,15 +49,15 @@ if_return_2: {
if_return_3: {
options = {
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
function f(x) {
@@ -75,15 +75,15 @@ if_return_3: {
if_return_4: {
options = {
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
function f(x, y) {
@@ -100,15 +100,15 @@ if_return_4: {
if_return_5: {
options = {
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
function f() {
@@ -126,15 +126,15 @@ if_return_5: {
if_return_6: {
options = {
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
function f(x) {
@@ -150,15 +150,15 @@ if_return_6: {
if_return_7: {
options = {
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
function f(x) {
@@ -176,10 +176,10 @@ if_return_7: {
if_return_8: {
options = {
if_return: true,
sequences: true,
conditionals: true,
side_effects : true,
conditionals: true,
if_return: true,
sequences: true,
side_effects: true,
}
input: {
function f(e) {
@@ -220,15 +220,15 @@ if_return_8: {
issue_1089: {
options = {
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
function x() {
@@ -243,7 +243,7 @@ issue_1089: {
expect: {
function x() {
var f = document.getElementById("fname");
if (f.files[0].size > 12345)
if (12345 < f.files[0].size)
return alert("alert"), f.focus(), !1;
}
}
@@ -251,9 +251,9 @@ issue_1089: {
issue_1437: {
options = {
if_return : true,
sequences : true,
conditionals : false
conditionals: false,
if_return: true,
sequences: true,
}
input: {
function x() {
@@ -281,9 +281,9 @@ issue_1437: {
issue_1437_conditionals: {
options = {
conditionals : true,
if_return : true,
sequences : true
conditionals: true,
if_return: true,
sequences: true,
}
input: {
function x() {
@@ -302,3 +302,245 @@ issue_1437_conditionals: {
}
}
}
issue_512: {
options = {
conditionals: true,
if_return: true,
sequences: true,
side_effects: true,
}
input: {
function a() {
if (b()) {
c();
return;
}
throw e;
}
}
expect: {
function a() {
if (!b()) throw e;
c();
}
}
}
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: {
options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true
booleans: true,
comparisons: 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: {
function foo(x) {
@@ -27,19 +36,30 @@ non_hoisted_function_after_return: {
}
}
expect_warnings: [
'WARN: Dropping unreachable code [test/compress/issue-1034.js:11,16]',
"WARN: Dropping unreachable code [test/compress/issue-1034.js:14,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:17,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:18,21]"
"WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:11,21]"
]
}
non_hoisted_function_after_return_2a: {
options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true,
collapse_vars: false, passes: 2, warnings: "verbose"
booleans: true,
collapse_vars: false,
comparisons: true,
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: {
function foo(x) {
@@ -65,26 +85,37 @@ non_hoisted_function_after_return_2a: {
}
}
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:48,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:48,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:51,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:51,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:48,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:53,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:4,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:4,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]",
"WARN: pass 0: last_count: Infinity, count: 37",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
"WARN: pass 1: last_count: 37, count: 18",
]
}
non_hoisted_function_after_return_2b: {
options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true,
collapse_vars: false
booleans: true,
collapse_vars: false,
comparisons: 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: {
function foo(x) {
@@ -108,11 +139,174 @@ non_hoisted_function_after_return_2b: {
}
}
expect_warnings: [
// duplicate warnings no longer emitted
"WARN: Dropping unreachable code [test/compress/issue-1034.js:95,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:95,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:101,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:6,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:6,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
]
}
non_hoisted_function_after_return_strict: {
options = {
booleans: true,
comparisons: 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: {
"use strict";
function foo(x) {
if (x) {
return bar();
not_called1();
} else {
return baz();
not_called2();
}
function bar() { return 7; }
return not_reached;
function UnusedFunction() {}
function baz() { return 8; }
}
console.log(foo(0), foo(1));
}
expect: {
"use strict";
function foo(x) {
return x ? bar() : baz();
function bar() { return 7 }
function baz() { return 8 }
}
console.log(foo(0), foo(1));
}
expect_stdout: "8 7"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:5,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:11,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:12,21]",
]
}
non_hoisted_function_after_return_2a_strict: {
options = {
booleans: true,
collapse_vars: false,
comparisons: true,
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: {
"use strict";
function foo(x) {
if (x) {
return bar(1);
var a = not_called(1);
} else {
return bar(2);
var b = not_called(2);
}
var c = bar(3);
function bar(x) { return 7 - x; }
function nope() {}
return b || c;
}
console.log(foo(0), foo(1));
}
expect: {
"use strict";
function foo(x) {
return bar(x ? 1 : 2);
function bar(x) {
return 7 - x;
}
}
console.log(foo(0), foo(1));
}
expect_stdout: "5 6"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:5,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:5,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:5,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:12,21]",
"WARN: pass 0: last_count: Infinity, count: 48",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
"WARN: pass 1: last_count: 48, count: 29",
]
}
non_hoisted_function_after_return_2b_strict: {
options = {
booleans: true,
collapse_vars: false,
comparisons: 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: {
"use strict";
function foo(x) {
if (x) {
return bar(1);
} else {
return bar(2);
var b;
}
var c = bar(3);
function bar(x) {
return 7 - x;
}
return b || c;
}
console.log(foo(0), foo(1));
}
expect: {
"use strict";
function foo(x) {
return bar(x ? 1 : 2);
function bar(x) { return 7 - x; }
}
console.log(foo(0), foo(1));
}
expect_stdout: "5 6"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
]
}

View File

@@ -1,21 +1,9 @@
const_declaration: {
options = {
evaluate: true
};
input: {
const goog = goog || {};
}
expect: {
const goog = goog || {};
}
}
const_pragma: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
};
}
input: {
/** @const */ var goog = goog || {};
@@ -29,8 +17,9 @@ const_pragma: {
not_const: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
};
}
input: {
var goog = goog || {};

View File

@@ -1,90 +1,91 @@
multiple_functions: {
options = { if_return: true, hoist_funs: false };
options = {
hoist_funs: false,
if_return: true,
}
input: {
( function() {
if ( !window ) {
return;
}
function f() {}
function g() {}
} )();
}
expect: {
( function() {
function f() {}
function g() {}
// NOTE: other compression steps will reduce this
// down to just `window`.
if ( window );
function f() {}
function g() {}
} )();
}
}
single_function: {
options = { if_return: true, hoist_funs: false };
options = {
hoist_funs: false,
if_return: true,
}
input: {
( function() {
if ( !window ) {
return;
}
function f() {}
} )();
}
expect: {
( function() {
function f() {}
if ( window );
function f() {}
} )();
}
}
deeply_nested: {
options = { if_return: true, hoist_funs: false };
options = {
hoist_funs: false,
if_return: true,
}
input: {
( function() {
if ( !window ) {
return;
}
function f() {}
function g() {}
if ( !document ) {
return;
}
function h() {}
} )();
}
expect: {
( function() {
function f() {}
function g() {}
function h() {}
// NOTE: other compression steps will reduce this
// down to just `window`.
if ( window )
if (document);
function f() {}
function g() {}
function h() {}
} )();
}
}
not_hoisted_when_already_nested: {
options = { if_return: true, hoist_funs: false };
options = {
hoist_funs: false,
if_return: true,
}
input: {
( function() {
if ( !window ) {
return;
}
if ( foo ) function f() {}
} )();
}
expect: {
@@ -94,3 +95,70 @@ not_hoisted_when_already_nested: {
} )();
}
}
defun_if_return: {
options = {
hoist_funs: false,
if_return: true,
}
input: {
function e() {
function f() {}
if (!window) return;
else function g() {}
function h() {}
}
}
expect: {
function e() {
function f() {}
if (window) function g() {}
function h() {}
}
}
}
defun_hoist_funs: {
options = {
hoist_funs: true,
if_return: true,
}
input: {
function e() {
function f() {}
if (!window) return;
else function g() {}
function h() {}
}
}
expect: {
function e() {
function f() {}
function g() {}
function h() {}
if (window);
}
}
}
defun_else_if_return: {
options = {
hoist_funs: false,
if_return: true,
}
input: {
function e() {
function f() {}
if (window) function g() {}
else return;
function h() {}
}
}
expect: {
function e() {
function f() {}
if (window) function g() {}
function h() {}
}
}
}

View File

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

View File

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

View File

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

View File

@@ -1,15 +1,14 @@
pure_function_calls: {
options = {
evaluate : true,
conditionals : true,
comparisons : true,
side_effects : true,
booleans : true,
unused : true,
if_return : true,
join_vars : true,
cascade : true,
negate_iife : true,
booleans: true,
comparisons: true,
conditionals: true,
evaluate: true,
if_return: true,
join_vars: true,
negate_iife: true,
side_effects: true,
unused: true,
}
input: {
// pure top-level IIFE will be dropped
@@ -49,29 +48,28 @@ pure_function_calls: {
a.b(), f.g();
}
expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:17,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:17,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:30,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:30,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:28,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:38,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:39,31]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:3,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:3,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:16,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:14,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:24,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:25,31]",
]
}
pure_function_calls_toplevel: {
options = {
evaluate : true,
conditionals : true,
comparisons : true,
side_effects : true,
booleans : true,
unused : true,
if_return : true,
join_vars : true,
cascade : true,
negate_iife : true,
toplevel : true,
booleans: true,
comparisons: true,
conditionals: true,
evaluate: true,
if_return: true,
join_vars: true,
negate_iife: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
// pure top-level IIFE will be dropped
@@ -96,6 +94,13 @@ pure_function_calls_toplevel: {
})();
})();
// pure top-level calls will be dropped regardless of the leading comments position
var MyClass = /*#__PURE__*//*@class*/(function(){
function MyClass() {}
MyClass.prototype.method = function() {};
return MyClass;
})();
// comment #__PURE__ comment
bar(), baz(), quux();
a.b(), /* @__PURE__ */ c.d.e(), f.g();
@@ -105,15 +110,17 @@ pure_function_calls_toplevel: {
a.b(), f.g();
}
expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:79,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:79,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:92,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:92,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:90,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:100,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:101,31]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:84,33]",
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:84,12]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:3,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:3,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:16,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:14,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:31,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:32,31]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:8,33]",
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:8,12]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:24,45]",
"WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:24,12]",
]
}
@@ -148,29 +155,29 @@ should_warn: {
baz();
}
expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,61]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,23]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:128,23]",
"WARN: Boolean || always true [test/compress/issue-1261.js:129,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:129,23]",
"WARN: Condition always true [test/compress/issue-1261.js:129,23]",
"WARN: Condition left of || always true [test/compress/issue-1261.js:130,8]",
"WARN: Condition always true [test/compress/issue-1261.js:130,8]",
"WARN: Boolean && always false [test/compress/issue-1261.js:131,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:131,23]",
"WARN: Condition always false [test/compress/issue-1261.js:131,23]",
"WARN: Condition left of && always false [test/compress/issue-1261.js:132,8]",
"WARN: Condition always false [test/compress/issue-1261.js:132,8]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:133,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:133,23]",
"WARN: Condition always true [test/compress/issue-1261.js:133,23]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:134,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:134,31]",
"WARN: Condition always true [test/compress/issue-1261.js:134,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:136,24]",
"WARN: Condition always true [test/compress/issue-1261.js:136,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,31]",
"WARN: Condition always false [test/compress/issue-1261.js:137,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:1,61]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:1,23]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:1,23]",
"WARN: Boolean || always true [test/compress/issue-1261.js:2,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:2,23]",
"WARN: Condition always true [test/compress/issue-1261.js:2,23]",
"WARN: Condition left of || always true [test/compress/issue-1261.js:3,8]",
"WARN: Condition always true [test/compress/issue-1261.js:3,8]",
"WARN: Boolean && always false [test/compress/issue-1261.js:4,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:4,23]",
"WARN: Condition always false [test/compress/issue-1261.js:4,23]",
"WARN: Condition left of && always false [test/compress/issue-1261.js:5,8]",
"WARN: Condition always false [test/compress/issue-1261.js:5,8]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:6,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:6,23]",
"WARN: Condition always true [test/compress/issue-1261.js:6,23]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:7,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:7,31]",
"WARN: Condition always true [test/compress/issue-1261.js:7,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:8,23]",
"WARN: Condition always true [test/compress/issue-1261.js:9,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:9,24]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:10,31]",
"WARN: Condition always false [test/compress/issue-1261.js:10,8]",
]
}

View File

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

View File

@@ -1,6 +1,8 @@
issue_1321_no_debug: {
mangle_props = {
keep_quoted: true
mangle = {
properties: {
keep_quoted: true,
},
}
input: {
var x = {};
@@ -10,17 +12,19 @@ issue_1321_no_debug: {
}
expect: {
var x = {};
x.b = 1;
x["a"] = 2 * x.b;
console.log(x.b, x["a"]);
x.x = 1;
x["a"] = 2 * x.x;
console.log(x.x, x["a"]);
}
expect_stdout: true
}
issue_1321_debug: {
mangle_props = {
keep_quoted: true,
debug: ""
mangle = {
properties: {
debug: "",
keep_quoted: true,
},
}
input: {
var x = {};
@@ -30,16 +34,18 @@ issue_1321_debug: {
}
expect: {
var x = {};
x.a = 1;
x["_$foo$_"] = 2 * x.a;
console.log(x.a, x["_$foo$_"]);
x.x = 1;
x["_$foo$_"] = 2 * x.x;
console.log(x.x, x["_$foo$_"]);
}
expect_stdout: true
}
issue_1321_with_quoted: {
mangle_props = {
keep_quoted: false
mangle = {
properties: {
keep_quoted: false,
},
}
input: {
var x = {};
@@ -49,9 +55,9 @@ issue_1321_with_quoted: {
}
expect: {
var x = {};
x.a = 1;
x["b"] = 2 * x.a;
console.log(x.a, x["b"]);
x.x = 1;
x["o"] = 2 * x.x;
console.log(x.x, x["o"]);
}
expect_stdout: true
}

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
typeof_eq_undefined: {
options = {
comparisons: true
comparisons: true,
typeofs: true,
}
input: {
var a = typeof b != "undefined";
@@ -24,6 +25,7 @@ typeof_eq_undefined_ie8: {
options = {
comparisons: true,
ie8: true,
typeofs: true,
}
input: {
var a = typeof b != "undefined";
@@ -45,7 +47,8 @@ typeof_eq_undefined_ie8: {
undefined_redefined: {
options = {
comparisons: true
comparisons: true,
typeofs: true,
}
input: {
function f(undefined) {
@@ -58,7 +61,8 @@ undefined_redefined: {
undefined_redefined_mangle: {
options = {
comparisons: true
comparisons: true,
typeofs: true,
}
mangle = {}
input: {

View File

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

View File

@@ -61,7 +61,7 @@ unsafe_undefined: {
options = {
conditionals: true,
if_return: true,
unsafe: true,
unsafe_undefined: true,
}
mangle = {}
input: {
@@ -85,15 +85,3 @@ unsafe_undefined: {
}
expect_stdout: true
}
runtime_error: {
input: {
const a = 1;
console.log(a++);
}
expect: {
const a = 1;
console.log(a++);
}
expect_stdout: true
}

View File

@@ -2,6 +2,7 @@ chained_evaluation_1: {
options = {
collapse_vars: true,
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -28,6 +29,7 @@ chained_evaluation_2: {
options = {
collapse_vars: true,
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}

View File

@@ -2,7 +2,7 @@
issue_1639_1: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
conditionals: true,
evaluate: true,
join_vars: true,
@@ -26,7 +26,7 @@ issue_1639_1: {
}
expect: {
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
if (--b, !1) var ignore = 0;
if (--b, 0) var ignore = 0;
console.log(a, b);
}
expect_stdout: true
@@ -35,7 +35,7 @@ issue_1639_1: {
issue_1639_2: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
conditionals: true,
evaluate: true,
join_vars: true,
@@ -57,7 +57,7 @@ issue_1639_2: {
expect: {
var a = 100, b = 10;
function f19() {
++a, 1;
++a, 0;
}
f19(),
console.log(a, b);
@@ -68,7 +68,7 @@ issue_1639_2: {
issue_1639_3: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
conditionals: true,
evaluate: true,
sequences: true,

View File

@@ -1,7 +1,6 @@
f7: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
comparisons: true,
conditionals: true,
@@ -15,6 +14,7 @@ f7: {
negate_iife: true,
passes: 3,
properties: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -38,7 +38,7 @@ f7: {
"var b = 10;",
"",
"!function() {",
" for (;b = 100, !1; ) ;",
" b = 100;",
"}(), console.log(100, b);",
]
expect_stdout: true

View File

@@ -1,5 +1,6 @@
side_effects_catch: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -34,6 +35,7 @@ side_effects_catch: {
side_effects_else: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -62,6 +64,7 @@ side_effects_else: {
side_effects_finally: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -98,6 +101,7 @@ side_effects_finally: {
side_effects_label: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -130,6 +134,7 @@ side_effects_label: {
side_effects_switch: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,

View File

@@ -104,7 +104,7 @@ mangle_catch_toplevel: {
}
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"
}
@@ -148,7 +148,7 @@ mangle_catch_var_toplevel: {
}
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"
}
@@ -345,3 +345,95 @@ mangle_catch_redef_2_ie8_toplevel: {
expect_exact: 'try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
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();
}
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"
}
@@ -36,7 +36,7 @@ function_iife_catch_ie8: {
}
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"
}
@@ -61,7 +61,7 @@ function_catch_catch: {
}
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: [
"3",
"undefined",

View File

@@ -7,7 +7,7 @@ case_1: {
input: {
var a = 0, b = 1;
switch (true) {
case a, true:
case a || true:
default:
b = 2;
case true:
@@ -17,7 +17,7 @@ case_1: {
expect: {
var a = 0, b = 1;
switch (true) {
case a, true:
case a || true:
b = 2;
}
console.log(a, b);

View File

@@ -1,5 +1,7 @@
mangle_props: {
mangle_props = {}
mangle = {
properties: true,
}
input: {
var obj = {
undefined: 1,
@@ -54,10 +56,12 @@ mangle_props: {
}
numeric_literal: {
mangle = {
properties: true,
}
beautify = {
beautify: true,
}
mangle_props = {}
input: {
var obj = {
0: 0,
@@ -80,19 +84,19 @@ numeric_literal: {
' 0: 0,',
' "-0": 1,',
' 42: 2,',
' "42": 3,',
' 42: 3,',
' 37: 4,',
' a: 5,',
' o: 5,',
' 1e42: 6,',
' b: 7,',
' "1e+42": 8',
' 1e42: 8',
'};',
'',
'console.log(obj[-0], obj[-""], obj["-0"]);',
'',
'console.log(obj[42], obj["42"]);',
'',
'console.log(obj[37], obj["a"], obj[37], obj["37"]);',
'console.log(obj[37], obj["o"], obj[37], obj["37"]);',
'',
'console.log(obj[1e42], obj["b"], obj["1e+42"]);',
]
@@ -105,7 +109,9 @@ numeric_literal: {
}
identifier: {
mangle_props = {}
mangle = {
properties: true,
}
input: {
var obj = {
abstract: 1,
@@ -173,32 +179,32 @@ identifier: {
}
expect: {
var obj = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
f: 6,
g: 7,
h: 8,
i: 9,
j: 10,
k: 11,
l: 12,
m: 13,
n: 14,
o: 15,
p: 16,
q: 17,
r: 18,
s: 19,
t: 20,
u: 21,
v: 22,
w: 23,
x: 24,
y: 25,
z: 26,
e: 1,
t: 2,
n: 3,
a: 4,
i: 5,
o: 6,
r: 7,
l: 8,
s: 9,
c: 10,
f: 11,
u: 12,
d: 13,
h: 14,
p: 15,
b: 16,
v: 17,
w: 18,
y: 19,
g: 20,
m: 21,
k: 22,
x: 23,
j: 24,
z: 25,
q: 26,
A: 27,
B: 28,
C: 29,
@@ -229,11 +235,11 @@ identifier: {
Z: 54,
$: 55,
_: 56,
aa: 57,
ba: 58,
ca: 59,
da: 60,
ea: 61,
ee: 57,
te: 58,
ne: 59,
ae: 60,
ie: 61,
};
}
}

View File

@@ -1,6 +1,8 @@
unary_prefix: {
options = {
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}

View File

@@ -1,6 +1,7 @@
iife_for: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -26,6 +27,7 @@ iife_for: {
iife_for_in: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -51,6 +53,7 @@ iife_for_in: {
iife_do: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -80,6 +83,7 @@ iife_do: {
iife_while: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -121,8 +125,8 @@ label_do: {
label_while: {
options = {
evaluate: true,
dead_code: true,
evaluate: true,
loops: true,
}
input: {
@@ -130,5 +134,5 @@ label_while: {
L: while (0) continue L;
}
}
expect_exact: "function f(){L:;}"
expect_exact: "function f(){L:0}"
}

View File

@@ -0,0 +1,31 @@
operator: {
input: {
a. //comment
typeof
}
expect_exact: "a.typeof;"
}
name: {
input: {
a. //comment
b
}
expect_exact: "a.b;"
}
keyword: {
input: {
a. //comment
default
}
expect_exact: "a.default;"
}
atom: {
input: {
a. //comment
true
}
expect_exact: "a.true;"
}

View File

@@ -1,6 +1,8 @@
do_not_update_lhs: {
options = {
global_defs: { DEBUG: 0 }
global_defs: {
DEBUG: 0,
},
}
input: {
DEBUG++;
@@ -16,7 +18,9 @@ do_not_update_lhs: {
do_update_rhs: {
options = {
global_defs: { DEBUG: 0 }
global_defs: {
DEBUG: 0,
},
}
input: {
MY_DEBUG = DEBUG;
@@ -35,10 +39,10 @@ mixed: {
DEBUG: 0,
ENV: 1,
FOO: 2,
}
},
}
input: {
const ENV = 3;
var ENV = 3;
var FOO = 4;
f(ENV * 10);
--FOO;
@@ -49,7 +53,7 @@ mixed: {
x = DEBUG;
}
expect: {
const ENV = 3;
var ENV = 3;
var FOO = 4;
f(10);
--FOO;
@@ -60,11 +64,11 @@ mixed: {
x = 0;
}
expect_warnings: [
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,14]',
'WARN: global_defs FOO redefined [test/compress/issue-208.js:42,12]',
'WARN: global_defs FOO redefined [test/compress/issue-208.js:44,10]',
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:45,8]',
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:46,8]',
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:47,8]',
"WARN: global_defs ENV redefined [test/compress/issue-208.js:1,12]",
"WARN: global_defs FOO redefined [test/compress/issue-208.js:2,12]",
"WARN: global_defs FOO redefined [test/compress/issue-208.js:4,10]",
"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:5,8]",
"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:6,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: {
options = { conditionals: true };
options = {
conditionals: true,
}
input: {
function foo(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: {
options = { comparisons: true };
options = {
comparisons: true,
}
input: {
x = a % b / b * c * 2;
x = a % b * 2

View File

@@ -1,5 +1,7 @@
issue_269_1: {
options = {unsafe: true};
options = {
unsafe: true,
}
input: {
f(
String(x),
@@ -20,7 +22,9 @@ issue_269_1: {
}
issue_269_dangers: {
options = {unsafe: true};
options = {
unsafe: true,
}
input: {
f(
String(x, x),
@@ -34,7 +38,9 @@ issue_269_dangers: {
}
issue_269_in_scope: {
options = {unsafe: true};
options = {
unsafe: true,
}
input: {
var String, Number, Boolean;
f(
@@ -50,7 +56,9 @@ issue_269_in_scope: {
}
strings_concat: {
options = {unsafe: true};
options = {
unsafe: true,
}
input: {
f(
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]",
]
}

498
test/compress/issue-281.js Normal file
View File

@@ -0,0 +1,498 @@
collapse_vars_constants: {
options = {
collapse_vars: true,
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
function f1(x) {
var a = 4, b = x.prop, c = 5, d = sideeffect1(), e = sideeffect2();
return b + (function() { return d - a * e - c; })();
}
function f2(x) {
var a = 4, b = x.prop, c = 5, not_used = sideeffect1(), e = sideeffect2();
return b + (function() { return -a * e - c; })();
}
}
expect: {
function f1(x) {
var b = x.prop, d = sideeffect1(), e = sideeffect2();
return b + (d - 4 * e - 5);
}
function f2(x) {
var b = x.prop;
sideeffect1();
return b + (-4 * sideeffect2() - 5);
}
}
}
modified: {
options = {
collapse_vars: true,
inline: true,
unused: true,
}
input: {
function f5(b) {
var a = function() {
return b;
}();
return b++ + a;
}
console.log(f5(1));
}
expect: {
function f5(b) {
var a = b;
return b++ + a;
}
console.log(f5(1));
}
expect_stdout: "2"
}
ref_scope: {
options = {
collapse_vars: true,
inline: true,
unused: true,
}
input: {
console.log(function() {
var a = 1, b = 2, c = 3;
var a = c++, b = b /= a;
return function() {
return a;
}() + b;
}());
}
expect: {
console.log(function() {
var a = 1, b = 2, c = 3;
b = b /= a = c++;
return a + b;
}());
}
expect_stdout: true
}
safe_undefined: {
options = {
conditionals: true,
if_return: true,
inline: true,
unsafe: false,
unused: true,
}
mangle = {}
input: {
var a, c;
console.log(function(undefined) {
return function() {
if (a)
return b;
if (c)
return d;
};
}(1)());
}
expect: {
var a, c;
console.log(a ? b : c ? d : void 0);
}
expect_stdout: true
}
negate_iife_3: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: true,
}
input: {
(function(){ return t })() ? console.log(true) : console.log(false);
}
expect: {
t ? console.log(true) : console.log(false);
}
}
negate_iife_3_off: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: false,
}
input: {
(function(){ return t })() ? console.log(true) : console.log(false);
}
expect: {
t ? console.log(true) : console.log(false);
}
}
negate_iife_4: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: true,
sequences: true,
}
input: {
(function(){ return t })() ? console.log(true) : console.log(false);
(function(){
console.log("something");
})();
}
expect: {
t ? console.log(true) : console.log(false), void console.log("something");
}
}
negate_iife_5: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: true,
sequences: true,
}
input: {
if ((function(){ return t })()) {
foo(true);
} else {
bar(false);
}
(function(){
console.log("something");
})();
}
expect: {
t ? foo(true) : bar(false), void console.log("something");
}
}
negate_iife_5_off: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: false,
sequences: true,
}
input: {
if ((function(){ return t })()) {
foo(true);
} else {
bar(false);
}
(function(){
console.log("something");
})();
}
expect: {
t ? foo(true) : bar(false), void console.log("something");
}
}
issue_1254_negate_iife_true: {
options = {
expression: true,
inline: true,
negate_iife: true,
}
input: {
(function() {
return function() {
console.log('test')
};
})()();
}
expect_exact: 'void console.log("test");'
expect_stdout: true
}
issue_1254_negate_iife_nested: {
options = {
expression: true,
inline: true,
negate_iife: true,
}
input: {
(function() {
return function() {
console.log('test')
};
})()()()()();
}
expect_exact: '(void console.log("test"))()()();'
}
negate_iife_issue_1073: {
options = {
conditionals: true,
evaluate: true,
inline: true,
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
unused: true,
}
input: {
new (function(a) {
return function Foo() {
this.x = a;
console.log(this);
};
}(7))();
}
expect: {
new function() {
this.x = 7,
console.log(this);
}();
}
expect_stdout: true
}
issue_1288_side_effects: {
options = {
conditionals: true,
evaluate: true,
inline: true,
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
if (w) ;
else {
(function f() {})();
}
if (!x) {
(function() {
x = {};
})();
}
if (y)
(function() {})();
else
(function(z) {
return z;
})(0);
}
expect: {
w;
x || (x = {});
y;
}
}
inner_var_for_in_1: {
options = {
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
}
input: {
function f() {
var a = 1, b = 2;
for (b in (function() {
return x(a, b, c);
})()) {
var c = 3, d = 4;
x(a, b, c, d);
}
x(a, b, c, d);
}
}
expect: {
function f() {
var a = 1, b = 2;
for (b in x(1, b, c)) {
var c = 3, d = 4;
x(1, b, c, d);
}
x(1, b, c, d);
}
}
}
issue_1595_3: {
options = {
evaluate: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function f(a) {
return g(a + 1);
})(2);
}
expect: {
g(3);
}
}
issue_1758: {
options = {
inline: true,
sequences: true,
side_effects: true,
}
input: {
console.log(function(c) {
var undefined = 42;
return function() {
c--;
c--, c.toString();
return;
}();
}());
}
expect: {
console.log(function(c) {
var undefined = 42;
return c--, c--, void c.toString();
}());
}
expect_stdout: "undefined"
}
wrap_iife: {
options = {
inline: true,
negate_iife: false,
}
beautify = {
wrap_iife: true,
}
input: {
(function() {
return function() {
console.log('test')
};
})()();
}
expect_exact: 'void console.log("test");'
}
wrap_iife_in_expression: {
options = {
inline: true,
negate_iife: false,
}
beautify = {
wrap_iife: true,
}
input: {
foo = (function() {
return bar();
})();
}
expect_exact: 'foo=bar();'
}
wrap_iife_in_return_call: {
options = {
inline: true,
negate_iife: false,
}
beautify = {
wrap_iife: true,
}
input: {
(function() {
return (function() {
console.log('test')
})();
})()();
}
expect_exact: '(void console.log("test"))();'
}
pure_annotation_1: {
options = {
inline: true,
side_effects: true,
}
input: {
/*@__PURE__*/(function() {
console.log("hello");
}());
}
expect_exact: ""
}
pure_annotation_2: {
options = {
collapse_vars: true,
inline: true,
side_effects: true,
}
input: {
/*@__PURE__*/(function(n) {
console.log("hello", n);
}(42));
}
expect_exact: ""
}
drop_fargs: {
options = {
collapse_vars: true,
inline: true,
keep_fargs: false,
side_effects: true,
unused: true,
}
input: {
var a = 1;
!function(a_1) {
a++;
}(a++ + (a && a.var));
console.log(a);
}
expect: {
var a = 1;
++a && a.var, a++;
console.log(a);
}
expect_stdout: "3"
}
keep_fargs: {
options = {
collapse_vars: true,
inline: true,
keep_fargs: true,
side_effects: true,
unused: true,
}
input: {
var a = 1;
!function(a_1) {
a++;
}(a++ + (a && a.var));
console.log(a);
}
expect: {
var a = 1;
++a && a.var, a++;
console.log(a);
}
expect_stdout: "3"
}

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,6 +1,6 @@
collapse: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
unused: true,
@@ -41,7 +41,7 @@ collapse: {
return void 0 !== ('function' === typeof b ? b() : b) && c();
}
function f2(b) {
return b = c(), 'stirng' == typeof ('function' === typeof b ? b() : b) && d();
return 'stirng' == typeof ('function' === typeof (b = c()) ? b() : b) && d();
}
function f3(c) {
var a;

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,9 +1,9 @@
wrongly_optimized: {
options = {
conditionals: true,
booleans: true,
evaluate: true
};
conditionals: true,
evaluate: true,
}
input: {
function func() {
foo();
@@ -17,6 +17,6 @@ wrongly_optimized: {
foo();
}
// TODO: optimize to `func(), bar()`
(func(), 0) || bar();
(func(), 1) && bar();
}
}

View File

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

View File

@@ -1,37 +1,45 @@
dont_reuse_prop: {
mangle_props = {
regex: /asd/
};
mangle = {
properties: {
regex: /asd/,
},
}
input: {
"aaaaaaaaaabbbbb";
var obj = {};
obj.a = 123;
obj.asd = 256;
console.log(obj.a);
}
expect: {
"aaaaaaaaaabbbbb";
var obj = {};
obj.a = 123;
obj.b = 256;
console.log(obj.a);
}
expect_stdout: "123"
}
unmangleable_props_should_always_be_reserved: {
mangle_props = {
regex: /asd/
};
mangle = {
properties: {
regex: /asd/,
},
}
input: {
"aaaaaaaaaabbbbb";
var obj = {};
obj.asd = 256;
obj.a = 123;
console.log(obj.a);
}
expect: {
"aaaaaaaaaabbbbb";
var obj = {};
obj.b = 256;
obj.a = 123;
console.log(obj.a);
}
}
expect_stdout: "123"
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,9 +1,11 @@
this_binding_conditionals: {
options = {
conditionals: true,
evaluate : true
};
evaluate: true,
side_effects: true,
}
input: {
"use strict";
(1 && a)();
(0 || a)();
(0 || 1 && a)();
@@ -25,6 +27,7 @@ this_binding_conditionals: {
(1 ? eval : 0)();
}
expect: {
"use strict";
a();
a();
a();
@@ -51,13 +54,16 @@ this_binding_collapse_vars: {
options = {
collapse_vars: true,
toplevel: true,
};
unused: true,
}
input: {
"use strict";
var c = a; c();
var d = a.b; d();
var e = eval; e();
}
expect: {
"use strict";
a();
(0, a.b)();
(0, eval)();
@@ -66,32 +72,89 @@ this_binding_collapse_vars: {
this_binding_side_effects: {
options = {
side_effects : true
};
side_effects: true,
}
input: {
(function (foo) {
(function(foo) {
(0, foo)();
(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;
(0, foo)();
(0, foo.bar)();
(0, eval)('console.log(foo);');
(0, eval)("console.log(foo);");
}());
}
expect: {
(function (foo) {
(function(foo) {
foo();
(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;
foo();
(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: {
options = {
collapse_vars:true, sequences:false, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
};
booleans: true,
collapse_vars: 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: {
function f1() {
var e = 7;
@@ -46,7 +58,10 @@ eval_collapse_vars: {
}
eval_unused: {
options = { unused: true, keep_fargs: false };
options = {
keep_fargs: false,
unused: true,
}
input: {
function f1(a, eval, c, d, e) {
return a('c') + eval;

View File

@@ -1,8 +1,19 @@
issue979_reported: {
options = {
sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
booleans: 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: {
function f1() {
@@ -30,9 +41,20 @@ issue979_reported: {
issue979_test_negated_is_best: {
options = {
sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
booleans: 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: {
function f3() {

View File

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

View File

@@ -1,5 +1,7 @@
while_becomes_for: {
options = { loops: true };
options = {
loops: true,
}
input: {
while (foo()) bar();
}
@@ -9,7 +11,9 @@ while_becomes_for: {
}
drop_if_break_1: {
options = { loops: true };
options = {
loops: true,
}
input: {
for (;;)
if (foo()) break;
@@ -20,7 +24,9 @@ drop_if_break_1: {
}
drop_if_break_2: {
options = { loops: true };
options = {
loops: true,
}
input: {
for (;bar();)
if (foo()) break;
@@ -31,7 +37,9 @@ drop_if_break_2: {
}
drop_if_break_3: {
options = { loops: true };
options = {
loops: true,
}
input: {
for (;bar();) {
if (foo()) break;
@@ -48,7 +56,10 @@ drop_if_break_3: {
}
drop_if_break_4: {
options = { loops: true, sequences: true };
options = {
loops: true,
sequences: true,
}
input: {
for (;bar();) {
x();
@@ -64,7 +75,9 @@ drop_if_break_4: {
}
drop_if_else_break_1: {
options = { loops: true };
options = {
loops: true,
}
input: {
for (;;) if (foo()) bar(); else break;
}
@@ -74,7 +87,9 @@ drop_if_else_break_1: {
}
drop_if_else_break_2: {
options = { loops: true };
options = {
loops: true,
}
input: {
for (;bar();) {
if (foo()) baz();
@@ -87,7 +102,9 @@ drop_if_else_break_2: {
}
drop_if_else_break_3: {
options = { loops: true };
options = {
loops: true,
}
input: {
for (;bar();) {
if (foo()) baz();
@@ -106,7 +123,10 @@ drop_if_else_break_3: {
}
drop_if_else_break_4: {
options = { loops: true, sequences: true };
options = {
loops: true,
sequences: true,
}
input: {
for (;bar();) {
x();
@@ -123,7 +143,9 @@ drop_if_else_break_4: {
}
parse_do_while_with_semicolon: {
options = { loops: false };
options = {
loops: false,
}
input: {
do {
x();
@@ -135,7 +157,9 @@ parse_do_while_with_semicolon: {
}
parse_do_while_without_semicolon: {
options = { loops: false };
options = {
loops: false,
}
input: {
do {
x();
@@ -146,56 +170,14 @@ parse_do_while_without_semicolon: {
}
}
keep_collapse_const_in_own_block_scope: {
options = {
join_vars: true,
loops: true
}
input: {
var i=2;
const c=5;
while(i--)
console.log(i);
console.log(c);
}
expect: {
var i=2;
const c=5;
for(;i--;)
console.log(i);
console.log(c);
}
expect_stdout: true
}
keep_collapse_const_in_own_block_scope_2: {
options = {
join_vars: true,
loops: true
}
input: {
const c=5;
var i=2; // Moves to loop, while it did not in previous test
while(i--)
console.log(i);
console.log(c);
}
expect: {
const c=5;
for(var i=2;i--;)
console.log(i);
console.log(c);
}
expect_stdout: true
}
evaluate: {
options = {
loops: true,
dead_code: true,
evaluate: true,
};
loops: true,
passes: 2,
side_effects: true,
}
input: {
while (true) {
a();
@@ -336,10 +318,10 @@ issue_186_beautify_ie8: {
]
}
issue_186_bracketize: {
issue_186_braces: {
beautify = {
beautify: false,
bracketize: true,
braces: true,
ie8: false,
}
input: {
@@ -356,10 +338,10 @@ issue_186_bracketize: {
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: false,
bracketize: true,
braces: true,
ie8: true,
}
input: {
@@ -376,10 +358,10 @@ issue_186_bracketize_ie8: {
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: true,
bracketize: true,
braces: true,
ie8: false,
}
input: {
@@ -408,10 +390,10 @@ issue_186_beautify_bracketize: {
]
}
issue_186_beautify_bracketize_ie8: {
issue_186_beautify_braces_ie8: {
beautify = {
beautify: true,
bracketize: true,
braces: true,
ie8: true,
}
input: {
@@ -480,3 +462,187 @@ do_switch: {
} while (false);
}
}
in_parenthesis_1: {
input: {
for (("foo" in {});0;);
}
expect_exact: 'for(("foo"in{});0;);'
}
in_parenthesis_2: {
input: {
for ((function(){ "foo" in {}; });0;);
}
expect_exact: 'for(function(){"foo"in{}};0;);'
}
init_side_effects: {
options = {
loops: true,
side_effects: true,
}
input: {
for (function() {}(), i = 0; i < 5; i++) console.log(i);
for (function() {}(); i < 10; i++) console.log(i);
}
expect: {
for (i = 0; i < 5; i++) console.log(i);
for (; i < 10; i++) console.log(i);
}
expect_stdout: true
}
dead_code_condition: {
options = {
dead_code: true,
evaluate: true,
loops: true,
sequences: true,
}
input: {
for (var a = 0, b = 5; (a += 1, 3) - 3 && b > 0; b--) {
var c = function() {
b--;
}(a++);
}
console.log(a);
}
expect: {
var c;
var a = 0, b = 5;
a += 1, 0,
console.log(a);
}
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: [
'function f(a){',
'return{',
'c:42,',
'd:a(),',
'e:"foo"}}',
"function f(",
"a){return{",
"c:42,d:a(",
'),e:"foo"}',
"}",
]
expect_warnings: [
"WARN: Output exceeds 10 characters"
"WARN: Output exceeds 10 characters",
]
}
@@ -29,11 +29,25 @@ just_enough: {
}
}
expect_exact: [
'function f(a){',
'return{c:42,',
"function f(a){",
"return{c:42,",
'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: {
options = {
negate_iife: true
};
negate_iife: true,
}
input: {
(function(){ stuff() })();
}
@@ -13,7 +13,7 @@ negate_iife_1: {
negate_iife_1_off: {
options = {
negate_iife: false,
};
}
input: {
(function(){ stuff() })();
}
@@ -22,8 +22,9 @@ negate_iife_1_off: {
negate_iife_2: {
options = {
negate_iife: true
};
inline: true,
negate_iife: true,
}
input: {
(function(){ return {} })().x = 10;
}
@@ -32,6 +33,7 @@ negate_iife_2: {
negate_iife_2_side_effects: {
options = {
inline: true,
negate_iife: true,
side_effects: true,
}
@@ -43,9 +45,9 @@ negate_iife_2_side_effects: {
negate_iife_3: {
options = {
conditionals: true,
negate_iife: true,
conditionals: true
};
}
input: {
(function(){ return t })() ? console.log(true) : console.log(false);
}
@@ -58,13 +60,14 @@ negate_iife_3_evaluate: {
options = {
conditionals: true,
evaluate: true,
inline: true,
negate_iife: true,
}
input: {
(function(){ return true })() ? console.log(true) : console.log(false);
}
expect: {
console.log(true);
true, console.log(true);
}
expect_stdout: true
}
@@ -85,9 +88,9 @@ negate_iife_3_side_effects: {
negate_iife_3_off: {
options = {
negate_iife: false,
conditionals: true,
};
negate_iife: false,
}
input: {
(function(){ return t })() ? console.log(true) : console.log(false);
}
@@ -100,23 +103,24 @@ negate_iife_3_off_evaluate: {
options = {
conditionals: true,
evaluate: true,
inline: true,
negate_iife: false,
}
input: {
(function(){ return true })() ? console.log(true) : console.log(false);
}
expect: {
console.log(true);
true, console.log(true);
}
expect_stdout: true
}
negate_iife_4: {
options = {
negate_iife: true,
conditionals: true,
sequences: true
};
negate_iife: true,
sequences: true,
}
input: {
(function(){ return t })() ? console.log(true) : console.log(false);
(function(){
@@ -132,11 +136,11 @@ negate_iife_4: {
sequence_off: {
options = {
negate_iife: false,
conditionals: true,
sequences: true,
negate_iife: false,
passes: 2,
};
sequences: true,
}
input: {
function f() {
(function(){ return t })() ? console.log(true) : console.log(false);
@@ -167,10 +171,10 @@ sequence_off: {
negate_iife_5: {
options = {
conditionals: true,
negate_iife: true,
sequences: true,
conditionals: true,
};
}
input: {
if ((function(){ return t })()) {
foo(true);
@@ -190,10 +194,10 @@ negate_iife_5: {
negate_iife_5_off: {
options = {
conditionals: true,
negate_iife: false,
sequences: true,
conditionals: true,
};
}
input: {
if ((function(){ return t })()) {
foo(true);
@@ -213,10 +217,10 @@ negate_iife_5_off: {
negate_iife_nested: {
options = {
conditionals: true,
negate_iife: true,
sequences: true,
conditionals: true,
};
}
input: {
function Foo(f) {
this.f = f;
@@ -246,10 +250,10 @@ negate_iife_nested: {
negate_iife_nested_off: {
options = {
conditionals: true,
negate_iife: false,
sequences: true,
conditionals: true,
};
}
input: {
function Foo(f) {
this.f = f;
@@ -279,10 +283,10 @@ negate_iife_nested_off: {
negate_iife_issue_1073: {
options = {
conditionals: true,
negate_iife: true,
sequences: true,
conditionals: true,
};
}
input: {
new (function(a) {
return function Foo() {
@@ -352,7 +356,7 @@ issue_1288: {
conditionals: true,
negate_iife: true,
side_effects: false,
};
}
input: {
if (w) ;
else {

View File

@@ -36,7 +36,9 @@ new_statements_3: {
}
new_with_rewritten_true_value: {
options = { booleans: true }
options = {
booleans: true,
}
input: {
new true;
}
@@ -82,3 +84,19 @@ new_with_unary_prefix: {
}
expect_exact: 'var bar=(+new Date).toString(32);';
}
dot_parenthesis_1: {
input: {
console.log(new (Math.random().constructor) instanceof Number);
}
expect_exact: "console.log(new(Math.random().constructor)instanceof Number);"
expect_stdout: "true"
}
dot_parenthesis_2: {
input: {
console.log(typeof new function(){Math.random()}.constructor);
}
expect_exact: "console.log(typeof new function(){Math.random()}.constructor);"
expect_stdout: "function"
}

View File

@@ -0,0 +1,38 @@
eval_let_6: {
input: {
eval("let a;");
console.log();
}
expect: {
eval("let a;");
console.log();
}
expect_stdout: ""
node_version: ">=6"
}
eval_let_4: {
input: {
eval("let a;");
console.log();
}
expect: {
eval("let a;");
console.log();
}
expect_stdout: SyntaxError("Block-scoped declarations (let, const, function, class) not yet supported outside strict mode")
node_version: "4"
}
eval_let_0: {
input: {
eval("let a;");
console.log();
}
expect: {
eval("let a;");
console.log();
}
expect_stdout: SyntaxError("Unexpected identifier")
node_version: "<=0.12"
}

View File

@@ -1,21 +1,49 @@
hex_numbers_in_parentheses_for_prototype_functions: {
input: {
(-2);
(-2).toFixed(0);
(2);
(2).toFixed(0);
(0.2);
(0.2).toFixed(0);
(0.00000002);
(0.00000002).toFixed(0);
(1000000000000000128);
(1000000000000000128).toFixed(0);
beautify = {
beautify: true,
}
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: {

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;",
"};",
]
}

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