Compare commits

...

315 Commits

Author SHA1 Message Date
Alex Lam S.L
f9b811ce83 v3.17.2 2022-09-26 00:12:51 +08:00
Alex Lam S.L
9ac3879b06 fix corner case in conditionals (#5676) 2022-09-23 11:09:55 +08:00
Alex Lam S.L
37d3e4feaa fix corner case in if_return (#5675) 2022-09-22 23:27:06 +08:00
Alex Lam S.L
43ec350cd2 fix corner case in conditionals (#5674)
fixes #5673
2022-09-22 10:58:44 +08:00
Alex Lam S.L
63b04a687a minor tweaks (#5672) 2022-09-21 23:11:46 +08:00
Alex Lam S.L
9efa02afb6 fix corner case in assignments (#5671)
fixes #5670
2022-09-21 07:56:16 +08:00
Alex Lam S.L
3a6e58109e v3.17.1 2022-09-20 04:13:28 +08:00
Alex Lam S.L
5ac6ec5496 improve usability of --mangle-props (#5669) 2022-09-18 09:37:06 +08:00
Alex Lam S.L
eb22f0101e fix corner case in unused (#5668)
fixes #5663
2022-09-17 13:32:41 +08:00
Alex Lam S.L
e4bff315eb fix corner case in conditionals (#5667)
fixes #5666
2022-09-17 10:42:32 +08:00
Alex Lam S.L
001f6f9719 fix corner case in inline (#5664)
fixes #5662
2022-09-17 08:54:54 +08:00
Alex Lam S.L
e0b302d651 fix corner case in merge_vars (#5661)
fixes #5660
2022-09-14 23:36:54 +08:00
Alex Lam S.L
fa2511f71c tweak ufuzz job scheduling (#5659) 2022-09-11 04:05:21 +08:00
Alex Lam S.L
edf1bf1106 enhance varify (#5658) 2022-09-11 03:28:54 +08:00
Alex Lam S.L
88dfc49683 fix corner case in merge_vars (#5657)
fixes #5656
2022-09-10 04:14:33 +08:00
Alex Lam S.L
9dec612cd5 enhance inline (#5655)
- improve fix for #5653
2022-09-09 04:07:47 +08:00
Alex Lam S.L
02d966d914 fix corner case in hoist_props (#5654)
fixes #5653
2022-09-08 10:55:59 +08:00
Alex Lam S.L
5b5f6e329c fix corner case in ie (#5652)
fixes #5651
2022-09-08 10:49:40 +08:00
Alex Lam S.L
4e4a2f8ed3 fix corner case in if_return (#5650)
fixes #5649
2022-09-08 10:49:05 +08:00
Alex Lam S.L
32bd65a87f support ExtendScript parser quirks (#5648)
closes #1144
2022-09-07 02:28:34 +08:00
Alex Lam S.L
318206d41d suppress false positives in ufuzz (#5647) 2022-09-06 01:33:22 +08:00
Alex Lam S.L
535212c69e allow glob-style input for --in-situ (#5646)
closes #5645
2022-09-05 22:54:35 +08:00
Alex Lam S.L
1d42e9ad55 fix corner case in collapse_vars (#5644)
fixes #5643
2022-09-04 10:10:31 +08:00
Alex Lam S.L
78f354beb8 fix corner case in dead_code (#5642)
fixes #5641
2022-09-04 06:18:25 +08:00
Alex Lam S.L
e012f046bc tweak test cases (#5640) 2022-08-31 12:16:42 +08:00
Alex Lam S.L
f63b7b079d fix corner case in collapse_vars (#5639)
fixes #5638
2022-08-31 08:44:04 +08:00
Alex Lam S.L
d530f9332c enhance awaits (#5637) 2022-08-31 02:51:42 +08:00
Alex Lam S.L
10bc86ba10 enhance reduce_vars (#5636) 2022-08-30 16:00:43 +08:00
Alex Lam S.L
15b608f74c fix corner case in inline (#5635)
fixes #5634
2022-08-30 00:45:35 +08:00
Alex Lam S.L
7c52af0dec workaround quirks from npm (#5633) 2022-08-26 20:08:04 +08:00
Alex Lam S.L
cd97237c59 workaround quirks from GitHub Actions (#5632) 2022-08-26 15:16:03 +08:00
Alex Lam S.L
965e9767e5 workaround quirks from Node.js (#5631) 2022-08-26 06:25:44 +08:00
Alex Lam S.L
41a7000745 workaround quirks from GitHub Actions (#5630) 2022-08-26 02:35:53 +08:00
Alex Lam S.L
9cdc1ef6c2 fix corner case in unused (#5629)
fixes #5628
2022-08-25 05:01:12 +08:00
Alex Lam S.L
4db81065ee fix corner case in hoist_vars (#5627)
fixes #5626
2022-08-24 00:19:47 +08:00
Alex Lam S.L
4653e8aec0 improve diagnostics on top_retain & mangle.properties (#5622)
closes #5618
2022-08-19 02:32:21 +08:00
Alex Lam S.L
ac002b6338 fix corner case in reduce_vars (#5624)
fixes #5623
2022-08-19 02:31:48 +08:00
Alex Lam S.L
9eea3a673a provide diagnostic details on --mangle-props (#5621)
closes #5618
2022-08-17 22:22:30 +08:00
Alex Lam S.L
d6d2f5ced2 enhance reduce_vars (#5616)
closes #5614
2022-08-17 09:25:59 +08:00
Alex Lam S.L
887e086890 fix corner case in if_return (#5620)
fixes #5619
2022-08-17 09:10:33 +08:00
Alex Lam S.L
8602d1ba17 v3.17.0 2022-08-17 03:45:32 +08:00
Alex Lam S.L
dd90135944 fix corner case in pure_getters (#5617) 2022-08-14 02:54:06 +08:00
Alex Lam S.L
612701a706 tweak ufuzz test case generation (#5615) 2022-08-12 03:55:54 +08:00
Alex Lam S.L
503532cf77 workaround sporadic I/O lags in GitHub Actions (#5613) 2022-08-10 07:36:14 +08:00
Alex Lam S.L
6c0e522922 workaround sporadic I/O lags in GitHub Actions (#5612) 2022-08-10 04:33:32 +08:00
Alex Lam S.L
9d37276986 tweak ufuzz test case generation (#5611) 2022-08-10 00:20:20 +08:00
Alex Lam S.L
5a4cd09938 enhance inline (#5610) 2022-08-09 22:54:29 +08:00
Alex Lam S.L
c32fe26b8d fix corner case in merge_vars (#5609) 2022-08-09 10:18:11 +08:00
Alex Lam S.L
2c3c4ec323 improve source mapping accuracy (#5608) 2022-08-09 02:02:43 +08:00
Alex Lam S.L
f451a7ad79 implement --expression (#5607) 2022-08-08 03:42:18 +08:00
Alex Lam S.L
07953b36b0 update dependencies (#5605) 2022-08-06 13:16:47 +08:00
Alex Lam S.L
387c69b194 minor clean-ups (#5604) 2022-08-06 10:45:44 +08:00
Alex Lam S.L
a9d9af53e9 fix corner case in if_return (#5603)
fixes #5602
2022-08-06 07:56:20 +08:00
Alex Lam S.L
8a07f1202c expand builtins exclusions (#5601)
closes #5600
2022-08-05 13:37:02 +08:00
Alex Lam S.L
41b65af6e2 fix corner cases with static modifier (#5599) 2022-08-05 02:48:21 +08:00
Alex Lam S.L
884842cd6c fix corner case in if_return (#5598)
fixes #5597
2022-08-04 06:50:51 +08:00
Alex Lam S.L
8076d66ae5 fix corner case in if_return (#5596)
fixes #5595
2022-08-03 20:07:55 +08:00
Alex Lam S.L
64e3ceec3b enhance if_return (#5594) 2022-08-03 07:37:31 +08:00
Alex Lam S.L
672cdfa57a enhance conditionals (#5593) 2022-08-02 19:01:57 +08:00
Alex Lam S.L
e39f33e41b fix corner cases in if_return (#5590)
fixes #5589
fixes #5591
fixes #5592
2022-07-31 02:45:52 +08:00
Alex Lam S.L
6667440aaf enhance if_return (#5588)
fixes #5587
2022-07-30 20:53:46 +08:00
Alex Lam S.L
ab5c7e6863 fix corner cases in if_return (#5585)
fixes #5583
fixes #5584
fixes #5586
2022-07-30 16:07:19 +08:00
Alex Lam S.L
08c386f363 enhance if_return (#5582) 2022-07-30 05:25:17 +08:00
Alex Lam S.L
937a672879 fix corner case in mangle (#5581)
fixes #5580
2022-07-29 03:04:10 +08:00
Alex Lam S.L
513995f57d fix corner case in inline & reduce_vars (#5579) 2022-07-28 23:53:11 +08:00
Alex Lam S.L
db6fd6db3e enhance side_effects (#5578) 2022-07-28 04:06:11 +08:00
Alex Lam S.L
da930affd2 fix corner case in inline (#5577)
fixes #5576
2022-07-26 10:46:54 +08:00
Alex Lam S.L
996836b67e enhance conditionals (#5575) 2022-07-26 01:49:45 +08:00
Alex Lam S.L
fc7678c115 v3.16.3 2022-07-25 06:08:04 +08:00
Alex Lam S.L
b371dc2d1e fix corner case in collapse_vars (#5574)
fixes #5573
2022-07-23 07:18:26 +08:00
Alex Lam S.L
56e9454f1f fix corner case with spread syntax (#5572) 2022-07-23 03:07:04 +08:00
Alex Lam S.L
d67daa8314 support string namespace in import & export (#5570) 2022-07-20 05:55:38 +08:00
Alex Lam S.L
f0120e90b6 fix corner case collapse_vars (#5569)
fixes #5568
2022-07-18 09:04:51 +08:00
Alex Lam S.L
ec4558be29 fix corner cases with parameter scope (#5567)
fixes #5566
2022-07-17 16:03:12 +08:00
Alex Lam S.L
685ab357cc document v8 quirks (#5565)
closes #5564
2022-07-17 00:22:16 +08:00
Alex Lam S.L
5792f30175 fix corner case in evaluate (#5559)
fixes #5558
2022-07-15 20:36:52 +08:00
Alex Lam S.L
24443b6764 enhance collapse_vars (#5556) 2022-07-12 23:49:43 +08:00
Alex Lam S.L
154edf0427 enhance collapse_vars (#5555) 2022-07-11 23:10:40 +08:00
Alex Lam S.L
4778cf88e2 upgrade AST<->ESTree translation (#5554) 2022-07-11 07:18:25 +08:00
Alex Lam S.L
38bd4f65d0 fix corner cases in collapse_vars (#5553)
fixes #5552
2022-07-09 20:50:54 +08:00
Alex Lam S.L
0b808f6428 parse import expressions correctly (#5551)
fixes #5550
2022-07-08 19:25:30 +08:00
Alex Lam S.L
b2bc2e1173 parse export & import statements correctly (#5550)
fixes #5548
2022-07-08 04:04:56 +08:00
Alex Lam S.L
80787ff7ef minor cleanups (#5549) 2022-07-08 03:14:54 +08:00
Alex Lam S.L
b92a89f325 fix corner case in conditionals (#5548) 2022-07-07 21:28:33 +08:00
Alex Lam S.L
902292f776 fix corner case in conditionals (#5547)
fixes #5546
2022-07-07 15:49:33 +08:00
Alex Lam S.L
3dcf098468 fix corner cases in conditionals & switches (#5545)
fixes #5543
fixes #5544
2022-07-07 14:59:06 +08:00
Alex Lam S.L
d89f0965aa enhance conditionals (#5542) 2022-07-07 12:17:23 +08:00
Alex Lam S.L
c8d98f4787 enhance if_return (#5541) 2022-07-07 04:28:00 +08:00
Alex Lam S.L
0207b46d70 enhance if_return & inline (#5538) 2022-07-06 11:40:07 +08:00
Alex Lam S.L
aa2a9fbedb v3.16.2 2022-07-04 08:50:56 +08:00
Alex Lam S.L
3596b4feda fix corner case in inline (#5537)
fixes #5536
2022-07-02 00:10:02 +08:00
Alex Lam S.L
51deeff72e enhance inline (#5535) 2022-07-01 11:24:16 +08:00
Alex Lam S.L
4c227cc6bd fix corner cases in inline & unused (#5534)
fixes #5533
2022-06-30 15:34:45 +08:00
Alex Lam S.L
2426657daa fix corner case in inline (#5532)
fixes #5531
2022-06-30 04:09:53 +08:00
Alex Lam S.L
e1b03d0235 fix corner case in inline (#5529)
fixes #5528
2022-06-29 07:37:58 +08:00
Alex Lam S.L
f1b3e9df1e fix corner case in inline (#5527)
fixes #5526
2022-06-26 20:48:14 +08:00
Alex Lam S.L
fcc87edb71 fix corner cases in dead_code & if_return (#5525)
fixes #5521
fixes #5522
fixes #5523
fixes #5524
2022-06-26 18:40:56 +08:00
Alex Lam S.L
8b464331ba enhance dead_code & if_return (#5520) 2022-06-26 12:32:25 +08:00
Alex Lam S.L
9f57920566 enhance if_return (#5518) 2022-06-24 00:52:22 +08:00
Alex Lam S.L
933ca9ddd8 fix corner case in reduce_vars (#5517)
fixes #5516
2022-06-19 03:27:00 +08:00
Alex Lam S.L
74e36e4456 v3.16.1 2022-06-17 07:53:29 +08:00
Alex Lam S.L
4382bfe848 fix corner case in collapse_vars (#5513)
fixes #5512
2022-06-13 07:55:15 +08:00
Alex Lam S.L
b6f250f5c9 enhance unused (#5511) 2022-06-12 21:24:42 +08:00
Alex Lam S.L
5d69545299 enhance unsafe_comps (#5510) 2022-06-12 12:15:43 +08:00
Alex Lam S.L
139fad0c05 fix corner cases with instanceof (#5509)
- enhance `evaluate`
2022-06-12 10:01:54 +08:00
Alex Lam S.L
99946a3993 fix corner case in dead_code (#5507)
fixes #5506
2022-06-12 05:26:51 +08:00
Alex Lam S.L
053cb27fe3 fix corner case in collapse_vars (#5505)
fixes #5504
2022-06-10 09:12:59 +08:00
Alex Lam S.L
25017978e7 fix corner case in collapse_vars (#5503)
fixes #5502
2022-06-10 02:07:07 +08:00
Alex Lam S.L
f749863cb2 document ECMAScript quirks (#5501)
closes #5500
2022-06-09 03:01:00 +08:00
Alex Lam S.L
123f9cf987 fix corner case in hoist_props (#5499)
fixes #5498
2022-06-07 23:29:42 +08:00
Alex Lam S.L
a758b40e3f suppress false positives in ufuzz (#5497) 2022-06-07 23:28:06 +08:00
Alex Lam S.L
44e5e99aae parse directives within arrow functions correctly (#5496)
fixes #5495
2022-06-07 10:33:17 +08:00
Alex Lam S.L
be53c4838b fix corner case in collapse_vars (#5494)
fixes #5493
2022-06-06 23:36:19 +08:00
Alex Lam S.L
0c7b016fa7 fix corner case in inline & module (#5492)
fixes #5491
2022-06-06 22:52:22 +08:00
Alex Lam S.L
00665766da fix corner case in side_effects (#5490)
fixes #5489
2022-06-06 20:32:32 +08:00
Alex Lam S.L
88b4283200 support class static initialization block (#5488) 2022-06-06 12:01:15 +08:00
Alex Lam S.L
d2bd0d1c1c support top-level await (#5487) 2022-06-06 11:52:01 +08:00
Alex Lam S.L
25441d44f6 v3.16.0 2022-06-06 11:29:26 +08:00
Alex Lam S.L
a025392a30 fix corner case in comparisons (#5486)
fixes #5485
2022-06-05 00:47:38 +08:00
Alex Lam S.L
ad5f5ef2a3 fix corner case in webkit (#5483)
fixes #5480
2022-06-02 02:45:02 +08:00
Chen Yangjian
40e669eacb docs: toplevel webkit option sets compress.webkit as well (#5480) 2022-06-02 02:44:06 +08:00
Alex Lam S.L
ad3a331ca3 fix corner case in collapse_vars (#5482)
fixes #5481
2022-06-02 02:42:39 +08:00
Alex Lam S.L
3c9e1693d5 fix corner case in side_effects (#5479)
fixes #5478
2022-05-31 00:27:40 +08:00
Alex Lam S.L
8bc03dc6c4 fix corner case in keep_fargs (#5477)
fixes #5476
2022-05-29 12:10:19 +08:00
Alex Lam S.L
2152f00de2 enhance inline & module (#5475) 2022-05-27 11:57:05 +08:00
Alex Lam S.L
94aae05d45 fix corner case in merge_vars (#5472)
fixes #5471
2022-05-27 03:13:24 +08:00
Alex Lam S.L
0dbf2b1d3c suppress false positives in ufuzz (#5473) 2022-05-26 23:17:47 +08:00
Alex Lam S.L
59b23b8c13 fix corner case in booleans (#5470)
fixes #5469
2022-05-26 05:33:50 +08:00
Alex Lam S.L
5979b195fe suppress false positives in ufuzz (#5468) 2022-05-25 23:50:47 +08:00
Alex Lam S.L
a1cff23377 suppress false positives in ufuzz (#5467) 2022-05-25 06:35:59 +08:00
Alex Lam S.L
c82fc1ef71 implement --module (#5462) 2022-05-24 05:45:47 +08:00
Alex Lam S.L
740f93f5a9 fix corner case in merge_vars (#5466)
fixes #5465
2022-05-24 05:45:07 +08:00
Alex Lam S.L
d4caa97b88 fix corner case in reduce_vars (#5464)
fixes #5463
2022-05-23 11:08:12 +08:00
Alex Lam S.L
c2ca7b7659 drop unused extends properly (#5461) 2022-05-23 03:53:32 +08:00
Alex Lam S.L
59edda6ca5 suppress false positives in ufuzz (#5460) 2022-05-22 01:36:45 +08:00
Alex Lam S.L
1668bc33c3 improve ufuzz coverage (#5459) 2022-05-21 02:57:13 +08:00
Alex Lam S.L
01f1e3fef8 avoid v8 quirks in ufuzz (#5458) 2022-05-20 00:00:24 +08:00
Alex Lam S.L
27aa85f84b fix corner cases in merge_vars (#5457)
fixes #5456
2022-05-19 06:39:20 +08:00
Alex Lam S.L
33c9c48318 fix corner case in hoist_props & unused (#5455)
fixes #5454
2022-05-19 04:45:38 +08:00
Alex Lam S.L
63f16e4616 fix corner case in merge_vars (#5452)
fixes #5451
2022-05-18 02:41:05 +08:00
Alex Lam S.L
cb6dd34b98 avoid broken versions of Node.js (#5453) 2022-05-18 02:40:31 +08:00
Alex Lam S.L
27727e6926 fix corner cases in unused (#5449)
fixes #5448
2022-05-17 17:03:06 +08:00
Alex Lam S.L
a968ddc78c avoid webpack bug in web-tooling-benchmark (#5450) 2022-05-17 14:08:11 +08:00
Alex Lam S.L
f70462aeb2 fix corner case in merge_vars (#5445)
fixes #5444
2022-05-16 16:30:14 +08:00
Alex Lam S.L
3aa92c76cc avoid extends error in ufuzz (#5447) 2022-05-16 11:11:10 +08:00
Alex Lam S.L
fc6a66836a fix corner case in unused (#5446)
fixes #5444
2022-05-16 09:13:30 +08:00
Alex Lam S.L
31167da1a9 avoid extends error in test cases (#5443) 2022-05-16 06:50:22 +08:00
Alex Lam S.L
7db2ada880 fix corner case in hoist_props (#5442)
fixes #5441
2022-05-16 06:49:09 +08:00
Alex Lam S.L
e31bbe329a improve compatibility with use strict (#5440) 2022-05-14 12:15:54 +08:00
Alex Lam S.L
8946c87011 suppress invalid test case generation (#5439)
- document v8 quirks

closes #5438
2022-05-12 04:38:11 +08:00
Alex Lam S.L
a9ef659bcb v3.15.5 2022-05-11 05:26:10 +08:00
Alex Lam S.L
35c2149dbd fix corner case in merge_vars (#5437)
fixes #5436
2022-05-08 04:16:28 +08:00
Alex Lam S.L
89a35f9fcd fix corner case in reduce_vars (#5435)
fixes #5434
2022-05-06 09:32:47 +08:00
Alex Lam S.L
1a4e99dc2d avoid v8 quirks in ufuzz (#5431)
closes #5428
closes #5429
2022-04-25 21:33:31 +08:00
Alex Lam S.L
cb870f6fd6 document v8 quirks (#5430)
closes #5428
closes #5429
2022-04-21 02:51:53 +08:00
Alex Lam S.L
a0c0c294c5 fix corner case in assignments (#5426)
fixes #5425
2022-04-19 13:19:30 +08:00
Alex Lam S.L
fbdb7eeda3 fix corner case in merge_vars (#5424)
fixes #5423
2022-04-19 09:04:06 +08:00
Alex Lam S.L
1bc0fccc8c improve ufuzz resilience (#5422) 2022-04-18 13:03:01 +08:00
Alex Lam S.L
20252c6483 fix corner case in merge_vars (#5421)
fixes #5420
2022-04-18 06:38:08 +08:00
Alex Lam S.L
e396912ea2 suppress false positives with export & import (#5418) 2022-04-16 04:27:50 +08:00
Alex Lam S.L
5ebfa78f56 fix corner case with arguments (#5417)
fixes #5416
2022-04-15 06:52:10 +08:00
Alex Lam S.L
950609f578 fix corner case in inline (#5415)
fixes #5414
2022-04-13 06:19:37 +08:00
Alex Lam S.L
4a44d95f09 v3.15.4 2022-04-10 01:16:11 +08:00
David Luhmer
36718948be rename reserved keyword await (#5413) 2022-04-08 00:31:29 +08:00
Alex Lam S.L
21bd4c4a9d fix corner cases in collapse_vars & hoist_vars (#5412)
fixes #5411
2022-04-07 04:12:03 +08:00
Alex Lam S.L
998c9792da fix corner case in inline (#5410)
fixes #5409
2022-04-06 12:23:47 +08:00
Alex Lam S.L
ccd77d70db fix corner case in reduce_vars (#5408)
fixes #5407
2022-04-05 10:09:25 +08:00
Alex Lam S.L
d75a946707 fix corner case in reduce_vars (#5406)
fixes #5405
2022-04-03 21:57:37 +08:00
Alex Lam S.L
696a20f10d patch export default within sandbox correctly (#5404)
fixes #5403
2022-04-03 19:56:19 +08:00
Alex Lam S.L
224c91b6c1 fix corner case in inline (#5402)
fixes #5401
2022-04-03 01:12:53 +08:00
Alex Lam S.L
8065e27a7d patch export default within sandbox correctly (#5400)
fixes #5399
2022-04-02 21:59:28 +08:00
Alex Lam S.L
584e253f33 enahnce collapse_vars (#5398) 2022-04-01 20:26:27 +08:00
Alex Lam S.L
fb5e08e4ec fix corner case in collapse_vars (#5397)
fixes #5396
2022-03-31 20:02:56 +08:00
Alex Lam S.L
e3d328f741 fix corner case in collapse_vars (#5395)
fixes #5394
2022-03-30 01:22:57 +08:00
Alex Lam S.L
8922f08fbf fix corner cases in keep_fnames (#5393) 2022-03-29 03:01:01 +08:00
Alex Lam S.L
15a4074d1a fix corner case in unused (#5392)
fixes #5391
2022-03-28 05:46:43 +08:00
Alex Lam S.L
c624b43739 fix corner case in collapse_vars (#5390)
fixes #5389
2022-03-22 13:05:57 +08:00
Alex Lam S.L
a8e040b133 fix corner case in properties (#5388)
fixes #5387
2022-03-21 00:01:42 +08:00
Alex Lam S.L
5e30f3a48b fix corner case in inline (#5386)
fixes #5385
2022-03-20 22:50:28 +08:00
Alex Lam S.L
46570a4eb6 fix corner case in side_effects (#5383)
fixes #5382
2022-03-12 14:14:30 +08:00
Alex Lam S.L
01b84074d7 fix corner case in evaluate (#5381)
fixes #5380
2022-03-12 13:08:29 +08:00
Alex Lam S.L
7aba2dc5f2 v3.15.3 2022-03-10 12:50:19 +08:00
Alex Lam S.L
12a6728c4e fix corner case in hoist_vars (#5379)
fixes #5378
2022-03-06 17:56:00 +08:00
Alex Lam S.L
042c228c7b fix corner case in inline (#5377)
fixes #5376
2022-03-06 03:29:56 +08:00
Alex Lam S.L
e2b00814a8 fix corner cases in inline (#5375) 2022-03-04 04:05:31 +08:00
Alex Lam S.L
104d385ba9 fix corner case in ie (#5372)
fixes #5370
2022-03-02 13:52:27 +08:00
Alex Lam S.L
fdbbef2991 enhance conditionals (#5371) 2022-03-02 11:00:37 +08:00
Alex Lam S.L
f8edf05c3c v3.15.2 2022-02-26 20:41:02 +08:00
Alex Lam S.L
a9d0ddea9d fix corner case in directives & expression (#5369)
fixes #5368
2022-02-24 05:04:04 +08:00
Alex Lam S.L
313e4974a4 fix corner case in inline (#5367)
fixes #5366
2022-02-21 11:31:29 +08:00
Alex Lam S.L
dd3b81dec6 enhance booleans (#5365) 2022-02-21 11:02:19 +08:00
Alex Lam S.L
d5afe16bc8 enhance booleans & evaluate (#5364) 2022-02-21 01:25:37 +08:00
Alex Lam S.L
212ce4608e fix corner case in evaluate (#5363)
fixes #5362
2022-02-20 21:38:04 +08:00
Alex Lam S.L
fbc5ecf75a fix corner case in unused (#5361)
fixes #5360
2022-02-20 02:26:51 +08:00
Alex Lam S.L
a7d06167a0 enhance mangle (#5359) 2022-02-19 14:02:40 +08:00
Alex Lam S.L
9686379884 enhance comparisons (#5358) 2022-02-19 04:27:17 +08:00
Alex Lam S.L
82e8ebd77d fix corner case in evaluate (#5357)
fixes #5356
2022-02-15 16:28:49 +00:00
Alex Lam S.L
0b50880b4f fix corner case in evaluate & unsafe (#5355)
fixes #5354
2022-02-15 14:47:22 +08:00
Alex Lam S.L
316245ee12 fix corner case in merge_vars (#5353)
fixes #5352
2022-02-13 08:22:34 +08:00
Alex Lam S.L
63b92ead4e fix corner case in properties (#5351)
fixes #5350
2022-02-13 06:09:33 +08:00
Alex Lam S.L
a14555a39e enhance conditionals, if_return & side_effects (#5348) 2022-02-12 23:18:07 +08:00
Alex Lam S.L
6d0bb58d68 enhance merge_vars (#5349) 2022-02-12 20:41:02 +08:00
Alex Lam S.L
33c163f648 patch export default within sandbox correctly (#5346)
fixes #5345
2022-02-10 16:07:40 +08:00
Alex Lam S.L
b6c72c84d4 reduce overlap of sequences & side_effects (#5344) 2022-02-08 00:29:04 +08:00
Alex Lam S.L
327e94a759 v3.15.1 2022-02-07 10:15:48 +08:00
Alex Lam S.L
6fb7de7787 fix corner case in inline (#5343)
fixes #5342
2022-02-05 13:19:42 +08:00
Alex Lam S.L
d338e45033 add test case for unused (#5341)
closes #5340
2022-02-04 10:36:54 +08:00
Alex Lam S.L
b106cd9476 fix corner case in unused (#5339)
fixes #5338
2022-02-04 07:13:23 +08:00
Alex Lam S.L
9a91a7a4dc fix corner case in default_values (#5337)
fixes #5336
2022-02-04 05:44:25 +08:00
Alex Lam S.L
fa30960b8b fix corner case in conditionals (#5335)
fixes #5334
2022-02-04 01:48:30 +08:00
Alex Lam S.L
8ceb4b0492 fix corner case in inline (#5333)
fixes #5332
2022-02-03 13:13:35 +08:00
Alex Lam S.L
aad5d6e122 enhance if_return (#5330) 2022-02-02 08:13:38 +08:00
Alex Lam S.L
77552d9e69 fix corner case in inline (#5329)
fixes #5328
2022-02-01 19:35:03 +08:00
Alex Lam S.L
93105f1a6d suppress false positives in ufuzz (#5327) 2022-02-01 12:17:47 +08:00
Alex Lam S.L
d7eb80b050 enhance if_return (#5326) 2022-01-31 06:32:25 +08:00
Alex Lam S.L
0a5a1f3687 fix corner case in reduce_vars (#5325)
fixes #5324
2022-01-29 21:39:30 +08:00
Alex Lam S.L
e7d6dd2ea2 fix corner case in unused (#5323)
fixes #5322
2022-01-29 19:28:19 +08:00
Alex Lam S.L
28943bcebb fix corner cases in collapse_vars (#5321)
fixes #5319
2022-01-29 15:57:53 +08:00
Alex Lam S.L
18f00457f6 fix corner case in merge_vars (#5320)
fixes #5319
2022-01-28 16:05:57 +08:00
Alex Lam S.L
e4a91a89e0 support custom indentation (#5318)
closes #50
2022-01-28 08:38:11 +08:00
Alex Lam S.L
3693bde2dd fix corner case in inline (#5317)
fixes #5316
2022-01-28 07:17:17 +08:00
Alex Lam S.L
67438f3ff9 fix corner case in side_effects (#5315)
fixes #5314
2022-01-27 08:13:19 +08:00
Alex Lam S.L
371d25944d fix corner case in max_line_len (#5313)
- speed up `max_line_len` & `preserve_line`
2022-01-26 23:47:21 +08:00
Alex Lam S.L
5c863b74d7 enhance collapse_vars (#5312) 2022-01-26 04:18:58 +08:00
Alex Lam S.L
6de708af37 v3.15.0 2022-01-26 01:33:13 +08:00
Alex Lam S.L
b9b2a4f7f8 fix corner case in inline (#5311)
fixes #5222
2022-01-26 00:47:24 +08:00
Alex Lam S.L
b46c7944c6 fix corner case in collapse_vars (#5310)
fixes #5309
2022-01-23 00:45:11 +08:00
Alex Lam S.L
866cd4a975 enhance merge_vars (#5308) 2022-01-21 09:40:33 +08:00
Alex Lam S.L
e24b255350 implement keep_fargs for mangle (#5307)
closes #4657
2022-01-21 05:13:26 +08:00
Alex Lam S.L
efed55f42d fix corner case in inline (#5306)
fixes #5305
2022-01-19 08:14:19 +08:00
Alex Lam S.L
8c2b76eff9 enhance side_effects (#5304) 2022-01-17 23:18:42 +08:00
Alex Lam S.L
b636e97e3b fix corner cases in awaits (#5303) 2022-01-17 16:22:26 +08:00
Alex Lam S.L
35d7f316ef fix corner cases in typeofs (#5301) 2022-01-17 14:03:41 +08:00
Alex Lam S.L
43807c26fb fix performance regression (#5302)
fixes #5297
2022-01-17 11:49:47 +08:00
Alex Lam S.L
774feeadb8 minor clean-ups (#5300) 2022-01-17 01:14:52 +08:00
Alex Lam S.L
d96c59f9e6 fix corner case in side_effects (#5299)
fixes #5298
2022-01-16 02:33:14 +08:00
Alex Lam S.L
dfd6418878 fix corner case in inline (#5297)
fixes #5296
2022-01-15 04:18:35 +08:00
Alex Lam S.L
87e8aca245 fix corner cases in reduce_vars, side_effects & unused (#5295)
fixes #5294
2022-01-15 01:44:36 +08:00
Alex Lam S.L
14e1311bdf fix corner cases in side_effects (#5293)
fixes #5292
2022-01-14 09:14:04 +08:00
Alex Lam S.L
ff3c2ed7a2 fix corner case in inline (#5291)
fixes #5290
2022-01-12 20:17:34 +08:00
Alex Lam S.L
f8602aca96 fix corner case in inline (#5289)
fixes #5288
2022-01-12 16:24:50 +08:00
Alex Lam S.L
9a58270b70 enhance imports (#5287) 2022-01-12 16:24:04 +08:00
Alex Lam S.L
f639a30bd2 fix corner cases in typeofs (#5286) 2022-01-11 13:13:46 +08:00
Alex Lam S.L
082013c20f report runtime process aborts correctly (#5285) 2022-01-11 09:12:01 +08:00
Alex Lam S.L
c7d2837184 fix corner case in inline (#5284)
fixes #5283
2022-01-10 15:43:26 +08:00
Alex Lam S.L
caaa753861 minor clean-ups (#5282) 2022-01-10 13:02:26 +08:00
Alex Lam S.L
4b949f6686 suppress false positives in ufuzz (#5281) 2022-01-10 05:05:35 +08:00
Alex Lam S.L
e9d9d5a9d2 improve class compatibility in side_effects (#5279) 2022-01-09 21:15:42 +08:00
Alex Lam S.L
f473b4db38 fix corner case in collapse_vars (#5278)
fixes #5277
2022-01-08 09:46:21 +08:00
Alex Lam S.L
b0df5d7b55 enhance collapse_vars & reduce_vars (#5275)
fixes #5276
2022-01-08 05:26:49 +08:00
Alex Lam S.L
be8c75bae1 fix corner case in collapse_vars (#5274)
fixes #5273
2022-01-07 15:00:23 +08:00
Alex Lam S.L
58bea676ac fix corner case in unused (#5272)
fixes #5271
2022-01-07 14:33:42 +08:00
Alex Lam S.L
9aab1f3661 fix corner case in inline (#5270)
fixes #5269
2022-01-07 13:22:16 +08:00
Alex Lam S.L
10a1523ee6 enhance collapse_vars (#5268) 2022-01-07 05:13:37 +08:00
Alex Lam S.L
d46eb69320 fix corner case in inline (#5267)
fixes #5266
2022-01-05 04:25:48 +08:00
Alex Lam S.L
3a3666a94e fix corner cases in inline (#5265)
fixes #5263
fixes #5264
2022-01-04 22:05:03 +08:00
Alex Lam S.L
2f568b9357 enhance mangle (#5262) 2022-01-04 10:06:00 +08:00
Alex Lam S.L
c94624f36c fix corner case in collapse_vars (#5261)
fixes #5260
2022-01-04 04:18:41 +08:00
Alex Lam S.L
dec359ce58 fix corner case in awaits & inline (#5259)
fixes #5258
2022-01-03 20:57:24 +08:00
Alex Lam S.L
1a054e869e fix corner case in inline (#5257)
fixes #5256
2022-01-03 10:13:29 +08:00
Alex Lam S.L
7889192cae fix corner cases in inline (#5255)
fixes #5254
2022-01-02 21:24:41 +08:00
Alex Lam S.L
f7841bc8b8 fix corner case in inline (#5253)
fixes #5251
2022-01-02 16:10:39 +08:00
Alex Lam S.L
aa6eb0d5be fix corner cases in inline (#5252)
fixes #5249
fixes #5250
2022-01-02 14:59:32 +08:00
Alex Lam S.L
87a7426598 enhance inline & unused (#5245) 2022-01-02 05:40:43 +08:00
Alex Lam S.L
8d0422b6f3 enhance reduce_vars (#5248) 2022-01-01 07:53:47 +08:00
Alex Lam S.L
e7ce1051fe fix corner cases in reduce_vars & unused (#5247)
fixes #5246
2021-12-31 04:47:13 +08:00
Alex Lam S.L
80d5f23fee fix corner case with lexical variables (#5244) 2021-12-30 05:15:53 +08:00
Alex Lam S.L
d51caaf358 enhance inline (#5243) 2021-12-28 00:53:12 +08:00
Alex Lam S.L
835d130ccf fix corner cases in inline (#5241)
fixes #5239
fixes #5240
2021-12-26 08:39:06 +08:00
Alex Lam S.L
e1013bd56d fix corner case in inline (#5238)
fixes #5237
2021-12-25 19:30:49 +08:00
Alex Lam S.L
13d41778b3 suppress false positives in test/reduce (#5235) 2021-12-25 03:13:37 +08:00
Alex Lam S.L
bab416465f fix corner case in conditionals (#5233)
fixes #5232
2021-12-23 22:25:02 +08:00
Alex Lam S.L
29a1e71705 fix corner case in inline (#5231)
fixes #5230
2021-12-23 14:26:07 +08:00
Alex Lam S.L
7b2eb4b5ff improve handling of non-trivial assignment values (#5227) 2021-12-23 07:55:06 +08:00
Alex Lam S.L
343bf6d7a5 fix corner case in booleans & inline (#5229)
fixes #5228
2021-12-21 23:46:20 +08:00
Alex Lam S.L
ba42cbad3f enhance inline (#5226) 2021-12-21 13:03:11 +08:00
Alex Lam S.L
86406e71ec fix corner case in unused (#5225)
fixes #5224
2021-12-20 02:25:38 +08:00
Alex Lam S.L
9e927ecc9a fix corner case in hoist_props (#5223)
fixes #5222
2021-12-16 02:57:34 +08:00
Alex Lam S.L
509896a410 improve compress efficiency (#5220) 2021-12-15 08:08:24 +08:00
Alex Lam S.L
7fe7c39a01 speed up compress (#5219) 2021-12-14 07:42:47 +08:00
Alex Lam S.L
2c5e23506b v3.14.5 2021-12-13 08:11:48 +08:00
Alex Lam S.L
07f35ea2c9 suppress false positives in ufuzz (#5216)
closes #5212
closes #5215
2021-12-12 06:19:06 +08:00
Alex Lam S.L
57a9519c3d fix corner case in objects (#5214)
fixes #5213
2021-12-10 06:02:22 +08:00
Alex Lam S.L
9e4c4c995c minor clean-up (#5210) 2021-12-10 04:48:06 +08:00
Alex Lam S.L
d11c82f8ca minor clean-up (#5209) 2021-12-09 05:14:57 +08:00
Alex Lam S.L
bc27966a19 workaround v8 performance quirks (#5207) 2021-12-08 13:40:47 +08:00
Alex Lam S.L
8f39491e96 workaround Unicode compatibility in testing (#5206) 2021-12-07 18:56:57 +08:00
Alex Lam S.L
065c50ebde improve sandbox resilience against process aborts (#5205) 2021-12-07 04:54:58 +08:00
Alex Lam S.L
d2e7c4af20 improve testing compatibility with Node.js (#5204) 2021-12-06 22:42:45 +08:00
Alex Lam S.L
033d8d9405 reduce memory pressure via bit fields (#5203) 2021-12-06 11:30:05 +08:00
Alex Lam S.L
b0799105c2 improve Dictionary performance (#5202)
- workaround `__proto__` quirks on v8
2021-12-05 14:58:52 +08:00
Alex Lam S.L
860aa9531b v3.14.4 2021-12-01 02:34:20 +08:00
Alex Lam S.L
2547542873 workaround sporadic slowdown in GitHub Actions (#5201) 2021-11-28 08:45:29 +08:00
Alex Lam S.L
3f8f0e246e fix corner case in collapse_vars (#5200)
fixes #5199
2021-11-28 01:43:43 +08:00
Alex Lam S.L
12227ebbb0 workaround toString() quirks on global context (#5198)
closes #5197
2021-11-27 23:17:51 +08:00
Alex Lam S.L
1b4bd7082b fix corner case in hoist_vars (#5196)
fixes #5195
2021-11-25 04:49:38 +08:00
Alex Lam S.L
0b6c185818 enhance merge_vars (#5194)
closes #5182
2021-11-24 19:08:40 +08:00
Alex Lam S.L
bfd0ac7f4b fix corner case in ie (#5193)
fixes #5192
2021-11-24 17:29:26 +08:00
Alex Lam S.L
1a8f2ecc65 enhance collapse_vars (#5186)
closes #5182
2021-11-24 17:28:36 +08:00
Alex Lam S.L
dc9e1ff0b1 fix corner case in unused (#5190)
fixes #5189
2021-11-23 20:10:05 +08:00
Alex Lam S.L
ea10498902 fix corner case in hoist_vars (#5188)
fixes #5187
2021-11-23 18:00:47 +08:00
Alex Lam S.L
69636dad69 improve sandbox async detection (#5185)
closes #5184
2021-11-23 02:29:54 +08:00
Alex Lam S.L
3ee1b0d00d enhance hoist_props & reduce_vars (#5183)
closes #5182
2021-11-23 00:31:10 +08:00
Alex Lam S.L
1e3ca4c6f7 enhance side_effects & unused (#5181) 2021-11-22 11:14:28 +08:00
Alex Lam S.L
839f4361f4 minor clean-up (#5180) 2021-11-19 16:34:11 +08:00
Alex Lam S.L
ae5c3ee8a1 fix corner cases in properties (#5178)
fixes #5177
2021-11-17 04:21:44 +08:00
Alex Lam S.L
77f7ae5ba2 fix corner case in join_vars (#5176)
fixes #5175
2021-11-15 21:35:54 +08:00
Alex Lam S.L
2d0f8bcff5 fix corner case in inline (#5174)
fixes #5173
2021-11-15 07:14:08 +08:00
Alex Lam S.L
f97e107c09 enhance reduce_vars (#5171) 2021-11-13 22:18:56 +08:00
Alex Lam S.L
e9932e1314 fix corner case in collapse_vars (#5169)
fixes #5168
2021-11-13 22:18:18 +08:00
Alex Lam S.L
eaa84d32df include Node.js v16 in CI tests (#5170)
- fix compatibility issues on v0.10 & v0.12
2021-11-13 18:34:18 +08:00
Alex Lam S.L
6e4aa0326f enhance reduce_vars (#5164)
- fix corner case in `join_vars`
2021-11-04 18:36:39 +08:00
Alex Lam S.L
f9a4b36dd1 fix corner cases in reduce_vars & rests (#5166)
fixes #5165
2021-11-03 21:29:01 +08:00
Alex Lam S.L
3acb5a329e enhance join_vars (#5162) 2021-11-02 11:33:24 +08:00
Alex Lam S.L
6d94242318 enhance reduce_vars (#5163) 2021-11-02 11:32:26 +08:00
112 changed files with 24421 additions and 4537 deletions

View File

@@ -50,7 +50,7 @@ jobs:
OPTIONS: ${{ matrix.options }}
SCRIPT: ${{ matrix.script }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Perform uglify, build & test
shell: bash
run: |

View File

@@ -7,7 +7,7 @@ jobs:
test:
strategy:
matrix:
node: [ '0.10', '0.12', '4', '6', '8', '10', '12', '14', latest ]
node: [ '0.10', '0.12', '4', '6', '8', '10', '12', '14', '16', latest ]
os: [ ubuntu-latest, windows-latest ]
script: [ compress, mocha, release/benchmark, release/jetstream ]
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
@@ -15,9 +15,10 @@ jobs:
env:
NODE: ${{ matrix.node }}
TYPE: ${{ matrix.script }}
UGLIFY_GITHUB_LAG: 10000
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: tmp
key: tmp ${{ matrix.script }}

View File

@@ -17,13 +17,13 @@ jobs:
fail-fast: false
matrix:
include:
- node: latest
- node: '16'
os: macos-latest
- node: '8'
- node: '12'
os: ubuntu-latest
- node: '8'
os: ubuntu-latest
- node: '8'
- node: '12'
os: windows-latest
- node: '8'
os: windows-latest
@@ -32,7 +32,7 @@ jobs:
env:
NODE: ${{ matrix.node }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Perform fuzzing
shell: bash
run: |

144
README.md
View File

@@ -54,8 +54,6 @@ a double dash to prevent input files being used as option arguments:
modules and Userscripts that may
be anonymous function wrapped (IIFE)
by the .user.js engine `caller`.
`expression` Parse a single expression, rather than
a program (for parsing JSON).
`spidermonkey` Assume input files are SpiderMonkey
AST format (as JSON).
-c, --compress [options] Enable compressor/specify compressor options:
@@ -111,12 +109,16 @@ a double dash to prevent input files being used as option arguments:
-d, --define <expr>[=value] Global definitions.
-e, --enclose [arg[:value]] Embed everything in a big function, with configurable
argument(s) & value(s).
--expression Parse a single expression, rather than a program
(for parsing JSON).
--ie Support non-standard Internet Explorer.
Equivalent to setting `ie: true` in `minify()`
for `compress`, `mangle` and `output` options.
By default UglifyJS will not try to be IE-proof.
--keep-fargs Do not mangle/drop function arguments.
--keep-fnames Do not mangle/drop function names. Useful for
code relying on Function.prototype.name.
--module Process input as ES module (implies --toplevel)
--name-cache <file> File to hold mangled name mappings.
--self Build UglifyJS as a library (implies --wrap UglifyJS)
--source-map [options] Enable source map/specify source map options:
@@ -145,7 +147,7 @@ a double dash to prevent input files being used as option arguments:
--warn Print warning messages.
--webkit Support non-standard Safari/Webkit.
Equivalent to setting `webkit: true` in `minify()`
for `mangle` and `output` options.
for `compress`, `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
@@ -325,7 +327,7 @@ unquoted style (`o.foo`). Example:
// stuff.js
var o = {
"foo": 1,
bar: 3
bar: 3,
};
o.foo += o.bar;
console.log(o.foo);
@@ -337,6 +339,16 @@ $ uglifyjs stuff.js --mangle-props keep_quoted -c -m
var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);
```
If the minified output will be processed again by UglifyJS, consider specifying
`keep_quoted_props` so the same property names are preserved:
```bash
$ uglifyjs stuff.js --mangle-props keep_quoted -c -m -O keep_quoted_props
```
```javascript
var o={"foo":1,o:3};o.foo+=o.o,console.log(o.foo);
```
### Debugging property name mangling
You can also pass `--mangle-props debug` in order to mangle property names
@@ -502,8 +514,13 @@ if (result.error) throw result.error;
- `compress` (default: `{}`) — pass `false` to skip compressing entirely.
Pass an object to specify custom [compress options](#compress-options).
- `expression` (default: `false`) — parse as a single expression, e.g. JSON.
- `ie` (default: `false`) — enable workarounds for Internet Explorer bugs.
- `keep_fargs` (default: `false`) — pass `true` to prevent discarding or mangling
of function arguments.
- `keep_fnames` (default: `false`) — pass `true` to prevent discarding or mangling
of function names. Useful for code relying on `Function.prototype.name`.
@@ -513,6 +530,10 @@ if (result.error) throw result.error;
- `mangle.properties` (default: `false`) — a subcategory of the mangle option.
Pass an object to specify custom [mangle property options](#mangle-properties-options).
- `module` (default: `false`) — set to `true` if you wish to process input as
ES module, i.e. implicit `"use strict";` and support for top-level `await`,
alongside with `toplevel` enabled.
- `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
@@ -624,7 +645,11 @@ to be `false` and all symbol names will be omitted.
- `bare_returns` (default: `false`) — support top level `return` statements
- `html5_comments` (default: `true`)
- `html5_comments` (default: `true`) — process HTML comment as workaround for
browsers which do not recognise `<script>` tags
- `module` (default: `false`) — set to `true` if you wish to process input as
ES module, i.e. implicit `"use strict";` and support for top-level `await`.
- `shebang` (default: `true`) — support `#!command` as the first line
@@ -707,7 +732,8 @@ to be `false` and all symbol names will be omitted.
- `1` — inline simple functions
- `2` — inline functions with arguments
- `3` — inline functions with arguments and variables
- `true`same as `3`
- `4`inline functions with arguments, variables and statements
- `true` — same as `4`
- `join_vars` (default: `true`) — join consecutive `var` statements
@@ -723,6 +749,9 @@ to be `false` and all symbol names will be omitted.
- `merge_vars` (default: `true`) — combine and reuse variables.
- `module` (default: `false`) — set to `true` if you wish to process input as
ES module, i.e. implicit `"use strict";` alongside with `toplevel` enabled.
- `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.
@@ -799,8 +828,9 @@ to be `false` and all symbol names will be omitted.
- `unsafe` (default: `false`) — apply "unsafe" transformations (discussion below)
- `unsafe_comps` (default: `false`) — compress expressions like `a <= b` assuming
none of the operands can be (coerced to) `NaN`.
- `unsafe_comps` (default: `false`) — assume operands cannot be (coerced to) `NaN`
in numeric comparisons, e.g. `a <= b`. In addition, expressions involving `in`
or `instanceof` would never throw.
- `unsafe_Function` (default: `false`) — compress and mangle `Function(args, code)`
when both `args` and `code` are string literals.
@@ -867,6 +897,9 @@ UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
- `debug` (default: `false`) — Mangle names with the original name still present.
Pass an empty string `""` to enable, or a non-empty string to set the debug suffix.
- `keep_fargs` (default: `false`) — Use `true` to prevent mangling of function
arguments.
- `keep_quoted` (default: `false`) — Only mangle unquoted property names.
- `regex` (default: `null`) — Pass a RegExp literal to only mangle property
@@ -907,11 +940,16 @@ can pass additional arguments that control the code output:
}
```
- `extendscript` (default: `false`) — enable workarounds for Adobe ExtendScript
bugs
- `galio` (default: `false`) — enable workarounds for ANT Galio bugs
- `indent_level` (default: `4`)
- `indent_level` (default: `4`) — indent by specified number of spaces or the
exact whitespace sequence supplied, e.g. `"\t"`.
- `indent_start` (default: `0`) — prefix all lines by that many spaces
- `indent_start` (default: `0`) — prefix all lines by whitespace sequence
specified in the same format as `indent_level`.
- `inline_script` (default: `true`) — escape HTML comments and the slash in
occurrences of `</script>` in strings
@@ -1321,10 +1359,8 @@ To allow for better optimizations, the compiler makes various assumptions:
- Later versions of JavaScript will throw `SyntaxError` with the following:
```javascript
var await;
async function f() {
class A {
static p = await;
}
class A {
static p = await;
}
// SyntaxError: Unexpected reserved word
```
@@ -1336,7 +1372,7 @@ To allow for better optimizations, the compiler makes various assumptions:
// SyntaxError: The left-hand side of a for-of loop may not be 'async'.
```
UglifyJS may modify the input which in turn may suppress those errors.
- Later versions of Chrome and Node.js will give incorrect results with the
- Some versions of Chrome and Node.js will give incorrect results with the
following:
```javascript
console.log({
@@ -1345,9 +1381,15 @@ To allow for better optimizations, the compiler makes various assumptions:
return "FAIL";
},
[42]: "PASS",
}[42], {
...console,
get 42() {
return "FAIL";
},
42: "PASS",
}[42]);
// Expected: "PASS"
// Actual: "FAIL"
// Expected: "PASS PASS"
// Actual: "PASS FAIL"
```
UglifyJS may modify the input which in turn may suppress those errors.
- Earlier versions of JavaScript will throw `TypeError` with the following:
@@ -1363,3 +1405,71 @@ To allow for better optimizations, the compiler makes various assumptions:
// TypeError: const 'a' has already been declared
```
UglifyJS may modify the input which in turn may suppress those errors.
- Later versions of Chrome and Node.js will give incorrect results with the
following:
```javascript
try {
class A {
static 42;
static get 42() {}
}
console.log("PASS");
} catch (e) {
console.log("FAIL");
}
// Expected: "PASS"
// Actual: "FAIL"
```
UglifyJS may modify the input which in turn may suppress those errors.
- Some versions of Chrome and Node.js will give incorrect results with the
following:
```javascript
(async function(a) {
(function() {
var b = await => console.log("PASS");
b();
})();
})().catch(console.error);
// Expected: "PASS"
// Actual: SyntaxError: Unexpected reserved word
```
UglifyJS may modify the input which in turn may suppress those errors.
- Later versions of Chrome and Node.js will give incorrect results with the
following:
```javascript
try {
f();
function f() {
throw 42;
}
} catch (e) {
console.log(typeof f, e);
}
// Expected: "function 42"
// Actual: "undefined 42"
```
UglifyJS may modify the input which in turn may suppress those errors.
- Later versions of JavaScript will throw `SyntaxError` with the following:
```javascript
"use strict";
console.log(function f() {
return f = "PASS";
}());
// Expected: "PASS"
// Actual: TypeError: invalid assignment to const 'f'
```
UglifyJS may modify the input which in turn may suppress those errors.
- Adobe ExtendScript will give incorrect results with the following:
```javascript
alert(true ? "PASS" : false ? "FAIL" : null);
// Expected: "PASS"
// Actual: "FAIL"
```
UglifyJS may modify the input which in turn may suppress those errors.
- Adobe ExtendScript will give incorrect results with the following:
```javascript
alert(42 ? null ? "FAIL" : "PASS" : "FAIL");
// Expected: "PASS"
// Actual: SyntaxError: Expected: :
```
UglifyJS may modify the input which in turn may suppress those errors.

View File

@@ -10,7 +10,9 @@ var info = require("../package.json");
var path = require("path");
var UglifyJS = require("../tools/node");
var skip_keys = [ "cname", "fixed", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
var skip_keys = [ "cname", "fixed", "in_arg", "inlined", "length_read", "parent_scope", "redef", "scope", "unused" ];
var truthy_keys = [ "optional", "pure", "terminal", "uses_arguments", "uses_eval", "uses_with" ];
var files = {};
var options = {};
var short_forms = {
@@ -70,6 +72,7 @@ function process_option(name, no_value) {
} else {
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
toplevels.push([ {
keep_fargs: "keep-fargs",
keep_fnames: "keep-fnames",
nameCache: "name-cache",
}[name] || name, option ]);
@@ -101,8 +104,11 @@ function process_option(name, no_value) {
" --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).",
" --expression Parse a single expression, rather than a program.",
" --ie Support non-standard Internet Explorer.",
" --keep-fargs Do not mangle/drop function arguments.",
" --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name.",
" --module Process input as ES module (implies --toplevel)",
" --name-cache <file> File to hold mangled name mappings.",
" --rename Force symbol expansion.",
" --no-rename Disable symbol expansion.",
@@ -146,8 +152,10 @@ function process_option(name, no_value) {
options[name] = read_value();
break;
case "annotations":
case "expression":
case "ie":
case "ie8":
case "module":
case "timings":
case "toplevel":
case "v8":
@@ -158,6 +166,9 @@ function process_option(name, no_value) {
case "no-annotations":
options.annotations = false;
break;
case "keep-fargs":
options.keep_fargs = true;
break;
case "keep-fnames":
options.keep_fnames = true;
break;
@@ -267,6 +278,8 @@ if (specified["self"]) {
if (paths.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
if (!options.wrap) options.wrap = "UglifyJS";
paths = UglifyJS.FILES;
} else if (paths.length) {
paths = simple_glob(paths);
}
if (specified["in-situ"]) {
if (output && output != "spidermonkey" || specified["reduce-test"] || specified["self"]) {
@@ -281,7 +294,7 @@ if (specified["in-situ"]) {
run();
});
} else if (paths.length) {
simple_glob(paths).forEach(function(name) {
paths.forEach(function(name) {
files[convert_path(name)] = read_file(name);
});
run();
@@ -430,7 +443,7 @@ function run() {
case "thedef":
return symdef(value);
}
if (skip_key(key)) return;
if (skip_property(key, value)) return;
if (value instanceof UglifyJS.AST_Token) return;
if (value instanceof UglifyJS.Dictionary) return;
if (value instanceof UglifyJS.AST_Node) {
@@ -480,33 +493,42 @@ function fatal(message) {
// A file glob function that only supports "*" and "?" wildcards in the basename.
// Example: "foo/bar/*baz??.*.js"
// Argument `glob` may be a string or an array of strings.
// Argument `paths` must be an array of strings.
// Returns an array of strings. Garbage in, garbage out.
function simple_glob(glob) {
if (Array.isArray(glob)) {
return [].concat.apply([], glob.map(simple_glob));
}
if (glob.match(/\*|\?/)) {
var dir = path.dirname(glob);
try {
var entries = fs.readdirSync(dir);
} catch (ex) {}
if (entries) {
var pattern = "^" + path.basename(glob)
.replace(/[.+^$[\]\\(){}]/g, "\\$&")
.replace(/\*/g, "[^/\\\\]*")
.replace(/\?/g, "[^/\\\\]") + "$";
var mod = process.platform === "win32" ? "i" : "";
var rx = new RegExp(pattern, mod);
var results = entries.sort().filter(function(name) {
return rx.test(name);
}).map(function(name) {
return path.join(dir, name);
});
if (results.length) return results;
function simple_glob(paths) {
return paths.reduce(function(paths, glob) {
if (/\*|\?/.test(glob)) {
var dir = path.dirname(glob);
try {
var entries = fs.readdirSync(dir).filter(function(name) {
try {
return fs.statSync(path.join(dir, name)).isFile();
} catch (ex) {
return false;
}
});
} catch (ex) {}
if (entries) {
var pattern = "^" + path.basename(glob)
.replace(/[.+^$[\]\\(){}]/g, "\\$&")
.replace(/\*/g, "[^/\\\\]*")
.replace(/\?/g, "[^/\\\\]") + "$";
var mod = process.platform === "win32" ? "i" : "";
var rx = new RegExp(pattern, mod);
var results = entries.filter(function(name) {
return rx.test(name);
}).sort().map(function(name) {
return path.join(dir, name);
});
if (results.length) {
[].push.apply(paths, results);
return paths;
}
}
}
}
return [ glob ];
paths.push(glob);
return paths;
}, []);
}
function read_file(path, default_value) {
@@ -519,7 +541,7 @@ function read_file(path, default_value) {
}
function parse_js(value, options, flag) {
if (!options || typeof options != "object") options = {};
if (!options || typeof options != "object") options = Object.create(null);
if (typeof value == "string") try {
UglifyJS.parse(value, {
expression: true
@@ -559,8 +581,10 @@ function parse_js(value, options, flag) {
return options;
}
function skip_key(key) {
return skip_keys.indexOf(key) >= 0;
function skip_property(key, value) {
return skip_keys.indexOf(key) >= 0
// only skip truthy_keys if their value is falsy
|| truthy_keys.indexOf(key) >= 0 && !value;
}
function symdef(def) {

View File

@@ -50,6 +50,8 @@ function DEFNODE(type, props, methods, base) {
if (base && base.PROPS) props = props.concat(base.PROPS);
var code = [
"return function AST_", type, "(props){",
// not essential, but speeds up compress by a few percent
"this._bits=0;",
"if(props){",
];
props.forEach(function(prop) {
@@ -107,6 +109,9 @@ var AST_Node = DEFNODE("Node", "start end", {
start: "[AST_Token] The first token of this node",
end: "[AST_Token] The last token of this node"
},
equals: function(node) {
return this.TYPE == node.TYPE && this._equals(node);
},
walk: function(visitor) {
visitor.visit(this);
},
@@ -123,18 +128,63 @@ var AST_Node = DEFNODE("Node", "start end", {
var marker = {};
this.walk(new TreeWalker(function(node) {
if (node.validate_visited === marker) {
throw new Error(string_template("cannot reuse {type} from [{file}:{line},{col}]", {
type: "AST_" + node.TYPE,
file: node.start.file,
line: node.start.line,
col: node.start.col,
}));
throw new Error(string_template("cannot reuse AST_{TYPE} from [{start}]", node));
}
node.validate_visited = marker;
}));
},
}, null);
DEF_BITPROPS(AST_Node, [
// AST_Node
"_optimized",
"_squeezed",
// AST_Call
"call_only",
// AST_Lambda
"collapse_scanning",
// AST_SymbolRef
"defined",
"evaluating",
"falsy",
// AST_SymbolRef
"in_arg",
// AST_Return
"in_bool",
// AST_SymbolRef
"is_undefined",
// AST_LambdaExpression
// AST_LambdaDefinition
"inlined",
// AST_Lambda
"length_read",
// AST_Yield
"nested",
// AST_Lambda
"new",
// AST_Call
// AST_PropAccess
"optional",
// AST_ClassProperty
"private",
// AST_Call
"pure",
// AST_Assign
"redundant",
// AST_Node
"single_use",
// AST_ClassProperty
"static",
// AST_Call
// AST_PropAccess
"terminal",
"truthy",
// AST_Scope
"uses_eval",
// AST_Scope
"uses_with",
]);
(AST_Node.log_function = function(fn, verbose) {
if (typeof fn != "function") {
AST_Node.info = AST_Node.warn = noop;
@@ -182,6 +232,24 @@ AST_Node.disable_validation = function() {
while (restore = restore_transforms.pop()) restore();
};
function all_equals(k, l) {
return k.length == l.length && all(k, function(m, i) {
return m.equals(l[i]);
});
}
function list_equals(s, t) {
return s.length == t.length && all(s, function(u, i) {
return u == t[i];
});
}
function prop_equals(u, v) {
if (u === v) return true;
if (u == null) return v == null;
return u instanceof AST_Node && v instanceof AST_Node && u.equals(v);
}
/* -----[ statements ]----- */
var AST_Statement = DEFNODE("Statement", null, {
@@ -193,6 +261,7 @@ var AST_Statement = DEFNODE("Statement", null, {
var AST_Debugger = DEFNODE("Debugger", null, {
$documentation: "Represents a debugger statement",
_equals: return_true,
}, AST_Statement);
var AST_Directive = DEFNODE("Directive", "quote value", {
@@ -201,6 +270,9 @@ var AST_Directive = DEFNODE("Directive", "quote value", {
quote: "[string?] the original quote character",
value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
},
_equals: function(node) {
return this.value == node.value;
},
_validate: function() {
if (this.quote != null) {
if (typeof this.quote != "string") throw new Error("quote must be string");
@@ -211,7 +283,8 @@ var AST_Directive = DEFNODE("Directive", "quote value", {
}, AST_Statement);
var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
$documentation: "The empty statement (empty block or simply a semicolon)"
$documentation: "The empty statement (empty block or simply a semicolon)",
_equals: return_true,
}, AST_Statement);
function is_statement(node) {
@@ -242,6 +315,9 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
$propdoc: {
body: "[AST_Node] an expression node (should not be instanceof AST_Statement)",
},
_equals: function(node) {
return this.body.equals(node.body);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -253,7 +329,7 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
},
}, AST_Statement);
var AST_BlockScope = DEFNODE("BlockScope", "enclosed functions make_def parent_scope variables", {
var AST_BlockScope = DEFNODE("BlockScope", "_var_names enclosed functions make_def parent_scope variables", {
$documentation: "Base class for all statements introducing a lexical scope",
$propdoc: {
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
@@ -293,6 +369,9 @@ var AST_Block = DEFNODE("Block", "body", {
$propdoc: {
body: "[AST_Statement*] an array of statements"
},
_equals: function(node) {
return all_equals(this.body, node.body);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -327,6 +406,10 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
$propdoc: {
label: "[AST_Label] a label definition"
},
_equals: function(node) {
return this.label.equals(node.label)
&& this.body.equals(node.body);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -368,6 +451,10 @@ var AST_DWLoop = DEFNODE("DWLoop", "condition", {
$propdoc: {
condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement"
},
_equals: function(node) {
return this.body.equals(node.body)
&& this.condition.equals(node.condition);
},
_validate: function() {
if (this.TYPE == "DWLoop") throw new Error("should not instantiate AST_DWLoop");
must_be_expression(this, "condition");
@@ -382,7 +469,7 @@ var AST_Do = DEFNODE("Do", null, {
node.body.walk(visitor);
node.condition.walk(visitor);
});
}
},
}, AST_DWLoop);
var AST_While = DEFNODE("While", null, {
@@ -393,7 +480,7 @@ var AST_While = DEFNODE("While", null, {
node.condition.walk(visitor);
node.body.walk(visitor);
});
}
},
}, AST_DWLoop);
var AST_For = DEFNODE("For", "init condition step", {
@@ -403,6 +490,12 @@ var AST_For = DEFNODE("For", "init condition step", {
condition: "[AST_Node?] the `for` termination clause, or null if empty",
step: "[AST_Node?] the `for` update clause, or null if empty"
},
_equals: function(node) {
return prop_equals(this.init, node.init)
&& prop_equals(this.condition, node.condition)
&& prop_equals(this.step, node.step)
&& this.body.equals(node.body);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -430,6 +523,11 @@ var AST_ForEnumeration = DEFNODE("ForEnumeration", "init object", {
init: "[AST_Node] the assignment target during iteration",
object: "[AST_Node] the object to iterate over"
},
_equals: function(node) {
return this.init.equals(node.init)
&& this.object.equals(node.object)
&& this.body.equals(node.body);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -470,6 +568,10 @@ var AST_With = DEFNODE("With", "expression", {
$propdoc: {
expression: "[AST_Node] the `with` expression"
},
_equals: function(node) {
return this.expression.equals(node.expression)
&& this.body.equals(node.body);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -484,8 +586,8 @@ var AST_With = DEFNODE("With", "expression", {
/* -----[ scope and functions ]----- */
var AST_Scope = DEFNODE("Scope", "uses_eval uses_with", {
$documentation: "Base class for all statements introducing a lexical scope",
var AST_Scope = DEFNODE("Scope", "fn_defs may_call_this uses_eval uses_with", {
$documentation: "Base class for all statements introducing a lambda scope",
$propdoc: {
uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
@@ -543,13 +645,17 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
}
}, AST_Scope);
var AST_Lambda = DEFNODE("Lambda", "argnames length_read rest uses_arguments", {
var AST_ClassInitBlock = DEFNODE("ClassInitBlock", null, {
$documentation: "Value for `class` static initialization blocks",
}, AST_Scope);
var AST_Lambda = DEFNODE("Lambda", "argnames length_read rest safe_ids uses_arguments", {
$documentation: "Base class for functions",
$propdoc: {
argnames: "[(AST_DefaultValue|AST_Destructured|AST_SymbolFunarg)*] array of function arguments and/or destructured literals",
length_read: "[boolean/S] whether length property of this function is accessed",
rest: "[(AST_Destructured|AST_SymbolFunarg)?] rest parameter, or null if absent",
uses_arguments: "[boolean/S] whether this function accesses the arguments array",
uses_arguments: "[boolean|number/S] whether this function accesses the arguments array",
},
each_argname: function(visit) {
var tw = new TreeWalker(function(node) {
@@ -568,6 +674,13 @@ var AST_Lambda = DEFNODE("Lambda", "argnames length_read rest uses_arguments", {
});
if (this.rest) this.rest.walk(tw);
},
_equals: function(node) {
return prop_equals(this.rest, node.rest)
&& prop_equals(this.name, node.name)
&& prop_equals(this.value, node.value)
&& all_equals(this.argnames, node.argnames)
&& all_equals(this.body, node.body);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -778,6 +891,14 @@ var AST_Class = DEFNODE("Class", "extends name properties", {
extends: "[AST_Node?] the super class, or null if not specified",
properties: "[AST_ClassProperty*] array of class properties",
},
_equals: function(node) {
return prop_equals(this.name, node.name)
&& prop_equals(this.extends, node.extends)
&& all_equals(this.properties, node.properties);
},
resolve: function(def_class) {
return def_class ? this : this.parent_scope.resolve();
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -822,11 +943,17 @@ var AST_ClassExpression = DEFNODE("ClassExpression", null, {
var AST_ClassProperty = DEFNODE("ClassProperty", "key private static value", {
$documentation: "Base class for `class` properties",
$propdoc: {
key: "[string|AST_Node] property name (AST_Node for computed property)",
key: "[string|AST_Node?] property name (AST_Node for computed property, null for initialization block)",
private: "[boolean] whether this is a private property",
static: "[boolean] whether this is a static property",
value: "[AST_Node?] property value (AST_Accessor for getters/setters, AST_LambdaExpression for methods, null if not specified for fields)",
},
_equals: function(node) {
return !this.private == !node.private
&& !this.static == !node.static
&& prop_equals(this.key, node.key)
&& prop_equals(this.value, node.value);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -836,7 +963,9 @@ var AST_ClassProperty = DEFNODE("ClassProperty", "key private static value", {
},
_validate: function() {
if (this.TYPE == "ClassProperty") throw new Error("should not instantiate AST_ClassProperty");
if (typeof this.key != "string") {
if (this instanceof AST_ClassInit) {
if (this.key != null) throw new Error("key must be null");
} else if (typeof this.key != "string") {
if (!(this.key instanceof AST_Node)) throw new Error("key must be string or AST_Node");
must_be_expression(this, "key");
}
@@ -876,6 +1005,17 @@ var AST_ClassMethod = DEFNODE("ClassMethod", null, {
},
}, AST_ClassProperty);
var AST_ClassInit = DEFNODE("ClassInit", null, {
$documentation: "A `class` static initialization block",
_validate: function() {
if (!this.static) throw new Error("static must be true");
if (!(this.value instanceof AST_ClassInitBlock)) throw new Error("value must be AST_ClassInitBlock");
},
initialize: function() {
this.static = true;
},
}, AST_ClassProperty);
/* -----[ JUMPS ]----- */
var AST_Jump = DEFNODE("Jump", null, {
@@ -890,6 +1030,9 @@ var AST_Exit = DEFNODE("Exit", "value", {
$propdoc: {
value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
},
_equals: function(node) {
return prop_equals(this.value, node.value);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -920,6 +1063,9 @@ var AST_LoopControl = DEFNODE("LoopControl", "label", {
$propdoc: {
label: "[AST_LabelRef?] the label, or null if none",
},
_equals: function(node) {
return prop_equals(this.label, node.label);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -950,6 +1096,11 @@ var AST_If = DEFNODE("If", "condition alternative", {
condition: "[AST_Node] the `if` condition",
alternative: "[AST_Statement?] the `else` part, or null if not present"
},
_equals: function(node) {
return this.body.equals(node.body)
&& this.condition.equals(node.condition)
&& prop_equals(this.alternative, node.alternative);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -973,6 +1124,10 @@ var AST_Switch = DEFNODE("Switch", "expression", {
$propdoc: {
expression: "[AST_Node] the `switch` “discriminant”"
},
_equals: function(node) {
return this.expression.equals(node.expression)
&& all_equals(this.body, node.body);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1004,6 +1159,10 @@ var AST_Case = DEFNODE("Case", "expression", {
$propdoc: {
expression: "[AST_Node] the `case` expression"
},
_equals: function(node) {
return this.expression.equals(node.expression)
&& all_equals(this.body, node.body);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1024,6 +1183,11 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", {
bcatch: "[AST_Catch?] the catch block, or null if not present",
bfinally: "[AST_Finally?] the finally block, or null if not present"
},
_equals: function(node) {
return all_equals(this.body, node.body)
&& prop_equals(this.bcatch, node.bcatch)
&& prop_equals(this.bfinally, node.bfinally);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1047,6 +1211,10 @@ var AST_Catch = DEFNODE("Catch", "argname", {
$propdoc: {
argname: "[(AST_Destructured|AST_SymbolCatch)?] symbol for the exception, or null if not present",
},
_equals: function(node) {
return prop_equals(this.argname, node.argname)
&& all_equals(this.body, node.body);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1072,6 +1240,9 @@ var AST_Definitions = DEFNODE("Definitions", "definitions", {
$propdoc: {
definitions: "[AST_VarDef*] array of variable definitions"
},
_equals: function(node) {
return all_equals(this.definitions, node.definitions);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1128,6 +1299,10 @@ var AST_VarDef = DEFNODE("VarDef", "name value", {
name: "[AST_Destructured|AST_SymbolVar] name of the variable",
value: "[AST_Node?] initializer, or null of there's no initializer",
},
_equals: function(node) {
return this.name.equals(node.name)
&& prop_equals(this.value, node.value);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1147,6 +1322,9 @@ var AST_ExportDeclaration = DEFNODE("ExportDeclaration", "body", {
$propdoc: {
body: "[AST_DefClass|AST_Definitions|AST_LambdaDefinition] the statement to export",
},
_equals: function(node) {
return this.body.equals(node.body);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1167,6 +1345,9 @@ var AST_ExportDefault = DEFNODE("ExportDefault", "body", {
$propdoc: {
body: "[AST_Node] the default export",
},
_equals: function(node) {
return this.body.equals(node.body);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1180,29 +1361,29 @@ var AST_ExportDefault = DEFNODE("ExportDefault", "body", {
},
}, AST_Statement);
var AST_ExportForeign = DEFNODE("ExportForeign", "aliases keys path quote", {
var AST_ExportForeign = DEFNODE("ExportForeign", "aliases keys path", {
$documentation: "An `export ... from '...'` statement",
$propdoc: {
aliases: "[string*] array of aliases to export",
keys: "[string*] array of keys to import",
path: "[string] the path to import module",
quote: "[string?] the original quote character",
aliases: "[AST_String*] array of aliases to export",
keys: "[AST_String*] array of keys to import",
path: "[AST_String] the path to import module",
},
_equals: function(node) {
return this.path.equals(node.path)
&& all_equals(this.aliases, node.aliases)
&& all_equals(this.keys, node.keys);
},
_validate: function() {
if (this.aliases.length != this.keys.length) {
throw new Error("aliases:key length mismatch: " + this.aliases.length + " != " + this.keys.length);
}
this.aliases.forEach(function(name) {
if (typeof name != "string") throw new Error("aliases must contain string");
if (!(name instanceof AST_String)) throw new Error("aliases must contain AST_String");
});
this.keys.forEach(function(name) {
if (typeof name != "string") throw new Error("keys must contain string");
if (!(name instanceof AST_String)) throw new Error("keys must contain AST_String");
});
if (typeof this.path != "string") throw new Error("path must be string");
if (this.quote != null) {
if (typeof this.quote != "string") throw new Error("quote must be string");
if (!/^["']$/.test(this.quote)) throw new Error("invalid quote: " + this.quote);
}
if (!(this.path instanceof AST_String)) throw new Error("path must be AST_String");
},
}, AST_Statement);
@@ -1211,6 +1392,9 @@ var AST_ExportReferences = DEFNODE("ExportReferences", "properties", {
$propdoc: {
properties: "[AST_SymbolExport*] array of aliases to export",
},
_equals: function(node) {
return all_equals(this.properties, node.properties);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1226,14 +1410,20 @@ var AST_ExportReferences = DEFNODE("ExportReferences", "properties", {
},
}, AST_Statement);
var AST_Import = DEFNODE("Import", "all default path properties quote", {
var AST_Import = DEFNODE("Import", "all default path properties", {
$documentation: "An `import` statement",
$propdoc: {
all: "[AST_SymbolImport?] the imported namespace, or null if not specified",
default: "[AST_SymbolImport?] the alias for default `export`, or null if not specified",
path: "[string] the path to import module",
path: "[AST_String] the path to import module",
properties: "[(AST_SymbolImport*)?] array of aliases, or null if not specified",
quote: "[string?] the original quote character",
},
_equals: function(node) {
return this.path.equals(node.path)
&& prop_equals(this.all, node.all)
&& prop_equals(this.default, node.default)
&& !this.properties == !node.properties
&& (!this.properties || all_equals(this.properties, node.properties));
},
walk: function(visitor) {
var node = this;
@@ -1252,16 +1442,12 @@ var AST_Import = DEFNODE("Import", "all default path properties quote", {
}
if (this.default != null) {
if (!(this.default instanceof AST_SymbolImport)) throw new Error("default must be AST_SymbolImport");
if (this.default.key !== "") throw new Error("invalid default key: " + this.default.key);
if (this.default.key.value !== "") throw new Error("invalid default key: " + this.default.key.value);
}
if (typeof this.path != "string") throw new Error("path must be string");
if (!(this.path instanceof AST_String)) throw new Error("path must be AST_String");
if (this.properties != null) this.properties.forEach(function(node) {
if (!(node instanceof AST_SymbolImport)) throw new Error("properties must contain AST_SymbolImport");
});
if (this.quote != null) {
if (typeof this.quote != "string") throw new Error("quote must be string");
if (!/^["']$/.test(this.quote)) throw new Error("invalid quote: " + this.quote);
}
},
}, AST_Statement);
@@ -1271,6 +1457,10 @@ var AST_DefaultValue = DEFNODE("DefaultValue", "name value", {
name: "[AST_Destructured|AST_SymbolDeclaration] name of the variable",
value: "[AST_Node] value to assign if variable is `undefined`",
},
_equals: function(node) {
return this.name.equals(node.name)
&& this.value.equals(node.value);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1295,9 +1485,14 @@ var AST_Call = DEFNODE("Call", "args expression optional pure terminal", {
args: "[AST_Node*] array of arguments",
expression: "[AST_Node] expression to invoke as function",
optional: "[boolean] whether the expression is optional chaining",
pure: "[string/S] marker for side-effect-free call expression",
pure: "[boolean/S] marker for side-effect-free call expression",
terminal: "[boolean] whether the chain has ended",
},
_equals: function(node) {
return !this.optional == !node.optional
&& this.expression.equals(node.expression)
&& all_equals(this.args, node.args);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1324,7 +1519,10 @@ var AST_New = DEFNODE("New", null, {
var AST_Sequence = DEFNODE("Sequence", "expressions", {
$documentation: "A sequence expression (comma-separated expressions)",
$propdoc: {
expressions: "[AST_Node*] array of expressions (at least two)"
expressions: "[AST_Node*] array of expressions (at least two)",
},
_equals: function(node) {
return all_equals(this.expressions, node.expressions);
},
walk: function(visitor) {
var node = this;
@@ -1353,6 +1551,11 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression optional property termina
property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node",
terminal: "[boolean] whether the chain has ended",
},
_equals: function(node) {
return !this.optional == !node.optional
&& prop_equals(this.property, node.property)
&& this.expression.equals(node.expression);
},
get_property: function() {
var p = this.property;
if (p instanceof AST_Constant) return p.value;
@@ -1365,8 +1568,11 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression optional property termina
},
});
var AST_Dot = DEFNODE("Dot", null, {
var AST_Dot = DEFNODE("Dot", "quoted", {
$documentation: "A dotted property access expression",
$propdoc: {
quoted: "[boolean] whether property is transformed from a quoted string",
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1397,6 +1603,9 @@ var AST_Spread = DEFNODE("Spread", "expression", {
$propdoc: {
expression: "[AST_Node] expression to be expanded",
},
_equals: function(node) {
return this.expression.equals(node.expression);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1412,7 +1621,11 @@ var AST_Unary = DEFNODE("Unary", "operator expression", {
$documentation: "Base class for unary expressions",
$propdoc: {
operator: "[string] the operator",
expression: "[AST_Node] expression that this unary operator applies to"
expression: "[AST_Node] expression that this unary operator applies to",
},
_equals: function(node) {
return this.operator == node.operator
&& this.expression.equals(node.expression);
},
walk: function(visitor) {
var node = this;
@@ -1442,6 +1655,11 @@ var AST_Binary = DEFNODE("Binary", "operator left right", {
operator: "[string] the operator",
right: "[AST_Node] right-hand side expression"
},
_equals: function(node) {
return this.operator == node.operator
&& this.left.equals(node.left)
&& this.right.equals(node.right);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1463,6 +1681,11 @@ var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative",
consequent: "[AST_Node]",
alternative: "[AST_Node]"
},
_equals: function(node) {
return this.condition.equals(node.condition)
&& this.consequent.equals(node.consequent)
&& this.alternative.equals(node.alternative);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1489,6 +1712,12 @@ var AST_Assign = DEFNODE("Assign", null, {
throw new Error("left must be assignable: " + node.TYPE);
}
});
} else if (!(this.left instanceof AST_Infinity
|| this.left instanceof AST_NaN
|| this.left instanceof AST_PropAccess && !this.left.optional
|| this.left instanceof AST_SymbolRef
|| this.left instanceof AST_Undefined)) {
throw new Error("left must be assignable");
}
},
}, AST_Binary);
@@ -1498,6 +1727,9 @@ var AST_Await = DEFNODE("Await", "expression", {
$propdoc: {
expression: "[AST_Node] expression with Promise to resolve on",
},
_equals: function(node) {
return this.expression.equals(node.expression);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1515,6 +1747,10 @@ var AST_Yield = DEFNODE("Yield", "expression nested", {
expression: "[AST_Node?] return value for iterator, or null if undefined",
nested: "[boolean] whether to iterate over expression as generator",
},
_equals: function(node) {
return !this.nested == !node.nested
&& prop_equals(this.expression, node.expression);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1537,6 +1773,9 @@ var AST_Array = DEFNODE("Array", "elements", {
$propdoc: {
elements: "[AST_Node*] array of elements"
},
_equals: function(node) {
return all_equals(this.elements, node.elements);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1579,6 +1818,10 @@ var AST_DestructuredArray = DEFNODE("DestructuredArray", "elements", {
$propdoc: {
elements: "[(AST_DefaultValue|AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef)*] array of elements",
},
_equals: function(node) {
return prop_equals(this.rest, node.rest)
&& all_equals(this.elements, node.elements);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1596,6 +1839,10 @@ var AST_DestructuredKeyVal = DEFNODE("DestructuredKeyVal", "key value", {
key: "[string|AST_Node] property name. For computed property this is an AST_Node.",
value: "[AST_DefaultValue|AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef] property value",
},
_equals: function(node) {
return prop_equals(this.key, node.key)
&& this.value.equals(node.value);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1617,6 +1864,10 @@ var AST_DestructuredObject = DEFNODE("DestructuredObject", "properties", {
$propdoc: {
properties: "[AST_DestructuredKeyVal*] array of properties",
},
_equals: function(node) {
return prop_equals(this.rest, node.rest)
&& all_equals(this.properties, node.properties);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1638,6 +1889,9 @@ var AST_Object = DEFNODE("Object", "properties", {
$propdoc: {
properties: "[(AST_ObjectProperty|AST_Spread)*] array of properties"
},
_equals: function(node) {
return all_equals(this.properties, node.properties);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1661,6 +1915,10 @@ var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
key: "[string|AST_Node] property name. For computed property this is an AST_Node.",
value: "[AST_Node] property value. For getters and setters this is an AST_Accessor.",
},
_equals: function(node) {
return prop_equals(this.key, node.key)
&& this.value.equals(node.value);
},
walk: function(visitor) {
var node = this;
visitor.visit(node, function() {
@@ -1715,6 +1973,9 @@ var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
thedef: "[SymbolDef/S] the definition of this symbol"
},
_equals: function(node) {
return this.thedef ? this.thedef === node.thedef : this.name == node.name;
},
_validate: function() {
if (this.TYPE == "Symbol") throw new Error("should not instantiate AST_Symbol");
if (typeof this.name != "string") throw new Error("name must be string");
@@ -1732,10 +1993,14 @@ var AST_SymbolConst = DEFNODE("SymbolConst", null, {
var AST_SymbolImport = DEFNODE("SymbolImport", "key", {
$documentation: "Symbol defined by an `import` statement",
$propdoc: {
key: "[string] the original `export` name",
key: "[AST_String] the original `export` name",
},
_equals: function(node) {
return this.name == node.name
&& this.key.equals(node.key);
},
_validate: function() {
if (typeof this.key != "string") throw new Error("key must be string");
if (!(this.key instanceof AST_String)) throw new Error("key must be AST_String");
},
}, AST_SymbolConst);
@@ -1747,7 +2012,7 @@ var AST_SymbolVar = DEFNODE("SymbolVar", null, {
$documentation: "Symbol defining a variable",
}, AST_SymbolDeclaration);
var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
var AST_SymbolFunarg = DEFNODE("SymbolFunarg", "unused", {
$documentation: "Symbol naming a function argument",
}, AST_SymbolVar);
@@ -1779,7 +2044,7 @@ var AST_Label = DEFNODE("Label", "references", {
initialize: function() {
this.references = [];
this.thedef = this;
}
},
}, AST_Symbol);
var AST_SymbolRef = DEFNODE("SymbolRef", "fixed in_arg redef", {
@@ -1789,10 +2054,14 @@ var AST_SymbolRef = DEFNODE("SymbolRef", "fixed in_arg redef", {
var AST_SymbolExport = DEFNODE("SymbolExport", "alias", {
$documentation: "Reference in an `export` statement",
$propdoc: {
alias: "[string] the `export` alias",
alias: "[AST_String] the `export` alias",
},
_equals: function(node) {
return this.name == node.name
&& this.alias.equals(node.alias);
},
_validate: function() {
if (typeof this.alias != "string") throw new Error("alias must be string");
if (!(this.alias instanceof AST_String)) throw new Error("alias must be AST_String");
},
}, AST_SymbolRef);
@@ -1802,6 +2071,7 @@ var AST_LabelRef = DEFNODE("LabelRef", null, {
var AST_ObjectIdentity = DEFNODE("ObjectIdentity", null, {
$documentation: "Base class for `super` & `this`",
_equals: return_true,
_validate: function() {
if (this.TYPE == "ObjectIdentity") throw new Error("should not instantiate AST_ObjectIdentity");
},
@@ -1836,7 +2106,12 @@ var AST_Template = DEFNODE("Template", "expressions strings tag", {
$propdoc: {
expressions: "[AST_Node*] the placeholder expressions",
strings: "[string*] the raw text segments",
tag: "[AST_Node] tag function, or null if absent",
tag: "[AST_Node?] tag function, or null if absent",
},
_equals: function(node) {
return prop_equals(this.tag, node.tag)
&& list_equals(this.strings, node.strings)
&& all_equals(this.expressions, node.expressions);
},
walk: function(visitor) {
var node = this;
@@ -1861,6 +2136,9 @@ var AST_Template = DEFNODE("Template", "expressions strings tag", {
var AST_Constant = DEFNODE("Constant", null, {
$documentation: "Base class for all constants",
_equals: function(node) {
return this.value === node.value;
},
_validate: function() {
if (this.TYPE == "Constant") throw new Error("should not instantiate AST_Constant");
},
@@ -1909,6 +2187,9 @@ var AST_RegExp = DEFNODE("RegExp", "value", {
$propdoc: {
value: "[RegExp] the actual regexp"
},
_equals: function(node) {
return "" + this.value == "" + node.value;
},
_validate: function() {
if (!(this.value instanceof RegExp)) throw new Error("value must be RegExp");
},
@@ -1916,6 +2197,7 @@ var AST_RegExp = DEFNODE("RegExp", "value", {
var AST_Atom = DEFNODE("Atom", null, {
$documentation: "Base class for atoms",
_equals: return_true,
_validate: function() {
if (this.TYPE == "Atom") throw new Error("should not instantiate AST_Atom");
},
@@ -1923,27 +2205,27 @@ var AST_Atom = DEFNODE("Atom", null, {
var AST_Null = DEFNODE("Null", null, {
$documentation: "The `null` atom",
value: null
value: null,
}, AST_Atom);
var AST_NaN = DEFNODE("NaN", null, {
$documentation: "The impossible value",
value: 0/0
value: 0/0,
}, AST_Atom);
var AST_Undefined = DEFNODE("Undefined", null, {
$documentation: "The `undefined` value",
value: function(){}()
value: function(){}(),
}, AST_Atom);
var AST_Hole = DEFNODE("Hole", null, {
$documentation: "A hole in an array",
value: function(){}()
value: function(){}(),
}, AST_Atom);
var AST_Infinity = DEFNODE("Infinity", null, {
$documentation: "The `Infinity` value",
value: 1/0
value: 1/0,
}, AST_Atom);
var AST_Boolean = DEFNODE("Boolean", null, {
@@ -1955,12 +2237,12 @@ var AST_Boolean = DEFNODE("Boolean", null, {
var AST_False = DEFNODE("False", null, {
$documentation: "The `false` atom",
value: false
value: false,
}, AST_Boolean);
var AST_True = DEFNODE("True", null, {
$documentation: "The `true` atom",
value: true
value: true,
}, AST_Boolean);
/* -----[ TreeWalker ]----- */
@@ -1981,16 +2263,21 @@ TreeWalker.prototype = {
return this.stack[this.stack.length - 2 - (n || 0)];
},
push: function(node) {
if (node instanceof AST_Lambda) {
var value;
if (node instanceof AST_Class) {
this.directives = Object.create(this.directives);
value = "use strict";
} else if (node instanceof AST_Directive) {
value = node.value;
} else if (node instanceof AST_Lambda) {
this.directives = Object.create(this.directives);
} else if (node instanceof AST_Directive && !this.directives[node.value]) {
this.directives[node.value] = node;
}
if (value && !this.directives[value]) this.directives[value] = node;
this.stack.push(node);
},
pop: function() {
var node = this.stack.pop();
if (node instanceof AST_Lambda) {
if (node instanceof AST_Class || node instanceof AST_Lambda) {
this.directives = Object.getPrototypeOf(this.directives);
}
},
@@ -1999,7 +2286,7 @@ TreeWalker.prototype = {
},
find_parent: function(type) {
var stack = this.stack;
for (var i = stack.length; --i >= 0;) {
for (var i = stack.length - 1; --i >= 0;) {
var x = stack[i];
if (x instanceof type) return x;
}
@@ -2030,33 +2317,40 @@ TreeWalker.prototype = {
}
},
in_boolean_context: function() {
var self = this.self();
for (var i = 0, p; p = this.parent(i); i++) {
if (p instanceof AST_Conditional && p.condition === self
|| p instanceof AST_DWLoop && p.condition === self
|| p instanceof AST_For && p.condition === self
|| p instanceof AST_If && p.condition === self
|| p instanceof AST_Return && p.in_bool
|| p instanceof AST_Sequence && p.tail_node() !== self
|| p instanceof AST_SimpleStatement
|| p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
return true;
}
if (p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")
|| p instanceof AST_Conditional
|| p.tail_node() === self) {
self = p;
} else if (p instanceof AST_Return) {
for (var call, fn = p; call = this.parent(++i); fn = call) {
if (call.TYPE == "Call") {
if (!(fn instanceof AST_Lambda) || fn.name) return false;
} else if (fn instanceof AST_Lambda) {
return false;
}
}
} else {
for (var drop = true, level = 0, parent, self = this.self(); parent = this.parent(level++); self = parent) {
if (parent instanceof AST_Binary) switch (parent.operator) {
case "&&":
case "||":
if (parent.left === self) drop = false;
continue;
default:
return false;
}
if (parent instanceof AST_Conditional) {
if (parent.condition === self) return true;
continue;
}
if (parent instanceof AST_DWLoop) return parent.condition === self;
if (parent instanceof AST_For) return parent.condition === self;
if (parent instanceof AST_If) return parent.condition === self;
if (parent instanceof AST_Return) {
if (parent.in_bool) return true;
while (parent = this.parent(level++)) {
if (parent instanceof AST_Lambda) {
if (parent.name) return false;
parent = this.parent(level++);
if (parent.TYPE != "Call") return false;
break;
}
}
}
if (parent instanceof AST_Sequence) {
if (parent.tail_node() === self) continue;
return drop ? "d" : true;
}
if (parent instanceof AST_SimpleStatement) return drop ? "d" : true;
if (parent instanceof AST_UnaryPrefix) return parent.operator == "!";
return false;
}
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -28,7 +28,7 @@ function read_source_map(name, toplevel) {
var match = /^# ([^\s=]+)=(\S+)\s*$/.exec(comment.value);
if (!match) break;
if (match[1] == "sourceMappingURL") {
match = /^data:application\/json(;.*?)?;base64,(\S+)$/.exec(match[2]);
match = /^data:application\/json(;.*?)?;base64,([^,]+)$/.exec(match[2]);
if (!match) break;
return to_ascii(match[2]);
}
@@ -76,17 +76,20 @@ function minify(files, options) {
annotations: undefined,
compress: {},
enclose: false,
expression: false,
ie: false,
ie8: false,
keep_fargs: false,
keep_fnames: false,
mangle: {},
module: false,
nameCache: null,
output: {},
parse: {},
rename: undefined,
sourceMap: false,
timings: false,
toplevel: false,
toplevel: !!(options && options["module"]),
v8: false,
validate: false,
warnings: false,
@@ -95,20 +98,23 @@ function minify(files, options) {
}, true);
if (options.validate) AST_Node.enable_validation();
var timings = options.timings && { start: Date.now() };
if (options.rename === undefined) options.rename = options.compress && options.mangle;
if (options.annotations !== undefined) set_shorthand("annotations", options, [ "compress", "output" ]);
if (options.expression) set_shorthand("expression", options, [ "compress", "parse" ]);
if (options.ie8) options.ie = options.ie || options.ie8;
if (options.ie) set_shorthand("ie", options, [ "compress", "mangle", "output" ]);
if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
if (options.toplevel) set_shorthand("toplevel", options, [ "compress", "mangle" ]);
if (options.v8) set_shorthand("v8", options, [ "mangle", "output" ]);
if (options.webkit) set_shorthand("webkit", options, [ "compress", "mangle", "output" ]);
if (options.ie) set_shorthand("ie", options, [ "compress", "mangle", "output", "rename" ]);
if (options.keep_fargs) set_shorthand("keep_fargs", options, [ "compress", "mangle", "rename" ]);
if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle", "rename" ]);
if (options.module) set_shorthand("module", options, [ "compress", "parse" ]);
if (options.toplevel) set_shorthand("toplevel", options, [ "compress", "mangle", "rename" ]);
if (options.v8) set_shorthand("v8", options, [ "mangle", "output", "rename" ]);
if (options.webkit) set_shorthand("webkit", options, [ "compress", "mangle", "output", "rename" ]);
var quoted_props;
if (options.mangle) {
options.mangle = defaults(options.mangle, {
cache: options.nameCache && (options.nameCache.vars || {}),
eval: false,
ie: false,
keep_fargs: false,
keep_fnames: false,
properties: false,
reserved: [],
@@ -132,6 +138,7 @@ function minify(files, options) {
init_cache(options.mangle.cache);
init_cache(options.mangle.properties.cache);
}
if (options.rename === undefined) options.rename = options.compress && options.mangle;
if (options.sourceMap) {
options.sourceMap = defaults(options.sourceMap, {
content: null,
@@ -148,13 +155,11 @@ function minify(files, options) {
}, options.warnings == "verbose");
if (timings) timings.parse = Date.now();
var toplevel;
if (files instanceof AST_Toplevel) {
options.parse = options.parse || {};
if (files instanceof AST_Node) {
toplevel = files;
} else {
if (typeof files == "string") {
files = [ files ];
}
options.parse = options.parse || {};
if (typeof files == "string") files = [ files ];
options.parse.toplevel = null;
var source_map_content = options.sourceMap && options.sourceMap.content;
if (typeof source_map_content == "string" && source_map_content != "inline") {
@@ -166,17 +171,14 @@ function minify(files, options) {
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);
}
if (inlined_content) options.sourceMap.orig[name] = parse_source_map(inlined_content);
} else if (source_map_content) {
options.sourceMap.orig[name] = source_map_content;
}
}
}
if (quoted_props) {
reserve_quoted_keys(toplevel, quoted_props);
}
if (options.parse.expression) toplevel = toplevel.wrap_expression();
if (quoted_props) reserve_quoted_keys(toplevel, quoted_props);
[ "enclose", "wrap" ].forEach(function(action) {
var option = options[action];
if (!option) return;
@@ -187,8 +189,8 @@ function minify(files, options) {
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);
toplevel.figure_out_scope(options.rename);
toplevel.expand_names(options.rename);
}
if (timings) timings.compress = Date.now();
if (options.compress) {
@@ -203,7 +205,9 @@ function minify(files, options) {
toplevel.mangle_names(options.mangle);
}
if (timings) timings.properties = Date.now();
if (quoted_props) reserve_quoted_keys(toplevel, quoted_props);
if (options.mangle && options.mangle.properties) mangle_properties(toplevel, options.mangle.properties);
if (options.parse.expression) toplevel = toplevel.unwrap_expression();
if (timings) timings.output = Date.now();
var result = {};
var output = defaults(options.output, {

View File

@@ -192,6 +192,19 @@
value: from_moz(M.value),
});
},
StaticBlock: function(M) {
var start = my_start_token(M);
var end = my_end_token(M);
return new AST_ClassInit({
start: start,
end: end,
value: new AST_ClassInitBlock({
start: start,
end: end,
body: normalize_directives(M.body.map(from_moz)),
}),
});
},
ForOfStatement: function(M) {
return new (M.await ? AST_ForAwaitOf : AST_ForOf)({
start: my_start_token(M),
@@ -303,13 +316,22 @@
});
},
ExportAllDeclaration: function(M) {
var alias = M.exported ? read_name(M.exported) : "*";
var start = my_start_token(M);
var end = my_end_token(M);
return new AST_ExportForeign({
start: my_start_token(M),
end: my_end_token(M),
aliases: [ alias ],
keys: [ "*" ],
path: M.source.value,
start: start,
end: end,
aliases: [ M.exported ? from_moz_alias(M.exported) : new AST_String({
start: start,
value: "*",
end: end,
}) ],
keys: [ new AST_String({
start: start,
value: "*",
end: end,
}) ],
path: from_moz(M.source),
});
},
ExportDefaultDeclaration: function(M) {
@@ -346,15 +368,15 @@
if (M.source) {
var aliases = [], keys = [];
M.specifiers.forEach(function(prop) {
aliases.push(read_name(prop.exported));
keys.push(read_name(prop.local));
aliases.push(from_moz_alias(prop.exported));
keys.push(from_moz_alias(prop.local));
});
return new AST_ExportForeign({
start: my_start_token(M),
end: my_end_token(M),
aliases: aliases,
keys: keys,
path: M.source.value,
path: from_moz(M.source),
});
}
return new AST_ExportReferences({
@@ -362,38 +384,48 @@
end: my_end_token(M),
properties: M.specifiers.map(function(prop) {
var sym = new AST_SymbolExport(from_moz(prop.local));
sym.alias = read_name(prop.exported);
sym.alias = from_moz_alias(prop.exported);
return sym;
}),
});
},
ImportDeclaration: function(M) {
var start = my_start_token(M);
var end = my_end_token(M);
var all = null, def = null, props = null;
M.specifiers.forEach(function(prop) {
var sym = new AST_SymbolImport(from_moz(prop.local));
switch (prop.type) {
case "ImportDefaultSpecifier":
def = sym;
def.key = "";
def.key = new AST_String({
start: start,
value: "",
end: end,
});
break;
case "ImportNamespaceSpecifier":
all = sym;
all.key = "*";
all.key = new AST_String({
start: start,
value: "*",
end: end,
});
break;
default:
sym.key = prop.imported.name || syn.name;
sym.key = from_moz_alias(prop.imported);
if (!props) props = [];
props.push(sym);
break;
}
});
return new AST_Import({
start: my_start_token(M),
end: my_end_token(M),
start: start,
end: end,
all: all,
default: def,
properties: props,
path: M.source.value,
path: from_moz(M.source),
});
},
ImportExpression: function(M) {
@@ -714,6 +746,10 @@
};
});
def_to_moz(AST_ClassInit, function To_Moz_StaticBlock(M) {
return to_moz_scope("StaticBlock", M.value);
});
function To_Moz_ForOfStatement(is_await) {
return function(M) {
return {
@@ -780,38 +816,26 @@
});
def_to_moz(AST_ExportForeign, function To_Moz_ExportAllDeclaration_ExportNamedDeclaration(M) {
if (M.keys[0] == "*") return {
if (M.keys[0].value == "*") return {
type: "ExportAllDeclaration",
exported: M.aliases[0] == "*" ? null : {
type: "Identifier",
name: M.aliases[0],
},
source: {
type: "Literal",
value: M.path,
},
exported: M.aliases[0].value == "*" ? null : to_moz_alias(M.aliases[0]),
source: to_moz(M.path),
};
var specifiers = [];
for (var i = 0; i < M.aliases.length; i++) {
specifiers.push({
specifiers.push(set_moz_loc({
start: M.keys[i].start,
end: M.aliases[i].end,
}, {
type: "ExportSpecifier",
exported: {
type: "Identifier",
name: M.aliases[i],
},
local: {
type: "Identifier",
name: M.keys[i],
},
});
local: to_moz_alias(M.keys[i]),
exported: to_moz_alias(M.aliases[i]),
}));
}
return {
type: "ExportNamedDeclaration",
specifiers: specifiers,
source: {
type: "Literal",
value: M.path,
},
source: to_moz(M.path),
};
});
@@ -819,44 +843,41 @@
return {
type: "ExportNamedDeclaration",
specifiers: M.properties.map(function(prop) {
return {
return set_moz_loc({
start: prop.start,
end: prop.alias.end,
}, {
type: "ExportSpecifier",
local: to_moz(prop),
exported: {
type: "Identifier",
name: prop.alias,
},
};
exported: to_moz_alias(prop.alias),
});
}),
};
});
def_to_moz(AST_Import, function To_Moz_ImportDeclaration(M) {
var specifiers = M.properties ? M.properties.map(function(prop) {
return {
return set_moz_loc({
start: prop.key.start,
end: prop.end,
}, {
type: "ImportSpecifier",
local: to_moz(prop),
imported: {
type: "Identifier",
name: prop.key,
},
};
imported: to_moz_alias(prop.key),
});
}) : [];
if (M.all) specifiers.unshift({
if (M.all) specifiers.unshift(set_moz_loc(M.all, {
type: "ImportNamespaceSpecifier",
local: to_moz(M.all),
});
if (M.default) specifiers.unshift({
}));
if (M.default) specifiers.unshift(set_moz_loc(M.default, {
type: "ImportDefaultSpecifier",
local: to_moz(M.default),
});
}));
return {
type: "ImportDeclaration",
specifiers: specifiers,
source: {
type: "Literal",
value: M.path,
},
source: to_moz(M.path),
};
});
@@ -1005,7 +1026,7 @@
});
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
var flags = M.value.toString().match(/[gimuy]*$/)[0];
var flags = M.value.toString().match(/\/([gimuy]*)$/)[1];
var value = "/" + M.value.raw_source + "/" + flags;
return {
type: "Literal",
@@ -1013,8 +1034,8 @@
raw: value,
regex: {
pattern: M.value.raw_source,
flags: flags
}
flags: flags,
},
};
});
@@ -1203,6 +1224,14 @@
return node;
}
function from_moz_alias(moz) {
return new AST_String({
start: my_start_token(moz),
value: read_name(moz),
end: my_end_token(moz),
});
}
AST_Node.from_mozilla_ast = function(node) {
var save_stack = FROM_MOZ_STACK;
FROM_MOZ_STACK = [];
@@ -1254,6 +1283,13 @@
return node != null ? node.to_mozilla_ast() : null;
}
function to_moz_alias(alias) {
return is_identifier_string(alias.value) ? set_moz_loc(alias, {
type: "Identifier",
name: alias.value,
}) : to_moz(alias);
}
function to_moz_block(node) {
return {
type: "BlockStatement",

View File

@@ -55,6 +55,7 @@ function OutputStream(options) {
beautify : false,
braces : false,
comments : false,
extendscript : false,
galio : false,
ie : false,
indent_level : 4,
@@ -101,10 +102,18 @@ function OutputStream(options) {
}
}
function make_indent(value) {
if (typeof value == "number") return new Array(value + 1).join(" ");
if (!value) return "";
if (!/^\s*$/.test(value)) throw new Error("unsupported indentation: " + JSON.stringify("" + value));
return value;
}
var current_col = 0;
var current_line = 1;
var current_pos = 0;
var indentation = options.indent_start;
var current_indent = make_indent(options.indent_start);
var full_indent = make_indent(options.indent_level);
var half_indent = full_indent.length + 1 >> 1;
var last;
var line_end = 0;
var line_fixed = true;
@@ -115,17 +124,17 @@ function OutputStream(options) {
var might_need_semicolon;
var need_newline_indented = false;
var need_space = false;
var newline_insert = -1;
var output;
var stack;
var OUTPUT;
var stored = "";
function reset() {
last = "";
might_need_space = false;
might_need_semicolon = false;
stack = [];
var str = OUTPUT;
OUTPUT = "";
var str = output;
output = "";
return str;
}
@@ -227,32 +236,39 @@ function OutputStream(options) {
} : noop;
function insert_newlines(count) {
var index = OUTPUT.lastIndexOf("\n");
if (line_end < index) line_end = index;
var left = OUTPUT.slice(0, line_end);
var right = OUTPUT.slice(line_end);
adjust_mappings(count, right.length - current_col);
stored += output.slice(0, line_end);
output = output.slice(line_end);
var new_col = output.length;
adjust_mappings(count, new_col - current_col);
current_line += count;
current_pos += count;
current_col = right.length;
OUTPUT = left;
while (count--) OUTPUT += "\n";
OUTPUT += right;
current_col = new_col;
while (count--) stored += "\n";
}
var fix_line = options.max_line_len ? function() {
var fix_line = options.max_line_len ? function(flush) {
if (line_fixed) {
if (current_col > options.max_line_len) {
AST_Node.warn("Output exceeds {max_line_len} characters", options);
}
return;
}
if (current_col > options.max_line_len) insert_newlines(1);
line_fixed = true;
flush_mappings();
if (current_col > options.max_line_len) {
insert_newlines(1);
line_fixed = true;
}
if (line_fixed || flush) flush_mappings();
} : noop;
var requireSemicolonChars = makePredicate("( [ + * / - , .");
var require_semicolon = makePredicate("( [ + * / - , .");
function require_space(prev, ch, str) {
return is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\")
|| (ch == "/" && ch == prev)
|| ((ch == "+" || ch == "-") && ch == last)
|| last == "--" && ch == ">"
|| last == "!" && str == "--"
|| prev == "/" && (str == "in" || str == "instanceof");
}
var print = options.beautify
|| options.comments
@@ -276,45 +292,39 @@ function OutputStream(options) {
space();
}
}
newline_insert = -1;
var prev = last.slice(-1);
if (might_need_semicolon) {
might_need_semicolon = false;
if (prev == ":" && ch == "}" || (!ch || ";}".indexOf(ch) < 0) && prev != ";") {
if (options.semicolons || requireSemicolonChars[ch]) {
OUTPUT += ";";
if (prev == ":" && ch == "}" || prev != ";" && (!ch || ";}".indexOf(ch) < 0)) {
var need_semicolon = require_semicolon[ch];
if (need_semicolon || options.semicolons) {
output += ";";
current_col++;
current_pos++;
if (!line_fixed) {
fix_line();
if (line_fixed && !need_semicolon && output == ";") {
output = "";
current_col = 0;
}
}
if (line_end == output.length - 1) line_end++;
} else {
fix_line();
OUTPUT += "\n";
current_pos++;
output += "\n";
current_line++;
current_col = 0;
if (/^\s+$/.test(str)) {
// reset the semicolon flag, since we didn't print one
// now and might still have to later
might_need_semicolon = true;
}
// reset the semicolon flag, since we didn't print one
// now and might still have to later
if (/^\s+$/.test(str)) might_need_semicolon = true;
}
if (!options.beautify)
might_need_space = false;
if (!options.beautify) might_need_space = false;
}
}
if (might_need_space) {
if (is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\")
|| (ch == "/" && ch == prev)
|| ((ch == "+" || ch == "-") && ch == last)
|| str == "--" && last == "!"
|| str == "in" && prev == "/"
|| last == "--" && ch == ">") {
OUTPUT += " ";
if (require_space(prev, ch, str)) {
output += " ";
current_col++;
current_pos++;
}
if (prev != "<" || str != "!") might_need_space = false;
}
@@ -324,14 +334,13 @@ function OutputStream(options) {
token: mapping_token,
name: mapping_name,
line: current_line,
col: current_col
col: current_col,
});
mapping_token = false;
if (line_fixed) flush_mappings();
}
OUTPUT += str;
current_pos += str.length;
output += str;
var a = str.split(/\r?\n/), n = a.length - 1;
current_line += n;
current_col += a[0].length;
@@ -346,22 +355,15 @@ function OutputStream(options) {
if (might_need_semicolon) {
might_need_semicolon = false;
if (prev == ":" && ch == "}" || (!ch || ";}".indexOf(ch) < 0) && prev != ";") {
OUTPUT += ";";
output += ";";
might_need_space = false;
}
}
if (might_need_space) {
if (is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\")
|| (ch == "/" && ch == prev)
|| ((ch == "+" || ch == "-") && ch == last)
|| str == "--" && last == "!"
|| str == "in" && prev == "/"
|| last == "--" && ch == ">") {
OUTPUT += " ";
}
if (require_space(prev, ch, str)) output += " ";
if (prev != "<" || str != "!") might_need_space = false;
}
OUTPUT += str;
output += str;
last = str;
};
@@ -373,30 +375,25 @@ function OutputStream(options) {
var indent = options.beautify ? function(half) {
if (need_newline_indented) print("\n");
print(repeat_string(" ", half ? indentation - (options.indent_level >> 1) : indentation));
print(half ? current_indent.slice(0, -half_indent) : current_indent);
} : noop;
var with_indent = options.beautify ? function(cont) {
var save_indentation = indentation;
indentation += options.indent_level;
var save_indentation = current_indent;
current_indent += full_indent;
cont();
indentation = save_indentation;
current_indent = save_indentation;
} : function(cont) { cont() };
var may_add_newline = options.max_line_len || options.preserve_line ? function() {
fix_line();
line_end = OUTPUT.length;
line_end = output.length;
line_fixed = false;
} : noop;
var newline = options.beautify ? function() {
if (newline_insert < 0) return print("\n");
if (OUTPUT[newline_insert] != "\n") {
OUTPUT = OUTPUT.slice(0, newline_insert) + "\n" + OUTPUT.slice(newline_insert);
current_pos++;
current_line++;
}
newline_insert++;
print("\n");
line_end = output.length;
} : may_add_newline;
var semicolon = options.beautify ? function() {
@@ -410,10 +407,11 @@ function OutputStream(options) {
print(";");
}
function with_block(cont) {
function with_block(cont, end) {
print("{");
newline();
with_indent(cont);
add_mapping(end);
indent();
print("}");
}
@@ -452,13 +450,12 @@ function OutputStream(options) {
} : noop;
function get() {
if (!line_fixed) fix_line();
return OUTPUT;
if (!line_fixed) fix_line(true);
return stored + output;
}
function has_nlb() {
var index = OUTPUT.lastIndexOf("\n");
return /^ *$/.test(OUTPUT.slice(index + 1));
return /(^|\n) *$/.test(output);
}
function pad_comment(token, force) {
@@ -515,15 +512,13 @@ function OutputStream(options) {
scan.walk(tw);
}
if (current_pos == 0) {
if (current_line == 1 && current_col == 0) {
if (comments.length > 0 && options.shebang && comments[0].type == "comment5") {
print("#!" + comments.shift().value + "\n");
indent();
}
var preamble = options.preamble;
if (preamble) {
print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
}
if (preamble) print(preamble.replace(/\r\n?|\u2028|\u2029|(^|\S)\s*$/g, "$1\n"));
}
comments = comments.filter(comment_filter, node);
@@ -561,20 +556,18 @@ function OutputStream(options) {
return !/comment[134]/.test(c.type);
}))) return;
comments._dumped = self;
var insert = OUTPUT.length;
comments.filter(comment_filter, node).forEach(function(comment, index) {
pad_comment(comment, index || !tail);
print_comment(comment);
});
if (OUTPUT.length > insert) newline_insert = insert;
}
return {
get : get,
reset : reset,
indent : indent,
should_break : options.width ? function() {
return current_col - indentation >= options.width;
should_break : options.beautify && options.width ? function() {
return current_col >= options.width;
} : return_false,
has_parens : function() { return last.slice(-1) == "(" },
newline : newline,
@@ -708,6 +701,7 @@ function OutputStream(options) {
if (p instanceof AST_Class) return true;
// (x++)[y]
// (typeof x).y
// https://github.com/mishoo/UglifyJS/issues/115
if (p instanceof AST_PropAccess) return p.expression === this;
// (~x)`foo`
if (p instanceof AST_Template) return p.tag === this;
@@ -883,7 +877,9 @@ function OutputStream(options) {
return needs_parens_assign_cond(this, output);
});
PARENS(AST_Conditional, function(output) {
return needs_parens_assign_cond(this, output);
return needs_parens_assign_cond(this, output)
// https://github.com/mishoo/UglifyJS/issues/1144
|| output.option("extendscript") && output.parent() instanceof AST_Conditional;
});
PARENS(AST_Yield, function(output) {
return needs_parens_assign_cond(this, output);
@@ -962,7 +958,7 @@ function OutputStream(options) {
if (self.body.length > 0) {
output.with_block(function() {
display_body(self.body, false, output, allow_directives);
});
}, self.end);
} else print_braced_empty(self, output);
}
DEFPRINT(AST_BlockStatement, function(output) {
@@ -1070,6 +1066,14 @@ function OutputStream(options) {
}
output.semicolon();
});
function print_alias(alias, output) {
var value = alias.value;
if (value == "*" || is_identifier_string(value)) {
output.print_name(value);
} else {
output.print_string(value, alias.quote);
}
}
DEFPRINT(AST_ExportForeign, function(output) {
var self = this;
output.print("export");
@@ -1077,7 +1081,7 @@ function OutputStream(options) {
var len = self.keys.length;
if (len == 0) {
print_braced_empty(self, output);
} else if (self.keys[0] == "*") {
} else if (self.keys[0].value == "*") {
print_entry(0);
} else output.with_block(function() {
output.indent();
@@ -1089,22 +1093,22 @@ function OutputStream(options) {
print_entry(i);
}
output.newline();
});
}, self.end);
output.space();
output.print("from");
output.space();
output.print_string(self.path, self.quote);
self.path.print(output);
output.semicolon();
function print_entry(index) {
var alias = self.aliases[index];
var key = self.keys[index];
output.print_name(key);
if (alias != key) {
print_alias(key, output);
if (alias.value != key.value) {
output.space();
output.print("as");
output.space();
output.print_name(alias);
print_alias(alias, output);
}
}
});
@@ -1133,7 +1137,7 @@ function OutputStream(options) {
output.print("from");
output.space();
}
output.print_string(self.path, self.quote);
self.path.print(output);
output.semicolon();
});
@@ -1152,8 +1156,9 @@ function OutputStream(options) {
});
}
function print_arrow(self, output) {
if (self.argnames.length == 1 && self.argnames[0] instanceof AST_SymbolFunarg && !self.rest) {
self.argnames[0].print(output);
var argname = self.argnames.length == 1 && !self.rest && self.argnames[0];
if (argname instanceof AST_SymbolFunarg && argname.name != "yield") {
argname.print(output);
} else {
print_funargs(self, output);
}
@@ -1262,6 +1267,11 @@ function OutputStream(options) {
}
print_method(self, output);
});
DEFPRINT(AST_ClassInit, function(output) {
output.print("static");
output.space();
print_braced(this.value, output);
});
/* -----[ jumps ]----- */
function print_jump(kind, prop) {
@@ -1347,7 +1357,7 @@ function OutputStream(options) {
if (i < last && branch.body.length > 0)
output.newline();
});
});
}, self.end);
});
function print_branch_body(self, output) {
output.newline();
@@ -1464,17 +1474,15 @@ function OutputStream(options) {
parent = output.parent(level++);
if (parent instanceof AST_Call && parent.expression === node) return;
} while (parent instanceof AST_PropAccess && parent.expression === node);
output.print(typeof self.pure == "string" ? "/*" + self.pure + "*/" : "/*@__PURE__*/");
output.print("/*@__PURE__*/");
}
function print_call_args(self, output) {
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
output.add_mapping(self.start);
}
output.with_parens(function() {
self.args.forEach(function(expr, i) {
if (i) output.comma();
expr.print(output);
});
output.add_mapping(self.end);
});
}
DEFPRINT(AST_Call, function(output) {
@@ -1509,11 +1517,12 @@ function OutputStream(options) {
var expr = self.expression;
expr.print(output);
var prop = self.property;
if (output.option("ie") && RESERVED_WORDS[prop]) {
output.print(self.optional ? "?.[" : "[");
output.add_mapping(self.end);
output.print_string(prop);
output.print("]");
if (output.option("ie") && RESERVED_WORDS[prop] || self.quoted && output.option("keep_quoted_props")) {
if (self.optional) output.print("?.");
output.with_square(function() {
output.add_mapping(self.end);
output.print_string(prop);
});
} else {
if (expr instanceof AST_Number && !/[ex.)]/i.test(output.last())) output.print(".");
output.print(self.optional ? "?." : ".");
@@ -1525,9 +1534,10 @@ function OutputStream(options) {
DEFPRINT(AST_Sub, function(output) {
var self = this;
self.expression.print(output);
output.print(self.optional ? "?.[" : "[");
self.property.print(output);
output.print("]");
if (self.optional) output.print("?.");
output.with_square(function() {
self.property.print(output);
});
});
DEFPRINT(AST_Spread, function(output) {
output.print("...");
@@ -1546,8 +1556,10 @@ function OutputStream(options) {
exp.print(output);
});
DEFPRINT(AST_UnaryPostfix, function(output) {
this.expression.print(output);
output.print(this.operator);
var self = this;
self.expression.print(output);
output.add_mapping(self.end);
output.print(self.operator);
});
DEFPRINT(AST_Binary, function(output) {
var self = this;
@@ -1640,7 +1652,8 @@ function OutputStream(options) {
value.print(output);
});
DEFPRINT(AST_DestructuredObject, function(output) {
var props = this.properties, len = props.length, rest = this.rest;
var self = this;
var props = self.properties, len = props.length, rest = self.rest;
if (len || rest) output.with_block(function() {
props.forEach(function(prop, i) {
if (i) {
@@ -1660,8 +1673,8 @@ function OutputStream(options) {
rest.print(output);
}
output.newline();
});
else print_braced_empty(this, output);
}, self.end);
else print_braced_empty(self, output);
});
function print_properties(self, output, no_comma) {
var props = self.properties;
@@ -1675,7 +1688,7 @@ function OutputStream(options) {
prop.print(output);
});
output.newline();
});
}, self.end);
else print_braced_empty(self, output);
}
DEFPRINT(AST_Object, function(output) {
@@ -1737,19 +1750,19 @@ function OutputStream(options) {
var name = get_symbol_name(self);
output.print_name(name);
var alias = self.alias;
if (alias != name) {
if (alias.value != name) {
output.space();
output.print("as");
output.space();
output.print_name(alias);
print_alias(alias, output);
}
});
DEFPRINT(AST_SymbolImport, function(output) {
var self = this;
var name = get_symbol_name(self);
var key = self.key;
if (key && key != name) {
output.print_name(key);
if (key.value && key.value != name) {
print_alias(key, output);
output.space();
output.print("as");
output.space();
@@ -1819,9 +1832,6 @@ function OutputStream(options) {
case "\u2029": return "\\u2029";
}
}));
var p = output.parent();
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === this)
output.print(" ");
});
function force_statement(stat, output) {
@@ -1869,8 +1879,8 @@ function OutputStream(options) {
len = match[0].length;
digits = str.slice(len);
candidates.push(digits + "e-" + (digits.length + len - 1));
} else if (match = /0+$/.exec(str)) {
len = match[0].length;
} else if (match = /[^0]0+$/.exec(str)) {
len = match[0].length - 1;
candidates.push(str.slice(0, -len) + "e" + len);
} else if (match = /^(\d)\.(\d+)e(-?\d+)$/.exec(str)) {
candidates.push(match[1] + match[2] + "e" + (match[3] - match[2].length));
@@ -1888,7 +1898,7 @@ function OutputStream(options) {
output.indent();
stmt.print(output);
output.newline();
});
}, stmt.end);
}
/* -----[ source map generators ]----- */
@@ -1911,22 +1921,27 @@ function OutputStream(options) {
// or if we should add even more.
DEFMAP([
AST_Array,
AST_Await,
AST_BlockStatement,
AST_Catch,
AST_Constant,
AST_Debugger,
AST_Definitions,
AST_Destructured,
AST_Directive,
AST_Finally,
AST_Jump,
AST_Lambda,
AST_New,
AST_Object,
AST_Spread,
AST_StatementWithBody,
AST_Symbol,
AST_Switch,
AST_SwitchBranch,
AST_Try,
AST_UnaryPrefix,
AST_Yield,
], function(output) {
output.add_mapping(this.start);
});

View File

@@ -237,8 +237,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
newline_before : false,
regex_allowed : false,
comments_before : [],
directives : {},
directive_stack : [],
directives : Object.create(null),
read_template : with_eof_error("Unterminated template literal", function(strings) {
var s = "";
for (;;) {
@@ -553,16 +552,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
function handle_dot() {
next();
var ch = peek();
if (ch == ".") {
var op = ".";
do {
op += ".";
next();
} while (peek() == ".");
return token("operator", op);
}
return is_digit(ch.charCodeAt(0)) ? read_num(".") : token("punc", ".");
if (looking_at("..")) return token("operator", "." + next() + next());
return is_digit(peek().charCodeAt(0)) ? read_num(".") : token("punc", ".");
}
function read_word() {
@@ -635,24 +626,19 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
};
next_token.add_directive = function(directive) {
S.directive_stack[S.directive_stack.length - 1].push(directive);
if (S.directives[directive]) S.directives[directive]++;
else S.directives[directive] = 1;
S.directives[directive] = true;
}
next_token.push_directives_stack = function() {
S.directive_stack.push([]);
S.directives = Object.create(S.directives);
}
next_token.pop_directives_stack = function() {
var directives = S.directive_stack.pop();
for (var i = directives.length; --i >= 0;) {
S.directives[directives[i]]--;
}
S.directives = Object.getPrototypeOf(S.directives);
}
next_token.has_directive = function(directive) {
return S.directives[directive] > 0;
return !!S.directives[directive];
}
return next_token;
@@ -699,6 +685,7 @@ function parse($TEXT, options) {
expression : false,
filename : null,
html5_comments : true,
module : false,
shebang : true,
strict : false,
toplevel : null,
@@ -820,7 +807,7 @@ function parse($TEXT, options) {
}
}
var statement = embed_tokens(function() {
var statement = embed_tokens(function(toplevel) {
handle_regexp();
switch (S.token.type) {
case "string":
@@ -859,15 +846,15 @@ function parse($TEXT, options) {
if (S.in_async) return simple_statement();
break;
case "export":
if (!toplevel && options.module !== "") unexpected();
next();
return export_();
case "import":
var token = peek();
if (!(token.type == "punc" && /^[(.]$/.test(token.value))) {
next();
return import_();
}
break;
if (token.type == "punc" && /^[(.]$/.test(token.value)) break;
if (!toplevel && options.module !== "") unexpected();
next();
return import_();
case "let":
if (is_vardefs()) {
next();
@@ -1069,13 +1056,13 @@ function parse($TEXT, options) {
return stat;
}
function has_modifier(name) {
function has_modifier(name, no_nlb) {
if (!is("name", name)) return;
var token = peek();
if (!token) return;
if (is_token(token, "operator", "=")) return;
if (token.type == "punc" && /^[(;}]$/.test(token.value)) return;
if (has_newline_before(token)) return;
if (no_nlb && has_newline_before(token)) return;
return next();
}
@@ -1105,7 +1092,7 @@ function parse($TEXT, options) {
}
var start = S.token;
var fixed = !!has_modifier("static");
var async = has_modifier("async");
var async = has_modifier("async", true);
if (is("operator", "*")) {
next();
var internal = is("name") && /^#/.test(S.token.value);
@@ -1124,6 +1111,18 @@ function parse($TEXT, options) {
}));
continue;
}
if (fixed && is("punc", "{")) {
props.push(new AST_ClassInit({
start: start,
value: new AST_ClassInitBlock({
start: start,
body: block_(),
end: prev(),
}),
end: prev(),
}));
continue;
}
var internal = is("name") && /^#/.test(S.token.value);
var key = as_property_key();
if (is("punc", "(")) {
@@ -1194,10 +1193,10 @@ function parse($TEXT, options) {
}
function for_() {
var await = is("name", "await") && next();
var await_token = is("name", "await") && next();
expect("(");
var init = null;
if (await || !is("punc", ";")) {
if (await_token || !is("punc", ";")) {
init = is("keyword", "const")
? (next(), const_(true))
: is("name", "let") && is_vardefs()
@@ -1206,7 +1205,7 @@ function parse($TEXT, options) {
? (next(), var_(true))
: expression(true);
var ctor;
if (await) {
if (await_token) {
expect_token("name", "of");
ctor = AST_ForAwaitOf;
} else if (is("operator", "in")) {
@@ -1316,6 +1315,11 @@ function parse($TEXT, options) {
}
if (node instanceof AST_SymbolFunarg) return node;
if (node instanceof AST_SymbolRef) return new AST_SymbolFunarg(node);
if (node instanceof AST_Yield) return new AST_SymbolFunarg({
start: node.start,
name: "yield",
end: node.end,
});
token_error(node.start, "Invalid arrow parameter");
}
@@ -1335,11 +1339,11 @@ function parse($TEXT, options) {
var loop = S.in_loop;
var labels = S.labels;
++S.in_function;
S.in_directives = true;
S.input.push_directives_stack();
S.in_loop = 0;
S.labels = [];
if (is("punc", "{")) {
S.in_directives = true;
body = block_();
value = null;
} else {
@@ -1407,7 +1411,7 @@ function parse($TEXT, options) {
name: name,
argnames: argnames,
rest: argnames.rest || null,
body: body
body: body,
});
if (is_strict) {
if (name) strict_verify_symbol(name);
@@ -1430,28 +1434,41 @@ function parse($TEXT, options) {
}
function is_alias() {
return is("name") || is_identifier_string(S.token.value);
return is("name") || is("string") || is_identifier_string(S.token.value);
}
function make_string(token) {
return new AST_String({
start: token,
quote: token.quote,
value: token.value,
end: token,
});
}
function as_path() {
var path = S.token;
expect_token("string");
semicolon();
return make_string(path);
}
function export_() {
if (is("operator", "*")) {
var key = S.token;
var alias = key;
next();
var alias = "*";
if (is("name", "as")) {
next();
if (!is_alias()) expect_token("name");
alias = S.token.value;
alias = S.token;
next();
}
expect_token("name", "from");
var path = S.token;
expect_token("string");
semicolon();
return new AST_ExportForeign({
aliases: [ alias ],
keys: [ "*" ],
path: path.value,
quote: path.quote,
aliases: [ make_string(alias) ],
keys: [ make_string(key) ],
path: as_path(),
});
}
if (is("punc", "{")) {
@@ -1465,26 +1482,20 @@ function parse($TEXT, options) {
if (is("name", "as")) {
next();
if (!is_alias()) expect_token("name");
aliases.push(S.token.value);
aliases.push(S.token);
next();
} else {
aliases.push(key.value);
aliases.push(key);
}
if (!is("punc", "}")) expect(",");
}
expect("}");
if (is("name", "from")) {
next();
var path = S.token;
expect_token("string");
semicolon();
return new AST_ExportForeign({
aliases: aliases,
keys: keys.map(function(token) {
return token.value;
}),
path: path.value,
quote: path.quote,
aliases: aliases.map(make_string),
keys: keys.map(make_string),
path: as_path(),
});
}
semicolon();
@@ -1492,7 +1503,7 @@ function parse($TEXT, options) {
properties: keys.map(function(token, index) {
if (!is_token(token, "name")) token_error(token, "Name expected");
var sym = _make_symbol(AST_SymbolExport, token);
sym.alias = aliases[index];
sym.alias = make_string(aliases[index]);
return sym;
}),
});
@@ -1582,26 +1593,42 @@ function parse($TEXT, options) {
var all = null;
var def = as_symbol(AST_SymbolImport, true);
var props = null;
if (def ? (def.key = "", is("punc", ",") && next()) : !is("string")) {
var cont;
if (def) {
def.key = new AST_String({
start: def.start,
value: "",
end: def.end,
});
if (cont = is("punc", ",")) next();
} else {
cont = !is("string");
}
if (cont) {
if (is("operator", "*")) {
var key = S.token;
next();
expect_token("name", "as");
all = as_symbol(AST_SymbolImport);
all.key = "*";
all.key = make_string(key);
} else {
expect("{");
props = [];
while (is_alias()) {
var alias;
if (is_token(peek(), "name", "as")) {
var key = S.token.value;
var key = S.token;
next();
next();
alias = as_symbol(AST_SymbolImport);
alias.key = key;
alias.key = make_string(key);
} else {
alias = as_symbol(AST_SymbolImport);
alias.key = alias.name;
alias.key = new AST_String({
start: alias.start,
value: alias.name,
end: alias.end,
});
}
props.push(alias);
if (!is("punc", "}")) expect(",");
@@ -1610,15 +1637,11 @@ function parse($TEXT, options) {
}
}
if (all || def || props) expect_token("name", "from");
var path = S.token;
expect_token("string");
semicolon();
return new AST_Import({
all: all,
default: def,
path: path.value,
path: as_path(),
properties: props,
quote: path.quote,
});
}
@@ -1796,7 +1819,7 @@ function parse($TEXT, options) {
ret = new AST_BigInt({ value: value });
break;
case "string":
ret = new AST_String({ value : value, quote : tok.quote });
ret = new AST_String({ value: value, quote: tok.quote });
break;
case "regexp":
ret = new AST_RegExp({ value: value });
@@ -2311,9 +2334,8 @@ function parse($TEXT, options) {
var comments = start.comments_before;
var i = HOP(start, "comments_before_length") ? start.comments_before_length : comments.length;
while (--i >= 0) {
var match = /[@#]__PURE__/.exec(comments[i].value);
if (match) {
expr.pure = match[0];
if (/[@#]__PURE__/.test(comments[i].value)) {
expr.pure = true;
break;
}
}
@@ -2546,9 +2568,13 @@ function parse($TEXT, options) {
return function() {
var start = S.token;
var body = [];
if (options.module) {
S.in_async = true;
S.input.add_directive("use strict");
}
S.input.push_directives_stack();
while (!is("eof"))
body.push(statement());
body.push(statement(true));
S.input.pop_directives_stack();
var end = prev() || start;
var toplevel = options.toplevel;

View File

@@ -43,10 +43,11 @@
"use strict";
var builtins = function() {
var names = [];
// NaN will be included due to Number.NaN
function get_builtins() {
var names = new Dictionary();
// constants
[
"NaN",
"null",
"true",
"false",
@@ -54,35 +55,79 @@ var builtins = function() {
"-Infinity",
"undefined",
].forEach(add);
// global functions
[
Array,
Boolean,
Date,
Error,
Function,
Math,
Number,
Object,
RegExp,
String,
].forEach(function(ctor) {
"encodeURI",
"encodeURIComponent",
"escape",
"eval",
"decodeURI",
"decodeURIComponent",
"isFinite",
"isNaN",
"parseFloat",
"parseInt",
"unescape",
].forEach(add);
// global constructors & objects
var global = Function("return this")();
[
"Array",
"ArrayBuffer",
"Atomics",
"BigInt",
"Boolean",
"console",
"DataView",
"Date",
"Error",
"Function",
"Int8Array",
"Intl",
"JSON",
"Map",
"Math",
"Number",
"Object",
"Promise",
"Proxy",
"Reflect",
"RegExp",
"Set",
"String",
"Symbol",
"WebAssembly",
].forEach(function(name) {
add(name);
var ctor = global[name];
if (!ctor) return;
Object.getOwnPropertyNames(ctor).map(add);
if (ctor.prototype) {
if (typeof ctor != "function") return;
if (ctor.__proto__) Object.getOwnPropertyNames(ctor.__proto__).map(add);
if (ctor.prototype) Object.getOwnPropertyNames(ctor.prototype).map(add);
try {
Object.getOwnPropertyNames(new ctor()).map(add);
Object.getOwnPropertyNames(ctor.prototype).map(add);
} catch (e) {
try {
Object.getOwnPropertyNames(ctor()).map(add);
} catch (e) {}
}
});
return makePredicate(names);
return (get_builtins = function() {
return names.clone();
})();
function add(name) {
names.push(name);
names.set(name, true);
}
}();
}
function reserve_quoted_keys(ast, reserved) {
ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ClassProperty) {
if (node.start && node.start.quote) add(node.key);
} else if (node instanceof AST_Dot) {
if (node.quoted) add(node.property);
} else if (node instanceof AST_ObjectProperty) {
if (node.start && node.start.quote) add(node.key);
} else if (node instanceof AST_Sub) {
@@ -116,9 +161,9 @@ function mangle_properties(ast, options) {
reserved: null,
}, true);
var reserved = Object.create(options.builtins ? null : builtins);
var reserved = options.builtins ? new Dictionary() : get_builtins();
if (Array.isArray(options.reserved)) options.reserved.forEach(function(name) {
reserved[name] = true;
reserved.set(name, true);
});
var cname = -1;
@@ -126,7 +171,7 @@ function mangle_properties(ast, options) {
if (options.cache) {
cache = options.cache.props;
cache.each(function(name) {
reserved[name] = true;
reserved.set(name, true);
});
} else {
cache = new Dictionary();
@@ -141,8 +186,8 @@ function mangle_properties(ast, options) {
var debug_suffix;
if (debug) debug_suffix = options.debug === true ? "" : options.debug;
var names_to_mangle = Object.create(null);
var unmangleable = Object.create(reserved);
var names_to_mangle = new Dictionary();
var unmangleable = reserved.clone();
// step 1: find candidates to mangle
ast.walk(new TreeWalker(function(node) {
@@ -211,20 +256,26 @@ function mangle_properties(ast, options) {
// only function declarations after this line
function can_mangle(name) {
if (unmangleable[name]) return false;
if (unmangleable.has(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;
return cache.has(name) || names_to_mangle[name];
if (reserved.has(name)) {
AST_Node.info("Preserving reserved property {this}", name);
return false;
}
if (regex && !regex.test(name)) {
AST_Node.info("Preserving excluded property {this}", name);
return false;
}
return cache.has(name) || names_to_mangle.has(name);
}
function add(name) {
if (can_mangle(name)) names_to_mangle[name] = true;
if (!should_mangle(name)) unmangleable[name] = true;
if (can_mangle(name)) names_to_mangle.set(name, true);
if (!should_mangle(name)) unmangleable.set(name, true);
}
function mangle(name) {
@@ -243,6 +294,10 @@ function mangle_properties(ast, options) {
if (/^#/.test(name)) mangled = "#" + mangled;
cache.set(name, mangled);
}
AST_Node.info("Mapping property {name} to {mangled}", {
mangled: mangled,
name: name,
});
return mangled;
}

View File

@@ -44,9 +44,9 @@
"use strict";
function SymbolDef(id, scope, orig, init) {
this._bits = 0;
this.defun = undefined;
this.eliminated = 0;
this.exported = false;
this.global = false;
this.id = id;
this.init = init;
this.mangled_name = null;
@@ -54,8 +54,8 @@ function SymbolDef(id, scope, orig, init) {
this.orig = [ orig ];
this.references = [];
this.replaced = 0;
this.safe_ids = undefined;
this.scope = scope;
this.undeclared = false;
}
SymbolDef.prototype = {
@@ -64,19 +64,20 @@ SymbolDef.prototype = {
this.references.forEach(fn);
},
mangle: function(options) {
var cache = options.cache && options.cache.props;
if (this.global && cache && cache.has(this.name)) {
if (this.mangled_name) return;
var cache = this.global && options.cache && options.cache.props;
if (cache && cache.has(this.name)) {
this.mangled_name = cache.get(this.name);
} else if (!this.mangled_name && !this.unmangleable(options)) {
} else if (this.unmangleable(options)) {
names_in_use(this.scope, options).set(this.name, true);
} else {
var def = this.redefined();
if (def) {
this.mangled_name = def.mangled_name || def.name;
} else {
this.mangled_name = next_mangled_name(this, options);
}
if (this.global && cache) {
cache.set(this.name, this.mangled_name);
}
if (cache) cache.set(this.name, this.mangled_name);
}
},
redefined: function() {
@@ -92,18 +93,35 @@ SymbolDef.prototype = {
if (def && def !== self) return def.redefined() || def;
},
unmangleable: function(options) {
return this.global && !options.toplevel
|| this.exported
|| this.undeclared
|| !options.eval && this.scope.pinned()
|| options.keep_fnames
&& (this.orig[0] instanceof AST_SymbolClass
|| this.orig[0] instanceof AST_SymbolDefClass
|| this.orig[0] instanceof AST_SymbolDefun
|| this.orig[0] instanceof AST_SymbolLambda);
if (this.exported) return true;
if (this.undeclared) return true;
if (!options.eval && this.scope.pinned()) return true;
if (options.keep_fargs && is_funarg(this)) return true;
if (options.keep_fnames) {
var sym = this.orig[0];
if (sym instanceof AST_SymbolClass) return true;
if (sym instanceof AST_SymbolDefClass) return true;
if (sym instanceof AST_SymbolDefun) return true;
if (sym instanceof AST_SymbolLambda) return true;
}
if (!options.toplevel && this.global) return true;
return false;
},
};
DEF_BITPROPS(SymbolDef, [
"const_redefs",
"cross_loop",
"direct_access",
"exported",
"global",
"undeclared",
]);
function is_funarg(def) {
return def.orig[0] instanceof AST_SymbolFunarg || def.orig[1] instanceof AST_SymbolFunarg;
}
var unary_side_effects = makePredicate("delete ++ --");
function is_lhs(node, parent) {
@@ -205,20 +223,17 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
} else if (node instanceof AST_SymbolDefun) {
var def = defun.def_function(node, tw.parent());
if (exported) def.exported = true;
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.ie) def.defun = defun.parent_scope.resolve();
if (options.ie && node.name != "arguments") def.defun = defun.parent_scope.resolve();
} else if (node instanceof AST_SymbolLet) {
var def = scope.def_variable(node);
if (exported) def.exported = true;
} else if (node instanceof AST_SymbolVar) {
var def = defun.def_variable(node, node instanceof AST_SymbolImport ? undefined : null);
if (exported) def.exported = true;
entangle(defun, scope);
}
function walk_scope(descend) {
@@ -231,16 +246,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
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);
@@ -261,6 +266,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
}
if (node instanceof AST_Lambda) {
in_arg.push(node);
if (node.name) node.name.walk(tw);
node.argnames.forEach(function(argname) {
argname.walk(tw);
});
@@ -280,13 +286,23 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
// ensure mangling works if `catch` reuses a scope variable
var redef = def.redefined();
if (redef) for (var s = node.scope; s; s = s.parent_scope) {
push_uniq(s.enclosed, redef);
if (!push_uniq(s.enclosed, redef)) break;
if (s === redef.scope) break;
}
} else if (node instanceof AST_SymbolConst) {
// ensure compression works if `const` reuses a scope variable
var redef = def.redefined();
if (redef) redef.const_redefs = true;
} else if (def.scope !== node.scope && (node instanceof AST_SymbolDefun
|| node instanceof AST_SymbolFunarg
|| node instanceof AST_SymbolVar)) {
node.mark_enclosed(options);
var redef = node.scope.find_variable(node.name);
if (node.thedef !== redef) {
node.thedef = redef;
redef.orig.push(node);
node.mark_enclosed(options);
}
}
if (node.name != "arguments") return true;
var parent = node instanceof AST_SymbolVar && tw.parent();
@@ -353,8 +369,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
// pass 3: fix up any scoping issue with IE8
if (options.ie) 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) {
var def = node.thedef;
var scope = def.defun;
if (def.name != "arguments" && scope.name instanceof AST_SymbolLambda && scope.name.name == def.name) {
scope = scope.parent_scope.resolve();
}
redefine(node, scope);
@@ -363,7 +380,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
if (node instanceof AST_SymbolLambda) {
var def = node.thedef;
if (!redefine(node, node.scope.parent_scope.resolve())) {
delete def.defun;
def.defun = undefined;
} else if (typeof node.thedef.init !== "undefined") {
node.thedef.init = false;
} else if (def.init) {
@@ -454,6 +471,7 @@ AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) {
this.uses_arguments = false;
this.def_variable(new AST_SymbolFunarg({
name: "arguments",
scope: this,
start: this.start,
end: this.end,
}));
@@ -463,11 +481,14 @@ AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) {
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
var def = this.definition();
for (var s = this.scope; s; s = s.parent_scope) {
push_uniq(s.enclosed, def);
if (!push_uniq(s.enclosed, def)) break;
if (!options) {
delete s._var_names;
} else if (options.keep_fnames) {
s.functions.each(function(d) {
s._var_names = undefined;
} else {
if (options.keep_fargs && s instanceof AST_Lambda) s.each_argname(function(arg) {
push_uniq(def.scope.enclosed, arg.definition());
});
if (options.keep_fnames) s.functions.each(function(d) {
push_uniq(def.scope.enclosed, d);
});
}
@@ -510,12 +531,12 @@ function names_in_use(scope, options) {
if (!names) {
scope.cname = -1;
scope.cname_holes = [];
scope.names_in_use = names = Object.create(null);
scope.names_in_use = names = new Dictionary();
var cache = options.cache && options.cache.props;
scope.enclosed.forEach(function(def) {
if (def.unmangleable(options)) names[def.name] = true;
if (def.unmangleable(options)) names.set(def.name, true);
if (def.global && cache && cache.has(def.name)) {
names[cache.get(def.name)] = true;
names.set(cache.get(def.name), true);
}
});
}
@@ -526,34 +547,33 @@ 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);
var names = new Dictionary();
var scopes = [ scope ];
def.forEach(function(sym) {
var scope = sym.scope;
do {
if (scopes.indexOf(scope) < 0) {
for (var name in names_in_use(scope, options)) {
names[name] = true;
}
scopes.push(scope);
} else break;
if (member(scope, scopes)) break;
names_in_use(scope, options).each(function(marker, name) {
names.set(name, marker);
});
scopes.push(scope);
} while (scope = scope.parent_scope);
});
var name;
for (var i = 0; i < holes.length; i++) {
name = base54(holes[i]);
if (names[name]) continue;
if (names.has(name)) continue;
holes.splice(i, 1);
in_use[name] = true;
in_use.set(name, true);
return name;
}
while (true) {
name = base54(++scope.cname);
if (in_use[name] || RESERVED_WORDS[name] || options.reserved.has[name]) continue;
if (!names[name]) break;
if (in_use.has(name) || RESERVED_WORDS[name] || options.reserved.has[name]) continue;
if (!names.has(name)) break;
holes.push(scope.cname);
}
in_use[name] = true;
in_use.set(name, true);
return name;
}
@@ -573,6 +593,7 @@ function _default_mangler_options(options) {
options = defaults(options, {
eval : false,
ie : false,
keep_fargs : false,
keep_fnames : false,
reserved : [],
toplevel : false,
@@ -580,38 +601,32 @@ function _default_mangler_options(options) {
webkit : false,
});
if (!Array.isArray(options.reserved)) options.reserved = [];
// Never mangle arguments
// Never mangle `arguments`
push_uniq(options.reserved, "arguments");
options.reserved.has = makePredicate(options.reserved);
return options;
}
// We only need to mangle declaration nodes. Special logic wired into the code
// generator will display the mangled name if it is present (and for
// `AST_SymbolRef`s it will use the mangled name of the `AST_SymbolDeclaration`
// that it points to).
AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
options = _default_mangler_options(options);
// We only need to mangle declaration nodes. Special logic wired
// into the code generator will display the mangled name if it's
// present (and for AST_SymbolRef-s it'll use the mangled name of
// the AST_SymbolDeclaration that it points to).
var lname = -1;
if (options.cache && options.cache.props) {
var mangled_names = names_in_use(this, options);
options.cache.props.each(function(mangled_name) {
mangled_names[mangled_name] = true;
mangled_names.set(mangled_name, true);
});
}
var cutoff = 36;
var lname = -1;
var redefined = [];
var tw = new TreeWalker(function(node, descend) {
if (node instanceof AST_LabeledStatement) {
// lname is incremented when we get to the AST_Label
var save_nesting = lname;
descend();
if (!options.v8 || !in_label(tw)) lname = save_nesting;
return true;
}
var save_nesting;
if (node instanceof AST_BlockScope) {
// `lname` is incremented when we get to the `AST_Label`
if (node instanceof AST_LabeledStatement) save_nesting = lname;
if (options.webkit && node instanceof AST_IterationStatement && node.init instanceof AST_Let) {
node.init.definitions.forEach(function(defn) {
defn.name.match_symbol(function(sym) {
@@ -627,9 +642,9 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
});
}, true);
}
node.to_mangle = [];
var to_mangle = node.to_mangle = [];
node.variables.each(function(def) {
if (!defer_redef(def)) node.to_mangle.push(def);
if (!defer_redef(def)) to_mangle.push(def);
});
descend();
if (options.cache && node instanceof AST_Toplevel) {
@@ -640,7 +655,24 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
sym.scope = node;
sym.reference(options);
}
node.to_mangle.forEach(mangle);
if (to_mangle.length > cutoff) {
var indices = to_mangle.map(function(def, index) {
return index;
}).sort(function(i, j) {
return to_mangle[j].references.length - to_mangle[i].references.length || i - j;
});
to_mangle = indices.slice(0, cutoff).sort(function(i, j) {
return i - j;
}).map(function(index) {
return to_mangle[index];
}).concat(indices.slice(cutoff).sort(function(i, j) {
return i - j;
}).map(function(index) {
return to_mangle[index];
}));
}
to_mangle.forEach(mangle);
if (node instanceof AST_LabeledStatement && !(options.v8 && in_label(tw))) lname = save_nesting;
return true;
}
if (node instanceof AST_Label) {
@@ -673,7 +705,12 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
}
redefined.push(def);
def.references.forEach(reference);
if (sym instanceof AST_SymbolCatch || sym instanceof AST_SymbolConst) reference(sym);
if (sym instanceof AST_SymbolCatch || sym instanceof AST_SymbolConst) {
reference(sym);
def.redefined = function() {
return redef;
};
}
return true;
function reference(sym) {

View File

@@ -77,21 +77,23 @@ function vlq_encode(num) {
}
function create_array_map() {
var map = Object.create(null);
var map = new Dictionary();
var array = [];
array.index = function(name) {
if (!HOP(map, name)) {
map[name] = array.length;
var index = map.get(name);
if (!(index >= 0)) {
index = array.length;
array.push(name);
map.set(name, index);
}
return map[name];
return index;
};
return array;
}
function SourceMap(options) {
var sources = create_array_map();
var sources_content = options.includeSources && Object.create(null);
var sources_content = options.includeSources && new Dictionary();
var names = create_array_map();
var mappings = "";
if (options.orig) Object.keys(options.orig).forEach(function(name) {
@@ -110,7 +112,7 @@ function SourceMap(options) {
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;
if (content) sources_content.set(map.sources[i], content);
}
});
var prev_source;
@@ -144,8 +146,8 @@ function SourceMap(options) {
add(source, gen_line, gen_col, orig_line, orig_col, name);
} : add,
setSourceContent: sources_content ? function(source, content) {
if (!(source in sources_content)) {
sources_content[source] = content;
if (!sources_content.has(source)) {
sources_content.set(source, content);
}
} : noop,
toString: function() {
@@ -155,7 +157,7 @@ function SourceMap(options) {
sourceRoot: options.root || undefined,
sources: sources,
sourcesContent: sources_content ? sources.map(function(source) {
return sources_content[source] || null;
return sources_content.get(source) || null;
}) : undefined,
names: names,
mappings: mappings,

View File

@@ -55,14 +55,6 @@ function find_if(func, array) {
for (var i = array.length; --i >= 0;) if (func(array[i])) return array[i];
}
function repeat_string(str, i) {
if (i <= 0) return "";
if (i == 1) return str;
var d = repeat_string(str, i >> 1);
d += d;
return i & 1 ? d + str : d;
}
function configure_error_stack(fn) {
Object.defineProperty(fn.prototype, "stack", {
get: function() {
@@ -96,15 +88,6 @@ function defaults(args, defs, croak) {
return defs;
}
function merge(obj, ext) {
var count = 0;
for (var i in ext) if (HOP(ext, i)) {
obj[i] = ext[i];
count++;
}
return count;
}
function noop() {}
function return_false() { return false; }
function return_true() { return true; }
@@ -144,8 +127,10 @@ function push_uniq(array, el) {
function string_template(text, props) {
return text.replace(/\{([^{}]+)\}/g, function(str, p) {
var value = props[p];
return value instanceof AST_Node ? value.print_to_string() : value;
var value = p == "this" ? props : props[p];
if (value instanceof AST_Node) return value.print_to_string();
if (value instanceof AST_Token) return value.file + ":" + value.line + "," + value.col;
return value;
});
}
@@ -171,63 +156,80 @@ function all(array, predicate) {
}
function Dictionary() {
this._values = Object.create(null);
this._size = 0;
this.values = Object.create(null);
}
Dictionary.prototype = {
set: function(key, val) {
if (!this.has(key)) ++this._size;
this._values["$" + key] = val;
if (key == "__proto__") {
this.proto_value = val;
} else {
this.values[key] = val;
}
return this;
},
add: function(key, val) {
if (this.has(key)) {
this.get(key).push(val);
var list = this.get(key);
if (list) {
list.push(val);
} else {
this.set(key, [ val ]);
}
return this;
},
get: function(key) { return this._values["$" + key] },
get: function(key) {
return key == "__proto__" ? this.proto_value : this.values[key];
},
del: function(key) {
if (this.has(key)) {
--this._size;
delete this._values["$" + key];
if (key == "__proto__") {
delete this.proto_value;
} else {
delete this.values[key];
}
return this;
},
has: function(key) { return ("$" + key) in this._values },
has: function(key) {
return key == "__proto__" ? "proto_value" in this : key in this.values;
},
all: function(predicate) {
for (var i in this._values)
if (!predicate(this._values[i], i.substr(1)))
return false;
for (var i in this.values)
if (!predicate(this.values[i], i)) return false;
if ("proto_value" in this && !predicate(this.proto_value, "__proto__")) return false;
return true;
},
each: function(f) {
for (var i in this._values)
f(this._values[i], i.substr(1));
for (var i in this.values)
f(this.values[i], i);
if ("proto_value" in this) f(this.proto_value, "__proto__");
},
size: function() {
return this._size;
return Object.keys(this.values).length + ("proto_value" in this);
},
map: function(f) {
var ret = [];
for (var i in this._values)
ret.push(f(this._values[i], i.substr(1)));
for (var i in this.values)
ret.push(f(this.values[i], i));
if ("proto_value" in this) ret.push(f(this.proto_value, "__proto__"));
return ret;
},
clone: function() {
var ret = new Dictionary();
for (var i in this._values)
ret._values[i] = this._values[i];
ret._size = this._size;
this.each(function(value, i) {
ret.set(i, value);
});
return ret;
},
toObject: function() { return this._values }
toObject: function() {
var obj = {};
this.each(function(value, i) {
obj["$" + i] = value;
});
return obj;
},
};
Dictionary.fromObject = function(obj) {
var dict = new Dictionary();
dict._size = merge(dict._values, obj);
for (var i in obj)
if (HOP(obj, i)) dict.set(i.slice(1), obj[i]);
return dict;
};
@@ -265,3 +267,21 @@ function first_in_statement(stack, arrow, export_default) {
return false;
}
}
function DEF_BITPROPS(ctor, props) {
if (props.length > 31) throw new Error("Too many properties: " + props.length + "\n" + props.join(", "));
props.forEach(function(name, pos) {
var mask = 1 << pos;
Object.defineProperty(ctor.prototype, name, {
get: function() {
return !!(this._bits & mask);
},
set: function(val) {
if (val)
this._bits |= mask;
else
this._bits &= ~mask;
},
});
});
}

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.14.3",
"version": "3.17.2",
"engines": {
"node": ">=0.8.0"
},
@@ -23,7 +23,7 @@
"LICENSE"
],
"devDependencies": {
"acorn": "~8.2.1",
"acorn": "~8.7.1",
"semver": "~6.3.0"
},
"scripts": {

View File

@@ -17,6 +17,7 @@ var urls = [
"https://unpkg.com/mathjs@6.2.3/dist/math.js",
"https://unpkg.com/react@15.3.2/dist/react.js",
"https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.js",
"https://cdnjs.cloudflare.com/ajax/libs/antd/4.18.7/antd.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",

View File

@@ -60,8 +60,9 @@ function log() {
console.log("%s", tmpl.apply(null, arguments));
}
function make_code(ast, options) {
function make_code(ast, options, expression) {
var stream = U.OutputStream(options);
if (expression) ast = ast.clone(true).unwrap_expression();
ast.print(stream);
return stream.get();
}
@@ -69,9 +70,7 @@ function make_code(ast, options) {
function parse_test(file) {
var script = fs.readFileSync(file, "utf8");
try {
var ast = U.parse(script, {
filename: file
});
var ast = U.parse(script, { filename: file, module: "" });
} catch (e) {
console.error("Caught error while parsing tests in " + file);
console.error(e);
@@ -98,14 +97,14 @@ function parse_test(file) {
file: file,
line: node.start.line,
col: node.start.col,
code: make_code(node, { beautify: false })
code: make_code(node, { beautify: false }),
}));
}
function read_string(stat) {
if (stat.TYPE == "SimpleStatement") {
var body = stat.body;
switch(body.TYPE) {
switch (body.TYPE) {
case "String":
return body.value;
case "Array":
@@ -142,7 +141,7 @@ function parse_test(file) {
].indexOf(label.name) >= 0, tmpl("Unsupported label {name} [{line},{col}]", {
name: label.name,
line: label.start.line,
col: label.start.col
col: label.start.col,
}));
var stat = node.body;
if (label.name == "expect_exact" || label.name == "node_version") {
@@ -155,12 +154,12 @@ function parse_test(file) {
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
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
col: label.start.col,
}));
return node.value;
}));
@@ -180,16 +179,23 @@ function parse_test(file) {
// Try to reminify original input with standard options
// to see if it matches expect_stdout.
function reminify(orig_options, input_code, input_formatted, stdout) {
function reminify(expression, 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) [
if (expression) {
if (!options.parse || typeof options.parse != "object") options.parse = {};
options.parse.expression = true;
if (options.compress == null) options.compress = {};
if (options.compress) {
if (typeof options.compress != "object") options.compress = {};
options.compress.expression = true;
}
}
[
"keep_fargs",
"keep_fnames",
].forEach(function(name) {
if (name in orig_options) {
options.compress[name] = orig_options[name];
}
if (name in orig_options) options[name] = orig_options[name];
});
var options_formatted = JSON.stringify(options, null, 4);
options.validate = true;
@@ -214,7 +220,7 @@ function reminify(orig_options, input_code, input_formatted, stdout) {
} else {
var toplevel = sandbox.has_toplevel(options);
var expected = stdout[toplevel ? 1 : 0];
var actual = sandbox.run_code(result.code, toplevel);
var actual = run_code(expression, result.code, toplevel);
if (typeof expected != "string" && typeof actual != "string" && expected.name == actual.name) {
actual = expected;
}
@@ -249,18 +255,23 @@ function reminify(orig_options, input_code, input_formatted, stdout) {
return true;
}
function run_code(expression, code, toplevel) {
return sandbox.run_code(expression ? "console.log(" + code + ");" : code, toplevel);
}
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);
expect = to_toplevel(test.expect, test.mangle, test.expression);
expect = make_code(expect, output_options, test.expression);
} else {
expect = test.expect_exact;
}
var input = to_toplevel(test.input, test.mangle);
var input_code = make_code(input);
var input = to_toplevel(test.input, test.mangle, test.expression);
var input_code = make_code(input, {}, test.expression);
var input_formatted = make_code(test.input, {
annotations: true,
beautify: true,
@@ -270,7 +281,7 @@ function test_case(test) {
});
try {
input.validate_ast();
U.parse(input_code);
U.parse(input_code, { expression: test.expression });
} catch (ex) {
log([
"!!! Cannot parse input",
@@ -296,8 +307,9 @@ function test_case(test) {
warnings_emitted.push(text);
}, /"INFO: /.test(expected_warnings));
}
var quoted_props;
if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) {
var quoted_props = test.mangle.properties.reserved;
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);
@@ -312,9 +324,10 @@ function test_case(test) {
if (test.mangle) {
output.compute_char_frequency(test.mangle);
output.mangle_names(test.mangle);
if (quoted_props) U.reserve_quoted_keys(input, quoted_props);
if (test.mangle.properties) U.mangle_properties(output, test.mangle.properties);
}
var output_code = make_code(output, output_options);
var output_code = make_code(output, output_options, test.expression);
U.AST_Node.log_function();
if (expect != output_code) {
log([
@@ -337,7 +350,7 @@ function test_case(test) {
// expect == output
try {
output.validate_ast();
U.parse(output_code);
U.parse(output_code, { expression: test.expression });
} catch (ex) {
log([
"!!! Test matched expected result but cannot parse output",
@@ -381,7 +394,7 @@ function test_case(test) {
}
}
if (test.expect_stdout && (!test.node_version || semver.satisfies(process.version, test.node_version))) {
var stdout = [ sandbox.run_code(input_code), sandbox.run_code(input_code, true) ];
var stdout = [ run_code(test.expression, input_code), run_code(test.expression, input_code, true) ];
var toplevel = sandbox.has_toplevel({
compress: test.options,
mangle: test.mangle
@@ -410,7 +423,7 @@ function test_case(test) {
});
return false;
}
actual = sandbox.run_code(output_code, toplevel);
actual = run_code(test.expression, output_code, toplevel);
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
log([
"!!! failed",
@@ -431,7 +444,7 @@ function test_case(test) {
});
return false;
}
if (!reminify(test.options, input_code, input_formatted, stdout)) {
if (!reminify(test.expression, test.options, input_code, input_formatted, stdout)) {
return false;
}
}
@@ -442,20 +455,30 @@ function tmpl() {
return U.string_template.apply(null, arguments);
}
function to_toplevel(input, mangle_options) {
function to_toplevel(input, mangle_options, expression) {
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) {
input.walk(new U.TreeWalker(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 {
if (U.push_uniq(tokens, node.end)) node.end.line -= offset;
}));
var toplevel;
if (!expression) {
var directive = true;
toplevel = new U.AST_Toplevel(input.transform(new U.TreeTransformer(function(node) {
if (!directive) return node;
if (node === input) return;
if (node instanceof U.AST_SimpleStatement && node.body instanceof U.AST_String) {
return new U.AST_Directive(node.body);
}
directive = false;
}
})));
})));
} else if (input.body.length == 1) {
toplevel = input.body[0].wrap_expression();
} else {
throw new Error("Invalid expression");
}
toplevel.figure_out_scope(mangle_options);
return toplevel;
}

View File

@@ -442,9 +442,9 @@ compress_annotations_disabled_output_annotations_enabled: {
}
expect_exact: [
"/*@__PURE__*/a(3),",
"/*#__PURE__*/b(5),",
"/*@__PURE__*/b(5),",
"c(side_effect),",
"/*#__PURE__*/d(effect());",
"/*@__PURE__*/d(effect());",
]
}

View File

@@ -363,6 +363,28 @@ negate: {
}
inline_this: {
options = {
inline: true,
}
input: {
var p = "PASS";
console.log({
p: "FAIL",
q: (() => this.p)(),
}.q);
}
expect: {
var p = "PASS";
console.log({
p: "FAIL",
q: this.p,
}.q);
}
expect_stdout: "PASS"
node_version: ">=4"
}
dont_inline_this: {
options = {
inline: true,
}
@@ -486,7 +508,7 @@ drop_value: {
((a, b) => a + b)(console.log(42));
}
expect: {
((a, b) => {})(console.log(42));
void console.log(42);
}
expect_stdout: "42"
node_version: ">=4"
@@ -646,6 +668,28 @@ single_use_recursive: {
node_version: ">=4"
}
inline_iife_within_arrow: {
options = {
arrows: true,
inline: true,
}
input: {
var f = () => console.log(function(a) {
return Math.ceil(a);
}(Math.random()));
f();
}
expect: {
var f = () => {
return console.log((a = Math.random(), Math.ceil(a)));
var a;
};
f();
}
expect_stdout: "1"
node_version: ">=4"
}
issue_4388: {
options = {
inline: true,
@@ -884,3 +928,334 @@ issue_4772: {
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5251: {
options = {
inline: true,
toplevel: true,
}
input: {
(() => {
while (console.log(arguments))
var arguments = "FAIL";
})();
}
expect: {
(() => {
while (console.log(arguments))
var arguments = "FAIL";
})();
}
expect_stdout: true
node_version: ">=4"
}
issue_5342_1: {
options = {
dead_code: true,
inline: true,
toplevel: true,
unused: true,
}
input: {
for (var a in 0) {
(() => {
while (1);
})(new function(NaN) {
a.p;
}());
}
console.log(function() {
return b;
try {
b;
} catch (e) {
var b;
}
}());
}
expect: {
for (var a in 0) {
(function(NaN) {
a.p;
})();
while (1);
}
console.log(b);
var b;
}
expect_stdout: "undefined"
node_version: ">=4"
}
issue_5342_2: {
rename = true
options = {
dead_code: true,
inline: true,
toplevel: true,
unused: true,
}
input: {
for (var a in 0) {
(() => {
while (1);
})(new function(NaN) {
a.p;
}());
}
console.log(function() {
return b;
try {
b;
} catch (e) {
var b;
}
}());
}
expect: {
for (var a in 0) {
a.p;
while (1);
}
console.log(c);
var c;
}
expect_stdout: "undefined"
node_version: ">=4"
}
issue_5356: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
console.log((a => a++)(console));
}
expect: {
console.log((a => +a)(console));
}
expect_stdout: "NaN"
node_version: ">=4"
}
issue_5414_1: {
options = {
arrows: true,
if_return: true,
inline: true,
toplevel: true,
}
input: {
(() => {
(() => {
if (!console)
var arguments = 42;
while (console.log(arguments));
})();
})();
}
expect: {
(() => {
if (!console)
var arguments = 42;
while (console.log(arguments));
})();
}
expect_stdout: true
node_version: ">=4"
}
issue_5414_2: {
options = {
arrows: true,
inline: true,
side_effects: true,
toplevel: true,
}
input: {
(() => {
(() => {
if (!console)
var arguments = 42;
while (console.log(arguments));
})();
})();
}
expect: {
(() => {
if (!console)
var arguments = 42;
while (console.log(arguments));
})();
}
expect_stdout: true
node_version: ">=4"
}
issue_5416_1: {
options = {
dead_code: true,
evaluate: true,
inline: true,
loops: true,
unused: true,
}
input: {
var f = () => {
while ((() => {
console;
var a = function g(arguments) {
console.log(arguments);
}();
})());
};
f();
}
expect: {
var f = () => {
{
console;
arguments = void 0,
console.log(arguments);
var arguments;
return;
}
};
f();
}
expect_stdout: "undefined"
node_version: ">=4"
}
issue_5416_2: {
options = {
dead_code: true,
evaluate: true,
inline: true,
loops: true,
unused: true,
}
input: {
var f = () => {
while ((() => {
console;
var a = function g(arguments) {
while (console.log(arguments));
}();
})());
};
f();
}
expect: {
var f = () => {
{
console;
var arguments = void 0;
for (; console.log(arguments););
return;
}
};
f();
}
expect_stdout: "undefined"
node_version: ">=4"
}
issue_5416_3: {
options = {
inline: true,
side_effects: true,
unused: true,
}
input: {
var f = () => {
(() => {
var a = function g(arguments) {
console.log(arguments);
}();
})();
};
f();
}
expect: {
var f = () => {
arguments = void 0,
console.log(arguments);
var arguments;
};
f();
}
expect_stdout: "undefined"
node_version: ">=4"
}
issue_5416_4: {
options = {
arrows: true,
inline: true,
side_effects: true,
unused: true,
}
input: {
var f = () => {
(() => {
var a = function g(arguments) {
while (console.log(arguments));
}();
})();
};
f();
}
expect: {
var f = () => {
var arguments = void 0;
while (console.log(arguments));
return;
};
f();
}
expect_stdout: "undefined"
node_version: ">=4"
}
issue_5495: {
input: {
console.log((() => {
"use strict";
return function() {
return this;
}();
})());
}
expect_exact: 'console.log((()=>{"use strict";return function(){return this}()})());'
expect_stdout: "undefined"
node_version: ">=4"
}
issue_5653: {
options = {
arrows: true,
hoist_props: true,
passes: 2,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
console.log((a => {
a = { p: console };
return a++;
})());
}
expect: {
console.log((a => {
return console, +{};
})());
}
expect_stdout: "NaN"
node_version: ">=4"
}

View File

@@ -489,7 +489,7 @@ logical_assignments: {
node_version: ">=15"
}
logical_collapse_vars: {
logical_collapse_vars_1: {
options = {
collapse_vars: true,
}
@@ -509,6 +509,46 @@ logical_collapse_vars: {
node_version: ">=15"
}
logical_collapse_vars_2: {
options = {
collapse_vars: true,
}
input: {
var a = "PASS";
(function(b) {
b ||= (a = "FAIL", {});
return b;
})(console).log(a);
}
expect: {
var a = "PASS";
(function(b) {
return b ||= (a = "FAIL", {});
})(console).log(a);
}
expect_stdout: "PASS"
node_version: ">=15"
}
logical_collapse_vars_3: {
options = {
collapse_vars: true,
}
input: {
var a = 6;
a *= 7;
a ??= "FAIL";
console.log(a);
}
expect: {
var a = 6;
a = a * 7 ?? "FAIL";
console.log(a);
}
expect_stdout: "42"
node_version: ">=15"
}
logical_reduce_vars: {
options = {
evaluate: true,
@@ -550,6 +590,24 @@ logical_side_effects: {
node_version: ">=15"
}
evaluate_lazy_assignment: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 42;
console.log(a &&= "PASS");
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=15"
}
issue_4815_1: {
options = {
evaluate: true,
@@ -615,8 +673,7 @@ issue_4827_1: {
c &&= b = a, console.log(b);
}
expect: {
A = "FAIL";
var a = A, b = "PASS", c;
var a = A = "FAIL", b = "PASS", c;
c &&= b = a, console.log(b);
}
expect_stdout: "PASS"
@@ -746,3 +803,23 @@ issue_4924_2: {
expect_stdout: "PASS"
node_version: ">=15"
}
issue_5670: {
options = {
assignments: true,
evaluate: true,
reduce_vars: true,
}
input: {
(function(a, b) {
a && a && (a = b += "") || console.log("PASS");
})();
}
expect: {
(function(a, b) {
a = a,
console.log("PASS");
})();
}
expect_stdout: "PASS"
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@ arithmetic: {
}
expect_exact: "console.log((1n+0x2n)*(0o3n- -4n)>>5n-6n);"
expect_stdout: "42n"
node_version: ">=10"
node_version: ">=10.4.0"
}
minus_dot: {
@@ -13,7 +13,7 @@ minus_dot: {
}
expect_exact: "console.log(typeof-42n.toString(),typeof(-42n).toString());"
expect_stdout: "number string"
node_version: ">=10"
node_version: ">=10.4.0"
}
evaluate: {
@@ -28,7 +28,7 @@ evaluate: {
console.log(0xdeadbeefn.toString(16));
}
expect_stdout: "deadbeef"
node_version: ">=10"
node_version: ">=10.4.0"
}
Number: {
@@ -42,7 +42,7 @@ Number: {
console.log(+("" + -0xfeed_dead_beef_badn));
}
expect_stdout: "-1148098955808013200"
node_version: ">=10"
node_version: ">=10.4.0"
}
issue_4590: {
@@ -58,7 +58,7 @@ issue_4590: {
0n || console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=10"
node_version: ">=10.4.0"
}
issue_4801: {
@@ -88,5 +88,5 @@ issue_4801: {
}
}
expect_stdout: "PASS"
node_version: ">=10"
node_version: ">=10.4.0"
}

View File

@@ -427,6 +427,44 @@ negated_if: {
expect_stdout: "PASS"
}
concat_truthy: {
options = {
booleans: true,
evaluate: true,
}
input: {
console.log("foo") + (console.log("bar"), "baz") || console.log("moo");
}
expect: {
console.log("foo") + (console.log("bar"), "baz");
}
expect_stdout: [
"foo",
"bar",
]
expect_warnings: [
"WARN: + in boolean context always true [test/compress/booleans.js:1,8]",
"WARN: Condition left of || always true [test/compress/booleans.js:1,8]",
]
}
process_returns: {
options = {
booleans: true,
}
input: {
(function() {
return 42;
})() && console.log("PASS");
}
expect: {
(function() {
return 42;
})() && console.log("PASS");
}
expect_stdout: "PASS"
}
issue_3465_1: {
options = {
booleans: true,
@@ -697,3 +735,54 @@ issue_5041_2: {
}
expect_stdout: "PASS"
}
issue_5228: {
options = {
booleans: true,
evaluate: true,
inline: true,
passes: 2,
}
input: {
console.log(function() {
return !function() {
do {
return null;
} while (console);
}();
}());
}
expect: {
console.log(function() {
do {
return !0;
} while (console);
return !0;
}());
}
expect_stdout: "true"
}
issue_5469: {
options = {
assignments: true,
booleans: true,
conditionals: true,
dead_code: true,
evaluate: true,
pure_getters: "strict",
side_effects: true,
}
input: {
console.log(function f(a) {
a && 42[a = A && null];
}());
}
expect: {
console.log(function f(a) {
a && A,
0;
}());
}
expect_stdout: "undefined"
}

File diff suppressed because it is too large Load Diff

View File

@@ -346,9 +346,7 @@ collapse_vars_if: {
return "x" != "Bar" + x / 4 ? g9 : g5;
}
function f3(x) {
if (x)
return 1;
return 2;
return x ? 1 : 2;
}
}
}
@@ -1912,6 +1910,42 @@ collapse_vars_regexp: {
]
}
collapse_arg_sequence: {
options = {
collapse_vars: true,
unused: true,
}
input: {
(function(a) {
a("foo");
})((console.log("bar"), console.log));
}
expect: {
(function(a) {
(0, console.log)("foo");
})(console.log("bar"));
}
expect_stdout: [
"bar",
"foo",
]
}
collapse_for_init: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
for (var a = (Math, console), b = a.log("PASS"); b;);
}
expect: {
Math;
for (var a, b = console.log("PASS"); b;);
}
expect_stdout: "PASS"
}
issue_1537: {
options = {
collapse_vars: true,
@@ -2545,7 +2579,7 @@ side_effects_property: {
expect_stdout: true
}
undeclared: {
undeclared_1: {
options = {
collapse_vars: true,
unused: true,
@@ -2560,8 +2594,68 @@ undeclared: {
}
expect: {
function f(x, y) {
return (b = y) + x;
}
}
}
undeclared_2: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f(x, y) {
var a;
a = x;
b = y;
return b + x;
return a + b;
}
}
expect: {
function f(x, y) {
return x + (b = y);
}
}
}
undeclared_3: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f(x, y) {
var a;
a = x;
b = y;
return b + a();
}
}
expect: {
function f(x, y) {
return (b = y) + x();
}
}
}
undeclared_4: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f(x, y) {
var a;
a = x;
b = y;
return a() + b;
}
}
expect: {
function f(x, y) {
b = y;
return x() + b;
}
}
}
@@ -2667,6 +2761,24 @@ chained_4: {
expect_stdout: "foo undefined"
}
chained_5: {
options = {
collapse_vars: true,
}
input: {
var a = "PASS";
var a = (console, console.log(a));
a && ++a;
}
expect: {
var a = "PASS";
console;
var a;
(a = console.log(a)) && ++a;
}
expect_stdout: "PASS"
}
boolean_binary_1: {
options = {
collapse_vars: true,
@@ -2906,6 +3018,127 @@ compound_assignment_2: {
expect_stdout: "4"
}
compound_assignment_3: {
options = {
collapse_vars: true,
}
input: {
var a = 1;
a += (console.log("PASS"), 2);
a.p;
}
expect: {
var a = 1;
(a += (console.log("PASS"), 2)).p;
}
expect_stdout: "PASS"
}
compound_assignment_4: {
options = {
collapse_vars: true,
evaluate: true,
}
input: {
A = "PASS";
var a = "";
a += (a = "FAIL", A);
a.p;
console.log(a);
}
expect: {
var a = "";
(a += (a = "FAIL", A = "PASS")).p;
console.log(a);
}
expect_stdout: "PASS"
}
compound_assignment_5: {
options = {
collapse_vars: true,
}
input: {
var a = 0, b;
a += 42;
b && (a *= null);
console.log(a);
}
expect: {
var a = 0, b;
a += 42;
b && (a *= null);
console.log(a);
}
expect_stdout: "42"
}
compound_assignment_6: {
options = {
collapse_vars: true,
}
input: {
var a;
a ^= 6;
a *= a + 1;
console.log(a);
}
expect: {
var a;
a = (a ^= 6) * (a + 1);
console.log(a);
}
expect_stdout: "42"
}
compound_assignment_7: {
options = {
assignments: true,
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = "FA";
a = a + "I";
a = a + "L";
if (console)
a = "PASS";
console.log(a);
}
expect: {
var a = "FA";
a = a + "I" + "L";
if (console)
a = "PASS";
console.log(a);
}
expect_stdout: "PASS"
}
compound_assignment_8: {
options = {
assignments: true,
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 2;
a = 3 * a;
a = 7 * a;
console || (a = "FAIL");
console.log(a);
}
expect: {
var a = 2;
a = a * 3 * 7;
console || (a = "FAIL");
console.log(a);
}
expect_stdout: "42"
}
issue_2187_1: {
options = {
collapse_vars: true,
@@ -3030,10 +3263,10 @@ issue_2203_2: {
a: "FAIL",
b: function() {
return function(c) {
return (String, (Object, function() {
return (Object, function() {
return this;
}())).a;
}();
}()).a;
}(String);
}
}.b());
}
@@ -3731,6 +3964,7 @@ issue_2437_1: {
options = {
collapse_vars: true,
conditionals: true,
if_return: true,
inline: true,
join_vars: true,
passes: 2,
@@ -3763,17 +3997,17 @@ issue_2437_1: {
console.log(foo());
}
expect: {
console.log(function() {
if (xhrDesc) {
var result = !!(req = new XMLHttpRequest()).onreadystatechange;
return Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
result;
}
var req = new XMLHttpRequest(), detectFunc = function(){};
return req.onreadystatechange = detectFunc,
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc,
req.onreadystatechange = null, result;
}());
var req, detectFunc, result;
console.log((
xhrDesc ? (result = !!(req = new XMLHttpRequest).onreadystatechange,
Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc||{})
) : (
(req = new XMLHttpRequest).onreadystatechange = detectFunc = function(){},
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc,
req.onreadystatechange = null
),
result
));
}
}
@@ -3783,6 +4017,7 @@ issue_2437_2: {
conditionals: true,
inline: true,
join_vars: true,
negate_iife: true,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
@@ -3813,15 +4048,15 @@ issue_2437_2: {
foo();
}
expect: {
!function() {
if (xhrDesc)
return (req = new XMLHttpRequest()).onreadystatechange,
Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {});
var req = new XMLHttpRequest();
req.onreadystatechange = function(){},
var req;
xhrDesc ? (
(req = new XMLHttpRequest).onreadystatechange,
Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {})
) : (
(req = new XMLHttpRequest).onreadystatechange = function(){},
req[SYMBOL_FAKE_ONREADYSTATECHANGE_1],
req.onreadystatechange = null;
}();
req.onreadystatechange = null
);
}
}
@@ -6443,7 +6678,8 @@ assign_undeclared: {
console.log(typeof B);
}
expect: {
B = new (console.log(42), function() {})();
console.log(42);
B = new function() {}();
console.log(typeof B);
}
expect_stdout: [
@@ -8156,9 +8392,9 @@ issue_3884_1: {
console.log(a, b);
}
expect: {
var a = 100, b = 1;
b <<= ++a;
console.log(a, b);
var a = 100;
++a;
console.log(a, 32);
}
expect_stdout: "101 32"
}
@@ -8778,6 +9014,27 @@ collapse_and_assign: {
expect_stdout: "PASS"
}
collapse_and_assign_property: {
options = {
collapse_vars: true,
pure_getters: "strict",
reduce_vars: true,
unused: true,
}
input: {
console.log(function f() {
f && (f.p = "PASS");
return f.p;
}());
}
expect: {
console.log(function f() {
return f.p = f ? "PASS" : f.p;
}());
}
expect_stdout: "PASS"
}
collapse_or_assign: {
options = {
collapse_vars: true,
@@ -8795,7 +9052,7 @@ collapse_or_assign: {
var a = {
p: "PASS",
};
log(a = !a.q ? a.p : a);
log(a = a.q ? a: a.p);
}
expect_stdout: "PASS"
}
@@ -9064,12 +9321,11 @@ issue_4874: {
})(a = 42);
}
expect: {
var a;
null;
(function(b) {
for (var c in a && a[console.log("PASS")])
for (var c in 42, 42[console.log("PASS")])
console;
})(a = 42);
})();
}
expect_stdout: "PASS"
}
@@ -9139,9 +9395,7 @@ issue_4908: {
console.log(d[1]);
}
expect: {
var a = 0, b;
console || a++;
var c = a, d = [ (d = a) && d, d += 42 ];
var a = 0, b, c = (console || a++, a), d = [ (d = a) && d, d += 42 ];
console.log(d[1]);
}
expect_stdout: "42"
@@ -9253,13 +9507,13 @@ issue_4920_2: {
console.log(b);
}
expect: {
var o = {
var o;
var a = "PASS", b;
({
get PASS() {
a = "FAIL";
},
};
var a = "PASS", b;
o[b = a];
})[b = a];
console.log(b);
}
expect_stdout: "PASS"
@@ -9283,16 +9537,47 @@ issue_4920_3: {
}
expect: {
var log = console.log;
var o = {
var o;
var a = "PASS", b;
({
get PASS() {
a = "FAIL";
},
})[b = a];
log(b);
}
expect_stdout: "PASS"
}
issue_4920_4: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var o = {
get [(a = "FAIL 1", "PASS")]() {
a = "FAIL 2";
},
};
var a = "PASS", b;
o[b = a];
log(b);
}
expect: {
var log = console.log;
var o = {
get [(a = "FAIL 1", "PASS")]() {
a = "FAIL 2";
},
};
var a = "PASS", b;
o[b = a];
log(b);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4935: {
@@ -9343,9 +9628,8 @@ inline_throw: {
expect: {
try {
(function(a) {
return function() {
throw a;
}();
throw a;
return;
})("PASS");
} catch (e) {
console.log(e);
@@ -9482,3 +9766,358 @@ issue_5112_2: {
}
expect_stdout: "PASS"
}
issue_5182: {
options = {
arrows: true,
collapse_vars: true,
evaluate: true,
hoist_props: true,
inline: true,
merge_vars: true,
passes: 4,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var con = console;
global.log = con.log;
var jump = function(x) {
console.log("JUMP:", x * 10);
return x + x;
};
var jump2 = jump;
var run = function(x) {
console.log("RUN:", x * -10);
return x * x;
};
var run2 = run;
var bar = (x, y) => {
console.log("BAR:", x + y);
return x - y;
};
var bar2 = bar;
var obj = {
foo: bar2,
go: run2,
not_used: jump2,
};
console.log(obj.foo(1, 2), global.log("PASS"));
}
expect: {
var con = console;
global.log = con.log,
console.log((console.log("BAR:", 3), -1), global.log("PASS"));
}
expect_stdout: [
"BAR: 3",
"PASS",
"-1 undefined",
]
node_version: ">=4"
}
issue_5273: {
options = {
collapse_vars: true,
evaluate: true,
inline: true,
reduce_vars: true,
sequences: true,
toplevel: true,
}
input: {
var a = "10", b = 1;
function f(c, d) {
return d;
}
f((b += a, b *= a), f);
console.log(b);
}
expect: {
var a = "10", b = 1;
function f(c, d) {
return d;
}
b = 1100,
f,
console.log(b);
}
expect_stdout: "1100"
}
issue_5276: {
options = {
collapse_vars: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
}
input: {
var a = A = "PASS";
a.p += null;
a.p -= 42;
console.log(a);
}
expect: {
var a = A = "PASS";
a.p = a.p + null - 42;
console.log(a);
}
expect_stdout: "PASS"
}
issue_5277: {
options = {
collapse_vars: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function() {
var a = function() {
a += null;
a -= 42;
};
}());
}
expect: {
console.log(function() {}());
}
expect_stdout: "undefined"
}
issue_5309_1: {
options = {
collapse_vars: true,
conditionals: true,
toplevel: true,
}
input: {
if (console)
var a = (console.log("PASS"), b), b = a;
else
console.log("FAIL");
}
expect: {
var a, b;
console ? (console.log("PASS"), b = b) : console.log("FAIL");
}
expect_stdout: "PASS"
}
issue_5309_2: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var a, b;
console ? (a = (console.log("PASS"), b), b = a) : console.log("FAIL");
}
expect: {
var a, b;
console ? (console.log("PASS"), b = b) : console.log("FAIL");
}
expect_stdout: "PASS"
}
issue_5394: {
options = {
collapse_vars: true,
evaluate: true,
}
input: {
try {
throw A.p = (console.log("FAIL"), []), !1;
} catch (e) {
console.log(typeof e);
}
}
expect: {
try {
throw !(A.p = (console.log("FAIL"), []));
} catch (e) {
console.log(typeof e);
}
}
expect_stdout: "object"
}
issue_5396: {
options = {
collapse_vars: true,
merge_vars: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
var a, b;
function f() {}
b = 0;
new function g(c) {
var d = a && g(e), e = ++d, i = [ 42 ];
for (var j in i)
console.log("PASS"),
i;
}();
}
expect: {
var a, b;
function f() {}
b = 0;
(function g(c) {
a && g();
for (var j in [ 42 ])
console.log("PASS");
})();
}
expect_stdout: "PASS"
}
issue_5568: {
options = {
collapse_vars: true,
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
A = "FAIL";
var a = (A = "PASS", !1);
for (var b in a);
console.log(A);
}
expect: {
A = "FAIL";
for (var b in !(A = "PASS"));
console.log(A);
}
expect_stdout: "PASS"
}
issue_5638_1: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a;
console;
a = [ 42 ];
console || FAIL(a);
console.log(a++);
}
expect: {
var a;
console;
a = [ 42 ];
console || FAIL(a);
console.log(a++);
}
expect_stdout: "42"
}
issue_5638_2: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a;
console;
a = [ 6 ];
console || FAIL(a);
console.log(a *= 7);
}
expect: {
var a;
console;
a = [ 6 ];
console || FAIL(a);
console.log(a *= 7);
}
expect_stdout: "42"
}
issue_5638_3: {
options = {
collapse_vars: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var a = { foo: 42 }, b;
for (var k in a) {
b = a[k];
log(k || b, b++);
}
}
expect: {
var log = console.log;
var a = { foo: 42 }, b;
for (var k in a) {
b = a[k];
log(k || b, b++);
}
}
expect_stdout: "foo 42"
}
issue_5638_4: {
options = {
collapse_vars: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var a = { foo: 6 }, b;
for (var k in a) {
b = a[k];
log(k || b, b *= 7);
}
}
expect: {
var log = console.log;
var a = { foo: 6 }, b;
for (var k in a) {
b = a[k];
log(k || b, b *= 7);
}
}
expect_stdout: "foo 42"
}
issue_5643: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 3, b;
a *= 7;
b = !!this;
console || console.log(b);
console.log(a * ++b);
}
expect: {
var a = 3, b;
a *= 7;
b = !!this;
console || console.log(b);
console.log(a * ++b);
}
expect_stdout: "42"
}

View File

@@ -40,6 +40,22 @@ unsafe_comps: {
}
}
unsafe_in_instanceof: {
options = {
side_effects: true,
unsafe_comps: true,
}
input: {
var a;
42 in a;
f() instanceof "foo";
}
expect: {
var a;
f();
}
}
dont_change_in_or_instanceof_expressions: {
input: {
1 in 1;
@@ -489,7 +505,36 @@ issue_3413: {
}
expect: {
var b;
void 0 !== ("" < b || void 0) || console.log("PASS");
void 0 === ("" < b || void 0) && console.log("PASS");
}
expect_stdout: "PASS"
}
nullish_assign: {
options = {
comparisons: true,
}
input: {
var a;
void 0 !== (a = "PASS".split("")) && null !== a && console.log(a.join("-"));
}
expect: {
var a;
null != (a = "PASS".split("")) && console.log(a.join("-"));
}
expect_stdout: "P-A-S-S"
}
nullish_chain: {
options = {
comparisons: true,
}
input: {
var a;
A || B || void 0 === a || null === a || C;
}
expect: {
var a;
A || B || null == a || C;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -142,6 +142,80 @@ if_dead_branch: {
expect_stdout: "undefined"
}
retain_tail_1: {
options = {
conditionals: true,
}
input: {
function f(a) {
var b = "foo";
if (a) {
const b = "bar";
while (console.log("baz"));
console.log(b);
} else {
while (console.log("moo"));
console.log(b);
}
}
f();
f(42);
}
expect: {
function f(a) {
var b = "foo";
if (a) {
const b = "bar";
while (console.log("baz"));
console.log(b);
} else {
while (console.log("moo"));
console.log(b);
}
}
f();
f(42);
}
expect_stdout: true
}
retain_tail_2: {
options = {
conditionals: true,
}
input: {
function f(a) {
var b = "foo";
if (a) {
while (console.log("bar"));
console.log(b);
} else {
const b = "baz";
while (console.log("moo"));
console.log(b);
}
}
f();
f(42);
}
expect: {
function f(a) {
var b = "foo";
if (a) {
while (console.log("bar"));
console.log(b);
} else {
const b = "baz";
while (console.log("moo"));
console.log(b);
}
}
f();
f(42);
}
expect_stdout: true
}
merge_vars_1: {
options = {
merge_vars: true,
@@ -220,6 +294,32 @@ merge_vars_3: {
expect_stdout: true
}
merge_vars_4: {
options = {
merge_vars: true,
toplevel: true,
}
input: {
var a = 1;
console.log(typeof a);
{
var b = console;
console.log(typeof b);
const a = 0;
}
}
expect: {
var a = 1;
console.log(typeof a);
{
var b = console;
console.log(typeof b);
const a = 0;
}
}
expect_stdout: true
}
use_before_init_1: {
options = {
reduce_vars: true,
@@ -553,6 +653,37 @@ dead_block_after_return: {
expect_stdout: true
}
if_return_3: {
options = {
if_return: true,
}
input: {
var a = "PASS";
function f(b) {
if (console) {
const b = a;
return b;
} else
while (console.log("FAIL 1"));
return b;
}
console.log(f("FAIL 2"));
}
expect: {
var a = "PASS";
function f(b) {
if (console) {
const b = a;
return b;
} else
while (console.log("FAIL 1"));
return b;
}
console.log(f("FAIL 2"));
}
expect_stdout: true
}
do_if_continue_1: {
options = {
if_return: true,
@@ -571,8 +702,7 @@ do_if_continue_1: {
}
expect: {
do {
if (!console);
else {
if (console) {
console.log("PASS");
{
const a = 0;
@@ -602,8 +732,7 @@ do_if_continue_2: {
}
expect: {
do {
if (!console);
else {
if (console) {
console.log("PASS");
{
const a = 0;
@@ -838,12 +967,10 @@ issue_4202: {
expect: {
{
const o = {};
(function() {
function f() {
o.p = 42;
}
f(f);
})();
function f() {
o.p = 42;
}
f(f);
console.log(o.p++);
}
}
@@ -1219,9 +1346,9 @@ issue_4248: {
expect_stdout: "PASS"
}
issue_4261: {
issue_4261_1: {
options = {
inline: true,
inline: 3,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
@@ -1259,6 +1386,43 @@ issue_4261: {
expect_stdout: "42"
}
issue_4261_2: {
options = {
if_return: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
{
const a = 42;
(function() {
function f() {
console.log(a);
}
function g() {
while (f());
}
(function() {
while (g());
})();
})();
}
}
expect: {
{
const a = 42;
function g() {
while (void console.log(a));
}
while (g());
}
}
expect_stdout: "42"
}
issue_4274_1: {
options = {
loops: true,
@@ -1457,6 +1621,7 @@ issue_4689: {
issue_4691: {
options = {
conditionals: true,
if_return: true,
toplevel: true,
}
@@ -1692,3 +1857,350 @@ issue_4965_2: {
expect_stdout: "undefined"
node_version: ">=4"
}
issue_5254: {
options = {
inline: true,
toplevel: true,
}
input: {
do {
(function() {
const a = console.log;
a && a("foo");
})();
} while (console.log("bar"));
}
expect: {
do {
const a = console.log;
a && a("foo");
} while (console.log("bar"));
}
expect_stdout: [
"foo",
"bar",
]
}
issue_5260: {
options = {
collapse_vars: true,
}
input: {
"use strict";
var a = "foo", o;
while (console.log("bar"));
o = {
baz: function(b) {
console.log(a, b);
},
};
for (const a in o)
o[a](a);
}
expect: {
"use strict";
var a = "foo", o;
while (console.log("bar"));
o = {
baz: function(b) {
console.log(a, b);
},
};
for (const a in o)
o[a](a);
}
expect_stdout: [
"bar",
"foo baz",
]
node_version: ">=4"
}
issue_5319: {
options = {
collapse_vars: true,
merge_vars: true,
}
input: {
(function(a, c) {
var b = a, c = b;
{
const a = c;
console.log(c());
}
})(function() {
return "PASS";
});
}
expect: {
(function(a, c) {
var b = a, c;
{
const a = c = b;
console.log(c());
}
})(function() {
return "PASS";
});
}
expect_stdout: true
}
issue_5338: {
options = {
unused: true,
}
input: {
const a = a;
}
expect: {
const a = a;
}
expect_stdout: true
}
issue_5476: {
mangle = {
keep_fargs: true,
}
input: {
console.log(function(n) {
const a = 42;
}());
}
expect: {
console.log(function(n) {
const o = 42;
}());
}
expect_stdout: "undefined"
}
issue_5516: {
options = {
inline: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(typeof function() {
try {} catch (a) {
(function f() {
a;
})();
}
{
const a = function() {};
return a;
}
}());
}
expect: {
console.log(typeof function() {
try {} catch (a) {
void a;
}
{
const a = function() {};
return a;
}
}());
}
expect_stdout: "function"
}
issue_5580_1: {
mangle = {}
input: {
"use strict";
console.log(function(a, b, c) {
try {
FAIL;
} catch (e) {
return function() {
var d = e, i, j;
{
const e = j;
}
return a;
}();
} finally {
const e = 42;
}
}("PASS"));
}
expect: {
"use strict";
console.log(function(r, n, t) {
try {
FAIL;
} catch (o) {
return function() {
var n = o, t, c;
{
const o = c;
}
return r;
}();
} finally {
const c = 42;
}
}("PASS"));
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5580_2: {
options = {
inline: true,
reduce_vars: true,
varify: true,
}
input: {
"use strict";
(function() {
try {
throw "PASS";
} catch (e) {
return function() {
console.log(e);
{
const e = "FAIL 1";
}
}();
} finally {
const e = "FAIL 2";
}
})();
}
expect: {
"use strict";
(function() {
try {
throw "PASS";
} catch (e) {
console.log(e);
{
const e = "FAIL 1";
}
return;
} finally {
var e = "FAIL 2";
}
})();
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5591: {
options = {
dead_code: true,
if_return: true,
}
input: {
"use strict";
function f(a) {
switch (console.log("foo")) {
case console.log("bar"):
if (console.log("baz"))
return;
else {
const a = 42;
return;
}
break;
case null:
FAIL;
}
}
f();
}
expect: {
"use strict";
function f(a) {
switch (console.log("foo")) {
case console.log("bar"):
if (console.log("baz"))
return;
else {
const a = 42;
return;
}
case null:
FAIL;
}
}
f();
}
expect_stdout: [
"foo",
"bar",
"baz",
]
node_version: ">=4"
}
issue_5656: {
options = {
collapse_vars: true,
merge_vars: true,
}
input: {
console.log(function(a) {
var b = a;
b++;
{
const a = b;
}
}());
}
expect: {
console.log(function(a) {
var b = a;
{
const a = ++b;
}
}());
}
expect_stdout: true
}
issue_5660: {
options = {
merge_vars: true,
side_effects: true,
}
input: {
function f() {
try {
a;
var b;
return b;
} catch (e) {
var a = "FAIL";
const b = null;
return a;
}
}
console.log(f());
}
expect: {
function f() {
try {
var b;
return b;
} catch (e) {
var a = "FAIL";
const b = null;
return a;
}
}
console.log(f());
}
expect_stdout: true
}

View File

@@ -1485,8 +1485,6 @@ self_assignments_5: {
}
expect: {
var i = 0, l = [ "FAIL", "PASS" ];
l[0];
l[0];
l[0] = l[1];
console.log(l[0], 2);
}
@@ -1669,3 +1667,66 @@ issue_5106_2: {
}
expect_stdout: "PASS"
}
issue_5506: {
options = {
dead_code: true,
}
input: {
try {
(function(a) {
var b = 1;
(function f() {
try {
b-- && f();
} catch (c) {}
console.log(a);
a = 42 in (a = "bar");
})();
})("foo");
} catch (e) {}
}
expect: {
try {
(function(a) {
var b = 1;
(function f() {
try {
b-- && f();
} catch (c) {}
console.log(a);
a = 42 in (a = "bar");
})();
})("foo");
} catch (e) {}
}
expect_stdout: [
"foo",
"bar",
]
}
issue_5641: {
options = {
collapse_vars: true,
conditionals: true,
dead_code: true,
}
input: {
function f(a) {
if (a || b) {
var b = "PASS", c = b && console.log(b);
} else
var d = a || b;
}
f(42);
}
expect: {
function f(a) {
var b, c, d;
(a || b) && (b = "PASS") && console.log(b);
}
f(42);
}
expect_stdout: "PASS"
}

File diff suppressed because it is too large Load Diff

View File

@@ -220,7 +220,7 @@ funarg_side_effects_2: {
}
}
expect_stdout: "PASS"
node_version: ">=6"
node_version: ">=6.9.2"
}
funarg_side_effects_3: {
@@ -254,7 +254,7 @@ funarg_side_effects_3: {
}
}
expect_stdout: "PASS"
node_version: ">=6"
node_version: ">=6.9.2"
}
funarg_unused_1: {
@@ -395,7 +395,8 @@ funarg_unused_6_keep_fargs: {
}
expect: {
(function() {
var {} = (console, 42);
console;
var {} = 42;
})();
console.log(typeof a);
}
@@ -471,6 +472,93 @@ funarg_collapse_vars_3: {
node_version: ">=6"
}
funarg_collapse_vars_4: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var a = "PASS";
(function(b, { log: c }) {
c(b);
})(a, console);
}
expect: {
var a = "PASS";
(function(b, { log: c }) {
c(a);
})(0, console);
}
expect_stdout: "PASS"
node_version: ">=6"
}
funarg_collapse_vars_5: {
options = {
collapse_vars: true,
unused: true,
}
input: {
A = "FAIL";
B = "PASS";
try {
console.log(function({}, a) {
return a;
}(null, A = B));
} catch (e) {}
console.log(A);
}
expect: {
A = "FAIL";
B = "PASS";
try {
console.log(function({}, a) {
return a;
}(null, A = B));
} catch (e) {}
console.log(A);
}
expect_stdout: "PASS"
node_version: ">=6"
}
funarg_collapse_vars_6: {
options = {
collapse_vars: true,
unused: true,
}
input: {
A = "FAIL";
B = "PASS";
function f() {
console.log(function({}, a) {
return a;
}(null, A = B));
}
try {
f();
} catch (e) {
console.log(A);
}
}
expect: {
A = "FAIL";
B = "PASS";
function f() {
console.log(function({}, a) {
return a;
}(null, A = B));
}
try {
f();
} catch (e) {
console.log(A);
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
funarg_reduce_vars_1: {
options = {
reduce_vars: true,
@@ -691,7 +779,7 @@ funarg_inline: {
node_version: ">=6"
}
process_boolean_returns: {
process_returns: {
options = {
booleans: true,
}
@@ -705,9 +793,7 @@ process_boolean_returns: {
expect: {
console.log(function({ length }) {
return length ? "FAIL" : "PASS";
}(function() {
return 42;
}));
}(function() {}));
}
expect_stdout: "PASS"
node_version: ">=6"
@@ -1129,7 +1215,7 @@ drop_unused_2: {
}
f();
}
expect:{
expect: {
(function(a) {
console.log("PASS");
})();
@@ -1220,7 +1306,7 @@ keep_reference: {
}
expect: {
var a = [ {}, 42 ];
var [ b ] = a;
var b = a[0];
console.log(a[0] === b ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
@@ -1566,6 +1652,8 @@ fn_name_unused: {
hoist_vars: {
options = {
hoist_vars: true,
join_vars: true,
unused: true,
}
input: {
var a = "PASS";
@@ -1573,14 +1661,82 @@ hoist_vars: {
console.log(a, b);
}
expect: {
var a = "PASS";
var [ b ] = [ 42 ];
var a = "PASS", b = [ 42 ][0];
console.log(a, b);
}
expect_stdout: "PASS 42"
node_version: ">=6"
}
singleton_1: {
options = {
pure_getters: true,
side_effects: true,
unused: true,
}
input: {
var [ a ] = "P", b, o = {};
[ { 1: o.p } ] = [ "FAIL" ];
({ foo: [ o.q ] } = { foo: "S" });
[ b = "S" ] = [];
console.log(a + o.p + o.q + b);
}
expect: {
var b, a = "P"[0], o = {};
o.p = [ "FAIL"["1"] ][0];
o.q = { foo: "S"[0] }["foo"];
[ b = "S" ] = [];
console.log(a + o.p + o.q + b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
singleton_2: {
options = {
evaluate: true,
passes: 2,
pure_getters: true,
side_effects: true,
unsafe: true,
unused: true,
}
input: {
var [ a ] = "P", b, o = {};
[ { 1: o.p } ] = [ "FAIL" ];
({ foo: [ o.q ] } = { foo: "S" });
[ b = "S" ] = [];
console.log(a + o.p + o.q + b);
}
expect: {
var b, a = "P", o = {};
o.p = "A";
o.q = "S";
[ b = "S" ] = [];
console.log(a + o.p + o.q + b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
singleton_side_effects: {
options = {
side_effects: true,
unused: true,
}
input: {
[ 42[console.log("foo")] ] = [ console.log("bar") ];
}
expect: {
[ 42[console.log("foo")] ] = [ console.log("bar") ];
}
expect_stdout: [
"bar",
"foo",
]
node_version: ">=6"
}
issue_4280: {
options = {
evaluate: true,
@@ -1747,8 +1903,8 @@ issue_4288: {
console.log(typeof b);
}()]: a,
}) {
var b = a;
b++;
var a = a;
a++;
}
f(0);
}
@@ -1775,10 +1931,10 @@ issue_4294: {
expect: {
A = "PASS";
(function() {
var b = function({
[b]: {},
var a = function({
[a]: {},
}) {}({
[b]: 0,
[a]: 0,
});
var b = A;
console.log(b);
@@ -1921,17 +2077,16 @@ issue_4312: {
console.log(a);
}
expect: {
var a;
b = "PASS",
c = "FAIL",
[
{
[a = b]: d,
[c = b]: d,
},
] = [ c && c ],
void 0;
var b, c, d;
console.log(a);
console.log(c);
}
expect_stdout: "PASS"
node_version: ">=6"
@@ -2000,7 +2155,7 @@ issue_4319: {
issue_4321: {
options = {
inline: true,
inline: 3,
keep_fargs: false,
}
input: {
@@ -2952,6 +3107,7 @@ issue_5074_method_pure_getters: {
issue_5085_1: {
options = {
evaluate: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unsafe: true,
@@ -2964,8 +3120,7 @@ issue_5085_1: {
}
expect: {
var a = "PASS";
var b = [ 42 ][0];
b;
42;
console.log(a);
}
expect_stdout: "PASS"
@@ -2975,6 +3130,7 @@ issue_5085_1: {
issue_5085_2: {
options = {
evaluate: true,
passes: 2,
reduce_vars: true,
side_effects: true,
unsafe: true,
@@ -2991,7 +3147,7 @@ issue_5085_2: {
expect: {
var a = "PASS";
(function(b) {
b = [ 42 ][0];
0;
})();
console.log(a);
}
@@ -3225,3 +3381,491 @@ issue_5153_object_var: {
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5168: {
options = {
collapse_vars: true,
}
input: {
(function a({
[console.log(typeof function() {
++a;
return a;
}())]: b,
}) {
var a;
})({});
}
expect: {
(function a({
[console.log(typeof function() {
++a;
return a;
}())]: b,
}) {
var a;
})({});
}
expect_stdout: "function"
node_version: ">=6"
}
issue_5189_1: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = 42;
[ a.p ] = a = "PASS";
console.log(a);
}
expect: {
var a;
[ a.p ] = a = "PASS";
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5189_2: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = 42;
({ p: a.q } = a = "PASS");
console.log(a);
}
expect: {
var a;
({ p: a.q } = a = "PASS");
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5222: {
options = {
hoist_props: true,
inline: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function f() {
do {
(function() {
var a = {
p: [ a ] = [],
};
})();
} while (console.log("PASS"));
}
f();
}
expect: {
do {
a = void 0,
a = {
p: [ a ] = [],
};
} while (console.log("PASS"));
var a;
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5288_1: {
options = {
conditionals: true,
inline: true,
keep_fargs: false,
reduce_vars: true,
toplevel: true,
unused: true,
varify: true,
}
input: {
while (function([]) {}([ function f() {
if (console)
return console.log("PASS");
else {
let a = 0;
}
}() ]));
}
expect: {
while (function() {
if (console)
console.log("PASS");
}(), void 0);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5288_2: {
options = {
conditionals: true,
inline: true,
keep_fargs: false,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
varify: true,
}
input: {
while (function([]) {}([ function f() {
if (console)
return console.log("PASS");
else {
let a = 0;
}
}() ]));
}
expect: {
while (console && console.log("PASS"), void 0);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5314_1: {
options = {
side_effects: true,
}
input: {
A = this;
new function() {
(function({
[console.log(this === A ? "PASS" : "FAIL")]: a,
}) {})(42);
}();
}
expect: {
A = this;
(function() {
(function({
[console.log(this === A ? "PASS" : "FAIL")]: a,
}) {})(42);
})();
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5314_2: {
options = {
side_effects: true,
}
input: {
A = this;
new function() {
(({
[console.log(this === A ? "FAIL" : "PASS")]: a,
}) => {})(42);
}();
}
expect: {
A = this;
new function() {
[ {
[console.log(this === A ? "FAIL" : "PASS")]: [][0],
} ] = [ 42 ];
}();
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5370: {
options = {
dead_code: true,
ie: true,
unused: true,
}
input: {
console.log(function arguments({}) {
return arguments;
try {} catch (e) {
var arguments;
}
}(42));
}
expect: {
console.log(function arguments({}) {
return arguments;
var arguments;
}(42));
}
expect_stdout: true
node_version: ">=6"
}
issue_5405_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
}
input: {
var [ a ] = [ {} ];
console.log(a === a ? "PASS" : "FAIL");
}
expect: {
var [ a ] = [ {} ];
console.log(true ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5405_2: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
}
input: {
var { p: a } = { p: [] };
console.log(a === a ? "PASS" : "FAIL");
}
expect: {
var { p: a } = { p: [] };
console.log(true ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5423: {
options = {
merge_vars: true,
toplevel: true,
}
input: {
var a, b;
function f({
[function() {
if (++a)
return 42;
}()]: c
}) {}
f(b = f);
console.log(typeof b);
}
expect: {
var a, b;
function f({
[function() {
if (++a)
return 42;
}()]: c
}) {}
f(b = f);
console.log(typeof b);
}
expect_stdout: "function"
node_version: ">=6"
}
issue_5454: {
options = {
hoist_props: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function f(a) {
var a = 42, a = {
p: [ a ] = [],
};
return "PASS";
}
console.log(f());
}
expect: {
console.log(function(a) {
a = 42, a = {
p: [ a ] = [],
};
return "PASS";
}());
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5485: {
options = {
comparisons: true,
}
input: {
(function f({
p: f,
[console.log(void 0 === f ? "PASS" : "FAIL")]: a,
}) {})(42);
}
expect: {
(function f({
p: f,
[console.log(void 0 === f ? "PASS" : "FAIL")]: a,
}) {})(42);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5533_keep_fargs: {
options = {
evaluate: true,
inline: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
}
input: {
"use strict";
try {
(function() {
var a;
for (; 1;)
a = function() {
(function f([ b ]) {
b;
throw "PASS";
})([]);
}();
})();
} catch (e) {
console.log(e);
}
}
expect: {
"use strict";
try {
(function() {
for (;;)
throw "PASS";
})();
} catch (e) {
console.log(e);
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5533_drop_fargs: {
options = {
evaluate: true,
inline: true,
join_vars: true,
keep_fargs: false,
loops: true,
side_effects: true,
unused: true,
}
input: {
"use strict";
try {
(function() {
var a;
for (; 1;)
a = function() {
(function f([ b ]) {
b;
throw "PASS";
})([]);
}();
})();
} catch (e) {
console.log(e);
}
}
expect: {
"use strict";
try {
(function() {
for (;;)
throw "PASS";
})();
} catch (e) {
console.log(e);
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5573: {
options = {
collapse_vars: true,
}
input: {
var log = console.log;
var a = "FAIL";
(function([ { [log(a)]: b } ]) {
A = 42;
})((a = "PASS", [ {} ]));
log(a, A);
}
expect: {
var log = console.log;
var a = "FAIL";
(function([ { [log(a)]: b } ]) {
A = 42;
})((a = "PASS", [ {} ]));
log(a, A);
}
expect_stdout: [
"PASS",
"PASS 42",
]
node_version: ">=6"
}
issue_5651: {
options = {
ie: true,
unused: true,
}
input: {
console.log(function arguments({}) {
try {} catch (arguments) {
var arguments;
}
return arguments[0];
}("PASS"));
}
expect: {
console.log(function arguments({}) {
try {} catch (arguments) {
var arguments;
}
return arguments[0];
}("PASS"));
}
expect_stdout: true
node_version: ">=6"
}

View File

@@ -129,3 +129,47 @@ valid_after_invalid_2: {
}
expect_stdout: "undefined"
}
issue_5368_1: {
expression = true
options = {
directives: true,
expression: true,
}
input: {
"foo"
}
expect_exact: '"foo"'
expect_stdout: "foo"
}
issue_5368_2: {
expression = true
options = {
directives: true,
expression: true,
}
input: {
(function() {
"foo";
})()
}
expect_exact: "function(){}()"
expect_stdout: "undefined"
}
issue_5368_3: {
options = {
directives: true,
expression: true,
}
input: {
"foo";
(function() {
"bar";
})();
}
expect: {
(function() {})();
}
}

View File

@@ -409,6 +409,15 @@ drop_toplevel_retain: {
a = 2;
console.log(3);
}
expect_stdout: "3"
expect_warnings: [
"INFO: Retaining variable a",
"INFO: Retaining variable f",
"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]",
"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]",
"INFO: Dropping unused function g [test/compress/drop-unused.js:8,17]",
"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]",
]
}
drop_toplevel_retain_array: {
@@ -442,6 +451,15 @@ drop_toplevel_retain_array: {
a = 2;
console.log(3);
}
expect_stdout: "3"
expect_warnings: [
"INFO: Retaining variable a",
"INFO: Retaining variable f",
"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]",
"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]",
"INFO: Dropping unused function g [test/compress/drop-unused.js:8,17]",
"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]",
]
}
drop_toplevel_retain_regex: {
@@ -471,6 +489,15 @@ drop_toplevel_retain_regex: {
a = 2;
console.log(3);
}
expect_stdout: "3"
expect_warnings: [
"INFO: Retaining variable a",
"INFO: Retaining variable f",
"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]",
"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]",
"INFO: Dropping unused function g [test/compress/drop-unused.js:8,17]",
"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]",
]
}
drop_toplevel_all_retain: {
@@ -501,6 +528,15 @@ drop_toplevel_all_retain: {
a = 2;
console.log(3);
}
expect_stdout: "3"
expect_warnings: [
"INFO: Retaining variable a",
"INFO: Retaining variable f",
"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]",
"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]",
"INFO: Dropping unused function g [test/compress/drop-unused.js:8,17]",
"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]",
]
}
drop_toplevel_funcs_retain: {
@@ -532,6 +568,12 @@ drop_toplevel_funcs_retain: {
function g() {}
console.log(b = 3);
}
expect_stdout: "3"
expect_warnings: [
"INFO: Retaining variable a",
"INFO: Retaining variable f",
"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]",
]
}
drop_toplevel_vars_retain: {
@@ -564,6 +606,13 @@ drop_toplevel_vars_retain: {
function h() {}
console.log(3);
}
expect_stdout: "3"
expect_warnings: [
"INFO: Retaining variable a",
"INFO: Retaining variable f",
"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]",
"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]",
]
}
drop_toplevel_keep_assign: {
@@ -671,6 +720,76 @@ iife: {
}
}
drop_instanceof: {
options = {
booleans: true,
toplevel: true,
unused: true,
}
input: {
function f() {}
console.log({} instanceof f, Math instanceof f);
}
expect: {
console.log(!1, (Math, !1));
}
expect_stdout: "false false"
}
keep_instanceof_1: {
options = {
toplevel: true,
unused: true,
}
input: {
function f() {}
var f;
console.log({} instanceof f, Math instanceof f);
}
expect: {
function f() {}
var f;
console.log({} instanceof f, Math instanceof f);
}
expect_stdout: "false false"
}
keep_instanceof_2: {
options = {
toplevel: true,
unused: true,
}
input: {
function f() {}
var f = Object;
console.log({} instanceof f, Math instanceof f);
}
expect: {
function f() {}
var f = Object;
console.log({} instanceof f, Math instanceof f);
}
expect_stdout: "true true"
}
keep_instanceof_3: {
options = {
toplevel: true,
unused: true,
}
input: {
f = Object;
function f() {}
console.log({} instanceof f, Math instanceof f);
}
expect: {
f = Object;
function f() {}
console.log({} instanceof f, Math instanceof f);
}
expect_stdout: "true true"
}
issue_1539: {
options = {
collapse_vars: true,
@@ -1233,8 +1352,11 @@ issue_2105_2: {
issue_2105_3: {
options = {
inline: true,
passes: 2,
join_vars: true,
passes: 3,
reduce_vars: true,
side_effects: true,
sequences: true,
unused: true,
}
input: {
@@ -1258,12 +1380,12 @@ issue_2105_3: {
});
}
expect: {
!void void {
({
prop: function() {
console.log;
void console.log("PASS");
}
}.prop();
console.log,
console.log("PASS");
},
}).prop();
}
expect_stdout: "PASS"
}
@@ -1728,7 +1850,8 @@ issue_2768: {
}
expect: {
var a = "FAIL";
var c = (d = a, void (d && (a = "PASS")));
d = a;
var c = void (d && (a = "PASS"));
var d;
console.log(a, typeof c);
}
@@ -1755,7 +1878,7 @@ issue_2846: {
var c = function(a, b) {
a = 0;
b && b(a);
return a++;
return +a;
}();
console.log(c);
}
@@ -1765,7 +1888,7 @@ issue_2846: {
issue_805_1: {
options = {
inline: true,
passes: 2,
passes: 3,
pure_getters: "strict",
reduce_vars: true,
sequences: true,
@@ -1798,7 +1921,7 @@ issue_805_1: {
issue_805_2: {
options = {
inline: true,
passes: 2,
passes: 3,
pure_getters: "strict",
reduce_vars: true,
sequences: true,
@@ -2382,7 +2505,8 @@ issue_3664: {
}
expect: {
console.log(function() {
var a, b = (a = (a = [ b && console.log("FAIL") ]).p = 0, 0);
a = (a = [ b && console.log("FAIL") ]).p = 0;
var a, b = 0;
return "PASS";
}());
}
@@ -2551,10 +2675,9 @@ issue_3899: {
console.log(typeof a);
}
expect: {
function a() {
console.log(typeof function() {
return 2;
}
console.log(typeof a);
});
}
expect_stdout: "function"
}
@@ -2652,7 +2775,7 @@ issue_3956: {
collapse_vars: true,
evaluate: true,
inline: true,
passes: 2,
passes: 3,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -2783,7 +2906,7 @@ issue_3986: {
expect_stdout: "0"
}
issue_4017: {
issue_4017_1: {
options = {
pure_getters: "strict",
reduce_vars: true,
@@ -2801,7 +2924,31 @@ issue_4017: {
var a = 0;
console.log(function() {
c &= 0;
var c;
var c = a++ + (A = a);
}());
}
expect_stdout: "undefined"
}
issue_4017_2: {
options = {
passes: 2,
pure_getters: "strict",
reduce_vars: true,
unused: true,
}
input: {
var a = 0;
console.log(function f() {
var b = c &= 0;
var c = a++ + (A = a);
var d = c && c[f];
}());
}
expect: {
var a = 0;
console.log(function() {
0;
a++,
A = a;
}());
@@ -2829,14 +2976,12 @@ issue_4025: {
console.log(a, b, d);
}
expect: {
var c = 0;
try {
console.log(c);
console.log(0);
} finally {
var d = c + 1;
c = 0;
0;
}
console.log(1, 1, d);
console.log(1, 1, 1);
}
expect_stdout: [
"0",
@@ -2916,7 +3061,7 @@ issue_4133: {
console.log(a);
}
expect: {
var b = 1;
var a = 1;
console.log(0);
}
expect_stdout: "0"
@@ -3062,7 +3207,7 @@ issue_4184: {
expect_stdout: "42"
}
issue_4235: {
issue_4235_1: {
options = {
inline: true,
reduce_vars: true,
@@ -3081,13 +3226,37 @@ issue_4235: {
}
expect: {
void function() {
var f;
console.log(f);
var f = console.log(f);
}();
}
expect_stdout: "undefined"
}
issue_4235_2: {
options = {
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
unused: true,
varify: true,
}
input: {
(function() {
{
const f = 0;
}
(function f() {
var f = console.log(f);
})();
})();
}
expect: {
console.log(void 0);
}
expect_stdout: "undefined"
}
issue_4404: {
options = {
pure_getters: "strict",
@@ -3220,7 +3389,7 @@ issue_4558_1: {
expect: {
var a = 0;
var b = c >>>= a;
var c;
var c = 0;
b && a++,
console.log(a);
}
@@ -3306,6 +3475,7 @@ issue_4806_1: {
issue_4806_2: {
options = {
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
@@ -3492,3 +3662,155 @@ issue_5079: {
}
expect_stdout: "PASS"
}
issue_5224: {
options = {
evaluate: true,
keep_fargs: false,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {
try {
var b = function() {
var a = "FAIL 1";
null && a;
a = console.log(a);
}(new function(c, d) {
console.log(d);
a;
}("FAIL 2", Infinity));
} finally {
return f;
}
}
f();
}
expect: {
(function f() {
try {
(function() {
var a = "FAIL 1";
null;
console.log(a);
})(function() {
console.log(1 / 0);
a;
}());
} finally {
return f;
}
})();
}
expect_stdout: "Infinity"
}
issue_5271: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {
do {
var a = b = 0 ^ f, b = b;
} while (console.log(42 - b));
}
f();
}
expect: {
(function f() {
do {
var b;
b = 0 ^ f;
} while (console.log(42 - b));
})();
}
expect_stdout: "42"
}
issue_5533_keep_fargs: {
options = {
evaluate: true,
inline: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
}
input: {
"use strict";
try {
(function() {
var a;
for (; 1;)
a = function() {
(function f(b) {
b;
throw "PASS";
})();
}();
})();
} catch (e) {
console.log(e);
}
}
expect: {
"use strict";
try {
(function() {
for (;;)
throw "PASS";
})();
} catch (e) {
console.log(e);
}
}
expect_stdout: "PASS"
}
issue_5533_drop_fargs: {
options = {
evaluate: true,
inline: true,
join_vars: true,
keep_fargs: false,
loops: true,
side_effects: true,
unused: true,
}
input: {
"use strict";
try {
(function() {
var a;
for (; 1;)
a = function() {
(function f(b) {
b;
throw "PASS";
})();
}();
})();
} catch (e) {
console.log(e);
}
}
expect: {
"use strict";
try {
(function() {
for (;;)
throw "PASS";
})();
} catch (e) {
console.log(e);
}
}
expect_stdout: "PASS"
}

View File

@@ -745,7 +745,7 @@ call_args: {
expect: {
var a = 1;
console.log(1);
+(1, 1);
1, 1;
}
expect_stdout: true
}
@@ -769,7 +769,7 @@ call_args_drop_param: {
}
expect: {
console.log(1);
+(b, 1);
b, 1;
}
expect_stdout: true
}
@@ -888,6 +888,39 @@ unsafe_charAt_noop: {
expect_stdout: "f n"
}
chained_side_effects: {
options = {
evaluate: true,
}
input: {
console.log("foo") || (console.log("bar"), "baz") || console.log("moo");
}
expect: {
console.log("foo") || (console.log("bar"), "baz");
}
expect_stdout: [
"foo",
"bar",
]
expect_warnings: [
"WARN: Condition left of || always true [test/compress/evaluate.js:1,8]",
]
}
instanceof_lambda: {
options = {
evaluate: true,
side_effects: true,
}
input: {
console.log(42 instanceof function() {});
}
expect: {
console.log(false);
}
expect_stdout: "false"
}
issue_1649: {
options = {
evaluate: true,
@@ -2752,8 +2785,7 @@ issue_3944: {
}
expect: {
void function f() {
while (a = 0 == (a = void 0), console.log(a), void 0);
var a;
while (0 == void 0, console.log(false), void 0);
f;
}();
}
@@ -3203,7 +3235,7 @@ issue_4552: {
expect_stdout: "NaN"
}
issue_4886: {
issue_4886_1: {
options = {
evaluate: true,
unsafe: true,
@@ -3222,3 +3254,165 @@ issue_4886: {
}
expect_stdout: "true"
}
issue_4886_2: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log("foo" in {
"foo": null,
__proto__: 42,
});
}
expect: {
console.log("foo" in {
"foo": null,
__proto__: 42,
});
}
expect_stdout: "true"
}
issue_5354: {
options = {
evaluate: true,
unsafe: true,
}
input: {
function f(a) {
return +a.toExponential(1);
}
function g(b) {
return 0 + b.toFixed(2);
}
function h(c) {
return 1 * c.toPrecision(3);
}
console.log(typeof f(45), typeof g(67), typeof h(89));
}
expect: {
function f(a) {
return +a.toExponential(1);
}
function g(b) {
return 0 + b.toFixed(2);
}
function h(c) {
return +c.toPrecision(3);
}
console.log(typeof f(45), typeof g(67), typeof h(89));
}
expect_stdout: "number string number"
}
issue_5356: {
options = {
evaluate: true,
inline: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
console.log(function() {
return a++;
var a = a;
}());
}
expect: {
console.log(+a);
var a;
}
expect_stdout: "NaN"
}
issue_5362_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = -console;
console.log(delete +a);
}
expect: {
var a = -console;
console.log((+a, true));
}
expect_stdout: "true"
}
issue_5362_2: {
options = {
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var a = -console;
console.log(delete +a);
}
expect: {
console.log(true);
}
expect_stdout: "true"
}
issue_5380: {
options = {
evaluate: true,
keep_fnames: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = function f(b) {
return function g() {
for (b in { PASS: 42 });
}(), b;
}("FAIL");
console.log(a);
}
expect: {
var a = function f(b) {
return function g() {
for (b in { PASS: 42 });
}(), b;
}("FAIL");
console.log(a);
}
expect_stdout: "PASS"
}
issue_5558: {
options = {
collapse_vars: true,
evaluate: true,
reduce_vars: true,
sequences: true,
toplevel: true,
}
input: {
var a = 99, b = 0;
a++;
b++;
b += a;
b *= a;
b += a;
console.log(a);
}
expect: {
var a = 99, b = 0;
b++,
b = (b += ++a) * a + a,
console.log(a);
}
expect_stdout: "100"
}

View File

@@ -62,7 +62,7 @@ assignment_2: {
}
expect_exact: "var a=8n;a**=a;console.log(a);"
expect_stdout: "16777216n"
node_version: ">=10"
node_version: ">=10.4.0"
}
evaluate: {
@@ -99,8 +99,8 @@ issue_4664: {
expect: {
(function f() {
new function(a) {
console.log(typeof f, a, typeof this);
}((A = 0, 2 ** 30));
console.log(typeof f, 2 ** 30, typeof this);
}(A = 0);
})();
}
expect_stdout: "function 1073741824 object"

View File

@@ -109,6 +109,17 @@ foreign: {
expect_exact: 'export*from"foo";export{}from"bar";export*as a from"baz";export{default}from"moo";export{b,c as case,default as delete,d}from"moz";'
}
non_identifiers: {
beautify = {
quote_style: 3,
}
input: {
export * as "42" from 'foo';
export { '42', "delete" as 'foo' } from "bar";
}
expect_exact: "export*as\"42\"from'foo';export{'42',delete as foo}from\"bar\";"
}
same_quotes: {
beautify = {
beautify: true,
@@ -417,6 +428,46 @@ hoist_funs: {
expect_exact: "export function f(){}export default async function*g(){}"
}
instanceof_default_class: {
options = {
toplevel: true,
unused: true,
}
input: {
export default class A {
f(a) {
return a instanceof A;
}
}
}
expect: {
export default class A {
f(a) {
return a instanceof A;
}
}
}
}
instanceof_default_function: {
options = {
toplevel: true,
unused: true,
}
input: {
export default function f() {
if (!(this instanceof f))
throw new Error("must instantiate");
}
}
expect: {
export default function f() {
if (!(this instanceof f))
throw new Error("must instantiate");
}
}
}
issue_4742_join_vars_1: {
options = {
join_vars: true,
@@ -496,3 +547,36 @@ issue_4766: {
export var a = "bar";
}
}
issue_5444: {
options = {
unused: true,
}
input: {
export var a = (console, console);
}
expect: {
console;
export var a = console;
}
}
issue_5628: {
options = {
unused: true,
}
input: {
var a;
export default function f() {
for (a in 42);
}
console.log(a);
}
expect: {
var a;
export default function f() {
for (a in 42);
}
console.log(a);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -217,7 +217,8 @@ name_collision_1: {
var obj_foo = 1;
var obj_bar = 2;
function f() {
var obj_foo$0 = 3,
var obj,
obj_foo$0 = 3,
obj_bar = 4,
obj_b_r = 5,
obj_b_r$0 = 6,
@@ -249,7 +250,8 @@ name_collision_2: {
console.log(o.p === o.p, o["+"](4), o["-"](5), o__$0, o__$1);
}
expect: {
var o_p = 1,
var o,
o_p = 1,
o__ = function(x) {
return x;
},
@@ -283,7 +285,8 @@ name_collision_3: {
console.log(o.p === o.p, o["+"](4), o["-"](5));
}
expect: {
var o_p = 1,
var o,
o_p = 1,
o__ = function(x) {
return x;
},
@@ -315,7 +318,7 @@ name_collision_4: {
}
expect: {
console.log(function() {
var o_p$0 = 0, o_q = "PASS";
var o, o_p$0 = 0, o_q = "PASS";
return function(o_p) {
if (!o_p$0) return o_p;
}(o_q);
@@ -459,6 +462,11 @@ issue_2473_1: {
var x = {};
var y = [];
}
expect_warnings: [
"INFO: Retaining variable x",
"INFO: Retaining variable y",
"WARN: Dropping unused variable z [test/compress/hoist_props.js:3,12]",
]
}
issue_2473_2: {
@@ -481,6 +489,11 @@ issue_2473_2: {
var x = {};
var y = [];
}
expect_warnings: [
"INFO: Retaining variable x",
"INFO: Retaining variable y",
"WARN: Dropping unused variable z [test/compress/hoist_props.js:3,12]",
]
}
issue_2473_3: {
@@ -506,6 +519,9 @@ issue_2473_3: {
console.log(o.a, o.b);
}
expect_stdout: "1 2"
expect_warnings: [
"INFO: Retaining variable o",
]
}
issue_2473_4: {
@@ -532,6 +548,9 @@ issue_2473_4: {
})();
}
expect_stdout: "1 2"
expect_warnings: [
"INFO: Dropping unused variable o [test/compress/hoist_props.js:2,16]",
]
}
issue_2508_1: {
@@ -768,7 +787,7 @@ issue_3046: {
expect: {
console.log(function(a) {
do {
var b_c = a++;
var b, b_c = a++;
} while (b_c && a);
return a;
}(0));
@@ -931,7 +950,7 @@ issue_3411: {
expect: {
var c = 1;
!function f() {
var o_p = --c && f();
var o, o_p = --c && f();
+{} || console.log("PASS");
}();
}
@@ -1042,9 +1061,7 @@ issue_3945_1: {
expect: {
function f() {
o.p;
var o = {
q: 0,
};
var o, o_q = 0;
}
}
}
@@ -1063,9 +1080,7 @@ issue_3945_2: {
}
expect: {
console.log(typeof o);
var o = {
p: 0,
};
var o, o_p = 0;
}
expect_stdout: "undefined"
}
@@ -1134,10 +1149,94 @@ issue_4985: {
}());
}
expect: {
var a_p = 42;
var a, a_p = 42;
console.log(function() {
({});
}());
}
expect_stdout: "undefined"
}
issue_5182: {
options = {
hoist_props: true,
merge_vars: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var o = console;
log = o.log;
o = {
p: function(a) {
console.log(a ? "PASS" : "FAIL");
return a;
},
};
log(o.p(42));
}
expect: {
var o = console;
log = o.log;
o = function(a) {
console.log(a ? "PASS" : "FAIL");
return a;
};
log(o(42));
}
expect_stdout: [
"PASS",
"42",
]
}
issue_5441: {
options = {
hoist_props: true,
passes: 2,
reduce_vars: true,
side_effects: true,
}
input: {
console.log(function(a) {
(function() {
a = { p: this };
})();
return typeof a;
}());
}
expect: {
console.log(function(a) {
(function() {
a_p = this;
})();
var a_p;
return typeof {};
}());
}
expect_stdout: "object"
}
issue_5498: {
options = {
hoist_props: true,
reduce_vars: true,
toplevel: true,
}
input: {
var o = {
__proto__: 42,
};
while (console.log(typeof o.__proto__));
}
expect: {
var o = {
__proto__: 42,
};
while (console.log(typeof o.__proto__));
}
expect_stdout: "object"
}

View File

@@ -2,6 +2,8 @@ statements: {
options = {
hoist_funs: false,
hoist_vars: true,
join_vars: true,
unused: true,
}
input: {
function f() {
@@ -25,6 +27,8 @@ statements_funs: {
options = {
hoist_funs: true,
hoist_vars: true,
join_vars: true,
unused: true,
}
input: {
function f() {
@@ -48,6 +52,8 @@ sequences: {
options = {
hoist_funs: false,
hoist_vars: true,
join_vars: true,
unused: true,
}
input: {
function f() {
@@ -71,6 +77,8 @@ sequences_funs: {
options = {
hoist_funs: true,
hoist_vars: true,
join_vars: true,
unused: true,
}
input: {
function f() {
@@ -108,7 +116,8 @@ catch_var: {
console.log(a);
}
expect: {
var a = "PASS";
a = "PASS";
var a;
console.log(a);
}
expect_stdout: "PASS"
@@ -118,6 +127,8 @@ issue_2295: {
options = {
collapse_vars: true,
hoist_vars: true,
join_vars: true,
unused: true,
}
input: {
function foo(o) {
@@ -135,10 +146,11 @@ issue_2295: {
}
}
issue_4487: {
issue_4487_1: {
options = {
functions: true,
hoist_vars: true,
join_vars: true,
keep_fnames: true,
reduce_vars: true,
toplevel: true,
@@ -150,16 +162,66 @@ issue_4487: {
};
var b = a();
}
expect: {
var a = function f() {
var f = console.log(typeof f);
};
a();
}
expect_stdout: "undefined"
}
issue_4487_2: {
options = {
functions: true,
hoist_vars: true,
join_vars: true,
keep_fnames: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = function f() {
var f = console.log(typeof f);
};
var b = a();
}
expect: {
function a() {
var f;
console.log(typeof f);
var f = console.log(typeof f);
}
a();
}
expect_stdout: "undefined"
}
issue_4487_3: {
options = {
functions: true,
hoist_vars: true,
join_vars: true,
keep_fnames: true,
passes: 3,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = function f() {
var f = console.log(typeof f);
};
var b = a();
}
expect: {
(function a() {
console.log(typeof void 0);
})();
}
expect_stdout: "undefined"
}
issue_4489: {
options = {
collapse_vars: true,
@@ -176,8 +238,7 @@ issue_4489: {
console.log(k);
}
expect: {
!(A = 0);
for (var k in true);
for (var k in !(A = 0));
console.log(k);
}
expect_stdout: "undefined"
@@ -201,9 +262,7 @@ issue_4517: {
}
expect: {
console.log(function() {
var a = 2;
A = a;
return A + typeof !1;
return (A = 2) + typeof !1;
}());
}
expect_stdout: "2boolean"
@@ -214,6 +273,7 @@ issue_4736: {
collapse_vars: true,
evaluate: true,
hoist_vars: true,
join_vars: true,
merge_vars: true,
reduce_vars: true,
toplevel: true,
@@ -233,8 +293,8 @@ issue_4736: {
expect: {
(function() {
(function() {
0,
console.log(1073741824);
0;
console.log(1 << 30);
})();
})();
}
@@ -245,24 +305,25 @@ issue_4839: {
options = {
evaluate: true,
hoist_vars: true,
join_vars: true,
keep_fargs: false,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = function(a, b) {
var log = console.log, o = function(a, b) {
return b && b;
}("foo");
for (var k in o)
throw "FAIL";
console.log("PASS");
log("PASS");
}
expect: {
var k, o = void 0;
for (k in o)
var k, log = console.log;
for (k in void 0)
throw "FAIL";
console.log("PASS");
log("PASS");
}
expect_stdout: "PASS"
}
@@ -271,6 +332,7 @@ issue_4859: {
options = {
evaluate: true,
hoist_vars: true,
join_vars: true,
keep_infinity: true,
merge_vars: true,
reduce_vars: true,
@@ -288,8 +350,7 @@ issue_4859: {
}
expect: {
(function f(a) {
var d = 1 / 0, d = Infinity;
console.log(d);
console.log(2 + 1 / 0);
return f;
})();
}
@@ -361,9 +422,9 @@ issue_4893_2: {
expect: {
try{
(function() {
var b;
b = null;
b.p += 42;
var a;
a = null;
a.p += 42;
})();
} catch (e) {
console.log("PASS");
@@ -395,3 +456,348 @@ issue_4898: {
}
expect_stdout: "PASS"
}
issue_5187_1: {
options = {
hoist_props: true,
hoist_vars: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function f() {
var a = 42;
do {
var b = { 0: a++ };
} while (console.log(b[b ^= 0]));
}
f();
}
expect: {
(function() {
var a, b;
a = 42;
do {
b = { 0: a++ };
} while (console.log(b[b ^= 0]));
})();
}
expect_stdout: "42"
}
issue_5187_2: {
options = {
hoist_props: true,
hoist_vars: true,
join_vars: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function f() {
var a = 42;
do {
var b = { 0: a++ };
} while (console.log(b[b ^= 0]));
}
f();
}
expect: {
(function() {
var b, a = 42;
do {
b = { 0: a++ };
} while (console.log(b[b ^= 0]));
})();
}
expect_stdout: "42"
}
issue_5195: {
options = {
hoist_props: true,
hoist_vars: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function f() {
var a;
do {
var b = { p: a };
} while (console.log(b += ""));
}
f();
}
expect: {
(function() {
var a, b;
do {
b = { p: a };
} while (console.log(b += ""));
})();
}
expect_stdout: "[object Object]"
}
issue_5378: {
options = {
hoist_vars: true,
inline: true,
toplevel: true,
}
input: {
var a = 2;
while (a--)
(function() {
var b;
var c;
while (console.log(b));
--b;
})();
}
expect: {
var a = 2;
while (a--) {
b = void 0;
var b, c;
while (console.log(b));
--b;
}
}
expect_stdout: [
"undefined",
"undefined",
]
}
issue_5411_1: {
options = {
collapse_vars: true,
dead_code: true,
hoist_vars: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a = "PASS";
b++;
b = a;
var b = b, c = c && c[b];
console.log(b);
}
expect: {
var a, b, c;
b++;
b = a = "PASS";
c = c && c[b];
console.log(b);
}
expect_stdout: "PASS"
}
issue_5411_2: {
options = {
collapse_vars: true,
dead_code: true,
evaluate: true,
hoist_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = "PASS";
b++;
b = a;
var b = b, c = c && c[b];
console.log(b);
}
expect: {
var b, c;
b++;
b = "PASS",
c;
console.log(b);
}
expect_stdout: "PASS"
}
issue_5411_3: {
options = {
collapse_vars: true,
hoist_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = console;
a++;
var a = A = a;
console.log(A);
}
expect: {
var a;
a = console;
a = A = ++a;
console.log(A);
}
expect_stdout: "NaN"
}
issue_5411_4: {
options = {
collapse_vars: true,
hoist_vars: true,
join_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = console;
a++;
var a = A = a;
console.log(A);
}
expect: {
var a = console;
a = A = ++a;
console.log(A);
}
expect_stdout: "NaN"
}
issue_5626: {
options = {
conditionals: true,
evaluate: true,
hoist_vars: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = function() {
return console.log(arguments[0]), 42;
}("PASS") ? null : "foo";
for (var b in a)
FAIL;
}
expect: {
(function() {
console.log(arguments[0]);
}("PASS"));
for (var b in null)
FAIL;
}
expect_stdout: "PASS"
}
issue_5638_1: {
options = {
collapse_vars: true,
hoist_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = "FAIL";
var a = [ 42 ];
console || FAIL(a);
console.log(a++);
}
expect: {
var a;
a = "FAIL";
a = [ 42 ];
console || FAIL(a);
console.log(a++);
}
expect_stdout: "42"
}
issue_5638_2: {
options = {
collapse_vars: true,
hoist_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = "FAIL";
var a = [ 6 ];
console || FAIL(a);
console.log(a *= 7);
}
expect: {
var a;
a = "FAIL";
a = [ 6 ];
console || FAIL(a);
console.log(a *= 7);
}
expect_stdout: "42"
}
issue_5638_3: {
options = {
collapse_vars: true,
hoist_vars: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var o = { foo: 42 };
for (var k in o) {
var v = o[k];
log(k || v, v++);
}
}
expect: {
var log, o, k, v;
log = console.log;
for (k in o = { foo: 42 }) {
v = o[k];
log(k || v, v++);
}
}
expect_stdout: "foo 42"
}
issue_5638_4: {
options = {
collapse_vars: true,
hoist_vars: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var o = { foo: 6 };
for (var k in o) {
var v = o[k];
log(k || v, v *= 7);
}
}
expect: {
var log, o, k, v;
log = console.log;
for (k in o = { foo: 6 }) {
v = o[k];
log(k || v, v *= 7);
}
}
expect_stdout: "foo 42"
}

View File

@@ -2631,13 +2631,14 @@ issue_3999: {
]
}
issue_4001: {
issue_4001_1: {
options = {
collapse_vars: true,
ie: true,
inline: true,
reduce_vars: true,
sequences: true,
side_effects: false,
toplevel: true,
unused: true,
}
@@ -2660,7 +2661,42 @@ issue_4001: {
return a;
}
var a;
console.log((a = 42, void f()[42], void function a() {}));
console.log((a = 42, f()[42], void f, void function a() {}));
}
expect_stdout: "undefined"
}
issue_4001_2: {
options = {
collapse_vars: true,
ie: true,
inline: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
console.log(function(a) {
function f() {
return a;
var b;
}
var c = f();
(function g() {
c[42];
f;
})();
(function a() {});
}(42));
}
expect: {
function f() {
return a;
}
var a;
console.log((a = 42, void f()[42]));
}
expect_stdout: "undefined"
}
@@ -3109,9 +3145,9 @@ issue_5081_call: {
}));
}
expect: {
function f(b) {
function f(a) {
// IE5-10: TypeError: Function expected
return b(b = "A") + (b += "SS");
return a(a = "A") + (a += "SS");
}
console.log(f(function() {
return "P";
@@ -3161,8 +3197,8 @@ issue_5081_property_access: {
console.log(f({ A: "P" }));
}
expect: {
function f(b) {
return b[b = "A"] + (b += "SS");
function f(a) {
return a[a = "A"] + (a += "SS");
}
// IE9-11: undefinedASS
console.log(f({ A: "P" }));
@@ -3192,3 +3228,249 @@ issue_5081_property_access_ie: {
}
expect_stdout: "PASS"
}
issue_5269_1: {
options = {
ie: false,
inline: true,
toplevel: true,
}
input: {
"use strict";
do {
(function() {
try {
throw "PASS";
} catch (e) {
console.log(e);
}
})();
} while (!console);
}
expect: {
"use strict";
do {
try {
throw "PASS";
} catch (e) {
console.log(e);
}
} while (!console);
}
expect_stdout: "PASS"
}
issue_5269_1_ie: {
options = {
ie: true,
inline: true,
toplevel: true,
}
input: {
"use strict";
do {
(function() {
try {
throw "PASS";
} catch (e) {
console.log(e);
}
})();
} while (!console);
}
expect: {
"use strict";
do {
try {
throw "PASS";
} catch (e) {
console.log(e);
}
} while (!console);
}
expect_stdout: "PASS"
}
issue_5269_2: {
options = {
ie: false,
inline: true,
toplevel: true,
}
input: {
for (var i = 0; i < 2; i++)
(function() {
console.log(e);
try {
console;
} catch (e) {
var e = "FAIL 1";
}
e = "FAIL 2";
console;
})();
}
expect: {
for (var i = 0; i < 2; i++) {
e = void 0;
console.log(e);
try {
console;
} catch (e) {
var e = "FAIL 1";
}
e = "FAIL 2";
console;
}
}
expect_stdout: [
"undefined",
"undefined",
]
}
issue_5269_2_ie: {
options = {
ie: true,
inline: true,
toplevel: true,
}
input: {
for (var i = 0; i < 2; i++)
(function() {
console.log(e);
try {
console;
} catch (e) {
var e = "FAIL 1";
}
e = "FAIL 2";
console;
})();
}
expect: {
for (var i = 0; i < 2; i++) {
e = void 0;
console.log(e);
try {
console;
} catch (e) {
var e = "FAIL 1";
}
e = "FAIL 2";
console;
}
}
expect_stdout: [
"undefined",
"undefined",
]
}
issue_5269_3: {
options = {
ie: false,
inline: true,
toplevel: true,
}
input: {
e = "foo";
for (var i = 0; i < 2; i++)
(function() {
console.log(e);
try {
console;
} catch (e) {
e = "FAIL";
}
e = "bar";
console;
})();
}
expect: {
e = "foo";
for (var i = 0; i < 2; i++) {
console.log(e);
try {
console;
} catch (e) {
e = "FAIL";
}
e = "bar";
console;
}
}
expect_stdout: [
"foo",
"bar",
]
}
issue_5269_3_ie: {
options = {
ie: true,
inline: true,
toplevel: true,
}
input: {
e = "foo";
for (var i = 0; i < 2; i++)
(function() {
console.log(e);
try {
console;
} catch (e) {
e = "FAIL";
}
e = "bar";
console;
})();
}
expect: {
e = "foo";
for (var i = 0; i < 2; i++) {
console.log(e);
try {
console;
} catch (e) {
e = "FAIL";
}
e = "bar";
console;
}
}
expect_stdout: [
"foo",
"bar",
]
}
issue_5350: {
options = {
ie: false,
properties: true,
side_effects: true,
}
input: {
console.log(typeof f, [ 42, function f() {} ][0]);
}
expect: {
console.log(typeof f, 42);
}
expect_stdout: "undefined 42"
}
issue_5350_ie: {
options = {
ie: true,
properties: true,
side_effects: true,
}
input: {
console.log(typeof f, [ 42, function f() {} ][0]);
}
expect: {
console.log(typeof f, (function f() {}, 42));
}
expect_stdout: "undefined 42"
}

File diff suppressed because it is too large Load Diff

View File

@@ -40,6 +40,17 @@ default_keys: {
expect_exact: 'import foo,{bar}from"baz";'
}
non_identifiers: {
beautify = {
quote_style: 3,
}
input: {
import { '42' as foo } from "bar";
import { "foo" as bar } from 'baz';
}
expect_exact: "import{'42'as foo}from\"bar\";import{foo as bar}from'baz';"
}
dynamic: {
input: {
(async a => await import(a))("foo").then(bar);
@@ -106,6 +117,22 @@ drop_unused: {
}
}
drop_side_effect_free: {
options = {
imports: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
import foo from "bar";
var a = foo;
}
expect: {
import "bar";
}
}
mangle: {
rename = false
mangle = {
@@ -211,3 +238,33 @@ issue_4708_2: {
import a from "foo";
}
}
pr_5550_1: {
input: {
if (console)
import("foo");
else
import.meta.url.replace(/bar/g, console.log);
}
expect: {
if (console)
import("foo");
else
import.meta.url.replace(/bar/g, console.log);
}
}
pr_5550_2: {
input: {
L: {
import("foo");
import.meta.url.replace(/bar/g, console.log);
}
}
expect: {
L: {
import("foo");
import.meta.url.replace(/bar/g, console.log);
}
}
}

View File

@@ -0,0 +1,100 @@
numeric: {
beautify = {
beautify: true,
indent_start: 1,
indent_level: 3,
}
input: {
switch (42) {
case null:
console.log("FAIL");
}
console.log("PASS");
}
expect_exact: [
" switch (42) {",
" case null:",
' console.log("FAIL");',
" }",
"",
' console.log("PASS");',
]
expect_stdout: "PASS"
}
spaces: {
beautify = {
beautify: true,
indent_start: " ",
indent_level: " ",
}
input: {
switch (42) {
case null:
console.log("FAIL");
}
console.log("PASS");
}
expect_exact: [
" switch (42) {",
" case null:",
' console.log("FAIL");',
" }",
"",
' console.log("PASS");',
]
expect_stdout: "PASS"
}
tabs: {
beautify = {
beautify: true,
indent_start: "\t",
indent_level: "\t",
}
input: {
switch (42) {
case null:
console.log("FAIL");
}
console.log("PASS");
}
expect_exact: [
"\tswitch (42) {",
"\tcase null:",
'\t\tconsole.log("FAIL");',
"\t}",
"",
'\tconsole.log("PASS");',
]
expect_stdout: "PASS"
}
mixed: {
beautify = {
beautify: true,
indent_start: "\n",
indent_level: " \t",
}
input: {
switch (42) {
case null:
console.log("FAIL");
}
console.log("PASS");
}
expect_exact: [
"",
"switch (42) {",
"",
" case null:",
"",
' \tconsole.log("FAIL");',
"",
"}",
"",
"",
'console.log("PASS");',
]
expect_stdout: "PASS"
}

View File

@@ -4,22 +4,21 @@ multiple_functions: {
if_return: true,
}
input: {
( function() {
if ( !window ) {
(function() {
if (!window)
return;
}
function f() {}
function g() {}
} )();
})();
}
expect: {
( function() {
(function() {
// NOTE: other compression steps will reduce this
// down to just `window`.
if ( !window );
if (!window);
function f() {}
function g() {}
} )();
})();
}
}
@@ -29,18 +28,17 @@ single_function: {
if_return: true,
}
input: {
( function() {
if ( !window ) {
(function() {
if (!window)
return;
}
function f() {}
} )();
})();
}
expect: {
( function() {
if ( !window );
(function() {
if (!window);
function f() {}
} )();
})();
}
}
@@ -50,28 +48,26 @@ deeply_nested: {
if_return: true,
}
input: {
( function() {
if ( !window ) {
(function() {
if (!window)
return;
}
function f() {}
function g() {}
if ( !document ) {
if (!document)
return;
}
function h() {}
} )();
})();
}
expect: {
( function() {
(function() {
// NOTE: other compression steps will reduce this
// down to just `window`.
if ( window )
if ( !document );
if (!window);
else if (!document);
function f() {}
function g() {}
function h() {}
} )();
})();
}
}
@@ -81,18 +77,18 @@ not_hoisted_when_already_nested: {
if_return: true,
}
input: {
( function() {
if ( !window ) {
(function() {
if (!window)
return;
}
if ( foo ) function f() {}
} )();
if (foo) function f() {}
})();
}
expect: {
( function() {
if ( window )
if ( foo ) function f() {}
} )();
(function() {
if (!window);
else if (foo)
function f() {}
})();
}
}
@@ -104,15 +100,19 @@ defun_if_return: {
input: {
function e() {
function f() {}
if (!window) return;
else function g() {}
if (!window)
return;
else
function g() {}
function h() {}
}
}
expect: {
function e() {
function f() {}
if (window) function g() {}
if (!window);
else
function g() {}
function h() {}
}
}
@@ -126,8 +126,10 @@ defun_hoist_funs: {
input: {
function e() {
function f() {}
if (!window) return;
else function g() {}
if (!window)
return;
else
function g() {}
function h() {}
}
}
@@ -136,7 +138,7 @@ defun_hoist_funs: {
function f() {}
function g() {}
function h() {}
if (window);
if (!window);
}
}
}
@@ -149,15 +151,18 @@ defun_else_if_return: {
input: {
function e() {
function f() {}
if (window) function g() {}
else return;
if (window)
function g() {}
else
return;
function h() {}
}
}
expect: {
function e() {
function f() {}
if (window) function g() {}
if (window)
function g() {}
function h() {}
}
}

View File

@@ -40,6 +40,9 @@ conditional_false_stray_else_in_loop: {
console.log(i);
}
}
expect_exact: "for(var i=1;i<=4;++i)if(!(i<=2))console.log(i);"
expect_stdout: true
expect_exact: "for(var i=1;i<=4;++i)if(i<=2);else console.log(i);"
expect_stdout: [
"3",
"4",
]
}

View File

@@ -356,6 +356,7 @@ mangle_catch_redef_3: {
try {
throw 0;
} catch (o) {
// prints "FAIL" if inlined on Node.js v4-
(function() {
function f() {
o = "FAIL";
@@ -366,7 +367,8 @@ 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: true
expect_stdout: "PASS"
node_version: ">=6"
}
mangle_catch_redef_3_toplevel: {
@@ -379,6 +381,7 @@ mangle_catch_redef_3_toplevel: {
try {
throw 0;
} catch (o) {
// prints "FAIL" if inlined on Node.js v4-
(function() {
function f() {
o = "FAIL";
@@ -389,7 +392,8 @@ 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: true
expect_stdout: "PASS"
node_version: ">=6"
}
mangle_catch_redef_3_ie8: {
@@ -402,6 +406,7 @@ mangle_catch_redef_3_ie8: {
try {
throw 0;
} catch (o) {
// prints "FAIL" if inlined on Node.js v4-
(function() {
function f() {
o = "FAIL";
@@ -412,7 +417,8 @@ mangle_catch_redef_3_ie8: {
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: true
expect_stdout: "PASS"
node_version: ">=6"
}
mangle_catch_redef_3_ie8_toplevel: {
@@ -425,6 +431,7 @@ mangle_catch_redef_3_ie8_toplevel: {
try {
throw 0;
} catch (o) {
// prints "FAIL" if inlined on Node.js v4-
(function() {
function f() {
o = "FAIL";
@@ -435,5 +442,6 @@ 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: true
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -53,6 +53,14 @@ mangle_props: {
);
}
expect_stdout: "1 1 1 2 2 2 3 3 3 4 4 4 5 5"
expect_warnings: [
"INFO: Preserving reserved property undefined",
"INFO: Preserving reserved property NaN",
"INFO: Preserving reserved property Infinity",
"INFO: Preserving reserved property -Infinity",
"INFO: Preserving reserved property null",
"INFO: Preserving reserved property log",
]
}
numeric_literal: {
@@ -106,11 +114,18 @@ numeric_literal: {
"4 5 4 4",
"8 7 8",
]
expect_warnings: [
"INFO: Preserving reserved property log",
"INFO: Mapping property 0x25 to o",
"INFO: Mapping property 1E42 to b",
]
}
identifier: {
mangle = {
properties: true,
properties: {
builtins: true,
},
}
input: {
var obj = {
@@ -209,37 +224,37 @@ identifier: {
B: 28,
C: 29,
D: 30,
F: 31,
G: 32,
false: 33,
null: 34,
true: 35,
H: 36,
I: 37,
J: 38,
K: 39,
L: 40,
M: 41,
N: 42,
O: 43,
P: 44,
Q: 45,
R: 46,
S: 47,
T: 48,
U: 49,
V: 50,
W: 51,
X: 52,
Y: 53,
Z: 54,
$: 55,
_: 56,
ee: 57,
te: 58,
ne: 59,
ae: 60,
ie: 61,
E: 31,
F: 32,
G: 33,
H: 34,
I: 35,
J: 36,
K: 37,
L: 38,
M: 39,
N: 40,
O: 41,
P: 42,
Q: 43,
R: 44,
S: 45,
T: 46,
U: 47,
V: 48,
W: 49,
X: 50,
Y: 51,
Z: 52,
$: 53,
_: 54,
ee: 55,
te: 56,
ne: 57,
ae: 58,
ie: 59,
oe: 60,
re: 61,
};
}
}

View File

@@ -108,6 +108,7 @@ safe_undefined: {
}
negate_iife_3: {
expression = true
options = {
conditionals: true,
expression: true,
@@ -123,6 +124,7 @@ negate_iife_3: {
}
negate_iife_3_off: {
expression = true
options = {
conditionals: true,
expression: true,
@@ -203,6 +205,7 @@ negate_iife_5_off: {
}
issue_1254_negate_iife_true: {
expression = true
options = {
expression: true,
inline: true,
@@ -215,11 +218,12 @@ issue_1254_negate_iife_true: {
};
})()();
}
expect_exact: 'void console.log("test");'
expect_exact: 'void console.log("test")'
expect_stdout: true
}
issue_1254_negate_iife_nested: {
expression = true
options = {
expression: true,
inline: true,
@@ -232,7 +236,7 @@ issue_1254_negate_iife_nested: {
};
})()()()()();
}
expect_exact: '(void console.log("test"))()()();'
expect_exact: '(void console.log("test"))()()()'
}
negate_iife_issue_1073: {

195
test/compress/issue-5614.js Normal file
View File

@@ -0,0 +1,195 @@
record_update: {
options = {
loops: true,
passes: 3,
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var value = { a: 42, b: "PASS" };
var unused = _Utils_update(value, { b: "FAIL" });
function _Utils_update(oldRecord, updatedFields) {
var newRecord = {};
for (var key in oldRecord)
newRecord[key] = oldRecord[key];
for (var key in updatedFields)
newRecord[key] = updatedFields[key];
return newRecord;
}
}
expect: {}
}
currying: {
options = {
inline: true,
passes: 2,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function F(arity, fun, wrapper) {
wrapper.a = arity;
wrapper.f = fun;
return wrapper;
}
function F2(fun) {
return F(2, fun, function(a) {
return function(b) {
return fun(a, b);
};
});
}
function _Utils_eq(x, y) {
var pair, stack = [], isEqual = _Utils_eqHelp(x, y, 0, stack);
while (isEqual && (pair = stack.pop()))
isEqual = _Utils_eqHelp(pair.a, pair.b, 0, stack);
return isEqual;
}
var _Utils_equal = F2(_Utils_eq);
}
expect: {}
}
conditional_property_write: {
options = {
pure_getters: "strict",
reduce_vars: true,
unused: true,
}
input: {
function f(a) {
var o = {};
if (a)
o.p = console.log("foo");
else
o.q = console.log("bar");
o.r = console.log("baz");
}
f(42);
f(null);
}
expect: {
function f(a) {
if (a)
console.log("foo");
else
console.log("bar");
console.log("baz");
}
f(42);
f(null);
}
expect_stdout: [
"foo",
"baz",
"bar",
"baz",
]
}
reassign_1: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = "PASS", b = "FAIL";
(b = a).toString();
console.log(b);
}
expect: {
var b = "FAIL";
(b = "PASS").toString();
console.log(b);
}
expect_stdout: "PASS"
}
reassign_2: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = "PASS";
if (false) {
a = null + 0;
a();
}
console.log(a);
}
expect: {
var a = "PASS";
if (false) {
a = 0;
a();
}
console.log(a);
}
expect_stdout: "PASS"
}
reassign_3: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 0;
(a = a || "PASS").toString();
console.log(a);
}
expect: {
var a = 0;
(a = (0, "PASS")).toString();
console.log(a);
}
expect_stdout: "PASS"
}
retain_instance_write: {
options = {
pure_getters: true,
reduce_vars: true,
unused: true,
}
input: {
function f(a) {
return a;
}
function g() {
var o = {};
var b = new f(o);
if (console)
b.p = "PASS";
return o;
}
console.log(g().p);
}
expect: {
function f(a) {
return a;
}
function g() {
var o = {};
var b = new f(o);
if (console)
b.p = "PASS";
return o;
}
console.log(g().p);
}
expect_stdout: "PASS"
}

View File

@@ -68,6 +68,7 @@ drop_console_2: {
}
drop_value: {
expression = true
options = {
expression: true,
side_effects: true,
@@ -106,6 +107,7 @@ wrongly_optimized: {
}
negate_iife_1: {
expression = true
options = {
expression: true,
negate_iife: true,
@@ -119,6 +121,7 @@ negate_iife_1: {
}
negate_iife_3: {
expression = true
options = {
conditionals: true,
expression: true,
@@ -133,6 +136,7 @@ negate_iife_3: {
}
negate_iife_3_off: {
expression = true
options = {
conditionals: true,
expression: true,
@@ -215,6 +219,7 @@ negate_iife_5_off: {
}
issue_1254_negate_iife_true: {
expression = true
options = {
expression: true,
negate_iife: true,
@@ -226,11 +231,12 @@ issue_1254_negate_iife_true: {
};
})()();
}
expect_exact: '(function(){return function(){console.log("test")}})()();'
expect_exact: 'function(){return function(){console.log("test")}}()()'
expect_stdout: true
}
issue_1254_negate_iife_nested: {
expression = true
options = {
expression: true,
negate_iife: true,
@@ -242,7 +248,7 @@ issue_1254_negate_iife_nested: {
};
})()()()()();
}
expect_exact: '(function(){return function(){console.log("test")}})()()()()();'
expect_exact: 'function(){return function(){console.log("test")}}()()()()()'
expect_stdout: true
}
@@ -317,7 +323,35 @@ iife: {
typeof function g() {}();
}
expect: {
x = 42, function a() {}(), function b() {}(), function c() {}(),
function d() {}(), function e() {}(), function f() {}(), typeof function g() {}();
x = 42,
function a() {}(),
!function b() {}(),
~function c() {}(),
+function d() {}(),
-function e() {}(),
void function f() {}(),
typeof function g() {}();
}
}
iife_drop_side_effect_free: {
options = {
expression: true,
sequences: true,
side_effects: true,
}
input: {
x = 42;
(function a() {})();
!function b() {}();
~function c() {}();
+function d() {}();
-function e() {}();
void function f() {}();
typeof function g() {}();
}
expect: {
x = 42,
typeof void 0;
}
}

View File

@@ -19,6 +19,11 @@ dont_reuse_prop: {
console.log(obj.a);
}
expect_stdout: "123"
expect_warnings: [
"INFO: Preserving excluded property a",
"INFO: Preserving reserved property log",
"INFO: Mapping property asd to b",
]
}
unmangleable_props_should_always_be_reserved: {
@@ -42,4 +47,9 @@ unmangleable_props_should_always_be_reserved: {
console.log(obj.a);
}
expect_stdout: "123"
expect_warnings: [
"INFO: Preserving excluded property a",
"INFO: Preserving reserved property log",
"INFO: Mapping property asd to b",
]
}

View File

@@ -1,6 +1,4 @@
dont_mangle_arguments: {
mangle = {
};
options = {
booleans: true,
comparisons: true,
@@ -21,12 +19,13 @@ dont_mangle_arguments: {
side_effects: true,
unused: true,
}
mangle = {}
input: {
(function(){
var arguments = arguments, not_arguments = 9;
console.log(not_arguments, arguments);
})(5,6,7);
})(5, 6, 7);
}
expect_exact: "(function(){var arguments=arguments,o=9;console.log(o,arguments)})(5,6,7);"
expect_exact: "(function(){var arguments,o=9;console.log(o,arguments)})(5,6,7);"
expect_stdout: true
}

View File

@@ -1,17 +1,18 @@
keep_var_for_in: {
options = {
hoist_vars: true,
join_vars: true,
unused: true,
}
input: {
(function(obj){
(function(obj) {
var foo = 5;
for (var i in obj)
return foo;
})();
}
expect: {
(function(obj){
(function(obj) {
var i, foo = 5;
for (i in obj)
return foo;

View File

@@ -1,4 +1,4 @@
issue979_reported: {
reported: {
options = {
booleans: true,
comparisons: true,
@@ -17,29 +17,26 @@ issue979_reported: {
}
input: {
function f1() {
if (a == 1 || b == 2) {
if (a == 1 || b == 2)
foo();
}
}
function f2() {
if (!(a == 1 || b == 2)) {
}
else {
if (!(a == 1 || b == 2));
else
foo();
}
}
}
expect: {
function f1() {
1!=a&&2!=b||foo();
1 != a && 2 != b || foo();
}
function f2() {
1!=a&&2!=b||foo();
1 != a && 2 != b || foo();
}
}
}
issue979_test_negated_is_best: {
test_negated_is_best: {
options = {
booleans: true,
comparisons: true,
@@ -58,53 +55,47 @@ issue979_test_negated_is_best: {
}
input: {
function f3() {
if (a == 1 | b == 2) {
if (a == 1 | b == 2)
foo();
}
}
function f4() {
if (!(a == 1 | b == 2)) {
}
else {
if (!(a == 1 | b == 2));
else
foo();
}
}
function f5() {
if (a == 1 && b == 2) {
if (a == 1 && b == 2)
foo();
}
}
function f6() {
if (!(a == 1 && b == 2)) {
}
else {
if (!(a == 1 && b == 2));
else
foo();
}
}
function f7() {
if (a == 1 || b == 2) {
if (a == 1 || b == 2)
foo();
}
else {
else
return bar();
}
}
}
expect: {
function f3() {
1==a|2==b&&foo();
1 == a | 2 == b && foo();
}
function f4() {
1==a|2==b&&foo();
1 == a | 2 == b && foo();
}
function f5() {
1==a&&2==b&&foo();
1 == a && 2 == b && foo();
}
function f6() {
1!=a||2!=b||foo();
1 == a && 2 == b && foo();
}
function f7() {
if(1!=a&&2!=b)return bar();foo()
if (1 != a && 2 != b)
return bar();
foo();
}
}
}

View File

@@ -489,6 +489,160 @@ join_object_assignments_regex: {
expect_stdout: "1"
}
chained_assignments: {
options = {
join_vars: true,
}
input: {
var a, b = a = {};
b.p = "PASS";
console.log(a.p);
}
expect: {
var a, b = a = {
p: "PASS",
};
console.log(a.p);
}
expect_stdout: "PASS"
}
folded_assignments_1: {
options = {
evaluate: true,
join_vars: true,
}
input: {
var a = {};
a[a.PASS = 42] = "PASS";
console.log(a[42], a.PASS);
}
expect: {
var a = {
PASS: 42,
42: "PASS",
};
console.log(a[42], a.PASS);
}
expect_stdout: "PASS 42"
}
folded_assignments_2: {
options = {
evaluate: true,
join_vars: true,
}
input: {
"use strict";
var a = {};
a[42] = "FAIL";
a[a.PASS = 42] = "PASS";
console.log(a[42], a.PASS);
}
expect: {
"use strict";
var a = {
42: "FAIL",
PASS: 42,
};
a[42] = "PASS";
console.log(a[42], a.PASS);
}
expect_stdout: "PASS 42"
}
inlined_assignments: {
options = {
join_vars: true,
unused: true,
}
input: {
var a;
(a = {}).p = "PASS";
console.log(a.p);
}
expect: {
var a = {
p: "PASS",
};
console.log(a.p);
}
expect_stdout: "PASS"
}
inilne_for: {
options = {
inline: true,
join_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = function() {
for (; console.log("PASS"););
};
a();
}
expect: {
for (; console.log("PASS"););
}
expect_stdout: "PASS"
}
inilne_var: {
options = {
inline: true,
join_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
A = "PASS";
var a = function() {
var b = A;
for (b in console.log(b));
};
a();
}
expect: {
A = "PASS";
var b = A;
for (b in console.log(b));
}
expect_stdout: "PASS"
}
typescript_enum: {
rename = true
options = {
assignments: true,
collapse_vars: true,
evaluate: true,
hoist_props: true,
inline: true,
join_vars: true,
passes: 4,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var Enum;
(function (Enum) {
Enum[Enum.PASS = 42] = "PASS";
})(Enum || (Enum = {}));
console.log(Enum[42], Enum.PASS);
}
expect: {
console.log("PASS", 42);
}
expect_stdout: "PASS 42"
}
issue_2816: {
options = {
join_vars: true,
@@ -990,7 +1144,7 @@ conditional_assignments_3: {
expect_stdout: "PASS"
}
issue_3856: {
issue_3856_1: {
options = {
booleans: true,
conditionals: true,
@@ -1015,9 +1169,46 @@ issue_3856: {
console.log(function() {
(function() {
var a, b;
if (a) return a, 1;
for (a = 0; !console;);
return 0;
if (a) a;
else {
a = 0;
for (; !console;);
}
})();
}());
}
expect_stdout: "undefined"
}
issue_3856_2: {
options = {
booleans: true,
conditionals: true,
if_return: true,
join_vars: true,
passes: 2,
sequences: true,
side_effects: true,
}
input: {
console.log(function() {
(function() {
var a;
if (!a) {
a = 0;
for (var b; !console;);
return 0;
}
if (a) return 1;
})();
}());
}
expect: {
console.log(function() {
(function() {
var a, b;
if (!a)
for (a = 0; !console;);
})();
}());
}
@@ -1172,10 +1363,7 @@ assign_sequence_var: {
console.log(a, b, c);
}
expect: {
var a = 0, b = 1;
console.log(a),
a++;
var b = 2, c = 3;
var a = 0, b = 1, c = (console.log(a), a++, b = 2, 3);
console.log(a, b, c);
}
expect_stdout: [
@@ -1183,3 +1371,26 @@ assign_sequence_var: {
"1 2 3",
]
}
issue_5175: {
options = {
join_vars: true,
}
input: {
function log(f) {
console.log(f(), A.p);
}
log(function() {
return (A = {}).p = "PASS";
});
}
expect: {
function log(f) {
console.log(f(), A.p);
}
log(function() {
return (A = {}).p = "PASS";
});
}
expect_stdout: "PASS PASS"
}

View File

@@ -181,10 +181,10 @@ issue_2203_2: {
a: "FAIL",
b: function() {
return function() {
return (String, (Object, function() {
return (Object, function() {
return this;
}())).a;
}();
}()).a;
}(String);
}
}.b());
}
@@ -925,6 +925,28 @@ duplicate_lambda_defun_name_2: {
expect_stdout: "0"
}
function_argument_mangle: {
mangle = {
keep_fargs: true,
toplevel: true,
}
input: {
A = "PASS";
var a = A;
(function(o) {
console.log(a);
})("FAIL");
}
expect: {
A = "PASS";
var n = A;
(function(o) {
console.log(n);
})("FAIL");
}
expect_stdout: "PASS"
}
function_name_mangle: {
options = {
keep_fargs: false,
@@ -1217,6 +1239,7 @@ issues_3267_1: {
evaluate: true,
inline: true,
keep_fargs: false,
negate_iife: true,
reduce_vars: true,
sequences: true,
side_effects: true,

View File

@@ -111,6 +111,7 @@ labels_5: {
labels_6: {
options = {
dead_code: true,
unused: true,
}
input: {
out: break out;
@@ -208,6 +209,59 @@ labels_10: {
expect_stdout: "PASS"
}
labels_11: {
options = {
conditionals: true,
if_return: true,
unused: true,
}
input: {
L: if (console.log("PASS"))
break L;
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
}
labels_12: {
options = {
conditionals: true,
dead_code: true,
if_return: true,
}
input: {
L: try {
if (console.log("foo"))
break L;
throw "bar";
} catch (e) {
console.log(e);
break L;
} finally {
if (console.log("baz"))
break L;
}
}
expect: {
L: try {
if (!console.log("foo"))
throw "bar";
} catch (e) {
console.log(e);
} finally {
if (console.log("baz"))
break L;
}
}
expect_stdout: [
"foo",
"bar",
"baz",
]
}
issue_4466_1: {
mangle = {
v8: false,
@@ -327,3 +381,53 @@ issue_4466_2_toplevel_v8: {
}
expect_stdout: "PASS"
}
issue_5522: {
options = {
dead_code: true,
}
input: {
console.log(function() {
L: try {
return "FAIL";
} finally {
break L;
}
return "PASS";
}());
}
expect: {
console.log(function() {
L: try {
return "FAIL";
} finally {
break L;
}
return "PASS";
}());
}
expect_stdout: "PASS"
}
issue_5524: {
options = {
dead_code: true,
}
input: {
L: try {
FAIL;
} finally {
break L;
}
console.log("PASS");
}
expect: {
L: try {
FAIL;
} finally {
break L;
}
console.log("PASS");
}
expect_stdout: "PASS"
}

View File

@@ -1,4 +1,4 @@
retain_block: {
retain_block_1: {
options = {}
input: {
"use strict";
@@ -20,6 +20,94 @@ retain_block: {
node_version: ">=4"
}
retain_block_2: {
options = {
toplevel: true,
unused: true,
}
input: {
"use strict";
{
var a;
let a;
}
}
expect: {
"use strict";
{
var a;
let a;
}
}
expect_stdout: true
node_version: ">=4"
}
retain_block_2_mangle: {
rename = true
mangle = {
toplevel: true,
}
input: {
"use strict";
{
var a;
let a;
}
}
expect: {
"use strict";
{
var t;
let t;
}
}
}
retain_block_3: {
options = {
toplevel: true,
unused: true,
}
input: {
"use strict";
{
let a;
var a;
}
}
expect: {
"use strict";
{
let a;
var a;
}
}
expect_stdout: true
node_version: ">=4"
}
retain_block_3_mangle: {
rename = true
mangle = {
toplevel: true,
}
input: {
"use strict";
{
let a;
var a;
}
}
expect: {
"use strict";
{
let t;
var t;
}
}
}
retain_assignment: {
options = {
dead_code: true,
@@ -102,6 +190,96 @@ if_dead_branch: {
node_version: ">=4"
}
retain_tail_1: {
options = {
conditionals: true,
}
input: {
"use strict";
function f(a) {
var b = "foo";
if (a) {
let b = "bar";
while (console.log("baz"));
console.log(b);
} else {
while (console.log("moo"));
console.log(b);
}
}
f();
f(42);
}
expect: {
"use strict";
function f(a) {
var b = "foo";
if (a) {
let b = "bar";
while (console.log("baz"));
console.log(b);
} else {
while (console.log("moo"));
console.log(b);
}
}
f();
f(42);
}
expect_stdout: [
"moo",
"foo",
"baz",
"bar",
]
node_version: ">=4"
}
retain_tail_2: {
options = {
conditionals: true,
}
input: {
"use strict";
function f(a) {
var b = "foo";
if (a) {
while (console.log("bar"));
console.log(b);
} else {
let b = "baz";
while (console.log("moo"));
console.log(b);
}
}
f();
f(42);
}
expect: {
"use strict";
function f(a) {
var b = "foo";
if (a) {
while (console.log("bar"));
console.log(b);
} else {
let b = "baz";
while (console.log("moo"));
console.log(b);
}
}
f();
f(42);
}
expect_stdout: [
"moo",
"baz",
"bar",
"foo",
]
node_version: ">=4"
}
merge_vars_1: {
options = {
merge_vars: true,
@@ -182,8 +360,8 @@ merge_vars_3: {
var b = console;
console.log(typeof b);
}
var a = 1;
console.log(typeof a);
var b = 1;
console.log(typeof b);
}
expect_stdout: [
"object",
@@ -192,6 +370,38 @@ merge_vars_3: {
node_version: ">=4"
}
merge_vars_4: {
options = {
merge_vars: true,
toplevel: true,
}
input: {
"use strict";
var a = 1;
console.log(typeof a);
{
var b = console;
console.log(typeof b);
let a = 0;
}
}
expect: {
"use strict";
var a = 1;
console.log(typeof a);
{
var b = console;
console.log(typeof b);
let a = 0;
}
}
expect_stdout: [
"number",
"object",
]
node_version: ">=4"
}
use_before_init_1: {
options = {
evaluate: true,
@@ -772,6 +982,40 @@ if_return_2: {
node_version: ">=4"
}
if_return_3: {
options = {
if_return: true,
}
input: {
"use strict";
var a = "PASS";
function f(b) {
if (console) {
let b = a;
return b;
} else
while (console.log("FAIL 1"));
return b;
}
console.log(f("FAIL 2"));
}
expect: {
"use strict";
var a = "PASS";
function f(b) {
if (console) {
let b = a;
return b;
} else
while (console.log("FAIL 1"));
return b;
}
console.log(f("FAIL 2"));
}
expect_stdout: "PASS"
node_version: ">=4"
}
do_if_continue_1: {
options = {
if_return: true,
@@ -792,8 +1036,7 @@ do_if_continue_1: {
expect: {
"use strict";
do {
if (!console);
else {
if (console) {
console.log("PASS");
{
let a = 0;
@@ -826,8 +1069,7 @@ do_if_continue_2: {
expect: {
"use strict";
do {
if (!console);
else {
if (console) {
console.log("FAIL");
{
let a = 0;
@@ -966,12 +1208,10 @@ issue_4202: {
"use strict";
{
let o = {};
(function() {
function f() {
o.p = 42;
}
f(f);
})();
function f() {
o.p = 42;
}
f(f);
console.log(o.p++);
}
}
@@ -1488,48 +1728,6 @@ issue_4305_2: {
node_version: ">=4"
}
issue_1753: {
mangle = {
toplevel: false,
webkit: true,
}
input: {
"use strict";
let l = null;
for (let i = 0; i < 1; i++)
console.log(i);
}
expect: {
"use strict";
let l = null;
for (let i = 0; i < 1; i++)
console.log(i);
}
expect_stdout: "0"
node_version: ">=4"
}
issue_1753_toplevel: {
mangle = {
toplevel: true,
webkit: true,
}
input: {
"use strict";
let l = null;
for (let i = 0; i < 1; i++)
console.log(i);
}
expect: {
"use strict";
let l = null;
for (let e = 0; e < 1; e++)
console.log(e);
}
expect_stdout: "0"
node_version: ">=4"
}
issue_4438: {
options = {
if_return: true,
@@ -1549,9 +1747,7 @@ issue_4438: {
expect: {
"use strict";
function f() {
if (!console)
;
else {
if (console) {
let a = console.log;
a("PASS");
}
@@ -1639,6 +1835,7 @@ issue_4689: {
issue_4691: {
options = {
conditionals: true,
if_return: true,
toplevel: true,
}
@@ -1747,3 +1944,229 @@ issue_4985: {
expect_stdout: "undefined"
node_version: ">=4"
}
issue_5240: {
options = {
inline: true,
}
input: {
"use strict";
function f() {
if (console) {
let g = function() {
e;
}, e;
(function() {
if (console) {
console.log(e);
var e = "FAIL";
}
})(console.log(e));
}
}
f();
}
expect: {
"use strict";
function f() {
if (console) {
let g = function() {
e;
}, e;
(function() {
if (console) {
console.log(e);
var e = "FAIL";
}
})(console.log(e));
}
}
f();
}
expect_stdout: [
"undefined",
"undefined",
]
node_version: ">=4"
}
issue_5254: {
options = {
inline: true,
toplevel: true,
}
input: {
"use strict";
do {
(function() {
let a = console.log;
a && a("foo");
})();
} while (console.log("bar"));
}
expect: {
"use strict";
do {
let a = console.log;
a && a("foo");
} while (console.log("bar"));
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=4"
}
issue_5260: {
options = {
collapse_vars: true,
}
input: {
"use strict";
var a = "foo", o;
while (console.log("bar"));
o = {
baz: function(b) {
console.log(a, b);
},
};
for (let a in o)
o[a](a);
}
expect: {
"use strict";
var a = "foo", o;
while (console.log("bar"));
o = {
baz: function(b) {
console.log(a, b);
},
};
for (let a in o)
o[a](a);
}
expect_stdout: [
"bar",
"foo baz",
]
node_version: ">=4"
}
issue_5319: {
options = {
collapse_vars: true,
merge_vars: true,
}
input: {
"use strict";
(function(a, c) {
var b = a, c = b;
{
let a = c;
console.log(c());
}
})(function() {
return "PASS";
});
}
expect: {
"use strict";
(function(a, c) {
var b = a, c;
{
let a = c = b;
console.log(c());
}
})(function() {
return "PASS";
});
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5338: {
options = {
unused: true,
}
input: {
"use strict";
let a = a;
}
expect: {
"use strict";
a;
let a;
}
expect_stdout: ReferenceError("a is not defined")
node_version: ">=4"
}
issue_5476: {
mangle = {
keep_fargs: true,
}
input: {
"use strict";
console.log(function(n) {
let a;
}());
}
expect: {
"use strict";
console.log(function(n) {
let o;
}());
}
expect_stdout: "undefined"
node_version: ">=4"
}
issue_5591: {
options = {
dead_code: true,
if_return: true,
}
input: {
"use strict";
function f(a) {
switch (console.log("foo")) {
case console.log("bar"):
if (console.log("baz"))
return;
else {
let a;
return;
}
break;
case null:
FAIL;
}
}
f();
}
expect: {
"use strict";
function f(a) {
switch (console.log("foo")) {
case console.log("bar"):
if (console.log("baz"))
return;
else {
let a;
return;
}
case null:
FAIL;
}
}
f();
}
expect_stdout: [
"foo",
"bar",
"baz",
]
node_version: ">=4"
}

View File

@@ -37,6 +37,51 @@ just_enough: {
expect_warnings: []
}
drop_semicolon: {
beautify = {
max_line_len: 5,
semicolons: true,
}
input: {
var a;
console.log(a || 42);
}
expect_exact: [
"var a",
"console.log(",
"a||42",
");",
]
expect_stdout: "42"
expect_warnings: [
"WARN: Output exceeds 5 characters",
]
}
template_newline: {
beautify = {
max_line_len: 2,
}
input: {
console.log(`foo
bar`);
}
expect_exact: [
"console.log(",
"`foo",
"bar`",
");",
]
expect_stdout: [
"foo",
"bar",
]
expect_warnings: [
"WARN: Output exceeds 2 characters",
]
node_version: ">=4"
}
issue_304: {
beautify = {
max_line_len: 10,

File diff suppressed because it is too large Load Diff

View File

@@ -122,13 +122,41 @@ negate_iife_4: {
sequences: true,
}
input: {
(function(){ return t })() ? console.log(true) : console.log(false);
(function(){
(function() {
return t;
})() ? console.log(true) : console.log(false);
(function() {
console.log("something");
})();
}
expect: {
!function(){ return t }() ? console.log(false) : console.log(true), function(){
!function() {
return t;
}() ? console.log(false) : console.log(true), !function() {
console.log("something");
}();
}
}
negate_iife_4_drop_side_effect_free: {
options = {
conditionals: true,
negate_iife: true,
sequences: true,
side_effects: true,
}
input: {
(function() {
return t;
})() ? console.log(true) : console.log(false);
(function() {
console.log("something");
})();
}
expect: {
!function() {
return t;
}() ? console.log(false) : console.log(true), function() {
console.log("something");
}();
}
@@ -176,17 +204,49 @@ negate_iife_5: {
sequences: true,
}
input: {
if ((function(){ return t })()) {
if (function() {
return t;
}()) {
foo(true);
} else {
bar(false);
}
(function(){
(function() {
console.log("something");
})();
}
expect: {
!function(){ return t }() ? bar(false) : foo(true), function(){
!function() {
return t;
}() ? bar(false) : foo(true), !function() {
console.log("something");
}();
}
}
negate_iife_5_drop_side_effect_free: {
options = {
conditionals: true,
negate_iife: true,
sequences: true,
side_effects: true,
}
input: {
if (function() {
return t;
}()) {
foo(true);
} else {
bar(false);
}
(function() {
console.log("something");
})();
}
expect: {
!function() {
return t;
}() ? bar(false) : foo(true), function() {
console.log("something");
}();
}
@@ -389,6 +449,7 @@ issue_1288_side_effects: {
options = {
conditionals: true,
negate_iife: true,
sequences: true,
side_effects: true,
}
input: {
@@ -409,10 +470,10 @@ issue_1288_side_effects: {
})(0);
}
expect: {
w;
w,
x || function() {
x = {};
}();
}(),
y;
}
}

View File

@@ -262,6 +262,30 @@ de_morgan_2e: {
node_version: ">=14"
}
inline_binary_nullish: {
options = {
inline: true,
}
input: {
(function() {
while (console.log("foo"));
})() ?? (function() {
while (console.log("bar"));
})();
}
expect: {
if (null == function() {
while (console.log("foo"));
}())
while (console.log("bar"));
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=14"
}
issue_4679: {
options = {
comparisons: true,
@@ -280,3 +304,43 @@ issue_4679: {
expect_stdout: "PASS"
node_version: ">=14"
}
issue_5266: {
options = {
inline: true,
side_effects: true,
}
input: {
[
42,
null,
false,
void 0,
"FAIL",
].forEach(function (a) {
a ?? function() {
while (console.log(a));
}();
});
}
expect: {
[
42,
null,
false,
void 0,
"FAIL",
].forEach(function (a) {
if (null == a) {
while (console.log(a));
return;
} else
return;
});
}
expect_stdout: [
"null",
"undefined",
]
node_version: ">=14"
}

View File

@@ -842,9 +842,9 @@ unary_binary_parentheses: {
v.forEach(function(x) {
v.forEach(function(y) {
console.log(
+x*y,
+x/y,
+x%y,
x*y,
x/y,
x%y,
-x*y,
-x/y,
-x%y
@@ -1397,7 +1397,7 @@ issue_3695: {
}
expect: {
var a = [];
console.log(+(a * (a[0] = false)));
console.log(a * (a[0] = false));
}
expect_stdout: "NaN"
}

View File

@@ -521,3 +521,25 @@ issue_4415: {
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5213: {
options = {
objects: true,
}
input: {
var a = "FAIL";
console.log({
p: a = "PASS",
0: a,
p: null,
}[0]);
}
expect: {
var a = "FAIL";
console.log({
p: (a = "PASS", null),
0: a,
}[0]);
}
expect_stdout: "PASS"
}

View File

@@ -361,7 +361,9 @@ issue_4906: {
} while (console.log("PASS"));
}
expect: {
do {} while (console.log("PASS"));
do {
var a = a?.[42];
} while (console.log("PASS"));
}
expect_stdout: "PASS"
node_version: ">=14"
@@ -434,7 +436,7 @@ issue_5039: {
console.log("PASS");
}
expect: {
(function f() {});
var a = a?.[function f() {}];
console.log("PASS");
}
expect_stdout: "PASS"
@@ -455,14 +457,163 @@ issue_5091: {
console.log(f("FAIL 1") || "PASS");
}
expect: {
function f(b) {
var b = b.p;
function f(a) {
var a = a.p;
var c;
b?.[c = "FAIL 2"];
return b || c;
a?.[c = "FAIL 2"];
return a || c;
}
console.log(f("FAIL 1") || "PASS");
}
expect_stdout: "PASS"
node_version: ">=14"
}
issue_5292_dot: {
options = {
side_effects: true,
}
input: {
var o = {
get p() {
console.log("PASS");
}
};
o?.p;
}
expect: {
var o = {
get p() {
console.log("PASS");
}
};
o?.p;
}
expect_stdout: "PASS"
node_version: ">=14"
}
issue_5292_dot_pure_getters: {
options = {
pure_getters: true,
side_effects: true,
}
input: {
var o = {
get p() {
console.log("PASS");
}
};
o?.p;
}
expect: {
var o = {
get p() {
console.log("PASS");
}
};
}
}
issue_5292_dot_pure_getters_strict: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
var o = {
get p() {
console.log("PASS");
}
};
o?.p;
}
expect: {
var o = {
get p() {
console.log("PASS");
}
};
o?.p;
}
expect_stdout: "PASS"
node_version: ">=14"
}
issue_5292_sub: {
options = {
side_effects: true,
}
input: {
var o = {
get p() {
console.log("foo");
}
};
o?.[console.log("bar"), "p"];
}
expect: {
var o = {
get p() {
console.log("foo");
}
};
o?.[console.log("bar"), "p"];
}
expect_stdout: [
"bar",
"foo",
]
node_version: ">=14"
}
issue_5292_sub_pure_getters: {
options = {
pure_getters: true,
side_effects: true,
}
input: {
var o = {
get p() {
console.log("foo");
}
};
o?.[console.log("bar"), "p"];
}
expect: {
var o = {
get p() {
console.log("foo");
}
};
console.log("bar");
}
}
issue_5292_sub_pure_getters_strict: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
var o = {
get p() {
console.log("foo");
}
};
o?.[console.log("bar"), "p"];
}
expect: {
var o = {
get p() {
console.log("foo");
}
};
o?.[console.log("bar"), "p"];
}
expect_stdout: [
"bar",
"foo",
]
node_version: ">=14"
}

View File

@@ -97,10 +97,10 @@ return_5: {
}
expect_exact: [
"_is_selected=function(tags,slug){",
"var ref",
"var ref;",
"",
"",
";return null!=(ref=_.find(tags,{slug:slug}))?ref.selected:void 0};",
"return null!=(ref=_.find(tags,{slug:slug}))?ref.selected:void 0};",
]
}
@@ -146,10 +146,10 @@ return_7: {
}
expect_exact: [
"_is_selected=function(e,l){",
"var n",
"var n;",
"",
"",
";return null!=(n=_.find(e,{slug:l}))?n.selected:void 0};",
"return null!=(n=_.find(e,{slug:l}))?n.selected:void 0};",
]
}

View File

@@ -206,6 +206,7 @@ mangle_unquoted_properties: {
}
mangle = {
properties: {
builtins: true,
keep_quoted: true,
},
}
@@ -305,6 +306,7 @@ mangle_debug_suffix_keep_quoted: {
}
mangle = {
properties: {
builtins: true,
debug: "XYZ",
keep_quoted: true,
reserved: [],
@@ -351,6 +353,68 @@ mangle_debug_suffix_keep_quoted: {
}
}
keep_substituted_property: {
options = {
evaluate: true,
properties: true,
reduce_vars: true,
}
mangle = {
properties: {
keep_quoted: true,
},
}
input: {
var o = { p: [] };
function f(b) {
return o[b];
}
function g() {
var a = "p";
return o[a] === f(a);
}
console.log(g() ? "PASS" : "FAIL");
}
expect: {
var o = { p: [] };
function f(n) {
return o[n];
}
function g() {
var n = "p";
return o.p === f(n);
}
console.log(g() ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
}
keep_substituted_property_quotes: {
options = {
evaluate: true,
properties: true,
reduce_vars: true,
}
beautify = {
keep_quoted_props: true,
}
input: {
function f(o) {
var a = "p";
return o[a];
}
console.log(f({ p: "PASS" }));
}
expect: {
function f(o) {
var a = "p";
return o["p"];
}
console.log(f({ p: "PASS" }));
}
expect_stdout: "PASS"
}
first_256_chars_as_properties: {
beautify = {
ascii_only: true,
@@ -897,12 +961,15 @@ issue_2256: {
},
}
input: {
({ "keep": 1 });
g.keep = g.change;
({ "keep": 42 });
global.keep = global.change;
console.log(keep);
}
expect: {
g.keep = g.g;
global.keep = global.l;
console.log(keep);
}
expect_stdout: "undefined"
}
lhs_prop_1: {
@@ -1510,3 +1577,71 @@ issue_5093_quote_style: {
expect_exact: 'console.log({a:true,\'42\':"PASS","null":[]}[6*7]);'
expect_stdout: "PASS"
}
object_methods: {
options = {
properties: true,
}
input: {
({
p() {
console.log("FAIL 1");
},
*q() {
console.log("FAIL 2");
},
async r() {
console.log("FAIL 3");
},
async *s() {
console.log("PASS");
},
}).s().next();
}
expect: {
[
() => {
console.log("FAIL 1");
},
function*() {
console.log("FAIL 2");
},
async () => {
console.log("FAIL 3");
},
async function*() {
console.log("PASS");
},
][3]().next();
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5177: {
options = {
properties: true,
}
input: {
var a = "FAIL";
var o = { a: "PASS" };
o.p = {
q() {
return this.a;
},
}.q;
console.log(o.p());
}
expect: {
var a = "FAIL";
var o = { a: "PASS" };
o.p = {
q() {
return this.a;
},
}.q;
console.log(o.p());
}
expect_stdout: "PASS"
node_version: ">=4"
}

View File

@@ -147,7 +147,7 @@ relational: {
"bar" >= "bar";
}
expect: {
bar();
0 instanceof bar();
bar();
bar(), bar();
bar();

View File

@@ -1289,6 +1289,7 @@ issue_2878: {
collapse_vars: true,
pure_getters: true,
sequences: true,
side_effects: true,
}
input: {
var c = 0;
@@ -1363,9 +1364,8 @@ issue_3490_1: {
}
expect: {
var b = 42, c = "FAIL";
if (function() {
var a;
}(), c = "PASS", b) while ("" == typeof d);
var a;
if (c = "PASS", b) while ("" == typeof d);
console.log(c, b);
}
expect_stdout: "PASS 42"
@@ -1540,10 +1540,12 @@ this_toString: {
issue_4803: {
options = {
hoist_vars: true,
join_vars: true,
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var o = {
@@ -1640,6 +1642,26 @@ nested_property_assignments_3: {
expect_stdout: "PASS"
}
nested_property_assignments_4: {
options = {
pure_getters: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var n, o = { p: { q: { r: "PASS" } } };
(n = o.p).r = n.q.r;
console.log(o.p.r);
}
expect: {
var n, o = { p: { q: { r: "PASS" } } };
(n = o.p).r = n.q.r;
console.log(o.p.r);
}
expect_stdout: "PASS"
}
issue_4939: {
options = {
pure_getters: "strict",

View File

@@ -6,6 +6,7 @@ reduce_vars: {
C: 0,
},
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
@@ -41,10 +42,8 @@ reduce_vars: {
}
expect: {
var A = 1;
(function() {
console.log(-3);
console.log(A - 5);
})();
console.log(-3);
console.log(A - 5);
(function f1() {
var a = 2;
console.log(a - 5);
@@ -905,7 +904,7 @@ use_before_var: {
}
expect: {
function f(){
console.log(void 0);
console.log(t);
var t = 1;
}
}
@@ -981,7 +980,7 @@ inner_var_for_1: {
expect: {
function f() {
var a = 1;
x(1, void 0, d);
x(1, b, d);
for (var b = 2, c = 3; x(1, 2, 3, d); x(1, 2, 3, d)) {
var d = 4, e = 5;
x(1, 2, 3, d, e);
@@ -2489,7 +2488,7 @@ side_effects_assign: {
console.log(a);
}
expect: {
var a = typeof void (a && a.in);
var a = "undefined";
console.log(a);
}
expect_stdout: "undefined"
@@ -2531,7 +2530,8 @@ pure_getters_2: {
var a = a && a.b;
}
expect: {
var a = a && a.b;
var a;
a && a.b;
}
}
@@ -5425,7 +5425,7 @@ issue_2774: {
get a() {
var b;
(b = true) && b.c;
b = void 0;
void 0;
}
}.a);
}
@@ -6671,6 +6671,7 @@ issues_3267_1: {
dead_code: true,
evaluate: true,
inline: true,
negate_iife: true,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -6688,7 +6689,7 @@ issues_3267_1: {
});
}
expect: {
!function(i) {
!function(x) {
if (Object())
return console.log("PASS");
throw "FAIL";
@@ -6705,6 +6706,7 @@ issues_3267_2: {
evaluate: true,
inline: true,
keep_fargs: false,
negate_iife: true,
passes: 2,
reduce_vars: true,
sequences: true,
@@ -7320,6 +7322,64 @@ local_assignment_loop: {
expect_stdout: "PASS"
}
local_assignment_modified: {
options = {
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a;
(a = a || {}).p = 42;
console.log(a.p);
}
expect: {
var a;
(a = {}).p = 42;
console.log(a.p);
}
expect_stdout: "42"
}
local_declaration: {
options = {
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a;
a || console.log(a = "PASS");
}
expect: {
var a;
console.log("PASS");
}
expect_stdout: "PASS"
}
local_definition_modified: {
options = {
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a = a || {};
a.p = 42;
console.log(a.p);
}
expect: {
var a = {};
a.p = 42;
console.log(a.p);
}
expect_stdout: "42"
}
issue_3957_1: {
options = {
evaluate: true,
@@ -7435,6 +7495,7 @@ issue_4030: {
collapse_vars: true,
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
@@ -7772,3 +7833,97 @@ issue_5055_2: {
}
expect_stdout: "PASS"
}
issue_5324: {
options = {
inline: true,
merge_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
A = 0;
do {
var a, b = A;
for (a in b)
var c = b;
} while (function() {
var d;
console.log(d *= A);
}());
}
expect: {
A = 0;
do {
var a, b = A;
for (a in b);
} while (b = void 0, void console.log(b *= A));
}
expect_stdout: "NaN"
}
issue_5434: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function(a) {
for (var i = 0; i < 2; i++) {
var b = "FAIL";
f && f();
a = b;
var f = function() {
b = "PASS";
};
}
return a;
}());
}
expect: {
console.log(function(a) {
for (var i = 0; i < 2; i++) {
var b = "FAIL";
f && f();
a = b;
var f = function() {
b = "PASS";
};
}
return a;
}());
}
expect_stdout: "PASS"
}
issue_5623: {
options = {
collapse_vars: true,
evaluate: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a = 0;
function f() {
var b = a;
a = b;
}
f && f((a++ && a).toString());
console.log(a);
}
expect: {
var a = 0;
function f() {
var b;
a = a;
}
f((a++ && a).toString());
console.log(a);
}
expect_stdout: "1"
}

View File

@@ -50,6 +50,22 @@ regexp_properties: {
expect_stdout: "abc true false 0 false"
}
instanceof_1: {
input: {
console.log(/foo/ instanceof RegExp);
}
expect_exact: "console.log(/foo/ instanceof RegExp);"
expect_stdout: "true"
}
instanceof_2: {
input: {
console.log(42 + /foo/ instanceof Object);
}
expect_exact: "console.log(42+/foo/ instanceof Object);"
expect_stdout: "false"
}
issue_3434_1: {
options = {
evaluate: true,

View File

@@ -51,7 +51,7 @@ arrow_destructured_object_1: {
}
expect_exact: "var f=({...a})=>a,o=f({PASS:42});for(var k in o)console.log(k,o[k]);"
expect_stdout: "PASS 42"
node_version: ">=8"
node_version: ">=8.3.0"
}
arrow_destructured_object_2: {
@@ -62,7 +62,7 @@ arrow_destructured_object_2: {
}
expect_exact: "var f=({FAIL:a,...b})=>b,o=f({PASS:42,FAIL:null});for(var k in o)console.log(k,o[k]);"
expect_stdout: "PASS 42"
node_version: ">=8"
node_version: ">=8.3.0"
}
arrow_destructured_object_3: {
@@ -79,7 +79,7 @@ arrow_destructured_object_3: {
"2 S",
"3 S",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
funarg_1: {
@@ -131,7 +131,7 @@ destructured_object_1: {
}
expect_exact: 'var{...a}=["FAIL","PASS",42];console.log(a[1],a[2]);'
expect_stdout: "PASS 42"
node_version: ">=8"
node_version: ">=8.3.0"
}
destructured_object_2: {
@@ -141,7 +141,7 @@ destructured_object_2: {
}
expect_exact: 'var{0:a,...b}=["FAIL","PASS",42];console.log(b[1],b[2]);'
expect_stdout: "PASS 42"
node_version: ">=8"
node_version: ">=8.3.0"
}
drop_fargs: {
@@ -231,7 +231,7 @@ reduce_destructured_object: {
console.log(a[0]);
}
expect_stdout: "PASS"
node_version: ">=8"
node_version: ">=8.3.0"
}
retain_destructured_array: {
@@ -270,7 +270,7 @@ retain_destructured_object_1: {
"1 PASS",
"2 42",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
retain_destructured_object_2: {
@@ -292,7 +292,7 @@ retain_destructured_object_2: {
"bar PASS",
"baz 42",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
retain_funarg_destructured_array_1: {
@@ -344,11 +344,12 @@ retain_funarg_destructured_object_1: {
console.log((({ ...a }) => a)([ "PASS" ])[0]);
}
expect_stdout: "PASS"
node_version: ">=8"
node_version: ">=8.3.0"
}
retain_funarg_destructured_object_2: {
options = {
keep_fargs: false,
unused: true,
}
input: {
@@ -359,10 +360,10 @@ retain_funarg_destructured_object_2: {
expect: {
console.log(function({ p: a, ... b }) {
return b;
}({ p: "FAIL" }).p || "PASS");
}({}).p || "PASS");
}
expect_stdout: "PASS"
node_version: ">=8"
node_version: ">=8.3.0"
}
drop_unused_call_args_1: {
@@ -436,9 +437,9 @@ merge_funarg: {
})();
}
expect: {
(function(...b) {
var b = b.length;
console.log(b);
(function(...a) {
var a = a.length;
console.log(a);
})();
}
expect_stdout: "0"
@@ -456,9 +457,9 @@ merge_funarg_destructured_array: {
})([]);
}
expect: {
(function([ ...b ]) {
var b = b.length;
console.log(b);
(function([ ...a ]) {
var a = a.length;
console.log(a);
})([]);
}
expect_stdout: "0"
@@ -476,13 +477,13 @@ merge_funarg_destructured_object: {
})([ "PASS" ]);
}
expect: {
(function({ ...b }) {
var b = b[0];
console.log(b);
(function({ ...a }) {
var a = a[0];
console.log(a);
})([ "PASS" ]);
}
expect_stdout: "PASS"
node_version: ">=8"
node_version: ">=8.3.0"
}
keep_arguments: {
@@ -647,7 +648,7 @@ drop_new_function: {
}
expect: {
void ([ ... {
[console.log("PASS")]: [].e,
[console.log("PASS")]: [][0],
}] = []);
}
expect_stdout: "PASS"
@@ -866,9 +867,9 @@ issue_4575: {
}
expect: {
(function(a) {
(function a(...d) {
(function(d) {
console.log(d.length);
})();
})([]);
})();
}
expect_stdout: "0"
@@ -992,7 +993,7 @@ issue_5089_1: {
console.log(o.p);
}
expect_stdout: "undefined"
node_version: ">=8"
node_version: ">=8.3.0"
}
issue_5089_2: {
@@ -1019,7 +1020,7 @@ issue_5089_2: {
console.log(o.p);
}
expect_stdout: "undefined"
node_version: ">=8"
node_version: ">=8.3.0"
}
issue_5100_1: {
@@ -1044,17 +1045,19 @@ issue_5100_1: {
}
expect: {
var a;
[ {
({
p: {},
...a
} ] = [ {
p: [ a = 42["q"] ],
} = [ {
p: {
q: a,
} = 42,
r: "PASS",
} ];
} ][0]);
console.log(a.r);
}
expect_stdout: "PASS"
node_version: ">=8"
node_version: ">=8.3.0"
}
issue_5100_2: {
@@ -1077,20 +1080,23 @@ issue_5100_2: {
}
expect: {
var a;
[ {
({
p: {},
...a
} ] = [ {
p: [ console.log("PASS"), a = 42["q"] ],
} ];
} = [ {
p: (console.log("PASS"), {
q: a,
} = 42),
} ][0]);
}
expect_stdout: "PASS"
node_version: ">=10"
node_version: ">=10.22.0"
}
issue_5108: {
options = {
evaluate: true,
keep_fargs: false,
reduce_vars: true,
rests: true,
unsafe: true,
@@ -1102,9 +1108,7 @@ issue_5108: {
}([ "PASS", "FAIL" ]));
}
expect: {
console.log(function([]) {
return "PASS";
}([ "PASS", "FAIL" ]));
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
@@ -1151,3 +1155,472 @@ issue_5128_2: {
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5165_1: {
options = {
conditionals: true,
dead_code: true,
evaluate: true,
reduce_vars: true,
rests: true,
side_effects: true,
switches: true,
unsafe: true,
}
input: {
console.log(function([ ...a ]) {
switch (a) {
case a:
return "PASS";
}
}([]));
}
expect: {
console.log(function([ ...a ]) {
return "PASS";
}([]));
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5165_2: {
options = {
conditionals: true,
dead_code: true,
evaluate: true,
reduce_vars: true,
rests: true,
side_effects: true,
switches: true,
unsafe: true,
}
input: {
console.log(function(...a) {
switch (a) {
case a:
return "PASS";
}
}());
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5246_1: {
options = {
keep_fargs: false,
reduce_vars: true,
rests: true,
unused: true,
}
input: {
console.log(typeof function([ , ...a ]) {
return this && a;
}([ , function(){} ])[0]);
}
expect: {
console.log(typeof function() {
return this && [ function(){} ];
}()[0]);
}
expect_stdout: "function"
node_version: ">=6"
}
issue_5246_2: {
options = {
keep_fargs: false,
reduce_vars: true,
rests: true,
toplevel: true,
unused: true,
}
input: {
A = [ , "PASS", "FAIL" ];
var [ , ...a ] = [ ... A ];
console.log(a[0]);
}
expect: {
A = [ , "PASS", "FAIL" ];
var [ , ...a ] = [ ... A ];
console.log(a[0]);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5246_3: {
options = {
keep_fargs: false,
unused: true,
}
input: {
(function f(...[ [ a ] ]) {
console.log(a);
})([ "PASS" ]);
}
expect: {
(function(...[ a ]) {
console.log(a);
})([ "PASS" ][0]);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5360: {
options = {
keep_fargs: false,
pure_getters: "strict",
unused: true,
}
input: {
var a;
console.log(function({ p: {}, ...b }) {
return b.q;
}({
p: ~a && ([ a ] = []),
q: "PASS",
}));
}
expect: {
var a;
console.log(function({ p: {}, ...b }) {
return b.q;
}({
p: ~a && ([ a ] = []),
q: "PASS",
}));
}
expect_stdout: "PASS"
node_version: ">=8.3.0"
}
issue_5370: {
options = {
dead_code: true,
ie: true,
unused: true,
}
input: {
console.log(function arguments(...a) {
return arguments;
try {} catch (e) {
var arguments;
}
}());
}
expect: {
console.log(function arguments(...a) {
return arguments;
var arguments;
}());
}
expect_stdout: true
node_version: ">=6"
}
issue_5391: {
options = {
evaluate: true,
keep_fargs: false,
objects: true,
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a, b = function f({
p: {},
...c
}) {
while (c.q);
}({
p: {
r: a++,
r: 0,
}
});
console.log(a);
}
expect: {
(function({
p: {},
...c
}) {
while (c.q);
})({
p: 0,
});
console.log(NaN);
}
expect_stdout: "NaN"
node_version: ">=8.3.0"
}
issue_5533_1_keep_fargs: {
options = {
evaluate: true,
inline: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
}
input: {
"use strict";
try {
(function() {
var a;
for (; 1;)
a = function() {
(function f(...b) {
b;
throw "PASS";
})();
}();
})();
} catch (e) {
console.log(e);
}
}
expect: {
"use strict";
try {
(function() {
for (;;)
throw "PASS";
})();
} catch (e) {
console.log(e);
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5533_1_drop_fargs: {
options = {
evaluate: true,
inline: true,
join_vars: true,
keep_fargs: false,
loops: true,
side_effects: true,
unused: true,
}
input: {
"use strict";
try {
(function() {
var a;
for (; 1;)
a = function() {
(function f(...b) {
b;
throw "PASS";
})();
}();
})();
} catch (e) {
console.log(e);
}
}
expect: {
"use strict";
try {
(function() {
for (;;)
throw "PASS";
})();
} catch (e) {
console.log(e);
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5533_2_keep_fargs: {
options = {
evaluate: true,
inline: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
}
input: {
"use strict";
try {
(function() {
var a;
for (; 1;)
a = function() {
(function f(...[ b ]) {
b;
throw "PASS";
})();
}();
})();
} catch (e) {
console.log(e);
}
}
expect: {
"use strict";
try {
(function() {
for (;;)
throw "PASS";
})();
} catch (e) {
console.log(e);
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5533_2_drop_fargs: {
options = {
evaluate: true,
inline: true,
join_vars: true,
keep_fargs: false,
loops: true,
side_effects: true,
unused: true,
}
input: {
"use strict";
try {
(function() {
var a;
for (; 1;)
a = function() {
(function f(...[ b ]) {
b;
throw "PASS";
})();
}();
})();
} catch (e) {
console.log(e);
}
}
expect: {
"use strict";
try {
(function() {
for (;;)
throw "PASS";
})();
} catch (e) {
console.log(e);
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5552_1: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var a = f, b = log();
function f(...[ c = a = "PASS" ]) {}
f((a = "FAIL", b));
log(a);
}
expect: {
var log = console.log;
var a = f, b = log();
function f(...[ c = a = "PASS" ]) {}
f((a = "FAIL", b));
log(a);
}
expect_stdout: [
"",
"PASS",
]
node_version: ">=6"
}
issue_5552_2: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var a = f;
function f(...{ [a = "PASS"]: b }) {}
f((a = "FAIL", 42));
log(a);
}
expect: {
var log = console.log;
var a = f;
function f(...{ [a = "PASS"]: b }) {}
f((a = "FAIL", 42));
log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5552_3: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var a = [ "FAIL", "PASS" ];
console.log(function(b, ...[ c = a.pop() ]) {
return b;
}(a.pop()));
}
expect: {
var a = [ "FAIL", "PASS" ];
console.log(function(b, ...[ c = a.pop() ]) {
return b;
}(a.pop()));
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5552_4: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var a = [ "FAIL", "PASS" ];
console.log(function(b, ...{ [a.pop()]: c }) {
return b;
}(a.pop()));
}
expect: {
var a = [ "FAIL", "PASS" ];
console.log(function(b, ...{ [a.pop()]: c }) {
return b;
}(a.pop()));
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -201,3 +201,20 @@ issue_4811_2: {
expect_stdout: "PASS [object global] true"
node_version: ">=8"
}
issue_5197: {
rename = true
input: {
function f(async) {
async(")=>{}");
}
console.log("" + this.__proto__);
}
expect: {
function f(a) {
a(")=>{}");
}
console.log("" + this.__proto__);
}
expect_stdout: "[object global]"
}

View File

@@ -289,8 +289,34 @@ iife: {
typeof function g() {}();
}
expect: {
x = 42, function a() {}(), function b() {}(), function c() {}(),
function d() {}(), function e() {}(), function f() {}(), function g() {}();
x = 42,
function a() {}(),
!function b() {}(),
~function c() {}(),
+function d() {}(),
-function e() {}(),
void function f() {}(),
typeof function g() {}();
}
}
iife_drop_side_effect_free: {
options = {
sequences: true,
side_effects: true,
}
input: {
x = 42;
(function a() {})();
!function b() {}();
~function c() {}();
+function d() {}();
-function e() {}();
void function f() {}();
typeof function g() {}();
}
expect: {
x = 42;
}
}
@@ -774,7 +800,7 @@ side_effects_cascade_3: {
}
expect: {
function f(a, b) {
(b += a) || (b = a) || (b -= a, b ^= a),
(b += a) || (b = a) || (b = b - a ^ a),
a--;
}
}
@@ -910,9 +936,7 @@ hoist_decl: {
var d;
}
expect: {
var a;
w();
var b = x(), c, d;
var a, b = (w(), x()), c, d;
for (y(); 0;) z();
}
}
@@ -1047,11 +1071,102 @@ call: {
b.c = function() {
console.log(this === b ? "bar" : "baz");
},
a,
b(),
a,
b.c(),
(a, b.c)(),
a,
b["c"](),
(a, b["c"])(),
a,
function() {
console.log(this === a);
}(),
a,
new b(),
a,
new b.c(),
a,
new b.c(),
a,
new b["c"](),
a,
new b["c"](),
a,
new function() {
console.log(this === a);
}(),
console.log((a, typeof b.c)),
console.log((a, typeof b["c"]));
}
expect_stdout: [
"foo",
"bar",
"baz",
"bar",
"baz",
"true",
"foo",
"baz",
"baz",
"baz",
"baz",
"false",
"function",
"function",
]
}
call_drop_side_effect_free: {
options = {
sequences: true,
side_effects: true,
}
input: {
var a = function() {
return this;
}();
function b() {
console.log("foo");
}
b.c = function() {
console.log(this === b ? "bar" : "baz");
};
(a, b)();
(a, b).c();
(a, b.c)();
(a, b)["c"]();
(a, b["c"])();
(a, function() {
console.log(this === a);
})();
new (a, b)();
new (a, b).c();
new (a, b.c)();
new (a, b)["c"]();
new (a, b["c"])();
new (a, function() {
console.log(this === a);
})();
console.log(typeof (a, b).c);
console.log(typeof (a, b)["c"]);
}
expect: {
var a = function() {
return this;
}();
function b() {
console.log("foo");
}
b.c = function() {
console.log(this === b ? "bar" : "baz");
},
b(),
b.c(),
(0, b.c)(),
b["c"](),
(0, b["c"])(),
function() {
console.log(this === a);
}(),
@@ -1063,8 +1178,8 @@ call: {
new function() {
console.log(this === a);
}(),
console.log((a, typeof b.c)),
console.log((a, typeof b["c"]));
console.log(typeof b.c),
console.log(typeof b["c"]);
}
expect_stdout: [
"foo",
@@ -1099,6 +1214,26 @@ missing_link: {
expect: {
var a = 100;
a,
a++ + (0, 1),
console.log(a);
}
}
missing_link_drop_side_effect_free: {
options = {
conditionals: true,
evaluate: true,
sequences: true,
side_effects: true,
}
input: {
var a = 100;
a;
a++ + (0 ? 2 : 1);
console.log(a);
}
expect: {
var a = 100;
a++,
console.log(a);
}
@@ -1162,10 +1297,8 @@ issue_3490_1: {
}
expect: {
var b = 42, c = "FAIL";
if (function() {
var a;
a && a.p;
}(), c = "PASS", b) while ("" == typeof d);
var a;
if (a && a.p, c = "PASS", b) while ("" == typeof d);
console.log(c, b);
}
expect_stdout: "PASS 42"
@@ -1195,9 +1328,8 @@ issue_3490_2: {
}
expect: {
var b = 42, c = "FAIL";
for (function() {
var a;
}(), c = "PASS", b; "" == typeof d;);
var a;
for (c = "PASS"; "" == typeof d;);
console.log(c, b);
}
expect_stdout: "PASS 42"

View File

@@ -318,6 +318,32 @@ unsafe_string_replace: {
expect_stdout: "PASS"
}
unsafe_Object_call: {
options = {
side_effects: true,
unsafe: true,
}
input: {
var o = {
f: function(a) {
console.log(a ? this.p : "FAIL 1");
},
p: "FAIL 2",
}, p = "PASS";
Object(o.f)(42);
}
expect: {
var o = {
f: function(a) {
console.log(a ? this.p : "FAIL 1");
},
p: "FAIL 2",
}, p = "PASS";
(0, o.f)(42);
}
expect_stdout: "PASS"
}
drop_value: {
options = {
side_effects: true,
@@ -617,7 +643,7 @@ issue_4730_2: {
}
expect: {
var a;
!console.log("PASS") || a && a[a.p];
console.log("PASS") && a && a[a.p];
}
expect_stdout: "PASS"
}
@@ -645,3 +671,56 @@ issue_4751: {
}
expect_stdout: "PASS"
}
drop_instanceof: {
options = {
side_effects: true,
}
input: {
42 instanceof function() {};
console.log("PASS");
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
}
drop_instanceof_reference: {
options = {
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
function f() {}
42 instanceof f;
console.log("PASS");
}
expect: {
function f() {}
console.log("PASS");
}
expect_stdout: "PASS"
}
retain_instanceof: {
options = {
side_effects: true,
}
input: {
try {
42 instanceof "foo";
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
0 instanceof "foo";
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
}

View File

@@ -1,15 +1,24 @@
decimal: {
input: {
console.log({... 0.42});
}
expect_exact: "console.log({....42});"
expect_stdout: "{}"
node_version: ">=8.3.0"
}
collapse_vars_1: {
options = {
collapse_vars: true,
}
input: {
var a;
[ ...a = "PASS", "PASS"].slice();
[ ...a = "PASS", "PASS" ].slice();
console.log(a);
}
expect: {
var a;
[ ...a = "PASS", "PASS"].slice();
[ ...a = "PASS", "PASS" ].slice();
console.log(a);
}
expect_stdout: "PASS"
@@ -24,7 +33,7 @@ collapse_vars_2: {
var a = "FAIL";
try {
a = "PASS";
[ ...42, "PASS"].slice();
[ ...42, "PASS" ].slice();
} catch (e) {
console.log(a);
}
@@ -33,7 +42,7 @@ collapse_vars_2: {
var a = "FAIL";
try {
a = "PASS";
[ ...42, "PASS"].slice();
[ ...42, "PASS" ].slice();
} catch (e) {
console.log(a);
}
@@ -49,7 +58,7 @@ collapse_vars_3: {
input: {
var a = "FAIL";
try {
[ ...(a = "PASS", 42), "PASS"].slice();
[ ...(a = "PASS", 42), "PASS" ].slice();
} catch (e) {
console.log(a);
}
@@ -57,7 +66,7 @@ collapse_vars_3: {
expect: {
var a = "FAIL";
try {
[ ...(a = "PASS", 42), "PASS"].slice();
[ ...(a = "PASS", 42), "PASS" ].slice();
} catch (e) {
console.log(a);
}
@@ -147,7 +156,7 @@ dont_inline: {
node_version: ">=6"
}
do_inline: {
do_inline_1: {
options = {
inline: true,
spreads: true,
@@ -164,6 +173,46 @@ do_inline: {
node_version: ">=6"
}
do_inline_2: {
options = {
inline: true,
side_effects: true,
}
input: {
(function() {
(function() {
console.log("PASS");
})(..."");
})();
}
expect: {
[] = [ ..."" ],
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
do_inline_3: {
options = {
if_return: true,
inline: true,
}
input: {
(function() {
(function() {
while (console.log("PASS"));
})(..."");
})();
}
expect: {
var [] = [ ..."" ];
while (console.log("PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
drop_empty_call_1: {
options = {
side_effects: true,
@@ -201,7 +250,29 @@ drop_empty_call_2: {
node_version: ">=6"
}
convert_hole: {
convert_hole_array: {
options = {
spreads: true,
}
input: {
[ ...[ "PASS", , 42 ] ].forEach(function(a) {
console.log(a);
});
}
expect: {
[ "PASS", void 0, 42 ].forEach(function(a) {
console.log(a);
});
}
expect_stdout: [
"PASS",
"undefined",
"42",
]
node_version: ">=6"
}
convert_hole_call: {
options = {
spreads: true,
}
@@ -341,7 +412,7 @@ convert_setter: {
console.log(k, o[k]);
}
expect_stdout: "PASS undefined"
node_version: ">=8"
node_version: ">=8.3.0"
}
keep_getter_1: {
@@ -370,7 +441,7 @@ keep_getter_1: {
});
}
expect_stdout: "PASS"
node_version: ">=8"
node_version: ">=8.3.0"
}
keep_getter_2: {
@@ -399,7 +470,7 @@ keep_getter_2: {
"foo",
"bar",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
keep_getter_3: {
@@ -429,7 +500,7 @@ keep_getter_3: {
});
}
expect_stdout: "PASS"
node_version: ">=8"
node_version: ">=8.3.0"
}
keep_getter_4: {
@@ -460,7 +531,7 @@ keep_getter_4: {
});
}
expect_stdout: "PASS"
node_version: ">=8"
node_version: ">=8.3.0"
}
keep_accessor: {
@@ -508,7 +579,7 @@ keep_accessor: {
"q undefined",
"r null",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
object_key_order_1: {
@@ -538,7 +609,7 @@ object_key_order_1: {
"a 3",
"b 2",
]
node_version: ">=8 <=10"
node_version: ">=8.3.0 <=10"
}
object_key_order_2: {
@@ -568,7 +639,7 @@ object_key_order_2: {
"a 3",
"b 2",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
object_key_order_3: {
@@ -598,7 +669,7 @@ object_key_order_3: {
"a 3",
"b 2",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
object_key_order_4: {
@@ -628,7 +699,7 @@ object_key_order_4: {
"a 3",
"b 2",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
object_spread_array: {
@@ -654,7 +725,7 @@ object_spread_array: {
"0 foo",
"1 bar",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
object_spread_string: {
@@ -681,7 +752,7 @@ object_spread_string: {
"1 o",
"2 o",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
unused_var_side_effects: {
@@ -711,7 +782,7 @@ unused_var_side_effects: {
});
}
expect_stdout: "PASS"
node_version: ">=8"
node_version: ">=8.3.0"
}
unsafe_join_1: {
@@ -793,7 +864,7 @@ issue_4329: {
}[0]);
}
expect_stdout: "PASS"
node_version: ">=8"
node_version: ">=8.3.0"
}
issue_4331: {
@@ -871,7 +942,7 @@ issue_4345: {
}[42]);
}
expect_stdout: "PASS"
node_version: ">=8"
node_version: ">=8.3.0"
}
issue_4361: {
@@ -901,7 +972,7 @@ issue_4361: {
"foo",
"undefined",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
issue_4363: {
@@ -922,7 +993,7 @@ issue_4363: {
});
}
expect_stdout: "PASS"
node_version: ">=8"
node_version: ">=8.3.0"
}
issue_4556: {
@@ -994,7 +1065,7 @@ issue_4849: {
}()));
}
expect_stdout: "object"
node_version: ">=8"
node_version: ">=8.3.0"
}
issue_4882_1: {
@@ -1026,7 +1097,7 @@ issue_4882_1: {
"PASS",
"undefined",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
issue_4882_2: {
@@ -1052,7 +1123,7 @@ issue_4882_2: {
"42",
"PASS",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
issue_4882_3: {
@@ -1082,7 +1153,7 @@ issue_4882_3: {
"PASS",
"42",
]
node_version: ">=8"
node_version: ">=8.3.0"
}
issue_5006: {
@@ -1104,3 +1175,81 @@ issue_5006: {
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5382: {
options = {
side_effects: true,
}
input: {
({
f() {
({ ...this });
},
get p() {
console.log("PASS");
},
}).f();
}
expect: {
({
f() {
({ ...this });
},
get p() {
console.log("PASS");
},
}).f();
}
expect_stdout: "PASS"
node_version: ">=8.3.0"
}
issue_5602: {
options = {
collapse_vars: true,
conditionals: true,
evaluate: true,
if_return: true,
inline: true,
passes: 2,
sequences: true,
spreads: true,
unused: true,
}
input: {
(function() {
try {
var b = function(c) {
if (c)
return FAIL;
var d = 42;
}(...[ null, A = 0 ]);
} catch (e) {
b();
}
})();
console.log(A);
}
expect: {
(function() {
try {
var b = void (A = 0);
} catch (e) {
b();
}
})(),
console.log(A);
}
expect_stdout: "0"
expect_warnings: [
"INFO: Dropping unused variable d [test/compress/spreads.js:6,24]",
"INFO: Collapsing c [test/compress/spreads.js:4,24]",
"INFO: Dropping unused variable c [test/compress/spreads.js:3,33]",
"INFO: pass 0: last_count: Infinity, count: 27",
"WARN: Condition always false [test/compress/spreads.js:4,20]",
"INFO: Collapsing null [test/compress/spreads.js:7,23]",
"INFO: Collapsing 0 [test/compress/spreads.js:3,24]",
"INFO: pass 1: last_count: 27, count: 22",
]
node_version: ">=6"
}

View File

@@ -1608,3 +1608,83 @@ issue_5012: {
}
expect_stdout: "PASS"
}
issue_5543_1: {
options = {
dead_code: true,
switches: true,
}
input: {
var a;
switch (a) {
default:
switch (42) {
case a:
case console.log("PASS"):
}
break;
case null:
switch (false) {
case a:
case console.log("FAIL"):
}
}
}
expect: {
var a;
switch (a) {
default:
switch (42) {
case a:
case console.log("PASS"):
}
break;
case null:
switch (false) {
case a:
case console.log("FAIL"):
}
}
}
expect_stdout: "PASS"
}
issue_5543_2: {
options = {
dead_code: true,
switches: true,
}
input: {
var a;
switch (a) {
default:
switch (42) {
case a:
case console.log("PASS"):
}
break;
case null:
switch (42) {
case a:
case console.log("FAIL"):
}
}
}
expect: {
var a;
switch (a) {
default:
switch (42) {
case a:
case console.log("PASS"):
}
break;
case null:
switch (42) {
case a:
case console.log("FAIL"):
}
}
}
expect_stdout: "PASS"
}

View File

@@ -337,7 +337,7 @@ malformed_evaluate_4: {
console.log("\\u00b5");
}
expect_stdout: "\\u00b5"
node_version: ">=8"
node_version: ">=8.10.0"
}
unsafe_evaluate: {
@@ -353,7 +353,7 @@ unsafe_evaluate: {
console.log("\\uFo");
}
expect_stdout: "\\uFo"
node_version: ">=8"
node_version: ">=8.10.0"
}
side_effects_1: {
@@ -743,3 +743,29 @@ issue_5145_2: {
]
node_version: ">=4"
}
issue_5199: {
options = {
collapse_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = function() {
console.log(typeof b);
}``;
{
const b = a;
}
}
expect: {
var a = function() {
console.log(typeof b);
}``;
{
const b = a;
}
}
expect_stdout: "undefined"
node_version: ">=4"
}

View File

@@ -127,7 +127,7 @@ if_return: {
if (w) {
if (y) return;
} else if (z) return;
return x == y || (x && w(), y && z()), !0;
return x != y && (x && w(), y && z()), !0;
}
}
}

View File

@@ -307,7 +307,7 @@ typeof_defined_1: {
}
expect: {
"undefined" == typeof A && A;
"undefined" != typeof A || A;
"undefined" == typeof A && A;
}
}
@@ -324,7 +324,7 @@ typeof_defined_2: {
}
expect: {
"function" != typeof A && A;
"function" == typeof A || A;
"function" != typeof A && A;
}
}
@@ -355,16 +355,19 @@ typeof_defined_3: {
"undefined" == typeof A && "undefined" == typeof B && (A, B);
"undefined" == typeof A && "undefined" != typeof B && A;
"undefined" != typeof A && "undefined" == typeof B && B;
// dropped
"undefined" == typeof A && "undefined" == typeof B || (A, B);
"undefined" == typeof A && "undefined" != typeof B || (A, B);
"undefined" != typeof A && "undefined" == typeof B || (A, B);
"undefined" != typeof A && "undefined" != typeof B || (A, B);
"undefined" == typeof A || "undefined" == typeof B && B;
"undefined" != typeof A || "undefined" == typeof B && (A, B);
"undefined" != typeof A || "undefined" != typeof B && A;
"undefined" == typeof A || "undefined" != typeof B || B;
"undefined" != typeof A || "undefined" == typeof B || A;
"undefined" != typeof A || "undefined" != typeof B || (A, B);
"undefined" != typeof A && "undefined" == typeof B && B;
// dropped
"undefined" == typeof A && "undefined" == typeof B && (A, B);
"undefined" == typeof A && "undefined" != typeof B && A;
// dropped
"undefined" != typeof A && "undefined" == typeof B && B;
"undefined" == typeof A && "undefined" != typeof B && A;
"undefined" == typeof A && "undefined" == typeof B && (A, B);
}
}
@@ -392,6 +395,7 @@ typeof_defined_4: {
"object" != typeof A || "object" != typeof B || (A, B);
}
expect: {
// dropped
"object" == typeof A && "object" != typeof B && B;
"object" != typeof A && "object" == typeof B && A;
"object" != typeof A && "object" != typeof B && (A, B);
@@ -399,12 +403,14 @@ typeof_defined_4: {
"object" == typeof A && "object" != typeof B || (A, B);
"object" != typeof A && "object" == typeof B || (A, B);
"object" != typeof A && "object" != typeof B || (A, B);
"object" == typeof A || "object" == typeof B && A;
"object" == typeof A || "object" != typeof B && (A, B);
"object" != typeof A || "object" != typeof B && B;
"object" == typeof A || "object" == typeof B || (A, B);
"object" == typeof A || "object" != typeof B || A;
"object" != typeof A || "object" == typeof B || B;
"object" != typeof A && "object" == typeof B && A;
"object" != typeof A && "object" != typeof B && (A, B);
// dropped
"object" == typeof A && "object" != typeof B && B;
"object" != typeof A && "object" != typeof B && (A, B);
"object" != typeof A && "object" == typeof B && A;
"object" == typeof A && "object" != typeof B && B;
// dropped
}
}
@@ -436,6 +442,245 @@ emberjs_global: {
expect_stdout: Error("PASS")
}
reassign: {
options = {
comparisons: true,
conditionals: true,
passes: 2,
typeofs: true,
}
input: {
A = console;
if ("undefined" == typeof A)
console.log("FAIL 1");
else {
A = void 0;
while (console.log(void 0 === A ? "PASS" : "FAIL 2"));
}
}
expect: {
A = console;
if ("undefined" == typeof A)
console.log("FAIL 1");
else {
A = void 0;
while (console.log(void 0 === A ? "PASS" : "FAIL 2"));
}
}
expect_stdout: "PASS"
}
reassign_call: {
options = {
comparisons: true,
conditionals: true,
passes: 2,
typeofs: true,
}
input: {
A = console;
function f() {
A = void 0;
}
if ("undefined" == typeof A)
console.log("FAIL 1");
else {
f();
while (console.log(void 0 === A ? "PASS" : "FAIL 2"));
}
}
expect: {
A = console;
function f() {
A = void 0;
}
if ("undefined" == typeof A)
console.log("FAIL 1");
else {
f();
while (console.log(void 0 === A ? "PASS" : "FAIL 2"));
}
}
expect_stdout: "PASS"
}
reassign_conditional: {
options = {
comparisons: true,
conditionals: true,
passes: 2,
typeofs: true,
}
input: {
A = console;
if ("undefined" == typeof A)
console.log("FAIL 1");
else {
A &&= void 0;
while (console.log(void 0 === A ? "PASS" : "FAIL 2"));
}
}
expect: {
A = console;
if ("undefined" == typeof A)
console.log("FAIL 1");
else {
A &&= void 0;
while (console.log(void 0 === A ? "PASS" : "FAIL 2"));
}
}
expect_stdout: "PASS"
node_version: ">=15"
}
reassign_do: {
options = {
comparisons: true,
conditionals: true,
if_return: true,
passes: 2,
reduce_vars: true,
typeofs: true,
}
input: {
A = console;
(function() {
if ("undefined" == typeof A)
return;
var a = A, i = 2;
do {
console.log(void 0 === A, void 0 === a);
A = void 0;
} while (--i);
})();
}
expect: {
A = console;
(function() {
if ("undefined" != typeof A) {
var a = A, i = 2;
do {
console.log(void 0 === A, (a, false));
A = void 0;
} while (--i);
}
})();
}
expect_stdout: [
"false false",
"true false",
]
}
reassign_for: {
options = {
comparisons: true,
conditionals: true,
passes: 2,
reduce_vars: true,
toplevel: true,
typeofs: true,
}
input: {
if (A = console, "undefined" != typeof A)
for (var a = A, i = 0; i < 2; i++)
console.log(void 0 === A, void 0 === a),
A = void 0;
}
expect: {
if (A = console, "undefined" != typeof A)
for (var a = A, i = 0; i < 2; i++)
console.log(void 0 === A, (a, false)),
A = void 0;
}
expect_stdout: [
"false false",
"true false",
]
}
reassign_for_in: {
options = {
comparisons: true,
conditionals: true,
passes: 2,
reduce_vars: true,
typeofs: true,
}
input: {
(A = console) && "undefined" != typeof A && function(a) {
for (var k in [ a = A, 42 ]) {
console.log(void 0 === A, void 0 === a);
A = void 0;
}
}();
}
expect: {
(A = console) && "undefined" != typeof A && function(a) {
for (var k in [ a = A, 42 ]) {
console.log(void 0 === A, (a, false));
A = void 0;
}
}();
}
expect_stdout: [
"false false",
"true false",
]
}
reassign_iife: {
options = {
comparisons: true,
conditionals: true,
passes: 2,
typeofs: true,
}
input: {
A = console;
if ("undefined" == typeof A)
console.log("FAIL 1");
else (function() {
A = void 0;
})(console.log(void 0 === A ? "FAIL 2" : "PASS"));
}
expect: {
A = console;
"undefined" == typeof A ? console.log("FAIL 1") : function() {
A = void 0;
}(console.log((A, false) ? "FAIL 2" : "PASS"));
}
expect_stdout: "PASS"
}
reassign_property: {
options = {
comparisons: true,
conditionals: true,
passes: 2,
typeofs: true,
}
input: {
A = console;
if ("undefined" == typeof A)
console.log("FAIL 1");
else {
A.p = void 0;
console.log(void 0 === A ? "FAIL 2" : "PASS");
}
}
expect: {
A = console;
if ("undefined" == typeof A)
console.log("FAIL 1");
else {
A.p = void 0;
console.log((A, false) ? "FAIL 2" : "PASS");
}
}
expect_stdout: "PASS"
}
issue_3817: {
options = {
comparisons: true,

View File

@@ -67,7 +67,8 @@ unicode_escaped_identifier_2: {
}
expect_exact: 'var a="foo";var \u{10000}="bar";console.log(a,\u{10000});'
expect_stdout: "foo bar"
node_version: ">=4"
// non-BMP support is platform-dependent on Node.js v4
node_version: ">=6"
}
unicode_identifier_ascii_only: {
@@ -200,7 +201,8 @@ surrogate_pair: {
}
expect_exact: 'var \ud87e\udc00={"\ud87e\udc01":"\udbc0\udc00"};\ud87e\udc00.\ud87e\udc02="\udbc0\udc01";console.log(typeof \ud87e\udc00,\ud87e\udc00.\ud87e\udc01,\ud87e\udc00["\ud87e\udc02"]);'
expect_stdout: "object \udbc0\udc00 \udbc0\udc01"
node_version: ">=4"
// non-BMP support is platform-dependent on Node.js v4
node_version: ">=6"
}
surrogate_pair_ascii: {
@@ -216,5 +218,6 @@ surrogate_pair_ascii: {
}
expect_exact: 'var \\u{2f800}={"\\ud87e\\udc01":"\\udbc0\\udc00"};\\u{2f800}.\\u{2f802}="\\udbc0\\udc01";console.log(typeof \\u{2f800},\\u{2f800}.\\u{2f801},\\u{2f800}["\\ud87e\\udc02"]);'
expect_stdout: "object \udbc0\udc00 \udbc0\udc01"
node_version: ">=4"
// non-BMP support is platform-dependent on Node.js v4
node_version: ">=6"
}

View File

@@ -13,10 +13,10 @@ reduce_merge_const: {
console.log(b);
}
expect: {
var b = console;
console.log(typeof b);
b = typeof b;
console.log(b);
var a = console;
console.log(typeof a);
a = typeof a;
console.log(a);
}
expect_stdout: [
"object",
@@ -41,10 +41,10 @@ reduce_merge_let: {
}
expect: {
"use strict";
var b = console;
console.log(typeof b);
b = typeof b;
console.log(b);
var a = console;
console.log(typeof a);
a = typeof a;
console.log(a);
}
expect_stdout: [
"object",
@@ -111,7 +111,7 @@ hoist_props_const: {
}
}
expect: {
var o_p = "PASS";
var o, o_p = "PASS";
console.log(o_p);
}
expect_stdout: "PASS"
@@ -136,7 +136,7 @@ hoist_props_let: {
}
expect: {
"use strict";
var o_p = "PASS";
var o, o_p = "PASS";
console.log(o_p);
}
expect_stdout: "PASS"
@@ -194,6 +194,43 @@ scope_adjustment_let: {
node_version: ">=4"
}
escaped_const: {
options = {
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
const log = console.log;
log("PASS");
}
expect: {
var log = console.log;
log("PASS");
}
expect_stdout: "PASS"
}
escaped_let: {
options = {
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
"use strict";
let log = console.log;
log("PASS");
}
expect: {
"use strict";
var log = console.log;
log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4191_const: {
options = {
functions: true,
@@ -613,3 +650,35 @@ issue_4954: {
]
node_version: ">=4"
}
issue_5516: {
options = {
reduce_funcs: true,
reduce_vars: true,
unused: true,
varify: true,
}
input: {
"use strict";
console.log(typeof function() {
{
let a;
}
{
const a = function() {};
return a;
}
}());
}
expect: {
"use strict";
console.log(typeof function() {
{
const a = function() {};
return a;
}
}());
}
expect_stdout: "function"
node_version: ">=4"
}

View File

@@ -107,3 +107,209 @@ function_name_mangle_ie8: {
expect_exact: "(function(){console.log(typeof function n(o){})})();"
expect_stdout: "function"
}
issue_1753: {
mangle = {
toplevel: false,
webkit: true,
}
input: {
"use strict";
let l = null;
for (let i = 0; i < 1; i++)
console.log(i);
}
expect: {
"use strict";
let l = null;
for (let i = 0; i < 1; i++)
console.log(i);
}
expect_stdout: "0"
node_version: ">=4"
}
issue_1753_toplevel: {
mangle = {
toplevel: true,
webkit: true,
}
input: {
"use strict";
let l = null;
for (let i = 0; i < 1; i++)
console.log(i);
}
expect: {
"use strict";
let l = null;
for (let e = 0; e < 1; e++)
console.log(e);
}
expect_stdout: "0"
node_version: ">=4"
}
issue_5032_await: {
options = {
merge_vars: true,
webkit: false,
}
input: {
function log(value) {
console.log(value);
return value;
}
async function f(a) {
var b = log(a), c = b;
log(b);
log(c);
}
f("PASS");
}
expect: {
function log(value) {
console.log(value);
return value;
}
async function f(a) {
var a = log(a), c = a;
log(a);
log(c);
}
f("PASS");
}
expect_stdout: [
"PASS",
"PASS",
"PASS",
]
node_version: ">=8"
}
issue_5032_await_webkit: {
options = {
merge_vars: true,
webkit: true,
}
input: {
function log(value) {
console.log(value);
return value;
}
async function f(a) {
var b = log(a), c = b;
log(b);
log(c);
}
f("PASS");
}
expect: {
function log(value) {
console.log(value);
return value;
}
async function f(a) {
var b = log(a), c = b;
log(b);
log(c);
}
f("PASS");
}
expect_stdout: [
"PASS",
"PASS",
"PASS",
]
node_version: ">=8"
}
issue_5032_yield: {
options = {
merge_vars: true,
webkit: false,
}
input: {
function log(value) {
console.log(value);
return value;
}
function *f(a) {
var b = log(a), c = b;
log(b);
log(c);
}
f("PASS").next();
}
expect: {
function log(value) {
console.log(value);
return value;
}
function *f(a) {
var a = log(a), c = a;
log(a);
log(c);
}
f("PASS").next();
}
expect_stdout: [
"PASS",
"PASS",
"PASS",
]
node_version: ">=4"
}
issue_5032_yield_webkit: {
options = {
merge_vars: true,
webkit: true,
}
input: {
function log(value) {
console.log(value);
return value;
}
function *f(a) {
var b = log(a), c = b;
log(b);
log(c);
}
f("PASS").next();
}
expect: {
function log(value) {
console.log(value);
return value;
}
function *f(a) {
var b = log(a), c = b;
log(b);
log(c);
}
f("PASS").next();
}
expect_stdout: [
"PASS",
"PASS",
"PASS",
]
node_version: ">=4"
}
issue_5480: {
mangle = {
webkit: true,
}
input: {
"use strict";
L: for (let a in console.log("PASS"));
}
expect: {
"use strict";
o: for (let o in console.log("PASS"));
}
expect_stdout: "PASS"
node_version: ">=4"
}

View File

@@ -96,7 +96,7 @@ pause_resume: {
node_version: ">=4"
}
arrow_yield: {
arrow_yield_1: {
input: {
yield = "PASS";
console.log(function*() {
@@ -108,6 +108,18 @@ arrow_yield: {
node_version: ">=4"
}
arrow_yield_2: {
input: {
console.log(typeof function *() {
// Syntax error on Node.js v6+
return (yield) => {};
}().next().value);
}
expect_exact: "console.log(typeof function*(){return(yield)=>{}}().next().value);"
expect_stdout: "function"
node_version: "4"
}
for_of: {
input: {
function* f() {
@@ -737,7 +749,7 @@ lift_sequence: {
node_version: ">=4"
}
inline_nested_yield: {
inline_nested: {
options = {
inline: true,
sequences: true,
@@ -772,6 +784,118 @@ inline_nested_yield: {
node_version: ">=4"
}
inline_nested_async: {
options = {
awaits: true,
inline: true,
sequences: true,
side_effects: true,
yields: true,
}
input: {
console.log("foo");
var a = async function*() {
console.log(await(yield* async function*() {
yield {
then: r => r("bar"),
};
return "baz";
}()));
}();
console.log("moo");
a.next().then(function f(b) {
console.log(b.value);
b.done || a.next().then(f);
});
console.log("moz");
}
expect: {
console.log("foo");
var a = async function*() {
console.log((yield {
then: r => r("bar"),
}, await "baz"));
}();
console.log("moo"),
a.next().then(function f(b) {
console.log(b.value),
b.done || a.next().then(f);
}),
console.log("moz");
}
expect_stdout: [
"foo",
"moo",
"moz",
"bar",
"baz",
"undefined",
]
node_version: ">=10"
}
inline_nested_block: {
options = {
if_return: true,
inline: true,
yields: true,
}
input: {
var a = function*() {
yield* function*() {
for (var a of [ "foo", "bar" ])
yield a;
return "FAIL";
}();
}(), b;
do {
b = a.next();
console.log(b.value);
} while (!b.done);
}
expect: {
var a = function*() {
for (var a of [ "foo", "bar" ])
yield a;
"FAIL";
}(), b;
do {
b = a.next();
console.log(b.value);
} while (!b.done);
}
expect_stdout: [
"foo",
"bar",
"undefined",
]
node_version: ">=4"
}
dont_inline_nested: {
options = {
inline: true,
}
input: {
var yield = "PASS";
(function*() {
(function() {
console.log(yield);
})();
})().next();
}
expect: {
var yield = "PASS";
(function*() {
(function() {
console.log(yield);
})();
})().next();
}
expect_stdout: "PASS"
node_version: ">=4"
}
drop_body: {
options = {
side_effects: true,
@@ -783,7 +907,7 @@ drop_body: {
})([ console.log("baz") ]);
}
expect: {
[ [ , [].e = console.log("foo") ] ] = [ [ console.log("baz") ] ];
[ [ , [][0] = console.log("foo") ] ] = [ [ console.log("baz") ] ];
}
expect_stdout: [
"baz",
@@ -810,6 +934,21 @@ drop_unused_call: {
node_version: ">=4"
}
instanceof_lambda: {
options = {
evaluate: true,
side_effects: true,
}
input: {
console.log(42 instanceof function*() {});
}
expect: {
console.log(false);
}
expect_stdout: "false"
node_version: ">=4"
}
issue_4454_1: {
rename = false
options = {
@@ -852,8 +991,8 @@ issue_4454_2: {
f("PASS");
}
expect: {
function f(b) {
(function*(c = console.log(b)) {})();
function f(a) {
(function*(c = console.log(a)) {})();
var b = 42..toString();
console.log(b);
}
@@ -958,7 +1097,7 @@ issue_4639_1: {
}().next().value());
}
expect_stdout: "PASS"
node_version: ">=4"
node_version: ">=4 <7 || >=8.7.0"
}
issue_4639_2: {
@@ -1044,6 +1183,35 @@ issue_4641_2: {
node_version: ">=10"
}
issue_4641_3: {
options = {
if_return: true,
}
input: {
console.log(typeof async function*() {
try {
return void "FAIL";
} finally {
console.log("PASS");
}
}().next().then);
}
expect: {
console.log(typeof async function*() {
try {
return void "FAIL";
} finally {
console.log("PASS");
}
}().next().then);
}
expect_stdout: [
"function",
"PASS",
]
node_version: ">=10"
}
issue_4769_1: {
options = {
side_effects: true,
@@ -1143,80 +1311,6 @@ issue_5019_2: {
node_version: ">=4"
}
issue_5032_normal: {
options = {
merge_vars: true,
webkit: false,
}
input: {
function log(value) {
console.log(value);
return value;
}
function *f(a) {
var b = log(a), c = b;
log(b);
log(c);
}
f("PASS").next();
}
expect: {
function log(value) {
console.log(value);
return value;
}
function *f(c) {
var b = log(c), c = b;
log(b);
log(c);
}
f("PASS").next();
}
expect_stdout: [
"PASS",
"PASS",
"PASS",
]
node_version: ">=4"
}
issue_5032_webkit: {
options = {
merge_vars: true,
webkit: true,
}
input: {
function log(value) {
console.log(value);
return value;
}
function *f(a) {
var b = log(a), c = b;
log(b);
log(c);
}
f("PASS").next();
}
expect: {
function log(value) {
console.log(value);
return value;
}
function *f(a) {
var b = log(a), c = b;
log(b);
log(c);
}
f("PASS").next();
}
expect_stdout: [
"PASS",
"PASS",
"PASS",
]
node_version: ">=4"
}
issue_5034: {
options = {
functions: true,
@@ -1247,12 +1341,13 @@ issue_5034: {
node_version: ">=4"
}
issue_5076: {
issue_5076_1: {
options = {
evaluate: true,
hoist_vars: true,
passes: 2,
keep_fargs: false,
pure_getters: "strict",
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
@@ -1269,9 +1364,408 @@ issue_5076: {
}
expect: {
var a;
console.log("PASS");
console.log("PASS"),
a = 42["a"];
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5076_2: {
options = {
evaluate: true,
hoist_vars: true,
keep_fargs: false,
passes: 2,
pure_getters: "strict",
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
yields: true,
}
input: {
var a;
console.log("PASS");
var b = function*({
p: {},
}) {}({
p: { a } = 42,
});
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5177: {
options = {
properties: true,
}
input: {
console.log(typeof function*() {
return {
p(yield) {},
}.p;
}().next().value);
}
expect: {
console.log(typeof function*() {
return {
p(yield) {},
}.p;
}().next().value);
}
expect_stdout: "function"
node_version: ">=4"
}
issue_5385_1: {
options = {
inline: true,
}
input: {
(async function*() {
(function() {
try {
return console.log("foo");
} finally {
return console.log("bar");
}
console.log("baz");
})();
})().next();
console.log("moo");
}
expect: {
(async function*() {
(function() {
try {
return console.log("foo");
} finally {
return console.log("bar");
}
console.log("baz");
})();
})().next();
console.log("moo");
}
expect_stdout: [
"foo",
"bar",
"moo",
]
node_version: ">=10"
}
issue_5385_2: {
options = {
inline: true,
}
input: {
(async function*() {
return function() {
try {
return console.log("foo");
} finally {
return console.log("bar");
}
}();
})().next();
console.log("moo");
}
expect: {
(async function*() {
return function() {
try {
return console.log("foo");
} finally {
return console.log("bar");
}
}();
})().next();
console.log("moo");
}
expect_stdout: [
"foo",
"bar",
"moo",
]
node_version: ">=10"
}
issue_5385_3: {
options = {
inline: true,
}
input: {
(async function*() {
return function() {
try {
throw console.log("foo");
} catch (e) {
return console.log("bar");
}
}();
})().next();
console.log("moo");
}
expect: {
(async function*() {
try {
throw console.log("foo");
} catch (e) {
return console.log("bar");
}
return void 0;
})().next();
console.log("moo");
}
expect_stdout: [
"foo",
"bar",
"moo",
]
node_version: ">=10"
}
issue_5385_4: {
options = {
awaits: true,
inline: true,
}
input: {
(async function*() {
return async function() {
try {
return {
then(resolve) {
resolve(console.log("FAIL"));
},
};
} finally {
return "PASS";
}
}();
})().next().then(o => console.log(o.value, o.done));
}
expect: {
(async function*() {
return async function() {
try {
return {
then(resolve) {
resolve(console.log("FAIL"));
},
};
} finally {
return "PASS";
}
}();
})().next().then(o => console.log(o.value, o.done));
}
expect_stdout: "PASS true"
node_version: ">=10"
}
issue_5425: {
options = {
assignments: true,
ie: true,
toplevel: true,
unused: true,
yields: true,
}
input: {
var a = "FAIL";
var b = function* f() {}(a ? a = "PASS" : 42);
console.log(a, typeof f);
}
expect: {
var a = "FAIL";
(function* f() {})(a && (a = "PASS"));
console.log(a, typeof f);
}
expect_stdout: "PASS undefined"
node_version: ">=4"
}
issue_5456: {
options = {
inline: true,
merge_vars: true,
}
input: {
var a = true;
(function() {
(function(b, c) {
var d = function*() {
c = null;
}();
var e = function() {
if (c)
console.log(typeof d);
while (b);
}();
})(function(i) {
return console.log("foo") && i;
}(a));
})();
}
expect: {
var a = true;
(function() {
b = (i = a, console.log("foo") && i),
d = function*() {
c = null;
}(),
e = function() {
if (c) console.log(typeof d);
while (b);
}(),
void 0;
var b, c, d, e;
var i;
})();
}
expect_stdout: "foo"
node_version: ">=4"
}
issue_5506: {
options = {
dead_code: true,
}
input: {
console.log(function(a) {
var b = function*() {
a = null in (a = "PASS");
}();
try {
b.next();
} catch (e) {
return a;
}
}("FAIL"));
}
expect: {
console.log(function(a) {
var b = function*() {
a = null in (a = "PASS");
}();
try {
b.next();
} catch (e) {
return a;
}
}("FAIL"));
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5526: {
options = {
inline: true,
side_effects: true,
}
input: {
(async function*() {
try {
return function() {
while (console.log("foo"));
}();
} finally {
console.log("bar");
}
})().next();
console.log("baz");
}
expect: {
(async function*() {
try {
while (console.log("foo"));
return void 0;
} finally {
console.log("bar");
}
})().next();
console.log("baz");
}
expect_stdout: [
"foo",
"baz",
"bar",
]
node_version: ">=10"
}
issue_5576: {
options = {
inline: true,
}
input: {
(async function*() {
try {
(function() {
while (console.log("foo"));
})();
} finally {
console.log("bar");
}
})().next();
console.log("baz");
}
expect: {
(async function*() {
try {
while (console.log("foo"));
} finally {
console.log("bar");
}
})().next();
console.log("baz");
}
expect_stdout: [
"foo",
"bar",
"baz",
]
node_version: ">=10"
}
issue_5663: {
options = {
toplevel: true,
unused: true,
}
input: {
var [ , a ] = function*() {
console.log("foo");
yield console.log("bar");
console.log("baz");
yield console.log("moo");
console.log("moz");
yield FAIL;
}();
}
expect: {
var [ , , ] = function*() {
console.log("foo");
yield console.log("bar");
console.log("baz");
yield console.log("moo");
console.log("moz");
yield FAIL;
}();
}
expect_stdout: [
"foo",
"bar",
"baz",
"moo",
]
node_version: ">=6"
}

View File

@@ -38,4 +38,4 @@ var _require = require("bar"), foo = _require.foo;
var _require2 = require("world"), hello = _require2.hello;
foo.x.apply(foo, _toConsumableArray(foo.y(hello.z)));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImNvbnN0IHtmb299ID0gcmVxdWlyZShcImJhclwiKTtcbmNvbnN0IHtoZWxsb30gPSByZXF1aXJlKFwid29ybGRcIik7XG5cbmZvby54KC4uLmZvby55KGhlbGxvLnopKTtcbiJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiZm9vIiwiaGVsbG8iLCJ4IiwiYXBwbHkiLCJfdG9Db25zdW1hYmxlQXJyYXkiLCJ5IiwieiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7ZUFBY0EsUUFBUSxRQUFmQyxNLFNBQUFBOztBLGdCQUNTRCxRQUFRLFVBQWpCRSxRLFVBQUFBOztBQUVQRCxJQUFJRSxFQUFKQyxNQUFBSCxLQUFHSSxtQkFBTUosSUFBSUssRUFBRUosTUFBTUsifQ==
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImNvbnN0IHtmb299ID0gcmVxdWlyZShcImJhclwiKTtcbmNvbnN0IHtoZWxsb30gPSByZXF1aXJlKFwid29ybGRcIik7XG5cbmZvby54KC4uLmZvby55KGhlbGxvLnopKTtcbiJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiZm9vIiwiaGVsbG8iLCJ4IiwiYXBwbHkiLCJfdG9Db25zdW1hYmxlQXJyYXkiLCJ5IiwieiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7ZUFBY0EsUUFBUSxLQUFELEdBQWRDLE0sU0FBQUE7O0EsZ0JBQ1NELFFBQVEsT0FBRCxHQUFoQkUsUSxVQUFBQTs7QUFFUEQsSUFBSUUsRUFBSkMsTUFBQUgsS0FBR0ksbUJBQU1KLElBQUlLLEVBQUVKLE1BQU1LLENBQVosQ0FBTixDQUFBIn0=

View File

@@ -1,2 +1,2 @@
console.log(3);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUEwQkEsUUFBUUMsSUFBSSJ9
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUEwQkEsUUFBUUMsSUFBSSxDQUFHIn0=

View File

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

View File

@@ -1,2 +1,2 @@
console.log(3);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUEwQkEsUUFBUUMsSUFBSSJ9
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUEwQkEsUUFBUUMsSUFBSSxDQUFHIn0=

View File

@@ -0,0 +1 @@
function n(){return this||arguments[0]+arguments[1]}function o(){return this||arguments[0]+arguments[1]}console.log(n(n(1,3),5)),console.log(o(o(2,4),6));

View File

@@ -0,0 +1,13 @@
console.log(function() {
function sum(...params) {
return this || arguments[0] + arguments[1];
}
return sum(sum(1, 3), 5);
}());
console.log(function() {
"use strict";
function sum(...params) {
return this || arguments[0] + arguments[1];
}
return sum(sum(2, 4), 6);
}());

View File

@@ -0,0 +1,17 @@
var unused;
export default class {
____11111() {
a, b, c, d, e;
f, g, h, i, j;
k, l, m, n, o;
p, q, r, s, t;
u, v, w, x, y, z;
A, B, C, D, E;
F, G, H, I, J;
K, L, M, N, O;
P, Q, R, S, T;
U, V, W, X, Y, Z;
$, _;
unused;
}
}

View File

@@ -62,6 +62,7 @@ if (typeof phantom == "undefined") {
var cmd = process.platform == "win32" ? "npm.cmd" : "npm";
function npm(args, done) {
args.push("--loglevel=error");
child_process.spawn(cmd, args, { stdio: [ "ignore", 1, 2 ] }).on("exit", done);
}
@@ -69,11 +70,15 @@ if (typeof phantom == "undefined") {
npm([
"install",
"graceful-fs@4.2.6",
"is-my-json-valid@2.20.5",
"phantomjs-prebuilt@2.1.14",
"--no-audit",
"--no-fund",
"--no-optional",
"--no-save",
"--no-strict-ssl",
"--no-update-notifier",
"--production",
], function(code) {
if (code) {
console.log("npm install failed with code", code);

View File

@@ -1,13 +1,14 @@
var fs = require("fs");
var config = {
limit: 10000,
timeout: function(limit) {
this.limit = limit;
}
this.limit = limit + lag;
},
};
var lag = +process.env["UGLIFY_GITHUB_LAG"] || 0;
var tasks = [];
var titles = [];
config.timeout(10000);
describe = function(title, fn) {
config = Object.create(config);
titles.push(title);
@@ -21,10 +22,11 @@ it = function(title, fn) {
fn.titles.push(title);
tasks.push(fn);
};
fs.readdirSync("test/mocha").filter(function(file) {
return /\.js$/.test(file);
}).forEach(function(file) {
(function(arg) {
return arg ? [ arg ] : fs.readdirSync("test/mocha").filter(function(file) {
return /\.js$/.test(file);
});
})(process.argv[2]).forEach(function(file) {
require("./mocha/" + file);
});
@@ -66,12 +68,13 @@ process.nextTick(function run() {
if (task.length) {
task.timeout = function(limit) {
clearTimeout(timer);
limit += lag;
task.limit = limit;
timer = setTimeout(function() {
raise(new Error("Timed out: exceeds " + limit + "ms"));
}, limit);
};
task.timeout(task.limit);
task.timeout(task.limit - lag);
process.on("uncaughtException", raise);
task.call(task, done);
} else {

View File

@@ -7,7 +7,7 @@ describe("async", function() {
"function await() {}",
"function(await) {}",
"function() { await; }",
"function() { await:{} }",
"function() { await: {} }",
"function() { var await; }",
"function() { function await() {} }",
"function() { try {} catch (await) {} }",

View File

@@ -2,6 +2,7 @@ var assert = require("assert");
var exec = require("child_process").exec;
var fs = require("fs");
var run_code = require("../sandbox").run_code;
var semver = require("semver");
var to_ascii = require("../node").to_ascii;
function read(path) {
@@ -12,10 +13,13 @@ describe("bin/uglifyjs", function() {
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
it("Should produce a functional build when using --self", function(done) {
this.timeout(30000);
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
exec(command, {
maxBuffer: 1048576
}, function(err, stdout) {
var command = [
uglifyjscmd,
"--self",
semver.satisfies(process.version, "<=0.12") ? "-mc hoist_funs" : "-mc",
"--wrap WrappedUglifyJS",
].join(" ");
exec(command, { maxBuffer: 1048576 }, function(err, stdout) {
if (err) throw err;
eval(stdout);
assert.strictEqual(typeof WrappedUglifyJS, "object");
@@ -49,6 +53,23 @@ describe("bin/uglifyjs", function() {
done();
});
});
it("Should work with --expression", function(done) {
exec([
uglifyjscmd,
"--expression",
"--compress",
"--mangle",
].join(" "), function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function(n){for(;n(););return 42}(A)\n");
done();
}).stdin.end([
"function(x) {",
" while (x()) {}",
" return 42;",
"}(A)",
].join("\n"));
});
it("Should work with --source-map names=true", function(done) {
exec([
uglifyjscmd,
@@ -65,7 +86,7 @@ describe("bin/uglifyjs", function() {
" q: b",
"};",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,",
].join("\n")
].join("\n");
assert.strictEqual(stdout.slice(0, expected.length), expected);
var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim()));
assert.deepEqual(map.names, [ "obj", "p", "a", "q", "b" ]);
@@ -93,7 +114,7 @@ describe("bin/uglifyjs", function() {
" q: b",
"};",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,",
].join("\n")
].join("\n");
assert.strictEqual(stdout.slice(0, expected.length), expected);
var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim()));
assert.deepEqual(map.names, []);
@@ -122,7 +143,7 @@ describe("bin/uglifyjs", function() {
if (err) throw err;
assert.strictEqual(stdout, [
"var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxHQUNYLENBRUEsT0FBT0MsR0FDVixFQUFFIn0=",
"",
].join("\n"));
done();
@@ -184,6 +205,30 @@ describe("bin/uglifyjs", function() {
child.stdin.end(read("test/input/issue-3040/input.js"));
}, 1000);
});
it("Should work with --keep-fargs (mangle only)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fargs -m';
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(){function n(a){return a*a}return x(n)}}function g(op){return op(1)+op(2)}console.log(f(g)()==5);\n");
done();
});
});
it("Should work with --keep-fargs (mangle & compress)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fargs -m -c';
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(){return x(function(a){return a*a})}}function g(op){return op(1)+op(2)}console.log(5==f(g)());\n");
done();
});
});
it("Should work with keep_fargs under mangler options", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep_fargs=true';
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(){function n(a){return a*a}return x(n)}}function g(op){return op(1)+op(2)}console.log(f(g)()==5);\n");
done();
});
});
it("Should work with --keep-fnames (mangle only)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
exec(command, function(err, stdout) {
@@ -193,10 +238,10 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with --keep-fnames (mangle & compress)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c unused=false';
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c';
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n");
assert.strictEqual(stdout, "function f(n){return function(){return n(function n(r){return r*r})}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n");
done();
});
});
@@ -285,7 +330,7 @@ describe("bin/uglifyjs", function() {
if (err) throw err;
assert.strictEqual(stdout, [
"var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxHQUNYLENBRUEsT0FBT0MsR0FDVixFQUFFIn0=",
"",
].join("\n"));
var stderrLines = stderr.split("\n");
@@ -305,7 +350,7 @@ describe("bin/uglifyjs", function() {
if (err) throw err;
assert.strictEqual(stdout, [
"var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUVBLE1BQWNDLFFBQVFDLElBQUksRUFBRSxJQUFPLElBQUlGLElDQW5ELElBQUlHLElBQU0sV0FDTixTQUFTQyxJQUFLRCxLQUNWLE9BQU9BLElBR1gsT0FBT0MsSUFMRCJ9",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUVBLE1BQWNDLFFBQVFDLElBQUksRUFBRSxDQUFDLENBQUUsRUFBSSxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxHQUNYLENBRUEsT0FBT0MsR0FDVixFQUFFIn0=",
"",
].join("\n"));
var stderrLines = stderr.split("\n");
@@ -746,7 +791,7 @@ describe("bin/uglifyjs", function() {
if (err) throw err;
assert.strictEqual(stdout, [
'"use strict";var foo=function foo(x){return"foo "+x};console.log(foo("bar"));',
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiYUFBQSxJQUFJQSxJQUFNLFNBQU5BLElBQU1DLEdBQUEsTUFBSyxPQUFTQSxHQUN4QkMsUUFBUUMsSUFBSUgsSUFBSSJ9",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiYUFBQSxJQUFJQSxJQUFNLFNBQU5BLElBQU1DLEdBQUEsTUFBSyxPQUFTQSxDQUFkLEVBQ1ZDLFFBQVFDLElBQUlILElBQUksS0FBSixDQUFaIn0=",
""
].join("\n"));
done();
@@ -769,7 +814,7 @@ describe("bin/uglifyjs", function() {
if (err) throw err;
assert.strictEqual(stdout, [
'function foo(){return function(){console.log("PASS")}}foo()();',
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIiwiZiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsTUFDTCxPQUFPLFdBQ0hDLFFBQVFDLElBQUksU0FLUkYsS0FDUkcifQ==",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxNQUNMLE9BQU8sV0FDSEMsUUFBUUMsSUFBSSxNQUFNLENBQ3RCLENBQ0osQ0FHWUYsSUFBSSxFQUNWIn0=",
""
].join("\n"));
done();
@@ -900,6 +945,14 @@ describe("bin/uglifyjs", function() {
done();
});
});
it("Should work with --module", function(done) {
var command = uglifyjscmd + " test/input/module/input.js --module -mc";
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, read("test/input/module/expect.js"));
done();
});
});
it("Should compress swarm of unused variables with reasonable performance", function(done) {
var code = [
"console.log(function() {",

View File

@@ -1,3 +1,4 @@
var acorn = require("acorn");
var assert = require("assert");
var UglifyJS = require("../node");
@@ -25,6 +26,7 @@ describe("export", function() {
"export { * };",
"export { * as A };",
"export { 42 as A };",
"export { 'A' as B };",
"export { A as B-C };",
"export { default as A };",
].forEach(function(code) {
@@ -51,8 +53,11 @@ describe("export", function() {
it("Should reject invalid `export ... from ...` statement syntax", function() {
[
"export from 'path';",
"export A from 'path';",
"export * from `path`;",
"export 'A' from 'path';",
"export A as B from 'path';",
"export 'A' as B from 'path';",
"export default from 'path';",
"export { A }, B from 'path';",
"export * as A, B from 'path';",
@@ -68,4 +73,109 @@ describe("export", function() {
}, code);
});
});
it("Should reject `export` statement not under top-level scope", function() {
[
"{ export {}; }",
"if (0) export var A;",
"function f() { export default 42; }",
].forEach(function(code) {
assert.throws(function() {
UglifyJS.parse(code);
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error;
}, code);
});
});
it("Should compare `export` statements correctly", function() {
var stats = {
Declaration: [
"export let A;",
"export const A = 42;",
"export var { A, B: [] } = C;",
"export function A() { return B(A); }",
"export async function* A({}, ...[]) { return B(A); }",
],
Default: [
"export default 42;",
"export default A => A(B);",
"export default class A extends B {}",
"export default (class A extends B {});",
"export default class A { static C = 42; }",
"export default class A extends B { static C = 42; }",
],
Foreign: [
"export * from 'path';",
"export {} from 'path';",
"export * as A from 'path';",
"export { default } from 'path';",
"export { A, B as C } from 'path';",
"export { A, default as C } from 'path';",
],
References: [
"export {};",
"export { A };",
"export { A as B };",
"export { A, B as C };",
"export { A as default };",
],
};
for (var k in stats) stats[k].forEach(function(c, i) {
var s = UglifyJS.parse(c);
assert.ok(s instanceof UglifyJS.AST_Toplevel, c);
assert.strictEqual(s.body.length, 1, c);
assert.strictEqual(s.body[0].TYPE, "Export" + k, c);
for (var l in stats) stats[l].forEach(function(d, j) {
var t = UglifyJS.parse(d);
assert.ok(t instanceof UglifyJS.AST_Toplevel, d);
assert.strictEqual(t.body.length, 1, d);
assert.strictEqual(t.body[0].TYPE, "Export" + l, d);
assert.strictEqual(s.equals(t), k === l && i === j, c + "\n" + d);
});
});
});
it("Should interoperate with ESTree correctly", function() {
[
"export var A = 42;",
"export default (class A {});",
"var A; export { A as '42' };",
"export { '42' } from 'path';",
"export * as '42' from 'path';",
].forEach(function(code) {
var ast = UglifyJS.parse(code);
try {
var spidermonkey = ast.to_mozilla_ast();
} catch (ex) {
assert.fail("[to_mozilla_ast] " + ex.stack);
}
try {
var ast2 = UglifyJS.AST_Node.from_mozilla_ast(spidermonkey);
} catch (ex) {
assert.fail("[from_mozilla_ast] " + ex.stack);
}
assert.strictEqual(ast2.print_to_string(), ast.print_to_string(), [
"spidermonkey:",
ast.print_to_string(),
ast2.print_to_string(),
].join("\n"));
try {
var acorn_est = acorn.parse(code, {
ecmaVersion: "latest",
locations: true,
sourceType: "module",
});
} catch (ex) {
assert.fail("[acorn.parse] " + ex.stack);
}
try {
var ast3 = UglifyJS.AST_Node.from_mozilla_ast(acorn_est);
} catch (ex) {
assert.fail("[from_acorn] " + ex.stack);
}
assert.strictEqual(ast3.print_to_string(), ast.print_to_string(), [
"acorn:",
ast.print_to_string(),
ast3.print_to_string(),
].join("\n"));
});
});
});

View File

@@ -1,3 +1,4 @@
var acorn = require("acorn");
var assert = require("assert");
var UglifyJS = require("../node");
@@ -8,15 +9,25 @@ describe("import", function() {
"import A;",
"import {};",
"import `path`;",
"{ import 'path'; }",
"import from 'path';",
"if (0) import 'path';",
"import * from 'path';",
"import 'A' from 'path';",
"import A-B from 'path';",
"import A as B from 'path';",
"import { A }, B from 'path';",
"import * as 'A' from 'path';",
"import * as A-B from 'path';",
"import * as A, B from 'path';",
"import * as A, {} from 'path';",
"import { * as A } from 'path';",
"import { * as 'A' } from 'path';",
"import { * as A-B } from 'path';",
"function f() { import 'path'; }",
"import { 42 as A } from 'path';",
"import { A-B as C } from 'path';",
"import { 'A' as 'B' } from 'path';",
].forEach(function(code) {
assert.throws(function() {
UglifyJS.parse(code);
@@ -25,4 +36,74 @@ describe("import", function() {
}, code);
});
});
it("Should compare `import` statements correctly", function() {
[
"import 'foo';",
"import 'path';",
"import A from 'path';",
"import { A } from 'path';",
"import * as A from 'path';",
"import A, { B } from 'path';",
"import A, * as B from 'path';",
"import { A as B } from 'path';",
"import A, { B, C as D } from 'path';",
].forEach(function(c, i, stats) {
var s = UglifyJS.parse(c);
assert.ok(s instanceof UglifyJS.AST_Toplevel, c);
assert.strictEqual(s.body.length, 1, c);
assert.ok(s.body[0] instanceof UglifyJS.AST_Import, c);
stats.forEach(function(d, j) {
var t = UglifyJS.parse(d);
assert.ok(t instanceof UglifyJS.AST_Toplevel, d);
assert.strictEqual(t.body.length, 1, d);
assert.ok(t.body[0] instanceof UglifyJS.AST_Import, d);
assert.strictEqual(s.equals(t), i === j, c + "\n" + d);
});
});
});
it("Should interoperate with ESTree correctly", function() {
[
"import A from 'path';",
"import * as A from 'path';",
"import A, * as B from 'path';",
"import { '42' as A, B } from 'path';",
"import A, { '42' as B } from 'path';",
].forEach(function(code) {
var ast = UglifyJS.parse(code);
try {
var spidermonkey = ast.to_mozilla_ast();
} catch (ex) {
assert.fail("[to_mozilla_ast] " + ex.stack);
}
try {
var ast2 = UglifyJS.AST_Node.from_mozilla_ast(spidermonkey);
} catch (ex) {
assert.fail("[from_mozilla_ast] " + ex.stack);
}
assert.strictEqual(ast2.print_to_string(), ast.print_to_string(), [
"spidermonkey:",
ast.print_to_string(),
ast2.print_to_string(),
].join("\n"));
try {
var acorn_est = acorn.parse(code, {
ecmaVersion: "latest",
locations: true,
sourceType: "module",
});
} catch (ex) {
assert.fail("[acorn.parse] " + ex.stack);
}
try {
var ast3 = UglifyJS.AST_Node.from_mozilla_ast(acorn_est);
} catch (ex) {
assert.fail("[from_acorn] " + ex.stack);
}
assert.strictEqual(ast3.print_to_string(), ast.print_to_string(), [
"acorn:",
ast.print_to_string(),
ast3.print_to_string(),
].join("\n"));
});
});
});

View File

@@ -1,6 +1,7 @@
var assert = require("assert");
var readFileSync = require("fs").readFileSync;
var run_code = require("../sandbox").run_code;
var semver = require("semver");
var UglifyJS = require("../..");
function read(path) {
@@ -320,6 +321,24 @@ describe("minify", function() {
});
});
describe("module", function() {
it("Should not inline `await` variables", function() {
if (semver.satisfies(process.version, "<8")) return;
var code = [
"console.log(function() {",
" return typeof await;",
"}());",
].join("\n");
assert.strictEqual(run_code("(async function(){" + code + "})();"), "undefined\n");
var result = UglifyJS.minify(code, {
module: true,
});
if (result.error) throw result.error;
assert.strictEqual(result.code, "console.log(function(){return typeof await}());");
assert.strictEqual(run_code("(async function(){" + result.code + "})();"), "undefined\n");
});
});
describe("rename", function() {
it("Should be repeatable", function() {
var code = "!function(x){return x(x)}(y);";

View File

@@ -50,12 +50,10 @@ describe("Number literals", function() {
"0.000_000_004_2e+1_0-0B101_010+0x2_A-0o5_2+4_2",
].forEach(function(code) {
var result = UglifyJS.minify(code, {
compress: {
expression: true,
},
expression: true,
});
if (result.error) throw result.error;
assert.strictEqual(result.code, "42;");
assert.strictEqual(result.code, "42");
});
});
it("Should reject invalid use of underscore", function() {

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