Compare commits

...

787 Commits

Author SHA1 Message Date
Alex Lam S.L
bba7cd0a70 v3.12.3 2020-12-22 23:59:53 +08:00
Alex Lam S.L
e1b2026929 improve object function generation in ufuzz (#4434) 2020-12-21 15:32:50 +08:00
Alex Lam S.L
c319030373 fix corner case in reduce_vars (#4433)
fixes #4432
2020-12-21 14:03:18 +08:00
Alex Lam S.L
47b63ed1a0 fix corner case in collapse_vars (#4431)
fixes #4430
2020-12-20 22:54:27 +08:00
Alex Lam S.L
7aefe97083 parse destructuring under strict mode correctly (#4429) 2020-12-20 20:48:51 +08:00
Alex Lam S.L
89198e0ad4 improve destructuring generation in ufuzz (#4428) 2020-12-20 13:38:56 +08:00
Alex Lam S.L
caea6aac81 handle destructuring catch in --reduce-test (#4427) 2020-12-20 11:22:45 +08:00
Alex Lam S.L
f5224ca1f5 fix corner case with destructuring catch (#4426)
fixes #4425
2020-12-20 10:31:32 +08:00
Alex Lam S.L
b7c49b72b3 support async function within object literal (#4424) 2020-12-20 08:19:04 +08:00
Alex Lam S.L
8ce3c7d70f fix corner case in evaluate & reduce_vars (#4423)
fixes #4422
2020-12-20 05:47:15 +08:00
Alex Lam S.L
87cf715213 fix corner case with destructuring catch (#4421)
fixes #4420
2020-12-20 05:47:01 +08:00
Alex Lam S.L
2c9c72e06c suppress false positives in ufuzz (#4419) 2020-12-20 02:31:09 +08:00
Alex Lam S.L
882968c68c fix corner case in inline (#4418)
fixes #4417
2020-12-20 01:24:29 +08:00
Alex Lam S.L
acc2d7d845 fix corner case in objects (#4416)
fixes #4415
2020-12-20 00:14:57 +08:00
Alex Lam S.L
9a5aede941 fix corner case in reduce_vars & unused (#4414)
fixes #4413
2020-12-19 12:47:46 +08:00
Alex Lam S.L
e6dd471f8f support destructuring of catch variable (#4412) 2020-12-19 12:28:38 +08:00
Alex Lam S.L
0f55bd92f1 fix corner case in arguments (#4411)
fixes #4410
2020-12-19 04:53:53 +08:00
Alex Lam S.L
7d9dad0289 fix corner case with parentheses (#4409)
fixes #4408
2020-12-19 01:01:49 +08:00
Alex Lam S.L
44e494f16f fix corner case in merge_vars (#4407)
fixes #4406
2020-12-19 00:52:37 +08:00
Alex Lam S.L
2415a72e75 fix corner case in unused (#4405)
fixes #4404
2020-12-18 23:45:41 +08:00
Alex Lam S.L
9c0718b162 enhance arrows (#4403) 2020-12-18 14:55:20 +08:00
Alex Lam S.L
d2c50ace99 fix corner case in merge_vars (#4402)
fixes #4401
2020-12-18 12:20:43 +08:00
Alex Lam S.L
1b646d3bc4 fix corner case in arguments (#4400)
fixes #4399
2020-12-18 10:12:01 +08:00
Alex Lam S.L
82d2aa4acf fix corner case in arguments (#4398)
fixes #4397
2020-12-18 09:42:07 +08:00
Alex Lam S.L
c1256c399a fix corner case in arguments (#4396)
fixes #4395
2020-12-18 08:41:13 +08:00
Alex Lam S.L
2c637fea8a fix corner case in evaluate & reduce_vars (#4394)
fixes #4393
2020-12-18 07:16:04 +08:00
Alex Lam S.L
4fa54b075c enhance reduce_vars (#4392) 2020-12-18 06:18:47 +08:00
Alex Lam S.L
ab82be82b2 fix corner case in collapse_vars (#4391)
fixes #4390
2020-12-18 03:10:16 +08:00
Alex Lam S.L
02fdcfde01 fix corner case in inline (#4389)
fixes #4388
2020-12-18 00:55:19 +08:00
Alex Lam S.L
a96f087ac3 support arrow function (#4385) 2020-12-17 18:23:41 +08:00
Alex Lam S.L
75e9fd8417 fix corner case in arguments (#4387)
fixes #4386
2020-12-17 13:51:34 +08:00
Alex Lam S.L
f68e267830 fix corner case in reduce_vars (#4384)
fixes #4383
2020-12-17 04:47:48 +08:00
Alex Lam S.L
8b10b93ee1 v3.12.2 2020-12-16 14:11:48 +08:00
Alex Lam S.L
549de028b6 fix corner case in objects (#4381)
fixes #4380
2020-12-15 21:23:55 +08:00
Alex Lam S.L
f579f1aa47 emulate global context in Node.js & web (#4379) 2020-12-14 02:05:07 +08:00
Alex Lam S.L
fcc40d0502 fix corner case in dead_code (#4378)
fixes #4377
2020-12-14 00:03:44 +08:00
Alex Lam S.L
b309527264 maintain compatibility options when testing (#4376) 2020-12-13 14:26:45 +08:00
Alex Lam S.L
5d19bb8d5d fix corner case in booleans (#4375)
fixes #4374
2020-12-13 05:01:38 +08:00
Alex Lam S.L
af97629912 fix corner case in dead_code (#4373)
fixes #4372
2020-12-13 02:24:18 +08:00
Alex Lam S.L
8c000033d3 clarify corner case in object literal (#4371)
closes #4366
2020-12-12 07:42:29 +08:00
Alex Lam S.L
fd0d28e465 fix corner case in spread (#4370) 2020-12-12 06:45:59 +08:00
Alex Lam S.L
2123f38394 fix asynchronous state tracking in ufuzz (#4369) 2020-12-12 05:19:56 +08:00
Alex Lam S.L
58dff9ada3 fix corner cases in unused & varify (#4368)
fixes #4365
2020-12-12 04:45:35 +08:00
Alex Lam S.L
4fdec765bc gate language features in ufuzz automatically (#4367) 2020-12-12 03:43:12 +08:00
Alex Lam S.L
1020d37256 fix corner case in spread (#4364)
fixes #4363
2020-12-12 02:19:11 +08:00
Alex Lam S.L
076739db07 fix corner case in unused (#4362)
fixes #4361
2020-12-12 00:57:05 +08:00
Alex Lam S.L
515e93d88a fix corner case in collapse_vars (#4360)
fixes #4359
2020-12-12 00:07:28 +08:00
Alex Lam S.L
57105b299e fix corner cases with spread syntax (#4358) 2020-12-11 06:59:21 +08:00
Alex Lam S.L
77e1bda426 improve fix for #4355 (#4357) 2020-12-11 00:48:41 +08:00
Alex Lam S.L
a59593cac8 fix corner case in loops & unused (#4356)
fixes #4355
2020-12-10 15:45:39 +08:00
Alex Lam S.L
046bbde9d4 fix corner case in keep_fargs & reduce_vars (#4354)
fixes #4353
2020-12-09 01:41:10 +08:00
Alex Lam S.L
fea9da9866 forbid AST_Await in computed function arguments (#4352)
fixes #4351
2020-12-08 12:59:08 +08:00
Alex Lam S.L
4733159782 fix corner cases with await (#4350)
fixes #4349
2020-12-08 11:26:03 +08:00
Alex Lam S.L
5fba98608c fix corner case in reduce_vars (#4348)
fixes #4347
2020-12-08 08:52:14 +08:00
Alex Lam S.L
c587d7917d introduce spread (#4346)
fixes #4345
2020-12-08 06:51:20 +08:00
Alex Lam S.L
336336f53f fix corner case with parentheses around await (#4344) 2020-12-08 04:29:54 +08:00
Alex Lam S.L
4bde50ce85 fix corner case in side_effects (#4343)
fixes #4342
2020-12-07 17:25:04 +08:00
Alex Lam S.L
fbecedf94c fix corner case in evaluate (#4341)
fixes #4340
2020-12-07 16:05:11 +08:00
Alex Lam S.L
2f31f95095 improve ufuzz (#4339) 2020-12-07 16:04:51 +08:00
Alex Lam S.L
6b603e1a62 fix corner case in unused (#4338)
fixes #4337
2020-12-07 13:23:53 +08:00
Alex Lam S.L
499f8d89ff fix corner case in inline (#4336)
fixes #4335
2020-12-07 11:30:37 +08:00
Alex Lam S.L
9eb65f3af3 extend trailing comma support (#4334) 2020-12-07 10:07:34 +08:00
Alex Lam S.L
2cbbf5c375 support async function (#4333) 2020-12-07 05:22:40 +08:00
Alex Lam S.L
3c384cf9a8 fix corner case in collapse_vars (#4332)
fixes #4331
2020-12-06 18:30:50 +08:00
Alex Lam S.L
37f4f56752 fix corner case in properties (#4330)
fixes #4329
2020-12-06 13:59:04 +08:00
Alex Lam S.L
1e4985ed9e support spread syntax (#4328) 2020-12-06 05:19:31 +08:00
Alex Lam S.L
d2d56e301e v3.12.1 2020-12-01 01:46:27 +08:00
Alex Lam S.L
9d34f8428b fix corner case in side_effects (#4326)
fixes #4325
2020-11-29 10:05:48 +08:00
Alex Lam S.L
f045e2b460 fix corner case in merge_vars (#4324)
fixes #4323
2020-11-29 05:38:24 +08:00
Alex Lam S.L
8791f258e3 fix corner case in inline (#4322)
fixes #4321
2020-11-29 03:48:42 +08:00
Alex Lam S.L
af1cca25bf fix corner case in inline (#4320)
fixes #4319
2020-11-27 01:31:06 +08:00
Alex Lam S.L
9b3a363604 fix infinite recursion in ufuzz (#4318) 2020-11-25 09:33:42 +08:00
Alex Lam S.L
1e8fa1aa1d fix corner case in passes & reduce_vars (#4316)
fixes #4315
2020-11-23 07:05:20 +08:00
Alex Lam S.L
9f67866147 v3.12.0 2020-11-23 01:10:39 +08:00
Alex Lam S.L
645d5a348b workaround Safari quirks (#4314)
fixes #1753
2020-11-21 10:30:46 +08:00
Alex Lam S.L
cf120c7cea fix corner case in merge_vars & reduce_vars (#4313)
fixes #4312
2020-11-21 08:57:59 +08:00
Alex Lam S.L
8d30902ba9 fix corner case in mangle (#4311) 2020-11-21 08:05:40 +08:00
Alex Lam S.L
02459cddf9 gate galio workaround (#4310) 2020-11-21 03:37:33 +08:00
Alex Lam S.L
1b579779be fix corner case in collapse_vars (#4309)
fixes #4308
2020-11-20 06:23:37 +08:00
Alex Lam S.L
b18b70f63b fix corner case in hoist_props (#4307) 2020-11-20 00:02:25 +08:00
Alex Lam S.L
641406d491 fix corner cases in reduce_vars & unused (#4306) 2020-11-19 11:25:36 +08:00
Alex Lam S.L
134ef0b1eb fix corner case in dead_code (#4304) 2020-11-19 08:34:55 +08:00
Alex Lam S.L
db87dcf13e enhance varify (#4303) 2020-11-19 07:58:33 +08:00
Alex Lam S.L
aecbabc587 fix corner case in merge_vars (#4302)
fixes #4301
2020-11-19 05:44:47 +08:00
Alex Lam S.L
fd6544b340 fix corner case reduce_vars (#4300)
fixes #4297
2020-11-19 01:11:28 +08:00
Alex Lam S.L
f6a83f7944 fix corner case in merge_vars (#4299)
fixes #4298
2020-11-18 23:43:55 +08:00
Alex Lam S.L
35283e5dd1 enhance arguments (#4296) 2020-11-18 11:39:32 +08:00
Alex Lam S.L
7a51c17ff0 fix corner case in merge_vars (#4295)
fixes #4294
2020-11-18 09:32:53 +08:00
Alex Lam S.L
aff842f2f9 fix corner case in arguments (#4293)
fixes #4291
2020-11-18 08:54:58 +08:00
Alex Lam S.L
0bedd031da fix corner cases in collapse_vars, unused & varify (#4292)
fixes #4290
2020-11-18 08:22:54 +08:00
Alex Lam S.L
caa92aea5d fix corner case in merge_vars (#4289)
fixes #4288
2020-11-18 04:03:20 +08:00
Alex Lam S.L
383163afa6 fix corner case in collapse_vars (#4287)
fixes #4286
2020-11-17 18:03:31 +08:00
Alex Lam S.L
8a83c8dd46 fix corner cases in collapse_vars & dead_code (#4285)
fixes #4284
2020-11-17 16:23:50 +08:00
Alex Lam S.L
2a612fd472 fix corner case in reduce_vars (#4283)
fixes #4282
2020-11-17 14:43:04 +08:00
Alex Lam S.L
b9798a01a8 fix corner case in reduce_vars (#4281)
fixes #4280
2020-11-17 12:59:44 +08:00
Alex Lam S.L
6dbacb5e3f enhance varify (#4279) 2020-11-17 12:35:00 +08:00
Alex Lam S.L
e5f80afc53 support destructured literals (#4278) 2020-11-17 08:01:24 +08:00
Alex Lam S.L
42e34c870a fix corner case in unused (#4277)
fixes #4276
2020-11-17 02:06:00 +08:00
Alex Lam S.L
e390e7e124 v3.11.6 2020-11-14 22:21:19 +08:00
Alex Lam S.L
6fd5b5b371 fix corner case in loops (#4275)
fixes #4274
2020-11-14 02:08:05 +08:00
Alex Lam S.L
fba27bfb71 fix corner case in evaluate (#4272)
fixes #4271
2020-11-11 00:06:13 +08:00
Alex Lam S.L
41310e6404 fix corner case in objects (#4270)
fixes #4269
2020-11-09 10:47:02 +08:00
Alex Lam S.L
91fc1c82b5 support computed property name in object literal (#4268) 2020-11-08 23:38:32 +08:00
Alex Lam S.L
810cd40356 fix corner case in inline (#4266)
fixes #4265
2020-11-08 18:50:08 +08:00
Alex Lam S.L
1cbd07e789 support shorthand method name in object literal (#4264) 2020-11-08 13:17:53 +08:00
Alex Lam S.L
b82de04775 support shorthand property name in object literal (#4263) 2020-11-08 10:44:44 +08:00
Alex Lam S.L
4bbeb09f7c fix corner case in reduce_vars (#4262)
fixes #4261
2020-11-07 10:00:04 +08:00
Alex Lam S.L
c2f6fd5fde fix corner case in functions (#4260)
fixes #4259
2020-11-06 03:55:25 +08:00
Alex Lam S.L
af4ea3ff69 v3.11.5 2020-11-03 08:59:02 +08:00
Alex Lam S.L
e7643248a3 fix corner case in merge_vars (#4258)
fixes #4257
2020-11-02 01:01:00 +08:00
Alex Lam S.L
68091dbf69 fix corner case in merge_vars (#4256)
fixes #4255
2020-11-01 14:34:07 +08:00
Alex Lam S.L
cbf7269296 fix corner case in merge_vars (#4254)
fixes #4253
2020-11-01 10:37:21 +08:00
Alex Lam S.L
d8563caba7 improve resilience against spurious time-outs (#4252) 2020-10-30 11:06:48 +08:00
Alex Lam S.L
2e0ad40fe6 fix corner case in ie8 (#4251)
fixes #4250
2020-10-30 11:06:31 +08:00
Alex Lam S.L
5d12abc41b fix corner cases in collapse_vars (#4249)
fixes #4248
2020-10-30 10:04:23 +08:00
Alex Lam S.L
79e5c3f564 improve warnings (#4247)
closes #4244
2020-10-27 17:39:33 +08:00
Alex Lam S.L
607f87c5cd fix corner case in booleans (#4246)
fixes #4245
2020-10-26 18:53:58 +08:00
Alex Lam S.L
b2775746a7 v3.11.4 2020-10-25 23:40:42 +00:00
Alex Lam S.L
e478da24c7 fix corner case in collapse_vars (#4243)
fixes #4242
2020-10-24 22:44:20 +08:00
Alex Lam S.L
c5df8355ba fix corner case in loops & unused (#4241)
fixes #4240
2020-10-24 13:33:48 +08:00
Alex Lam S.L
ff38d2471f improve resilience against npm failures (#4239) 2020-10-24 11:22:13 +08:00
Alex Lam S.L
8e86d05c32 fix corner case in merge_vars (#4238)
fixes #4237
2020-10-24 10:19:43 +08:00
Alex Lam S.L
9e40abeded fix corner case in unused (#4236)
fixes #4235
2020-10-22 22:19:47 +08:00
Alex Lam S.L
23ca7d675f fix corner case in functions (#4234)
fixes #4233
2020-10-22 10:13:11 +08:00
Alex Lam S.L
fd8c0212b8 fix corner case in ie8 (#4232)
fixes #4231
2020-10-20 14:02:39 +08:00
Alex Lam S.L
256950c2c0 fix corner case in ie8 (#4230)
fixes #4229
2020-10-20 06:13:23 +08:00
Alex Lam S.L
8ecaa40c6e extend support for Unicode (#4228) 2020-10-19 09:34:17 +08:00
Alex Lam S.L
96bf7fceab support let (#4227) 2020-10-19 08:32:39 +08:00
Alex Lam S.L
6c7226c10e v3.11.3 2020-10-19 07:25:47 +08:00
Alex Lam S.L
dc575919e2 fix corner case in side_effects (#4226)
fixes #4225
2020-10-18 22:13:10 +08:00
Alex Lam S.L
4298201938 flush stdout from ufuzz jobs properly (#4224) 2020-10-16 21:56:54 +08:00
Alex Lam S.L
4f833937fe fix corner case in inline (#4223)
fixes #4222
2020-10-15 21:52:40 +08:00
Alex Lam S.L
3d71e97dd1 fix corner cases in braces & sequences (#4221)
fixes #4220
2020-10-14 23:39:35 +08:00
Alex Lam S.L
7f35d9cee0 fix corner case in reduce_vars (#4219)
fixes #4218
2020-10-14 07:58:04 +08:00
Alex Lam S.L
9f8106e1d8 fix corner case in collapse_vars (#4217)
fixes #4216
2020-10-14 07:18:26 +08:00
Alex Lam S.L
b7b8435721 fix corner case in evaluate (#4215)
fixes #4214
2020-10-14 02:49:45 +08:00
Alex Lam S.L
c0c04c33bb fix corner cases in dead_code & reduce_vars (#4213)
fixes #4212
2020-10-14 00:09:17 +08:00
Alex Lam S.L
0e234a25c5 fix corner case in reduce_vars (#4211)
fixes #4210
2020-10-13 15:52:03 +08:00
Alex Lam S.L
3096f6fdad restore inline functionality disabled by #4204 (#4209) 2020-10-13 09:33:49 +08:00
Alex Lam S.L
176c09c6a5 fix corner case in reduce_vars & unused (#4208)
fixes #4207
2020-10-13 07:32:17 +08:00
Alex Lam S.L
9272f662c0 fix corner case in collapse_vars (#4206)
fixes #4205
2020-10-13 01:30:21 +08:00
Alex Lam S.L
4d33cb2f94 fix corner case in inilne (#4204)
fixes #4202
2020-10-12 23:10:32 +08:00
Alex Lam S.L
00d0eda85b fix corner case in arguments (#4201)
fixes #4200
2020-10-12 19:03:21 +08:00
Alex Lam S.L
1cdf810f0b fix corner case in reduce_vars (#4203)
fixes #4198
2020-10-12 19:02:44 +08:00
Alex Lam S.L
b512726cf3 fix corner case in collapse_vars (#4199)
fixes #4197
2020-10-12 14:13:17 +08:00
Alex Lam S.L
9b7a13c8c7 fix corner case in ie8 & mangle (#4196)
fixes #4195
2020-10-12 12:43:26 +08:00
Alex Lam S.L
74ff6ce261 fix corner case in dead_code (#4194)
fixes #4193
2020-10-12 11:09:26 +08:00
Alex Lam S.L
b1b8898e7c fix corner case in functions (#4192)
fixes #4191
2020-10-12 09:26:56 +08:00
Alex Lam S.L
55451e7b78 support const (#4190) 2020-10-12 01:18:57 +08:00
Alex Lam S.L
ffcce28ce1 v3.11.2 2020-10-11 21:19:25 +08:00
Alex Lam S.L
9c0feb69e5 fix corner case in reduce_vars (#4189)
fixes #4188
2020-10-07 22:01:39 +08:00
Alex Lam S.L
bc6e105174 fix corner case in ie8 (#4187)
fixes #4186
2020-10-06 09:20:41 +08:00
Alex Lam S.L
b91a2459c0 fix corner case in unused (#4185)
fixes #4184
2020-10-05 18:59:03 +08:00
Alex Lam S.L
b7a57fc69d fix corner case in loops (#4183)
fixes #4182
2020-10-05 17:28:46 +08:00
Alex Lam S.L
2dbe40b01b enhance conditionals (#4181) 2020-10-05 15:55:37 +08:00
Alex Lam S.L
813ac3ba96 enhance loops (#4180) 2020-10-05 08:26:59 +08:00
Alex Lam S.L
220dc95c0d clean up scope-related variables (#4179) 2020-10-05 06:56:52 +08:00
Alex Lam S.L
8f0521d51d retrofit try-catch-finally as block-scoped (#4178)
- support optional catch binding
2020-10-05 05:30:14 +08:00
Alex Lam S.L
f9946767c9 retrofit AST_BlockStatement as block-scoped (#4177) 2020-10-05 01:58:50 +08:00
Alex Lam S.L
58ac5b9bd5 extend support for numeral literals (#4176) 2020-10-05 00:05:03 +08:00
Alex Lam S.L
66140b459e enhance side_effects (#4175) 2020-10-04 23:43:49 +08:00
Alex Lam S.L
1786c69070 v3.11.1 2020-10-04 22:12:07 +08:00
Alex Lam S.L
95ef4d5377 fix corner case in mangle (#4174) 2020-10-04 08:24:41 +08:00
Alex Lam S.L
04017215cc support JSON dump beyond AST_Toplevel (#4173) 2020-10-03 22:53:06 +08:00
Alex Lam S.L
142bd1bd1a workaround quirks on latter specs (#4172)
closes #4171
2020-10-03 18:27:17 +08:00
Alex Lam S.L
8cb509d50e fix corner case in merge_vars (#4170)
fixes #4168
2020-10-03 07:03:39 +08:00
Alex Lam S.L
baf4903aa7 fix corner cases of catch variable inlining (#4169) 2020-10-03 07:02:28 +08:00
Alex Lam S.L
35465d590e report immediate ufuzz failure from Pull Request (#4166) 2020-10-02 23:43:38 +08:00
Alex Lam S.L
ccd91b9952 retrofit catch as block-scoped (#4165) 2020-10-02 23:29:58 +08:00
Alex Lam S.L
47a5e6e17a enhance if_return (#4164) 2020-10-02 16:10:25 +08:00
Alex Lam S.L
090ee895e1 enhance inline (#4163) 2020-09-30 21:03:28 +08:00
Alex Lam S.L
1cd1a1e5ee improve resilience against GitHub API (#4161) 2020-09-30 01:13:29 +08:00
Alex Lam S.L
1d835ac17d fix corner case in inline (#4160)
fixes #4159
2020-09-29 07:01:38 +08:00
Alex Lam S.L
9e07ac4102 fix corner case in merge_vars (#4158)
fixes #4157
2020-09-28 14:09:55 +08:00
Alex Lam S.L
92d1391e5e v3.11.0 2020-09-27 20:36:27 +08:00
Alex Lam S.L
b4ff6d0f2d fix corner cases in functions & merge_vars (#4156)
fixes #4155
2020-09-26 15:31:33 +08:00
Alex Lam S.L
9882a9f4af fix corner case in ufuzz scheduling (#4154) 2020-09-26 11:23:56 +08:00
Alex Lam S.L
40f36b9e01 improve ufuzz duty cycle heuristic (#4153) 2020-09-26 07:56:00 +08:00
Alex Lam S.L
6e105c5ca6 enhance merge_vars (#4152) 2020-09-25 22:00:20 +08:00
Alex Lam S.L
af35cd32f2 fix corner case in merge_vars (#4151) 2020-09-25 08:04:51 +08:00
Alex Lam S.L
7de8daa4b1 minor clean up (#4149) 2020-09-23 23:06:12 +08:00
Alex Lam S.L
305a4bdcee minor clean up (#4148) 2020-09-23 16:34:22 +08:00
Alex Lam S.L
3472cf1a90 fix corner case in unused (#4147)
fixes #4146
2020-09-22 20:08:45 +08:00
Alex Lam S.L
6d4c0fa6fa fix corner case in unused (#4145)
fixes #4144
2020-09-22 14:03:27 +08:00
Alex Lam S.L
3cca0d6249 fix corner case in evaluate (#4143)
fixes #4142
2020-09-22 12:11:25 +08:00
Alex Lam S.L
12ac49b970 Merge pull request #4141 from alexlamsl/unused
enhance `unused`
2020-09-22 02:21:43 +01:00
alexlamsl
8c670cae93 enhance unused 2020-09-22 07:48:55 +08:00
Alex Lam S.L
0e3da27727 fix corner case in merge_vars (#4140)
fixes #4139
2020-09-21 23:49:41 +01:00
Alex Lam S.L
13cdc167a2 fix corner case in evaluate (#4138)
fixes #4137
2020-09-22 06:49:32 +08:00
alexlamsl
51803cdcb2 fix corner case in merge_vars
fixes #4139
2020-09-22 05:03:06 +08:00
Alex Lam S.L
8fa470c17c fix corner case in merge_vars (#4136)
fixes #4135
2020-09-20 23:54:14 +08:00
Alex Lam S.L
90410f9fc3 fix corner case in unused (#4134)
fixes #4133
2020-09-20 23:21:59 +08:00
Alex Lam S.L
ef3831437d improve ufuzz duty cycle heuristic (#4132) 2020-09-20 08:29:35 +08:00
Alex Lam S.L
171c544705 fix corner case in merge_vars (#4131)
fixes #4130
2020-09-20 05:36:16 +08:00
Alex Lam S.L
3c609e2f4a enhance unused (#4129) 2020-09-20 01:45:52 +08:00
Alex Lam S.L
f0ae03ed39 report immediate ufuzz failure from Pull Request (#4128) 2020-09-19 20:31:37 +08:00
Alex Lam S.L
31c6b45036 fix corner case in merge_vars (#4127)
fixes #4126
2020-09-19 19:56:21 +08:00
Alex Lam S.L
3ac533e644 enhance merge_vars (#4125) 2020-09-19 11:16:23 +08:00
Alex Lam S.L
38a46c86d7 enhance side_effects (#4124)
- add documentation for `merge_vars`
2020-09-18 21:35:29 +08:00
Alex Lam S.L
0f0759ec15 remove redundant transform (#4123) 2020-09-18 07:04:46 +08:00
Alex Lam S.L
7f501f9fed add tests (#4122) 2020-09-18 00:26:31 +08:00
Alex Lam S.L
72844eb5a4 improve fix for #4119 (#4121) 2020-09-17 23:08:36 +08:00
Alex Lam S.L
09d93cc6c8 fix corner case in evaluate (#4120)
fixes #4119
2020-09-17 21:20:31 +08:00
Alex Lam S.L
dd1374aa8a minor clean up (#4118) 2020-09-17 07:10:45 +08:00
Alex Lam S.L
fdf2e8c5b0 enhance collapse_vars (#4117) 2020-09-17 06:35:22 +08:00
Alex Lam S.L
a9d934ab4e improve handling of switch statements (#4114) 2020-09-17 03:12:08 +08:00
Alex Lam S.L
2a053710bd fix corner case in merge_vars (#4116)
fixes #4115
2020-09-17 03:11:57 +08:00
Alex Lam S.L
219aac6a84 fix corner case in merge_vars (#4113)
fixes #4112
2020-09-16 22:18:28 +08:00
Alex Lam S.L
2039185051 enhance conditionals (#4106) 2020-09-16 05:51:42 +08:00
Alex Lam S.L
ad27c14202 fix corner cases in merge_vars (#4108)
fixes #4107
fixes #4109
fixes #4110
fixes #4111
2020-09-16 04:43:01 +08:00
Alex Lam S.L
a62b086184 enhance merge_vars (#4105) 2020-09-15 22:59:10 +08:00
Alex Lam S.L
335456cf77 fix corner case in merge_vars (#4104)
fixes #4103
2020-09-15 19:47:12 +08:00
Alex Lam S.L
d64d0b0bec fix corner case in merge_vars (#4102)
fixes #4101
2020-09-15 19:18:12 +08:00
Alex Lam S.L
3ac575f2e8 introduce merge_vars (#4100) 2020-09-15 10:01:48 +08:00
Alex Lam S.L
d33a3a3253 enhance unused (#4098) 2020-09-13 01:05:43 +08:00
Alex Lam S.L
d7456a2dc2 enhance if_return (#4097) 2020-09-10 22:31:34 +08:00
Alex Lam S.L
d97672613d fix corner case in reduce_vars (#4095) 2020-09-08 22:12:27 +08:00
Alex Lam S.L
30761eede5 v3.10.4 2020-09-07 00:25:54 +08:00
Alex Lam S.L
fb30aeccaf relax ufuzz job timing constraint (#4094) 2020-09-05 19:29:50 +08:00
Alex Lam S.L
226aa1f76b enhance unsafe_math (#4093) 2020-09-04 10:14:39 +08:00
Alex Lam S.L
6e235602fb fix corner case in loops & unused (#4092)
fixes #4091
2020-09-04 01:51:26 +08:00
Alex Lam S.L
980fcbb56b enhance unused (#4090) 2020-09-03 17:41:33 +08:00
Alex Lam S.L
375ebe316d enhance join_vars (#4089) 2020-09-03 01:41:10 +08:00
Alex Lam S.L
2500930234 enhance reduce_vars (#4088) 2020-09-02 11:30:46 +08:00
Alex Lam S.L
2f0da2ff05 reduce AST_ForIn gracefully (#4087) 2020-09-02 08:51:43 +08:00
Alex Lam S.L
83a3cbf151 fix test case runtime accounting (#4086) 2020-09-02 03:23:08 +08:00
Alex Lam S.L
da8d154571 fix corner case in loops & unused (#4085)
fixes #4084
2020-09-02 03:20:58 +08:00
Alex Lam S.L
e33c727e8b v3.10.3 2020-08-30 13:09:12 +01:00
Alex Lam S.L
f886b3fb2b fix corner case in loops & unused (#4083)
fixes #4082
2020-08-29 02:42:17 +08:00
Alex Lam S.L
b1cc15e85b fix corner case in sequences (#4080)
fixes #4079
2020-08-26 20:41:11 +08:00
Alex Lam S.L
3aa765e429 fix corner case in evaluate (#4078)
fixes #4077
2020-08-26 19:45:38 +08:00
Alex Lam S.L
93d084a1d1 fix corner case in loops & unused (#4076)
fixes #4075
2020-08-26 17:32:20 +08:00
Alex Lam S.L
c7a3e09407 enhance loops & unused (#4074)
- extend `ufuzz` generation of for-in loops
2020-08-26 09:32:55 +08:00
Alex Lam S.L
09525c7530 fix corner case in sequences (#4073) 2020-08-26 01:26:49 +08:00
Alex Lam S.L
a7e15fe73c streamline parenthesis logic (#4072) 2020-08-25 19:45:37 +08:00
Alex Lam S.L
a31c27c7cf fix corner case in collapse_vars (#4071)
fixes #4070
2020-08-25 17:23:36 +08:00
Alex Lam S.L
1caf7c7bd2 minor clean up (#4069) 2020-08-25 10:10:56 +08:00
Alex Lam S.L
0eb0c9b388 fix corner case in evaluate (#4068)
fixes #4067
2020-08-24 14:57:26 +08:00
Alex Lam S.L
7dc61cdc89 tidy up various interfaces (#4066) 2020-08-24 04:39:38 +08:00
Alex Lam S.L
af1b2f30c9 v3.10.2 2020-08-23 23:09:12 +08:00
Alex Lam S.L
37b4fc7e31 update domprops (#4065) 2020-08-23 23:06:15 +08:00
Alex Lam S.L
da85d102e3 enhance mangle.properties (#4064) 2020-08-23 08:45:39 +08:00
Alex Lam S.L
35fe1092d3 simplify traversal logic (#4063) 2020-08-23 05:45:35 +08:00
Alex Lam S.L
f2d486e771 enhance comparisons (#4062) 2020-08-23 01:03:48 +08:00
Alex Lam S.L
fee677786e fix corner case in collapse_vars (#4061) 2020-08-21 10:35:34 +08:00
Alex Lam S.L
aa83ecdb3b fix corner case in switches (#4060)
fixes #4059
2020-08-21 08:05:10 +08:00
Alex Lam S.L
a153176469 enhance conditionals & switches (#4058) 2020-08-21 00:35:39 +08:00
Alex Lam S.L
1c6384b6a5 improve ufuzz duty cycle heuristic (#4057) 2020-08-19 23:29:01 +08:00
Alex Lam S.L
e8db526f51 avoid setters during console.log() in sandbox (#4055)
fixes #4054
2020-08-19 06:14:41 +08:00
Alex Lam S.L
fa13ed4391 reject multiple defaults in switch (#4053)
fixes #4050
2020-08-17 10:09:12 +08:00
Alex Lam S.L
23f0dca992 fix corner cases in collapse_vars & dead_code (#4052)
fixes #4051
2020-08-17 05:54:27 +08:00
Alex Lam S.L
45ab3b51d8 clarify toplevel & global variable aliasing (#4046) 2020-08-10 06:39:28 +08:00
Alex Lam S.L
49670d216b fix corner case in collapse_vars (#4048)
fixes #4047
2020-08-10 05:48:56 +08:00
Alex Lam S.L
e2237d8cd2 improve ufuzz duty cycle heuristic (#4045) 2020-08-09 03:10:19 +08:00
Alex Lam S.L
91f078fe35 workaround incorrect workflow status (#4044) 2020-08-08 05:16:54 +08:00
Alex Lam S.L
a546cb881d improve ufuzz duty cycle on GitHub Actions (#4043) 2020-08-07 18:42:36 +08:00
Alex Lam S.L
84d5dffd9f tweak GitHub Actions (#4042) 2020-08-07 02:15:51 +08:00
Alex Lam S.L
a8e286f7e1 fix corner case in collapse_vars (#4041)
fixes #4040
2020-08-06 20:30:28 +08:00
Alex Lam S.L
9b05494ebc fix corner cases in aliasing of global variables (#4039)
fixes #4038
2020-08-06 09:39:50 +01:00
Alex Lam S.L
30ef20a208 tweak GitHub Actions (#4037) 2020-08-05 22:09:02 +08:00
Alex Lam S.L
a4002ef467 fix corner case in evaluate (#4036)
fixes #4035
2020-08-04 20:05:10 +08:00
Alex Lam S.L
9d758a216b v3.10.1 2020-08-02 21:08:48 +08:00
Alex Lam S.L
af13f8dd2c improve diagnostics upon AST validation failure (#4033) 2020-07-31 22:50:16 +08:00
Alex Lam S.L
88423f2574 validate against multiple parents on AST_Node (#4032)
- fix related issues in `global_defs`, `ie8` & `reduce_vars`
2020-07-31 08:09:19 +08:00
Alex Lam S.L
ee632a5519 fix corner case in reduce_vars (#4031)
fixes #4030
2020-07-31 08:05:09 +08:00
Alex Lam S.L
dfe47bcc42 fix corner case in ie8 & reduce_vars (#4029)
fixes #4028
2020-07-29 03:11:02 +08:00
Alex Lam S.L
6d3dcaa59e fix corner case in unused (#4026)
fixes #4025
2020-07-26 09:27:54 +08:00
Alex Lam S.L
1bc0df1569 fix corner case in hoist_props (#4024)
fixes #4023
2020-07-26 09:27:34 +08:00
Alex Lam S.L
a98ba994bd reduce ufuzz test cases that fail to minify() (#4021) 2020-07-21 17:22:18 +08:00
Alex Lam S.L
cd671221c5 fix corner case in ie8 & reduce_vars (#4020)
fixes #4019
2020-07-21 17:22:18 +08:00
Alex Lam S.L
bce3919748 fix corner case in unused (#4018)
fixes #4017
2020-07-21 17:21:58 +08:00
Alex Lam S.L
61b66e83f1 fix corner case in ie8 (#4016)
fixes #4015
2020-07-21 02:32:20 +08:00
Alex Lam S.L
a5db8cd14c fix corner case in collapse_vars (#4013)
fixes #4012
2020-07-20 23:28:13 +08:00
Alex Lam S.L
2021c2fa3e fix corner case in false positive detection (#4011) 2020-07-20 21:57:22 +08:00
Alex Lam S.L
484d3fd8c7 fix corner case in side_effects (#4009)
fixes #4008
2020-07-01 11:33:48 +08:00
Alex Lam S.L
3bf8699f95 fix corner case in inline (#4007)
fixes #4006
2020-06-29 09:06:23 +08:00
Alex Lam S.L
58c24f8007 v3.10.0 2020-06-21 11:30:24 +01:00
Alex Lam S.L
e61bc34eb1 fix corner case in collapse_vars (#4002)
fixes #4001
2020-06-20 02:19:37 +08:00
Alex Lam S.L
8b2cfd45fa fix corner case in rename (#4000)
fixes #3999
2020-06-15 01:29:01 +08:00
Alex Lam S.L
ae9f56be10 fix corner case in evaluate (#3998)
fixes #3997
2020-06-15 01:28:44 +08:00
Alex Lam S.L
9aed0e3a73 speed up false positive detection in ufuzz (#3996) 2020-06-14 03:42:42 +08:00
Alex Lam S.L
88850a6e05 enhance evaluate (#3995) 2020-06-14 02:50:26 +08:00
Alex Lam S.L
9e881407bd fix corner cases related to AST_Hole (#3994) 2020-06-13 15:24:57 +01:00
Alex Lam S.L
3188db7b90 remove AppVeyor (#3992) 2020-06-12 08:43:42 +08:00
Alex Lam S.L
a82ca62b66 fix corner case in dead_code (#3991) 2020-06-12 08:00:19 +08:00
Alex Lam S.L
e9465717ab enhance dead_code (#3990) 2020-06-12 02:16:13 +08:00
Alex Lam S.L
e89031f1af fix corner case in unsafe evaluate (#3989)
fixes #3988
2020-06-11 07:37:39 +08:00
Alex Lam S.L
596fad182e fix corner case in unused (#3987)
fixes #3986
2020-06-11 02:01:23 +08:00
Alex Lam S.L
ed69adedcd fix corner case in --reduce-test (#3985) 2020-06-10 15:51:00 +01:00
Alex Lam S.L
1dbf7d4a3a fix corner case in side_effects (#3984)
fixes #3983
2020-06-10 19:30:37 +08:00
Alex Lam S.L
2a9d0fc6fb improve false positive detection in ufuzz (#3982) 2020-06-10 07:28:56 +08:00
Alex Lam S.L
45db96679e perform ufuzz on more stable Node.js version (#3981) 2020-06-10 00:02:05 +08:00
Alex Lam S.L
1d15f51238 improve fix for #3976 (#3980) 2020-06-10 00:00:57 +08:00
Alex Lam S.L
ed7c82fa5e fix corner case in collapse_vars (#3978)
fixes #3976
2020-06-09 19:07:20 +08:00
Alex Lam S.L
3b273cecac improve false positive detection in ufuzz (#3977) 2020-06-09 19:07:02 +08:00
Alex Lam S.L
d764b6cc3b fix corner case in reduce_vars (#3975)
fixes #3974
2020-06-09 10:33:47 +08:00
Alex Lam S.L
08c4729eb4 improve false positive detection in ufuzz (#3973) 2020-06-09 01:47:50 +08:00
Alex Lam S.L
5561d3e7f3 fix corner case in collapse_vars (#3972)
fixes #3971
2020-06-09 00:09:21 +08:00
Alex Lam S.L
491d6ce1d5 improve false positive detection in ufuzz (#3968) 2020-06-08 14:21:45 +08:00
Alex Lam S.L
cd55eeb77c fix corner case in dead_code (#3969)
fixes #3967
2020-06-08 13:42:09 +08:00
Alex Lam S.L
3230952d57 improve handling of invalid CLI options (#3966) 2020-06-08 11:16:03 +08:00
Alex Lam S.L
df3bb8028a fix corner cases related to in (#3964) 2020-06-08 05:23:23 +08:00
Alex Lam S.L
28b7b15da1 parse command line internally (#3961) 2020-06-07 13:48:51 +08:00
Alex Lam S.L
aa37b19698 fix corner case in unused (#3963)
fixes #3962
2020-06-07 13:48:29 +08:00
Alex Lam S.L
02e889e449 improve fix for #3958 (#3960) 2020-06-06 15:07:32 +01:00
Alex Lam S.L
486ce00b8e fix corner case in reduce_vars (#3959)
fixes #3958
2020-06-06 10:04:37 +08:00
Alex Lam S.L
eb481cee8c fix corner cases in reduce_vars & unused (#3955)
fixes #3953
fixes #3956
fixes #3957
2020-06-05 18:51:21 +08:00
Alex Lam S.L
fbc9d8009b fix corner case in collapse_vars (#3954) 2020-06-05 14:28:08 +08:00
Alex Lam S.L
04fd3d90f8 fix corner cases in assignments, reduce_vars & unused (#3950)
fixes #3949
fixes #3951
2020-06-05 04:06:43 +08:00
Alex Lam S.L
a489f8cb5e add test case for #3945 (#3948) 2020-06-03 03:34:38 +08:00
Alex Lam S.L
e2e4b7fb37 fix corner case in hoist_props (#3947)
fixes #3945
2020-06-02 23:51:06 +08:00
Alex Lam S.L
c97ad98f92 fix corner case in evaluate (#3946)
fixes #3944
2020-06-02 23:50:40 +08:00
Alex Lam S.L
b24eb22c6b enhance reduce_vars (#3942) 2020-06-01 20:55:23 +08:00
Alex Lam S.L
06ba4e2ce8 fix corner case in arguments (#3939) 2020-05-31 12:18:27 +08:00
Alex Lam S.L
0eb4577a82 fix corner case in evaluate (#3938)
fixes #3937
2020-05-30 18:22:40 +08:00
Alex Lam S.L
43498769f0 fix corner case in evaluate (#3936)
fixes #3935
2020-05-29 22:10:36 +08:00
Alex Lam S.L
60c0bc1e6b fix corner case in evaluate (#3934)
fixes #3933
2020-05-29 17:48:26 +08:00
Alex Lam S.L
6a5c63e1e3 enhance evaluate, functions & inline (#3931) 2020-05-29 07:05:47 +08:00
Alex Lam S.L
d47ea77811 fix corner case in functions (#3930)
fixes #3929
2020-05-28 20:07:36 +08:00
Alex Lam S.L
7840746bd9 fix corner case in collapse_vars (#3928)
fixes #3927
2020-05-27 21:02:48 +08:00
Alex Lam S.L
49ea629f3f v3.9.4 2020-05-27 07:50:18 +01:00
Alex Lam S.L
13c72a986c fix corner case in infinite recursion detection (#3926) 2020-05-27 02:03:38 +08:00
Alex Lam S.L
08af3eae44 perform ufuzz on Pull Requests (#3925) 2020-05-25 22:55:14 +08:00
Alex Lam S.L
27bdcbbd83 fix corner cases in infinite recursion detection (#3924) 2020-05-25 22:54:57 +08:00
Alex Lam S.L
2c4d7d66ef fix corner case in reduce_vars (#3923)
fixes #3922
2020-05-24 07:38:40 +08:00
Alex Lam S.L
d1cc5270a3 fix corner case in evaluate (#3921)
fixes #3920
2020-05-22 11:38:09 +08:00
Alex Lam S.L
75c5b6029b fix corner case in ie8 & reduce_vars (#3919)
fixes #3918
2020-05-22 09:56:35 +08:00
Alex Lam S.L
fa14a9cfcd fix corner case in join_vars (#3917)
fixes #3916
2020-05-22 05:26:46 +08:00
Alex Lam S.L
aeb9ea5ac2 fix corner case in inline (#3915)
fixes #3911
2020-05-21 22:05:31 +08:00
Alex Lam S.L
798841be82 improve job resilience (#3913) 2020-05-21 04:50:42 +08:00
Alex Lam S.L
cc6eb4b15f improve ufuzz (#3912)
- preserve test case if `beautify` suppresses bug
- determine suspicious options even if `minify()` fails
2020-05-21 04:00:38 +08:00
Alex Lam S.L
14eee81dc6 update header comment for --reduce-test (#3910) 2020-05-19 11:35:33 +08:00
Alex Lam S.L
55ebb27878 fix corner case in collapse_vars (#3909)
fixes #3908
2020-05-19 11:34:50 +08:00
Alex Lam S.L
87046410ef enhance dead_code (#3907) 2020-05-19 03:53:08 +08:00
Alex Lam S.L
f9b3198714 fix corner case in evaluate (#3906)
fixes #3905
2020-05-18 08:41:10 +08:00
Alex Lam S.L
48b62393a4 fix corner case in evaluate (#3904)
fixes #3903
2020-05-17 22:25:13 +08:00
Alex Lam S.L
a00f8dade7 fix suspicious toplevel detection (#3902) 2020-05-17 21:35:17 +08:00
Alex Lam S.L
9daa2fb6f5 benchmark without validation by default (#3901) 2020-05-15 23:57:50 +08:00
Alex Lam S.L
8d81d264f4 fix corner case in functions (#3900)
fixes #3899
2020-05-15 18:03:56 +08:00
Alex Lam S.L
5ef7060098 fix corner case in collapse_vars (#3898)
fixes #3897
2020-05-15 01:09:54 +08:00
Alex Lam S.L
938368ba21 enhance collapse_vars (#3896) 2020-05-14 07:52:42 +08:00
Alex Lam S.L
fe2f1965d6 fix corner case in reduce_vars (#3895)
fixes #3894
2020-05-13 23:44:54 +08:00
Alex Lam S.L
30ed8f5580 v3.9.3 2020-05-13 17:23:01 +08:00
Alex Lam S.L
dc9e7cd1fe suppress ufuzz false positives (#3893) 2020-05-13 07:07:49 +08:00
Alex Lam S.L
76f40e2528 fix corner case in collapse_vars (#3892)
fixes #3891
2020-05-12 22:28:55 +08:00
Alex Lam S.L
8024f7f7a8 fix corner case in ie8 (#3890)
fixes #3889
2020-05-12 19:28:29 +08:00
Alex Lam S.L
eb7fa25270 fix corner case in evaluate (#3888)
fixes #3887
2020-05-12 17:58:37 +08:00
Alex Lam S.L
ee7647dc67 fix corner case in collapse_vars (#3885)
fixes #3884
2020-05-12 04:01:14 +08:00
Alex Lam S.L
bd2f53bc8b fix corner case in evaluate (#3883)
fixes #3882
2020-05-12 03:24:44 +08:00
Alex Lam S.L
e8a7956b6f fix corner case in reduce_vars (#3881)
fixes #3880
2020-05-12 02:29:33 +08:00
Alex Lam S.L
2b24dc25fb fix corner cases in evaluate & reduce_vars (#3879)
fixes #3878
2020-05-11 22:46:00 +08:00
Alex Lam S.L
35cc5aa06f extend --reduce-test to cover minify() bugs (#3876) 2020-05-11 07:32:21 +08:00
Alex Lam S.L
c1dd49e075 fix corner case in comparisons (#3877) 2020-05-11 06:33:52 +08:00
Alex Lam S.L
c76ee4b868 enhance if_return (#3875) 2020-05-11 04:29:55 +08:00
Alex Lam S.L
e23bf48052 enhance evaluate & reduce_vars (#3873) 2020-05-11 03:08:05 +08:00
Alex Lam S.L
7e0ad232b0 retain @__PURE__ call when return value is used (#3874) 2020-05-11 01:07:05 +08:00
Alex Lam S.L
63adfb1590 fix corner case in hoist_props (#3872)
fixes #3871
2020-05-10 22:23:09 +08:00
Alex Lam S.L
f9806b43c3 enhance evaluate & reduce_vars (#3870) 2020-05-10 18:38:32 +08:00
Alex Lam S.L
c4c9c6d37d fix corner case in hoist_props (#3869)
fixes #3868
2020-05-10 10:35:24 +01:00
Alex Lam S.L
33f3b0c1d9 fix corner case in reduce_vars (#3867)
fixes #3866
2020-05-10 16:35:03 +08:00
Alex Lam S.L
abb8ae02a5 improve inline of /*@__PURE__*/ calls (#3865) 2020-05-10 07:16:09 +08:00
Alex Lam S.L
97728c4f0b improve AST validation (#3864) 2020-05-10 05:25:44 +08:00
Alex Lam S.L
f74b7f7401 implement AST validation (#3863) 2020-05-09 09:58:03 +08:00
Alex Lam S.L
b06fd8a933 improve fix for #3856 (#3862) 2020-05-09 08:50:25 +08:00
Alex Lam S.L
1bb0804d60 improve ufuzz detection of suspicious options (#3860) 2020-05-08 15:03:48 +08:00
Alex Lam S.L
998245ffd6 fix corner case in inline (#3859)
fixes #3858
2020-05-08 15:03:29 +08:00
Alex Lam S.L
7a033bb825 fix corner case in join_vars (#3857)
fixes #3856
2020-05-08 11:49:17 +08:00
Alex Lam S.L
a441b00951 suppress ufuzz false positives (#3855) 2020-05-08 03:21:44 +08:00
Alex Lam S.L
88985a46ed fix corner case in inline (#3853)
fixes #3852
2020-05-07 20:53:05 +08:00
Alex Lam S.L
34ead0430b enhance dead_code (#3849) 2020-05-06 05:02:35 +08:00
Alex Lam S.L
66ab2df97f fix intermittent CI failures on GitHub Actions (#3851) 2020-05-06 03:29:23 +08:00
kzc
b656f7c083 remove unused returns from tree walk (#3850) 2020-05-06 02:21:36 +08:00
Alex Lam S.L
873db281e8 improve TreeWalker performance (#3848) 2020-05-05 22:45:58 +08:00
Alex Lam S.L
6bf1486935 update links to repository after rename (#3847) 2020-05-05 21:07:33 +08:00
Alex Lam S.L
ffa1943177 fix corner case in reduce_vars (#3845)
fixes #3844
2020-05-04 03:30:10 +08:00
Alex Lam S.L
ac429dc8e1 enhance reduce_vars (#3843) 2020-05-03 22:52:43 +08:00
Alex Lam S.L
3766d5c962 enhance unused (#3839) 2020-05-03 17:38:28 +08:00
Alex Lam S.L
20f9a1d908 v3.9.2 2020-05-03 11:01:18 +08:00
Alex Lam S.L
dcb74f558e fix diagnostic text (#3838) 2020-05-01 18:55:06 +08:00
Alex Lam S.L
0794aaa2c2 fix corner case in inline (#3837)
fixes #3836
2020-05-01 17:20:23 +08:00
Alex Lam S.L
74801de315 fix corner cases in inline (#3834)
fixes #3833
fixes #3835
2020-05-01 09:06:40 +08:00
Alex Lam S.L
f80d5b8c9e enhance inline (#3832) 2020-05-01 04:33:46 +08:00
Alex Lam S.L
d900006973 fix corner case in dead_code (#3831)
fixes #3830
2020-04-30 21:52:57 +08:00
Alex Lam S.L
39f849590b update dependencies (#3828)
- actions/checkout@v2
2020-04-30 05:55:04 +08:00
Alex Lam S.L
818738beec fix corner case in ie8 (#3826)
fixes #3825
2020-04-27 16:51:21 +08:00
Alex Lam S.L
bc2a4a3bb8 fix corner case in ie8 (#3824)
fixes #3823
2020-04-27 06:44:53 +08:00
Alex Lam S.L
a4a8ccea8c fix corner case in inline (#3822)
fixes #3821
2020-04-27 03:31:19 +08:00
Alex Lam S.L
36dcfa3e82 improve suspicious option detection (#3820) 2020-04-27 00:59:26 +08:00
Alex Lam S.L
94f33570e3 fix corner case in --reduce-test (#3819) 2020-04-25 06:49:50 +08:00
Alex Lam S.L
44d6912a55 improve --reduce-test on Error.message (#3816)
closes #3815
2020-04-25 01:30:37 +08:00
Alex Lam S.L
3a4497a1c3 fix corner case in typeofs (#3818)
fixes #3817
2020-04-25 01:29:42 +08:00
Alex Lam S.L
3ee13cae02 improve compress (#3814)
- avoid identifier overflow through consecutive API calls
- simplify `reduce_vars`
- enhance `unsafe` `evaluate`
2020-04-24 06:50:53 +08:00
Alex Lam S.L
99cf3a38c5 improve unused efficiency (#3813) 2020-04-23 08:31:35 +08:00
Alex Lam S.L
3ae24329eb gate various label-related transformations (#3812) 2020-04-23 05:27:26 +08:00
Alex Lam S.L
01b13d797c enhance dead_code (#3811) 2020-04-22 18:22:45 +08:00
Alex Lam S.L
306e8e9873 adjust ufuzz schedule (#3810) 2020-04-22 16:03:15 +08:00
Alex Lam S.L
9577c8c1b7 fix corner case in conditionals (#3809)
fixes #3808
2020-04-22 06:30:08 +08:00
Alex Lam S.L
925a0ca1a0 adjust ufuzz schedule (#3807) 2020-04-22 02:58:02 +08:00
Alex Lam S.L
b694bfa351 speed up ufuzz on GitHub Actions (#3806) 2020-04-21 22:51:42 +08:00
Alex Lam S.L
a2fc32c64b enhance conditionals (#3805) 2020-04-20 09:42:13 +08:00
Alex Lam S.L
88504ab869 enhance join_vars (#3804) 2020-04-20 06:37:46 +08:00
Alex Lam S.L
e38754e802 fix corner case in functions & unused (#3803)
fixes #3802
2020-04-19 06:28:01 +08:00
Alex Lam S.L
eb6f32bfc3 enhance collapse_vars (#3801) 2020-04-19 05:04:21 +08:00
Alex Lam S.L
f110601fb4 enhance unused (#3800) 2020-04-19 00:10:24 +08:00
Alex Lam S.L
2a508c6e5f enhance collapse_vars (#3799) 2020-04-18 23:12:20 +08:00
Alex Lam S.L
fd6144d95b enhance conditionals (#3798) 2020-04-18 22:32:22 +08:00
Alex Lam S.L
60d4e7b09f enhance unused (#3794) 2020-04-18 18:52:44 +08:00
Alex Lam S.L
b38838c6bf fix corner case in join_vars (#3796)
fixes #3795
2020-04-18 18:08:05 +08:00
Alex Lam S.L
708973e51d report top-level default options (#3797) 2020-04-18 18:03:06 +08:00
Alex Lam S.L
dac9e69f9e enhance collapse_vars (#3793) 2020-04-18 10:06:20 +08:00
Alex Lam S.L
39aa33749b expand ufuzz patterns (#3792) 2020-04-18 07:12:13 +08:00
Alex Lam S.L
da68ec6e19 fix corner cases in join_vars (#3790)
fixes #3789
fixes #3791
2020-04-18 02:53:26 +08:00
Alex Lam S.L
15a3ebd467 fix corner cases in join_vars (#3787)
fixes #3786
fixes #3788
2020-04-17 21:19:18 +08:00
Alex Lam S.L
9110fac9a2 suppress mutation of input options (#3785) 2020-04-17 15:13:49 +08:00
Alex Lam S.L
83f42ede36 support optional output of names in source maps (#3784) 2020-04-17 07:20:48 +08:00
Alex Lam S.L
0ce71bbec0 enhance join_vars (#3783) 2020-04-17 05:31:33 +08:00
Alex Lam S.L
46d142cbf6 improve source-map generation (#3782)
- emit singleton segments to mark generated code from input
2020-04-16 23:30:25 +08:00
Alex Lam S.L
38c3bcf9a0 v3.9.1 2020-04-15 17:26:30 +08:00
Alex Lam S.L
6e9afdc94f prevent input source map mutation (#3781)
fixes #3780
2020-04-15 17:25:58 +08:00
Alex Lam S.L
c4d28e3b2a expand testing on Node.js versions (#3779) 2020-04-14 10:13:42 +08:00
Alex Lam S.L
77261e1ee0 v3.9.0 2020-04-13 13:45:02 +01:00
Alex Lam S.L
903a5df9a5 fix corner case in inline (#3778)
fixes #3777
2020-04-11 19:54:26 +08:00
Alex Lam S.L
c810ecd081 improve handling of eval (#3776)
closes #3768
2020-04-11 06:36:17 +08:00
Alex Lam S.L
dce9dfce0e fix corner case in reduce_vars (#3775)
fixes #3774
2020-04-11 02:19:38 +08:00
Alex Lam S.L
3d72663689 add tests for eval() (#3769)
closes #3768
2020-04-11 00:36:53 +08:00
Alex Lam S.L
a2b16e89a4 fix corner cases in inline (#3773)
fixes #3770
fixes #3771
fixes #3772
2020-04-11 00:34:45 +08:00
Alex Lam S.L
b35f4c5a83 enhance inline (#3767) 2020-04-10 10:48:24 +08:00
Alex Lam S.L
41eb4f1725 workaround intermittent nodejs.org corruptions (#3766) 2020-04-07 08:40:38 +08:00
Alex Lam S.L
94bc221669 fix export of PATH to Node.js (#3765) 2020-04-07 01:14:16 +08:00
Alex Lam S.L
822d298a55 fix Github Actions retry logic (#3763) 2020-04-06 22:16:48 +08:00
Alex Lam S.L
273c6020ba expand ufuzz patterns (#3761) 2020-04-05 22:12:46 +08:00
Alex Lam S.L
1b07f64057 enhance inline (#3760) 2020-04-05 10:42:23 +08:00
Alex Lam S.L
80d9c44b22 improve resilience against nodejs.org failures (#3759) 2020-04-03 02:49:38 +08:00
Alex Lam S.L
dc0cd088cf fix corner case in evaluate & unsafe_math (#3756)
fixes #3755
2020-03-30 19:13:14 +08:00
Alex Lam S.L
c69c026728 improve resilience against nodejs.org failures (#3758) 2020-03-30 10:20:13 +08:00
Alex Lam S.L
b5f4e1187f handle single-field segments (#3757) 2020-03-30 06:39:32 +08:00
Alex Lam S.L
827bcec186 handle source-map operations internally (#3754) 2020-03-28 22:18:56 +08:00
Alex Lam S.L
d105ab9722 v3.8.1 2020-03-28 01:04:40 +08:00
Alex Lam S.L
b39228892d fix line accounting in multi-line strings (#3752)
fixes #3748
2020-03-21 07:17:41 +08:00
Alex Lam S.L
ff72eaa3c3 improve --reduce-test (#3742)
- ignore difference in error messages
- improve readability on trailing whitespace differences
- improve performance & quality via `console.log()` insertions
2020-03-21 05:50:41 +08:00
Alex Lam S.L
0a1c9b34ce fix corner case in evaluate & ie8 (#3751)
fixes #3750
2020-03-21 00:55:24 +08:00
Alex Lam S.L
03e968be62 improve suspicious option detection (#3749) 2020-03-13 04:03:47 +08:00
Alex Lam S.L
421bb7083a fix corner case in unused (#3747)
fixes #3746
2020-03-06 18:27:42 +00:00
Alex Lam S.L
bdc8ef2218 fix corner case in collapse_vars (#3745)
fixes #3744
2020-03-06 18:27:06 +00:00
Alex Lam S.L
bca52fcba2 speed up CI (#3741) 2020-03-02 22:07:30 +08:00
Alex Lam S.L
d6d31cbb5a improve AST fuzzing (#3740) 2020-03-02 19:38:30 +08:00
Alex Lam S.L
a051846d22 fix corner case in evaluate (#3739)
fixes #3738
2020-03-01 20:34:31 +00:00
Alex Lam S.L
3485472866 avoid reducing setter argument (#3737) 2020-03-01 05:04:21 +00:00
Alex Lam S.L
c8d60d6983 detect toplevel option properly (#3735)
fixes #3730
2020-02-29 17:33:48 +00:00
Alex Lam S.L
6092bf23de fix corner case in evaluate (#3729) 2020-02-19 00:41:10 +00:00
Alex Lam S.L
7052ce5aef fix corner case in evaluate (#3728)
- augment `ufuzz` for further `RegExp` testing
2020-02-18 19:35:37 +00:00
Alex Lam S.L
d13b71297e v3.8.0 2020-02-18 20:32:37 +08:00
Alex Lam S.L
457f958af3 improve --reduce-test (#3727)
- print out Node.js and OS information
2020-02-17 20:56:22 +00:00
Alex Lam S.L
53517db3e4 speed up --reduce-test (#3726)
- avoid pathological test case branches via adaptive time-out
- use initial test case elapsed time to adjust maximum time-out
- index output cache using hash instead of raw source
2020-02-17 15:35:07 +00:00
Alex Lam S.L
c13caf4876 speed up --reduce-test via result caching (#3725) 2020-02-15 22:43:34 +00:00
kzc
fbfa6178a6 improve --reduce-test (#3722)
- hoist body of functions and IIFEs
- simplify var declarations
2020-02-15 20:22:33 +00:00
Alex Lam S.L
5315dd95b0 minor cleanup (#3723) 2020-02-15 17:55:26 +00:00
Marco Gonzalez
31a7bf2a22 Updated "Output options" > "comments" in README.md (#3717)
Expanded the current documentation to include:

- What the value of `"some"` means based on `lib/output.js`.
- Information about the `Function` overload parameters and expected output.
2020-02-15 15:10:58 +00:00
Alex Lam S.L
f0a29902ac enhance properties (#3721) 2020-02-15 13:04:44 +00:00
Alex Lam S.L
0d820e4c0a workaround RegExp formatting bugs (#3720) 2020-02-15 05:26:48 +00:00
Alex Lam S.L
f01f580d6c improve --reduce-test (#3719)
- cover missing cases when eliminating unreferenced labels
- format multi-line outputs correctly
2020-02-14 02:47:20 +00:00
Alex Lam S.L
c01ff76288 improve code reuse (#3718) 2020-02-13 05:16:10 +00:00
Alex Lam S.L
83a42716c3 fix corner case in unused (#3716) 2020-02-12 23:46:16 +00:00
Alex Lam S.L
2557148bba increase mocha --reduce-test timeout (#3715) 2020-02-12 02:25:04 +00:00
Alex Lam S.L
dd22eda888 enhance evaluate (#3714) 2020-02-12 01:01:17 +00:00
Alex Lam S.L
f4c77886e7 add test for --reduce-test (#3712) 2020-02-09 23:21:46 +00:00
Alex Lam S.L
df547ffd97 improve test reduction (#3711)
- scan `AST_SymbolFunarg`
- scan `console.log(...)`
2020-02-09 20:42:36 +00:00
Alex Lam S.L
70551febc8 improve test/reduce (#3710)
- suppress several instances of malformed AST generation
- improve resilience & reporting against malformed ASTs
2020-02-09 08:07:55 +00:00
Alex Lam S.L
44499a6643 fix corner cases in test/reduce (#3709) 2020-02-07 02:41:07 +00:00
Alex Lam S.L
470a7d4df1 improve reduction of AST_BlockStatement (#3708) 2020-02-06 21:20:05 +00:00
Alex Lam S.L
551420132c export missing API for AST manipulation (#3707) 2020-02-06 18:46:25 +00:00
kzc
b0040ba654 implement CLI --reduce-test and reduce tests in ufuzz (#3705) 2020-02-06 02:50:59 +00:00
Alex Lam S.L
c93ca6ee53 fix corner case in ie8 & reduce_vars (#3706)
fixes #3703
2020-02-05 20:03:22 +00:00
Alex Lam S.L
df506439b1 fix corner case in sequences (#3704)
fixes #3703
2020-02-04 04:57:32 +00:00
Alex Lam S.L
36b2d35bf3 v3.7.7 2020-02-02 00:24:50 +00:00
Alex Lam S.L
79c60032a5 fix corner case in collapse_vars (#3701)
fixes #3700
2020-01-30 09:04:44 +08:00
Alex Lam S.L
a3754068dd fix corner case in collapse_vars (#3699)
fixes #3698
2020-01-30 00:08:53 +08:00
Alex Lam S.L
2ba5f391e0 enhance collapse_vars (#3697) 2020-01-29 08:52:20 +08:00
Alex Lam S.L
87119e44a0 fix corner case in sign propagation (#3696)
- migrate de-facto functionality to `evaluate`

fixes #3695
2020-01-28 22:44:18 +08:00
Alex Lam S.L
b499e03f82 enhance conditionals (#3694) 2020-01-28 12:33:21 +08:00
Alex Lam S.L
a478f275e4 enhance sequences (#3693) 2020-01-28 09:58:01 +08:00
Alex Lam S.L
e9e76dcf04 fix corner case in string concatenations (#3692)
- migrate de-facto compression to `conditionals` & `strings`

fixes #3689
2020-01-28 07:33:11 +08:00
Alex Lam S.L
0dcedad2d5 fix corner case in booleans (#3691)
fixes #3690
2020-01-28 02:04:44 +08:00
Alex Lam S.L
36a430cd1e v3.7.6 2020-01-19 11:02:58 +00:00
Alex Lam S.L
41a6eb892a fix corner case in evaluate (#3685)
fixes #3684
2020-01-16 01:51:37 +08:00
Alex Lam S.L
91d87ae663 fix corner case in unsafe_math (#3683)
fixes #3682
2020-01-15 04:05:58 +08:00
Alex Lam S.L
5beb7e4797 v3.7.5 2020-01-12 11:12:11 +08:00
Alex Lam S.L
46caaa82ba enhance collapse_vars (#3680)
closes #3679
2020-01-10 04:28:43 +08:00
Alex Lam S.L
5d258259a4 introduce --output-opts CLI option (#3678)
closes #3675
2020-01-08 20:44:03 +08:00
Alex Lam S.L
14c35739dd fix corner case in unsafe_math (#3677)
fixes #3676
2020-01-08 10:28:10 +08:00
Alex Lam S.L
f5ceff6e4b fix corner case in unused (#3674)
fixes #3673
2020-01-07 20:06:25 +08:00
Alex Lam S.L
4d6771b9b1 fix corner case in collapse_vars (#3672)
fixes #3671
2020-01-07 19:34:16 +08:00
Alex Lam S.L
d17191111a v3.7.4 2020-01-07 07:59:54 +08:00
Alex Lam S.L
0ff607cb80 improve ufuzz false positive detection (#3670) 2020-01-06 11:26:15 +08:00
Alex Lam S.L
1988495d71 fix corner case in conditionals (#3669)
fixes #3668
2020-01-04 09:24:28 +08:00
Alex Lam S.L
fdc10086da fix corner case in reduce_vars (#3667)
fixes #3666
2020-01-03 19:28:47 +08:00
Alex Lam S.L
746f5f6c62 fix corner case in unused (#3665)
fixes #3664
2020-01-01 20:24:30 +08:00
Alex Lam S.L
d83d3d741a enhance unused (#3662) 2019-12-31 23:39:24 +08:00
Alex Lam S.L
99ac73a635 enhance booleans (#3661) 2019-12-31 13:10:05 +08:00
Alex Lam S.L
a2e4c2fd97 enhance evaluate (#3660) 2019-12-31 11:51:21 +08:00
Alex Lam S.L
94785e8e14 fix corner case in booleans (#3659)
fixes #3658
2019-12-31 09:57:35 +08:00
Alex Lam S.L
4dbdac9c31 enhance booleans (#3657) 2019-12-30 22:41:11 +08:00
Alex Lam S.L
78c8efd851 fix corner case in evaluate (#3656)
fixes #3655
2019-12-29 21:16:53 +08:00
Alex Lam S.L
af310ba2d0 fix corner case in evaluate (#3654)
fixes #3653
2019-12-29 02:50:57 +00:00
Alex Lam S.L
2f3930d1b9 fix corner case in collapse_vars (#3652)
fixes #3651
2019-12-29 00:57:59 +00:00
Alex Lam S.L
d1a78920d9 workaround firefox asm.js quirks (#3650)
fixes #3636
2019-12-28 23:14:53 +00:00
Alex Lam S.L
d9cd3d33c8 enhance evaluate (#3649) 2019-12-28 20:26:15 +00:00
Alex Lam S.L
22b47cdd63 improve unicode handling (#3648) 2019-12-28 18:06:51 +00:00
Alex Lam S.L
4cf612dc9f increase mocha default timeout (#3647)
closes #3640
2019-12-28 02:32:22 +00:00
Alex Lam S.L
a19d31dd33 fix corner case in unsafe (#3646) 2019-12-27 14:24:54 +00:00
Alex Lam S.L
01d6e0f223 v3.7.3 2019-12-27 06:11:29 +08:00
Alex Lam S.L
ab050e7a94 fix corner case in directives (#3645) 2019-12-25 00:55:39 +00:00
Alex Lam S.L
75aa6ef848 enhance conditionals (#3643) 2019-12-22 04:29:32 +00:00
Alex Lam S.L
519a00bd8a fix corner case in collapse_vars (#3642)
fixes #3641
2019-12-22 01:08:56 +00:00
Alex Lam S.L
3ff0feddee suppress false positives from fuzzer (#3638) 2019-12-16 17:32:47 +02:00
Alex Lam S.L
74396acc86 fix corner case in loops (#3635)
fixes #3634
2019-12-11 06:39:46 +08:00
Alex Lam S.L
036bca980c enhance loops (#3633) 2019-12-10 12:57:47 +00:00
Alex Lam S.L
18c2b1841b fix corner case in reduce_vars (#3632)
fixes #3631
2019-12-10 09:45:51 +00:00
Alex Lam S.L
fe19ab7c57 v3.7.2 2019-12-08 15:36:18 +00:00
Alex Lam S.L
9074f05129 fix corner case in collapse_vars (#3629)
fixes #3628
2019-12-05 05:08:37 +08:00
Alex Lam S.L
04fbb1f949 avoid collision with HTML comments (#3625)
fixes #3624
2019-12-05 02:43:25 +08:00
Alex Lam S.L
bf7e4ca1a3 fix corner case in collapse_vars (#3627)
fixes #3626
2019-12-05 00:59:57 +08:00
Alex Lam S.L
d68ddc31f9 fix corner case in reduce_vars (#3623)
fixes #3622
2019-12-04 20:24:55 +08:00
Alex Lam S.L
500e31e03b enhance collapse_vars (#3621) 2019-12-02 15:25:38 +08:00
Alex Lam S.L
bef856addb fix corner case in keep_fargs (#3620)
fixes #3619
2019-12-02 12:28:17 +08:00
Alex Lam S.L
9a6faf365b fix corner cases in keep_fargs & unused (#3618) 2019-12-02 06:43:54 +08:00
Alex Lam S.L
e915832a36 enhance unused (#3617) 2019-12-01 18:10:37 +08:00
Alex Lam S.L
0593892d6e enhance collapse_vars (#3616) 2019-12-01 02:31:04 +08:00
Alex Lam S.L
b866a23671 v3.7.1 2019-11-30 06:02:09 +08:00
Alex Lam S.L
1283d73853 fix corner case in parsing directives (#3615) 2019-11-29 18:57:29 +08:00
Alex Lam S.L
1b61a81b5d enhance collapse_vars (#3613) 2019-11-29 17:45:49 +08:00
Alex Lam S.L
5a88c30d65 enhance assignments (#3612) 2019-11-28 07:40:34 +08:00
Alex Lam S.L
168ae747ad enhance collapse_vars (#3611) 2019-11-28 03:57:10 +08:00
Alex Lam S.L
d4b7010678 fix corner case in unsafe_regexp (#3609) 2019-11-27 17:35:21 +08:00
Alex Lam S.L
e27493f3c2 fix corner case in inline (#3608) 2019-11-27 14:54:36 +08:00
Alex Lam S.L
292d1de363 use stable Node.js version for fuzzing (#3605) 2019-11-26 02:11:11 +08:00
Alex Lam S.L
6768e6578f inline functions with directives more effectively (#3604) 2019-11-26 01:51:04 +08:00
Alex Lam S.L
48a0f6fe41 enhance unsafe_math (#3603) 2019-11-25 21:14:13 +08:00
Alex Lam S.L
81caadb709 enhance collapse_vars (#3602) 2019-11-20 12:54:49 +08:00
Alex Lam S.L
d959e0b86f fix corner case in if_return (#3601)
fixes #3600
2019-11-19 15:45:20 +08:00
Alex Lam S.L
67278e76c8 fix corner case in unused (#3599)
fixes #3598
2019-11-19 04:26:41 +08:00
Alex Lam S.L
c289ba1139 fix corner case in collapse_vars (#3597)
fixes #3596
2019-11-19 02:30:52 +08:00
Alex Lam S.L
02cc4a0d03 v3.7.0 2019-11-18 20:21:07 +08:00
Alex Lam S.L
4e06e1ca34 fix corner case in inline (#3595) 2019-11-18 15:04:55 +08:00
Alex Lam S.L
644f65feca fix corner case in unsafe_math (#3594)
fixes #3593
2019-11-18 13:44:13 +08:00
Alex Lam S.L
8504a4ea0e fix corner case in reduce_funcs (#3592) 2019-11-17 11:19:42 +08:00
Alex Lam S.L
10c1a78772 fix corner case in collapse_vars (#3591) 2019-11-17 05:24:02 +08:00
Alex Lam S.L
a6a0319f1c compress empty for-in loops (#3590) 2019-11-17 02:36:42 +08:00
Alex Lam S.L
d1b2ecec27 refine precision limits on unsafe_math (#3589) 2019-11-17 01:16:42 +08:00
Alex Lam S.L
552be61c4d introduce eager evaluation (#3587) 2019-11-16 06:10:47 +08:00
Alex Lam S.L
dcfc4aca5b minor clean-ups (#3588) 2019-11-16 00:40:22 +08:00
Alex Lam S.L
4027f87717 migrate to GitHub Actions (#3586) 2019-11-14 10:48:32 +08:00
Alex Lam S.L
910799ca99 fix corner case in switches (#3585) 2019-11-14 02:29:55 +08:00
Alex Lam S.L
4bd36dc8da enhance unused (#3584) 2019-11-13 21:44:44 +08:00
Alex Lam S.L
ab15c40770 enhance switches (#3583) 2019-11-13 20:03:48 +08:00
Alex Lam S.L
fe65ce9658 fix corner case in collapse_vars (#3582)
fixes #3581
2019-11-13 16:45:16 +08:00
Alex Lam S.L
d6fd18d0b0 enhance evaluate & inline (#3580) 2019-11-13 04:17:09 +08:00
Alex Lam S.L
0d17c5b0fa v3.6.9 2019-11-12 22:50:52 +08:00
Alex Lam S.L
5b20bad4b3 fix corner case in dead_code (#3579)
fixes #3578
2019-11-12 05:16:14 +08:00
Alex Lam S.L
765a06340f enable cache on GitHub Actions (#3570) 2019-11-10 09:06:48 +08:00
Alex Lam S.L
5045e140b1 fix corner case in conditionals (#3577)
fixes #3576
2019-11-09 00:53:15 +08:00
Alex Lam S.L
10648c9af6 enhance dead_code (#3575) 2019-11-08 13:45:28 +08:00
Alex Lam S.L
87e67ec299 fix corner case in collapse_vars (#3574)
fixes #3573
2019-11-07 20:38:03 +08:00
Alex Lam S.L
61a0dad9fe v3.6.8 2019-11-06 13:52:58 +08:00
Alex Lam S.L
3e2c51a4da enhance collapse_vars (#3572) 2019-11-05 18:15:28 +08:00
Alex Lam S.L
0e29ad5eb9 fix corner case in evaluate (#3569) 2019-11-04 13:13:48 +08:00
Alex Lam S.L
0f2687ecfc v3.6.7 2019-11-02 13:32:05 +08:00
Alex Lam S.L
1c0defdc03 enhance unsafe evaluate (#3564) 2019-11-02 03:34:32 +08:00
Alex Lam S.L
dcbf2236c7 more tests for #3562 (#3565) 2019-11-02 03:34:20 +08:00
Alex Lam S.L
24bb288832 fix corner case in collapse_vars (#3563)
fixes #3562
2019-11-01 22:38:19 +08:00
Alex Lam S.L
6ad8e1081f v3.6.6 2019-11-01 13:40:03 +08:00
Alex Lam S.L
815eff1f7c enhance if_return (#3560) 2019-11-01 02:08:31 +08:00
Alex Lam S.L
1e9b576ee9 fix corner case in evaluate (#3559)
fixes #3558
2019-11-01 00:01:25 +08:00
Alex Lam S.L
3797458365 enhance conditionals (#3557) 2019-10-31 09:33:46 +08:00
Alex Lam S.L
1858c2018c enhance typeofs (#3556) 2019-10-31 08:00:04 +08:00
Alex Lam S.L
ec7f071272 fix corner case in dead_code (#3553)
fixes #3552
2019-10-30 14:21:22 +08:00
Alex Lam S.L
f1eb03f2c0 enhance dead_code (#3551) 2019-10-30 06:34:54 +08:00
Alex Lam S.L
0f4cfa877a fix corner case in comments (#3550) 2019-10-30 03:49:39 +08:00
Alex Lam S.L
1d5c2becbd enhance evaluate (#3549) 2019-10-29 19:51:55 +08:00
Alex Lam S.L
22a09ea7c5 fix corner case in unsafe_math (#3548)
fixes #3547
2019-10-29 17:06:57 +08:00
Alex Lam S.L
bad664c632 compress object literals (#3546) 2019-10-29 16:53:48 +08:00
Alex Lam S.L
8a191c0a84 v3.6.5 2019-10-29 12:55:28 +08:00
Alex Lam S.L
83fb8b4ca1 fix corner case in ie8 (#3543)
fixes #3542
2019-10-28 23:54:27 +08:00
Alex Lam S.L
f38e31bd1e fix corner case in evaluate (#3540)
fixes #3539
2019-10-28 19:56:42 +08:00
Alex Lam S.L
24e8b47977 improve ufuzz resilience (#3541) 2019-10-28 18:08:51 +08:00
Alex Lam S.L
95618793a4 fix corner case in ufuzz (#3538) 2019-10-28 16:04:07 +08:00
Alex Lam S.L
2f3b460212 fix & enhance unsafe_math (#3537)
closes #3535
fixes #3536
2019-10-28 13:37:08 +08:00
Alex Lam S.L
06e135e35f migrate CI workaround (#3534) 2019-10-27 17:29:54 +08:00
Alex Lam S.L
ebbf3d4a51 improve ufuzz resilience (#3533) 2019-10-27 14:17:35 +08:00
Alex Lam S.L
a270ba6b59 fix corner cases in unsafe_math (#3532)
fixes #3531
2019-10-27 08:25:11 +08:00
Alex Lam S.L
37f35e4ac2 prevent tty truncation in test/compress (#3530) 2019-10-27 05:00:21 +08:00
Alex Lam S.L
50a578c1f6 compress arithmetic expressions further (#3529) 2019-10-27 03:07:07 +08:00
Alex Lam S.L
85237b08d4 fix corner case in collapse_vars (#3527)
fixes #3526
2019-10-26 05:41:02 +08:00
Alex Lam S.L
27b159e711 separate ufuzz job failures (#3525) 2019-10-25 02:06:29 +08:00
Alex Lam S.L
82b3eed5ef fix corner case in ie8 & mangle (#3524)
fixes #3523
2019-10-24 23:43:19 +08:00
Alex Lam S.L
0f7aa41e33 fix corner case in collapse_vars (#3521)
fixes #3520
2019-10-24 01:13:57 +08:00
Alex Lam S.L
370c8e0385 v3.6.4 2019-10-23 15:38:05 +08:00
Alex Lam S.L
4240fba9b8 fix corner cases in unused (#3519) 2019-10-23 06:46:05 +08:00
Alex Lam S.L
267bc70d33 fix corner case in unused (#3517)
fixes #3515
2019-10-23 01:58:40 +08:00
Alex Lam S.L
a53ab99378 fix corner case in side_effects (#3514)
fixes #3512
2019-10-23 01:04:00 +08:00
Alex Lam S.L
02308a7b56 fix corner case in reduce_vars (#3510)
fixes #3509
2019-10-22 20:36:05 +08:00
Alex Lam S.L
0b3705e82f fix corner cases in inline (#3507)
fixes #3506
2019-10-22 15:41:55 +08:00
Alex Lam S.L
da5a21b240 fix GitHub Actions script for fuzzing (#3504) 2019-10-21 04:30:00 +08:00
Alex Lam S.L
5bd0cf8633 enable GitHub Actions (#3503) 2019-10-21 04:11:14 +08:00
Alex Lam S.L
9199ab5846 minor tweaks (#3502) 2019-10-20 15:19:19 +08:00
Alex Lam S.L
ca6dce43fe fix corner case in collapse_vars (#3501) 2019-10-20 03:53:20 +08:00
Alex Lam S.L
543dd7d3d7 fix corner case in comments (#3500) 2019-10-20 03:21:30 +08:00
Alex Lam S.L
6b4886c908 v3.6.3 2019-10-19 14:28:11 +08:00
Alex Lam S.L
0201cb4b52 fix corner case in unused (#3499)
fixes #3497
2019-10-18 20:08:05 +08:00
Alex Lam S.L
cd072317d0 fix corner case in unused (#3496)
fixes #3495
2019-10-18 17:09:43 +08:00
Alex Lam S.L
0785a15ace fix corner case in dead_code & ie8 (#3494)
fixes #3493
2019-10-17 09:58:05 +08:00
Alex Lam S.L
b1279a46d9 fix corner case in sequences (#3491)
fixes #3490
2019-10-17 09:57:50 +08:00
Alex Lam S.L
b571619d31 handle throw of non-Errors gracefully (#3492) 2019-10-17 06:29:02 +08:00
Alex Lam S.L
7b5350b459 tweak Travis CI execution environment (#3489) 2019-10-16 15:47:06 +08:00
Alex Lam S.L
1549db70e6 fix corner case in ie8 (#3487)
fixes #3486
2019-10-16 12:18:27 +08:00
Alex Lam S.L
8ff9a3c8fb fix corner cases in ie8 (#3485)
fixes #3484
2019-10-16 06:37:40 +08:00
Alex Lam S.L
91cae51d8f fix corner case in evaluate & ie8 (#3483)
fixes #3482
2019-10-16 01:09:16 +08:00
Alex Lam S.L
8af2f5fbcf fix corner case in rename (#3481)
fixes #3480
2019-10-15 19:44:07 +08:00
Alex Lam S.L
86a8016323 fix corner case in ie8 & mangle (#3479)
fixes #3478
2019-10-15 17:14:48 +08:00
David xu
009dcdae01 avoid mangling of MutationObserver properties (#3477) 2019-10-15 16:16:43 +08:00
Alex Lam S.L
f86f615d83 fix corner case in ie8 & mangle (#3476)
fixes #3475
2019-10-15 14:18:12 +08:00
Alex Lam S.L
d3d1d11926 fix corner case in ie8 & rename (#3474)
fixes #3473
2019-10-15 07:27:02 +08:00
Alex Lam S.L
736019b767 fix corner cases in ie8 (#3472)
fixes #3471
2019-10-14 18:15:40 +08:00
Alex Lam S.L
a39bdb5840 fix corner case with collapse_vars & ie8 (#3469)
fixes #3468
2019-10-14 13:34:35 +08:00
Alex Lam S.L
e8ab0a44b2 update dependency (#3470) 2019-10-14 13:34:22 +08:00
Alex Lam S.L
c3ca293e6b v3.6.2 2019-10-12 20:19:05 +08:00
Alex Lam S.L
516b67a43b minor tweaks to CI test scripts (#3467) 2019-10-12 05:36:38 +08:00
Alex Lam S.L
eba3a37bb5 fix boolean context detection (#3466)
fixes #3465
2019-10-12 03:42:57 +08:00
Alex Lam S.L
6d57ca1a59 improve source map handling (#3464)
fixes #2947
fixes #3277
fixes #3411
2019-10-11 03:52:33 +08:00
Alex Lam S.L
3320251b4b update benchmark URLs (#3462) 2019-10-11 01:00:09 +08:00
Alex Lam S.L
33c94d3bd9 detect boolean context across IIFEs (#3461) 2019-10-10 09:37:02 +08:00
Alex Lam S.L
b18f717b46 improve readability of --help ast (#3460) 2019-10-10 04:32:32 +08:00
Alex Lam S.L
a0d4b648bb remove extraneous property (#3459)
fixes #3455
2019-10-10 01:36:58 +08:00
Alex Lam S.L
6db880e16d clean up AST_Binary optimisation logic (#3458) 2019-10-09 23:45:41 +08:00
Alex Lam S.L
a82003d6ac v3.6.1 2019-10-07 14:36:46 +08:00
Alex Lam S.L
da9f1622fc report errors correctly in ufuzz (#3456) 2019-10-07 14:36:00 +08:00
Alex Lam S.L
8a4c7077bb account for catch in constant lambda expressions (#3454) 2019-10-06 16:51:37 +08:00
Alex Lam S.L
0a63f2f2b0 workaround V8 RegExp bug (#3453)
fixes #3434
2019-10-06 11:49:39 +08:00
Alex Lam S.L
931ac66638 fix corner case in hoist_props (#3452)
fixes #3440
2019-10-06 10:29:13 +08:00
Alex Lam S.L
35338a100f handle function/variable name collisions correctly (#3451)
fixes #3439
2019-10-06 08:51:38 +08:00
David xu
d57b606e73 exclude mangling of addEventListener parameters (#3445) 2019-10-06 05:29:08 +08:00
Sampson Crowley
00ada04111 facilitate Webpack compatibility (#3435)
Verbose application of `require.resolve` instead of `[].map`
2019-10-06 05:20:47 +08:00
Alex Lam S.L
a31c477fea fix variable scope determination (#3449)
fixes #3444
2019-10-06 05:13:44 +08:00
Alex Lam S.L
bde7418ce1 update & fix dependencies (#3450) 2019-10-06 03:10:12 +08:00
Alex Lam S.L
70bb304a0a v3.6.0 2019-05-30 15:30:00 +08:00
Alex Lam S.L
9d3b1efd86 fix corner case in assignments (#3430)
fixes #3429
2019-05-30 05:01:53 +08:00
Alex Lam S.L
482e1baea3 enhance assignments & unused (#3428)
closes #3427
2019-05-29 01:21:08 +08:00
Alex Lam S.L
e4f5ba1d29 v3.5.15 2019-05-21 14:26:58 +08:00
Alex Lam S.L
b9053c7a25 fix corner case in keep_fargs (#3424)
fixes #3423
2019-05-21 12:55:34 +08:00
Alex Lam S.L
d357a7aabc v3.5.14 2019-05-20 00:13:06 +08:00
Alex Lam S.L
ae77ebe5a5 fix corner case in arguments (#3421)
fixes #3420
2019-05-19 12:59:40 +08:00
Alex Lam S.L
04439edcec v3.5.13 2019-05-17 14:10:33 +08:00
Alex Lam S.L
a246195412 enhance unsafe comparisons (#3419) 2019-05-17 01:28:18 +08:00
Alex Lam S.L
8939a36bc7 reduce false positives from fuzzing (#3417) 2019-05-16 16:15:03 +08:00
Alex Lam S.L
a21c348d93 improve sandbox fidelity (#3415) 2019-05-15 23:26:57 +08:00
Alex Lam S.L
1f0def10eb fix corner case in comparisons (#3414)
fixes #3413
2019-05-15 01:01:18 +08:00
Alex Lam S.L
f87caac9d8 fix corner case in hoist_props (#3412)
fixes #3411
2019-05-14 19:12:00 +08:00
Alex Lam S.L
d538a73250 enhance side_effects (#3410) 2019-05-14 05:26:40 +08:00
Alex Lam S.L
2e4fbdeb08 enhance keep_fargs (#3409) 2019-05-13 21:58:04 +08:00
Alex Lam S.L
3bc7cc82bb v3.5.12 2019-05-12 10:40:13 +08:00
Alex Lam S.L
45fbdbc2dc improve tests (#3408) 2019-05-12 09:44:02 +08:00
Alex Lam S.L
54cb678055 fix corner case in assignments (#3407)
fixes #3406
2019-05-12 03:52:46 +08:00
Alex Lam S.L
e88c439eac improve tests (#3405) 2019-05-11 22:06:14 +08:00
Alex Lam S.L
9fc8cd4076 fix corner case in functions (#3403)
fixes #3402
2019-05-11 18:55:45 +08:00
Alex Lam S.L
5476cb8f05 fix corner case in inline (#3401)
fixes #3400
2019-05-10 01:22:44 +08:00
Alex Lam S.L
6a30e1d6be improve tests (#3399) 2019-05-09 07:18:22 +08:00
Alex Lam S.L
e4881245d9 v3.5.11 2019-05-07 01:45:40 +08:00
Alex Lam S.L
354fec8a9c make enclose & wrap work with sourceMap (#3396)
fixes #3313
2019-05-04 20:25:52 +08:00
Alex Lam S.L
11cdab745d fix corner cases in sourceMap (#3397)
fixes #3255
fixes #3294
2019-05-04 20:08:57 +08:00
Alex Lam S.L
a89d424a0b render comments in custom ASTs gracefully (#3393)
fixes #3246
2019-05-02 13:50:51 +08:00
Alex Lam S.L
429d2b56b7 v3.5.10 2019-05-02 00:01:40 +08:00
Alex Lam S.L
2ea96549c5 unify logging functionality (#3392)
fixes #3253
fixes #3254
2019-04-30 06:32:24 +08:00
Alex Lam S.L
fba008e298 remove blanket safeguard from source-map (#3391)
Things has stabilised since 80a18fe2fa, so it makes sense to remove the unconditional masking for ease of debugging.
2019-04-30 02:40:36 +08:00
Alex Lam S.L
c37a8e927e fix corner case in properties (#3390)
fixes #3389
2019-04-29 17:23:00 +08:00
Alex Lam S.L
413bbe0480 fix corner case in evaluate (#3388)
fixes #3387
2019-04-29 08:55:46 +08:00
Alex Lam S.L
34075fc4c4 v3.5.9 2019-04-27 17:00:58 +08:00
Alex Lam S.L
e5436ca566 enhance side_effects (#3384) 2019-04-25 15:15:50 +08:00
Alex Lam S.L
cfde686eab v3.5.8 2019-04-25 12:33:13 +08:00
Alex Lam S.L
a206964c0a enhance side_effects (#3383) 2019-04-25 04:14:21 +08:00
Alex Lam S.L
c56d89f804 enhance unsafe (#3382) 2019-04-25 02:42:54 +08:00
Alex Lam S.L
c215706350 enhance unsafe comparisons (#3381) 2019-04-25 00:08:08 +08:00
Alex Lam S.L
d3b93ec682 fix corner case in unsafe (#3380) 2019-04-24 22:21:28 +08:00
Alex Lam S.L
6fe20dbe33 enhance comparisons (#3379) 2019-04-24 21:38:55 +08:00
Alex Lam S.L
7ccdf3337b v3.5.7 2019-04-24 14:05:07 +08:00
Alex Lam S.L
dafed54764 fix corner case in reduce_vars (#3378)
fixes #3377
2019-04-24 14:01:01 +08:00
Alex Lam S.L
a84beafd1b fix corner case in assignments (#3376)
fixes #3375
2019-04-24 02:50:15 +08:00
Alex Lam S.L
f01cc1e413 unwind IIFE class patterns (#3373)
fixes #2332
2019-04-21 09:49:07 +08:00
Alex Lam S.L
338dd144b8 v3.5.6 2019-04-21 07:19:29 +08:00
Alex Lam S.L
c719552317 fix corner cases in functions (#3372)
fixes #3371
2019-04-21 02:16:05 +08:00
Alex Lam S.L
855964a87a enhance unsafe evaluate (#3370) 2019-04-20 19:42:41 +08:00
Alex Lam S.L
a438e2fca9 update domprops (#3369)
fixes #2343
fixes #3037
2019-04-20 07:16:14 +08:00
Alex Lam S.L
00833e893a enhance functions (#3368) 2019-04-19 19:01:47 +08:00
Alex Lam S.L
f1a77e4fc0 v3.5.5 2019-04-19 15:22:46 +08:00
Alex Lam S.L
b55a2fd531 fix corner case in functions (#3367)
fixes #3366
2019-04-19 02:55:43 +08:00
Alex Lam S.L
e8a2c0b5bf fix corner case in functions (#3365)
fixes #3364
2019-04-18 17:03:52 +08:00
Alex Lam S.L
21cd7e3f57 reduce test exports (#3361) 2019-04-17 16:19:08 +08:00
Alex Lam S.L
5172ba5f2a introduce functions (#3360)
`var f = function() {};` => `function f() {}`
2019-04-15 22:23:11 +08:00
Alex Lam S.L
a57b069409 v3.5.4 2019-04-10 02:40:42 +08:00
Alex Lam S.L
4454656c3b update dependencies (#3358)
- commander@2.20.0
- semver@6.0.0
2019-04-10 02:39:56 +08:00
Alex Lam S.L
fa43768ce0 v3.5.3 2019-04-01 18:12:03 +08:00
Alex Lam S.L
a74e600fa0 mangle shadowed lambda under ie8 correctly (#3356)
fixes #3355
2019-04-01 15:22:00 +08:00
Ruben Bridgewater
4b21526310 Fix test expectation (#3357)
The test expects a specific precision value that is not met on all V8 versions anymore due to a recent consolidation of different algorithms across the V8 code base.

This makes sure the preceision is tested against one digit less to keep the test working on all V8 versions.

Refs: 98453126c1
Refs: https://github.com/nodejs/node/issues/25060#issuecomment-477953457
2019-03-30 02:08:27 +08:00
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
197 changed files with 55492 additions and 10138 deletions

48
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,48 @@
name: CI
on:
pull_request:
push:
branches: [ master ]
jobs:
test:
strategy:
matrix:
node: [ "0.8", "0.10", "0.12", "4", "6", "8", "10", "12", latest ]
os: [ ubuntu-latest, windows-latest ]
script: [ compress, mocha, release/benchmark, release/jetstream ]
exclude:
- node: "0.8"
script: release/benchmark
- node: "0.8"
script: release/jetstream
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
runs-on: ${{ matrix.os }}
env:
NODE: ${{ matrix.node }}
TYPE: ${{ matrix.script }}
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: tmp
key: tmp ${{ matrix.script }}
- name: Perform tests
shell: bash
run: |
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add $NODE && nvs use $NODE'; do
cd ~/.nvs
while !(git clean -xdf); do echo "'git clean' failed - retrying..."; done
cd -
done
. ~/.nvs/nvs.sh --version
nvs use $NODE
node --version
npm config set audit false
npm config set optional false
npm config set save false
npm config set strict-ssl false
npm config set update-notifier false
npm --version
while !(npm install); do echo "'npm install' failed - retrying..."; done
node test/$TYPE

44
.github/workflows/ufuzz.yml vendored Normal file
View File

@@ -0,0 +1,44 @@
name: Fuzzing
on:
pull_request:
schedule:
- cron: "*/5 * * * *"
env:
BASE_URL: https://api.github.com/repos/${{ github.repository }}
CAUSE: ${{ github.event_name }}
RUN_NUM: ${{ github.run_number }}
TOKEN: ${{ github.token }}
jobs:
ufuzz:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest ]
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Perform fuzzing
shell: bash
run: |
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add 8 && nvs use 8'; do
cd ~/.nvs
while !(git clean -xdf); do echo "'git clean' failed - retrying..."; done
cd -
done
. ~/.nvs/nvs.sh --version
nvs use 8
node --version
npm config set audit false
npm config set optional false
npm config set save false
npm config set strict-ssl false
npm config set update-notifier false
npm --version
while !(npm install); do echo "'npm install' failed - retrying..."; done
if [[ $CAUSE == "schedule" ]]; then
node test/ufuzz/job $BASE_URL $TOKEN $RUN_NUM
else
node test/ufuzz/job 5000
fi

View File

@@ -1,14 +0,0 @@
language: node_js
node_js:
- "0.10"
- "0.12"
- "4"
- "6"
- "8"
env:
- UGLIFYJS_TEST_ALL=1
matrix:
fast_finish: true
sudo: false
cache:
directories: tmp

View File

@@ -1,6 +1,6 @@
UglifyJS is released under the BSD license:
Copyright 2012-2018 (c) Mihai Bazon <mihai.bazon@gmail.com>
Copyright 2012-2019 (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

219
README.md
View File

@@ -4,10 +4,12 @@ UglifyJS 3
UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.
#### Note:
- **`uglify-js@3` has a simplified [API](#api-reference) and [CLI](#command-line-usage) that is not backwards compatible with [`uglify-js@2`](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
- **Documentation for UglifyJS `2.x` releases can be found [here](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
- `uglify-js` only supports JavaScript (ECMAScript 5).
- To minify ECMAScript 2015 or above, transpile using tools like [Babel](https://babeljs.io/).
- **`uglify-js@3` has a simplified [API](#api-reference) and [CLI](#command-line-usage)
that is not backwards compatible with [`uglify-js@2`](https://github.com/mishoo/UglifyJS/tree/v2.x)**.
- **Documentation for UglifyJS `2.x` releases can be found [here](https://github.com/mishoo/UglifyJS/tree/v2.x)**.
- `uglify-js` supports ECMAScript 5 and some newer language features.
- To minify ECMAScript 2015 or above, you may need to transpile using tools like
[Babel](https://babeljs.io/).
Install
-------
@@ -87,6 +89,7 @@ a double dash to prevent input files being used as option arguments:
`wrap_iife` Wrap IIFEs in parenthesis. Note: you may
want to disable `negate_iife` under
compressor options.
-O, --output-opts [options] Specify output options (`beautify` disabled by default).
-o, --output <file> Output file path (default STDOUT). Specify `ast` or
`spidermonkey` to write UglifyJS or SpiderMonkey AST
as JSON to STDOUT respectively.
@@ -104,6 +107,8 @@ a double dash to prevent input files being used as option arguments:
sequences.
--config-file <file> Read `minify()` options from JSON file.
-d, --define <expr>[=value] Global definitions.
-e, --enclose [arg[:value]] Embed everything in a big function, with configurable
argument(s) & value(s).
--ie8 Support non-standard Internet Explorer 8.
Equivalent to setting `ie8: true` in `minify()`
for `compress`, `mangle` and `output` options.
@@ -118,10 +123,12 @@ a double dash to prevent input files being used as option arguments:
JS that was generated from some other original
code. Specify "inline" if the source map is
included within the sources.
`filename` Name and/or location of the output source.
`filename` Filename and/or location of the output source
(sets `file` attribute in source map).
`includeSources` Pass this flag if you want to include
the content of source files in the
source map as sourcesContent property.
`names` Include symbol names in the source map.
`root` Path to the original source to be included in
the source map.
`url` If specified, path to the source map to append in
@@ -130,6 +137,10 @@ a double dash to prevent input files being used as option arguments:
--toplevel Compress and/or mangle variables in top level scope.
--verbose Print diagnostic messages.
--warn Print warning messages.
--webkit Support non-standard Safari/Webkit.
Equivalent to setting `webkit: true` in `minify()`
for `mangle` and `output` options.
By default UglifyJS will not try to be Safari-proof.
--wrap <name> Embed everything in a big function, making the
“exports” and “global” variables available. You
need to pass an argument to this option to
@@ -149,10 +160,15 @@ debugging your compressed JavaScript. To get a source map, pass
Additional options:
- `--source-map "filename='<NAME>'"` to specify the name of the source map.
- `--source-map "filename='<NAME>'"` to specify the name of the source map. The value of
`filename` is only used to set `file` attribute (see [the spec][sm-spec])
in source map file.
- `--source-map "root='<URL>'"` to pass the URL where the original files can be found.
- `--source-map "names=false"` to omit symbol names if you want to reduce size
of the source map file.
- `--source-map "url='<URL>'"` to specify the URL where the source map can be found.
Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
`//# sourceMappingURL=` directive.
@@ -202,17 +218,16 @@ Example:
To enable the mangler you need to pass `--mangle` (`-m`). The following
(comma-separated) options are supported:
- `toplevel` (default `false`) -- mangle names declared in the top level scope.
- `eval` (default `false`) -- mangle names visible in scopes where `eval` or
`with` are used.
- `eval` (default `false`) -- mangle names visible in scopes where `eval` or `with` are used.
- `reserved` (default: `[]`) -- when mangling is enabled but you want to
prevent certain names from being mangled, you can declare those names with
`--mangle reserved` — pass a comma-separated list of names. For example:
When mangling is enabled but you want to prevent certain names from being
mangled, you can declare those names with `--mangle reserved` — pass a
comma-separated list of names. For example:
uglifyjs ... -m reserved=['$','require','exports']
uglifyjs ... -m reserved=['$','require','exports']
to prevent the `require`, `exports` and `$` names from being changed.
to prevent the `require`, `exports` and `$` names from being changed.
### CLI mangling property names (`--mangle-props`)
@@ -473,42 +488,45 @@ if (result.error) throw result.error;
## Minify options
- `warnings` (default `false`) — pass `true` to return compressor warnings
in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
- `parse` (default `{}`) — pass an object if you wish to specify some
additional [parse options](#parse-options).
- `compress` (default `{}`) — pass `false` to skip compressing entirely.
Pass an object to specify custom [compress options](#compress-options).
- `ie8` (default `false`) -- set to `true` to support IE8.
- `keep_fnames` (default: `false`) -- pass `true` to prevent discarding or mangling
of function names. Useful for code relying on `Function.prototype.name`.
- `mangle` (default `true`) — pass `false` to skip mangling names, or pass
an object to specify [mangle options](#mangle-options) (see below).
- `mangle.properties` (default `false`) — a subcategory of the mangle option.
Pass an object to specify custom [mangle property options](#mangle-properties-options).
- `output` (default `null`) pass an object if you wish to specify
additional [output options](#output-options). The defaults are optimized
for best compression.
- `sourceMap` (default `false`) - pass an object if you wish to specify
[source map options](#source-map-options).
- `toplevel` (default `false`) - set to `true` if you wish to enable top level
variable and function name mangling and to drop unused variables and functions.
- `nameCache` (default `null`) - pass an empty object `{}` or a previously
- `nameCache` (default `null`) -- pass an empty object `{}` or a previously
used `nameCache` object if you wish to cache mangled variable and
property names across multiple invocations of `minify()`. Note: this is
a read/write property. `minify()` will read the name cache state of this
object and update it during minification so that it may be
reused or externally persisted by the user.
- `ie8` (default `false`) - set to `true` to support IE8.
- `output` (default `null`) — pass an object if you wish to specify
additional [output options](#output-options). The defaults are optimized
for best compression.
- `keep_fnames` (default: `false`) - pass `true` to prevent discarding or mangling
of function names. Useful for code relying on `Function.prototype.name`.
- `parse` (default `{}`) pass an object if you wish to specify some
additional [parse options](#parse-options).
- `sourceMap` (default `false`) -- pass an object if you wish to specify
[source map options](#source-map-options).
- `toplevel` (default `false`) -- set to `true` if you wish to enable top level
variable and function name mangling and to drop unused variables and functions.
- `warnings` (default `false`) — pass `true` to return compressor warnings
in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
- `webkit` (default `false`) -- enable workarounds for Safari/WebKit bugs.
PhantomJS users should set this option to `true`.
## Minify options structure
@@ -587,6 +605,9 @@ var result = UglifyJS.minify({"compiled.js": "compiled code"}, {
If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.url`.
If you wish to reduce file size of the source map, set option `sourceMap.names`
to be `false` and all symbol names will be omitted.
## Parse options
- `bare_returns` (default `false`) -- support top level `return` statements
@@ -600,6 +621,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `arguments` (default: `true`) -- replace `arguments[index]` with function
parameter name whenever possible.
- `assignments` (default: `true`) -- apply optimizations to assignment expressions.
- `booleans` (default: `true`) -- various optimizations for boolean context,
for example `!!a ? b : c → a ? b : c`
@@ -615,6 +638,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `dead_code` (default: `true`) -- remove unreachable code
- `directives` (default: `true`) -- remove redundant or non-standard directives
- `drop_console` (default: `false`) -- Pass `true` to discard calls to
`console.*` functions. If you wish to drop a specific function call
such as `console.info` and/or retain side effects from function arguments
@@ -622,11 +647,17 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `drop_debugger` (default: `true`) -- remove `debugger;` statements
- `evaluate` (default: `true`) -- attempt to evaluate constant expressions
- `evaluate` (default: `true`) -- Evaluate expression for shorter constant
representation. Pass `"eager"` to always replace function calls whenever
possible, or a positive integer to specify an upper bound for each individual
evaluation in number of characters.
- `expression` (default: `false`) -- Pass `true` to preserve completion values
from terminal statements without `return`, e.g. in bookmarklets.
- `functions` (default: `true`) -- convert declarations from `var`to `function`
whenever possible.
- `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation)
- `hoist_funs` (default: `false`) -- hoist function declarations
@@ -634,8 +665,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `hoist_props` (default: `true`) -- hoist properties from constant object and
array literals into regular variables subject to a set of constraints. For example:
`var o={p:1, q:2}; f(o.p, o.q);` is converted to `f(1, 2);`. Note: `hoist_props`
works best with `mangle` enabled, the `compress` option `passes` set to `2` or higher,
and the `compress` option `toplevel` enabled.
works best with `toplevel` and `mangle` enabled, alongside with `compress` option
`passes` set to `2` or higher.
- `hoist_vars` (default: `false`) -- hoist `var` declarations (this is `false`
by default because it seems to increase the size of the output in general)
@@ -652,12 +683,13 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `join_vars` (default: `true`) -- join consecutive `var` statements
- `keep_fargs` (default: `true`) -- Prevents the compressor from discarding unused
function arguments. You need this for code which relies on `Function.length`.
- `keep_fargs` (default: `strict`) -- Discard unused function arguments. Code
which relies on `Function.length` will break if this is done indiscriminately,
i.e. when passing `true`. Pass `false` to always retain function arguments.
- `keep_fnames` (default: `false`) -- Pass `true` to prevent the
compressor from discarding function names. Useful for code relying on
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle-options).
- `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from
being compressed into `1/0`, which may cause performance issues on Chrome.
@@ -665,10 +697,14 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops
when we can statically determine the condition.
- `merge_vars` (default: `true`) -- combine and reuse variables.
- `negate_iife` (default: `true`) -- negate "Immediately-Called Function Expressions"
where the return value is discarded, to avoid the parens that the
code generator would insert.
- `objects` (default: `true`) -- compact duplicate keys in object literals.
- `passes` (default: `1`) -- The maximum number of times to run compress.
In some cases more than one pass leads to further compressed code. Keep in
mind more passes will take more time.
@@ -717,6 +753,10 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
example: `/*@__PURE__*/foo();`
- `spread` (default: `true`) -- flatten spread expressions.
- `strings` (default: `true`) -- compact string concatenations.
- `switches` (default: `true`) -- de-duplicate and remove unreachable `switch` branches
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or
@@ -755,8 +795,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple
direct variable assignments do not count as references unless set to `"keep_assign"`)
- `warnings` (default: `false`) -- display warnings when dropping unreachable
code or unused declarations etc.
- `varify` (default: `true`) -- convert block-scoped declaractions into `var`
whenever safe to do so
## Mangle options
@@ -830,8 +870,16 @@ can pass additional arguments that control the code output:
statement.
- `comments` (default `false`) -- pass `true` or `"all"` to preserve all
comments, `"some"` to preserve some comments, a regular expression string
(e.g. `/^!/`) or a function.
comments, `"some"` to preserve multi-line comments that contain `@cc_on`,
`@license`, or `@preserve` (case-insensitive), a regular expression string
(e.g. `/^!/`), or a function which returns `boolean`, e.g.
```js
function(node, comment) {
return comment.value.indexOf("@type " + node.TYPE) >= 0;
}
```
- `galio` (default `false`) -- enable workarounds for ANT Galio bugs
- `indent_level` (default `4`)
@@ -850,8 +898,8 @@ can pass additional arguments that control the code output:
adjust for this text. Can be used to insert a comment containing
licensing information, for example.
- `preserve_line` (default `false`) -- pass `true` to preserve lines, but it
only works if `beautify` is set to `false`.
- `preserve_line` (default `false`) -- pass `true` to retain line numbering on
a best effort basis.
- `quote_keys` (default `false`) -- pass `true` to quote all keys in literal
objects
@@ -871,8 +919,7 @@ can pass additional arguments that control the code output:
- `shebang` (default `true`) -- preserve shebang `#!` in preamble (bash scripts)
- `webkit` (default `false`) -- enable workarounds for WebKit bugs.
PhantomJS users should set this option to `true`.
- `v8` (default `false`) -- enable workarounds for Chrome & Node.js bugs
- `width` (default `80`) -- only takes effect when beautification is on, this
specifies an (orientative) line width that the beautifier will try to
@@ -882,7 +929,7 @@ can pass additional arguments that control the code output:
- `wrap_iife` (default `false`) -- pass `true` to wrap immediately invoked
function expressions. See
[#640](https://github.com/mishoo/UglifyJS2/issues/640) for more details.
[#640](https://github.com/mishoo/UglifyJS/issues/640) for more details.
# Miscellaneous
@@ -1041,8 +1088,8 @@ var result = UglifyJS.minify(ast, {
### Working with Uglify AST
Transversal and transformation of the native AST can be performed through
[`TreeWalker`](https://github.com/mishoo/UglifyJS2/blob/master/lib/ast.js) and
[`TreeTransformer`](https://github.com/mishoo/UglifyJS2/blob/master/lib/transform.js)
[`TreeWalker`](https://github.com/mishoo/UglifyJS/blob/master/lib/ast.js) and
[`TreeTransformer`](https://github.com/mishoo/UglifyJS/blob/master/lib/transform.js)
respectively.
### ESTree / SpiderMonkey AST
@@ -1103,7 +1150,7 @@ To enable fast minify mode with the API use:
UglifyJS.minify(code, { compress: false, mangle: true });
```
#### Source maps and debugging
### Source maps and debugging
Various `compress` transforms that simplify, rearrange, inline and remove code
are known to have an adverse effect on debugging with source maps. This is
@@ -1115,6 +1162,10 @@ disable the Uglify `compress` option and just use `mangle`.
To allow for better optimizations, the compiler makes various assumptions:
- The code does not rely on preserving its runtime performance characteristics.
Typically uglified code will run faster due to less instructions and easier
inlining, but may be slower on rare occasions for a specific platform, e.g.
see [`reduce_funcs`](#compress-options).
- `.toString()` and `.valueOf()` don't have side effects, and for built-in
objects they have not been overridden.
- `undefined`, `NaN` and `Infinity` have not been externally redefined.
@@ -1126,3 +1177,67 @@ To allow for better optimizations, the compiler makes various assumptions:
- Object properties can be added, removed and modified (not prevented with
`Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
`Object.preventExtensions()` or `Object.seal()`).
- Earlier versions of JavaScript will throw `SyntaxError` with the following:
```js
({
p: 42,
get p() {},
});
// SyntaxError: Object literal may not have data and accessor property with
// the same name
```
UglifyJS may modify the input which in turn may suppress those errors.
- Iteration order of keys over an object which contains spread syntax in later
versions of Chrome and Node.js may be altered.
- When `toplevel` is enabled, UglifyJS effectively assumes input code is wrapped
within `function(){ ... }`, thus forbids aliasing of declared global variables:
```js
A = "FAIL";
var B = "FAIL";
// can be `global`, `self`, `window` etc.
var top = function() {
return this;
}();
// "PASS"
top.A = "PASS";
console.log(A);
// "FAIL" after compress and/or mangle
top.B = "PASS";
console.log(B);
```
- Use of `arguments` alongside destructuring as function parameters, e.g.
`function({}, arguments) {}` will result in `SyntaxError` in earlier versions
of Chrome and Node.js - UglifyJS may modify the input which in turn may
suppress those errors.
- Earlier versions of Chrome and Node.js will throw `ReferenceError` with the
following:
```js
var a;
try {
throw 42;
} catch ({
[a]: b,
// ReferenceError: a is not defined
}) {
let a;
}
```
UglifyJS may modify the input which in turn may suppress those errors.
- Later versions of JavaScript will throw `SyntaxError` with the following:
```js
a => {
let a;
};
// SyntaxError: Identifier 'a' has already been declared
```
UglifyJS may modify the input which in turn may suppress those errors.
- Later versions of JavaScript will throw `SyntaxError` with the following:
```js
try {
// ...
} catch ({ message: a }) {
var a;
}
// SyntaxError: Identifier 'a' has already been declared
```
UglifyJS may modify the input which in turn may suppress those errors.

View File

@@ -1,20 +0,0 @@
environment:
matrix:
- nodejs_version: "0.10"
- nodejs_version: "0.12"
- nodejs_version: "4"
- nodejs_version: "6"
- nodejs_version: "8"
install:
- ps: Install-Product node $env:nodejs_version
- set UGLIFYJS_TEST_ALL=1
- npm install
build: off
cache:
- tmp
matrix:
fast_finish: true
test_script:
- node --version
- npm --version
- npm test

View File

@@ -8,151 +8,254 @@ require("../tools/exit");
var fs = require("fs");
var info = require("../package.json");
var path = require("path");
var program = require("commander");
var UglifyJS = require("../tools/node");
var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
var files = {};
var options = {
compress: false,
mangle: false
var options = {};
var short_forms = {
b: "beautify",
c: "compress",
d: "define",
e: "enclose",
h: "help",
m: "mangle",
o: "output",
O: "output-opts",
p: "parse",
v: "version",
V: "version",
};
program.version(info.name + " " + info.version);
program.parseArgv = program.parse;
program.parse = undefined;
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("--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_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.");
program.option("--wrap <name>", "Embed everything as a function with “exports” corresponding to “name” globally.");
program.arguments("[files...]").parseArgv(process.argv);
if (program.configFile) {
options = JSON.parse(read_file(program.configFile));
var args = process.argv.slice(2);
var paths = [];
var output, nameCache;
var specified = {};
while (args.length) {
var arg = args.shift();
if (arg[0] != "-") {
paths.push(arg);
} else if (arg == "--") {
paths = paths.concat(args);
break;
} else if (arg[1] == "-") {
process_option(arg.slice(2));
} else [].forEach.call(arg.slice(1), function(letter, index, arg) {
if (!(letter in short_forms)) fatal("invalid option -" + letter);
process_option(short_forms[letter], index + 1 < arg.length);
});
}
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
fatal("ERROR: cannot write source map to STDOUT");
}
[
"compress",
"ie8",
"mangle",
"sourceMap",
"toplevel",
"wrap"
].forEach(function(name) {
if (name in program) {
options[name] = program[name];
function process_option(name, no_value) {
specified[name] = true;
switch (name) {
case "help":
switch (read_value()) {
case "ast":
print(UglifyJS.describe_ast());
break;
case "options":
var text = [];
var toplevels = [];
var padding = "";
var defaults = UglifyJS.default_options();
for (var name in defaults) {
var option = defaults[name];
if (option && typeof option == "object") {
text.push("--" + ({
output: "beautify",
sourceMap: "source-map",
}[name] || name) + " options:");
text.push(format_object(option));
text.push("");
} else {
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
toplevels.push([ {
keep_fnames: "keep-fnames",
nameCache: "name-cache",
}[name] || name, option ]);
}
}
toplevels.forEach(function(tokens) {
text.push("--" + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
});
print(text.join("\n"));
break;
default:
print([
"Usage: uglifyjs [files...] [options]",
"",
"Options:",
" -h, --help Print usage information.",
" `--help options` for details on available options.",
" -v, -V, --version Print version number.",
" -p, --parse <options> Specify parser options.",
" -c, --compress [options] Enable compressor/specify compressor options.",
" -m, --mangle [options] Mangle names/specify mangler options.",
" --mangle-props [options] Mangle properties/specify mangler options.",
" -b, --beautify [options] Beautify output/specify output options.",
" -O, --output-opts <options> Output options (beautify disabled).",
" -o, --output <file> Output file (default STDOUT).",
" --comments [filter] Preserve copyright comments in the output.",
" --config-file <file> Read minify() options from JSON file.",
" -d, --define <expr>[=value] Global definitions.",
" -e, --enclose [arg[,...][:value[,...]]] Embed everything in a big function, with configurable argument(s) & value(s).",
" --ie8 Support non-standard Internet Explorer 8.",
" --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name.",
" --name-cache <file> File to hold mangled name mappings.",
" --rename Force symbol expansion.",
" --no-rename Disable symbol expansion.",
" --self Build UglifyJS as a library (implies --wrap UglifyJS)",
" --source-map [options] Enable source map/specify source map options.",
" --timings Display operations run time on STDERR.",
" --toplevel Compress and/or mangle variables in toplevel scope.",
" --validate Perform validation during AST manipulations.",
" --verbose Print diagnostic messages.",
" --warn Print warning messages.",
" --webkit Support non-standard Safari/Webkit.",
" --wrap <name> Embed everything as a function with “exports” corresponding to “name” globally.",
" --reduce-test Reduce a standalone test case (assumes cloned repository).",
].join("\n"));
}
process.exit();
case "version":
print(info.name + " " + info.version);
process.exit();
case "config-file":
var config = JSON.parse(read_file(read_value(true)));
if (config.mangle && config.mangle.properties && config.mangle.properties.regex) {
config.mangle.properties.regex = UglifyJS.parse(config.mangle.properties.regex, {
expression: true,
}).value;
}
for (var key in config) if (!(key in options)) options[key] = config[key];
break;
case "compress":
case "mangle":
options[name] = parse_js(read_value(), options[name]);
break;
case "source-map":
options.sourceMap = parse_js(read_value(), options.sourceMap);
break;
case "enclose":
options[name] = read_value();
break;
case "ie8":
case "timings":
case "toplevel":
case "validate":
case "webkit":
options[name] = true;
break;
case "keep-fnames":
options.keep_fnames = true;
break;
case "wrap":
options[name] = read_value(true);
break;
case "verbose":
options.warnings = "verbose";
break;
case "warn":
if (!options.warnings) options.warnings = true;
break;
case "beautify":
options.output = parse_js(read_value(), options.output);
if (!("beautify" in options.output)) options.output.beautify = true;
break;
case "output-opts":
options.output = parse_js(read_value(true), options.output);
break;
case "comments":
if (typeof options.output != "object") options.output = {};
options.output.comments = read_value();
if (options.output.comments === true) options.output.comments = "some";
break;
case "define":
if (typeof options.compress != "object") options.compress = {};
options.compress.global_defs = parse_js(read_value(true), options.compress.global_defs, "define");
break;
case "mangle-props":
if (typeof options.mangle != "object") options.mangle = {};
options.mangle.properties = parse_js(read_value(), options.mangle.properties);
break;
case "name-cache":
nameCache = read_value(true);
options.nameCache = JSON.parse(read_file(nameCache, "{}"));
break;
case "output":
output = read_value(true);
break;
case "parse":
options.parse = parse_js(read_value(true), options.parse);
break;
case "rename":
options.rename = true;
break;
case "no-rename":
options.rename = false;
break;
case "reduce-test":
case "self":
break;
default:
fatal("invalid option --" + name);
}
function read_value(required) {
if (no_value || !args.length || args[0][0] == "-") {
if (required) fatal("missing option argument for --" + name);
return true;
}
return args.shift();
}
}
if (!output && options.sourceMap && options.sourceMap.url != "inline") fatal("cannot write source map to STDOUT");
if (specified["beautify"] && specified["output-opts"]) fatal("--beautify cannot be used with --output-opts");
[ "compress", "mangle" ].forEach(function(name) {
if (!(name in options)) options[name] = false;
});
if (program.beautify) {
options.output = typeof program.beautify == "object" ? program.beautify : {};
if (!("beautify" in options.output)) {
options.output.beautify = true;
}
}
if (program.comments) {
if (typeof options.output != "object") options.output = {};
options.output.comments = typeof program.comments == "string" ? program.comments : "some";
}
if (program.define) {
if (typeof options.compress != "object") options.compress = {};
if (typeof options.compress.global_defs != "object") options.compress.global_defs = {};
for (var expr in program.define) {
options.compress.global_defs[expr] = program.define[expr];
}
}
if (program.keepFnames) {
options.keep_fnames = true;
}
if (program.mangleProps) {
if (program.mangleProps.domprops) {
delete program.mangleProps.domprops;
if (options.mangle && options.mangle.properties) {
if (options.mangle.properties.domprops) {
delete options.mangle.properties.domprops;
} else {
if (typeof program.mangleProps != "object") program.mangleProps = {};
if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
if (typeof options.mangle.properties != "object") options.mangle.properties = {};
if (!Array.isArray(options.mangle.properties.reserved)) options.mangle.properties.reserved = [];
require("../tools/domprops").forEach(function(name) {
UglifyJS._push_uniq(program.mangleProps.reserved, name);
UglifyJS.push_uniq(options.mangle.properties.reserved, name);
});
}
if (typeof options.mangle != "object") options.mangle = {};
options.mangle.properties = program.mangleProps;
}
if (program.nameCache) {
options.nameCache = JSON.parse(read_file(program.nameCache, "{}"));
if (output == "ast") options.output = {
ast: true,
code: false,
};
if (options.parse && (options.parse.acorn || options.parse.spidermonkey)
&& options.sourceMap && options.sourceMap.content == "inline") {
fatal("inline source map only works with built-in parser");
}
if (program.output == "ast") {
options.output = {
ast: true,
code: false
};
}
if (program.parse) {
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;
if (options.warnings) {
UglifyJS.AST_Node.log_function(print_error, options.warnings == "verbose");
delete options.warnings;
}
var convert_path = function(name) {
return name;
};
if (typeof program.sourceMap == "object" && "base" in program.sourceMap) {
if (typeof options.sourceMap == "object" && "base" in options.sourceMap) {
convert_path = function() {
var base = program.sourceMap.base;
var base = options.sourceMap.base;
delete options.sourceMap.base;
return function(name) {
return path.relative(base, name);
};
}();
}
if (program.verbose) {
options.warnings = "verbose";
} else if (program.warn) {
options.warnings = true;
}
if (program.self) {
if (program.args.length) {
print_error("WARN: Ignoring input files since --self was passed");
}
if (specified["self"]) {
if (paths.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
if (!options.wrap) options.wrap = "UglifyJS";
simple_glob(UglifyJS.FILES).forEach(function(name) {
files[convert_path(name)] = read_file(name);
});
run();
} else if (program.args.length) {
simple_glob(program.args).forEach(function(name) {
paths = UglifyJS.FILES;
}
if (paths.length) {
simple_glob(paths).forEach(function(name) {
files[convert_path(name)] = read_file(name);
});
run();
@@ -173,18 +276,16 @@ function convert_ast(fn) {
}
function run() {
UglifyJS.AST_Node.warn_function = function(msg) {
print_error("WARN: " + msg);
};
var content = program.sourceMap && program.sourceMap.content;
var content = options.sourceMap && options.sourceMap.content;
if (content && content != "inline") {
print_error("INFO: Using input source map: " + content);
UglifyJS.AST_Node.info("Using input source map: {content}", {
content : content,
});
options.sourceMap.content = read_file(content, content);
}
if (program.timings) options.timings = true;
try {
if (program.parse) {
if (program.parse.acorn) {
if (options.parse) {
if (options.parse.acorn) {
files = convert_ast(function(toplevel, name) {
return require("acorn").parse(files[name], {
locations: true,
@@ -192,7 +293,7 @@ function run() {
sourceFile: name
});
});
} else if (program.parse.spidermonkey) {
} else if (options.parse.spidermonkey) {
files = convert_ast(function(toplevel, name) {
var obj = JSON.parse(files[name]);
if (!toplevel) return obj;
@@ -204,36 +305,58 @@ function run() {
} catch (ex) {
fatal(ex);
}
var result = UglifyJS.minify(files, options);
var result;
if (specified["reduce-test"]) {
// load on demand - assumes cloned repository
var reduce_test = require("../test/reduce");
if (Object.keys(files).length != 1) fatal("can only test on a single file");
result = reduce_test(files[Object.keys(files)[0]], options, {
log: print_error,
verbose: true,
});
} else {
result = UglifyJS.minify(files, options);
}
if (result.error) {
var ex = result.error;
if (ex.name == "SyntaxError") {
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];
if (!line && !col) {
line = lines[ex.line - 2];
col = line.length;
}
if (line) {
var limit = 70;
if (col > limit) {
line = line.slice(col - limit);
col = limit;
var file = files[ex.filename];
if (file) {
var col = ex.col;
var lines = file.split(/\r?\n/);
var line = lines[ex.line - 1];
if (!line && !col) {
line = lines[ex.line - 2];
col = line.length;
}
if (line) {
var limit = 70;
if (col > limit) {
line = line.slice(col - limit);
col = limit;
}
print_error(line.slice(0, 80));
print_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) {
} else if (ex.defs) {
print_error("Supported options:");
print_error(format_object(ex.defs));
}
fatal(ex);
} else if (program.output == "ast") {
} else if (output == "ast") {
if (!options.compress && !options.mangle) {
result.ast.figure_out_scope({});
var toplevel = result.ast;
if (!(toplevel instanceof UglifyJS.AST_Toplevel)) {
if (!(toplevel instanceof UglifyJS.AST_Statement)) toplevel = new UglifyJS.AST_SimpleStatement({
body: toplevel,
});
toplevel = new UglifyJS.AST_Toplevel({
body: [ toplevel ],
});
}
toplevel.figure_out_scope({});
}
print(JSON.stringify(result.ast, function(key, value) {
if (value) switch (key) {
@@ -260,33 +383,33 @@ function run() {
}
return value;
}, 2));
} else if (program.output == "spidermonkey") {
} else if (output == "spidermonkey") {
print(JSON.stringify(UglifyJS.minify(result.code, {
compress: false,
mangle: false,
output: {
ast: true,
code: false
}
},
}).ast.to_mozilla_ast(), null, 2));
} else if (program.output) {
fs.writeFileSync(program.output, result.code);
if (result.map) {
fs.writeFileSync(program.output + ".map", result.map);
}
} else if (output) {
fs.writeFileSync(output, result.code);
if (result.map) fs.writeFileSync(output + ".map", result.map);
} else {
print(result.code);
}
if (program.nameCache) {
fs.writeFileSync(program.nameCache, JSON.stringify(options.nameCache));
}
if (nameCache) fs.writeFileSync(nameCache, JSON.stringify(options.nameCache));
if (result.timings) for (var phase in result.timings) {
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
}
}
function fatal(message) {
if (message instanceof Error) message = message.stack.replace(/^\S*?Error:/, "ERROR:")
if (message instanceof Error) {
message = message.stack.replace(/^\S*?Error:/, "ERROR:")
} else {
message = "ERROR: " + message;
}
print_error(message);
process.exit(1);
}
@@ -311,7 +434,7 @@ function simple_glob(glob) {
.replace(/\?/g, "[^/\\\\]") + "$";
var mod = process.platform === "win32" ? "i" : "";
var rx = new RegExp(pattern, mod);
var results = entries.filter(function(name) {
var results = entries.sort().filter(function(name) {
return rx.test(name);
}).map(function(name) {
return path.join(dir, name);
@@ -331,55 +454,45 @@ function read_file(path, default_value) {
}
}
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
function parse_js(value, options, flag) {
if (!options || typeof options != "object") options = {};
if (typeof value == "string") try {
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 (flag) {
options[name] = value;
} else if (value instanceof UglifyJS.AST_Array) {
options[name] = value.elements.map(to_string);
} else {
options[name] = to_string(value);
}
}).ast.walk(new UglifyJS.TreeWalker(function(node) {
if (node instanceof UglifyJS.AST_Assign) {
var name = node.left.print_to_string();
var value = node.right;
if (flag) {
options[name] = value;
} else if (value instanceof UglifyJS.AST_Array) {
options[name] = value.elements.map(to_string);
} else {
options[name] = to_string(value);
}
return true;
}
if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_PropAccess) {
var name = node.print_to_string();
options[name] = true;
return true;
}
if (!(node instanceof UglifyJS.AST_Sequence)) throw node;
function to_string(value) {
return value instanceof UglifyJS.AST_Constant ? value.getValue() : value.print_to_string({
quote_keys: true
});
}
}));
} catch(ex) {
if (flag) {
fatal("Error parsing arguments for '" + flag + "': " + value);
} else {
options[value] = null;
return true;
}
if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_PropAccess) {
var name = node.print_to_string();
options[name] = true;
return true;
}
if (!(node instanceof UglifyJS.AST_Sequence)) throw node;
function to_string(value) {
return value instanceof UglifyJS.AST_Constant ? value.value : value.print_to_string({
quote_keys: true
});
}
}));
} catch (ex) {
if (flag) {
fatal("cannot parse arguments for '" + flag + "': " + value);
} else {
options[value] = null;
}
return options;
}
return options;
}
function skip_key(key) {

1096
lib/ast.js

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,41 @@
"use strict";
var to_ascii = typeof atob == "undefined" ? function(b64) {
return new Buffer(b64, "base64").toString();
} : atob;
var to_base64 = typeof btoa == "undefined" ? function(str) {
return new Buffer(str).toString("base64");
} : btoa;
var to_ascii, to_base64;
if (typeof Buffer == "undefined") {
to_ascii = atob;
to_base64 = btoa;
} else if (typeof Buffer.alloc == "undefined") {
to_ascii = function(b64) {
return new Buffer(b64, "base64").toString();
};
to_base64 = function(str) {
return new Buffer(str).toString("base64");
};
} else {
to_ascii = function(b64) {
return Buffer.from(b64, "base64").toString();
};
to_base64 = function(str) {
return Buffer.from(str).toString("base64");
};
}
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: " + name);
return null;
function read_source_map(name, toplevel) {
var comments = toplevel.end.comments_after;
for (var i = comments.length; --i >= 0;) {
var comment = comments[i];
if (comment.type != "comment1") break;
var match = /^# ([^\s=]+)=(\S+)\s*$/.exec(comment.value);
if (!match) break;
if (match[1] == "sourceMappingURL") {
match = /^data:application\/json(;.*?)?;base64,(\S+)$/.exec(match[2]);
if (!match) break;
return to_ascii(match[2]);
}
}
return to_ascii(match[2]);
AST_Node.warn("inline source map not found: {name}", {
name: name,
});
}
function parse_source_map(content) {
@@ -51,10 +73,10 @@ function to_json(cache) {
}
function minify(files, options) {
var warn_function = AST_Node.warn_function;
try {
options = defaults(options, {
compress: {},
enclose: false,
ie8: false,
keep_fnames: false,
mangle: {},
@@ -65,9 +87,12 @@ function minify(files, options) {
sourceMap: false,
timings: false,
toplevel: false,
validate: false,
warnings: false,
webkit: false,
wrap: false,
}, true);
if (options.validate) AST_Node.enable_validation();
var timings = options.timings && {
start: Date.now()
};
@@ -77,7 +102,7 @@ function minify(files, options) {
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" ]);
set_shorthand("webkit", options, [ "mangle", "output" ]);
var quoted_props;
if (options.mangle) {
options.mangle = defaults(options.mangle, {
@@ -88,6 +113,7 @@ function minify(files, options) {
properties: false,
reserved: [],
toplevel: false,
webkit: false,
}, true);
if (options.mangle.properties) {
if (typeof options.mangle.properties != "object") {
@@ -110,18 +136,17 @@ function minify(files, options) {
content: null,
filename: null,
includeSources: false,
names: true,
root: null,
url: null,
}, true);
}
var warnings = [];
if (options.warnings && !AST_Node.warn_function) {
AST_Node.warn_function = function(warning) {
warnings.push(warning);
};
}
if (options.warnings) AST_Node.log_function(function(warning) {
warnings.push(warning);
}, options.warnings == "verbose");
if (timings) timings.parse = Date.now();
var source_maps, toplevel;
var toplevel;
if (files instanceof AST_Toplevel) {
toplevel = files;
} else {
@@ -134,36 +159,41 @@ function minify(files, options) {
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);
if (source_map_content) options.sourceMap.orig = 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 (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;
options.parse.toplevel = toplevel = parse(files[name], options.parse);
if (source_map_content == "inline") {
var inlined_content = read_source_map(name, toplevel);
if (inlined_content) {
options.sourceMap.orig[name] = parse_source_map(inlined_content);
}
} else if (source_map_content) {
options.sourceMap.orig[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);
}
[ "enclose", "wrap" ].forEach(function(action) {
var option = options[action];
if (!option) return;
var orig = toplevel.print_to_string().slice(0, -1);
toplevel = toplevel[action](option);
files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
});
if (options.validate) toplevel.validate_ast();
if (timings) timings.rename = Date.now();
if (options.rename) {
toplevel.figure_out_scope(options.mangle);
toplevel.expand_names(options.mangle);
}
if (timings) timings.compress = Date.now();
if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
if (options.compress) {
toplevel = new Compressor(options.compress).compress(toplevel);
if (options.validate) toplevel.validate_ast();
}
if (timings) timings.scope = Date.now();
if (options.mangle) toplevel.figure_out_scope(options.mangle);
if (timings) timings.mangle = Date.now();
@@ -172,9 +202,7 @@ function minify(files, options) {
toplevel.mangle_names(options.mangle);
}
if (timings) timings.properties = Date.now();
if (options.mangle && options.mangle.properties) {
toplevel = mangle_properties(toplevel, options.mangle.properties);
}
if (options.mangle && options.mangle.properties) mangle_properties(toplevel, options.mangle.properties);
if (timings) timings.output = Date.now();
var result = {};
if (options.output.ast) {
@@ -182,19 +210,13 @@ function minify(files, options) {
}
if (!HOP(options.output, "code") || options.output.code) {
if (options.sourceMap) {
options.output.source_map = SourceMap({
file: options.sourceMap.filename,
orig: source_maps,
root: options.sourceMap.root
});
options.output.source_map = SourceMap(options.sourceMap);
if (options.sourceMap.includeSources) {
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]);
options.output.source_map.setSourceContent(name, files[name]);
}
} else {
options.output.source_map.get()._sourcesContents = null;
}
}
delete options.output.ast;
@@ -204,10 +226,14 @@ function minify(files, options) {
result.code = stream.get();
if (options.sourceMap) {
result.map = options.output.source_map.toString();
if (options.sourceMap.url == "inline") {
result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(result.map);
} else if (options.sourceMap.url) {
result.code += "\n//# sourceMappingURL=" + options.sourceMap.url;
var url = options.sourceMap.url;
if (url) {
result.code = result.code.replace(/\n\/\/# sourceMappingURL=\S+\s*$/, "");
if (url == "inline") {
result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(result.map);
} else {
result.code += "\n//# sourceMappingURL=" + url;
}
}
}
}
@@ -228,7 +254,7 @@ function minify(files, options) {
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;
@@ -237,6 +263,7 @@ function minify(files, options) {
} catch (ex) {
return { error: ex };
} finally {
AST_Node.warn_function = warn_function;
AST_Node.log_function();
AST_Node.disable_validation();
}
}

View File

@@ -1,7 +1,7 @@
/***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS2
https://github.com/mishoo/UglifyJS
-------------------------------- (C) ---------------------------------
@@ -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) {
@@ -114,13 +111,10 @@
var args = {
start : my_start_token(key),
end : my_end_token(M.value),
key : key.type == "Identifier" ? key.name : key.value,
key : "" + key[key.type == "Identifier" ? "name" : "value"],
value : from_moz(M.value)
};
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);
@@ -129,7 +123,7 @@
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);
})
});
@@ -138,7 +132,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)
})
@@ -215,7 +209,14 @@
end : my_end_token(M),
name : M.name
});
}
},
ThisExpression: function(M) {
return new AST_This({
start : my_start_token(M),
end : my_end_token(M),
name : "this",
});
},
};
MOZ_TO_ME.UpdateExpression =
@@ -248,7 +249,6 @@
map("VariableDeclarator", AST_VarDef, "id>name, init>value");
map("CatchClause", AST_Catch, "param>argname, body%body");
map("ThisExpression", AST_This);
map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
@@ -382,7 +382,7 @@
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
var key = {
type: "Literal",
value: M.key instanceof AST_SymbolAccessor ? M.key.name : M.key
value: M.key
};
var kind;
if (M instanceof AST_ObjectKeyVal) {
@@ -406,10 +406,14 @@
var def = M.definition();
return {
type: "Identifier",
name: def ? def.mangled_name || def.name : M.name
name: def && def.mangled_name || M.name
};
});
def_to_moz(AST_This, function To_Moz_ThisExpression() {
return { type: "ThisExpression" };
});
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
var flags = M.value.toString().match(/[gimuy]*$/)[0];
var value = "/" + M.value.raw_source + "/" + flags;
@@ -480,7 +484,7 @@
endpos : range ? range[0] : moznode.start,
raw : raw_token(moznode),
});
};
}
function my_end_token(moznode) {
var loc = moznode.loc, end = loc && loc.end;
@@ -495,7 +499,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";
@@ -507,7 +511,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];
@@ -550,7 +554,7 @@
);
MOZ_TO_ME[moztype] = moz_to_me;
def_to_moz(mytype, me_to_moz);
};
}
var FROM_MOZ_STACK = null;
@@ -559,9 +563,9 @@
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);
@@ -600,24 +604,24 @@
}
}
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);
@@ -628,5 +632,5 @@
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

@@ -1,7 +1,7 @@
/***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS2
https://github.com/mishoo/UglifyJS
-------------------------------- (C) ---------------------------------
@@ -43,7 +43,8 @@
"use strict";
function find_builtins(reserved) {
var builtins = function() {
var names = [];
// NaN will be included due to Number.NaN
[
"null",
@@ -53,46 +54,54 @@ 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(new ctor()).map(add);
Object.getOwnPropertyNames(ctor.prototype).map(add);
}
});
return makePredicate(names);
function add(name) {
push_uniq(reserved, name);
names.push(name);
}
}
}();
function reserve_quoted_keys(ast, reserved) {
function add(name) {
push_uniq(reserved, name);
}
ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ObjectKeyVal && node.quote) {
add(node.key);
if (node instanceof AST_ObjectProperty) {
if (node.start && node.start.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;
}));
if (node instanceof AST_Conditional) {
addStrings(node.consequent, add);
addStrings(node.alternative, add);
} else if (node instanceof AST_Sequence) {
addStrings(node.tail_node(), add);
} else if (node instanceof AST_String) {
add(node.value);
}
}
function mangle_properties(ast, options) {
@@ -101,21 +110,21 @@ function mangle_properties(ast, options) {
cache: null,
debug: false,
keep_quoted: false,
only_cache: false,
regex: null,
reserved: null,
}, true);
var reserved = options.reserved;
if (!Array.isArray(reserved)) reserved = [];
if (!options.builtins) find_builtins(reserved);
var reserved = Object.create(options.builtins ? null : builtins);
if (Array.isArray(options.reserved)) options.reserved.forEach(function(name) {
reserved[name] = true;
});
var cname = -1;
var cache;
if (options.cache) {
cache = options.cache.props;
cache.each(function(mangled_name) {
push_uniq(reserved, mangled_name);
cache.each(function(name) {
reserved[name] = true;
});
} else {
cache = new Dictionary();
@@ -127,126 +136,119 @@ function mangle_properties(ast, options) {
// 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 names_to_mangle = Object.create(null);
var unmangleable = Object.create(reserved);
// step 1: find candidates to mangle
ast.walk(new TreeWalker(function(node){
if (node instanceof AST_ObjectKeyVal) {
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) {
ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_Binary) {
if (node.operator == "in") addStrings(node.left, add);
} else if (node.TYPE == "Call") {
var exp = node.expression;
if (exp instanceof AST_Dot) switch (exp.property) {
case "defineProperty":
case "getOwnPropertyDescriptor":
if (node.args.length < 2) break;
exp = exp.expression;
if (!(exp instanceof AST_SymbolRef)) break;
if (exp.name != "Object") break;
if (!exp.definition().undeclared) break;
addStrings(node.args[1], add);
break;
case "hasOwnProperty":
if (node.args.length < 1) break;
addStrings(node.args[0], add);
break;
}
} else if (node instanceof AST_Dot) {
add(node.property);
}
else if (node instanceof AST_Sub) {
} else if (node instanceof AST_ObjectProperty) {
if (typeof node.key == "string") add(node.key);
} 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){
if (node instanceof AST_ObjectKeyVal) {
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) {
// step 2: renaming properties
ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_Binary) {
if (node.operator == "in") mangleStrings(node.left);
} else if (node.TYPE == "Call") {
var exp = node.expression;
if (exp instanceof AST_Dot) switch (exp.property) {
case "defineProperty":
case "getOwnPropertyDescriptor":
if (node.args.length < 2) break;
exp = exp.expression;
if (!(exp instanceof AST_SymbolRef)) break;
if (exp.name != "Object") break;
if (!exp.definition().undeclared) break;
mangleStrings(node.args[1]);
break;
case "hasOwnProperty":
if (node.args.length < 1) break;
mangleStrings(node.args[0]);
break;
}
} 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_ObjectProperty) {
if (typeof node.key == "string") node.key = mangle(node.key);
} else if (node instanceof AST_Sub) {
if (!options.keep_quoted) mangleStrings(node.property);
}
}));
// only function declarations after this line
function can_mangle(name) {
if (unmangleable.indexOf(name) >= 0) return false;
if (reserved.indexOf(name) >= 0) return false;
if (options.only_cache) {
return cache.has(name);
}
if (unmangleable[name]) return false;
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
return true;
}
function should_mangle(name) {
if (reserved[name]) return false;
if (regex && !regex.test(name)) return false;
if (reserved.indexOf(name) >= 0) return false;
return cache.has(name)
|| names_to_mangle.indexOf(name) >= 0;
return cache.has(name) || names_to_mangle[name];
}
function add(name) {
if (can_mangle(name))
push_uniq(names_to_mangle, name);
if (!should_mangle(name)) {
push_uniq(unmangleable, name);
}
if (can_mangle(name)) names_to_mangle[name] = true;
if (!should_mangle(name)) unmangleable[name] = true;
}
function mangle(name) {
if (!should_mangle(name)) {
return 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)) {
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) {
do {
mangled = base54(++cname);
} while (!can_mangle(mangled));
}
if (!mangled) do {
mangled = base54(++cname);
} while (!can_mangle(mangled));
cache.set(name, mangled);
}
return mangled;
}
function mangleStrings(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) {
node.value = mangle(node.value);
}
else if (node instanceof AST_Conditional) {
node.consequent = mangleStrings(node.consequent);
node.alternative = mangleStrings(node.alternative);
}
return node;
}));
if (node instanceof AST_Sequence) {
mangleStrings(node.expressions.tail_node());
} else if (node instanceof AST_String) {
node.value = mangle(node.value);
} else if (node instanceof AST_Conditional) {
mangleStrings(node.consequent);
mangleStrings(node.alternative);
}
}
}

View File

@@ -1,7 +1,7 @@
/***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS2
https://github.com/mishoo/UglifyJS
-------------------------------- (C) ---------------------------------
@@ -43,43 +43,36 @@
"use strict";
function SymbolDef(scope, orig, init) {
function SymbolDef(id, scope, orig, init) {
this.eliminated = 0;
this.global = false;
this.id = id;
this.init = init;
this.lambda = orig instanceof AST_SymbolLambda;
this.mangled_name = null;
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.scope = scope;
this.undeclared = false;
this.id = SymbolDef.next_id++;
}
SymbolDef.next_id = 1;
SymbolDef.prototype = {
unmangleable: function(options) {
if (!options) options = {};
return (this.global && !options.toplevel)
|| this.undeclared
|| (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
|| (options.keep_fnames
&& (this.orig[0] instanceof AST_SymbolLambda
|| this.orig[0] instanceof AST_SymbolDefun));
forEach: function(fn) {
this.orig.forEach(fn);
this.references.forEach(fn);
},
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 def;
if (def = this.redefined()) {
var def = this.redefined();
if (def) {
this.mangled_name = def.mangled_name || def.name;
} else {
this.mangled_name = next_mangled_name(this.scope, options, this);
this.mangled_name = next_mangled_name(this, options);
}
if (this.global && cache) {
cache.set(this.name, this.mangled_name);
@@ -87,11 +80,29 @@ SymbolDef.prototype = {
}
},
redefined: function() {
return this.defun && this.defun.variables.get(this.name);
}
var scope = this.defun;
if (!scope) return;
var name = this.name;
var def = scope.variables.get(name)
|| scope instanceof AST_Toplevel && scope.globals.get(name)
|| this.orig[0] instanceof AST_SymbolConst && find_if(function(def) {
return def.name == name;
}, scope.enclosed);
if (def && def !== this) return def.redefined() || def;
},
unmangleable: function(options) {
return this.global && !options.toplevel
|| this.undeclared
|| !options.eval && this.scope.pinned()
|| options.keep_fnames
&& (this.orig[0] instanceof AST_SymbolLambda
|| this.orig[0] instanceof AST_SymbolDefun);
},
};
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
var unary_side_effects = makePredicate("delete ++ --");
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
options = defaults(options, {
cache: null,
ie8: false,
@@ -99,31 +110,46 @@ 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 defun = null;
var tw = new TreeWalker(function(node, descend){
if (node instanceof AST_Catch) {
var save_scope = scope;
scope = new AST_Scope(node);
scope.init_scope_vars(save_scope);
descend();
scope = save_scope;
var next_def_id = 0;
var scope = self.parent_scope = null;
var tw = new TreeWalker(function(node, descend) {
if (is_defun(node)) {
node.name.walk(tw);
walk_scope(function() {
node.argnames.forEach(function(argname) {
argname.walk(tw);
});
walk_body(node, tw);
});
return true;
}
if (node instanceof AST_Scope) {
node.init_scope_vars(scope);
var save_scope = scope;
var save_defun = defun;
defun = scope = node;
if (node instanceof AST_SwitchBranch) {
node.init_vars(scope);
descend();
scope = save_scope;
defun = save_defun;
return true; // don't descend again in TreeWalker
return true;
}
if (node instanceof AST_Try) {
walk_scope(function() {
walk_body(node, tw);
});
if (node.bcatch) node.bcatch.walk(tw);
if (node.bfinally) node.bfinally.walk(tw);
return true;
}
if (node instanceof AST_With) {
for (var s = scope; s; s = s.parent_scope)
var s = scope;
do {
s = s.resolve();
if (s.uses_with) break;
s.uses_with = true;
return;
} while (s = s.parent_scope);
walk_scope(descend);
return true;
}
if (node instanceof AST_BlockScope) {
walk_scope(descend);
return true;
}
if (node instanceof AST_Symbol) {
node.scope = scope;
@@ -132,97 +158,205 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
node.thedef = node;
node.references = [];
}
if (node instanceof AST_SymbolLambda) {
defun.def_function(node, node.name == "arguments" ? undefined : defun);
}
else if (node instanceof AST_SymbolDefun) {
// Careful here, the scope where this should be defined is
// 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, defun);
}
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);
}
}
else if (node instanceof AST_SymbolCatch) {
if (node instanceof AST_SymbolCatch) {
scope.def_variable(node).defun = defun;
} else if (node instanceof AST_SymbolConst) {
scope.def_variable(node).defun = defun;
} else if (node instanceof AST_SymbolDefun) {
defun.def_function(node, tw.parent());
entangle(defun, scope);
} else if (node instanceof AST_SymbolFunarg) {
defun.def_variable(node);
entangle(defun, scope);
} 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_SymbolLet) {
scope.def_variable(node);
} else if (node instanceof AST_SymbolVar) {
defun.def_variable(node, null);
entangle(defun, scope);
}
function walk_scope(descend) {
node.init_vars(scope);
var save_defun = defun;
var save_scope = scope;
if (node instanceof AST_Scope) defun = node;
scope = node;
descend();
scope = save_scope;
defun = save_defun;
}
function entangle(defun, scope) {
if (defun === scope) return;
node.mark_enclosed(options);
var def = scope.find_variable(node.name);
if (node.thedef === def) return;
node.thedef = def;
def.orig.push(node);
node.mark_enclosed(options);
}
});
self.make_def = function(orig, init) {
return new SymbolDef(++next_def_id, this, orig, init);
};
self.walk(tw);
// pass 2: find back references and eval
self.globals = new Dictionary();
var tw = new TreeWalker(function(node, descend){
if (node instanceof AST_LoopControl && node.label) {
node.label.thedef.references.push(node);
var in_arg = [];
var tw = new TreeWalker(function(node) {
if (node instanceof AST_Catch) {
if (!(node.argname instanceof AST_Destructured)) return;
in_arg.push(node);
node.argname.walk(tw);
in_arg.pop();
walk_body(node, tw);
return true;
}
if (node instanceof AST_Lambda) {
in_arg.push(node);
node.argnames.forEach(function(argname) {
argname.walk(tw);
});
in_arg.pop();
if (node instanceof AST_Arrow && node.value) {
node.value.walk(tw);
} else {
walk_body(node, tw);
}
return true;
}
if (node instanceof AST_LoopControl) {
if (node.label) node.label.thedef.references.push(node);
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;
}
// ensure compression works if `const` reuses a scope variable
if (node instanceof AST_SymbolConst) {
var redef = node.definition().redefined();
if (redef) redef.const_redefs = true;
return true;
}
if (node instanceof AST_SymbolRef) {
var name = node.name;
if (name == "eval" && tw.parent() instanceof AST_Call) {
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
s.uses_eval = true;
}
}
var sym = node.scope.find_variable(name);
for (var i = in_arg.length; i > 0 && sym;) {
i = in_arg.lastIndexOf(sym.scope, i - 1);
if (i < 0) break;
var decl = sym.orig[0];
if (decl instanceof AST_SymbolCatch
|| decl instanceof AST_SymbolFunarg
|| decl instanceof AST_SymbolLambda) {
node.in_arg = true;
break;
}
sym = sym.scope.parent_scope.find_variable(name);
}
if (!sym) {
sym = self.def_global(node);
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
sym.scope.uses_arguments = true;
} else if (name == "arguments"
&& sym.orig[0] instanceof AST_SymbolFunarg
&& !(sym.orig[1] instanceof AST_SymbolFunarg)
&& !(sym.scope instanceof AST_Arrow)) {
var parent = tw.parent();
if (parent instanceof AST_Assign && parent.left === node
|| parent instanceof AST_Unary && unary_side_effects[parent.operator]) {
sym.scope.uses_arguments = 3;
} else if (sym.scope.uses_arguments < 2
&& !(parent instanceof AST_PropAccess && parent.expression === node)) {
sym.scope.uses_arguments = 2;
} else if (!sym.scope.uses_arguments) {
sym.scope.uses_arguments = true;
}
}
if (name == "eval") {
var parent = tw.parent();
if (parent.TYPE == "Call" && parent.expression === node) {
var s = node.scope;
do {
s = s.resolve();
if (s.uses_eval) break;
s.uses_eval = true;
} while (s = s.parent_scope);
} else if (sym.undeclared) {
self.uses_eval = true;
}
}
node.thedef = sym;
node.reference(options);
return true;
}
// ensure mangling works if catch reuses a scope variable
var def;
if (node instanceof AST_SymbolCatch && (def = node.definition().redefined())) {
var s = node.scope;
while (s) {
push_uniq(s.enclosed, def);
if (s === def.scope) break;
s = s.parent_scope;
}
}
});
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;
node.reference(options);
return true;
if (options.ie8) self.walk(new TreeWalker(function(node) {
if (node instanceof AST_SymbolCatch) {
var scope = node.thedef.defun;
if (scope.name instanceof AST_SymbolLambda && scope.name.name == node.name) {
scope = scope.parent_scope.resolve();
}
}));
redefine(node, scope);
return true;
}
if (node instanceof AST_SymbolLambda) {
var def = node.thedef;
redefine(node, node.scope.parent_scope.resolve());
if (typeof node.thedef.init !== "undefined") {
node.thedef.init = false;
} else if (def.init) {
node.thedef.init = def.init;
}
return true;
}
}));
function redefine(node, scope) {
var name = node.name;
var old_def = node.thedef;
if (!all(old_def.orig, function(sym) {
return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet);
})) return;
var new_def = scope.find_variable(name);
if (new_def) {
var redef = new_def.redefined();
if (redef) new_def = redef;
} else {
new_def = self.globals.get(name);
}
if (new_def) {
new_def.orig.push(node);
} else {
new_def = scope.def_variable(node);
}
old_def.defun = new_def.scope;
old_def.forEach(function(node) {
node.redef = true;
node.thedef = new_def;
node.reference(options);
});
if (old_def.lambda) new_def.lambda = true;
if (new_def.undeclared) self.variables.set(name, new_def);
}
});
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, node);
var g = this.make_def(node);
g.undeclared = true;
g.global = true;
globals.set(name, g);
@@ -230,30 +364,43 @@ AST_Toplevel.DEFMETHOD("def_global", function(node){
}
});
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
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
this.parent_scope = parent_scope; // the parent scope
this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
this.cname = -1; // the current index for mangling functions/variables
});
function init_block_vars(scope, parent) {
scope.enclosed = []; // variables from this or outer scope(s) that are referenced from this or inner scopes
scope.parent_scope = parent; // the parent scope (null if this is the top level)
scope.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
scope.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
if (parent) scope.make_def = parent.make_def; // top-level tracking of SymbolDef instances
}
AST_Lambda.DEFMETHOD("init_scope_vars", function(){
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
function init_scope_vars(scope, parent) {
init_block_vars(scope, parent);
scope.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
scope.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
}
AST_BlockScope.DEFMETHOD("init_vars", function(parent_scope) {
init_block_vars(this, parent_scope);
});
AST_Scope.DEFMETHOD("init_vars", function(parent_scope) {
init_scope_vars(this, parent_scope);
});
AST_Arrow.DEFMETHOD("init_vars", function(parent_scope) {
init_scope_vars(this, parent_scope);
});
AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) {
init_scope_vars(this, parent_scope);
this.uses_arguments = false;
this.def_variable(new AST_SymbolFunarg({
name: "arguments",
start: this.start,
end: this.end
end: this.end,
}));
return this;
});
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) {
@@ -261,7 +408,6 @@ AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
});
}
if (s === def.scope) break;
s = s.parent_scope;
}
});
@@ -270,28 +416,25 @@ AST_Symbol.DEFMETHOD("reference", function(options) {
this.mark_enclosed(options);
});
AST_Scope.DEFMETHOD("find_variable", function(name){
if (name instanceof AST_Symbol) name = name.name;
AST_BlockScope.DEFMETHOD("find_variable", function(name) {
return this.variables.get(name)
|| (this.parent_scope && this.parent_scope.find_variable(name));
|| this.parent_scope && this.parent_scope.find_variable(name);
});
AST_Scope.DEFMETHOD("def_function", function(symbol, init){
AST_BlockScope.DEFMETHOD("def_function", function(symbol, init) {
var def = this.def_variable(symbol, init);
if (!def.init || def.init instanceof AST_Defun) def.init = init;
if (!def.init || is_defun(def.init)) def.init = init;
this.functions.set(symbol.name, def);
return def;
});
AST_Scope.DEFMETHOD("def_variable", function(symbol, init){
AST_BlockScope.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;
}
if (is_function(def.init)) def.init = init;
} else {
def = new SymbolDef(this, symbol, init);
def = this.make_def(symbol, init);
this.variables.set(symbol.name, def);
def.global = !this.parent_scope;
}
@@ -301,29 +444,27 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init){
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 = -1;
scope.cname_holes = [];
scope.names_in_use = names = Object.create(null);
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) {
function next_mangled_name(def, options) {
var scope = def.scope;
var in_use = names_in_use(scope, options);
var holes = scope.cname_holes;
var names = Object.create(null);
// #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
if (scope instanceof AST_Function && scope.name && def.orig[0] instanceof AST_SymbolFunarg) {
var tricky_def = scope.name.definition();
// the function's mangled_name is null when keep_fnames is true
names[tricky_def.mangled_name || tricky_def.name] = true;
}
var scopes = [ scope ];
def.references.forEach(function(sym) {
def.forEach(function(sym) {
var scope = sym.scope;
do {
if (scopes.indexOf(scope) < 0) {
@@ -335,27 +476,24 @@ function next_mangled_name(scope, options, def) {
} while (scope = scope.parent_scope);
});
var name;
for (var i = 0, len = holes.length; i < len; i++) {
for (var i = 0; i < holes.length; i++) {
name = base54(holes[i]);
if (names[name]) continue;
holes.splice(i, 1);
scope.names_in_use[name] = true;
in_use[name] = true;
return name;
}
while (true) {
name = base54(++scope.cname);
if (in_use[name] || !is_identifier(name) || options.reserved.has[name]) continue;
if (in_use[name] || RESERVED_WORDS[name] || options.reserved.has[name]) continue;
if (!names[name]) break;
holes.push(scope.cname);
}
scope.names_in_use[name] = true;
if (options.ie8 && def.orig[0] instanceof AST_SymbolLambda) {
names_in_use(scope.parent_scope, options)[name] = true;
}
in_use[name] = true;
return name;
}
AST_Symbol.DEFMETHOD("unmangleable", function(options){
AST_Symbol.DEFMETHOD("unmangleable", function(options) {
var def = this.definition();
return !def || def.unmangleable(options);
});
@@ -363,19 +501,10 @@ AST_Symbol.DEFMETHOD("unmangleable", function(options){
// labels are always mangleable
AST_Label.DEFMETHOD("unmangleable", return_false);
AST_Symbol.DEFMETHOD("unreferenced", function(){
return this.definition().references.length == 0
&& !(this.scope.uses_eval || this.scope.uses_with);
});
AST_Symbol.DEFMETHOD("definition", function(){
AST_Symbol.DEFMETHOD("definition", function() {
return this.thedef;
});
AST_Symbol.DEFMETHOD("global", function(){
return this.definition().global;
});
function _default_mangler_options(options) {
options = defaults(options, {
eval : false,
@@ -383,6 +512,7 @@ function _default_mangler_options(options) {
keep_fnames : false,
reserved : [],
toplevel : false,
webkit : false,
});
if (!Array.isArray(options.reserved)) options.reserved = [];
// Never mangle arguments
@@ -391,7 +521,7 @@ function _default_mangler_options(options) {
return options;
}
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
options = _default_mangler_options(options);
// We only need to mangle declaration nodes. Special logic wired
@@ -401,53 +531,61 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
var lname = -1;
if (options.cache && options.cache.props) {
var mangled_names = this.mangled_names = Object.create(null);
var mangled_names = names_in_use(this, options);
options.cache.props.each(function(mangled_name) {
mangled_names[mangled_name] = true;
});
}
var redefined = [];
var tw = new TreeWalker(function(node, descend){
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) {
if (node instanceof AST_BlockScope) {
if (options.webkit && node instanceof AST_IterationStatement && node.init instanceof AST_Let) {
node.init.definitions.forEach(function(defn) {
defn.name.match_symbol(function(sym) {
if (!(sym instanceof AST_SymbolLet)) return;
var def = sym.definition();
var scope = sym.scope.parent_scope;
var redef = scope.def_variable(sym);
sym.thedef = def;
scope.to_mangle.push(redef);
def.redefined = function() {
return redef;
};
});
}, true);
}
node.to_mangle = [];
node.variables.each(function(def) {
if (!defer_redef(def)) node.to_mangle.push(def);
});
descend();
if (options.cache && node instanceof AST_Toplevel) {
node.globals.each(mangle);
}
node.variables.each(mangle);
if (node instanceof AST_Defun && tw.has_directive("use asm")) {
var sym = new AST_SymbolRef(node.name);
sym.scope = node;
sym.reference(options);
}
node.to_mangle.forEach(mangle);
return true;
}
if (node instanceof AST_Label) {
var name;
do name = base54(++lname); while (!is_identifier(name));
do {
name = base54(++lname);
} while (RESERVED_WORDS[name]);
node.mangled_name = name;
return true;
}
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);
redefined.forEach(mangle);
@@ -456,16 +594,37 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
if (options.reserved.has[def.name]) return;
def.mangle(options);
}
function defer_redef(def) {
var sym = def.orig[0];
var redef = def.redefined();
if (!redef) {
if (!(sym instanceof AST_SymbolConst)) return false;
var scope = def.scope.resolve();
if (def.scope === scope) return false;
redef = scope.def_variable(sym);
scope.to_mangle.push(redef);
}
redefined.push(def);
def.references.forEach(reference);
if (sym instanceof AST_SymbolCatch || sym instanceof AST_SymbolConst) reference(sym);
return true;
function reference(sym) {
sym.thedef = redef;
sym.reference(options);
sym.thedef = def;
}
}
});
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
var cache = options.cache && options.cache.props;
var avoid = Object.create(null);
var avoid = Object.create(RESERVED_WORDS);
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());
if (node instanceof AST_BlockScope) node.variables.each(add_def);
}));
return avoid;
@@ -489,15 +648,14 @@ AST_Toplevel.DEFMETHOD("expand_names", function(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());
if (node instanceof AST_BlockScope) node.variables.each(rename);
}));
function next_name() {
var name;
do {
name = base54(cname++);
} while (avoid[name] || !is_identifier(name));
} while (avoid[name]);
return name;
}
@@ -505,13 +663,11 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
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;
var redef = def.redefined();
var name = redef ? redef.rename || redef.name : next_name();
def.rename = name;
def.forEach(function(sym) {
if (sym.definition() === def) sym.name = name;
});
}
});
@@ -521,25 +677,27 @@ AST_Sequence.DEFMETHOD("tail_node", function() {
return this.expressions[this.expressions.length - 1];
});
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
options = _default_mangler_options(options);
base54.reset();
var fn = AST_Symbol.prototype.add_source_map;
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);
}
}
AST_Symbol.prototype.add_source_map = function() {
if (!this.unmangleable(options)) base54.consider(this.name, -1);
};
if (options.properties) {
AST_Dot.prototype.add_source_map = function() {
base54.consider(this.property, -1);
};
AST_Sub.prototype.add_source_map = function() {
skip_string(this.property);
};
}
base54.consider(this.print_to_string(), 1);
} finally {
AST_Node.prototype.print = AST_Node.prototype._print;
AST_Symbol.prototype.add_source_map = fn;
delete AST_Dot.prototype.add_source_map;
delete AST_Sub.prototype.add_source_map;
}
base54.sort();
@@ -559,7 +717,7 @@ var base54 = (function() {
var freq = Object.create(null);
function init(chars) {
var array = [];
for (var i = 0, len = chars.length; i < len; i++) {
for (var i = 0; i < chars.length; i++) {
var ch = chars[i];
array.push(ch);
freq[ch] = -1e-2 * i;

View File

@@ -1,7 +1,7 @@
/***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS2
https://github.com/mishoo/UglifyJS
-------------------------------- (C) ---------------------------------
@@ -43,55 +43,149 @@
"use strict";
// a small wrapper around fitzgen's source-map library
function SourceMap(options) {
options = defaults(options, {
file : null,
root : null,
orig : null,
var vlq_char = characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
var vlq_bits = vlq_char.reduce(function(map, ch, bits) {
map[ch] = bits;
return map;
}, Object.create(null));
orig_line_diff : 0,
dest_line_diff : 0,
function vlq_decode(indices, str) {
var value = 0;
var shift = 0;
for (var i = 0, j = 0; i < str.length; i++) {
var bits = vlq_bits[str[i]];
value += (bits & 31) << shift;
if (bits & 32) {
shift += 5;
} else {
indices[j++] += value & 1 ? 0x80000000 | -(value >> 1) : value >> 1;
value = shift = 0;
}
}
return j;
}
function vlq_encode(num) {
var result = "";
num = Math.abs(num) << 1 | num >>> 31;
do {
var bits = num & 31;
if (num >>>= 5) bits |= 32;
result += vlq_char[bits];
} while (num);
return result;
}
function create_array_map() {
var map = Object.create(null);
var array = [];
array.index = function(name) {
if (!HOP(map, name)) {
map[name] = array.length;
array.push(name);
}
return map[name];
};
return array;
}
function SourceMap(options) {
var sources = create_array_map();
var sources_content = options.includeSources && Object.create(null);
var names = create_array_map();
var mappings = "";
if (options.orig) Object.keys(options.orig).forEach(function(name) {
var map = options.orig[name];
var indices = [ 0, 0, 1, 0, 0 ];
options.orig[name] = {
names: map.names,
mappings: map.mappings.split(/;/).map(function(line) {
indices[0] = 0;
return line.split(/,/).map(function(segment) {
return indices.slice(0, vlq_decode(indices, segment));
});
}),
sources: map.sources,
};
if (!sources_content || !map.sourcesContent) return;
for (var i = 0; i < map.sources.length; i++) {
var content = map.sourcesContent[i];
if (content) sources_content[map.sources[i]] = content;
}
});
var generator = new MOZ_SourceMap.SourceMapGenerator({
file : options.file,
sourceRoot : options.root
});
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);
var prev_source;
var generated_line = 1;
var generated_column = 0;
var source_index = 0;
var original_line = 1;
var original_column = 0;
var name_index = 0;
return {
add: options.orig ? function(source, gen_line, gen_col, orig_line, orig_col, name) {
var map = options.orig[source];
if (map) {
var segments = map.mappings[orig_line - 1];
if (!segments) return;
var indices;
for (var i = 0; i < segments.length; i++) {
var col = segments[i][0];
if (orig_col >= col) indices = segments[i];
if (orig_col <= col) break;
}
if (!indices || indices.length < 4) {
source = null;
} else {
source = map.sources[indices[1]];
orig_line = indices[2];
orig_col = indices[3];
if (indices.length > 4) name = map.names[indices[4]];
}
}
add(source, gen_line, gen_col, orig_line, orig_col, name);
} : add,
setSourceContent: sources_content ? function(source, content) {
sources_content[source] = content;
} : noop,
toString: function() {
return JSON.stringify({
version: 3,
file: options.filename || undefined,
sourceRoot: options.root || undefined,
sources: sources,
sourcesContent: sources_content ? sources.map(function(source) {
return sources_content[source] || null;
}) : undefined,
names: names,
mappings: mappings,
});
}
maps[source] = map;
}
};
function add(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;
if (prev_source == null && source == null) return;
prev_source = source;
if (generated_line < gen_line) {
generated_column = 0;
do {
mappings += ";";
} while (++generated_line < gen_line);
} else if (mappings) {
mappings += ",";
}
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
});
};
return {
add : add,
get : function() { return generator },
toString : function() { return JSON.stringify(generator.toJSON()); }
};
};
mappings += vlq_encode(gen_col - generated_column);
generated_column = gen_col;
if (source == null) return;
var src_idx = sources.index(source);
mappings += vlq_encode(src_idx - source_index);
source_index = src_idx;
mappings += vlq_encode(orig_line - original_line);
original_line = orig_line;
mappings += vlq_encode(orig_col - original_column);
original_column = orig_col;
if (options.names && name != null) {
var name_idx = names.index(name);
mappings += vlq_encode(name_idx - name_index);
name_index = name_idx;
}
}
}

View File

@@ -1,7 +1,7 @@
/***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS2
https://github.com/mishoo/UglifyJS
-------------------------------- (C) ---------------------------------
@@ -43,8 +43,6 @@
"use strict";
// Tree transformer helpers.
function TreeTransformer(before, after) {
TreeWalker.call(this);
this.before = before;
@@ -52,168 +50,161 @@ 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) {
x = this;
descend(x, tw);
if (tw.after) {
y = tw.after(x, in_list);
if (y !== undefined) x = y;
}
}
tw.pop();
return x;
});
};
(function(DEF) {
function do_list(list, tw) {
return MAP(list, function(node){
return List(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_Do, function(self, tw){
DEF(AST_Do, function(self, tw) {
self.body = self.body.transform(tw);
self.condition = self.condition.transform(tw);
});
_(AST_While, function(self, 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){
self.argname = self.argname.transform(tw);
DEF(AST_Catch, function(self, tw) {
if (self.argname) 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_Arrow, function(self, tw) {
self.argnames = do_list(self.argnames, tw);
if (self.value) {
self.value = self.value.transform(tw);
} else {
self.body = do_list(self.body, 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_Await, function(self, tw) {
self.expression = self.expression.transform(tw);
});
_(AST_Sub, function(self, tw){
DEF(AST_Dot, function(self, tw) {
self.expression = self.expression.transform(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_Spread, function(self, tw) {
self.expression = self.expression.transform(tw);
});
_(AST_Binary, function(self, tw){
DEF(AST_Unary, function(self, tw) {
self.expression = self.expression.transform(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){
self.properties = do_list(self.properties, tw);
DEF(AST_DestructuredArray, function(self, tw) {
self.elements = do_list(self.elements, tw);
});
_(AST_ObjectProperty, function(self, tw){
DEF(AST_DestructuredKeyVal, function(self, tw) {
if (self.key instanceof AST_Node) self.key = self.key.transform(tw);
self.value = self.value.transform(tw);
});
})();
DEF(AST_DestructuredObject, function(self, tw) {
self.properties = do_list(self.properties, tw);
});
DEF(AST_Object, function(self, tw) {
self.properties = do_list(self.properties, tw);
});
DEF(AST_ObjectProperty, function(self, tw) {
if (self.key instanceof AST_Node) self.key = self.key.transform(tw);
self.value = self.value.transform(tw);
});
})(function(node, descend) {
node.DEFMETHOD("transform", function(tw, in_list) {
var x, y;
tw.push(this);
if (tw.before) x = tw.before(this, descend, in_list);
if (typeof x === "undefined") {
x = this;
descend(x, tw);
if (tw.after) {
y = tw.after(x, in_list);
if (typeof y !== "undefined") x = y;
}
}
tw.pop();
return x;
});
});

View File

@@ -1,7 +1,7 @@
/***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS2
https://github.com/mishoo/UglifyJS
-------------------------------- (C) ---------------------------------
@@ -52,9 +52,7 @@ function member(name, array) {
}
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) {
@@ -72,7 +70,7 @@ function configure_error_stack(fn) {
err.name = this.name;
try {
throw err;
} catch(e) {
} catch (e) {
return e.stack;
}
}
@@ -89,15 +87,13 @@ DefaultsError.prototype.name = "DefaultsError";
configure_error_stack(DefaultsError);
function defaults(args, defs, croak) {
if (args === true) args = {};
var ret = args || {};
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
throw new DefaultsError("`" + i + "` is not a supported option", defs);
if (croak) for (var i in args) {
if (HOP(args, 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];
for (var i in args) {
if (HOP(args, i)) defs[i] = args[i];
}
return ret;
return defs;
}
function merge(obj, ext) {
@@ -115,69 +111,47 @@ function return_true() { return true; }
function return_this() { return this; }
function return_null() { return null; }
var MAP = (function(){
function MAP(a, f, backwards) {
var ret = [], top = [], i;
function doit() {
var List = (function() {
function List(a, f) {
var ret = [];
for (var i = 0; i < a.length; i++) {
var val = f(a[i], i);
var is_last = val instanceof Last;
if (is_last) val = val.v;
if (val instanceof AtTop) {
val = val.v;
if (val instanceof Splice) {
top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
} else {
top.push(val);
}
}
else if (val !== skip) {
if (val instanceof Splice) {
ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
} else {
ret.push(val);
}
}
return is_last;
};
if (Array.isArray(a)) {
if (backwards) {
for (i = a.length; --i >= 0;) if (doit()) break;
ret.reverse();
top.reverse();
if (val === skip) continue;
if (val instanceof Splice) {
ret.push.apply(ret, val.v);
} else {
for (i = 0; i < a.length; ++i) if (doit()) break;
ret.push(val);
}
}
else {
for (i in a) if (HOP(a, i)) if (doit()) break;
}
return top.concat(ret);
return ret;
}
List.is_op = function(val) {
return val === skip || val instanceof Splice;
};
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 };
return MAP;
List.splice = function(val) {
return new Splice(val);
};
var skip = List.skip = {};
function Splice(val) {
this.v = val;
}
return List;
})();
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 props && props[p];
return text.replace(/\{([^}]+)\}/g, function(str, p) {
var value = props[p];
return value instanceof AST_Node ? value.print_to_string() : value;
});
}
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 makePredicate(words) {
@@ -191,7 +165,7 @@ function makePredicate(words) {
function all(array, predicate) {
for (var i = array.length; --i >= 0;)
if (!predicate(array[i]))
if (!predicate(array[i], i))
return false;
return true;
}
@@ -223,6 +197,12 @@ Dictionary.prototype = {
return this;
},
has: function(key) { return ("$" + key) in this._values },
all: function(predicate) {
for (var i in this._values)
if (!predicate(this._values[i], i.substr(1)))
return false;
return true;
},
each: function(f) {
for (var i in this._values)
f(this._values[i], i.substr(1));
@@ -258,13 +238,15 @@ function HOP(obj, prop) {
// return true if the node at the top of the stack (that means the
// innermost node in the current output) is lexically the first in
// a statement.
function first_in_statement(stack) {
function first_in_statement(stack, arrow) {
var node = stack.parent(-1);
for (var i = 0, p; p = stack.parent(i++); node = p) {
if (p.TYPE == "Call") {
if (p.expression === node) continue;
if (p instanceof AST_Arrow) {
return arrow && p.value === node;
} else if (p instanceof AST_Binary) {
if (p.left === node) continue;
} else if (p.TYPE == "Call") {
if (p.expression === node) continue;
} else if (p instanceof AST_Conditional) {
if (p.condition === node) continue;
} else if (p instanceof AST_PropAccess) {

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.3.24",
"version": "3.12.3",
"engines": {
"node": ">=0.8.0"
},
@@ -11,7 +11,7 @@
"Alex Lam <alexlamsl@gmail.com>",
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
],
"repository": "mishoo/UglifyJS2",
"repository": "mishoo/UglifyJS",
"main": "tools/node.js",
"bin": {
"uglifyjs": "bin/uglifyjs"
@@ -22,17 +22,12 @@
"tools",
"LICENSE"
],
"dependencies": {
"commander": "~2.15.0",
"source-map": "~0.6.1"
},
"devDependencies": {
"acorn": "~5.5.3",
"mocha": "~3.5.1",
"semver": "~5.5.0"
"acorn": "~7.1.0",
"semver": "~6.3.0"
},
"scripts": {
"test": "node test/run-tests.js"
"test": "node test/compress.js && node test/mocha.js"
},
"keywords": [
"cli",

View File

@@ -5,23 +5,22 @@
var createHash = require("crypto").createHash;
var fetch = require("./fetch");
var fork = require("child_process").fork;
var spawn = require("child_process").spawn;
var zlib = require("zlib");
var args = process.argv.slice(2);
if (!args.length) {
args.push("-mc");
}
if (!args.length) args.push("-mc");
args.unshift("bin/uglifyjs");
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",
"https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.9.0/math.js",
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
"https://code.jquery.com/jquery-3.4.1.js",
"https://code.angularjs.org/1.7.8/angular.js",
"https://unpkg.com/mathjs@6.2.3/dist/math.js",
"https://unpkg.com/react@15.3.2/dist/react.js",
"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",
"https://cdnjs.cloudflare.com/ajax/libs/d3/5.12.0/d3.js",
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
"https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js",
"https://cdnjs.cloudflare.com/ajax/libs/ember.js/2.12.2/ember.prod.js",
"https://raw.githubusercontent.com/kangax/html-minifier/v4.0.0/dist/htmlminifier.js",
];
var results = {};
var remaining = 2 * urls.length;
@@ -70,18 +69,20 @@ urls.forEach(function(url) {
};
fetch(url, function(err, res) {
if (err) throw err;
var uglifyjs = fork("bin/uglifyjs", args, { silent: true });
var uglifyjs = spawn(process.argv[0], args, { silent: true });
res.on("data", function(data) {
results[url].input += data.length;
}).pipe(uglifyjs.stdin);
var sha1 = createHash("sha1");
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");
sha1.update(data);
}).on("end", function() {
results[url].sha1 = sha1.digest("hex");
done();
});
uglifyjs.stderr.setEncoding("utf8");

460
test/compress.js Normal file
View File

@@ -0,0 +1,460 @@
"use strict";
require("../tools/exit");
var assert = require("assert");
var child_process = require("child_process");
var fs = require("fs");
var path = require("path");
var sandbox = require("./sandbox");
var semver = require("semver");
var U = require("./node");
var file = process.argv[2];
var dir = path.resolve(path.dirname(module.filename), "compress");
if (file) {
var minify_options = require("./ufuzz/options.json").map(JSON.stringify);
log("--- {file}", { file: file });
var tests = parse_test(path.resolve(dir, file));
process.exit(Object.keys(tests).filter(function(name) {
return !test_case(tests[name]);
}).length);
} else {
var files = fs.readdirSync(dir).filter(function(name) {
return /\.js$/i.test(name);
});
var failures = 0;
var failed_files = Object.create(null);
(function next() {
var file = files.shift();
if (file) {
child_process.spawn(process.argv[0], [ process.argv[1], file ], {
stdio: [ "ignore", 1, 2 ]
}).on("exit", function(code) {
if (code) {
failures += code;
failed_files[file] = code;
}
next();
});
} else if (failures) {
console.error();
console.error("!!! Failed " + failures + " test case(s).");
console.error("!!! " + Object.keys(failed_files).join(", "));
process.exit(1);
}
})();
}
function evaluate(code) {
if (code instanceof U.AST_Node) code = make_code(code, { beautify: true });
return new Function("return(" + code + ")")();
}
function log() {
console.log("%s", tmpl.apply(null, arguments));
}
function make_code(ast, options) {
var stream = U.OutputStream(options);
ast.print(stream);
return stream.get();
}
function parse_test(file) {
var script = fs.readFileSync(file, "utf8");
try {
var ast = U.parse(script, {
filename: file
});
} catch (e) {
console.error("Caught error while parsing tests in " + file);
console.error(e);
process.exit(1);
}
var tests = Object.create(null);
var tw = new U.TreeWalker(function(node, descend) {
if (node instanceof U.AST_LabeledStatement
&& tw.parent() instanceof U.AST_Toplevel) {
var name = node.label.name;
if (name in tests) {
throw new Error('Duplicated test name "' + name + '" in ' + file);
}
tests[name] = get_one_test(name, node.body);
return true;
}
if (!(node instanceof U.AST_Toplevel)) croak(node);
});
ast.walk(tw);
return tests;
function croak(node) {
throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", {
file: file,
line: node.start.line,
col: node.start.col,
code: make_code(node, { beautify: false })
}));
}
function read_string(stat) {
if (stat.TYPE == "SimpleStatement") {
var body = stat.body;
switch(body.TYPE) {
case "String":
return body.value;
case "Array":
return body.elements.map(function(element) {
if (element.TYPE !== "String")
throw new Error("Should be array of strings");
return element.value;
}).join("\n");
}
}
throw new Error("Should be string or array of strings");
}
function get_one_test(name, block) {
var test = { name: name, options: {} };
var tw = new U.TreeWalker(function(node, descend) {
if (node instanceof U.AST_Assign) {
if (!(node.left instanceof U.AST_SymbolRef)) {
croak(node);
}
var name = node.left.name;
test[name] = evaluate(node.right);
return true;
}
if (node instanceof U.AST_LabeledStatement) {
var label = node.label;
assert.ok([
"input",
"expect",
"expect_exact",
"expect_warnings",
"expect_stdout",
"node_version",
].indexOf(label.name) >= 0, tmpl("Unsupported label {name} [{line},{col}]", {
name: label.name,
line: label.start.line,
col: label.start.col
}));
var stat = node.body;
if (label.name == "expect_exact" || label.name == "node_version") {
test[label.name] = read_string(stat);
} else if (label.name == "expect_stdout") {
var body = stat.body;
if (body instanceof U.AST_Boolean) {
test[label.name] = body.value;
} else if (body instanceof U.AST_Call) {
var ctor = global[body.expression.name];
assert.ok(ctor === Error || ctor.prototype instanceof Error, tmpl("Unsupported expect_stdout format [{line},{col}]", {
line: label.start.line,
col: label.start.col
}));
test[label.name] = ctor.apply(null, body.args.map(function(node) {
assert.ok(node instanceof U.AST_Constant, tmpl("Unsupported expect_stdout format [{line},{col}]", {
line: label.start.line,
col: label.start.col
}));
return node.value;
}));
} else {
test[label.name] = read_string(stat) + "\n";
}
} else {
test[label.name] = stat;
}
return true;
}
});
block.walk(tw);
return test;
}
}
// Try to reminify original input with standard options
// to see if it matches expect_stdout.
function reminify(orig_options, input_code, input_formatted, stdout) {
for (var i = 0; i < minify_options.length; i++) {
var options = JSON.parse(minify_options[i]);
if (options.compress) [
"keep_fargs",
"keep_fnames",
].forEach(function(name) {
if (name in orig_options) {
options.compress[name] = orig_options[name];
}
});
var options_formatted = JSON.stringify(options, null, 4);
options.validate = true;
var result = U.minify(input_code, options);
if (result.error) {
log([
"!!! failed input reminify",
"---INPUT---",
"{input}",
"---OPTIONS---",
"{options}",
"--ERROR---",
"{error}",
"",
"",
].join("\n"), {
input: input_formatted,
options: options_formatted,
error: result.error,
});
return false;
} else {
var toplevel = sandbox.has_toplevel(options);
var expected = stdout[toplevel ? 1 : 0];
var actual = run_code(result.code, toplevel);
if (typeof expected != "string" && typeof actual != "string" && expected.name == actual.name) {
actual = expected;
}
if (!sandbox.same_stdout(expected, actual)) {
log([
"!!! failed running reminified input",
"---INPUT---",
"{input}",
"---OPTIONS---",
"{options}",
"---OUTPUT---",
"{output}",
"---EXPECTED {expected_type}---",
"{expected}",
"---ACTUAL {actual_type}---",
"{actual}",
"",
"",
].join("\n"), {
input: input_formatted,
options: options_formatted,
output: result.code,
expected_type: typeof expected == "string" ? "STDOUT" : "ERROR",
expected: expected,
actual_type: typeof actual == "string" ? "STDOUT" : "ERROR",
actual: actual,
});
return false;
}
}
}
return true;
}
function run_code(code, toplevel) {
var result = sandbox.run_code(code, toplevel);
return typeof result == "string" ? result.replace(/\u001b\[\d+m/g, "") : result;
}
function test_case(test) {
log(" Running test [{name}]", { name: test.name });
U.AST_Node.enable_validation();
var output_options = test.beautify || {};
var expect;
if (test.expect) {
expect = make_code(to_toplevel(test.expect, test.mangle), output_options);
} else {
expect = test.expect_exact;
}
var input = to_toplevel(test.input, test.mangle);
var input_code = make_code(input);
var input_formatted = make_code(test.input, {
beautify: true,
comments: "all",
keep_quoted_props: true,
quote_style: 3,
});
try {
input.validate_ast();
U.parse(input_code);
} catch (ex) {
log([
"!!! Cannot parse input",
"---INPUT---",
"{input}",
"--PARSE ERROR--",
"{error}",
"",
"",
].join("\n"), {
input: input_formatted,
error: ex,
});
return false;
}
var warnings_emitted = [];
if (test.expect_warnings) {
var expected_warnings = make_code(test.expect_warnings, {
beautify: false,
quote_style: 2, // force double quote to match JSON
});
U.AST_Node.log_function(function(text) {
warnings_emitted.push(text);
}, /"INFO: /.test(expected_warnings));
}
if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) {
var quoted_props = test.mangle.properties.reserved;
if (!Array.isArray(quoted_props)) quoted_props = [];
test.mangle.properties.reserved = quoted_props;
U.reserve_quoted_keys(input, quoted_props);
}
if (test.rename) {
input.figure_out_scope(test.mangle);
input.expand_names(test.mangle);
}
var cmp = new U.Compressor(test.options, true);
var output = cmp.compress(input);
output.figure_out_scope(test.mangle);
if (test.mangle) {
output.compute_char_frequency(test.mangle);
output.mangle_names(test.mangle);
if (test.mangle.properties) U.mangle_properties(output, test.mangle.properties);
}
var output_code = make_code(output, output_options);
U.AST_Node.log_function();
if (expect != output_code) {
log([
"!!! failed",
"---INPUT---",
"{input}",
"---OUTPUT---",
"{output}",
"---EXPECTED---",
"{expected}",
"",
"",
].join("\n"), {
input: input_formatted,
output: output_code,
expected: expect
});
return false;
}
// expect == output
try {
output.validate_ast();
U.parse(output_code);
} catch (ex) {
log([
"!!! Test matched expected result but cannot parse output",
"---INPUT---",
"{input}",
"---OUTPUT---",
"{output}",
"--REPARSE ERROR--",
"{error}",
"",
"",
].join("\n"), {
input: input_formatted,
output: output_code,
error: ex,
});
return false;
}
if (test.expect_warnings) {
warnings_emitted = warnings_emitted.map(function(input) {
return input.split(process.cwd() + path.sep).join("").split(path.sep).join("/");
});
var actual_warnings = JSON.stringify(warnings_emitted);
if (expected_warnings != actual_warnings) {
log([
"!!! failed",
"---INPUT---",
"{input}",
"---EXPECTED WARNINGS---",
"{expected_warnings}",
"---ACTUAL WARNINGS---",
"{actual_warnings}",
"",
"",
].join("\n"), {
input: input_formatted,
expected_warnings: expected_warnings,
actual_warnings: actual_warnings,
});
return false;
}
}
if (test.expect_stdout && (!test.node_version || semver.satisfies(process.version, test.node_version))) {
var stdout = [ run_code(input_code), run_code(input_code, true) ];
var toplevel = sandbox.has_toplevel({
compress: test.options,
mangle: test.mangle
});
var actual = stdout[toplevel ? 1 : 0];
if (test.expect_stdout === true || test.expect_stdout instanceof Error && test.expect_stdout.name === actual.name) {
test.expect_stdout = actual;
}
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
log([
"!!! Invalid input or expected stdout",
"---INPUT---",
"{input}",
"---EXPECTED {expected_type}---",
"{expected}",
"---ACTUAL {actual_type}---",
"{actual}",
"",
"",
].join("\n"), {
input: input_formatted,
expected_type: typeof test.expect_stdout == "string" ? "STDOUT" : "ERROR",
expected: test.expect_stdout,
actual_type: typeof actual == "string" ? "STDOUT" : "ERROR",
actual: actual,
});
return false;
}
actual = run_code(output_code, toplevel);
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
log([
"!!! failed",
"---INPUT---",
"{input}",
"---EXPECTED {expected_type}---",
"{expected}",
"---ACTUAL {actual_type}---",
"{actual}",
"",
"",
].join("\n"), {
input: input_formatted,
expected_type: typeof test.expect_stdout == "string" ? "STDOUT" : "ERROR",
expected: test.expect_stdout,
actual_type: typeof actual == "string" ? "STDOUT" : "ERROR",
actual: actual,
});
return false;
}
if (!reminify(test.options, input_code, input_formatted, stdout)) {
return false;
}
}
return true;
}
function tmpl() {
return U.string_template.apply(null, arguments);
}
function to_toplevel(input, mangle_options) {
if (!(input instanceof U.AST_BlockStatement)) throw new Error("Unsupported input syntax");
var directive = true;
var offset = input.start.line;
var tokens = [];
var toplevel = new U.AST_Toplevel(input.transform(new U.TreeTransformer(function(node) {
if (U.push_uniq(tokens, node.start)) node.start.line -= offset;
if (!directive || node === input) return;
if (node instanceof U.AST_SimpleStatement && node.body instanceof U.AST_String) {
return new U.AST_Directive(node.body);
} else {
directive = false;
}
})));
toplevel.figure_out_scope(mangle_options);
return toplevel;
}

View File

@@ -5,7 +5,8 @@ replace_index: {
properties: true,
}
input: {
console.log(arguments && arguments[0]);
var arguments = [];
console.log(arguments[0]);
(function() {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
@@ -21,7 +22,8 @@ replace_index: {
})("bar", 42);
}
expect: {
console.log(arguments && arguments[0]);
var arguments = [];
console.log(arguments[0]);
(function() {
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
@@ -45,6 +47,37 @@ replace_index: {
]
}
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,
@@ -53,7 +86,8 @@ replace_index_keep_fargs: {
properties: true,
}
input: {
console.log(arguments && arguments[0]);
var arguments = [];
console.log(arguments[0]);
(function() {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
@@ -69,7 +103,8 @@ replace_index_keep_fargs: {
})("bar", 42);
}
expect: {
console.log(arguments && arguments[0]);
var arguments = [];
console.log(arguments[0]);
(function(argument_0, argument_1) {
console.log(argument_1, argument_1, arguments.foo);
})("bar", 42);
@@ -93,6 +128,38 @@ replace_index_keep_fargs: {
]
}
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,
@@ -101,8 +168,10 @@ modified: {
(function(a, b) {
var c = arguments[0];
var d = arguments[1];
a = "foo";
var a = "foo";
b++;
arguments[0] = "moo";
arguments[1] *= 2;
console.log(a, b, c, d, arguments[0], arguments[1]);
})("bar", 42);
}
@@ -110,10 +179,786 @@ modified: {
(function(a, b) {
var c = a;
var d = b;
a = "foo";
var a = "foo";
b++;
a = "moo";
b *= 2;
console.log(a, b, c, d, a, b);
})("bar", 42);
}
expect_stdout: "foo 43 bar 42 foo 43"
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(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect: {
(function(a) {
console.log(a, a);
a++;
console.log(a, a);
})(0);
}
expect_stdout: [
"0 0",
"1 1",
]
}
issue_3273_no_call_arg: {
options = {
arguments: true,
}
input: {
(function(a) {
arguments[0] = "FAIL";
console.log(a);
})();
}
expect: {
(function(a) {
arguments[0] = "FAIL";
console.log(a);
})();
}
expect_stdout: "undefined"
}
issue_3273_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
(function(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect: {
(function(a) {
console.log(a, a);
a++;
console.log(a, a);
})(0);
}
expect_stdout: [
"0 0",
"1 1",
]
}
issue_3273_local_strict: {
options = {
arguments: true,
}
input: {
(function(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect: {
(function(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_local_strict_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
(function(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect: {
(function(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_global_strict: {
options = {
arguments: true,
}
input: {
"use strict";
(function(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect: {
"use strict";
(function(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_global_strict_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
"use strict";
(function(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect: {
"use strict";
(function(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_keep_fargs_false: {
options = {
arguments: true,
keep_fargs: false,
reduce_vars: true,
}
input: {
(function() {
"use strict";
arguments[0]++;
console.log(arguments[0]);
})(0);
}
expect: {
(function(argument_0) {
"use strict";
argument_0++;
console.log(argument_0);
})(0);
}
expect_stdout: "1"
}
issue_3273_keep_fargs_strict: {
options = {
arguments: true,
keep_fargs: "strict",
reduce_vars: true,
}
input: {
(function() {
"use strict";
arguments[0]++;
console.log(arguments[0]);
})(0);
}
expect: {
(function(argument_0) {
"use strict";
argument_0++;
console.log(argument_0);
})(0);
}
expect_stdout: "1"
}
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
}
issue_3420_1: {
options = {
arguments: true,
keep_fargs: "strict",
}
input: {
console.log(function() {
return function() {
return arguments[0];
};
}().length);
}
expect: {
console.log(function() {
return function() {
return arguments[0];
};
}().length);
}
expect_stdout: "0"
}
issue_3420_2: {
options = {
arguments: true,
keep_fargs: "strict",
}
input: {
var foo = function() {
delete arguments[0];
};
foo();
}
expect: {
var foo = function() {
delete arguments[0];
};
foo();
}
expect_stdout: true
}
issue_3420_3: {
options = {
arguments: true,
keep_fargs: "strict",
}
input: {
"use strict";
var foo = function() {
delete arguments[0];
};
foo();
}
expect: {
"use strict";
var foo = function() {
delete arguments[0];
};
foo();
}
expect_stdout: true
}
issue_3420_4: {
options = {
arguments: true,
keep_fargs: "strict",
}
input: {
!function() {
console.log(arguments[0]);
delete arguments[0];
console.log(arguments[0]);
}(42);
}
expect: {
!function(argument_0) {
console.log(argument_0);
delete arguments[0];
console.log(arguments[0]);
}(42);
}
expect_stdout: [
"42",
"undefined",
]
}
issue_3420_5: {
options = {
arguments: true,
keep_fargs: "strict",
}
input: {
"use strict";
!function() {
console.log(arguments[0]);
delete arguments[0];
console.log(arguments[0]);
}(42);
}
expect: {
"use strict";
!function(argument_0) {
console.log(argument_0);
delete arguments[0];
console.log(arguments[0]);
}(42);
}
expect_stdout: [
"42",
"undefined",
]
}
issue_3420_6: {
options = {
arguments: true,
keep_fargs: "strict",
}
input: {
console.log(function() {
return delete arguments[0];
}());
}
expect: {
console.log(function() {
return delete arguments[0];
}());
}
expect_stdout: "true"
}
issue_3420_7: {
options = {
arguments: true,
keep_fargs: "strict",
}
input: {
"use strict";
console.log(function() {
return delete arguments[0];
}());
}
expect: {
"use strict";
console.log(function() {
return delete arguments[0];
}());
}
expect_stdout: "true"
}
issue_4200: {
options = {
arguments: true,
keep_fargs: false,
}
input: {
var o = {
get p() {
return arguments[0];
},
};
console.log(o.p);
}
expect: {
var o = {
get p() {
return arguments[0];
},
};
console.log(o.p);
}
expect_stdout: "undefined"
}
issue_4291_1: {
options = {
arguments: true,
keep_fargs: "strict",
}
input: {
console.log(function() {
arguments[0] = "PASS";
return arguments;
}()[0]);
}
expect: {
console.log(function() {
arguments[0] = "PASS";
return arguments;
}()[0]);
}
expect_stdout: "PASS"
}
issue_4291_2: {
options = {
arguments: true,
keep_fargs: "strict",
}
input: {
var a = function() {
if (arguments[0])
arguments[1] = "PASS";
return arguments;
}(42);
console.log(a[1], a[0], a.length);
}
expect: {
var a = function(argument_0) {
if (argument_0)
arguments[1] = "PASS";
return arguments;
}(42);
console.log(a[1], a[0], a.length);
}
expect_stdout: "PASS 42 1"
}
issue_4397: {
options = {
arguments: true,
keep_fargs: "strict",
}
input: {
console.log(typeof function() {
arguments += 0;
return arguments[0];
}());
}
expect: {
console.log(typeof function() {
arguments += 0;
return arguments[0];
}());
}
expect_stdout: "string"
}
issue_4410_1: {
options = {
arguments: true,
conditionals: true,
evaluate: true,
reduce_vars: true,
}
input: {
(function(a) {
console.log(arguments[0] === (a = 0) ? "FAIL" : "PASS");
})(1);
}
expect: {
(function(a) {
console.log(a === (a = 0) ? "FAIL" : "PASS");
})(1);
}
expect_stdout: "PASS"
}
issue_4410_2: {
options = {
arguments: true,
conditionals: true,
evaluate: true,
reduce_vars: true,
}
input: {
(function f(a) {
console.log(arguments[0] === (a = 0) ? "FAIL" : "PASS");
})(1);
}
expect: {
(function f(a) {
console.log(arguments[0] === (a = 0) ? "FAIL" : "PASS");
})(1);
}
expect_stdout: "PASS"
}
issue_4410_3: {
options = {
arguments: true,
}
input: {
var a = 1;
(function f(b) {
a-- && f();
for (var c = 2; c--;)
switch (arguments[0]) {
case b = 42:
case 42:
console.log("PASS");
}
})(null);
}
expect: {
var a = 1;
(function f(b) {
a-- && f();
for (var c = 2; c--;)
switch (arguments[0]) {
case b = 42:
case 42:
console.log("PASS");
}
})(null);
}
expect_stdout: "PASS"
}
issue_4432: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
console.log(function(a) {
for (a in { FAIL: 42 });
return arguments[0];
}() || "PASS");
}
expect: {
console.log(function(a) {
for (a in { FAIL: 42 });
return arguments[0];
}() || "PASS");
}
expect_stdout: "PASS"
}

View File

@@ -15,9 +15,10 @@ holes_and_undefined: {
constant_join: {
options = {
unsafe : true,
evaluate : true
};
evaluate: true,
strings: true,
unsafe: true,
}
input: {
var a = [ "foo", "bar", "baz" ].join("");
var a1 = [ "foo", "bar", "baz" ].join();
@@ -64,9 +65,10 @@ constant_join: {
constant_join_2: {
options = {
unsafe : true,
evaluate : true
};
evaluate: true,
strings: true,
unsafe: true,
}
input: {
var a = [ "foo", "bar", boo(), "baz", "x", "y" ].join("");
var b = [ "foo", "bar", boo(), "baz", "x", "y" ].join("-");
@@ -93,10 +95,12 @@ constant_join_2: {
constant_join_3: {
options = {
unsafe: true,
evaluate: true,
};
strings: true,
unsafe: true,
}
input: {
var foo, bar, baz;
var a = [ null ].join();
var b = [ , ].join();
var c = [ , 1, , 3 ].join();
@@ -111,6 +115,7 @@ constant_join_3: {
var l = [ foo, bar + "baz" ].join("");
}
expect: {
var foo, bar, baz;
var a = "";
var b = "";
var c = ",1,,3";
@@ -133,7 +138,7 @@ for_loop: {
reduce_vars: true,
unsafe: true,
unused: true,
};
}
input: {
function f0() {
var a = [1, 2, 3];
@@ -239,3 +244,113 @@ index_length: {
}
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: []
}

589
test/compress/arrows.js Normal file
View File

@@ -0,0 +1,589 @@
no_funarg: {
input: {
(() => console.log(42))();
}
expect_exact: "(()=>console.log(42))();"
expect_stdout: "42"
node_version: ">=4"
}
single_funarg: {
input: {
(a => console.log(a))(42);
}
expect_exact: "(a=>console.log(a))(42);"
expect_stdout: "42"
node_version: ">=4"
}
multiple_funargs: {
input: {
((a, b) => console.log(a, b))("foo", "bar");
}
expect_exact: '((a,b)=>console.log(a,b))("foo","bar");'
expect_stdout: "foo bar"
node_version: ">=4"
}
destructured_funarg: {
input: {
(([ a, b, c ]) => console.log(a, b, c))("foo");
}
expect_exact: '(([a,b,c])=>console.log(a,b,c))("foo");'
expect_stdout: "f o o"
node_version: ">=6"
}
await_parenthesis: {
input: {
async function f() {
await (a => a);
}
}
expect_exact: "async function f(){await(a=>a)}"
}
for_parenthesis_init: {
input: {
for (a => (a in a); console.log(42););
}
expect_exact: "for((a=>a in a);console.log(42););"
expect_stdout: "42"
node_version: ">=4"
}
for_parenthesis_condition: {
input: {
for (console.log(42); a => (a in a);)
break;
}
expect_exact: "for(console.log(42);a=>a in a;)break;"
expect_stdout: "42"
node_version: ">=4"
}
for_parenthesis_step: {
input: {
for (; console.log(42); a => (a in a));
}
expect_exact: "for(;console.log(42);a=>a in a);"
expect_stdout: "42"
node_version: ">=4"
}
for_assign_parenthesis_init: {
input: {
for (f = a => (a in a); console.log(42););
}
expect_exact: "for((f=a=>a in a);console.log(42););"
expect_stdout: "42"
node_version: ">=4"
}
for_assign_parenthesis_condition: {
input: {
for (console.log(42); f = a => (a in a);)
break;
}
expect_exact: "for(console.log(42);f=a=>a in a;)break;"
expect_stdout: "42"
node_version: ">=4"
}
for_assign_parenthesis_step: {
input: {
for (; console.log(42); f = a => (a in a));
}
expect_exact: "for(;console.log(42);f=a=>a in a);"
expect_stdout: "42"
node_version: ">=4"
}
for_declaration_parenthesis_init: {
input: {
for (var f = a => (a in a); console.log(42););
}
expect_exact: "for(var f=(a=>a in a);console.log(42););"
expect_stdout: "42"
node_version: ">=4"
}
for_statement_parenthesis_init: {
input: {
for (a => {
a in a;
}; console.log(42););
}
expect_exact: "for(a=>{a in a};console.log(42););"
expect_stdout: "42"
node_version: ">=4"
}
body_call: {
input: {
(() => {
console.log("foo");
console.log("bar");
})();
}
expect_exact: '(()=>{console.log("foo");console.log("bar")})();'
expect_stdout: [
"foo",
"bar",
]
node_version: ">=4"
}
body_conditional: {
input: {
console.log((a => {}) ? "PASS" : "FAIL");
}
expect_exact: 'console.log((a=>{})?"PASS":"FAIL");'
expect_stdout: "PASS"
node_version: ">=4"
}
destructured_object_value: {
input: {
console.log((a => ({} = a))(42));
}
expect_exact: "console.log((a=>({}=a))(42));"
expect_stdout: "42"
node_version: ">=6"
}
function_value: {
input: {
console.log((a => function() {
return a;
})(42)());
}
expect_exact: "console.log((a=>function(){return a})(42)());"
expect_stdout: "42"
node_version: ">=4"
}
in_value: {
input: {
console.log((a => a in {
foo: 42,
})("foo"));
}
expect_exact: 'console.log((a=>a in{foo:42})("foo"));'
expect_stdout: "true"
node_version: ">=4"
}
object_value: {
input: {
console.log((() => ({
4: 2,
}))()[4]);
}
expect_exact: "console.log((()=>({4:2}))()[4]);"
expect_stdout: "2"
node_version: ">=4"
}
object_first_in_value: {
input: {
console.log((a => ({
p: a,
}.p ? "FAIL" : "PASS"))());
}
expect_exact: 'console.log((a=>({p:a}).p?"FAIL":"PASS")());'
expect_stdout: "PASS"
node_version: ">=4"
}
sequence_value: {
input: {
console.log((a => (console.log("foo"), a))("bar"));
}
expect_exact: 'console.log((a=>(console.log("foo"),a))("bar"));'
expect_stdout: [
"foo",
"bar",
]
node_version: ">=4"
}
side_effects_value: {
options = {
side_effects: true,
}
input: {
console.log((a => function() {
return a;
})(42)());
}
expect: {
console.log((a => function() {
return a;
})(42)());
}
expect_stdout: "42"
node_version: ">=4"
}
arrow_property: {
input: {
console.log((a => 42).prototype);
}
expect_exact: "console.log((a=>42).prototype);"
expect_stdout: "undefined"
node_version: ">=4"
}
assign_arrow: {
input: {
var f = a => a;
console.log(f(42));
}
expect_exact: "var f=a=>a;console.log(f(42));"
expect_stdout: "42"
node_version: ">=4"
}
binary_arrow: {
input: {
console.log(4 || (() => 2));
}
expect_exact: "console.log(4||(()=>2));"
expect_stdout: "4"
node_version: ">=4"
}
unary_arrow: {
input: {
console.log(+(() => 42));
}
expect_exact: "console.log(+(()=>42));"
expect_stdout: "NaN"
node_version: ">=4"
}
trailing_comma: {
input: {
((a,) => console.log(a))(42);
}
expect_exact: "(a=>console.log(a))(42);"
expect_stdout: "42"
node_version: ">=4"
}
drop_arguments: {
options = {
arguments: true,
keep_fargs: false,
}
input: {
console.log(function() {
return () => arguments[0];
}("PASS")("FAIL"));
}
expect: {
console.log(function(argument_0) {
return () => argument_0;
}("PASS")("FAIL"));
}
expect_stdout: "PASS"
node_version: ">=4"
}
funarg_arguments: {
options = {
inline: true,
}
input: {
console.log((arguments => arguments)(42));
}
expect: {
console.log(42);
}
expect_stdout: "42"
node_version: ">=4"
}
inline_arguments: {
options = {
inline: true,
}
input: {
console.log(function() {
return () => arguments[0];
}("PASS")("FAIL"));
}
expect: {
console.log(function() {
return () => arguments[0];
}("PASS")("FAIL"));
}
expect_stdout: "PASS"
node_version: ">=4"
}
var_arguments: {
options = {
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
console.log(function() {
return () => {
var arguments = [ "PASS" ];
return arguments;
};
}("FAIL 1")("FAIL 2")[0]);
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
negate: {
options = {
conditionals: true,
}
input: {
if (!console ? 0 : () => 1)
console.log("PASS");
}
expect: {
(console ? () => 1 : 0) && console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
inline_this: {
options = {
inline: true,
}
input: {
var o = {
p: function() {
return function() {
return () => this.q;
}();
},
q: "FAIL",
};
q = "PASS";
console.log(o.p()());
}
expect: {
var o = {
p: function() {
return function() {
return () => this.q;
}();
},
q: "FAIL",
};
q = "PASS";
console.log(o.p()());
}
expect_stdout: "PASS"
node_version: ">=4"
}
trim_body: {
options = {
arrows: true,
if_return: true,
side_effects: true,
}
input: {
var f = a => {
return a;
};
var g = b => void b;
console.log(f("PASS"), g("FAIL"));
}
expect: {
var f = a => a;
var g = b => {};
console.log(f("PASS"), g("FAIL"));
}
expect_stdout: "PASS undefined"
node_version: ">=4"
}
collapse_value: {
options = {
arrows: true,
collapse_vars: true,
keep_fargs: "strict",
unused: true,
}
input: {
var a = 42;
console.log((b => Math.floor(b))(a));
}
expect: {
var a = 42;
console.log((() => Math.floor(a))());
}
expect_stdout: "42"
node_version: ">=4"
}
reduce_iife_1: {
options = {
evaluate: true,
keep_fargs: "strict",
reduce_vars: true,
unused: true,
}
input: {
(a => console.log(a + a))(21);
}
expect: {
(() => console.log(42))();
}
expect_stdout: "42"
node_version: ">=4"
}
reduce_iife_2: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 21;
(() => console.log(a + a))();
}
expect: {
(() => console.log(42))();
}
expect_stdout: "42"
node_version: ">=4"
}
reduce_iife_3: {
options = {
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = "foo";
(() => {
console.log(a);
console.log(a);
})();
a = "bar";
}
expect: {
(() => {
console.log("foo");
console.log("foo");
})();
}
expect_stdout: [
"foo",
"foo",
]
node_version: ">=4"
}
single_use_recursive: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {
return (() => f)();
}
console.log(typeof f());
}
expect: {
console.log(typeof function f() {
return (() => f)();
}());
}
expect_stdout: "function"
node_version: ">=4"
}
issue_4388: {
options = {
inline: true,
toplevel: true,
}
input: {
(arguments => console.log(arguments && arguments))();
}
expect: {
(arguments => console.log(arguments && arguments))();
}
expect_stdout: "undefined"
node_version: ">=4"
}
issue_4390: {
options = {
collapse_vars: true,
}
input: {
function log() {
console.log.apply(console, arguments);
}
var a = 42, b = "FAIL";
b = "PASS";
(c => log(b, c))(a);
log(b);
}
expect: {
function log() {
console.log.apply(console, arguments);
}
var a = 42, b = "FAIL";
b = "PASS";
(c => log(b, c))(a);
log(b);
}
expect_stdout: [
"PASS 42",
"PASS",
]
node_version: ">=4"
}
issue_4401: {
options = {
merge_vars: true,
}
input: {
(function() {
var a = (b => b(a))(console.log || a);
var c = console.log;
c && c(typeof b);
})();
}
expect: {
(function() {
var a = (b => b(a))(console.log || a);
var c = console.log;
c && c(typeof b);
})();
}
expect_stdout: [
"undefined",
"undefined",
]
node_version: ">=4"
}

View File

@@ -1,35 +0,0 @@
ascii_only_true: {
options = {}
beautify = {
ascii_only : true,
ie8 : false,
beautify : false,
}
input: {
function f() {
return "\x000\x001\x007\x008\x00" +
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
"\x20\x21\x22\x23 ... \x7d\x7e\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: {
options = {}
beautify = {
ascii_only : false,
ie8 : false,
beautify : false,
}
input: {
function f() {
return "\x000\x001\x007\x008\x00" +
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
"\x20\x21\x22\x23 ... \x7d\x7e\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,24 +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,
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) {
@@ -75,9 +76,8 @@ asm_mixed: {
start = start | 0;
end = end | 0;
var sum = 0.0, p = 0, q = 0;
for (p = start << 3, q = end << 3; (p | 0) < (q | 0); p = p + 8 | 0) {
for (p = start << 3, q = end << 3; (p | 0) < (q | 0); p = p + 8 | 0)
sum = sum + +log(values[p >> 3]);
}
return +sum;
}
function geometricMean(start, end) {
@@ -90,12 +90,12 @@ asm_mixed: {
function no_asm_GeometricMean(stdlib, foreign, buffer) {
function logSum(start, end) {
start |= 0, end |= 0;
var sum = 0, p = 0, q = 0;
for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
for (var sum = 0, p = 0, q = 0, p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0)
sum += +log(values[p >> 3]);
return +sum;
}
function geometricMean(start, end) {
return start |= 0, end |= 0, +exp(+logSum(start, end) / +(end - start | 0));
return start |= 0, end |= 0, +exp(+logSum(start, end) / (end - start | 0));
}
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
return { geometricMean: geometricMean };
@@ -165,3 +165,69 @@ asm_nested_functions: {
}
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;'
}
issue_3636_1: {
mangle = {}
input: {
function n(stdlib, foreign, buffer) {
"use asm";
function add(x, y) {
x = x | 0;
y = y | 0;
return x + y | 0;
}
return {
add: add
};
}
console.log(new n().add("foo", 42));
}
expect: {
function n(o, e, u) {
"use asm";
function d(n, o) {
n = n | 0;
o = o | 0;
return n + o | 0;
}
return {
add: d
};
}
console.log(new n().add("foo", 42));
}
expect_stdout: "42"
}
issue_3636_2: {
mangle = {}
input: {
var n = function(stdlib, foreign, buffer) {
"use asm";
function add(x, y) {
x = x | 0;
y = y | 0;
return x + y | 0;
}
return {
add: add
};
};
console.log(new n().add("foo", 42));
}
expect: {
var n = function(n, o, e) {
"use asm";
function r(n, o) {
n = n | 0;
o = o | 0;
return n + o | 0;
}
return {
add: r
};
};
console.log(new n().add("foo", 42));
}
expect_stdout: "42"
}

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,224 @@ 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"
}
issue_3375_1: {
options = {
assignments: true,
reduce_vars: true,
}
input: {
function p(o) {
console.log(typeof o, o);
}
p(function(b) {
var a = b += 1;
--b;
return a;
}("object"));
}
expect: {
function p(o) {
console.log(typeof o, o);
}
p(function(b) {
var a = b += 1;
--b;
return a;
}("object"));
}
expect_stdout: "string object1"
}
issue_3375_2: {
options = {
assignments: true,
reduce_vars: true,
}
input: {
function p(o) {
console.log(typeof o, o);
}
p(function(b) {
var a = b -= 1;
--b;
return a;
}("object"));
}
expect: {
function p(o) {
console.log(typeof o, o);
}
p(function(b) {
var a = --b;
--b;
return a;
}("object"));
}
expect_stdout: "number NaN"
}
issue_3427: {
options = {
assignments: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
(function() {
var a;
a || (a = {});
})();
}
expect: {}
}
issue_3429_1: {
options = {
assignments: true,
side_effects: true,
unused: true,
}
input: {
var a = "PASS";
(function(b) {
b && (b = a = "FAIL");
})();
console.log(a);
}
expect: {
var a = "PASS";
(function(b) {
b = b && (a = "FAIL");
})();
console.log(a);
}
expect_stdout: "PASS"
}
issue_3429_2: {
options = {
assignments: true,
side_effects: true,
unused: true,
}
input: {
var a;
(function(b) {
b || (b = a = "FAIL");
})(42);
console.log(a);
}
expect: {
var a;
(function(b) {
b = b || (a = "FAIL");
})(42);
console.log(a);
}
expect_stdout: "undefined"
}
issue_3949_1: {
options = {
assignments: true,
evaluate: true,
reduce_vars: true,
}
input: {
var a = 42;
function f() {
var b = a;
b = b >> 2;
return 100 + b;
}
console.log(f());
}
expect: {
var a = 42;
function f() {
var b = a;
b >>= 2;
return 100 + b;
}
console.log(f());
}
expect_stdout: "110"
}
issue_3949_2: {
options = {
assignments: true,
evaluate: true,
reduce_vars: true,
}
input: {
var a = 42;
function f() {
var b = a;
b = 5 & b;
return 100 + b;
}
console.log(f());
}
expect: {
var a = 42;
function f() {
var b = a;
b &= 5;
return 100 + b;
}
console.log(f());
}
expect_stdout: "100"
}

642
test/compress/async.js Normal file
View File

@@ -0,0 +1,642 @@
await_await: {
input: {
(async function() {
console.log("PASS");
await await 42;
})();
}
expect: {
(async function() {
console.log("PASS");
await await 42;
})();
}
expect_stdout: "PASS"
node_version: ">=8"
}
defun_name: {
input: {
async function await() {
console.log("PASS");
}
await();
}
expect: {
async function await() {
console.log("PASS");
}
await();
}
expect_stdout: "PASS"
node_version: ">=8"
}
nested_await: {
input: {
(async function() {
console.log(function(await) {
return await;
}("PASS"));
})();
}
expect: {
(async function() {
console.log(function(await) {
return await;
}("PASS"));
})();
}
expect_stdout: "PASS"
node_version: ">=8"
}
reduce_single_use_defun: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
async function f(a) {
console.log(a);
}
f("PASS");
}
expect: {
(async function(a) {
console.log(a);
})("PASS");
}
expect_stdout: "PASS"
node_version: ">=8"
}
dont_inline: {
options = {
inline: true,
}
input: {
(async function() {
A;
})().catch(function() {});
console.log("PASS");
}
expect: {
(async function() {
A;
})().catch(function() {});
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=8"
}
evaluate: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = async function() {}();
console.log(typeof a);
}
expect: {
var a = async function() {}();
console.log(typeof a);
}
expect_stdout: "object"
node_version: ">=8"
}
negate: {
options = {
side_effects: true,
}
input: {
console && async function() {} && console.log("PASS");
}
expect: {
console && async function() {} && console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=8"
}
negate_iife: {
options = {
negate_iife: true,
}
input: {
(async function() {
console.log("PASS");
})();
}
expect: {
!async function() {
console.log("PASS");
}();
}
expect_stdout: "PASS"
node_version: ">=8"
}
object_function: {
options = {
properties: true,
side_effects: true,
}
input: {
({
async f() {
console.log("PASS");
},
}).f();
}
expect: {
(async function() {
console.log("PASS");
})();
}
expect_stdout: "PASS"
node_version: ">=8"
}
collapse_vars_1: {
options = {
collapse_vars: true,
}
input: {
var a = "FAIL";
(async function() {
a = "PASS";
await 42;
return "PASS";
})();
console.log(a);
}
expect: {
var a = "FAIL";
(async function() {
a = "PASS";
await 42;
return "PASS";
})();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=8"
}
collapse_vars_2: {
options = {
collapse_vars: true,
}
input: {
var a = "FAIL";
(async function() {
await (a = "PASS");
return "PASS";
})();
console.log(a);
}
expect: {
var a = "FAIL";
(async function() {
await (a = "PASS");
return "PASS";
})();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=8"
}
collapse_vars_3: {
options = {
collapse_vars: true,
}
input: {
var a = "FAIL";
(async function() {
await (a = "PASS", 42);
return "PASS";
})();
console.log(a);
}
expect: {
var a = "FAIL";
(async function() {
await (a = "PASS", 42);
return "PASS";
})();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_4335_1: {
options = {
inline: true,
}
input: {
var await = "PASS";
(async function() {
console.log(function() {
return await;
}());
})();
}
expect: {
var await = "PASS";
(async function() {
console.log(function() {
return await;
}());
})();
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_4335_2: {
options = {
inline: true,
}
input: {
(async function() {
console.log(function() {
function await() {}
return "PASS";
}());
})();
}
expect: {
(async function() {
console.log(function() {
function await() {}
return "PASS";
}());
})();
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_4337: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function(a) {
a();
})(async function() {
console.log("PASS");
});
}
expect: {
(function(a) {
(async function() {
console.log("PASS");
})();
})();
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_4340: {
options = {
evaluate: true,
reduce_vars: true,
}
input: {
(async function a(a) {
console.log(a || "PASS");
})();
}
expect: {
(async function a(a) {
console.log(a || "PASS");
})();
}
expect_stdout: "PASS"
node_version: ">=8"
}
call_expression: {
input: {
console.log(typeof async function(log) {
(await log)("FAIL");
}(console.log).then);
}
expect_exact: 'console.log(typeof async function(log){(await log)("FAIL")}(console.log).then);'
expect_stdout: "function"
node_version: ">=8"
}
property_access_expression: {
input: {
console.log(typeof async function(con) {
(await con).log("FAIL");
}(console).then);
}
expect_exact: 'console.log(typeof async function(con){(await con).log("FAIL")}(console).then);'
expect_stdout: "function"
node_version: ">=8"
}
reduce_iife_1: {
options = {
evaluate: true,
keep_fargs: "strict",
reduce_vars: true,
unused: true,
}
input: {
(async function(a) {
console.log(a + a);
})(21);
}
expect: {
(async function() {
console.log(42);
})();
}
expect_stdout: "42"
node_version: ">=8"
}
reduce_iife_2: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 21;
(async function() {
console.log(a + a);
})();
}
expect: {
(async function() {
console.log(42);
})();
}
expect_stdout: "42"
node_version: ">=8"
}
reduce_iife_3: {
options = {
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = "foo";
(async function() {
console.log(a);
console.log(await a);
})();
a = "bar";
}
expect: {
var a = "foo";
(async function() {
console.log(a);
console.log(await a);
})();
a = "bar";
}
expect_stdout: "foo"
node_version: ">=8"
}
issue_4347_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = "foo";
f();
a = "bar";
f();
async function f() {
console.log(a);
}
}
expect: {
var a = "foo";
f();
a = "bar";
f();
async function f() {
console.log(a);
}
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=8"
}
issue_4347_2: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = "PASS";
(async function() {
throw 42;
a = "FAIL";
})();
console.log(a);
}
expect: {
var a = "PASS";
(async function() {
throw 42;
a = "FAIL";
})();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_4349_1: {
input: {
console.log(typeof async function() {
await /abc/;
}().then);
}
expect_exact: "console.log(typeof async function(){await/abc/}().then);"
expect_stdout: "function"
node_version: ">=8"
}
issue_4349_2: {
options = {
collapse_vars: true,
unused: true,
}
input: {
console.log(typeof async function() {
(function(a) {
this[a];
}(await 0));
}().then);
}
expect: {
console.log(typeof async function() {
(function(a) {
this[a];
}(await 0));
}().then);
}
expect_stdout: "function"
node_version: ">=8"
}
issue_4349_3: {
options = {
collapse_vars: true,
unused: true,
}
input: {
console.log(typeof function(await) {
return async function(a) {
this[a];
}(await);
}(this).then);
}
expect: {
console.log(typeof function(await) {
return async function(a) {
this[a];
}(await);
}(this).then);
}
expect_stdout: "function"
node_version: ">=8"
}
issue_4359: {
options = {
collapse_vars: true,
unused: true,
}
input: {
try {
(async function(a) {
return a;
})(A);
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
(async function(a) {
return a;
})(A);
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_4377: {
options = {
dead_code: true,
inline: true,
side_effects: true,
}
input: {
console.log(typeof function() {
return function() {
f;
async function f() {}
return f();
}();
}().then);
}
expect: {
console.log(typeof function() {
return f();
async function f() {}
}().then);
}
expect_stdout: "function"
node_version: ">=8"
}
issue_4406: {
options = {
merge_vars: true,
}
input: {
A = "PASS";
B = "FAIL";
(function() {
var a, b;
a = A;
(async function({
[console.log(a)]: {},
}) {})((b = B) && { undefined: b });
})();
}
expect: {
A = "PASS";
B = "FAIL";
(function() {
var a, b;
a = A;
(async function({
[console.log(a)]: {},
}) {})((b = B) && { undefined: b });
})();
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_4417: {
options = {
inline: true,
}
input: {
(async function() {
console.log(function() {
return await => 0;
}().prototype);
})();
}
expect: {
(async function() {
console.log(function() {
return await => 0;
}().prototype);
})();
}
expect_stdout: "undefined"
node_version: ">=8"
}

183
test/compress/booleans.js Normal file
View File

@@ -0,0 +1,183 @@
iife_boolean_context: {
options = {
booleans: true,
evaluate: true,
}
input: {
console.log(function() {
return Object(1) || false;
}() ? "PASS" : "FAIL");
console.log(function() {
return [].length || true;
}() ? "PASS" : "FAIL");
}
expect: {
console.log(function() {
return Object(1);
}() ? "PASS" : "FAIL");
console.log(function() {
return [].length, 1;
}() ? "PASS" : "FAIL");
}
expect_stdout: [
"PASS",
"PASS",
]
expect_warnings: [
"WARN: Dropping side-effect-free || [test/compress/booleans.js:2,19]",
"WARN: Boolean || always true [test/compress/booleans.js:5,19]",
]
}
issue_3465_1: {
options = {
booleans: true,
}
input: {
console.log(function(a) {
return typeof a;
}() ? "PASS" : "FAIL");
}
expect: {
console.log(function(a) {
return 1;
}() ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
}
issue_3465_2: {
options = {
booleans: true,
}
input: {
console.log(function f(a) {
if (!a) console.log(f(42));
return typeof a;
}() ? "PASS" : "FAIL");
}
expect: {
console.log(function f(a) {
if (!a) console.log(f(42));
return typeof a;
}() ? "PASS" : "FAIL");
}
expect_stdout: [
"number",
"PASS",
]
}
issue_3465_3: {
options = {
booleans: true,
passes: 2,
unused: true,
}
input: {
console.log(function f(a) {
return typeof a;
}() ? "PASS" : "FAIL");
}
expect: {
console.log(function(a) {
return 1;
}() ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
}
issue_2737_2: {
options = {
booleans: true,
inline: true,
reduce_vars: true,
unused: true,
}
input: {
(function(bar) {
for (;bar();) break;
})(function qux() {
return console.log("PASS"), qux;
});
}
expect: {
(function(bar) {
for (;bar();) break;
})(function() {
return console.log("PASS"), 1;
});
}
expect_stdout: "PASS"
}
issue_3658: {
options = {
booleans: true,
evaluate: true,
reduce_vars: true,
}
input: {
console.log(function f() {
console || f();
return "PASS";
}());
}
expect: {
console.log(function f() {
console || f();
return "PASS";
}());
}
expect_stdout: "PASS"
}
issue_3690: {
options = {
booleans: true,
unused: true,
}
input: {
console.log(function(a) {
return function() {
return a = [ this ];
}() ? "PASS" : "FAIL";
}());
}
expect: {
console.log(function(a) {
return function() {
return 1;
}() ? "PASS" : "FAIL";
}());
}
expect_stdout: "PASS"
}
issue_4374: {
options = {
booleans: true,
conditionals: true,
if_return: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
console.log(f());
function f(a) {
if (null) return 0;
if (a) return 1;
return 0;
}
})();
}
expect: {
(function() {
console.log(function(a) {
return !null && a ? 1 : 0;
}());
})();
}
expect_stdout: "0"
}

File diff suppressed because it is too large Load Diff

View File

@@ -33,10 +33,10 @@ unsafe_comps: {
}
expect: {
var obj1, obj2;
obj2 < obj1 ? g1() : f1();
obj1 < obj2 ? f2() : g2();
obj1 < obj2 ? g3() : f3();
obj2 < obj1 ? f4() : g4();
(obj2 < obj1 ? g1 : f1)();
(obj1 < obj2 ? f2 : g2)();
(obj1 < obj2 ? g3 : f3)();
(obj2 < obj1 ? f4 : g4)();
}
}
@@ -93,6 +93,59 @@ self_comparison_2: {
expect_stdout: "false true"
}
self_comparison_3: {
options = {
comparisons: true,
}
input: {
var a;
function f() {
var b = a;
a = null;
return b;
}
for (var i = 0; i < 2; i++)
console.log(f() === f());
}
expect: {
var a;
function f() {
var b = a;
a = null;
return b;
}
for (var i = 0; i < 2; i++)
console.log(f() === f());
}
expect_stdout: [
"false",
"true",
]
}
self_comparison_4: {
options = {
booleans: true,
comparisons: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {};
console.log(o == o, o != o);
console.log(o === o, o !== o);
}
expect: {
console.log(!0, !1);
console.log(!0, !1);
}
expect_stdout: [
"true false",
"true false",
]
}
issue_2857_1: {
options = {
comparisons: true,
@@ -295,3 +348,148 @@ issue_2857_6: {
}
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"
}
is_defined: {
options = {
comparisons: true,
}
input: {
console.log(function a() {
return void 0 === a;
}());
}
expect: {
console.log(function a() {
return a, false;
}());
}
expect_stdout: "false"
expect_warnings: [
"WARN: Expression always defined [test/compress/comparisons.js:2,19]",
]
}
unsafe_indexOf: {
options = {
booleans: true,
comparisons: true,
unsafe: true,
}
input: {
var a = Object.keys({ foo: 42 });
if (a.indexOf("bar") < 0) console.log("PASS");
if (0 > a.indexOf("bar")) console.log("PASS");
if (a.indexOf("foo") >= 0) console.log("PASS");
if (0 <= a.indexOf("foo")) console.log("PASS");
if (a.indexOf("foo") > -1) console.log("PASS");
if (-1 < a.indexOf("foo")) console.log("PASS");
if (a.indexOf("bar") == -1) console.log("PASS");
if (-1 == a.indexOf("bar")) console.log("PASS");
if (a.indexOf("bar") === -1) console.log("PASS");
if (-1 === a.indexOf("bar")) console.log("PASS");
if (a.indexOf("foo") != -1) console.log("PASS");
if (-1 != a.indexOf("foo")) console.log("PASS");
if (a.indexOf("foo") !== -1) console.log("PASS");
if (-1 !== a.indexOf("foo")) console.log("PASS");
}
expect: {
var a = Object.keys({ foo: 42 });
if (!~a.indexOf("bar")) console.log("PASS");
if (!~a.indexOf("bar")) console.log("PASS");
if (~a.indexOf("foo")) console.log("PASS");
if (~a.indexOf("foo")) console.log("PASS");
if (~a.indexOf("foo")) console.log("PASS");
if (~a.indexOf("foo")) console.log("PASS");
if (!~a.indexOf("bar")) console.log("PASS");
if (!~a.indexOf("bar")) console.log("PASS");
if (!~a.indexOf("bar")) console.log("PASS");
if (!~a.indexOf("bar")) console.log("PASS");
if (~a.indexOf("foo")) console.log("PASS");
if (~a.indexOf("foo")) console.log("PASS");
if (~a.indexOf("foo")) console.log("PASS");
if (~a.indexOf("foo")) console.log("PASS");
}
expect_stdout: [
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
]
}
issue_3413: {
options = {
comparisons: true,
evaluate: true,
side_effects: true,
}
input: {
var b;
void 0 !== ("" < b || void 0) || console.log("PASS");
}
expect: {
var b;
void 0 !== ("" < b || void 0) || console.log("PASS");
}
expect_stdout: "PASS"
}

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";
@@ -26,7 +26,9 @@ concat_1: {
}
concat_2: {
options = {};
options = {
strings: true,
}
input: {
console.log(
1 + (2 + 3),
@@ -55,7 +57,9 @@ concat_2: {
}
concat_3: {
options = {};
options = {
strings: true,
}
input: {
console.log(
1 + 2 + (3 + 4 + 5),
@@ -84,7 +88,9 @@ concat_3: {
}
concat_4: {
options = {};
options = {
strings: true,
}
input: {
console.log(
1 + "2" + (3 + 4 + 5),
@@ -113,7 +119,9 @@ concat_4: {
}
concat_5: {
options = {};
options = {
strings: true,
}
input: {
console.log(
"1" + 2 + (3 + 4 + 5),
@@ -142,7 +150,9 @@ concat_5: {
}
concat_6: {
options = {};
options = {
strings: true,
}
input: {
console.log(
"1" + "2" + (3 + 4 + 5),
@@ -171,6 +181,9 @@ concat_6: {
}
concat_7: {
options = {
strings: true,
}
input: {
console.log(
"" + 1,
@@ -197,6 +210,9 @@ concat_7: {
}
concat_8: {
options = {
strings: true,
}
input: {
console.log(
1 + "",
@@ -221,3 +237,55 @@ concat_8: {
}
expect_stdout: true
}
concat_9: {
options = {
booleans: true,
evaluate: true,
reduce_vars: true,
strings: true,
toplevel: true,
}
input: {
var a = "foo";
console.log(
12 + (34 + a),
null + (34 + a),
12 + (null + a),
false + (34 + a),
12 + (false + a),
"bar" + (34 + a),
12 + ("bar" + a)
);
}
expect: {
var a = "foo";
console.log(
"1234" + a,
"null34" + a,
"12null" + a,
!1 + (34 + a),
12 + (!1 + a),
"bar34" + a,
"12bar" + a
);
}
expect_stdout: true
}
issue_3689: {
options = {
strings: true,
}
input: {
console.log(function(a) {
return a + ("" + (a[0] = 0));
}([]));
}
expect: {
console.log(function(a) {
return a + ("" + (a[0] = 0));
}([]));
}
expect_stdout: "00"
}

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();
@@ -41,28 +41,29 @@ ifs_2: {
}
expect: {
foo ? x() : bar ? y() : baz && z();
foo ? x() : bar ? y() : baz ? z() : t();
(foo ? x : bar ? y : baz ? z : t)();
}
}
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
// 1
if (x && !(x + "1") && y) {
var qq;
foo();
} else {
bar();
}
if (x || !!(x + "1") || y) { // 2
// 2
if (x || !!(x + "1") || y) {
foo();
} else {
var jj;
@@ -71,15 +72,31 @@ ifs_3_should_warn: {
}
expect: {
var x, y;
var qq; bar(); // 1
var jj; foo(); // 2
// 1
var qq; bar();
// 2
foo(); var jj;
}
expect_warnings: [
"WARN: + in boolean context always true [test/compress/conditionals.js:3,18]",
"WARN: Boolean && always false [test/compress/conditionals.js:3,12]",
"WARN: Condition left of && always false [test/compress/conditionals.js:3,12]",
"WARN: Condition always false [test/compress/conditionals.js:3,12]",
"WARN: Dropping unreachable code [test/compress/conditionals.js:3,34]",
"WARN: + in boolean context always true [test/compress/conditionals.js:10,19]",
"WARN: Boolean || always true [test/compress/conditionals.js:10,12]",
"WARN: Condition left of || always true [test/compress/conditionals.js:10,12]",
"WARN: Condition always true [test/compress/conditionals.js:10,12]",
"WARN: Dropping unreachable code [test/compress/conditionals.js:12,15]",
"WARN: Dropping side-effect-free statement [test/compress/conditionals.js:3,12]",
"WARN: Dropping side-effect-free statement [test/compress/conditionals.js:10,12]",
]
}
ifs_4: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
if (foo && bar) {
x(foo)[10].bar.baz = something();
@@ -95,10 +112,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 +149,9 @@ ifs_5: {
ifs_6: {
options = {
comparisons: true,
conditionals: true,
comparisons: true
};
}
input: {
var x, y;
if (!foo && !bar && !baz && !boo) {
@@ -161,10 +178,28 @@ ifs_6: {
}
}
ifs_7: {
options = {
conditionals: true,
}
input: {
if (A); else;
if (A) while (B); else;
if (A); else while (C);
if (A) while (B); else while (C);
}
expect: {
A;
if (A) while (B);
if (!A) while (C);
if (A) while (B); else while (C);
}
}
cond_1: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
function foo(do_something, some_condition) {
if (some_condition) {
@@ -189,8 +224,8 @@ cond_1: {
cond_2: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
function foo(x, FooBar, some_condition) {
if (some_condition) {
@@ -209,8 +244,8 @@ cond_2: {
cond_3: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
var FooBar;
if (some_condition()) {
@@ -227,8 +262,8 @@ cond_3: {
cond_4: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
var do_something;
if (some_condition()) {
@@ -251,8 +286,8 @@ cond_4: {
cond_5: {
options = {
conditionals: true
};
conditionals: true,
}
input: {
if (some_condition()) {
if (some_other_condition()) {
@@ -271,17 +306,56 @@ cond_5: {
}
}
expect: {
some_condition() && some_other_condition() ? do_something() : alternate();
(some_condition() && some_other_condition() ? do_something : alternate)();
some_condition() && some_other_condition() && do_something();
}
}
cond_6: {
options = {
booleans: true,
conditionals: true,
}
input: {
x ? a : b;
x ? a : a;
x ? y ? a : b : c;
x ? y ? a : a : b;
x ? y ? a : b : b;
x ? y ? a : b : a;
x ? y ? a : a : a;
x ? a : y ? b : c;
x ? a : y ? a : b;
x ? a : y ? b : b;
x ? a : y ? b : a;
x ? a : y ? a : a;
}
expect: {
x ? a : b;
x, a;
x ? y ? a : b : c;
x ? (y, a) : b;
x && y ? a : b;
!x || y ? a : b;
x && y, a;
x ? a : y ? b : c;
x || y ? a : b;
x ? a : (y, b);
!x && y ? b : a;
!x && y, a;
}
}
cond_7: {
options = {
conditionals: true,
evaluate : true,
evaluate: true,
side_effects: true,
};
}
input: {
var x, y, z, a, b;
// compress these
@@ -342,8 +416,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
@@ -361,10 +435,10 @@ cond_7_1: {
cond_8: {
options = {
booleans: false,
conditionals: true,
evaluate : true,
booleans : false
};
evaluate: true,
}
input: {
var a;
// compress these
@@ -445,10 +519,10 @@ cond_8: {
cond_8b: {
options = {
booleans: true,
conditionals: true,
evaluate : true,
booleans : true
};
evaluate: true,
}
input: {
var a;
// compress these
@@ -528,10 +602,10 @@ cond_8b: {
cond_8c: {
options = {
booleans: false,
conditionals: true,
evaluate : false,
booleans : false
};
evaluate: false,
}
input: {
var a;
// compress these
@@ -645,11 +719,126 @@ cond_9: {
}
}
cond_10: {
options = {
conditionals: true,
if_return: true,
}
input: {
function f(a) {
if (1 == a) return "foo";
if (2 == a) return "foo";
if (3 == a) return "foo";
if (4 == a) return 42;
if (5 == a) return "foo";
if (6 == a) return "foo";
return "bar";
}
console.log(f(1), f(2), f(3), f(4), f(5), f(6), f(7));
}
expect: {
function f(a) {
return 1 == a || 2 == a || 3 == a ? "foo" : 4 == a ? 42 : 5 == a || 6 == a ? "foo" : "bar";
}
console.log(f(1), f(2), f(3), f(4), f(5), f(6), f(7));
}
expect_stdout: "foo foo foo 42 foo foo bar"
}
cond_11: {
options = {
conditionals: true,
}
input: {
var o = {
p: "foo",
q: function() {
return this.p;
}
};
function f() {
return "bar";
}
function g(a) {
return a ? f() : o.q();
}
console.log(g(0), g(1));
}
expect: {
var o = {
p: "foo",
q: function() {
return this.p;
}
};
function f() {
return "bar";
}
function g(a) {
return a ? f() : o.q();
}
console.log(g(0), g(1));
}
expect_stdout: "foo bar"
}
cond_12: {
options = {
conditionals: true,
}
input: {
x ? y && a : a;
x ? y || a : a;
x ? a : y && a;
x ? a : y || a;
}
expect: {
(!x || y) && a;
x && y || a;
(x || y) && a;
!x && y || a;
}
}
cond_13: {
options = {
conditionals: true,
}
input: {
x ? y(a) : z(a);
x ? y.f(a) : z.f(a);
x ? y.f(a) : z.g(a);
x ? y.f()(a) : z.g()(a);
x ? y.f.u(a) : z.g.u(a);
x ? y.f().u(a) : z.g().u(a);
}
expect: {
(x ? y : z)(a);
(x ? y : z).f(a);
x ? y.f(a) : z.g(a);
(x ? y.f() : z.g())(a);
(x ? y.f : z.g).u(a);
(x ? y.f() : z.g()).u(a);
}
}
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, 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; }
@@ -675,9 +864,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, 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; }
@@ -778,11 +979,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; }
@@ -818,7 +1019,7 @@ issue_1154: {
no_evaluate: {
options = {
conditionals: true,
evaluate : false,
evaluate: false,
side_effects: true,
}
input: {
@@ -975,7 +1176,7 @@ issue_1645_2: {
expect_stdout: true
}
condition_symbol_matches_consequent: {
condition_matches_consequent: {
options = {
conditionals: true,
}
@@ -1004,6 +1205,35 @@ condition_symbol_matches_consequent: {
expect_stdout: "3 7 true 4"
}
condition_matches_alternative: {
options = {
conditionals: true,
}
input: {
function foo(x, y) {
return x.p ? y[0] : x.p;
}
function bar() {
return g ? h : g;
}
var g = 4;
var h = 5;
console.log(foo({ p: 3 }, [ null ]), foo({ p: 0 }, [ 7 ]), foo({ p: true } , [ false ]), bar());
}
expect: {
function foo(x, y) {
return x.p && y[0];
}
function bar() {
return g && h;
}
var g = 4;
var h = 5;
console.log(foo({ p: 3 }, [ null ]), foo({ p: 0 }, [ 7 ]), foo({ p: true } , [ false ]), bar());
}
expect_stdout: "null 0 false 5"
}
delete_conditional_1: {
options = {
booleans: true,
@@ -1078,11 +1308,11 @@ issue_2535_1: {
expect: {
y();
x() && y();
(x(), 1) && y();
x(), y();
x() && y();
x() && y();
x() && y();
(x(), 0) && y();
x();
}
}
@@ -1222,7 +1452,7 @@ hoist_decl: {
}
expect: {
var a, b;
x() ? y() : z();
(x() ? y : z)();
}
}
@@ -1268,3 +1498,366 @@ to_and_or: {
}
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"
}
iife_condition: {
options = {
conditionals: true,
side_effects: true,
}
input: {
if (function() {
return console;
}())
console.log("PASS");
}
expect: {
!function() {
return console;
}() || console.log("PASS");
}
expect_stdout: "PASS"
}
angularjs_chain: {
options = {
conditionals: true,
passes: 2,
side_effects: true,
}
input: {
function nonComputedMember(left, right, context, create) {
var lhs = left();
if (create && create !== 1) {
if (lhs && lhs[right] == null) {
lhs[right] = {};
}
}
var value = lhs != null ? lhs[right] : undefined;
if (context) {
return { context: lhs, name: right, value: value };
} else {
return value;
}
}
}
expect: {
function nonComputedMember(left, right, context, create) {
var lhs = left();
create && 1 !== create && lhs && null == lhs[right] && (lhs[right] = {});
var value = null != lhs ? lhs[right] : void 0;
return context ? {
context: lhs,
name: right,
value: value
} : value;
}
}
}
issue_3576: {
options = {
conditionals: true,
evaluate: true,
pure_getters: "strict",
reduce_vars: true,
}
input: {
var c = "FAIL";
(function(a) {
(a = -1) ? (a && (a.a = 0)) : (a && (a.a = 0));
a && a[c = "PASS"]++;
})();
console.log(c);
}
expect: {
var c = "FAIL";
(function(a) {
a = -1, a, a.a = 0;
a, a[c = "PASS"]++;
})();
console.log(c);
}
expect_stdout: "PASS"
}
issue_3668: {
options = {
conditionals: true,
if_return: true,
}
input: {
function f() {
try {
var undefined = typeof f;
if (!f) return undefined;
return;
} catch (e) {
return "FAIL";
}
}
console.log(f());
}
expect: {
function f() {
try {
var undefined = typeof f;
return f ? void 0 : undefined;
} catch (e) {
return "FAIL";
}
}
console.log(f());
}
expect_stdout: "undefined"
}
conditional_assignments_1: {
options = {
conditionals: true,
sequences: true,
}
input: {
function f(a, b, c, d) {
a = b;
if (c) a = d;
return a;
}
function g(a, b, c, d) {
a = b;
if (c); else a = d;
return a;
}
console.log(f(0, "FAIL", 1, "PASS"), g(0, "PASS", 1, "FAIL"));
}
expect: {
function f(a, b, c, d) {
return a = c ? d : b, a;
}
function g(a, b, c, d) {
return a = c ? b : d, a;
}
console.log(f(0, "FAIL", 1, "PASS"), g(0, "PASS", 1, "FAIL"));
}
expect_stdout: "PASS PASS"
}
conditional_assignments_2: {
options = {
conditionals: true,
sequences: true,
}
input: {
function f1(b, c, d) {
a = b;
if (c) a = d;
return a;
}
function f2(a, c, d) {
a = b;
if (c) a = d;
return a;
}
function f3(a, b, d) {
a = b;
if (c) a = d;
return a;
}
function f4(a, b, c) {
a = b;
if (c) a = d;
return a;
}
}
expect: {
function f1(b, c, d) {
return a = c ? d : b, a;
}
function f2(a, c, d) {
return a = b, c && (a = d), a;
}
function f3(a, b, d) {
return a = b, c && (a = d), a;
}
function f4(a, b, c) {
return a = b, c && (a = d), a;
}
}
}
conditional_assignments_3: {
options = {
conditionals: true,
sequences: true,
}
input: {
console.log(function(a, b) {
a = "PASS";
if (b) a = a;
return a;
}(0, 1));
}
expect: {
console.log(function(a, b) {
return a = "PASS", b && (a = a), a;
}(0, 1));
}
expect_stdout: "PASS"
}
issue_3808_1: {
options = {
conditionals: true,
side_effects: true,
}
input: {
var a;
a = "PASS", [] + "" && (a = "FAIL");
console.log(a);
}
expect: {
var a;
a = [] + "" ? "FAIL" : "PASS";
console.log(a);
}
expect_stdout: "PASS"
}
issue_3808_2: {
options = {
conditionals: true,
side_effects: true,
}
input: {
var a;
console.log((a = "PASS", [] + "" && (a = "FAIL")), a);
}
expect: {
var a;
console.log((a = "PASS", [] + "" && (a = "FAIL")), a);
}
expect_stdout: " PASS"
}

1377
test/compress/const.js Normal file

File diff suppressed because it is too large Load Diff

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;

File diff suppressed because it is too large Load Diff

131
test/compress/directives.js Normal file
View File

@@ -0,0 +1,131 @@
simple_statement_is_not_a_directive: {
input: {
"use strict"
.split(" ")
.forEach(function(s) {
console.log(s);
});
console.log(!this); // is strict mode?
(function() {
"directive"
""
"use strict"
"hello world"
.split(" ")
.forEach(function(s) {
console.log(s);
});
console.log(!this); // is strict mode?
})();
}
expect: {
"use strict".split(" ").forEach(function(s) {
console.log(s);
});
console.log(!this);
(function() {
"directive";
"";
"use strict";
"hello world".split(" ").forEach(function(s) {
console.log(s);
});
console.log(!this);
})();
}
expect_stdout: [
"use",
"strict",
"false",
"hello",
"world",
"true",
]
}
drop_lone_use_strict: {
options = {
directives: true,
unused: true,
}
input: {
function f1() {
"use strict";
}
function f2() {
"use strict";
function f3() {
"use strict";
}
}
(function f4() {
"use strict";
})();
}
expect: {
function f1() {
}
function f2() {
}
(function() {})();
}
}
issue_3166: {
options = {
directives: true,
}
input: {
"foo";
"use strict";
function f() {
"use strict";
"bar";
"use asm";
}
}
expect: {
"use strict";
function f() {
"use asm";
}
}
}
valid_after_invalid_1: {
input: {
console.log(typeof function() {
"use\x20strict";
"use strict";
return this;
}());
}
expect: {
console.log(typeof function() {
"use\x20strict";
"use strict";
return this;
}());
}
expect_stdout: "undefined"
}
valid_after_invalid_2: {
options = {
directives: true,
}
input: {
console.log(typeof function() {
"use\x20strict";
"use strict";
return this;
}());
}
expect: {
console.log(typeof function() {
"use strict";
return this;
}());
}
expect_stdout: "undefined"
}

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);
@@ -12,6 +12,20 @@ must_replace: {
}
}
repeated_nodes: {
options = {
global_defs: {
"@N": "rand()",
},
}
input: {
console.log(N, N);
}
expect: {
console.log(rand(), rand());
}
}
keyword: {
options = {
global_defs: {
@@ -141,9 +155,8 @@ mixed: {
console.log(CONFIG);
}
expect_warnings: [
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]',
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:128,22]',
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:130,8]',
"WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:4,22]",
"WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:7,8]",
]
}
@@ -197,3 +210,23 @@ issue_2167: {
doWork();
}
}
issue_3217: {
options = {
collapse_vars: true,
global_defs: {
"@o": "{fn:function(){var a=42;console.log(a)}}",
},
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
o.fn();
}
expect: {
console.log(42);
}
}

View File

@@ -1,8 +1,8 @@
issue_2377_1: {
options = {
evaluate: true,
inline: true,
hoist_props: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
@@ -33,8 +33,8 @@ issue_2377_1: {
issue_2377_2: {
options = {
evaluate: true,
inline: true,
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
@@ -64,8 +64,8 @@ issue_2377_2: {
issue_2377_3: {
options = {
evaluate: true,
inline: true,
hoist_props: true,
inline: true,
passes: 4,
reduce_funcs: true,
reduce_vars: true,
@@ -297,6 +297,33 @@ name_collision_3: {
expect_stdout: "true 4 6"
}
name_collision_4: {
options = {
hoist_props: true,
reduce_vars: true,
}
input: {
console.log(function() {
var o = {
p: 0,
q: "PASS",
};
return function(o_p) {
if (!o.p) return o_p;
}(o.q);
}());
}
expect: {
console.log(function() {
var o_p$0 = 0, o_q = "PASS";
return function(o_p) {
if (!o_p$0) return o_p;
}(o_q);
}());
}
expect_stdout: "PASS"
}
contains_this_1: {
options = {
evaluate: true,
@@ -416,7 +443,10 @@ issue_2473_1: {
options = {
hoist_props: false,
reduce_vars: true,
top_retain: [ "x", "y" ],
top_retain: [
"x",
"y"
],
toplevel: true,
unused: true,
}
@@ -435,7 +465,10 @@ issue_2473_2: {
options = {
hoist_props: true,
reduce_vars: true,
top_retain: [ "x", "y" ],
top_retain: [
"x",
"y"
],
toplevel: true,
unused: true,
}
@@ -658,7 +691,7 @@ issue_2519: {
}
expect: {
function testFunc() {
return 1 * ((6 + 5) / 2);
return +((6 + 5) / 2);
}
console.log(testFunc());
}
@@ -746,9 +779,9 @@ issue_3046: {
issue_3071_1: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
join_vars: true,
hoist_props: true,
passes: 3,
reduce_vars: true,
sequences: true,
@@ -761,21 +794,20 @@ issue_3071_1: {
var obj = {};
obj.one = 1;
obj.two = 2;
console.log(obj.one);
console.log(obj.one, obj.two);
})();
}
expect: {
console.log(1);
console.log(1, 2);
}
expect_stdout: "1"
expect_stdout: "1 2"
}
issue_3071_2: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
join_vars: true,
hoist_props: true,
passes: 3,
reduce_vars: true,
sequences: true,
@@ -787,22 +819,21 @@ issue_3071_2: {
obj = {};
obj.one = 1;
obj.two = 2;
console.log(obj.one);
console.log(obj.one, obj.two);
var obj;
})();
}
expect: {
console.log(1);
console.log(1, 2);
}
expect_stdout: "1"
expect_stdout: "1 2"
}
issue_3071_2_toplevel: {
options = {
evaluate: true,
hoist_props: true,
inline: true,
join_vars: true,
hoist_props: true,
passes: 3,
reduce_vars: true,
sequences: true,
@@ -815,14 +846,14 @@ issue_3071_2_toplevel: {
obj = {};
obj.one = 1;
obj.two = 2;
console.log(obj.one);
console.log(obj.one, obj.two);
var obj;
})();
}
expect: {
console.log(1);
console.log(1, 2);
}
expect_stdout: "1"
expect_stdout: "1 2"
}
issue_3071_3: {
@@ -856,3 +887,184 @@ issue_3071_3: {
}
expect_stdout: "2"
}
issue_3411: {
options = {
hoist_props: true,
reduce_vars: true,
}
input: {
var c = 1;
!function f() {
var o = {
p: --c && f()
};
+o || console.log("PASS");
}();
}
expect: {
var c = 1;
!function f() {
var o_p = --c && f();
+{} || console.log("PASS");
}();
}
expect_stdout: "PASS"
}
issue_3440: {
options = {
hoist_props: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
function f() {
console.log(o.p);
}
var o = {
p: "PASS",
};
return f;
})()();
}
expect: {
(function() {
var o_p = "PASS";
return function() {
console.log(o_p);
};
})()();
}
expect_stdout: "PASS"
}
issue_3868: {
options = {
hoist_props: true,
passes: 2,
reduce_vars: true,
side_effects: true,
}
input: {
(function(t) {
t = {};
({
get p() {},
q: (console.log("PASS"), +t),
}).r;
})();
}
expect: {
(function(t) {
t = {};
({
get p() {},
q: (console.log("PASS"), +t),
}).r;
})();
}
expect_stdout: "PASS"
}
issue_3871: {
options = {
hoist_props: true,
reduce_vars: true,
}
input: {
console.log(function() {
do {
var b = {
get null() {
c;
}
};
} while (!b);
return "PASS";
}());
}
expect: {
console.log(function() {
do {
var b = {
get null() {
c;
}
};
} while (!b);
return "PASS";
}());
}
expect_stdout: "PASS"
}
issue_3945_1: {
options = {
hoist_props: true,
reduce_vars: true,
}
input: {
function f() {
o.p;
var o = {
q: 0,
};
}
}
expect: {
function f() {
o.p;
var o = {
q: 0,
};
}
}
}
issue_3945_2: {
options = {
hoist_props: true,
reduce_vars: true,
toplevel: true,
}
input: {
console.log(typeof o);
var o = {
p: 0,
};
}
expect: {
console.log(typeof o);
var o = {
p: 0,
};
}
expect_stdout: "undefined"
}
issue_4023: {
options = {
comparisons: true,
hoist_props: true,
inline: true,
reduce_vars: true,
toplevel: true,
typeofs: true,
unused: true,
}
input: {
function f() {
var a = function() {
return { p: 0 };
}();
return console.log("undefined" != typeof a);
}
f();
}
expect: {
console.log(void 0 !== {});
}
expect_stdout: "true"
}

View File

@@ -1,55 +1,107 @@
html_comment_in_expression: {
input: {
function f(a, b, x, y) { return a < !--b && x-- > y; }
(function(a, b) {
console.log(a < !--b && a-- > b, a, b);
})(1, 2);
}
expect_exact: "function f(a,b,x,y){return a< !--b&&x-- >y}";
expect_exact: "(function(a,b){console.log(a<! --b&&a-- >b,a,b)})(1,2);"
expect_stdout: "false 1 1"
}
html_comment_in_less_than: {
input: {
function f(a, b) { return a < !--b; }
(function(a, b, c) {
console.log(
a < !--b,
a < !--b + c,
a + b < !--c,
a, b, c
);
})(1, 2, 3);
}
expect_exact: "function f(a,b){return a< !--b}";
expect_exact: "(function(a,b,c){console.log(a<! --b,a<! --b+c,a+b<! --c,a,b,c)})(1,2,3);"
expect_stdout: "false true false 1 0 2"
}
html_comment_in_left_shift: {
input: {
function f(a, b) { return a << !--b; }
(function(a, b, c) {
console.log(
a << !--b,
a << !--b + c,
a + b << !--c,
a, b, c
);
})(1, 2, 3);
}
expect_exact: "function f(a,b){return a<< !--b}";
}
html_comment_in_right_shift: {
input: {
function f(a, b) { return a-- >> b; }
}
expect_exact: "function f(a,b){return a-- >>b}";
}
html_comment_in_zero_fill_right_shift: {
input: {
function f(a, b) { return a-- >>> b; }
}
expect_exact: "function f(a,b){return a-- >>>b}";
expect_exact: "(function(a,b,c){console.log(a<<! --b,a<<! --b+c,a+b<<! --c,a,b,c)})(1,2,3);"
expect_stdout: "1 16 1 1 0 2"
}
html_comment_in_greater_than: {
input: {
function f(a, b) { return a-- > b; }
(function(a, b, c) {
console.log(
a-- > b,
a-- > b + c,
a + b-- > c,
a, b, c
);
})(1, 2, 3);
}
expect_exact: "function f(a,b){return a-- >b}";
expect_exact: "(function(a,b,c){console.log(a-- >b,a-- >b+c,a+b-- >c,a,b,c)})(1,2,3);"
expect_stdout: "false false false -1 1 3"
}
html_comment_in_greater_than_or_equal: {
input: {
function f(a, b) { return a-- >= b; }
(function(a, b, c) {
console.log(
a-- >= b,
a-- >= b + c,
a + b-- >= c,
a, b, c
);
})(1, 2, 3);
}
expect_exact: "function f(a,b){return a-- >=b}";
expect_exact: "(function(a,b,c){console.log(a-- >=b,a-- >=b+c,a+b-- >=c,a,b,c)})(1,2,3);"
expect_stdout: "false false false -1 1 3"
}
html_comment_in_right_shift: {
input: {
(function(a, b, c) {
console.log(
a-- >> b,
a-- >> b + c,
a + b-- >> c,
a, b, c
);
})(1, 2, 3);
}
expect_exact: "(function(a,b,c){console.log(a-- >>b,a-- >>b+c,a+b-- >>c,a,b,c)})(1,2,3);"
expect_stdout: "0 0 0 -1 1 3"
}
html_comment_in_zero_fill_right_shift: {
input: {
(function(a, b, c) {
console.log(
a-- >>> b,
a-- >>> b + c,
a + b-- >>> c,
a, b, c
);
})(1, 2, 3);
}
expect_exact: "(function(a,b,c){console.log(a-- >>>b,a-- >>>b+c,a+b-- >>>c,a,b,c)})(1,2,3);"
expect_stdout: "0 0 0 -1 1 3"
}
html_comment_in_string_literal: {
input: {
function f() { return "<!--HTML-->comment in<!--string literal-->"; }
console.log("<!--HTML-->comment in<!--string literal-->".length);
}
expect_exact: 'function f(){return"\\x3c!--HTML--\\x3ecomment in\\x3c!--string literal--\\x3e"}';
expect_exact: 'console.log("\\x3c!--HTML--\\x3ecomment in\\x3c!--string literal--\\x3e".length);'
expect_stdout: "42"
}

File diff suppressed because it is too large Load Diff

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() {
@@ -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() {
@@ -396,3 +396,355 @@ if_if_return_return: {
}
}
}
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",
]
}
issue_3600: {
options = {
if_return: true,
inline: true,
side_effects: true,
unused: true,
}
input: {
var c = 0;
(function() {
if ([ ][c++]); else return;
return void function() {
var b = --b, a = c = 42;
return c;
}();
})();
console.log(c);
}
expect: {
var c = 0;
(function() {
if ([][c++]) b = --b, c = 42;
var b;
})();
console.log(c);
}
expect_stdout: "1"
}
iife_if_return_simple: {
options = {
conditionals: true,
if_return: true,
inline: true,
sequences: true,
side_effects: true,
}
input: {
(function() {
if (console)
return console.log("PASS");
console.log("FAIL");
})();
}
expect: {
console ? console.log("PASS") : console.log("FAIL");
}
expect_stdout: "PASS"
}
nested_if_break: {
options = {
if_return: true,
}
input: {
for (var i = 0; i < 3; i++)
L1: if ("number" == typeof i) {
if (0 === i) break L1;
console.log(i);
}
}
expect: {
for (var i = 0; i < 3; i++)
L1: if ("number" == typeof i)
if (0 !== i) console.log(i);
}
expect_stdout: [
"1",
"2",
]
}
nested_if_continue: {
options = {
conditionals: true,
if_return: true,
join_vars: true,
loops: true,
}
input: {
function f(n) {
var i = 0;
do {
if ("number" == typeof n) {
if (0 === n) {
console.log("even", i);
continue;
}
if (1 === n) {
console.log("odd", i);
continue;
}
i++;
}
} while (0 <= (n -= 2));
}
f(37);
f(42);
}
expect: {
function f(n) {
for (var i = 0;
"number" == typeof n
&& (0 !== n
? 1 !== n
? i++
: console.log("odd", i)
: console.log("even", i)),
0 <= (n -= 2););
}
f(37);
f(42);
}
expect_stdout: [
"odd 18",
"even 21",
]
}
nested_if_return: {
options = {
conditionals: true,
if_return: true,
}
input: {
function f() {
if (A) {
if (B)
return B;
if (C)
return D;
if (E)
return F;
if (G)
return H;
if (I) {
if (J)
return K;
return;
}
if (L) {
if (M)
return;
return N;
}
}
}
}
expect: {
function f() {
if (A)
return B || (C ? D : E ? F : G ? H : I ? J ? K : void 0 : L && !M ? N : void 0);
}
}
}
issue_866_1: {
options = {
conditionals: true,
if_return: true,
sequences: false,
};
input: {
function f(a) {
if (a)
return "";
console.log(a);
}
}
expect: {
function f(a) {
if (a)
return "";
console.log(a);
}
}
}
issue_866_2: {
options = {
conditionals: true,
if_return: true,
sequences: true,
}
input: {
(function() {
if (a)
if (b)
c;
else
return d;
})();
}
expect: {
(function() {
if (a) {
if (!b)
return d;
c;
}
})();
}
}

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, 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) {
@@ -21,25 +30,35 @@ non_hoisted_function_after_return: {
}
expect: {
function foo(x) {
return x ? bar() : baz();
return (x ? bar : baz)();
function bar() { return 7 }
function baz() { return 8 }
}
}
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, 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,
}
input: {
function foo(x) {
@@ -65,28 +84,34 @@ 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: pass 0: last_count: Infinity, count: 37",
"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: pass 1: last_count: 37, count: 18",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:4,16]",
"WARN: Dropping initialization 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]",
"INFO: pass 0: last_count: Infinity, count: 35",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
"INFO: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
"INFO: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
"INFO: pass 1: last_count: 35, 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, 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) {
@@ -110,20 +135,25 @@ non_hoisted_function_after_return_2b: {
}
}
expect_warnings: [
// duplicate warnings no longer emitted
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:99,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:99,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:103,12]",
"WARN: Dropping initialization 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 = {
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, 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: {
"use strict";
@@ -145,7 +175,7 @@ non_hoisted_function_after_return_strict: {
expect: {
"use strict";
function foo(x) {
return x ? bar() : baz();
return (x ? bar : baz)();
function bar() { return 7 }
function baz() { return 8 }
}
@@ -153,19 +183,29 @@ non_hoisted_function_after_return_strict: {
}
expect_stdout: "8 7"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:133,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:136,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:139,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:140,21]",
"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 = {
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, 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,
}
input: {
"use strict";
@@ -196,28 +236,34 @@ non_hoisted_function_after_return_2a_strict: {
}
expect_stdout: "5 6"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:175,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:175,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:178,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:178,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:175,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:182,21]",
"WARN: pass 0: last_count: Infinity, count: 48",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:180,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:180,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:183,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:178,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:180,16]",
"WARN: pass 1: last_count: 48, count: 29",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:5,16]",
"WARN: Dropping initialization 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]",
"INFO: pass 0: last_count: Infinity, count: 46",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
"INFO: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
"INFO: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
"INFO: pass 1: last_count: 46, count: 29",
]
}
non_hoisted_function_after_return_2b_strict: {
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, 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: {
"use strict";
@@ -246,11 +292,7 @@ non_hoisted_function_after_return_2b_strict: {
}
expect_stdout: "5 6"
expect_warnings: [
// duplicate warnings no longer emitted
"WARN: Dropping unreachable code [test/compress/issue-1034.js:229,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:229,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:231,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:231,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:235,12]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
]
}

View File

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

View File

@@ -16,7 +16,7 @@ multiple_functions: {
( function() {
// NOTE: other compression steps will reduce this
// down to just `window`.
if ( window );
if ( !window );
function f() {}
function g() {}
} )();
@@ -38,7 +38,7 @@ single_function: {
}
expect: {
( function() {
if ( window );
if ( !window );
function f() {}
} )();
}
@@ -67,7 +67,7 @@ deeply_nested: {
// NOTE: other compression steps will reduce this
// down to just `window`.
if ( window )
if (document);
if ( !document );
function f() {}
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,51 +148,57 @@ check_drop_unused_in_peer_function: {
Infinity_not_in_with_scope: {
options = {
unused: true
unused: true,
}
input: {
var o = { Infinity: 'oInfinity' };
var o = { Infinity: "FAIL" };
var vInfinity = "Infinity";
vInfinity = Infinity;
console.log(vInfinity);
}
expect: {
var o = { Infinity: 'oInfinity' }
var vInfinity = "Infinity"
vInfinity = 1/0
var o = { Infinity: "FAIL" };
var vInfinity = "Infinity";
vInfinity = 1/0;
console.log(vInfinity);
}
expect_stdout: "Infinity"
}
Infinity_in_with_scope: {
options = {
unused: true
unused: true,
}
input: {
var o = { Infinity: 'oInfinity' };
var o = { Infinity: "PASS" };
var vInfinity = "Infinity";
with (o) { vInfinity = Infinity; }
console.log(vInfinity);
}
expect: {
var o = { Infinity: 'oInfinity' }
var vInfinity = "Infinity"
with (o) vInfinity = Infinity
var o = { Infinity: "PASS" };
var vInfinity = "Infinity";
with (o) vInfinity = Infinity;
console.log(vInfinity);
}
expect_stdout: "PASS"
}
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,
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;
@@ -242,19 +248,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,
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,14 +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,
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
@@ -48,28 +48,28 @@ pure_function_calls: {
a.b(), f.g();
}
expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:16,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:29,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:29,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:27,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:37,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:38,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,
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
@@ -110,17 +110,17 @@ pure_function_calls_toplevel: {
a.b(), f.g();
}
expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:77,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:77,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:90,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:90,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:88,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:105,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:106,31]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:82,33]",
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:82,12]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:98,45]",
"WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:98,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]",
]
}
@@ -155,29 +155,29 @@ should_warn: {
baz();
}
expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,61]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,23]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:135,23]",
"WARN: Boolean || always true [test/compress/issue-1261.js:136,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:136,23]",
"WARN: Condition always true [test/compress/issue-1261.js:136,23]",
"WARN: Condition left of || always true [test/compress/issue-1261.js:137,8]",
"WARN: Condition always true [test/compress/issue-1261.js:137,8]",
"WARN: Boolean && always false [test/compress/issue-1261.js:138,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:138,23]",
"WARN: Condition always false [test/compress/issue-1261.js:138,23]",
"WARN: Condition left of && always false [test/compress/issue-1261.js:139,8]",
"WARN: Condition always false [test/compress/issue-1261.js:139,8]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:140,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:140,23]",
"WARN: Condition always true [test/compress/issue-1261.js:140,23]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:141,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:141,31]",
"WARN: Condition always true [test/compress/issue-1261.js:141,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:142,23]",
"WARN: Condition always true [test/compress/issue-1261.js:143,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:143,24]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:144,31]",
"WARN: Condition always false [test/compress/issue-1261.js:144,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,16 +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,
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

@@ -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

@@ -22,17 +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,
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

@@ -52,3 +52,30 @@ chained_evaluation_2: {
})();
}
}
chained_evaluation_3: {
options = {
collapse_vars: true,
evaluate: 10,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
var a = "long piece of string";
(function() {
var b = a, c;
c = f(b);
c.bar = b;
})();
})();
}
expect: {
(function() {
(function() {
f("long piece of string").bar = "long piece of string";
})();
})();
}
}

View File

@@ -1,4 +1,3 @@
issue_1639_1: {
options = {
booleans: true,
@@ -12,7 +11,6 @@ issue_1639_1: {
}
input: {
var a = 100, b = 10;
var L1 = 5;
while (--L1 > 0) {
if ((--b), false) {
@@ -21,15 +19,15 @@ issue_1639_1: {
}
}
}
console.log(a, b);
}
expect: {
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
if (--b, 0) var ignore = 0;
for (var a = 100, b = 10, L1 = 5, ignore; --L1 > 0;) {
--b;
}
console.log(a, b);
}
expect_stdout: true
expect_stdout: "100 6"
}
issue_1639_2: {
@@ -44,25 +42,23 @@ issue_1639_2: {
}
input: {
var a = 100, b = 10;
function f19() {
if (++a, false)
if (a)
if (++a);
}
f19();
console.log(a, b);
}
expect: {
var a = 100, b = 10;
function f19() {
++a, 0;
++a, 1;
}
f19(),
console.log(a, b);
}
expect_stdout: true
expect_stdout: "101 10"
}
issue_1639_3: {
@@ -84,5 +80,5 @@ issue_1639_3: {
a++,
console.log(a, b);
}
expect_stdout: true
expect_stdout: "101 10"
}

View File

@@ -35,11 +35,7 @@ f7: {
console.log(a, b);
}
expect_exact: [
"var b = 10;",
"",
"!function() {",
" b = 100;",
"}(), console.log(100, b);",
"console.log(100, 100);",
]
expect_stdout: true
expect_stdout: "100 100"
}

View File

@@ -366,7 +366,7 @@ mangle_catch_redef_3: {
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"
expect_stdout: true
}
mangle_catch_redef_3_toplevel: {
@@ -389,10 +389,10 @@ mangle_catch_redef_3_toplevel: {
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"
expect_stdout: true
}
mangle_catch_redef_ie8_3: {
mangle_catch_redef_3_ie8: {
mangle = {
ie8: true,
toplevel: false,
@@ -412,7 +412,7 @@ mangle_catch_redef_ie8_3: {
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"
expect_stdout: true
}
mangle_catch_redef_3_ie8_toplevel: {
@@ -435,5 +435,5 @@ mangle_catch_redef_3_ie8_toplevel: {
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"
expect_stdout: true
}

View File

@@ -46,7 +46,7 @@ mangle_props: {
obj[1/0],
obj["Infinity"],
obj[-1/0],
obj[-1/0],
obj[-(1/0)],
obj["-Infinity"],
obj[null],
obj["null"]

View File

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

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,7 +39,7 @@ mixed: {
DEBUG: 0,
ENV: 1,
FOO: 2,
}
},
}
input: {
var ENV = 3;
@@ -60,11 +64,11 @@ mixed: {
x = 0;
}
expect_warnings: [
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,12]',
'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

@@ -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,90 +1,111 @@
issue_269_1: {
options = {unsafe: true};
input: {
f(
String(x),
Number(x),
Boolean(x),
options = {
unsafe: true,
}
input: {
var x = {};
console.log(
String(x),
Number(x),
Boolean(x),
String(),
Number(),
Boolean()
);
}
expect: {
f(
x + '', +x, !!x,
'', 0, false
);
}
String(),
Number(),
Boolean()
);
}
expect: {
var x = {};
console.log(
x + "", +x, !!x,
"", 0, false
);
}
expect_stdout: true
}
issue_269_dangers: {
options = {unsafe: true};
input: {
f(
String(x, x),
Number(x, x),
Boolean(x, x)
);
}
expect: {
f(String(x, x), Number(x, x), Boolean(x, x));
}
options = {
unsafe: true,
}
input: {
var x = {};
console.log(
String(x, x),
Number(x, x),
Boolean(x, x)
);
}
expect: {
var x = {};
console.log(String(x, x), Number(x, x), Boolean(x, x));
}
expect_stdout: true
}
issue_269_in_scope: {
options = {unsafe: true};
input: {
var String, Number, Boolean;
f(
String(x),
Number(x, x),
Boolean(x)
);
}
expect: {
var String, Number, Boolean;
f(String(x), Number(x, x), Boolean(x));
}
options = {
unsafe: true,
}
input: {
var String, Number, Boolean;
var x = {};
console.log(
String(x),
Number(x, x),
Boolean(x)
);
}
expect: {
var String, Number, Boolean;
var x = {};
console.log(String(x), Number(x, x), Boolean(x));
}
expect_stdout: true
}
strings_concat: {
options = {unsafe: true};
input: {
f(
String(x + 'str'),
String('str' + x)
);
}
expect: {
f(
x + 'str',
'str' + x
);
}
options = {
strings: true,
unsafe: true,
}
input: {
var x = {};
console.log(
String(x + "str"),
String("str" + x)
);
}
expect: {
var x = {};
console.log(
x + "str",
"str" + x
);
}
expect_stdout: true
}
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:78,2]',
]
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,8]',
]
}

View File

@@ -26,7 +26,7 @@ warn: {
}().length);
}
expect_warnings: [
"WARN: Function.protoype.caller not supported [test/compress/issue-2719.js:17,19]",
"WARN: Function.protoype.arguments not supported [test/compress/issue-2719.js:17,19]",
"WARN: Function.prototype.arguments not supported [test/compress/issue-2719.js:5,19]",
"WARN: Function.prototype.caller not supported [test/compress/issue-2719.js:5,19]",
]
}

View File

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

128
test/compress/issue-3768.js Normal file
View File

@@ -0,0 +1,128 @@
mangle: {
mangle = {
toplevel: true,
}
input: {
var e = eval, x = 42;
(function() {
console.log(e("typeof x"));
})();
}
expect: {
var e = eval, x = 42;
(function() {
console.log(e("typeof x"));
})();
}
expect_stdout: true
}
compress: {
options = {
collapse_vars: true,
inline: true,
unused: true,
}
input: {
console.log(function() {
var a = 42;
return eval("typeof a");
}(), function(e) {
var a = null;
return e("typeof a");
}(eval), function(eval) {
var a = false;
return eval("typeof a");
}(eval), function(f) {
var a = "STRING";
var eval = f;
return eval("typeof a");
}(eval), function(g) {
var a = eval;
function eval() {
return g;
}
return eval()("typeof a");
}(eval));
}
expect: {
console.log(function() {
var a = 42;
return eval("typeof a");
}(), (0, eval)("typeof a"), function(eval) {
var a = false;
return eval("typeof a");
}(eval), function(f) {
var a = "STRING";
var eval = f;
return eval("typeof a");
}(eval), function(g) {
var a = eval;
function eval() {
return g;
}
return eval()("typeof a");
}(eval));
}
expect_stdout: "number undefined boolean string undefined"
}
call_arg_1: {
mangle = {
toplevel: true,
}
input: {
var z = "foo";
(function() {
var z = false;
(function(e) {
var z = 42;
e("console.log(typeof z)");
})(eval);
})();
}
expect: {
var z = "foo";
(function() {
var o = false;
(function(o) {
var a = 42;
o("console.log(typeof z)");
})(eval);
})();
}
expect_stdout: true
}
call_arg_2: {
mangle = {
toplevel: true,
}
input: {
function eval() {
console.log("PASS");
}
var z = "foo";
(function() {
var z = false;
(function(e) {
var z = 42;
e("console.log(typeof z)");
})(eval);
})();
}
expect: {
function n() {
console.log("PASS");
}
var o = "foo";
(function() {
var o = false;
(function(o) {
var n = 42;
o("console.log(typeof z)");
})(n);
})();
}
expect_stdout: "PASS"
}

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();
@@ -16,7 +16,6 @@ wrongly_optimized: {
function func() {
foo();
}
// TODO: optimize to `func(), bar()`
(func(), 1) && bar();
func(), 1, bar();
}
}

View File

@@ -21,19 +21,19 @@ cond_5: {
}
}
expect: {
some_condition() && some_other_condition() ? do_something() : alternate();
(some_condition() && some_other_condition() ? do_something : alternate)();
if (some_condition() && some_other_condition()) do_something();
}
}
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,9 @@ drop_value: {
wrongly_optimized: {
options = {
conditionals: true,
booleans: true,
conditionals: true,
dead_code: true,
evaluate: true,
expression: true,
}
@@ -99,8 +100,8 @@ wrongly_optimized: {
function func() {
foo();
}
// TODO: optimize to `func(), bar()`
if (func(), 1) bar();
func(), 1;
bar();
}
}
@@ -195,7 +196,7 @@ negate_iife_5_off: {
expression: true,
negate_iife: false,
sequences: true,
};
}
input: {
if ((function(){ return t })()) {
foo(true);
@@ -248,7 +249,9 @@ issue_1254_negate_iife_nested: {
conditional: {
options = {
expression: true,
pure_funcs: [ "pure" ],
pure_funcs: [
"pure"
],
side_effects: true,
}
input: {

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,5 +1,7 @@
remove_redundant_sequence_items: {
options = { side_effects: true };
remove_sequence: {
options = {
side_effects: true,
}
input: {
(0, 1, eval)();
(0, 1, logThis)();
@@ -12,14 +14,36 @@ remove_redundant_sequence_items: {
}
}
dont_remove_this_binding_sequence: {
options = { side_effects: true };
remove_redundant_sequence_items: {
options = {
side_effects: true,
}
input: {
(0, eval)();
(0, logThis)();
(0, _decorators.logThis)();
"use strict";
(0, 1, eval)();
(0, 1, logThis)();
(0, 1, _decorators.logThis)();
}
expect: {
"use strict";
(0, eval)();
logThis();
(0, _decorators.logThis)();
}
}
dont_remove_this_binding_sequence: {
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,25 +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,
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

@@ -3,8 +3,9 @@ this_binding_conditionals: {
conditionals: true,
evaluate: true,
side_effects: true,
};
}
input: {
"use strict";
(1 && a)();
(0 || a)();
(0 || 1 && a)();
@@ -26,6 +27,7 @@ this_binding_conditionals: {
(1 ? eval : 0)();
}
expect: {
"use strict";
a();
a();
a();
@@ -51,49 +53,111 @@ this_binding_conditionals: {
this_binding_collapse_vars: {
options = {
collapse_vars: true,
toplevel: true,
unused: true,
};
}
input: {
var c = a; c();
var d = a.b; d();
var e = eval; e();
function f() {
"use strict";
var c = a; c();
var d = a.b; d();
var e = eval; e();
}
}
expect: {
a();
(0, a.b)();
(0, eval)();
function f() {
"use strict";
a();
(0, a.b)();
(0, eval)();
}
}
}
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);');
(0, 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 (0, 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, 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, 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, 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() {

1057
test/compress/join_vars.js Normal file

File diff suppressed because it is too large Load Diff

1488
test/compress/keep_fargs.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,10 @@
labels_1: {
options = { if_return: true, conditionals: true, dead_code: true };
options = {
conditionals: true,
dead_code: true,
if_return: true,
unused: true,
}
input: {
out: {
if (foo) break out;
@@ -13,7 +18,12 @@ labels_1: {
}
labels_2: {
options = { if_return: true, conditionals: true, dead_code: true };
options = {
conditionals: true,
dead_code: true,
if_return: true,
unused: true,
}
input: {
out: {
if (foo) print("stuff");
@@ -30,7 +40,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 +59,12 @@ labels_3: {
}
labels_4: {
options = { if_return: true, conditionals: true, dead_code: true };
options = {
conditionals: true,
dead_code: true,
if_return: true,
unused: true,
}
input: {
out: for (var i = 0; i < 5; ++i) {
if (i < 3) continue out;
@@ -60,7 +79,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) {
@@ -85,6 +108,9 @@ labels_5: {
}
labels_6: {
options = {
dead_code: true,
}
input: {
out: break out;
};
@@ -92,7 +118,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 +139,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 +161,12 @@ labels_8: {
}
labels_9: {
options = { if_return: true, conditionals: true, dead_code: true };
options = {
conditionals: true,
dead_code: true,
if_return: true,
unused: true,
}
input: {
out: while (foo) {
x();
@@ -146,7 +185,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();

1230
test/compress/let.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,37 +1,45 @@
while_becomes_for: {
options = { loops: true };
options = {
loops: true,
}
input: {
while (foo()) bar();
}
expect: {
for (; foo(); ) bar();
for (;foo();) bar();
}
}
drop_if_break_1: {
options = { loops: true };
options = {
loops: true,
}
input: {
for (;;)
if (foo()) break;
}
expect: {
for (; !foo(););
for (;!foo(););
}
}
drop_if_break_2: {
options = { loops: true };
options = {
loops: true,
}
input: {
for (;bar();)
if (foo()) break;
}
expect: {
for (; bar() && !foo(););
for (;bar() && !foo(););
}
}
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();
@@ -59,22 +70,26 @@ drop_if_break_4: {
}
}
expect: {
for (; bar() && (x(), y(), !foo());) z(), k();
for (;bar() && (x(), y(), !foo());) z(), k();
}
}
drop_if_else_break_1: {
options = { loops: true };
options = {
loops: true,
}
input: {
for (;;) if (foo()) bar(); else break;
}
expect: {
for (; foo(); ) bar();
for (;foo();) bar();
}
}
drop_if_else_break_2: {
options = { loops: true };
options = {
loops: true,
}
input: {
for (;bar();) {
if (foo()) baz();
@@ -82,12 +97,14 @@ drop_if_else_break_2: {
}
}
expect: {
for (; bar() && foo();) baz();
for (;bar() && foo();) baz();
}
}
drop_if_else_break_3: {
options = { loops: true };
options = {
loops: true,
}
input: {
for (;bar();) {
if (foo()) baz();
@@ -97,7 +114,7 @@ drop_if_else_break_3: {
}
}
expect: {
for (; bar() && foo();) {
for (;bar() && foo();) {
baz();
stuff1();
stuff2();
@@ -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();
@@ -118,12 +138,14 @@ drop_if_else_break_4: {
}
}
expect: {
for (; bar() && (x(), y(), foo());) baz(), z(), k();
for (;bar() && (x(), y(), foo());) baz(), z(), k();
}
}
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();
@@ -153,7 +177,7 @@ evaluate: {
loops: true,
passes: 2,
side_effects: true,
};
}
input: {
while (true) {
a();
@@ -177,7 +201,7 @@ evaluate: {
}
}
issue_1532: {
issue_1532_1: {
options = {
evaluate: true,
loops: true,
@@ -186,18 +210,56 @@ issue_1532: {
function f(x, y) {
do {
if (x) break;
foo();
console.log(y);
} while (false);
}
f(null, "PASS");
f(42, "FAIL");
}
expect: {
function f(x, y) {
for (; !x && (console.log(y), false););
}
f(null, "PASS");
f(42, "FAIL");
}
expect_stdout: "PASS"
}
issue_1532_2: {
options = {
evaluate: true,
loops: true,
}
input: {
function f(x, y) {
do {
if (x) {
console.log(x);
break;
}
console.log(y);
} while (false);
}
f(null, "PASS");
f(42, "FAIL");
}
expect: {
function f(x, y) {
do {
if (x) break;
foo();
} while (false);
if (x) {
console.log(x);
break;
}
} while (console.log(y), false);
}
f(null, "PASS");
f(42, "FAIL");
}
expect_stdout: [
"PASS",
"42",
]
}
issue_186: {
@@ -457,7 +519,7 @@ 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);
@@ -485,8 +547,8 @@ dead_code_condition: {
console.log(a);
}
expect: {
var c;
var a = 0, b = 5;
var c;
a += 1, 0,
console.log(a);
}
@@ -499,13 +561,13 @@ issue_2740_1: {
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 (;;) 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: {
@@ -525,6 +587,7 @@ issue_2740_2: {
dead_code: true,
loops: true,
passes: 2,
unused: true,
}
input: {
L1: while (x()) {
@@ -540,6 +603,7 @@ issue_2740_3: {
options = {
dead_code: true,
loops: true,
unused: true,
}
input: {
L1: for (var x = 0; x < 3; x++) {
@@ -550,9 +614,11 @@ issue_2740_3: {
console.log(x, y);
}
expect: {
L1: for (var x = 0; x < 3; x++)
for (var y = 0; y < 2; y++)
L1: for (var x = 0; x < 3; x++) {
var y = 0;
if (y < 2)
break L1;
}
console.log(x, y);
}
expect_stdout: "0 0"
@@ -563,6 +629,7 @@ issue_2740_4: {
dead_code: true,
loops: true,
passes: 2,
unused: true,
}
input: {
L1: for (var x = 0; x < 3; x++) {
@@ -587,6 +654,7 @@ issue_2740_5: {
dead_code: true,
loops: true,
passes: 2,
unused: true,
}
input: {
L1: for (var x = 0; x < 3; x++) {
@@ -622,3 +690,593 @@ issue_2904: {
}
expect_stdout: "1"
}
issue_3371: {
options = {
functions: true,
join_vars: true,
loops: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
var a = function() {
console.log("PASS");
};
while (a());
})();
}
expect: {
(function() {
function a() {
console.log("PASS");
}
for (;a(););
})();
}
expect_stdout: "PASS"
}
step: {
options = {
loops: true,
side_effects: true,
}
input: {
for (var i = 0; i < 42; "foo", i++, "bar");
console.log(i);
}
expect: {
for (var i = 0; i < 42; i++);
console.log(i);
}
expect_stdout: "42"
}
empty_for_in: {
options = {
loops: true,
toplevel: true,
unused: true,
}
input: {
for (var a in [ 1, 2, 3 ]) {
var b = a + 1;
}
}
expect: {}
expect_warnings: [
"WARN: Dropping unused variable b [test/compress/loops.js:2,16]",
"INFO: Dropping unused loop variable a [test/compress/loops.js:1,17]",
]
}
empty_for_in_used: {
options = {
loops: true,
toplevel: true,
unused: true,
}
input: {
for (var a in [ 1, 2, 3 ]) {
var b = a + 1;
}
console.log(a);
}
expect: {
for (var a in [ 1, 2, 3 ]);
console.log(a);
}
expect_stdout: "2"
expect_warnings: [
"WARN: Dropping unused variable b [test/compress/loops.js:2,16]",
]
}
empty_for_in_side_effects: {
options = {
loops: true,
toplevel: true,
unused: true,
}
input: {
for (var a in {
foo: console.log("PASS")
}) {
var b = a + "bar";
}
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
expect_warnings: [
"WARN: Dropping unused variable b [test/compress/loops.js:4,16]",
"INFO: Dropping unused loop variable a [test/compress/loops.js:1,17]",
"WARN: Side effects in object of for-in loop [test/compress/loops.js:2,17]",
]
}
empty_for_in_prop_init: {
options = {
loops: true,
pure_getters: "strict",
unused: true,
}
input: {
console.log(function f() {
var a = "bar";
for ((a, f)[a] in console.log("foo"));
return a;
}());
}
expect: {
console.log(function() {
var a = "bar";
console.log("foo");
return a;
}());
}
expect_stdout: [
"foo",
"bar",
]
expect_warnings: [
"INFO: Dropping unused loop variable f [test/compress/loops.js:3,21]",
"WARN: Side effects in object of for-in loop [test/compress/loops.js:3,30]",
]
}
issue_3631_1: {
options = {
dead_code: true,
evaluate: true,
loops: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var c = 0;
L: do {
for (;;) continue L;
var b = 1;
} while (b && c++);
console.log(c);
}
expect: {
var c = 0;
do {
var b;
} while (b && c++);
console.log(c);
}
expect_stdout: "0"
}
issue_3631_2: {
options = {
dead_code: true,
evaluate: true,
loops: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
L: for (var a = 1; a--; console.log(b)) {
for (;;) continue L;
var b = "FAIL";
}
}
expect: {
for (var a = 1; a--; console.log(b))
var b;
}
expect_stdout: "undefined"
}
loop_if_break: {
options = {
dead_code: true,
loops: true,
}
input: {
function f(a, b) {
try {
while (a) {
if (b) {
break;
var c = 42;
console.log(c);
} else {
var d = false;
throw d;
}
}
} catch (e) {
console.log("E:", e);
}
console.log(a, b, c, d);
}
f(0, 0);
f(0, 1);
f(1, 0);
f(1, 1);
}
expect: {
function f(a, b) {
try {
for (;a && !b;) {
var d = false;
throw d;
var c;
}
} catch (e) {
console.log("E:", e);
}
console.log(a, b, c, d);
}
f(0, 0);
f(0, 1);
f(1, 0);
f(1, 1);
}
expect_stdout: [
"0 0 undefined undefined",
"0 1 undefined undefined",
"E: false",
"1 0 undefined false",
"1 1 undefined undefined",
]
}
loop_return: {
options = {
dead_code: true,
loops: true,
}
input: {
function f(a) {
while (a) return 42;
return "foo";
}
console.log(f(0), f(1));
}
expect: {
function f(a) {
if (a) return 42;
return "foo";
}
console.log(f(0), f(1));
}
expect_stdout: "foo 42"
}
issue_3634_1: {
options = {
loops: true,
}
input: {
var b = 0;
L: while (++b < 2)
while (1)
if (b) break L;
console.log(b);
}
expect: {
var b = 0;
L: for (;++b < 2;)
for (;1;)
if (b) break L;
console.log(b);
}
expect_stdout: "1"
}
issue_3634_2: {
options = {
loops: true,
}
input: {
var b = 0;
L: while (++b < 2)
while (1)
if (!b)
continue L;
else
break L;
console.log(b);
}
expect: {
var b = 0;
L: for (;++b < 2;)
for (;1;)
if (!b)
continue L;
else
break L;
console.log(b);
}
expect_stdout: "1"
}
issue_4075: {
options = {
loops: true,
unused: true,
}
input: {
var a = "FAIL";
(function() {
for (a in { PASS: 0 });
})()
console.log(a);
}
expect: {
var a = "FAIL";
(function() {
for (a in { PASS: 0 });
})()
console.log(a);
}
expect_stdout: "PASS"
}
issue_4082: {
options = {
keep_fargs: "strict",
loops: true,
unused: true,
}
input: {
var a = "PASS";
(function(a) {
for (a in "foo")
var b;
})();
console.log(a);
}
expect: {
var a = "PASS";
(function(a) {
for (a in "foo");
})();
console.log(a);
}
expect_stdout: "PASS"
}
issue_4084: {
options = {
keep_fargs: "strict",
loops: true,
passes: 2,
reduce_vars: true,
unused: true,
}
input: {
console.log(function() {
function f(a) {
var b = a++;
for (a in "foo");
}
f();
return typeof a;
}());
}
expect: {
console.log(function() {
(function() {
0;
})();
return typeof a;
}());
}
expect_stdout: "undefined"
}
issue_4091_1: {
options = {
loops: true,
toplevel: true,
unused: true,
}
input: {
try {
throw "FAIL";
} catch (e) {
for (var e in 42);
}
console.log(e && e);
}
expect: {
try {
throw "FAIL";
} catch (e) {
var e;
}
console.log(e && e);
}
expect_stdout: "undefined"
}
issue_4091_2: {
options = {
loops: true,
toplevel: true,
unused: true,
}
input: {
try {
throw "FAIL";
} catch (e) {
for (e in 42);
var e;
}
console.log(e && e);
}
expect: {
try {
throw "FAIL";
} catch (e) {
var e;
}
console.log(e && e);
}
expect_stdout: "undefined"
}
issue_4182_1: {
options = {
loops: true,
}
input: {
(function() {
do {
try {
return;
} finally {
continue;
}
console.log("FAIL");
} while (0);
console.log("PASS");
})();
}
expect: {
(function() {
do {
try {
return;
} finally {
continue;
}
console.log("FAIL");
} while (0);
console.log("PASS");
})();
}
expect_stdout: "PASS"
}
issue_4182_2: {
options = {
loops: true,
}
input: {
(function() {
L: do {
do {
try {
return;
} finally {
continue L;
}
console.log("FAIL");
} while (0);
console.log("FAIL");
} while (0);
console.log("PASS");
})();
}
expect: {
(function() {
L: do {
do {
try {
return;
} finally {
continue L;
}
} while (console.log("FAIL"), 0);
console.log("FAIL");
} while (0);
console.log("PASS");
})();
}
expect_stdout: "PASS"
}
do_continue: {
options = {
loops: true,
}
input: {
try {
do {
continue;
} while ([ A ]);
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
do {
continue;
} while ([ A ]);
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
}
issue_4240: {
options = {
loops: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function(a) {
function f() {
var o = { PASS: 42 };
for (a in o);
}
(function() {
if (f());
})();
console.log(a);
})();
}
expect: {
(function(a) {
(function() {
if (function() {
for (a in { PASS: 42 });
}());
})();
console.log(a);
})();
}
expect_stdout: "PASS"
}
issue_4355: {
options = {
dead_code: true,
evaluate: true,
loops: true,
side_effects: true,
unused: true,
}
input: {
while (function() {
var a;
for (a in console.log("PASS"))
var b = 0;
}())
var c;
}
expect: {
(function() {
console.log("PASS");
})();
var c;
}
expect_stdout: "PASS"
}

3185
test/compress/merge_vars.js Normal file

File diff suppressed because it is too large Load Diff

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() })();
}
@@ -24,7 +24,7 @@ negate_iife_2: {
options = {
inline: true,
negate_iife: true,
};
}
input: {
(function(){ return {} })().x = 10;
}
@@ -45,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);
}
@@ -88,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);
}
@@ -117,10 +117,10 @@ negate_iife_3_off_evaluate: {
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(){
@@ -136,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);
@@ -171,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);
@@ -194,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);
@@ -217,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;
@@ -250,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;
@@ -283,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() {
@@ -356,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;
}

File diff suppressed because it is too large Load Diff

457
test/compress/objects.js Normal file
View File

@@ -0,0 +1,457 @@
duplicate_key: {
options = {
objects: true,
side_effects: true,
}
input: {
var o = {
a: 1,
b: 2,
a: 3,
};
for (var k in o)
console.log(k, o[k]);
}
expect: {
var o = {
a: 3,
b: 2,
};
for (var k in o)
console.log(k, o[k]);
}
expect_stdout: [
"a 3",
"b 2",
]
}
duplicate_key_strict: {
options = {
objects: true,
side_effects: true,
}
input: {
"use strict";
var o = {
a: 1,
b: 2,
a: 3,
};
for (var k in o)
console.log(k, o[k]);
}
expect: {
"use strict";
var o = {
a: 1,
a: 3,
b: 2,
};
for (var k in o)
console.log(k, o[k]);
}
expect_stdout: true
}
duplicate_key_side_effect: {
options = {
objects: true,
side_effects: true,
}
input: {
var o = {
a: 1,
b: o = 2,
a: 3,
};
for (var k in o)
console.log(k, o[k]);
}
expect: {
var o = {
a: 1,
b: o = 2,
a: 3,
};
for (var k in o)
console.log(k, o[k]);
}
expect_stdout: [
"a 3",
"b 2",
]
}
duplicate_key_with_accessor: {
options = {
objects: true,
side_effects: true,
}
input: {
[
{
a: 0,
b: 1,
a: 2,
set b(v) {},
},
{
a: 3,
b: 4,
get a() {
return 5;
},
a: 6,
b: 7,
a: 8,
b: 9,
},
].forEach(function(o) {
for (var k in o)
console.log(k, o[k]);
});
}
expect: {
[
{
a: 2,
b: 1,
set b(v) {},
},
{
a: 3,
b: 4,
get a() {
return 5;
},
a: 8,
b: 9,
},
].forEach(function(o) {
for (var k in o)
console.log(k, o[k]);
});
}
expect_stdout: true
}
unsafe_object_repeated: {
options = {
evaluate: true,
objects: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unsafe: true,
}
input: {
var o = { a: { b: 1 }, a: 1 };
console.log(
o + 1,
o.a + 1,
o.b + 1,
o.a.b + 1
);
}
expect: {
var o = { a: 1 };
console.log(
o + 1,
2,
o.b + 1,
NaN
);
}
expect_stdout: true
}
numeric_literal: {
options = {
objects: true,
side_effects: true,
}
mangle = {
properties: true,
}
beautify = {
beautify: true,
}
input: {
var obj = {
0: 0,
"-0": 1,
42: 2,
"42": 3,
0x25: 4,
"0x25": 5,
1E42: 6,
"1E42": 7,
"1e+42": 8,
};
console.log(obj[-0], obj[-""], obj["-0"]);
console.log(obj[42], obj["42"]);
console.log(obj[0x25], obj["0x25"], obj[37], obj["37"]);
console.log(obj[1E42], obj["1E42"], obj["1e+42"]);
}
expect_exact: [
'var obj = {',
' 0: 0,',
' "-0": 1,',
' 42: 3,',
' 37: 4,',
' o: 5,',
' 1e42: 8,',
' b: 7',
'};',
'',
'console.log(obj[-0], obj[-""], obj["-0"]);',
'',
'console.log(obj[42], obj["42"]);',
'',
'console.log(obj[37], obj["o"], obj[37], obj["37"]);',
'',
'console.log(obj[1e42], obj["b"], obj["1e+42"]);',
]
expect_stdout: [
"0 0 1",
"3 3",
"4 5 4 4",
"8 7 8",
]
}
evaluate_computed_key: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
["foo" + "bar"]: "PASS",
}.foobar);
}
expect: {
console.log({
foobar: "PASS",
}.foobar);
}
expect_stdout: "PASS"
node_version: ">=4"
}
keep_computed_key: {
options = {
side_effects: true,
}
input: {
({
[console.log("PASS")]: 42,
});
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
shorthand_keywords: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var async = 1, get = 2, set = 3, o = {
async,
get,
set,
};
console.log(o.async, o.get, o.set);
}
expect: {
console.log(1, 2, 3);
}
expect_stdout: "1 2 3"
node_version: ">=6"
}
issue_4269_1: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
get 0() {
return "FAIL";
},
[0]: "PASS",
}[0]);
}
expect: {
console.log({
get 0() {
return "FAIL";
},
[0]: "PASS",
}[0]);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4269_2: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
get [0]() {
return "FAIL";
},
0: "PASS",
}[0]);
}
expect: {
console.log({
get [0]() {
return "FAIL";
},
0: "PASS",
}[0]);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4269_3: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
["foo"]: "bar",
get 42() {
return "FAIL";
},
42: "PASS",
}[42]);
}
expect: {
console.log({
foo: "bar",
get [42]() {
return "FAIL";
},
42: "PASS",
}[42]);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4269_4: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
get 42() {
return "FAIL";
},
["foo"]: "bar",
42: "PASS",
}[42]);
}
expect: {
console.log({
get 42() {
return "FAIL";
},
foo: "bar",
[42]: "PASS",
}[42]);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4269_5: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
get 42() {
return "FAIL";
},
[console]: "bar",
42: "PASS",
}[42]);
}
expect: {
console.log({
get 42() {
return "FAIL";
},
[console]: "bar",
42: "PASS",
}[42]);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4380: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
get 0() {
return "FAIL 1";
},
0: "FAIL 2",
[0]: "PASS",
}[0]);
}
expect: {
console.log({
get 0() {
return "FAIL 1";
},
[0]: ("FAIL 2", "PASS"),
}[0]);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4415: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
["00"]: "FAIL",
}[0] || "PASS");
}
expect: {
console.log({
"00": "FAIL",
}[0] || "PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}

View File

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

View File

@@ -130,7 +130,7 @@ evaluate_string_length: {
}
}
mangle_properties: {
mangle_properties_1: {
mangle = {
properties: {
keep_quoted: false,
@@ -152,6 +152,53 @@ mangle_properties: {
}
}
mangle_properties_2: {
mangle = {
properties: {
reserved: [
"value",
]
},
}
input: {
var o = {
prop1: 1,
};
Object.defineProperty(o, "prop2", {
value: 2,
});
Object.defineProperties(o, {
prop3: {
value: 3,
},
});
console.log("prop1", o.prop1, "prop1" in o);
console.log("prop2", o.prop2, o.hasOwnProperty("prop2"));
console.log("prop3", o.prop3, Object.getOwnPropertyDescriptor(o, "prop3").value);
}
expect: {
var o = {
o: 1,
};
Object.defineProperty(o, "p", {
value: 2,
});
Object.defineProperties(o, {
r: {
value: 3,
},
});
console.log("prop1", o.o, "o" in o);
console.log("prop2", o.p, o.hasOwnProperty("p"));
console.log("prop3", o.r, Object.getOwnPropertyDescriptor(o, "r").value);
}
expect_stdout: [
"prop1 1 true",
"prop2 2 true",
"prop3 3 3",
]
}
mangle_unquoted_properties: {
options = {
evaluate: true,
@@ -817,6 +864,29 @@ issue_2208_5: {
expect_stdout: "42"
}
issue_2208_6: {
options = {
inline: true,
properties: true,
side_effects: true,
}
input: {
a = 42;
console.log(("FAIL", {
p: function() {
return this.a;
}
}.p)());
}
expect: {
a = 42;
console.log(function() {
return this.a;
}());
}
expect_stdout: "42"
}
issue_2256: {
options = {
side_effects: true,
@@ -1023,16 +1093,22 @@ array_hole: {
side_effects: true,
}
input: {
console.log(
[ 1, 2, , 3][1],
[ 1, 2, , 3][2],
[ 1, 2, , 3][3]
);
Array.prototype[2] = "PASS";
console.log([ 1, 2, , 3 ][1]);
console.log([ 1, 2, , 3 ][2]);
console.log([ 1, 2, , 3 ][3]);
}
expect: {
console.log(2, void 0, 3);
Array.prototype[2] = "PASS";
console.log(2);
console.log([ , , , ][2]);
console.log(3);
}
expect_stdout: "2 undefined 3"
expect_stdout: [
"2",
"PASS",
"3",
]
}
new_this: {
@@ -1047,11 +1123,7 @@ new_this: {
}
}.f(42);
}
expect: {
new function(a) {
this.a = a;
}(42);
}
expect: {}
}
issue_2513: {
@@ -1120,558 +1192,6 @@ const_prop_assign_pure: {
}
}
join_object_assignments_1: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function() {
var x = {
a: 1,
c: (console.log("c"), "C"),
};
x.b = 2;
x[3] = function() {
console.log(x);
},
x["a"] = /foo/,
x.bar = x;
return x;
}());
}
expect: {
console.log(function() {
var x = {
a: 1,
c: (console.log("c"), "C"),
b: 2,
3: function() {
console.log(x);
},
a: /foo/,
};
x.bar = x;
return x;
}());
}
expect_stdout: true
}
join_object_assignments_2: {
options = {
evaluate: true,
hoist_props: true,
join_vars: true,
passes: 3,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
foo: 1,
};
o.bar = 2;
o.baz = 3;
console.log(o.foo, o.bar + o.bar, o.foo * o.bar * o.baz);
}
expect: {
console.log(1, 4, 6);
}
expect_stdout: "1 4 6"
}
join_object_assignments_3: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function() {
var o = {
a: "PASS",
}, a = o.a;
o.a = "FAIL";
return a;
}());
}
expect: {
console.log(function() {
var o = {
a: "PASS",
}, a = o.a;
o.a = "FAIL";
return a;
}());
}
expect_stdout: "PASS"
}
join_object_assignments_4: {
options = {
join_vars: true,
sequences: true,
}
input: {
var o;
console.log(o);
o = {};
o.a = "foo";
console.log(o.b);
o.b = "bar";
console.log(o.a);
}
expect: {
var o;
console.log(o),
o = {
a: "foo",
},
console.log(o.b),
o.b = "bar",
console.log(o.a);
}
expect_stdout: [
"undefined",
"undefined",
"foo",
]
}
join_object_assignments_return_1: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
return o.q = "foo";
}());
}
expect: {
console.log(function() {
var o = {
p: 3,
q: "foo"
};
return o.q;
}());
}
expect_stdout: "foo"
}
join_object_assignments_return_2: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
return o.q = /foo/,
o.r = "bar";
}());
}
expect: {
console.log(function() {
var o = {
p: 3,
q: /foo/,
r: "bar"
};
return o.r;
}());
}
expect_stdout: "bar"
}
join_object_assignments_return_3: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
return o.q = "foo",
o.p += "",
console.log(o.q),
o.p;
}());
}
expect: {
console.log(function() {
var o = {
p: 3,
q: "foo"
};
return o.p += "",
console.log(o.q),
o.p;
}());
}
expect_stdout: [
"foo",
"3",
]
}
join_object_assignments_for: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {
p: 3
};
for (o.q = "foo"; console.log(o.q););
return o.p;
}());
}
expect: {
console.log(function() {
for (var o = {
p: 3,
q: "foo"
}; console.log(o.q););
return o.p;
}());
}
expect_stdout: [
"foo",
"3",
]
}
join_object_assignments_if: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {};
if (o.a = "PASS") return o.a;
}())
}
expect: {
console.log(function() {
var o = { a: "PASS" };
if (o.a) return o.a;
}());
}
expect_stdout: "PASS"
}
join_object_assignments_forin: {
options = {
join_vars: true,
}
input: {
console.log(function() {
var o = {};
for (var a in o.a = "PASS", o)
return o[a];
}())
}
expect: {
console.log(function() {
var o = { a: "PASS" };
for (var a in o)
return o[a];
}());
}
expect_stdout: "PASS"
}
join_object_assignments_negative: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[0] = 0;
o[-0] = 1;
o[-1] = 2;
console.log(o[0], o[-0], o[-1]);
}
expect: {
var o = {
0: 0,
0: 1,
"-1": 2
};
console.log(o[0], o[-0], o[-1]);
}
expect_stdout: "1 1 2"
}
join_object_assignments_NaN_1: {
options = {
join_vars: true,
}
input: {
var o = {};
o[NaN] = 1;
o[0/0] = 2;
console.log(o[NaN], o[NaN]);
}
expect: {
var o = {};
o[NaN] = 1;
o[0/0] = 2;
console.log(o[NaN], o[NaN]);
}
expect_stdout: "2 2"
}
join_object_assignments_NaN_2: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[NaN] = 1;
o[0/0] = 2;
console.log(o[NaN], o[NaN]);
}
expect: {
var o = {
NaN: 1,
NaN: 2
};
console.log(o.NaN, o.NaN);
}
expect_stdout: "2 2"
}
join_object_assignments_null_0: {
options = {
join_vars: true,
}
input: {
var o = {};
o[null] = 1;
console.log(o[null]);
}
expect: {
var o = {};
o[null] = 1;
console.log(o[null]);
}
expect_stdout: "1"
}
join_object_assignments_null_1: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[null] = 1;
console.log(o[null]);
}
expect: {
var o = {
null: 1
};
console.log(o.null);
}
expect_stdout: "1"
}
join_object_assignments_void_0: {
options = {
evaluate: true,
join_vars: true,
}
input: {
var o = {};
o[void 0] = 1;
console.log(o[void 0]);
}
expect: {
var o = {
undefined: 1
};
console.log(o[void 0]);
}
expect_stdout: "1"
}
join_object_assignments_undefined_1: {
options = {
join_vars: true,
}
input: {
var o = {};
o[undefined] = 1;
console.log(o[undefined]);
}
expect: {
var o = {};
o[void 0] = 1;
console.log(o[void 0]);
}
expect_stdout: "1"
}
join_object_assignments_undefined_2: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[undefined] = 1;
console.log(o[undefined]);
}
expect: {
var o = {
undefined : 1
};
console.log(o[void 0]);
}
expect_stdout: "1"
}
join_object_assignments_Infinity: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[Infinity] = 1;
o[1/0] = 2;
o[-Infinity] = 3;
o[-1/0] = 4;
console.log(o[Infinity], o[1/0], o[-Infinity], o[-1/0]);
}
expect: {
var o = {
Infinity: 1,
Infinity: 2,
"-Infinity": 3,
"-Infinity": 4
};
console.log(o[1/0], o[1/0], o[-1/0], o[-1/0]);
}
expect_stdout: "2 2 4 4"
}
join_object_assignments_regex: {
options = {
evaluate: true,
join_vars: true,
properties: true,
}
input: {
var o = {};
o[/rx/] = 1;
console.log(o[/rx/]);
}
expect: {
var o = {
"/rx/": 1
};
console.log(o[/rx/]);
}
expect_stdout: "1"
}
issue_2816: {
options = {
join_vars: true,
}
input: {
"use strict";
var o = {
a: 1
};
o.b = 2;
o.a = 3;
o.c = 4;
console.log(o.a, o.b, o.c);
}
expect: {
"use strict";
var o = {
a: 1,
b: 2
};
o.a = 3;
o.c = 4;
console.log(o.a, o.b, o.c);
}
expect_stdout: "3 2 4"
}
issue_2893_1: {
options = {
join_vars: true,
}
input: {
var o = {
get a() {
return "PASS";
},
};
o.a = "FAIL";
console.log(o.a);
}
expect: {
var o = {
get a() {
return "PASS";
},
};
o.a = "FAIL";
console.log(o.a);
}
expect_stdout: "PASS"
}
issue_2893_2: {
options = {
join_vars: true,
}
input: {
var o = {
set a(v) {
this.b = v;
},
b: "FAIL",
};
o.a = "PASS";
console.log(o.b);
}
expect: {
var o = {
set a(v) {
this.b = v;
},
b: "FAIL",
};
o.a = "PASS";
console.log(o.b);
}
expect_stdout: "PASS"
}
issue_869_1: {
mangle = {
properties: {
@@ -1729,3 +1249,132 @@ issue_869_2: {
}
expect_stdout: "PASS"
}
issue_3188_1: {
options = {
collapse_vars: true,
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
}
input: {
(function() {
function f() {
console.log(this.p);
}
(function() {
var o = {
p: "PASS",
f: f
};
o.f();
})();
})();
}
expect: {
(function() {
function f() {
console.log(this.p);
}
({
p: "PASS",
f: f
}).f();
var o;
})();
}
expect_stdout: "PASS"
}
issue_3188_2: {
options = {
collapse_vars: true,
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
(function() {
var f = function() {
console.log(this.p);
};
function g() {
var o = {
p: "PASS",
f: f
};
o.f();
}
g();
})();
}
expect: {
({
p: "PASS",
f: function() {
console.log(this.p);
}
}).f();
}
expect_stdout: "PASS"
}
issue_3188_3: {
options = {
collapse_vars: true,
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
}
input: {
(function() {
function f() {
console.log(this[0]);
}
(function() {
var o = ["PASS", f];
o[1]();
})();
})();
}
expect: {
(function() {
function f() {
console.log(this[0]);
}
["PASS", f][1]();
var o;
})();
}
expect_stdout: "PASS"
}
issue_3389: {
options = {
evaluate: true,
properties: true,
reduce_vars: true,
unsafe: true,
}
input: {
(function() {
var a = "PASS";
if (delete b)
b = a[null] = 42;
console.log(a);
})();
}
expect: {
(function() {
var a = "PASS";
if (delete b)
b = a.null = 42;
console.log(a);
})();
}
expect_stdout: "PASS"
}

View File

@@ -136,7 +136,7 @@ relational: {
side_effects :true,
}
input: {
foo() in foo();
foo() in new foo();
foo() instanceof bar();
foo() < "bar";
bar() > foo();
@@ -642,3 +642,168 @@ issue_3065_4: {
})();
}
}
issue_3325_1: {
options = {
pure_funcs: "cb",
side_effects: true,
}
input: {
function cb() {
console.log("PASS");
}
cb();
}
expect: {
function cb() {
console.log("PASS");
}
}
}
issue_3325_2: {
options = {
pure_funcs: "xxxcbxxx",
side_effects: true,
}
input: {
function cb() {
console.log("PASS");
}
cb();
}
expect: {
function cb() {
console.log("PASS");
}
cb();
}
expect_stdout: "PASS"
}
issue_3858: {
options = {
collapse_vars: true,
inline: true,
keep_fargs: "strict",
unused: true,
}
input: {
var f = function(a) {
return /*@__PURE__*/ function(b) {
console.log(b);
}(a);
};
f("PASS");
}
expect: {
var f = function(a) {
return function() {
console.log(a);
}();
};
f("PASS");
}
expect_stdout: "PASS"
}
inline_pure_call_1: {
options = {
collapse_vars: true,
inline: true,
keep_fargs: "strict",
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var f = function(a) {
return /*@__PURE__*/ function(b) {
console.log(b);
}(a);
};
f("PASS");
}
expect: {}
}
inline_pure_call_2: {
options = {
collapse_vars: true,
inline: true,
keep_fargs: "strict",
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var f = function(a) {
return /*@__PURE__*/ function(b) {
console.log(b);
}(a);
};
var a = f("PASS");
}
expect: {}
}
inline_pure_call_3: {
options = {
collapse_vars: true,
evaluate: true,
inline: true,
keep_fargs: "strict",
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var f = function(a) {
return /*@__PURE__*/ function(b) {
console.log(b);
}(a);
};
var a = f("PASS");
console.log(a);
}
expect: {
var a = function() {
console.log("PASS");
}();
console.log(a);
}
expect_stdout: [
"PASS",
"undefined",
]
}
inline_pure_call_4: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = /*@__PURE__*/ function() {
return console.log("PASS"), 42;
}();
console.log(a);
}
expect: {
var a = function() {
return console.log("PASS"), 42;
}();
console.log(a);
}
expect_stdout: [
"PASS",
"42",
]
}

View File

@@ -187,10 +187,10 @@ issue_2110_1: {
options = {
collapse_vars: true,
pure_getters: "strict",
sequences: true,
side_effects: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
@@ -848,9 +848,8 @@ collapse_vars_1_true: {
}
expect: {
function f(a, b) {
for (;;) {
for (;;)
if (a.g() || b.p) break;
}
}
}
}
@@ -1161,3 +1160,51 @@ collapse_rhs_lhs: {
}
expect_stdout: "1 3"
}
drop_arguments: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
(function() {
arguments.slice = function() {
console.log("PASS");
};
arguments[42];
arguments.length;
arguments.slice();
})();
}
expect: {
(function() {
arguments.slice = function() {
console.log("PASS");
};
arguments.slice();
})();
}
expect_stdout: "PASS"
}
issue_3427: {
options = {
assignments: true,
collapse_vars: true,
inline: true,
passes: 2,
pure_getters: "strict",
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a;
(function(b) {
b.p = 42;
})(a || (a = {}));
}
expect: {}
expect_stdout: true
}

File diff suppressed because it is too large Load Diff

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

@@ -0,0 +1,475 @@
regexp_simple: {
input: {
/rx/ig
}
expect_exact: "/rx/gi;"
}
regexp_slashes: {
input: {
/\\\/rx\/\\/ig
}
expect_exact: "/\\\\\\/rx\\/\\\\/gi;"
}
regexp_1: {
input: {
console.log(JSON.stringify("COMPASS? Overpass.".match(/([Sap]+)/ig)));
}
expect: {
console.log(JSON.stringify("COMPASS? Overpass.".match(/([Sap]+)/gi)));
}
expect_stdout: '["PASS","pass"]'
}
regexp_2: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(JSON.stringify("COMPASS? Overpass.".match(new RegExp("([Sap]+)", "ig"))));
}
expect: {
console.log(JSON.stringify("COMPASS? Overpass.".match(/([Sap]+)/gi)));
}
expect_stdout: '["PASS","pass"]'
}
regexp_properties: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(/abc/g.source, /abc/g.global, /abc/g.ignoreCase, /abc/g.lastIndex, /abc/g.multiline);
}
expect: {
console.log("abc", true, false, /abc/g.lastIndex, false);
}
expect_stdout: "abc true false 0 false"
}
issue_3434_1: {
options = {
evaluate: true,
unsafe: true,
}
beautify = {
beautify: true,
}
input: {
var o = {
"\n": RegExp("\n"),
"\r": RegExp("\r"),
"\t": RegExp("\t"),
"\b": RegExp("\b"),
"\f": RegExp("\f"),
"\0": RegExp("\0"),
"\x0B": RegExp("\x0B"),
"\u2028": RegExp("\u2028"),
"\u2029": RegExp("\u2029"),
};
for (var c in o)
console.log(o[c].test("\\"), o[c].test(c));
}
expect_exact: [
"var o = {",
' "\\n": /\\n/,',
' "\\r": /\\r/,',
' "\\t": /\t/,',
' "\\b": /\b/,',
' "\\f": /\f/,',
' "\\0": /\0/,',
' "\\v": /\v/,',
' "\\u2028": /\\u2028/,',
' "\\u2029": /\\u2029/',
"};",
"",
'for (var c in o) console.log(o[c].test("\\\\"), o[c].test(c));',
]
expect_stdout: [
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
]
}
issue_3434_2: {
options = {
evaluate: true,
unsafe: true,
}
beautify = {
beautify: true,
}
input: {
var o = {
"\n": RegExp("\\\n"),
"\r": RegExp("\\\r"),
"\t": RegExp("\\\t"),
"\b": RegExp("\\\b"),
"\f": RegExp("\\\f"),
"\0": RegExp("\\\0"),
"\x0B": RegExp("\\\x0B"),
"\u2028": RegExp("\\\u2028"),
"\u2029": RegExp("\\\u2029"),
};
for (var c in o)
console.log(o[c].test("\\"), o[c].test(c));
}
expect_exact: [
"var o = {",
' "\\n": /\\n/,',
' "\\r": /\\r/,',
' "\\t": /\t/,',
' "\\b": /\b/,',
' "\\f": /\f/,',
' "\\0": /\0/,',
' "\\v": /\v/,',
' "\\u2028": /\\u2028/,',
' "\\u2029": /\\u2029/',
"};",
"",
'for (var c in o) console.log(o[c].test("\\\\"), o[c].test(c));',
]
expect_stdout: [
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
]
}
issue_3434_3: {
options = {
evaluate: true,
unsafe: true,
}
input: {
RegExp("\n");
RegExp("\r");
RegExp("\\n");
RegExp("\\\n");
RegExp("\\\\n");
RegExp("\\\\\n");
RegExp("\\\\\\n");
RegExp("\\\\\\\n");
RegExp("\u2028");
RegExp("\u2029");
RegExp("\n\r\u2028\u2029");
RegExp("\\\nfo\n[\n]o\\bbb");
}
expect: {
/\n/;
/\r/;
/\n/;
/\n/;
/\\n/;
/\\\n/;
/\\\n/;
/\\\n/;
/\u2028/;
/\u2029/;
/\n\r\u2028\u2029/;
/\nfo\n[\n]o\bbb/;
}
}
issue_3434_4: {
options = {
evaluate: true,
unsafe: true,
}
input: {
[
[ "", RegExp("") ],
[ "/", RegExp("/") ],
[ "//", RegExp("//") ],
[ "\/", RegExp("\\/") ],
[ "///", RegExp("///") ],
[ "/\/", RegExp("/\\/") ],
[ "\//", RegExp("\\//") ],
[ "\\/", RegExp("\\\\/") ],
[ "////", RegExp("////") ],
[ "//\/", RegExp("//\\/") ],
[ "/\//", RegExp("/\\//") ],
[ "/\\/", RegExp("/\\\\/") ],
[ "\///", RegExp("\\///") ],
[ "\/\/", RegExp("\\/\\/") ],
[ "\\//", RegExp("\\\\//") ],
[ "\\\/", RegExp("\\\\\\/") ],
].forEach(function(test) {
console.log(test[1].test("\\"), test[1].test(test[0]));
});
}
expect: {
[
[ "", /(?:)/ ],
[ "/", /\// ],
[ "//", /\/\// ],
[ "/", /\// ],
[ "///", /\/\/\// ],
[ "//", /\/\// ],
[ "//", /\/\// ],
[ "\\/", /\\\// ],
[ "////", /\/\/\/\// ],
[ "///", /\/\/\// ],
[ "///", /\/\/\// ],
[ "/\\/", /\/\\\// ],
[ "///", /\/\/\// ],
[ "//", /\/\// ],
[ "\\//", /\\\/\// ],
[ "\\/", /\\\// ],
].forEach(function(test) {
console.log(test[1].test("\\"), test[1].test(test[0]));
});
}
expect_stdout: [
"true true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
"false true",
]
}
exec: {
options = {
evaluate: true,
loops: true,
unsafe: true,
}
input: {
while (/a/.exec("AAA"))
console.log("FAIL");
console.log("PASS");
}
expect: {
for (;null;)
console.log("FAIL");
console.log("PASS");
}
expect_stdout: "PASS"
}
exec_global: {
options = {
evaluate: true,
loops: true,
unsafe: true,
}
input: {
while (/a/g.exec("AAA"))
console.log("FAIL");
console.log("PASS");
}
expect: {
for (;null;)
console.log("FAIL");
console.log("PASS");
}
expect_stdout: "PASS"
}
test: {
options = {
evaluate: true,
unsafe: true,
}
input: {
while (/a/.test("AAA"))
console.log("FAIL");
console.log("PASS");
}
expect: {
while (false)
console.log("FAIL");
console.log("PASS");
}
expect_stdout: "PASS"
}
test_global: {
options = {
evaluate: true,
unsafe: true,
}
input: {
while (/a/g.test("AAA"))
console.log("FAIL");
console.log("PASS");
}
expect: {
while (false)
console.log("FAIL");
console.log("PASS");
}
expect_stdout: "PASS"
}
var_exec: {
options = {
evaluate: true,
loops: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
}
input: {
var r = /a/;
while (r.exec("AAA"))
console.log("FAIL");
console.log("PASS");
}
expect: {
var r = /a/;
for (;null;)
console.log("FAIL");
console.log("PASS");
}
expect_stdout: "PASS"
}
var_exec_global: {
options = {
evaluate: true,
loops: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
}
input: {
var r = /a/g;
while (r.exec("aaa"))
console.log("PASS");
}
expect: {
var r = /a/g;
for (;r.exec("aaa");)
console.log("PASS");
}
expect_stdout: [
"PASS",
"PASS",
"PASS",
]
}
var_test: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
}
input: {
var r = /a/;
while (r.test("AAA"))
console.log("FAIL");
console.log("PASS");
}
expect: {
var r = /a/;
while (false)
console.log("FAIL");
console.log("PASS");
}
expect_stdout: "PASS"
}
var_test_global: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
}
input: {
var r = /a/g;
while (r.test("aaa"))
console.log("PASS");
}
expect: {
var r = /a/g;
while (r.test("aaa"))
console.log("PASS");
}
expect_stdout: [
"PASS",
"PASS",
"PASS",
]
}
lazy_boolean: {
options = {
evaluate: true,
passes: 2,
side_effects: true,
unsafe: true,
}
input: {
/b/.exec({}) && console.log("PASS");
/b/.test({}) && console.log("PASS");
/b/g.exec({}) && console.log("PASS");
/b/g.test({}) && console.log("PASS");
}
expect: {
console.log("PASS");
console.log("PASS");
console.log("PASS");
console.log("PASS");
}
expect_stdout: [
"PASS",
"PASS",
"PASS",
"PASS",
]
}
reset_state_between_evaluate: {
options = {
evaluate: true,
passes: 2,
unsafe: true,
}
input: {
console.log(function() {
for (var a in /[abc4]/g.exec("a"))
return "PASS";
return "FAIL";
}());
}
expect: {
console.log(function() {
for (var a in /[abc4]/g.exec("a"))
return "PASS";
return "FAIL";
}());
}
expect_stdout: "PASS"
}

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