Compare commits

...

363 Commits

Author SHA1 Message Date
Alex Lam S.L
24b73a95fa v3.13.1 2021-03-12 06:50:05 +08:00
Alex Lam S.L
862b1b77b5 fix corner cases in merge_vars & with exports (#4762)
fixes #4761
2021-03-11 09:16:16 +08:00
Alex Lam S.L
b4944a31a4 fix corner case in merge_vars (#4760)
fixes #4759
2021-03-10 23:44:49 +08:00
Alex Lam S.L
58362d5ec7 build Math.js for verification testing (#4758) 2021-03-10 03:34:30 +08:00
Alex Lam S.L
01fa430a3e fix corner case in unused (#4757)
fixes #4756
2021-03-09 07:59:52 +08:00
Alex Lam S.L
f4ee0f651c fix corner case in unsafe (#4755) 2021-03-09 04:40:21 +08:00
Alex Lam S.L
077512d151 fix corner case in inline (#4754)
fixes #4753
2021-03-08 12:38:53 +08:00
Alex Lam S.L
e4848a7f5a speed up ufuzz asynchronous testing (#4750) 2021-03-08 04:25:56 +08:00
Alex Lam S.L
f52b0e7c31 fix corner case in side_effects (#4752)
fixes #4751
2021-03-08 04:19:51 +08:00
Alex Lam S.L
31e7d25cad fix issues uncovered by lgtm (#4749) 2021-03-07 12:44:34 +08:00
Alex Lam S.L
12babdfe20 build external projects for verification testing (#4741) 2021-03-07 12:41:52 +08:00
Alex Lam S.L
397e48b97e fix corner case in collapse_vars & reduce_vars (#4748)
fixes #4747
2021-03-07 10:33:51 +08:00
Alex Lam S.L
c7520b4b97 support new.target (#4746)
fixes #4745
2021-03-07 07:11:36 +08:00
Alex Lam S.L
ad903e9240 fix corner cases with export (#4743)
fixes #4742
2021-03-06 22:49:39 +08:00
Alex Lam S.L
83c3838b07 fix corner case in awaits (#4740)
fixes #4738
2021-03-06 04:25:44 +08:00
Alex Lam S.L
fa09f87589 fix corner case in hoist_vars (#4739)
fixes #4736
2021-03-06 04:25:32 +08:00
Alex Lam S.L
2db1a141ab speed up compress tests (#4737) 2021-03-06 01:11:05 +08:00
Alex Lam S.L
dd30ed6a9b enhance collapse_vars (#4735) 2021-03-05 13:18:01 +08:00
Alex Lam S.L
cb50a2d192 fix corner case in collapse_vars (#4733)
fixes #4732
2021-03-04 17:13:54 +08:00
Alex Lam S.L
20be5209c0 fix corner cases in ie8 & side_effects (#4731)
fixes #4729
fixes #4730
2021-03-04 03:30:07 +08:00
Alex Lam S.L
2a49760032 enhance side_effects (#4727) 2021-03-03 18:47:17 +08:00
Alex Lam S.L
04ed818f0a improve ufuzz test generation (#4724) 2021-03-03 15:42:46 +08:00
Alex Lam S.L
10ca578ee5 fix corner case in inline (#4726)
fixes #4725
2021-03-03 09:18:02 +08:00
Alex Lam S.L
955411e065 fix corner cases with class (#4723)
fixes #4720
fixes #4721
fixes #4722
2021-03-03 03:32:58 +08:00
Alex Lam S.L
adcafce048 fix corner cases in varify (#4719) 2021-03-02 23:33:58 +08:00
Alex Lam S.L
b1e05fd48a fix corner case in inline & sequences (#4718)
fixes #4717
2021-03-02 17:39:34 +08:00
Alex Lam S.L
23b51287aa fix corner case in evaluate (#4716)
fixes #4715
2021-03-02 17:33:28 +08:00
Alex Lam S.L
74dee5c445 enhance reduce_vars & varify (#4714) 2021-03-02 15:27:55 +08:00
Alex Lam S.L
ee27d87a08 enhance reduce_vars & side_effects (#4712) 2021-03-02 13:43:10 +08:00
Alex Lam S.L
62887f2c66 fix corner case with class (#4713) 2021-03-02 12:08:08 +08:00
Alex Lam S.L
68b2dadc58 enhance side_effects & unused (#4711) 2021-03-02 04:55:09 +08:00
Alex Lam S.L
bd73720061 v3.13.0 2021-03-01 23:24:17 +08:00
Alex Lam S.L
ec0440f264 fix corner cases with import (#4709)
fixes #4708
2021-03-01 07:13:49 +08:00
Alex Lam S.L
81254f67e4 support limited ufuzz testing for import (#4707) 2021-03-01 02:27:41 +08:00
Alex Lam S.L
c549ee89b9 fix corner case reduce_vars (#4706)
fixes #4705
2021-02-28 04:41:21 +08:00
Alex Lam S.L
7924a3ae8b improve export compatibility mode (#4704) 2021-02-27 21:06:23 +08:00
Alex Lam S.L
13ad10a6b5 improve export compatibility mode (#4703) 2021-02-27 14:05:36 +08:00
Alex Lam S.L
e6ebf827ce fix corner cases with export (#4699)
fixes #4698
fixes #4700
fixes #4701
fixes #4702
2021-02-27 10:15:14 +08:00
Alex Lam S.L
0a42457df6 fix corner case with arguments (#4697)
fixes #4696
2021-02-27 09:26:15 +08:00
Alex Lam S.L
ba4a771bbc support limited ufuzz testing for export (#4693)
fixes #4692
2021-02-27 04:56:34 +08:00
Alex Lam S.L
ac26993b5a fix corner cases with block-scoped functions (#4695) 2021-02-27 04:16:14 +08:00
Alex Lam S.L
ea52339502 use strict-mode-safe placeholder (#4694) 2021-02-26 16:43:53 +08:00
Alex Lam S.L
992952d8f6 fix corner cases with exports (#4691) 2021-02-26 02:22:49 +08:00
Alex Lam S.L
6d7ab63a66 fix corner cases in sequences (#4690)
fixes #4689
2021-02-25 12:48:40 +08:00
Alex Lam S.L
822b1da5d2 fix corner cases with arrow functions (#4688)
fixes #4687
2021-02-25 09:01:45 +08:00
Alex Lam S.L
72805ea73a fix corner case in collapse_vars (#4686)
fixes #4685
2021-02-25 05:31:12 +08:00
Alex Lam S.L
a5e6946f74 fix corner case in loops (#4684)
fixes #4683
2021-02-25 04:41:21 +08:00
Alex Lam S.L
b8672b55b2 fix corner case in unused (#4682)
fixes #4681
2021-02-25 02:17:28 +08:00
Alex Lam S.L
a5a958beda fix corner case in comparisons (#4680)
fixes #4679
2021-02-24 13:38:44 +00:00
Alex Lam S.L
c885660347 support nullish coalescing operator (#4678) 2021-02-24 05:57:11 +08:00
Alex Lam S.L
d68d155f93 support class literals (#4658) 2021-02-23 22:55:08 +08:00
Alex Lam S.L
e535f19189 fix corner case in templates (#4677)
fixes #4676
2021-02-22 23:59:28 +08:00
Alex Lam S.L
f9a2a9d78e enhance side_effects (#4675) 2021-02-22 15:44:16 +08:00
Alex Lam S.L
960668ccdb improve CLI usability (#4670)
closes #3308
2021-02-22 15:27:03 +08:00
Alex Lam S.L
55b59407e4 fix corner cases in reduce_vars (#4674) 2021-02-22 08:21:21 +08:00
Alex Lam S.L
b726e364c1 fix corner cases with export default (#4673) 2021-02-21 13:01:56 +08:00
Alex Lam S.L
bfe3a8b516 fix corner case with import (#4672) 2021-02-21 10:00:34 +08:00
Alex Lam S.L
ae09773ba0 parse dynamic import correctly (#4671) 2021-02-21 06:54:15 +08:00
Alex Lam S.L
8d668c2963 fix corner case in conditionals & side_effects (#4669)
fixes #4668
2021-02-20 11:13:15 +08:00
Alex Lam S.L
5f60c1b830 fix corner cases in arrow functions & rests (#4667)
fixes #4666
2021-02-19 08:26:57 +08:00
Alex Lam S.L
10de27ca3d fix corner case in reduce_vars (#4665)
fixes #4664
2021-02-19 02:04:33 +08:00
Alex Lam S.L
7b4fd858ba fix corner case in reduce_vars (#4663)
fixes #4662
2021-02-18 23:24:55 +08:00
Alex Lam S.L
a7bcd4d613 fix corner case in inline (#4660)
fixes #4659
2021-02-18 16:15:44 +08:00
Alex Lam S.L
6a2bda52f3 workaround bug in ECMAScript specification (#4656)
closes #4655
2021-02-16 23:39:06 +08:00
Alex Lam S.L
fa8aa204a0 fix corner case in reduce_vars (#4654)
fixes #4653
2021-02-16 06:46:45 +08:00
Alex Lam S.L
76b27891c6 fix syntax error in tests (#4652) 2021-02-15 14:41:07 +08:00
Alex Lam S.L
203ca2586a introduce hoist_exports (#4651) 2021-02-15 09:01:18 +08:00
Alex Lam S.L
c21f096ab8 support export statements (#4650) 2021-02-15 04:13:54 +08:00
Alex Lam S.L
b7219ac489 support import statements (#4646) 2021-02-14 04:26:43 +08:00
Alex Lam S.L
a6bb66931b improve fix for #4325 (#4649) 2021-02-14 02:24:57 +08:00
Alex Lam S.L
766742e1d3 v3.12.8 2021-02-13 21:38:27 +08:00
Alex Lam S.L
94e8944f67 avoid false positive in --reduce-test (#4648) 2021-02-13 21:15:11 +08:00
Alex Lam S.L
83197ffdb3 fix corner case in evaluate (#4645)
fixes #4644
2021-02-12 03:26:12 +08:00
Alex Lam S.L
952765be66 enhance join_vars (#4643) 2021-02-11 04:59:25 +08:00
Alex Lam S.L
083679bcad fix corner cases with asynchronous generators (#4642)
fixes #4641
2021-02-10 23:41:00 +08:00
Alex Lam S.L
f5659f292b enhance collapse_vars (#4637) 2021-02-10 23:06:12 +08:00
Alex Lam S.L
c6e287331d fix corner cases in inline (#4640)
fixes #4639
2021-02-10 20:40:57 +08:00
Alex Lam S.L
a98ec7e4df enhance side_effects (#4638) 2021-02-10 18:09:54 +08:00
Alex Lam S.L
5ec82e5801 fix corner case in reduce_vars (#4636) 2021-02-10 10:37:00 +08:00
Alex Lam S.L
c76481341c fix corner case in merge_vars (#4635) 2021-02-10 09:13:38 +08:00
Alex Lam S.L
5e6307974f fix corner case in collapse_vars (#4634)
fixes #4633
2021-02-10 08:45:36 +08:00
Alex Lam S.L
228cdf8e7e reject invalid for...of syntax (#4632) 2021-02-10 05:42:27 +08:00
Alex Lam S.L
14fedbf123 fix corner case with template literals (#4631)
fixes #4630
2021-02-09 14:21:15 +08:00
Alex Lam S.L
fcee32527b fix corner case in merge_vars (#4629)
fixes #4628
2021-02-09 12:36:12 +08:00
Alex Lam S.L
e13d1e9969 support for [await]...of statements (#4627) 2021-02-09 04:28:23 +08:00
Alex Lam S.L
aedc1e7fc9 improve false positive detection in ufuzz (#4626) 2021-02-08 20:17:14 +08:00
Alex Lam S.L
353f654038 fix corner case in --reduce-test (#4625) 2021-02-08 19:16:21 +08:00
Alex Lam S.L
357d861246 fix corner case in conditionals (#4624)
fixes #4623
2021-02-08 18:31:08 +08:00
Alex Lam S.L
fd4caf7a9c support generator functions (#4620) 2021-02-08 06:44:20 +08:00
Alex Lam S.L
c44b6399c3 fix corner case in side_effects (#4622)
fixes #4621
2021-02-07 22:40:41 +08:00
Alex Lam S.L
522cceeccf fix corner case in functions (#4619)
fixes #4618
2021-02-07 13:52:09 +08:00
Alex Lam S.L
5c84dfa151 v3.12.7 2021-02-07 02:43:47 +08:00
Alex Lam S.L
5359900b78 enhance compress on arrow and async functions (#4616) 2021-02-06 12:39:46 +08:00
Alex Lam S.L
739fa266f8 fix corner case in pure_getters (#4615)
fixes #4614
2021-02-05 09:03:51 +08:00
Alex Lam S.L
da24dfb59e fix corner cases with function inlining (#4613)
fixes #4612
2021-02-05 04:49:37 +08:00
Alex Lam S.L
a2f27c7640 fix corner cases in templates (#4610) 2021-02-02 17:39:30 +00:00
Alex Lam S.L
3c556b8689 fix corner case in arguments (#4609)
fixes #4608
2021-02-02 23:07:31 +08:00
Alex Lam S.L
7110c6923b fix corner case in templates (#4607)
fixes #4606
2021-02-02 02:29:43 +08:00
Alex Lam S.L
b27b6807cb fix corner case in collapse_vars (#4605)
fixes #4604
2021-02-01 23:24:11 +08:00
Alex Lam S.L
ba6e29d6fd introduce templates (#4603) 2021-02-01 17:20:13 +08:00
Alex Lam S.L
d4685640a0 support template literals (#4601) 2021-02-01 10:36:45 +08:00
Alex Lam S.L
ac7b5c07d7 v3.12.6 2021-02-01 01:37:32 +08:00
Alex Lam S.L
0cd4a199b0 fix corner case in conditionals (#4599)
fixes #4598
2021-01-30 16:54:29 +08:00
Alex Lam S.L
35435d4bd3 suppress false positives due to nested objects (#4597) 2021-01-29 13:21:19 +08:00
Alex Lam S.L
d0bb147639 fix corner case in inline (#4596)
fixes #4595
2021-01-27 01:30:05 +08:00
Alex Lam S.L
4723b4541e workaround tty bugs on Node.js (#4594) 2021-01-26 23:07:48 +08:00
Alex Lam S.L
9d23ba0a22 support exponentiation operator (#4593) 2021-01-25 05:48:51 +08:00
Alex Lam S.L
a08d42555a fix infinite recursion in ufuzz code generation (#4592) 2021-01-24 23:37:57 +08:00
Alex Lam S.L
fd7ad8e779 fix corner cases in collapse_vars (#4591)
fixes #4590
2021-01-24 22:15:43 +08:00
Alex Lam S.L
a36c5472d2 fix corner cases with default parameters (#4589)
fixes #4588
2021-01-24 11:00:47 +08:00
Alex Lam S.L
8bfd891c09 support BigInt literals (#4583) 2021-01-24 09:51:18 +08:00
Alex Lam S.L
ef9f7ca3e7 fix corner case in collapse_vars (#4587)
fixes #4586
2021-01-24 07:05:43 +08:00
Alex Lam S.L
acc443b2cf fix corner case in reduce_vars (#4585)
fixes #4584
2021-01-24 03:37:52 +08:00
Alex Lam S.L
f87e7be12c fix corner case in reduce_vars (#4582)
fixes #4581
2021-01-23 02:14:53 +08:00
Alex Lam S.L
c0614654d9 improve ufuzz on destructuring (#4580) 2021-01-23 02:00:26 +08:00
Alex Lam S.L
0358637725 workaround Node.js bug (#4579) 2021-01-22 11:34:30 +08:00
Alex Lam S.L
63b5b6d2b3 suppress false positives in ufuzz (#4578) 2021-01-22 02:33:00 +08:00
Alex Lam S.L
e675262d51 suppress false positives in ufuzz (#4577) 2021-01-21 14:33:31 +08:00
Alex Lam S.L
c1e771a89a fix corner case in rests (#4576)
fixes #4575
2021-01-21 07:23:06 +08:00
Alex Lam S.L
bc7a88baea suppress false positives in ufuzz (#4574) 2021-01-20 21:03:33 +08:00
Alex Lam S.L
018e0350f8 workaround GitHub Actions bug (#4573) 2021-01-20 20:17:58 +08:00
Alex Lam S.L
d37ee4d41c support asynchronous test cases properly (#4529) 2021-01-20 07:27:32 +08:00
Alex Lam S.L
7793c6c389 v3.12.5 2021-01-20 06:30:01 +08:00
Alex Lam S.L
90ec468240 fix corner case in dead_code (#4571)
fixes #4570
2021-01-19 09:33:57 +08:00
Jimb Esser
994293e972 Fix overwriting existing sourcesContent in sourcemaps (#4567) 2021-01-19 07:44:24 +08:00
Alex Lam S.L
b57bae4b9e fix corner case in reduce_vars (#4569)
fixes #4568
2021-01-19 06:34:48 +08:00
Alex Lam S.L
e23a10f7f9 fix corner case in loops (#4565)
fixes #4564
2021-01-18 06:36:59 +08:00
Alex Lam S.L
884ec4e8a5 improve false positive detection in ufuzz (#4566) 2021-01-18 06:35:53 +08:00
Alex Lam S.L
e616916de5 fix corner case in reduce_vars (#4563)
fixes #4562
2021-01-18 01:47:07 +08:00
Alex Lam S.L
8d21516623 fix corner cases in reduce_vars (#4561)
fixes #4560
2021-01-16 16:55:10 +08:00
Alex Lam S.L
74368c3dba fix corner case in unused (#4559)
fixes #4558
2021-01-16 02:37:27 +08:00
Alex Lam S.L
18dbceb36f fix corner case in unused (#4557)
fixes #4556
2021-01-15 12:33:17 +08:00
Alex Lam S.L
65d39a3702 fix corner cases in collapse_vars (#4555)
fixes #4554
2021-01-15 00:22:34 +08:00
Alex Lam S.L
24917e7084 fix corner case in evaluate (#4553)
fixes #4552
2021-01-13 22:17:24 +08:00
Alex Lam S.L
e84957e3da suppress invalid test generation in ufuzz (#4551) 2021-01-13 04:29:39 +08:00
Alex Lam S.L
c11a748908 fix corner case in merge_vars (#4550)
fixes #4548
2021-01-13 03:48:46 +08:00
Alex Lam S.L
90017051f2 document v8 bug (#4549)
closes #4547
2021-01-13 03:48:33 +08:00
Alex Lam S.L
fc816628c1 fix corner case in side_effects (#4545)
fixes #4544
2021-01-13 01:08:16 +08:00
Alex Lam S.L
46ad273df4 enhance rests (#4546) 2021-01-13 00:00:19 +08:00
Alex Lam S.L
b689028e87 fix corner case in unsafe_math (#4543)
fixes #4542
2021-01-12 12:07:01 +08:00
Alex Lam S.L
1e831df1f6 fix corner case in side_effects (#4541)
fixes #4540
2021-01-12 09:12:43 +08:00
Alex Lam S.L
c12486bab4 fix corner case in rests (#4539)
fixes #4538
2021-01-12 09:12:30 +08:00
Alex Lam S.L
52e94a0723 update command line examples (#4536) 2021-01-11 09:12:27 +08:00
Alex Lam S.L
16b97f9558 fix corner case in arguments (#4535)
fixes #4534
2021-01-11 04:17:39 +08:00
Alex Lam S.L
dbfa5d4d14 fix corner case in ie8 (#4532)
fixes #4531
2021-01-11 00:01:49 +08:00
Alex Lam S.L
ba54d074d8 support asynchronous arrow functions (#4530) 2021-01-10 11:34:26 +08:00
Alex Lam S.L
0818d396c5 fix corner case in mangle (#4528)
fixes #4527
2021-01-10 04:20:43 +08:00
Alex Lam S.L
770f3ba5fe fix corner cases with rest parameters (#4526)
fixes #4525
2021-01-09 08:38:51 +08:00
Alex Lam S.L
553034fe52 fix corner case in merge_vars (#4524)
fixes #4523
2021-01-08 15:49:14 +08:00
Alex Lam S.L
7fe8c9150a fix corner case in assignments (#4522)
fixes #4521
2021-01-08 13:03:21 +08:00
Alex Lam S.L
6c419bc083 implement UGLIFY_BUG_REPORT (#4516) 2021-01-07 16:53:29 +08:00
Alex Lam S.L
25321df959 fix corner cases with arguments (#4520)
fixes #4519
2021-01-07 16:53:14 +08:00
Alex Lam S.L
cf1b0165af fix corner case in hoist_vars (#4518)
fixes #4517
2021-01-07 15:05:48 +08:00
Alex Lam S.L
c3d358a5b8 support rest parameters (#4515) 2021-01-07 10:04:09 +08:00
Alex Lam S.L
68497d0258 update issue templates (#4514) 2021-01-06 05:37:30 +08:00
Alex Lam S.L
71c3d04681 fix corner case in side_effects (#4513)
fixes #4512
2021-01-06 02:11:30 +08:00
Alex Lam S.L
4c89550c43 fix corner case indefault_values (#4511)
fixes #4510
2021-01-06 01:26:19 +08:00
Alex Lam S.L
7ebfb22d16 fix corner cases in inline & unused (#4509)
fixes #4508
2021-01-06 00:15:12 +08:00
Alex Lam S.L
6eceac0966 enhance inline & side_effects (#4506) 2021-01-05 15:02:49 +08:00
Alex Lam S.L
fc5aee662d fix corner case in merge_vars (#4505)
fixes #4504
2021-01-05 14:23:46 +08:00
Alex Lam S.L
5fbbb43839 fix corner cases in inline & side_effects (#4503)
fixes #4502
2021-01-04 10:17:32 +08:00
Alex Lam S.L
df2cfcb5fc fix corner case in evaluate (#4501)
fixes #4500
2021-01-04 02:31:20 +08:00
Alex Lam S.L
623a0d920f fix toggling of AST validation (#4499) 2021-01-03 11:09:10 +08:00
Alex Lam S.L
e8c04f8cb6 suppress invalid AST transform in --reduce-test (#4498) 2021-01-03 10:34:46 +08:00
Alex Lam S.L
110c1ac097 fix corner case in default_values (#4497)
fixes #4496
2021-01-02 22:51:53 +08:00
Alex Lam S.L
15ef272790 introduce awaits (#4495) 2021-01-02 20:35:48 +08:00
Alex Lam S.L
b3a706114c enhance if_return & side_effects (#4494) 2021-01-02 12:39:51 +08:00
Alex Lam S.L
cc2d7acaf0 enhance inline, sequences & side_effects (#4493) 2021-01-02 09:43:05 +08:00
Alex Lam S.L
dfb86ccdd1 fix corner case in conditionals (#4492) 2021-01-02 07:53:15 +08:00
Alex Lam S.L
0417a69c3e enhance collapse_vars & dead_code (#4491) 2021-01-01 21:52:14 +08:00
Alex Lam S.L
2dbafbb4ee fix corner case in reduce_vars (#4490)
fixes #4489
2021-01-01 12:56:13 +08:00
Alex Lam S.L
311c074622 fix corner case in functions (#4488)
fixes #4487
2021-01-01 10:39:40 +08:00
Alex Lam S.L
a10c7793bb v3.12.4 2021-01-01 08:47:24 +08:00
Alex Lam S.L
0b7d65d331 fix corner case with arguments (#4486)
fixes #4485
2020-12-31 14:55:05 +08:00
Alex Lam S.L
8b954b022b fix corner case with default values (#4484)
fixes #4483
2020-12-31 01:47:00 +08:00
Alex Lam S.L
0013cbf91f improve false positive detection in ufuzz (#4482) 2020-12-30 21:53:03 +08:00
Alex Lam S.L
1956edd503 fix corner cases with arguments (#4481)
fixes #4480
2020-12-30 00:22:03 +08:00
Alex Lam S.L
560ccc1221 enhance reduce_vars (#4479) 2020-12-29 19:43:12 +08:00
Alex Lam S.L
10a71c182b fix corner case in arguments (#4477)
fixes #4476
2020-12-29 18:58:29 +08:00
Alex Lam S.L
ddc0ed7072 expand test options (#4475)
- fix corner cases in `hoist_vars` & `keep_fnames`
2020-12-29 06:17:52 +08:00
Alex Lam S.L
c00efe56f4 workaround asynchronous tty bugs on Node.js (#4473) 2020-12-28 13:32:07 +08:00
Alex Lam S.L
28bcdbd7df fix corner case in inline (#4472)
fixes #4471
2020-12-28 10:05:59 +08:00
Alex Lam S.L
6a8aed2049 fix corner case in unused (#4469)
fixes #4468
2020-12-27 20:06:50 +08:00
Alex Lam S.L
a8785fb694 workaround v8 bug with labels (#4467)
closes #4466
2020-12-27 13:32:18 +08:00
Alex Lam S.L
dd6d7b3d88 workaround schedule delays on GitHub Actions (#4463) 2020-12-26 17:27:03 +08:00
Alex Lam S.L
94f3819dc6 fix corner case in reduce_vars & unused (#4465)
fixes #4464
2020-12-26 16:52:16 +08:00
Alex Lam S.L
be1f5199f4 fix corner cases in collapse_vars (#4462)
fixes #4460
fixes #4461
2020-12-26 13:40:31 +08:00
Alex Lam S.L
95aea0e33c fix corner case in reduce_vars (#4459)
fixes #4458
2020-12-25 22:50:11 +08:00
Alex Lam S.L
a1b2735dd8 fix corner case in unused (#4457)
fixes #4456
2020-12-25 20:10:58 +08:00
Alex Lam S.L
f345175bc2 fix corner case in merge_vars (#4455)
fixes #4454
2020-12-25 19:27:05 +08:00
Alex Lam S.L
bb45f48ab7 workaround v8 heisenbug (#4453) 2020-12-25 13:14:36 +08:00
Alex Lam S.L
b2f27fd873 fix corner case in functions & reduce_vars (#4452)
fixes #4451
2020-12-25 08:38:24 +08:00
Alex Lam S.L
ced32f9bd8 enhance default_values (#4450) 2020-12-25 07:31:34 +08:00
Alex Lam S.L
dfc3ec9cef fix corner case in pure_getters (#4449)
fixes #4448
2020-12-25 03:58:23 +08:00
Alex Lam S.L
1896694532 fix & enhance collapse_vars (#4447)
fixes #4446
2020-12-24 17:02:18 +08:00
Alex Lam S.L
5f269cd573 fix corner case in collapse_vars (#4445)
fixes #4444
2020-12-24 10:56:22 +08:00
Alex Lam S.L
6988cd9558 replace keep_fargs default to false (#4443) 2020-12-24 09:56:02 +08:00
Alex Lam S.L
2390fae5c4 support default values (#4442) 2020-12-24 06:22:55 +08:00
Alex Lam S.L
56fce2131c fix corner case in pure_getters (#4441)
fixes #4440
2020-12-24 04:09:09 +08:00
Alex Lam S.L
7e575e9d7f fix corner case in if_return (#4439)
fixes #4438
2020-12-24 04:08:57 +08:00
Alex Lam S.L
cb4a02949e fix corner case with NaN (#4437)
fixes #4436
2020-12-23 07:01:50 +08:00
Alex Lam S.L
f85a206b9e fix corner case when parsing expression (#4435) 2020-12-23 02:16:04 +08:00
Alex Lam S.L
bba7cd0a70 v3.12.3 2020-12-22 23:59:53 +08:00
Alex Lam S.L
e1b2026929 improve object function generation in ufuzz (#4434) 2020-12-21 15:32:50 +08:00
Alex Lam S.L
c319030373 fix corner case in reduce_vars (#4433)
fixes #4432
2020-12-21 14:03:18 +08:00
Alex Lam S.L
47b63ed1a0 fix corner case in collapse_vars (#4431)
fixes #4430
2020-12-20 22:54:27 +08:00
Alex Lam S.L
7aefe97083 parse destructuring under strict mode correctly (#4429) 2020-12-20 20:48:51 +08:00
Alex Lam S.L
89198e0ad4 improve destructuring generation in ufuzz (#4428) 2020-12-20 13:38:56 +08:00
Alex Lam S.L
caea6aac81 handle destructuring catch in --reduce-test (#4427) 2020-12-20 11:22:45 +08:00
Alex Lam S.L
f5224ca1f5 fix corner case with destructuring catch (#4426)
fixes #4425
2020-12-20 10:31:32 +08:00
Alex Lam S.L
b7c49b72b3 support async function within object literal (#4424) 2020-12-20 08:19:04 +08:00
Alex Lam S.L
8ce3c7d70f fix corner case in evaluate & reduce_vars (#4423)
fixes #4422
2020-12-20 05:47:15 +08:00
Alex Lam S.L
87cf715213 fix corner case with destructuring catch (#4421)
fixes #4420
2020-12-20 05:47:01 +08:00
Alex Lam S.L
2c9c72e06c suppress false positives in ufuzz (#4419) 2020-12-20 02:31:09 +08:00
Alex Lam S.L
882968c68c fix corner case in inline (#4418)
fixes #4417
2020-12-20 01:24:29 +08:00
Alex Lam S.L
acc2d7d845 fix corner case in objects (#4416)
fixes #4415
2020-12-20 00:14:57 +08:00
Alex Lam S.L
9a5aede941 fix corner case in reduce_vars & unused (#4414)
fixes #4413
2020-12-19 12:47:46 +08:00
Alex Lam S.L
e6dd471f8f support destructuring of catch variable (#4412) 2020-12-19 12:28:38 +08:00
Alex Lam S.L
0f55bd92f1 fix corner case in arguments (#4411)
fixes #4410
2020-12-19 04:53:53 +08:00
Alex Lam S.L
7d9dad0289 fix corner case with parentheses (#4409)
fixes #4408
2020-12-19 01:01:49 +08:00
Alex Lam S.L
44e494f16f fix corner case in merge_vars (#4407)
fixes #4406
2020-12-19 00:52:37 +08:00
Alex Lam S.L
2415a72e75 fix corner case in unused (#4405)
fixes #4404
2020-12-18 23:45:41 +08:00
Alex Lam S.L
9c0718b162 enhance arrows (#4403) 2020-12-18 14:55:20 +08:00
Alex Lam S.L
d2c50ace99 fix corner case in merge_vars (#4402)
fixes #4401
2020-12-18 12:20:43 +08:00
Alex Lam S.L
1b646d3bc4 fix corner case in arguments (#4400)
fixes #4399
2020-12-18 10:12:01 +08:00
Alex Lam S.L
82d2aa4acf fix corner case in arguments (#4398)
fixes #4397
2020-12-18 09:42:07 +08:00
Alex Lam S.L
c1256c399a fix corner case in arguments (#4396)
fixes #4395
2020-12-18 08:41:13 +08:00
Alex Lam S.L
2c637fea8a fix corner case in evaluate & reduce_vars (#4394)
fixes #4393
2020-12-18 07:16:04 +08:00
Alex Lam S.L
4fa54b075c enhance reduce_vars (#4392) 2020-12-18 06:18:47 +08:00
Alex Lam S.L
ab82be82b2 fix corner case in collapse_vars (#4391)
fixes #4390
2020-12-18 03:10:16 +08:00
Alex Lam S.L
02fdcfde01 fix corner case in inline (#4389)
fixes #4388
2020-12-18 00:55:19 +08:00
Alex Lam S.L
a96f087ac3 support arrow function (#4385) 2020-12-17 18:23:41 +08:00
Alex Lam S.L
75e9fd8417 fix corner case in arguments (#4387)
fixes #4386
2020-12-17 13:51:34 +08:00
Alex Lam S.L
f68e267830 fix corner case in reduce_vars (#4384)
fixes #4383
2020-12-17 04:47:48 +08:00
Alex Lam S.L
8b10b93ee1 v3.12.2 2020-12-16 14:11:48 +08:00
Alex Lam S.L
549de028b6 fix corner case in objects (#4381)
fixes #4380
2020-12-15 21:23:55 +08:00
Alex Lam S.L
f579f1aa47 emulate global context in Node.js & web (#4379) 2020-12-14 02:05:07 +08:00
Alex Lam S.L
fcc40d0502 fix corner case in dead_code (#4378)
fixes #4377
2020-12-14 00:03:44 +08:00
Alex Lam S.L
b309527264 maintain compatibility options when testing (#4376) 2020-12-13 14:26:45 +08:00
Alex Lam S.L
5d19bb8d5d fix corner case in booleans (#4375)
fixes #4374
2020-12-13 05:01:38 +08:00
Alex Lam S.L
af97629912 fix corner case in dead_code (#4373)
fixes #4372
2020-12-13 02:24:18 +08:00
Alex Lam S.L
8c000033d3 clarify corner case in object literal (#4371)
closes #4366
2020-12-12 07:42:29 +08:00
Alex Lam S.L
fd0d28e465 fix corner case in spread (#4370) 2020-12-12 06:45:59 +08:00
Alex Lam S.L
2123f38394 fix asynchronous state tracking in ufuzz (#4369) 2020-12-12 05:19:56 +08:00
Alex Lam S.L
58dff9ada3 fix corner cases in unused & varify (#4368)
fixes #4365
2020-12-12 04:45:35 +08:00
Alex Lam S.L
4fdec765bc gate language features in ufuzz automatically (#4367) 2020-12-12 03:43:12 +08:00
Alex Lam S.L
1020d37256 fix corner case in spread (#4364)
fixes #4363
2020-12-12 02:19:11 +08:00
Alex Lam S.L
076739db07 fix corner case in unused (#4362)
fixes #4361
2020-12-12 00:57:05 +08:00
Alex Lam S.L
515e93d88a fix corner case in collapse_vars (#4360)
fixes #4359
2020-12-12 00:07:28 +08:00
Alex Lam S.L
57105b299e fix corner cases with spread syntax (#4358) 2020-12-11 06:59:21 +08:00
Alex Lam S.L
77e1bda426 improve fix for #4355 (#4357) 2020-12-11 00:48:41 +08:00
Alex Lam S.L
a59593cac8 fix corner case in loops & unused (#4356)
fixes #4355
2020-12-10 15:45:39 +08:00
Alex Lam S.L
046bbde9d4 fix corner case in keep_fargs & reduce_vars (#4354)
fixes #4353
2020-12-09 01:41:10 +08:00
Alex Lam S.L
fea9da9866 forbid AST_Await in computed function arguments (#4352)
fixes #4351
2020-12-08 12:59:08 +08:00
Alex Lam S.L
4733159782 fix corner cases with await (#4350)
fixes #4349
2020-12-08 11:26:03 +08:00
Alex Lam S.L
5fba98608c fix corner case in reduce_vars (#4348)
fixes #4347
2020-12-08 08:52:14 +08:00
Alex Lam S.L
c587d7917d introduce spread (#4346)
fixes #4345
2020-12-08 06:51:20 +08:00
Alex Lam S.L
336336f53f fix corner case with parentheses around await (#4344) 2020-12-08 04:29:54 +08:00
Alex Lam S.L
4bde50ce85 fix corner case in side_effects (#4343)
fixes #4342
2020-12-07 17:25:04 +08:00
Alex Lam S.L
fbecedf94c fix corner case in evaluate (#4341)
fixes #4340
2020-12-07 16:05:11 +08:00
Alex Lam S.L
2f31f95095 improve ufuzz (#4339) 2020-12-07 16:04:51 +08:00
Alex Lam S.L
6b603e1a62 fix corner case in unused (#4338)
fixes #4337
2020-12-07 13:23:53 +08:00
Alex Lam S.L
499f8d89ff fix corner case in inline (#4336)
fixes #4335
2020-12-07 11:30:37 +08:00
Alex Lam S.L
9eb65f3af3 extend trailing comma support (#4334) 2020-12-07 10:07:34 +08:00
Alex Lam S.L
2cbbf5c375 support async function (#4333) 2020-12-07 05:22:40 +08:00
Alex Lam S.L
3c384cf9a8 fix corner case in collapse_vars (#4332)
fixes #4331
2020-12-06 18:30:50 +08:00
Alex Lam S.L
37f4f56752 fix corner case in properties (#4330)
fixes #4329
2020-12-06 13:59:04 +08:00
Alex Lam S.L
1e4985ed9e support spread syntax (#4328) 2020-12-06 05:19:31 +08:00
Alex Lam S.L
d2d56e301e v3.12.1 2020-12-01 01:46:27 +08:00
Alex Lam S.L
9d34f8428b fix corner case in side_effects (#4326)
fixes #4325
2020-11-29 10:05:48 +08:00
Alex Lam S.L
f045e2b460 fix corner case in merge_vars (#4324)
fixes #4323
2020-11-29 05:38:24 +08:00
Alex Lam S.L
8791f258e3 fix corner case in inline (#4322)
fixes #4321
2020-11-29 03:48:42 +08:00
Alex Lam S.L
af1cca25bf fix corner case in inline (#4320)
fixes #4319
2020-11-27 01:31:06 +08:00
Alex Lam S.L
9b3a363604 fix infinite recursion in ufuzz (#4318) 2020-11-25 09:33:42 +08:00
Alex Lam S.L
1e8fa1aa1d fix corner case in passes & reduce_vars (#4316)
fixes #4315
2020-11-23 07:05:20 +08:00
Alex Lam S.L
9f67866147 v3.12.0 2020-11-23 01:10:39 +08:00
Alex Lam S.L
645d5a348b workaround Safari quirks (#4314)
fixes #1753
2020-11-21 10:30:46 +08:00
Alex Lam S.L
cf120c7cea fix corner case in merge_vars & reduce_vars (#4313)
fixes #4312
2020-11-21 08:57:59 +08:00
Alex Lam S.L
8d30902ba9 fix corner case in mangle (#4311) 2020-11-21 08:05:40 +08:00
Alex Lam S.L
02459cddf9 gate galio workaround (#4310) 2020-11-21 03:37:33 +08:00
Alex Lam S.L
1b579779be fix corner case in collapse_vars (#4309)
fixes #4308
2020-11-20 06:23:37 +08:00
Alex Lam S.L
b18b70f63b fix corner case in hoist_props (#4307) 2020-11-20 00:02:25 +08:00
Alex Lam S.L
641406d491 fix corner cases in reduce_vars & unused (#4306) 2020-11-19 11:25:36 +08:00
Alex Lam S.L
134ef0b1eb fix corner case in dead_code (#4304) 2020-11-19 08:34:55 +08:00
Alex Lam S.L
db87dcf13e enhance varify (#4303) 2020-11-19 07:58:33 +08:00
Alex Lam S.L
aecbabc587 fix corner case in merge_vars (#4302)
fixes #4301
2020-11-19 05:44:47 +08:00
Alex Lam S.L
fd6544b340 fix corner case reduce_vars (#4300)
fixes #4297
2020-11-19 01:11:28 +08:00
Alex Lam S.L
f6a83f7944 fix corner case in merge_vars (#4299)
fixes #4298
2020-11-18 23:43:55 +08:00
Alex Lam S.L
35283e5dd1 enhance arguments (#4296) 2020-11-18 11:39:32 +08:00
Alex Lam S.L
7a51c17ff0 fix corner case in merge_vars (#4295)
fixes #4294
2020-11-18 09:32:53 +08:00
Alex Lam S.L
aff842f2f9 fix corner case in arguments (#4293)
fixes #4291
2020-11-18 08:54:58 +08:00
Alex Lam S.L
0bedd031da fix corner cases in collapse_vars, unused & varify (#4292)
fixes #4290
2020-11-18 08:22:54 +08:00
Alex Lam S.L
caa92aea5d fix corner case in merge_vars (#4289)
fixes #4288
2020-11-18 04:03:20 +08:00
Alex Lam S.L
383163afa6 fix corner case in collapse_vars (#4287)
fixes #4286
2020-11-17 18:03:31 +08:00
Alex Lam S.L
8a83c8dd46 fix corner cases in collapse_vars & dead_code (#4285)
fixes #4284
2020-11-17 16:23:50 +08:00
Alex Lam S.L
2a612fd472 fix corner case in reduce_vars (#4283)
fixes #4282
2020-11-17 14:43:04 +08:00
Alex Lam S.L
b9798a01a8 fix corner case in reduce_vars (#4281)
fixes #4280
2020-11-17 12:59:44 +08:00
Alex Lam S.L
6dbacb5e3f enhance varify (#4279) 2020-11-17 12:35:00 +08:00
Alex Lam S.L
e5f80afc53 support destructured literals (#4278) 2020-11-17 08:01:24 +08:00
Alex Lam S.L
42e34c870a fix corner case in unused (#4277)
fixes #4276
2020-11-17 02:06:00 +08:00
Alex Lam S.L
e390e7e124 v3.11.6 2020-11-14 22:21:19 +08:00
Alex Lam S.L
6fd5b5b371 fix corner case in loops (#4275)
fixes #4274
2020-11-14 02:08:05 +08:00
Alex Lam S.L
fba27bfb71 fix corner case in evaluate (#4272)
fixes #4271
2020-11-11 00:06:13 +08:00
Alex Lam S.L
41310e6404 fix corner case in objects (#4270)
fixes #4269
2020-11-09 10:47:02 +08:00
Alex Lam S.L
91fc1c82b5 support computed property name in object literal (#4268) 2020-11-08 23:38:32 +08:00
Alex Lam S.L
810cd40356 fix corner case in inline (#4266)
fixes #4265
2020-11-08 18:50:08 +08:00
Alex Lam S.L
1cbd07e789 support shorthand method name in object literal (#4264) 2020-11-08 13:17:53 +08:00
Alex Lam S.L
b82de04775 support shorthand property name in object literal (#4263) 2020-11-08 10:44:44 +08:00
Alex Lam S.L
4bbeb09f7c fix corner case in reduce_vars (#4262)
fixes #4261
2020-11-07 10:00:04 +08:00
Alex Lam S.L
c2f6fd5fde fix corner case in functions (#4260)
fixes #4259
2020-11-06 03:55:25 +08:00
Alex Lam S.L
af4ea3ff69 v3.11.5 2020-11-03 08:59:02 +08:00
Alex Lam S.L
e7643248a3 fix corner case in merge_vars (#4258)
fixes #4257
2020-11-02 01:01:00 +08:00
Alex Lam S.L
68091dbf69 fix corner case in merge_vars (#4256)
fixes #4255
2020-11-01 14:34:07 +08:00
Alex Lam S.L
cbf7269296 fix corner case in merge_vars (#4254)
fixes #4253
2020-11-01 10:37:21 +08:00
Alex Lam S.L
d8563caba7 improve resilience against spurious time-outs (#4252) 2020-10-30 11:06:48 +08:00
Alex Lam S.L
2e0ad40fe6 fix corner case in ie8 (#4251)
fixes #4250
2020-10-30 11:06:31 +08:00
Alex Lam S.L
5d12abc41b fix corner cases in collapse_vars (#4249)
fixes #4248
2020-10-30 10:04:23 +08:00
Alex Lam S.L
79e5c3f564 improve warnings (#4247)
closes #4244
2020-10-27 17:39:33 +08:00
Alex Lam S.L
607f87c5cd fix corner case in booleans (#4246)
fixes #4245
2020-10-26 18:53:58 +08:00
Alex Lam S.L
b2775746a7 v3.11.4 2020-10-25 23:40:42 +00:00
Alex Lam S.L
e478da24c7 fix corner case in collapse_vars (#4243)
fixes #4242
2020-10-24 22:44:20 +08:00
Alex Lam S.L
c5df8355ba fix corner case in loops & unused (#4241)
fixes #4240
2020-10-24 13:33:48 +08:00
Alex Lam S.L
ff38d2471f improve resilience against npm failures (#4239) 2020-10-24 11:22:13 +08:00
Alex Lam S.L
8e86d05c32 fix corner case in merge_vars (#4238)
fixes #4237
2020-10-24 10:19:43 +08:00
Alex Lam S.L
9e40abeded fix corner case in unused (#4236)
fixes #4235
2020-10-22 22:19:47 +08:00
Alex Lam S.L
23ca7d675f fix corner case in functions (#4234)
fixes #4233
2020-10-22 10:13:11 +08:00
Alex Lam S.L
fd8c0212b8 fix corner case in ie8 (#4232)
fixes #4231
2020-10-20 14:02:39 +08:00
Alex Lam S.L
256950c2c0 fix corner case in ie8 (#4230)
fixes #4229
2020-10-20 06:13:23 +08:00
Alex Lam S.L
8ecaa40c6e extend support for Unicode (#4228) 2020-10-19 09:34:17 +08:00
Alex Lam S.L
96bf7fceab support let (#4227) 2020-10-19 08:32:39 +08:00
Alex Lam S.L
6c7226c10e v3.11.3 2020-10-19 07:25:47 +08:00
Alex Lam S.L
dc575919e2 fix corner case in side_effects (#4226)
fixes #4225
2020-10-18 22:13:10 +08:00
Alex Lam S.L
4298201938 flush stdout from ufuzz jobs properly (#4224) 2020-10-16 21:56:54 +08:00
Alex Lam S.L
4f833937fe fix corner case in inline (#4223)
fixes #4222
2020-10-15 21:52:40 +08:00
Alex Lam S.L
3d71e97dd1 fix corner cases in braces & sequences (#4221)
fixes #4220
2020-10-14 23:39:35 +08:00
Alex Lam S.L
7f35d9cee0 fix corner case in reduce_vars (#4219)
fixes #4218
2020-10-14 07:58:04 +08:00
Alex Lam S.L
9f8106e1d8 fix corner case in collapse_vars (#4217)
fixes #4216
2020-10-14 07:18:26 +08:00
Alex Lam S.L
b7b8435721 fix corner case in evaluate (#4215)
fixes #4214
2020-10-14 02:49:45 +08:00
Alex Lam S.L
c0c04c33bb fix corner cases in dead_code & reduce_vars (#4213)
fixes #4212
2020-10-14 00:09:17 +08:00
Alex Lam S.L
0e234a25c5 fix corner case in reduce_vars (#4211)
fixes #4210
2020-10-13 15:52:03 +08:00
Alex Lam S.L
3096f6fdad restore inline functionality disabled by #4204 (#4209) 2020-10-13 09:33:49 +08:00
Alex Lam S.L
176c09c6a5 fix corner case in reduce_vars & unused (#4208)
fixes #4207
2020-10-13 07:32:17 +08:00
Alex Lam S.L
9272f662c0 fix corner case in collapse_vars (#4206)
fixes #4205
2020-10-13 01:30:21 +08:00
Alex Lam S.L
4d33cb2f94 fix corner case in inilne (#4204)
fixes #4202
2020-10-12 23:10:32 +08:00
Alex Lam S.L
00d0eda85b fix corner case in arguments (#4201)
fixes #4200
2020-10-12 19:03:21 +08:00
Alex Lam S.L
1cdf810f0b fix corner case in reduce_vars (#4203)
fixes #4198
2020-10-12 19:02:44 +08:00
Alex Lam S.L
b512726cf3 fix corner case in collapse_vars (#4199)
fixes #4197
2020-10-12 14:13:17 +08:00
Alex Lam S.L
9b7a13c8c7 fix corner case in ie8 & mangle (#4196)
fixes #4195
2020-10-12 12:43:26 +08:00
Alex Lam S.L
74ff6ce261 fix corner case in dead_code (#4194)
fixes #4193
2020-10-12 11:09:26 +08:00
Alex Lam S.L
b1b8898e7c fix corner case in functions (#4192)
fixes #4191
2020-10-12 09:26:56 +08:00
Alex Lam S.L
55451e7b78 support const (#4190) 2020-10-12 01:18:57 +08:00
Alex Lam S.L
ffcce28ce1 v3.11.2 2020-10-11 21:19:25 +08:00
Alex Lam S.L
9c0feb69e5 fix corner case in reduce_vars (#4189)
fixes #4188
2020-10-07 22:01:39 +08:00
Alex Lam S.L
bc6e105174 fix corner case in ie8 (#4187)
fixes #4186
2020-10-06 09:20:41 +08:00
Alex Lam S.L
b91a2459c0 fix corner case in unused (#4185)
fixes #4184
2020-10-05 18:59:03 +08:00
Alex Lam S.L
b7a57fc69d fix corner case in loops (#4183)
fixes #4182
2020-10-05 17:28:46 +08:00
Alex Lam S.L
2dbe40b01b enhance conditionals (#4181) 2020-10-05 15:55:37 +08:00
Alex Lam S.L
813ac3ba96 enhance loops (#4180) 2020-10-05 08:26:59 +08:00
Alex Lam S.L
220dc95c0d clean up scope-related variables (#4179) 2020-10-05 06:56:52 +08:00
Alex Lam S.L
8f0521d51d retrofit try-catch-finally as block-scoped (#4178)
- support optional catch binding
2020-10-05 05:30:14 +08:00
Alex Lam S.L
f9946767c9 retrofit AST_BlockStatement as block-scoped (#4177) 2020-10-05 01:58:50 +08:00
Alex Lam S.L
58ac5b9bd5 extend support for numeral literals (#4176) 2020-10-05 00:05:03 +08:00
Alex Lam S.L
66140b459e enhance side_effects (#4175) 2020-10-04 23:43:49 +08:00
122 changed files with 30286 additions and 3215 deletions

View File

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

51
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,51 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
<!-- Note: sub-optimal but correct code is not a bug -->
**Uglify version (`uglifyjs -V`)**
**JavaScript input**
<!--
A complete parsable JS program exhibiting the issue with UglifyJS alone
- without third party tools or libraries.
Ideally the input should be as small as possible, but may be large if isolating
the problem proves to be difficult. The most important thing is that the
standalone program reliably exhibits the bug when minified. Provide a link to a
gist if necessary.
Solely providing minified output without the original uglify JS input is not
useful in determining the cause of the problem. Issues without a reproducible
test case will be closed.
-->
**The `uglifyjs` CLI command executed or `minify()` options used.**
<!--
Command-line or API call to UglifyJS without third party tools or libraries.
For users using bundlers or transpilers, you may be able to gather the required
information through setting the `UGLIFY_BUG_REPORT` environment variable:
export UGLIFY_BUG_REPORT=1 (bash)
set UGLIFY_BUG_REPORT=1 (Command Prompt)
$Env:UGLIFY_BUG_REPORT=1 (PowerShell)
before running your usual build process. The resulting "minified" output should
contain the necessary details for this report.
-->
**JavaScript output or error produced.**
<!--
Only minified code that produces different output (or error) from the original
upon execution would be considered a bug.
-->

55
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,55 @@
name: Build testing
on:
pull_request:
push:
branches: [ master ]
jobs:
ufuzz:
strategy:
fail-fast: false
matrix:
options: [ '-mb braces', '-mc', '--toplevel -mc passes=10,pure_getters,unsafe' ]
script: [ acorn.sh, buble.sh, butternut.sh, mathjs.sh, rollup-es.sh, rollup-ts.sh, sucrase.sh ]
include:
- node: '14'
script: acorn.sh
- node: '14'
script: buble.sh
- node: '14'
script: butternut.sh
- node: '14'
script: mathjs.sh
- node: '8'
script: rollup-es.sh
- node: '14'
script: rollup-ts.sh
- node: '14'
script: sucrase.sh
name: ${{ matrix.script }} ${{ matrix.options }}
runs-on: ubuntu-latest
env:
NODE: ${{ matrix.node }}
OPTIONS: ${{ matrix.options }}
SCRIPT: ${{ matrix.script }}
steps:
- uses: actions/checkout@v2
- name: Perform uglify, build & test
shell: bash
run: |
git clone --branch v1.6.0 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add $NODE && nvs use $NODE'; do
cd ~/.nvs
while !(git clean -xdf); do echo "'git clean' failed - retrying..."; done
cd -
done
. ~/.nvs/nvs.sh --version
nvs use $NODE
node --version
npm config set audit false
npm config set optional false
npm config set save false
npm config set strict-ssl false
npm config set update-notifier false
npm --version
while !(npm install); do echo "'npm install' failed - retrying..."; done
./test/release/$SCRIPT $OPTIONS

View File

@@ -7,13 +7,13 @@ jobs:
test:
strategy:
matrix:
node: [ "0.8", "0.10", "0.12", "4", "6", "8", "10", "12", latest ]
node: [ '0.8', '0.10', '0.12', '4', '6', '8', '10', '12', '14', latest ]
os: [ ubuntu-latest, windows-latest ]
script: [ compress, mocha, release/benchmark, release/jetstream ]
exclude:
- node: "0.8"
- node: '0.8'
script: release/benchmark
- node: "0.8"
- node: '0.8'
script: release/jetstream
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
runs-on: ${{ matrix.os }}
@@ -29,7 +29,7 @@ jobs:
- name: Perform tests
shell: bash
run: |
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
git clone --branch v1.6.0 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add $NODE && nvs use $NODE'; do
cd ~/.nvs
while !(git clean -xdf); do echo "'git clean' failed - retrying..."; done

View File

@@ -2,7 +2,7 @@ name: Fuzzing
on:
pull_request:
schedule:
- cron: "*/5 * * * *"
- cron: '*/5 * * * *'
env:
BASE_URL: https://api.github.com/repos/${{ github.repository }}
CAUSE: ${{ github.event_name }}
@@ -13,22 +13,42 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest ]
name: ${{ matrix.os }}
include:
- node: latest
os: macos-latest
- node: '8'
os: ubuntu-latest
- node: '8'
os: ubuntu-latest
- node: '8'
os: windows-latest
- node: '8'
os: windows-latest
name: ${{ matrix.node }} ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
NODE: ${{ matrix.node }}
steps:
- uses: actions/checkout@v2
- name: Install GNU Core Utilities
if: ${{ startsWith(matrix.os, 'macos') }}
env:
HOMEBREW_NO_BOTTLE_SOURCE_FALLBACK: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
shell: bash
run: |
while !(brew install coreutils); do echo "'brew install' failed - retrying..."; done
- name: Perform fuzzing
shell: bash
run: |
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add 8 && nvs use 8'; do
git clone --branch v1.6.0 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add $NODE && nvs use $NODE'; do
cd ~/.nvs
while !(git clean -xdf); do echo "'git clean' failed - retrying..."; done
cd -
done
. ~/.nvs/nvs.sh --version
nvs use 8
nvs use $NODE
node --version
npm config set audit false
npm config set optional false

181
README.md
View File

@@ -4,10 +4,11 @@ UglifyJS 3
UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.
#### Note:
- **`uglify-js@3` has a simplified [API](#api-reference) and [CLI](#command-line-usage) that is not backwards compatible with [`uglify-js@2`](https://github.com/mishoo/UglifyJS/tree/v2.x)**.
- **Documentation for UglifyJS `2.x` releases can be found [here](https://github.com/mishoo/UglifyJS/tree/v2.x)**.
- `uglify-js` only supports JavaScript (ECMAScript 5).
- To minify ECMAScript 2015 or above, transpile using tools like [Babel](https://babeljs.io/).
- `uglify-js` supports JavaScript and most language features in ECMAScript.
- For more exotic parts of ECMAScript, process your source file with transpilers
like [Babel](https://babeljs.io/) before passing onto `uglify-js`.
- `uglify-js@3` has a simplified [API](#api-reference) and [CLI](#command-line-usage)
that is not backwards compatible with [`uglify-js@2`](https://github.com/mishoo/UglifyJS/tree/v2.x).
Install
-------
@@ -84,7 +85,7 @@ a double dash to prevent input files being used as option arguments:
1 - single
2 - double
3 - original
`wrap_iife` Wrap IIFEs in parenthesis. Note: you may
`wrap_iife` Wrap IIFEs in parentheses. Note: you may
want to disable `negate_iife` under
compressor options.
-O, --output-opts [options] Specify output options (`beautify` disabled by default).
@@ -133,8 +134,16 @@ a double dash to prevent input files being used as option arguments:
`//# sourceMappingURL`.
--timings Display operations run time on STDERR.
--toplevel Compress and/or mangle variables in top level scope.
--v8 Support non-standard Chrome & Node.js
Equivalent to setting `v8: true` in `minify()`
for `mangle` and `output` options.
By default UglifyJS will not try to be v8-proof.
--verbose Print diagnostic messages.
--warn Print warning messages.
--webkit Support non-standard Safari/Webkit.
Equivalent to setting `webkit: true` in `minify()`
for `mangle` and `output` options.
By default UglifyJS will not try to be Safari-proof.
--wrap <name> Embed everything in a big function, making the
“exports” and “global” variables available. You
need to pass an argument to this option to
@@ -516,9 +525,14 @@ if (result.error) throw result.error;
- `toplevel` (default `false`) -- set to `true` if you wish to enable top level
variable and function name mangling and to drop unused variables and functions.
- `v8` (default `false`) -- enable workarounds for Chrome & Node.js bugs.
- `warnings` (default `false`) — pass `true` to return compressor warnings
in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
- `webkit` (default `false`) -- enable workarounds for Safari/WebKit bugs.
PhantomJS users should set this option to `true`.
## Minify options structure
```javascript
@@ -612,7 +626,11 @@ to be `false` and all symbol names will be omitted.
- `arguments` (default: `true`) -- replace `arguments[index]` with function
parameter name whenever possible.
- `assignments` (default: `true`) -- apply optimizations to assignment expressions.
- `arrows` (default: `true`) -- apply optimizations to arrow functions
- `assignments` (default: `true`) -- apply optimizations to assignment expressions
- `awaits` (default: `true`) -- apply optimizations to `await` expressions
- `booleans` (default: `true`) -- various optimizations for boolean context,
for example `!!a ? b : c → a ? b : c`
@@ -629,6 +647,8 @@ to be `false` and all symbol names will be omitted.
- `dead_code` (default: `true`) -- remove unreachable code
- `default_values` (default: `true`) -- drop overshadowed default values
- `directives` (default: `true`) -- remove redundant or non-standard directives
- `drop_console` (default: `false`) -- Pass `true` to discard calls to
@@ -646,11 +666,14 @@ to be `false` and all symbol names will be omitted.
- `expression` (default: `false`) -- Pass `true` to preserve completion values
from terminal statements without `return`, e.g. in bookmarklets.
- `functions` (default: `true`) -- convert declarations from `var`to `function`
- `functions` (default: `true`) -- convert declarations from `var` to `function`
whenever possible.
- `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation)
- `hoist_exports` (default: `true`) -- hoist `export` statements to facilitate
various `compress` and `mangle` optimizations.
- `hoist_funs` (default: `false`) -- hoist function declarations
- `hoist_props` (default: `true`) -- hoist properties from constant object and
@@ -664,6 +687,8 @@ to be `false` and all symbol names will be omitted.
- `if_return` (default: `true`) -- optimizations for if/return and if/continue
- `imports` (default: `true`) -- drop unreferenced import symbols when used with `unused`
- `inline` (default: `true`) -- inline calls to function with simple/`return` statement:
- `false` -- same as `0`
- `0` -- disabled inlining
@@ -674,13 +699,9 @@ to be `false` and all symbol names will be omitted.
- `join_vars` (default: `true`) -- join consecutive `var` statements
- `keep_fargs` (default: `strict`) -- Discard unused function arguments. Code
which relies on `Function.length` will break if this is done indiscriminately,
i.e. when passing `true`. Pass `false` to always retain function arguments.
- `keep_fnames` (default: `false`) -- Pass `true` to prevent the
compressor from discarding function names. Useful for code relying on
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle-options).
- `keep_fargs` (default: `false`) -- discard unused function arguments except
when unsafe to do so, e.g. code which relies on `Function.prototype.length`.
Pass `true` to always retain function arguments.
- `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from
being compressed into `1/0`, which may cause performance issues on Chrome.
@@ -730,6 +751,8 @@ to be `false` and all symbol names will be omitted.
- `reduce_vars` (default: `true`) -- Improve optimization on variables assigned with and
used as constant values.
- `rests` (default: `true`) -- apply optimizations to rest parameters
- `sequences` (default: `true`) -- join consecutive simple statements using the
comma operator. May be set to a positive integer to specify the maximum number
of consecutive comma sequences that will be generated. If this option is set to
@@ -744,18 +767,23 @@ to be `false` and all symbol names will be omitted.
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
example: `/*@__PURE__*/foo();`
- `spreads` (default: `true`) -- flatten spread expressions.
- `strings` (default: `true`) -- compact string concatenations.
- `switches` (default: `true`) -- de-duplicate and remove unreachable `switch` branches
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or
variables (`"vars"`) in the top level scope (`false` by default, `true` to drop
both unreferenced functions and variables)
- `templates` (default: `true`) -- compact template literals by embedding expressions
and/or converting to string literals, e.g. `` `foo ${42}` → "foo 42"``
- `top_retain` (default: `null`) -- prevent specific toplevel functions and
variables from `unused` removal (can be array, comma-separated, RegExp or
function. Implies `toplevel`)
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or
variables (`"vars"`) in the top level scope (`false` by default, `true` to drop
both unreferenced functions and variables)
- `typeofs` (default: `true`) -- Transforms `typeof foo == "undefined"` into
`foo === void 0`. Note: recommend to set this value to `false` for IE10 and
earlier versions due to known issues.
@@ -784,15 +812,16 @@ to be `false` and all symbol names will be omitted.
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple
direct variable assignments do not count as references unless set to `"keep_assign"`)
- `varify` (default: `true`) -- convert block-scoped declaractions into `var`
whenever safe to do so
- `yields` (default: `true`) -- apply optimizations to `yield` expressions
## Mangle options
- `eval` (default `false`) -- Pass `true` to mangle names visible in scopes
where `eval` or `with` are used.
- `keep_fnames` (default `false`) -- Pass `true` to not mangle function names.
Useful for code relying on `Function.prototype.name`. See also: the `keep_fnames`
[compress option](#compress-options).
- `reserved` (default `[]`) -- Pass an array of identifiers that should be
excluded from mangling. Example: `["foo", "bar"]`.
@@ -859,12 +888,14 @@ can pass additional arguments that control the code output:
comments, `"some"` to preserve multi-line comments that contain `@cc_on`,
`@license`, or `@preserve` (case-insensitive), a regular expression string
(e.g. `/^!/`), or a function which returns `boolean`, e.g.
```js
```javascript
function(node, comment) {
return comment.value.indexOf("@type " + node.TYPE) >= 0;
}
```
- `galio` (default `false`) -- enable workarounds for ANT Galio bugs
- `indent_level` (default `4`)
- `indent_start` (default `0`) -- prefix all lines by that many spaces
@@ -903,9 +934,6 @@ can pass additional arguments that control the code output:
- `shebang` (default `true`) -- preserve shebang `#!` in preamble (bash scripts)
- `webkit` (default `false`) -- enable workarounds for WebKit bugs.
PhantomJS users should set this option to `true`.
- `width` (default `80`) -- only takes effect when beautification is on, this
specifies an (orientative) line width that the beautifier will try to
obey. It refers to the width of the line text (excluding indentation).
@@ -1113,29 +1141,25 @@ in total it's a bit more than just using UglifyJS's own parser.
It's not well known, but whitespace removal and symbol mangling accounts
for 95% of the size reduction in minified code for most JavaScript - not
elaborate code transforms. One can simply disable `compress` to speed up
Uglify builds by 3 to 4 times. In this fast `mangle`-only mode Uglify has
comparable minify speeds and gzip sizes to
[`butternut`](https://www.npmjs.com/package/butternut):
Uglify builds by 3 to 5 times.
| d3.js | minify size | gzip size | minify time (seconds) |
| --- | ---: | ---: | ---: |
| original | 451,131 | 108,733 | - |
| uglify-js@3.0.24 mangle=false, compress=false | 316,600 | 85,245 | 0.70 |
| uglify-js@3.0.24 mangle=true, compress=false | 220,216 | 72,730 | 1.13 |
| butternut@0.4.6 | 217,568 | 72,738 | 1.41 |
| uglify-js@3.0.24 mangle=true, compress=true | 212,511 | 71,560 | 3.36 |
| babili@0.1.4 | 210,713 | 72,140 | 12.64 |
| original | 511,371 | 119,932 | - |
| uglify-js@3.13.0 mangle=false, compress=false | 363,988 | 95,695 | 0.56 |
| uglify-js@3.13.0 mangle=true, compress=false | 253,305 | 81,281 | 0.99 |
| uglify-js@3.13.0 mangle=true, compress=true | 244,436 | 79,854 | 5.30 |
To enable fast minify mode from the CLI use:
```
uglifyjs file.js -m
```
To enable fast minify mode with the API use:
```js
```javascript
UglifyJS.minify(code, { compress: false, mangle: true });
```
#### Source maps and debugging
### Source maps and debugging
Various `compress` transforms that simplify, rearrange, inline and remove code
are known to have an adverse effect on debugging with source maps. This is
@@ -1147,6 +1171,10 @@ disable the Uglify `compress` option and just use `mangle`.
To allow for better optimizations, the compiler makes various assumptions:
- The code does not rely on preserving its runtime performance characteristics.
Typically uglified code will run faster due to less instructions and easier
inlining, but may be slower on rare occasions for a specific platform, e.g.
see [`reduce_funcs`](#compress-options).
- `.toString()` and `.valueOf()` don't have side effects, and for built-in
objects they have not been overridden.
- `undefined`, `NaN` and `Infinity` have not been externally redefined.
@@ -1158,9 +1186,21 @@ To allow for better optimizations, the compiler makes various assumptions:
- Object properties can be added, removed and modified (not prevented with
`Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
`Object.preventExtensions()` or `Object.seal()`).
- Earlier versions of JavaScript will throw `SyntaxError` with the following:
```javascript
({
p: 42,
get p() {},
});
// SyntaxError: Object literal may not have data and accessor property with
// the same name
```
UglifyJS may modify the input which in turn may suppress those errors.
- Iteration order of keys over an object which contains spread syntax in later
versions of Chrome and Node.js may be altered.
- When `toplevel` is enabled, UglifyJS effectively assumes input code is wrapped
within `function(){ ... }`, thus forbids aliasing of declared global variables:
```js
```javascript
A = "FAIL";
var B = "FAIL";
// can be `global`, `self`, `window` etc.
@@ -1174,3 +1214,70 @@ To allow for better optimizations, the compiler makes various assumptions:
top.B = "PASS";
console.log(B);
```
- Use of `arguments` alongside destructuring as function parameters, e.g.
`function({}, arguments) {}` will result in `SyntaxError` in earlier versions
of Chrome and Node.js - UglifyJS may modify the input which in turn may
suppress those errors.
- Earlier versions of Chrome and Node.js will throw `ReferenceError` with the
following:
```javascript
var a;
try {
throw 42;
} catch ({
[a]: b,
// ReferenceError: a is not defined
}) {
let a;
}
```
UglifyJS may modify the input which in turn may suppress those errors.
- Later versions of JavaScript will throw `SyntaxError` with the following:
```javascript
a => {
let a;
};
// SyntaxError: Identifier 'a' has already been declared
```
UglifyJS may modify the input which in turn may suppress those errors.
- Later versions of JavaScript will throw `SyntaxError` with the following:
```javascript
try {
// ...
} catch ({ message: a }) {
var a;
}
// SyntaxError: Identifier 'a' has already been declared
```
UglifyJS may modify the input which in turn may suppress those errors.
- Some versions of Chrome and Node.js will throw `ReferenceError` with the
following:
```javascript
console.log(((a, b = function() {
return a;
// ReferenceError: a is not defined
}()) => b)());
```
UglifyJS may modify the input which in turn may suppress those errors.
- Some arithmetic operations with `BigInt` may throw `TypeError`:
```javascript
1n + 1;
// TypeError: can't convert BigInt to number
```
UglifyJS may modify the input which in turn may suppress those errors.
- Some versions of JavaScript will throw `SyntaxError` with the
following:
```javascript
console.log(String.raw`\uFo`);
// SyntaxError: Invalid Unicode escape sequence
```
UglifyJS may modify the input which in turn may suppress those errors.
- Some versions of JavaScript will throw `SyntaxError` with the
following:
```javascript
try {} catch (e) {
for (var e of []);
}
// SyntaxError: Identifier 'e' has already been declared
```
UglifyJS may modify the input which in turn may suppress those errors.

View File

@@ -3,14 +3,14 @@
"use strict";
require("../tools/exit");
require("../tools/tty");
var fs = require("fs");
var info = require("../package.json");
var path = require("path");
var UglifyJS = require("../tools/node");
var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
var skip_keys = [ "cname", "fixed", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
var files = {};
var options = {};
var short_forms = {
@@ -111,7 +111,11 @@ function process_option(name, no_value) {
" --validate Perform validation during AST manipulations.",
" --verbose Print diagnostic messages.",
" --warn Print warning messages.",
" --webkit Support non-standard Safari/Webkit.",
" --wrap <name> Embed everything as a function with “exports” corresponding to “name” globally.",
"",
"(internal debug use only)",
" --in-situ Warning: replaces original source files with minified output.",
" --reduce-test Reduce a standalone test case (assumes cloned repository).",
].join("\n"));
}
@@ -142,6 +146,7 @@ function process_option(name, no_value) {
case "timings":
case "toplevel":
case "validate":
case "webkit":
options[name] = true;
break;
case "keep-fnames":
@@ -192,6 +197,7 @@ function process_option(name, no_value) {
case "no-rename":
options.rename = false;
break;
case "in-situ":
case "reduce-test":
case "self":
break;
@@ -252,18 +258,33 @@ if (specified["self"]) {
if (!options.wrap) options.wrap = "UglifyJS";
paths = UglifyJS.FILES;
}
if (paths.length) {
if (specified["in-situ"]) {
if (output || specified["reduce-test"] || specified["self"]) fatal("incompatible options specified");
paths.forEach(function(name) {
print(name);
if (/^ast|spidermonkey$/.test(name)) fatal("invalid file name specified");
files = {};
files[convert_path(name)] = read_file(name);
output = name;
run();
});
} else if (paths.length) {
simple_glob(paths).forEach(function(name) {
files[convert_path(name)] = read_file(name);
});
run();
} else {
var timerId = process.stdin.isTTY && process.argv.length < 3 && setTimeout(function() {
print_error("Waiting for input... (use `--help` to print usage information)");
}, 1500);
var chunks = [];
process.stdin.setEncoding("utf8");
process.stdin.on("data", function(chunk) {
process.stdin.once("data", function() {
clearTimeout(timerId);
}).on("data", function(chunk) {
chunks.push(chunk);
}).on("end", function() {
files = [ chunks.join("") ];
files = { STDIN: chunks.join("") };
run();
});
process.stdin.resume();
@@ -276,7 +297,9 @@ function convert_ast(fn) {
function run() {
var content = options.sourceMap && options.sourceMap.content;
if (content && content != "inline") {
UglifyJS.AST_Node.info("Using input source map: " + content);
UglifyJS.AST_Node.info("Using input source map: {content}", {
content : content,
});
options.sourceMap.content = read_file(content, content);
}
try {
@@ -356,14 +379,14 @@ function run() {
}
print(JSON.stringify(result.ast, function(key, value) {
if (value) switch (key) {
case "thedef":
return symdef(value);
case "enclosed":
return value.length ? value.map(symdef) : undefined;
case "variables":
case "functions":
case "globals":
case "variables":
return value.size() ? value.map(symdef) : undefined;
case "thedef":
return symdef(value);
}
if (skip_key(key)) return;
if (value instanceof UglifyJS.AST_Token) return;

1060
lib/ast.js

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -33,7 +33,9 @@ function read_source_map(name, toplevel) {
return to_ascii(match[2]);
}
}
AST_Node.warn("inline source map not found: " + name);
AST_Node.warn("inline source map not found: {name}", {
name: name,
});
}
function parse_source_map(content) {
@@ -85,8 +87,10 @@ function minify(files, options) {
sourceMap: false,
timings: false,
toplevel: false,
v8: false,
validate: false,
warnings: false,
webkit: false,
wrap: false,
}, true);
if (options.validate) AST_Node.enable_validation();
@@ -99,6 +103,8 @@ function minify(files, options) {
set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
set_shorthand("v8", options, [ "mangle", "output" ]);
set_shorthand("webkit", options, [ "mangle", "output" ]);
var quoted_props;
if (options.mangle) {
options.mangle = defaults(options.mangle, {
@@ -109,6 +115,8 @@ function minify(files, options) {
properties: false,
reserved: [],
toplevel: false,
v8: false,
webkit: false,
}, true);
if (options.mangle.properties) {
if (typeof options.mangle.properties != "object") {
@@ -258,6 +266,7 @@ function minify(files, options) {
} catch (ex) {
return { error: ex };
} finally {
AST_Node.log_function();
AST_Node.disable_validation();
}
}

View File

@@ -115,9 +115,6 @@
value : from_moz(M.value)
};
if (M.kind == "init") return new AST_ObjectKeyVal(args);
args.key = new AST_SymbolAccessor({
name: args.key
});
args.value = new AST_Accessor(args.value);
if (M.kind == "get") return new AST_ObjectGetter(args);
if (M.kind == "set") return new AST_ObjectSetter(args);
@@ -385,7 +382,7 @@
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
var key = {
type: "Literal",
value: M.key instanceof AST_SymbolAccessor ? M.key.name : M.key
value: M.key
};
var kind;
if (M instanceof AST_ObjectKeyVal) {

View File

@@ -56,6 +56,7 @@ function OutputStream(options) {
beautify : false,
braces : false,
comments : false,
galio : false,
ie8 : false,
indent_level : 4,
indent_start : 0,
@@ -69,6 +70,7 @@ function OutputStream(options) {
semicolons : true,
shebang : true,
source_map : null,
v8 : false,
webkit : false,
width : 80,
wrap_iife : false,
@@ -107,6 +109,9 @@ function OutputStream(options) {
var OUTPUT = "";
var to_utf8 = options.ascii_only ? function(str, identifier) {
if (identifier) str = str.replace(/[\ud800-\udbff][\udc00-\udfff]/g, function(ch) {
return "\\u{" + (ch.charCodeAt(0) - 0xd7c0 << 10 | ch.charCodeAt(1) - 0xdc00).toString(16) + "}";
});
return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
var code = ch.charCodeAt(0).toString(16);
if (code.length <= 2 && !identifier) {
@@ -496,11 +501,11 @@ function OutputStream(options) {
}
}
if (/comment[134]/.test(c.type)) {
print("//" + c.value.replace(/[@#]__PURE__/g, ' ') + "\n");
print("//" + c.value.replace(/[@#]__PURE__/g, " ") + "\n");
indent();
last_nlb = true;
} else if (c.type == "comment2") {
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
print("/*" + c.value.replace(/[@#]__PURE__/g, " ") + "*/");
last_nlb = false;
}
});
@@ -554,10 +559,10 @@ function OutputStream(options) {
space();
}
if (/comment[134]/.test(c.type)) {
print("//" + c.value.replace(/[@#]__PURE__/g, ' '));
print("//" + c.value.replace(/[@#]__PURE__/g, " "));
need_newline_indented = true;
} else if (c.type == "comment2") {
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
print("/*" + c.value.replace(/[@#]__PURE__/g, " ") + "*/");
need_space = true;
}
});
@@ -607,7 +612,7 @@ function OutputStream(options) {
},
parent : function(n) {
return stack[stack.length - 2 - (n || 0)];
}
},
};
}
@@ -649,73 +654,121 @@ function OutputStream(options) {
/* -----[ PARENTHESES ]----- */
function PARENS(nodetype, func) {
if (Array.isArray(nodetype)) {
nodetype.forEach(function(nodetype) {
PARENS(nodetype, func);
});
} else {
nodetype.DEFMETHOD("needs_parens", func);
}
nodetype.DEFMETHOD("needs_parens", func);
}
PARENS(AST_Node, return_false);
// a function expression needs parens around it when it's provably
// the first token to appear in a statement.
PARENS(AST_Function, function(output) {
if (!output.has_parens() && first_in_statement(output)) return true;
if (output.option('webkit')) {
var p = output.parent();
if (p instanceof AST_PropAccess && p.expression === this) return true;
function needs_parens_function(output) {
var p = output.parent();
if (!output.has_parens() && first_in_statement(output, false, true)) {
// export default function() {}
// export default (function foo() {});
// export default (function() {})(foo);
// export default (function() {})`foo`;
// export default (function() {}) ? foo : bar;
return this.name || !(p instanceof AST_ExportDefault);
}
if (output.option('wrap_iife')) {
var p = output.parent();
if (p instanceof AST_Call && p.expression === this) return true;
}
});
if (output.option("webkit") && p instanceof AST_PropAccess && p.expression === this) return true;
if (output.option("wrap_iife") && p instanceof AST_Call && p.expression === this) return true;
}
PARENS(AST_AsyncFunction, needs_parens_function);
PARENS(AST_AsyncGeneratorFunction, needs_parens_function);
PARENS(AST_ClassExpression, needs_parens_function);
PARENS(AST_Function, needs_parens_function);
PARENS(AST_GeneratorFunction, needs_parens_function);
// same goes for an object literal, because otherwise it would be
// interpreted as a block of code.
PARENS(AST_Object, function(output) {
return !output.has_parens() && first_in_statement(output);
});
function needs_parens_obj(output) {
return !output.has_parens() && first_in_statement(output, true);
}
PARENS(AST_Object, needs_parens_obj);
PARENS(AST_Unary, function(output) {
function needs_parens_unary(output) {
var p = output.parent();
return (p instanceof AST_Call || p instanceof AST_PropAccess) && p.expression === this;
});
// (-x) ** y
if (p instanceof AST_Binary) return p.operator == "**" && p.left === this;
// (await x)(y)
// new (await x)
if (p instanceof AST_Call) return p.expression === this;
// class extends (x++) {}
// class x extends (typeof y) {}
if (p instanceof AST_Class) return true;
// (x++)[y]
// (typeof x).y
if (p instanceof AST_PropAccess) return p.expression === this;
}
PARENS(AST_Await, needs_parens_unary);
PARENS(AST_Unary, needs_parens_unary);
PARENS(AST_Sequence, function(output) {
var p = output.parent();
// [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
// [ 1, (2, 3), 4 ] ---> [ 1, 3, 4 ]
return p instanceof AST_Array
// 1 + (2, 3) + 4 ==> 8
// () ---> (foo, bar)
|| is_arrow(p) && p.value === this
// await (foo, bar)
|| p instanceof AST_Await
// 1 + (2, 3) + 4 ---> 8
|| p instanceof AST_Binary
// new (foo, bar) or foo(1, (2, 3), 4)
|| p instanceof AST_Call
// class extends (foo, bar) {}
// class foo extends (bar, baz) {}
|| p instanceof AST_Class
// class { foo = (bar, baz) }
// class { [(foo, bar)]() {} }
|| p instanceof AST_ClassProperty
// (false, true) ? (a = 10, b = 20) : (c = 30)
// ==> 20 (side effect, set a := 10 and b := 20)
// ---> 20 (side effect, set a := 10 and b := 20)
|| p instanceof AST_Conditional
// { foo: (1, 2) }.foo ==> 2
// [ a = (1, 2) ] = [] ---> a == 2
|| p instanceof AST_DefaultValue
// { [(1, 2)]: foo } = bar
// { 1: (2, foo) } = bar
|| p instanceof AST_DestructuredKeyVal
// export default (foo, bar)
|| p instanceof AST_ExportDefault
// for (foo of (bar, baz));
|| p instanceof AST_ForOf
// { [(1, 2)]: 3 }[2] ---> 3
// { foo: (1, 2) }.foo ---> 2
|| p instanceof AST_ObjectProperty
// (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
// (1, {foo:2}).foo or (1, {foo:2})["foo"] ---> 2
|| p instanceof AST_PropAccess && p.expression === this
// ...(foo, bar, baz)
|| p instanceof AST_Spread
// !(foo, bar, baz)
|| p instanceof AST_Unary
// var a = (1, 2), b = a + a; ==> b == 4
|| p instanceof AST_VarDef;
// var a = (1, 2), b = a + a; ---> b == 4
|| p instanceof AST_VarDef
// yield (foo, bar)
|| p instanceof AST_Yield;
});
PARENS(AST_Binary, function(output) {
var p = output.parent();
// this deals with precedence: 3 * (2 + 1)
// await (foo && bar)
if (p instanceof AST_Await) return true;
// this deals with precedence:
// 3 * (2 + 1)
// 3 - (2 - 1)
// (1 ** 2) ** 3
if (p instanceof AST_Binary) {
var po = p.operator, pp = PRECEDENCE[po];
var so = this.operator, sp = PRECEDENCE[so];
return pp > sp || (pp == sp && this === p.right);
return pp > sp
|| po == "??" && (so == "&&" || so == "||")
|| (pp == sp && this === p[po == "**" ? "left" : "right"]);
}
// (foo && bar)()
if (p instanceof AST_Call) return p.expression === this;
// class extends (foo && bar) {}
// class foo extends (bar || null) {}
if (p instanceof AST_Class) return true;
// (foo && bar)["prop"], (foo && bar).prop
if (p instanceof AST_PropAccess) return p.expression === this;
// typeof (foo && bar)
@@ -743,7 +796,7 @@ function OutputStream(options) {
var p = output.parent();
if (p instanceof AST_New) return p.expression === this;
// https://bugs.webkit.org/show_bug.cgi?id=123506
if (output.option('webkit')) {
if (output.option("webkit")) {
var g = output.parent(1);
return this.expression instanceof AST_Function
&& p instanceof AST_PropAccess
@@ -759,31 +812,57 @@ function OutputStream(options) {
// (new foo)(bar)
if (p instanceof AST_Call) return p.expression === this;
// (new Date).getTime(), (new Date)["getTime"]()
return p instanceof AST_PropAccess;
if (p instanceof AST_PropAccess) return true;
// (new foo)`bar`
if (p instanceof AST_Template) return p.tag === this;
});
PARENS(AST_Number, function(output) {
if (!output.option("galio")) return false;
// https://github.com/mishoo/UglifyJS/pull/1009
var p = output.parent();
if (p instanceof AST_PropAccess && p.expression === this) {
var value = this.value;
// https://github.com/mishoo/UglifyJS/issues/115
// https://github.com/mishoo/UglifyJS/pull/1009
return value < 0 || /^0/.test(make_num(value));
}
return p instanceof AST_PropAccess && p.expression === this && /^0/.test(make_num(this.value));
});
PARENS([ AST_Assign, AST_Conditional ], function(output) {
function needs_parens_assign_cond(self, output) {
var p = output.parent();
// await (a = foo)
if (p instanceof AST_Await) return true;
// 1 + (a = 2) + 3 → 6, side effect setting a = 2
if (p instanceof AST_Binary) return !(p instanceof AST_Assign);
// (a = func)() —or— new (a = Object)()
if (p instanceof AST_Call) return p.expression === this;
if (p instanceof AST_Call) return p.expression === self;
// class extends (a = foo) {}
// class foo extends (bar ? baz : moo) {}
if (p instanceof AST_Class) return true;
// (a = foo) ? bar : baz
if (p instanceof AST_Conditional) return p.condition === this;
if (p instanceof AST_Conditional) return p.condition === self;
// (a = foo)["prop"] —or— (a = foo).prop
if (p instanceof AST_PropAccess) return p.expression === this;
if (p instanceof AST_PropAccess) return p.expression === self;
// (a = foo)`bar`
if (p instanceof AST_Template) return p.tag === self;
// !(a = false) → true
if (p instanceof AST_Unary) return true;
}
PARENS(AST_Arrow, function(output) {
return needs_parens_assign_cond(this, output);
});
PARENS(AST_Assign, function(output) {
if (needs_parens_assign_cond(this, output)) return true;
// v8 parser bug ---> workaround
// f([1], [a] = []) ---> f([1], ([a] = []))
if (output.option("v8")) return this.left instanceof AST_Destructured;
// ({ p: a } = o);
if (this.left instanceof AST_DestructuredObject) return needs_parens_obj(output);
});
PARENS(AST_AsyncArrow, function(output) {
return needs_parens_assign_cond(this, output);
});
PARENS(AST_Conditional, function(output) {
return needs_parens_assign_cond(this, output);
});
PARENS(AST_Yield, function(output) {
return needs_parens_assign_cond(this, output);
});
/* -----[ PRINTERS ]----- */
@@ -835,14 +914,6 @@ function OutputStream(options) {
use_asm = was_asm;
}
AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
force_statement(this.body, output);
});
DEFPRINT(AST_Statement, function(output) {
this.body.print(output);
output.semicolon();
});
DEFPRINT(AST_Toplevel, function(output) {
display_body(this.body, true, output, true);
output.print("");
@@ -897,7 +968,7 @@ function OutputStream(options) {
self.condition.print(output);
});
output.space();
self._do_print_body(output);
force_statement(self.body, output);
});
DEFPRINT(AST_For, function(output) {
var self = this;
@@ -927,22 +998,27 @@ function OutputStream(options) {
}
});
output.space();
self._do_print_body(output);
force_statement(self.body, output);
});
DEFPRINT(AST_ForIn, function(output) {
var self = this;
output.print("for");
output.space();
output.with_parens(function() {
self.init.print(output);
function print_for_enum(prefix, infix) {
return function(output) {
var self = this;
output.print(prefix);
output.space();
output.print("in");
output.with_parens(function() {
self.init.print(output);
output.space();
output.print(infix);
output.space();
self.object.print(output);
});
output.space();
self.object.print(output);
});
output.space();
self._do_print_body(output);
});
force_statement(self.body, output);
};
}
DEFPRINT(AST_ForAwaitOf, print_for_enum("for await", "of"));
DEFPRINT(AST_ForIn, print_for_enum("for", "in"));
DEFPRINT(AST_ForOf, print_for_enum("for", "of"));
DEFPRINT(AST_With, function(output) {
var self = this;
output.print("with");
@@ -951,27 +1027,221 @@ function OutputStream(options) {
self.expression.print(output);
});
output.space();
self._do_print_body(output);
force_statement(self.body, output);
});
DEFPRINT(AST_ExportDeclaration, function(output) {
output.print("export");
output.space();
this.body.print(output);
});
DEFPRINT(AST_ExportDefault, function(output) {
output.print("export");
output.space();
output.print("default");
output.space();
var body = this.body;
body.print(output);
if (body instanceof AST_ClassExpression) {
if (!body.name) return;
}
if (body instanceof AST_DefClass) return;
if (body instanceof AST_LambdaDefinition) return;
if (body instanceof AST_LambdaExpression) {
if (!body.name && !is_arrow(body)) return;
}
output.semicolon();
});
DEFPRINT(AST_ExportForeign, function(output) {
var self = this;
output.print("export");
output.space();
var len = self.keys.length;
if (len == 0) {
print_braced_empty(self, output);
} else if (self.keys[0] == "*") {
print_entry(0);
} else output.with_block(function() {
output.indent();
print_entry(0);
for (var i = 1; i < len; i++) {
output.print(",");
output.newline();
output.indent();
print_entry(i);
}
output.newline();
});
output.space();
output.print("from");
output.space();
output.print_string(self.path, self.quote);
output.semicolon();
function print_entry(index) {
var alias = self.aliases[index];
var key = self.keys[index];
output.print_name(key);
if (alias != key) {
output.space();
output.print("as");
output.space();
output.print_name(alias);
}
}
});
DEFPRINT(AST_ExportReferences, function(output) {
var self = this;
output.print("export");
output.space();
print_properties(self, output);
output.semicolon();
});
DEFPRINT(AST_Import, function(output) {
var self = this;
output.print("import");
output.space();
if (self.default) self.default.print(output);
if (self.all) {
if (self.default) output.comma();
self.all.print(output);
}
if (self.properties) {
if (self.default) output.comma();
print_properties(self, output);
}
if (self.all || self.default || self.properties) {
output.space();
output.print("from");
output.space();
}
output.print_string(self.path, self.quote);
output.semicolon();
});
/* -----[ functions ]----- */
DEFPRINT(AST_Lambda, function(output, nokeyword) {
var self = this;
if (!nokeyword) {
output.print("function");
}
if (self.name) {
output.space();
self.name.print(output);
}
function print_funargs(self, output) {
output.with_parens(function() {
self.argnames.forEach(function(arg, i) {
if (i) output.comma();
arg.print(output);
});
if (self.rest) {
if (self.argnames.length) output.comma();
output.print("...");
self.rest.print(output);
}
});
}
function print_arrow(self, output) {
if (self.argnames.length == 1 && self.argnames[0] instanceof AST_SymbolFunarg && !self.rest) {
self.argnames[0].print(output);
} else {
print_funargs(self, output);
}
output.space();
output.print("=>");
output.space();
if (self.value) {
self.value.print(output);
} else {
print_braced(self, output, true);
}
}
DEFPRINT(AST_Arrow, function(output) {
print_arrow(this, output);
});
DEFPRINT(AST_AsyncArrow, function(output) {
output.print("async");
output.space();
print_arrow(this, output);
});
function print_lambda(self, output) {
if (self.name) {
output.space();
self.name.print(output);
}
print_funargs(self, output);
output.space();
print_braced(self, output, true);
}
DEFPRINT(AST_Lambda, function(output) {
output.print("function");
print_lambda(this, output);
});
function print_async(output) {
output.print("async");
output.space();
output.print("function");
print_lambda(this, output);
}
DEFPRINT(AST_AsyncDefun, print_async);
DEFPRINT(AST_AsyncFunction, print_async);
function print_async_generator(output) {
output.print("async");
output.space();
output.print("function*");
print_lambda(this, output);
}
DEFPRINT(AST_AsyncGeneratorDefun, print_async_generator);
DEFPRINT(AST_AsyncGeneratorFunction, print_async_generator);
function print_generator(output) {
output.print("function*");
print_lambda(this, output);
}
DEFPRINT(AST_GeneratorDefun, print_generator);
DEFPRINT(AST_GeneratorFunction, print_generator);
/* -----[ classes ]----- */
DEFPRINT(AST_Class, function(output) {
var self = this;
output.print("class");
if (self.name) {
output.space();
self.name.print(output);
}
if (self.extends) {
output.space();
output.print("extends");
output.space();
self.extends.print(output);
}
output.space();
print_properties(self, output, true);
});
DEFPRINT(AST_ClassField, function(output) {
var self = this;
if (self.static) {
output.print("static");
output.space();
}
print_property_key(self, output);
if (self.value) {
output.space();
output.print("=");
output.space();
self.value.print(output);
}
output.semicolon();
});
DEFPRINT(AST_ClassGetter, print_accessor("get"));
DEFPRINT(AST_ClassSetter, print_accessor("set"));
function print_method(self, output) {
var fn = self.value;
if (is_async(fn)) {
output.print("async");
output.space();
}
if (is_generator(fn)) output.print("*");
print_property_key(self, output);
print_lambda(self.value, output);
}
DEFPRINT(AST_ClassMethod, function(output) {
var self = this;
if (self.static) {
output.print("static");
output.space();
}
print_method(self, output);
});
/* -----[ jumps ]----- */
@@ -994,7 +1264,7 @@ function OutputStream(options) {
/* -----[ if ]----- */
function make_then(self, output) {
var b = self.body;
if (output.option("braces")
if (output.option("braces") && !(b instanceof AST_Const || b instanceof AST_Let)
|| output.option("ie8") && b instanceof AST_Do)
return make_block(b, output);
// The squeezer replaces "block"-s that contain only a single
@@ -1036,7 +1306,7 @@ function OutputStream(options) {
else
force_statement(self.alternative, output);
} else {
self._do_print_body(output);
force_statement(self.body, output);
}
});
@@ -1099,10 +1369,12 @@ function OutputStream(options) {
DEFPRINT(AST_Catch, function(output) {
var self = this;
output.print("catch");
output.space();
output.with_parens(function() {
self.argname.print(output);
});
if (self.argname) {
output.space();
output.with_parens(function() {
self.argname.print(output);
});
}
output.space();
print_braced(self, output);
});
@@ -1112,28 +1384,31 @@ function OutputStream(options) {
print_braced(this, output);
});
DEFPRINT(AST_Var, function(output) {
var self = this;
output.print("var");
output.space();
self.definitions.forEach(function(def, i) {
if (i) output.comma();
def.print(output);
});
var p = output.parent();
if (p && p.init !== self || !(p instanceof AST_For || p instanceof AST_ForIn)) output.semicolon();
});
function print_definitinos(type) {
return function(output) {
var self = this;
output.print(type);
output.space();
self.definitions.forEach(function(def, i) {
if (i) output.comma();
def.print(output);
});
var p = output.parent();
if (!(p instanceof AST_IterationStatement && p.init === self)) output.semicolon();
};
}
DEFPRINT(AST_Const, print_definitinos("const"));
DEFPRINT(AST_Let, print_definitinos("let"));
DEFPRINT(AST_Var, print_definitinos("var"));
function parenthesize_for_noin(node, output, noin) {
var parens = false;
// need to take some precautions here:
// https://github.com/mishoo/UglifyJS/issues/60
if (noin) node.walk(new TreeWalker(function(node) {
if (parens || node instanceof AST_Scope) return true;
if (node instanceof AST_Binary && node.operator == "in") {
parens = true;
return true;
}
if (parens) return true;
if (node instanceof AST_Binary && node.operator == "in") return parens = true;
if (node instanceof AST_Scope && !(is_arrow(node) && node.value)) return true;
}));
node.print(output, parens);
}
@@ -1146,11 +1421,20 @@ function OutputStream(options) {
output.print("=");
output.space();
var p = output.parent(1);
var noin = p instanceof AST_For || p instanceof AST_ForIn;
var noin = p instanceof AST_For || p instanceof AST_ForEnumeration;
parenthesize_for_noin(self.value, output, noin);
}
});
DEFPRINT(AST_DefaultValue, function(output) {
var self = this;
self.name.print(output);
output.space();
output.print("=");
output.space();
self.value.print(output);
});
/* -----[ other expressions ]----- */
function print_call_args(self, output) {
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
@@ -1214,6 +1498,10 @@ function OutputStream(options) {
this.property.print(output);
output.print("]");
});
DEFPRINT(AST_Spread, function(output) {
output.print("...");
this.expression.print(output);
});
DEFPRINT(AST_UnaryPrefix, function(output) {
var op = this.operator;
var exp = this.expression;
@@ -1249,6 +1537,18 @@ function OutputStream(options) {
output.colon();
self.alternative.print(output);
});
DEFPRINT(AST_Await, function(output) {
output.print("await");
output.space();
this.expression.print(output);
});
DEFPRINT(AST_Yield, function(output) {
output.print(this.nested ? "yield*" : "yield");
if (this.expression) {
output.space();
this.expression.print(output);
}
});
/* -----[ literals ]----- */
DEFPRINT(AST_Array, function(output) {
@@ -1267,9 +1567,31 @@ function OutputStream(options) {
output.space();
} : noop);
});
DEFPRINT(AST_Object, function(output) {
var props = this.properties;
if (props.length > 0) output.with_block(function() {
DEFPRINT(AST_DestructuredArray, function(output) {
var a = this.elements, len = a.length, rest = this.rest;
output.with_square(len || rest ? function() {
output.space();
a.forEach(function(exp, i) {
if (i) output.comma();
exp.print(output);
});
if (rest) {
if (len) output.comma();
output.print("...");
rest.print(output);
} else if (a[len - 1] instanceof AST_Hole) {
// If the final element is a hole, we need to make sure it
// doesn't look like a trailing comma, by inserting an actual
// trailing comma.
output.comma();
}
output.space();
} : noop);
});
DEFPRINT(AST_DestructuredKeyVal, print_key_value);
DEFPRINT(AST_DestructuredObject, function(output) {
var props = this.properties, len = props.length, rest = this.rest;
if (len || rest) output.with_block(function() {
props.forEach(function(prop, i) {
if (i) {
output.print(",");
@@ -1278,51 +1600,129 @@ function OutputStream(options) {
output.indent();
prop.print(output);
});
if (rest) {
if (len) {
output.print(",");
output.newline();
}
output.indent();
output.print("...");
rest.print(output);
}
output.newline();
});
else print_braced_empty(this, output);
});
function print_properties(self, output, no_comma) {
var props = self.properties;
if (props.length > 0) output.with_block(function() {
props.forEach(function(prop, i) {
if (i) {
if (!no_comma) output.print(",");
output.newline();
}
output.indent();
prop.print(output);
});
output.newline();
});
else print_braced_empty(self, output);
}
DEFPRINT(AST_Object, function(output) {
print_properties(this, output);
});
function print_property_name(key, quote, output) {
if (output.option("quote_keys")) {
function print_property_key(self, output) {
var key = self.key;
if (key instanceof AST_Node) {
output.with_square(function() {
key.print(output);
});
} else if (output.option("quote_keys")) {
output.print_string(key);
} else if ("" + +key == key && key >= 0) {
output.print(make_num(key));
} else if (RESERVED_WORDS[key] ? !output.option("ie8") : is_identifier_string(key)) {
if (quote && output.option("keep_quoted_props")) {
output.print_string(key, quote);
} else {
output.print_name(key);
}
} else {
output.print_string(key, quote);
var quote = self.start && self.start.quote;
if (self.private) {
output.print_name(key);
} else if (RESERVED_WORDS[key] ? !output.option("ie8") : is_identifier_string(key)) {
if (quote && output.option("keep_quoted_props")) {
output.print_string(key, quote);
} else {
output.print_name(key);
}
} else {
output.print_string(key, quote);
}
}
}
DEFPRINT(AST_ObjectKeyVal, function(output) {
function print_key_value(output) {
var self = this;
print_property_name(self.key, self.quote, output);
print_property_key(self, output);
output.colon();
self.value.print(output);
}
DEFPRINT(AST_ObjectKeyVal, print_key_value);
DEFPRINT(AST_ObjectMethod, function(output) {
print_method(this, output);
});
function print_accessor(type) {
return function(output) {
var self = this;
if (self.static) {
output.print("static");
output.space();
}
output.print(type);
output.space();
print_property_name(self.key.name, self.quote, output);
self.value._codegen(output, true);
print_property_key(self, output);
print_lambda(self.value, output);
};
}
DEFPRINT(AST_ObjectGetter, print_accessor("get"));
DEFPRINT(AST_ObjectSetter, print_accessor("set"));
function print_symbol(self, output) {
var def = self.definition();
output.print_name(def && def.mangled_name || self.name);
}
DEFPRINT(AST_Symbol, function(output) {
var def = this.definition();
output.print_name(def && def.mangled_name || this.name);
print_symbol(this, output);
});
DEFPRINT(AST_SymbolExport, function(output) {
var self = this;
print_symbol(self, output);
if (self.alias) {
output.space();
output.print("as");
output.space();
output.print_name(self.alias);
}
});
DEFPRINT(AST_SymbolImport, function(output) {
var self = this;
if (self.key) {
output.print_name(self.key);
output.space();
output.print("as");
output.space();
}
print_symbol(self, output);
});
DEFPRINT(AST_Hole, noop);
DEFPRINT(AST_This, function(output) {
output.print("this");
DEFPRINT(AST_Template, function(output) {
var self = this;
if (self.tag) self.tag.print(output);
output.print("`");
for (var i = 0; i < self.expressions.length; i++) {
output.print(self.strings[i]);
output.print("${");
self.expressions[i].print(output);
output.print("}");
}
output.print(self.strings[i]);
output.print("`");
});
DEFPRINT(AST_Constant, function(output) {
output.print(this.value);
@@ -1379,13 +1779,12 @@ function OutputStream(options) {
});
function force_statement(stat, output) {
if (output.option("braces")) {
if (output.option("braces") && !(stat instanceof AST_Const || stat instanceof AST_Let)) {
make_block(stat, output);
} else if (!stat || stat instanceof AST_EmptyStatement) {
output.force_semicolon();
} else {
if (!stat || stat instanceof AST_EmptyStatement)
output.force_semicolon();
else
stat.print(output);
stat.print(output);
}
}
@@ -1469,6 +1868,7 @@ function OutputStream(options) {
AST_Constant,
AST_Debugger,
AST_Definitions,
AST_Destructured,
AST_Finally,
AST_Jump,
AST_Lambda,
@@ -1483,14 +1883,7 @@ function OutputStream(options) {
output.add_mapping(this.start);
});
DEFMAP([
AST_ObjectGetter,
AST_ObjectSetter,
], function(output) {
output.add_mapping(this.start, this.key.name);
});
DEFMAP([ AST_ObjectProperty ], function(output) {
output.add_mapping(this.start, this.key);
DEFMAP([ AST_DestructuredKeyVal, AST_ObjectProperty ], function(output) {
if (typeof this.key == "string") output.add_mapping(this.start, this.key);
});
})();

File diff suppressed because it is too large Load Diff

View File

@@ -81,8 +81,8 @@ var builtins = function() {
function reserve_quoted_keys(ast, reserved) {
ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ObjectKeyVal) {
if (node.quote) add(node.key);
if (node instanceof AST_ObjectProperty) {
if (node.start && node.start.quote) add(node.key);
} else if (node instanceof AST_Sub) {
addStrings(node.property, add);
}
@@ -165,11 +165,8 @@ function mangle_properties(ast, options) {
}
} else if (node instanceof AST_Dot) {
add(node.property);
} else if (node instanceof AST_ObjectKeyVal) {
add(node.key);
} else if (node instanceof AST_ObjectProperty) {
// setter or getter, since KeyVal is handled above
add(node.key.name);
if (typeof node.key == "string") add(node.key);
} else if (node instanceof AST_Sub) {
addStrings(node.property, add);
}
@@ -198,11 +195,8 @@ function mangle_properties(ast, options) {
}
} else if (node instanceof AST_Dot) {
node.property = mangle(node.property);
} else if (node instanceof AST_ObjectKeyVal) {
node.key = mangle(node.key);
} else if (node instanceof AST_ObjectProperty) {
// setter or getter
node.key.name = mangle(node.key.name);
if (typeof node.key == "string") node.key = mangle(node.key);
} else if (node instanceof AST_Sub) {
if (!options.keep_quoted) mangleStrings(node.property);
}
@@ -234,7 +228,7 @@ function mangle_properties(ast, options) {
var mangled = cache.get(name);
if (!mangled) {
if (debug) {
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo ---> o._$foo$NNN_.
var debug_mangled = "_$" + name + "$" + debug_suffix + "_";
if (can_mangle(debug_mangled)) mangled = debug_mangled;
}

View File

@@ -45,10 +45,10 @@
function SymbolDef(id, scope, orig, init) {
this.eliminated = 0;
this.exported = false;
this.global = false;
this.id = id;
this.init = init;
this.lambda = orig instanceof AST_SymbolLambda;
this.mangled_name = null;
this.name = orig.name;
this.orig = [ orig ];
@@ -68,11 +68,11 @@ SymbolDef.prototype = {
if (this.global && cache && cache.has(this.name)) {
this.mangled_name = cache.get(this.name);
} else if (!this.mangled_name && !this.unmangleable(options)) {
var def;
if (def = this.redefined()) {
var def = this.redefined();
if (def) {
this.mangled_name = def.mangled_name || def.name;
} else {
this.mangled_name = next_mangled_name(this.scope, options, this);
this.mangled_name = next_mangled_name(this, options);
}
if (this.global && cache) {
cache.set(this.name, this.mangled_name);
@@ -80,10 +80,19 @@ SymbolDef.prototype = {
}
},
redefined: function() {
return this.defun && this.defun.variables.get(this.name);
var scope = this.defun;
if (!scope) return;
var name = this.name;
var def = scope.variables.get(name)
|| scope instanceof AST_Toplevel && scope.globals.get(name)
|| this.orig[0] instanceof AST_SymbolConst && find_if(function(def) {
return def.name == name;
}, scope.enclosed);
if (def && def !== this) return def.redefined() || def;
},
unmangleable: function(options) {
return this.global && !options.toplevel
|| this.exported
|| this.undeclared
|| !options.eval && this.scope.pinned()
|| options.keep_fnames
@@ -92,6 +101,17 @@ SymbolDef.prototype = {
},
};
var unary_side_effects = makePredicate("delete ++ --");
function is_lhs(node, parent) {
if (parent instanceof AST_Assign) return parent.left === node && node;
if (parent instanceof AST_DefaultValue) return parent.name === node && node;
if (parent instanceof AST_Destructured) return node;
if (parent instanceof AST_DestructuredKeyVal) return node;
if (parent instanceof AST_ForEnumeration) return parent.init === node && node;
if (parent instanceof AST_Unary) return unary_side_effects[parent.operator] && parent.expression;
}
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
options = defaults(options, {
cache: null,
@@ -101,27 +121,71 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
// pass 1: setup scope chaining and handle definitions
var self = this;
var defun = null;
var exported = false;
var next_def_id = 0;
var scope = self.parent_scope = null;
var tw = new TreeWalker(function(node, descend) {
if (node instanceof AST_Defun) {
if (node instanceof AST_DefClass) {
var save_exported = exported;
exported = tw.parent() instanceof AST_ExportDeclaration;
node.name.walk(tw);
exported = save_exported;
walk_scope(function() {
if (node.extends) node.extends.walk(tw);
node.properties.forEach(function(prop) {
prop.walk(tw);
});
});
return true;
}
if (node instanceof AST_Definitions) {
var save_exported = exported;
exported = tw.parent() instanceof AST_ExportDeclaration;
descend();
exported = save_exported;
return true;
}
if (node instanceof AST_LambdaDefinition) {
var save_exported = exported;
exported = tw.parent() instanceof AST_ExportDeclaration;
node.name.walk(tw);
exported = save_exported;
walk_scope(function() {
node.argnames.forEach(function(argname) {
argname.walk(tw);
});
if (node.rest) node.rest.walk(tw);
walk_body(node, tw);
});
return true;
}
if (node instanceof AST_SwitchBranch) {
node.init_vars(scope);
descend();
return true;
}
if (node instanceof AST_Try) {
walk_scope(function() {
walk_body(node, tw);
});
if (node.bcatch) node.bcatch.walk(tw);
if (node.bfinally) node.bfinally.walk(tw);
return true;
}
if (node instanceof AST_With) {
var s = scope;
do {
s = s.resolve();
if (s.uses_with) break;
s.uses_with = true;
} while (s = s.parent_scope);
walk_scope(descend);
return true;
}
if (node instanceof AST_BlockScope) {
walk_scope(descend);
return true;
}
if (node instanceof AST_With) {
for (var s = scope; s; s = s.parent_scope) s.uses_with = true;
return;
}
if (node instanceof AST_Symbol) {
node.scope = scope;
}
@@ -131,8 +195,13 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
}
if (node instanceof AST_SymbolCatch) {
scope.def_variable(node).defun = defun;
} else if (node instanceof AST_SymbolConst) {
var def = scope.def_variable(node);
def.defun = defun;
if (exported) def.exported = true;
} else if (node instanceof AST_SymbolDefun) {
defun.def_function(node, tw.parent());
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);
@@ -140,13 +209,17 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
} else if (node instanceof AST_SymbolLambda) {
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
if (options.ie8) def.defun = defun.parent_scope.resolve();
} else if (node instanceof AST_SymbolLet) {
var def = scope.def_variable(node);
if (exported) def.exported = true;
} else if (node instanceof AST_SymbolVar) {
defun.def_variable(node, null);
var def = defun.def_variable(node, node instanceof AST_SymbolImport ? undefined : null);
if (exported) def.exported = true;
entangle(defun, scope);
}
function walk_scope(descend) {
node.init_scope_vars(scope);
node.init_vars(scope);
var save_defun = defun;
var save_scope = scope;
if (node instanceof AST_Scope) defun = node;
@@ -159,7 +232,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
function entangle(defun, scope) {
if (defun === scope) return;
node.mark_enclosed(options);
var def = scope.find_variable(node);
var def = scope.find_variable(node.name);
if (node.thedef === def) return;
node.thedef = def;
def.orig.push(node);
@@ -173,42 +246,102 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
// pass 2: find back references and eval
self.globals = new Dictionary();
var in_arg = [];
var tw = new TreeWalker(function(node) {
if (node instanceof AST_Catch) {
if (!(node.argname instanceof AST_Destructured)) return;
in_arg.push(node);
node.argname.walk(tw);
in_arg.pop();
walk_body(node, tw);
return true;
}
if (node instanceof AST_Lambda) {
in_arg.push(node);
node.argnames.forEach(function(argname) {
argname.walk(tw);
});
if (node.rest) node.rest.walk(tw);
in_arg.pop();
walk_lambda(node, tw);
return true;
}
if (node instanceof AST_LoopControl) {
if (node.label) node.label.thedef.references.push(node);
return true;
}
if (node instanceof AST_SymbolDeclaration) {
if (node instanceof AST_SymbolCatch) {
// ensure mangling works if `catch` reuses a scope variable
var def = node.definition().redefined();
if (def) for (var s = node.scope; s; s = s.parent_scope) {
push_uniq(s.enclosed, def);
if (s === def.scope) break;
}
} else if (node instanceof AST_SymbolConst) {
// ensure compression works if `const` reuses a scope variable
var redef = node.definition().redefined();
if (redef) redef.const_redefs = true;
}
if (node.name != "arguments") return true;
var parent = node instanceof AST_SymbolVar && tw.parent();
if (parent instanceof AST_VarDef && !parent.value) return true;
var sym = node.scope.resolve().find_variable("arguments");
if (sym && is_arguments(sym)) sym.scope.uses_arguments = 3;
return true;
}
if (node instanceof AST_SymbolRef) {
var name = node.name;
var sym = node.scope.find_variable(name);
for (var i = in_arg.length; i > 0 && sym;) {
i = in_arg.lastIndexOf(sym.scope, i - 1);
if (i < 0) break;
var decl = sym.orig[0];
if (decl instanceof AST_SymbolCatch
|| decl instanceof AST_SymbolFunarg
|| decl instanceof AST_SymbolLambda) {
node.in_arg = true;
break;
}
sym = sym.scope.parent_scope.find_variable(name);
}
if (!sym) {
sym = self.def_global(node);
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
sym.scope.uses_arguments = true;
} else if (name == "arguments" && is_arguments(sym)) {
var parent = tw.parent();
if (is_lhs(node, parent)) {
sym.scope.uses_arguments = 3;
} else if (sym.scope.uses_arguments < 2
&& !(parent instanceof AST_PropAccess && parent.expression === node)) {
sym.scope.uses_arguments = 2;
} else if (!sym.scope.uses_arguments) {
sym.scope.uses_arguments = true;
}
}
if (name == "eval") {
var parent = tw.parent();
if (parent.TYPE == "Call" && parent.expression === node) {
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
var s = node.scope;
do {
s = s.resolve();
if (s.uses_eval) break;
s.uses_eval = true;
}
} while (s = s.parent_scope);
} else if (sym.undeclared) {
self.uses_eval = true;
}
}
if (sym.init instanceof AST_LambdaDefinition && sym.scope !== sym.init.name.scope) {
var scope = node.scope;
do {
if (scope === sym.init.name.scope) break;
} while (scope = scope.parent_scope);
if (!scope) sym.init = undefined;
}
node.thedef = sym;
node.reference(options);
return true;
}
// ensure mangling works if catch reuses a scope variable
if (node instanceof AST_SymbolCatch) {
var def = node.definition().redefined();
if (def) for (var s = node.scope; s; s = s.parent_scope) {
push_uniq(s.enclosed, def);
if (s === def.scope) break;
}
return true;
}
});
self.walk(tw);
@@ -224,8 +357,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
}
if (node instanceof AST_SymbolLambda) {
var def = node.thedef;
redefine(node, node.scope.parent_scope.resolve());
if (typeof node.thedef.init !== "undefined") {
if (!redefine(node, node.scope.parent_scope.resolve())) {
delete def.defun;
} else if (typeof node.thedef.init !== "undefined") {
node.thedef.init = false;
} else if (def.init) {
node.thedef.init = def.init;
@@ -234,13 +368,22 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
}
}));
function is_arguments(sym) {
return sym.orig[0] instanceof AST_SymbolFunarg
&& !(sym.orig[1] instanceof AST_SymbolFunarg || sym.orig[2] instanceof AST_SymbolFunarg)
&& !is_arrow(sym.scope);
}
function redefine(node, scope) {
var name = node.name;
var old_def = node.thedef;
if (!all(old_def.orig, function(sym) {
return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet);
})) return false;
var new_def = scope.find_variable(name);
if (new_def) {
var redef;
while (redef = new_def.redefined()) new_def = redef;
var redef = new_def.redefined();
if (redef) new_def = redef;
} else {
new_def = self.globals.get(name);
}
@@ -251,12 +394,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
}
old_def.defun = new_def.scope;
old_def.forEach(function(node) {
node.redef = true;
node.redef = old_def;
node.thedef = new_def;
node.reference(options);
});
if (old_def.lambda) new_def.lambda = true;
if (new_def.undeclared) self.variables.set(name, new_def);
return true;
}
});
@@ -273,22 +416,34 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
}
});
function init_scope_vars(scope, parent) {
scope.cname = -1; // the current index for mangling functions/variables
function init_block_vars(scope, parent) {
scope.enclosed = []; // variables from this or outer scope(s) that are referenced from this or inner scopes
scope.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
scope.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
scope.parent_scope = parent; // the parent scope (null if this is the top level)
scope.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
scope.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
if (parent) scope.make_def = parent.make_def; // top-level tracking of SymbolDef instances
}
AST_BlockScope.DEFMETHOD("init_scope_vars", function(parent_scope) {
function init_scope_vars(scope, parent) {
init_block_vars(scope, parent);
scope.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
scope.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
}
AST_BlockScope.DEFMETHOD("init_vars", function(parent_scope) {
init_block_vars(this, parent_scope);
});
AST_Scope.DEFMETHOD("init_vars", function(parent_scope) {
init_scope_vars(this, parent_scope);
});
AST_Lambda.DEFMETHOD("init_scope_vars", function(parent_scope) {
AST_Arrow.DEFMETHOD("init_vars", function(parent_scope) {
init_scope_vars(this, parent_scope);
return this;
});
AST_AsyncArrow.DEFMETHOD("init_vars", function(parent_scope) {
init_scope_vars(this, parent_scope);
});
AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) {
init_scope_vars(this, parent_scope);
this.uses_arguments = false;
this.def_variable(new AST_SymbolFunarg({
@@ -303,7 +458,9 @@ 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 (options.keep_fnames) {
if (!options) {
delete s._var_names;
} else if (options.keep_fnames) {
s.functions.each(function(d) {
push_uniq(def.scope.enclosed, d);
});
@@ -318,14 +475,13 @@ AST_Symbol.DEFMETHOD("reference", function(options) {
});
AST_BlockScope.DEFMETHOD("find_variable", function(name) {
if (name instanceof AST_Symbol) name = name.name;
return this.variables.get(name)
|| (this.parent_scope && this.parent_scope.find_variable(name));
|| this.parent_scope && this.parent_scope.find_variable(name);
});
AST_BlockScope.DEFMETHOD("def_function", function(symbol, init) {
var def = this.def_variable(symbol, init);
if (!def.init || def.init instanceof AST_Defun) def.init = init;
if (!def.init || def.init instanceof AST_LambdaDefinition) def.init = init;
this.functions.set(symbol.name, def);
return def;
});
@@ -334,7 +490,7 @@ AST_BlockScope.DEFMETHOD("def_variable", function(symbol, init) {
var def = this.variables.get(symbol.name);
if (def) {
def.orig.push(symbol);
if (def.init instanceof AST_Function) def.init = init;
if (def.init instanceof AST_LambdaExpression) def.init = init;
} else {
def = this.make_def(symbol, init);
this.variables.set(symbol.name, def);
@@ -346,8 +502,9 @@ AST_BlockScope.DEFMETHOD("def_variable", function(symbol, init) {
function names_in_use(scope, options) {
var names = scope.names_in_use;
if (!names) {
scope.names_in_use = names = Object.create(null);
scope.cname = -1;
scope.cname_holes = [];
scope.names_in_use = names = Object.create(null);
var cache = options.cache && options.cache.props;
scope.enclosed.forEach(function(def) {
if (def.unmangleable(options)) names[def.name] = true;
@@ -359,7 +516,8 @@ function names_in_use(scope, options) {
return names;
}
function next_mangled_name(scope, options, def) {
function next_mangled_name(def, options) {
var scope = def.scope;
var in_use = names_in_use(scope, options);
var holes = scope.cname_holes;
var names = Object.create(null);
@@ -412,6 +570,8 @@ function _default_mangler_options(options) {
keep_fnames : false,
reserved : [],
toplevel : false,
v8 : false,
webkit : false,
});
if (!Array.isArray(options.reserved)) options.reserved = [];
// Never mangle arguments
@@ -442,10 +602,29 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
// lname is incremented when we get to the AST_Label
var save_nesting = lname;
descend();
lname = save_nesting;
if (!options.v8 || !in_label(tw)) lname = save_nesting;
return true;
}
if (node instanceof AST_Scope) {
if (node instanceof AST_BlockScope) {
if (options.webkit && node instanceof AST_IterationStatement && node.init instanceof AST_Let) {
node.init.definitions.forEach(function(defn) {
defn.name.match_symbol(function(sym) {
if (!(sym instanceof AST_SymbolLet)) return;
var def = sym.definition();
var scope = sym.scope.parent_scope;
var redef = scope.def_variable(sym);
sym.thedef = def;
scope.to_mangle.push(redef);
def.redefined = function() {
return redef;
};
});
}, true);
}
node.to_mangle = [];
node.variables.each(function(def) {
if (!defer_redef(def)) node.to_mangle.push(def);
});
descend();
if (options.cache && node instanceof AST_Toplevel) {
node.globals.each(mangle);
@@ -455,9 +634,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
sym.scope = node;
sym.reference(options);
}
node.variables.each(function(def) {
if (!defer_redef(def)) mangle(def);
});
node.to_mangle.forEach(mangle);
return true;
}
if (node instanceof AST_Label) {
@@ -468,13 +645,6 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
node.mangled_name = name;
return true;
}
if (!options.ie8 && node instanceof AST_Catch) {
var def = node.argname.definition();
var redef = defer_redef(def, node.argname);
descend();
if (!redef) mangle(def);
return true;
}
});
this.walk(tw);
redefined.forEach(mangle);
@@ -484,12 +654,20 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
def.mangle(options);
}
function defer_redef(def, node) {
function defer_redef(def) {
var sym = def.orig[0];
var redef = def.redefined();
if (!redef) return false;
if (!redef) {
if (!(sym instanceof AST_SymbolConst)) return false;
var scope = def.scope.resolve();
if (def.scope === scope) return false;
if (def.scope.parent_scope.find_variable(sym.name)) return false;
redef = scope.def_variable(sym);
scope.to_mangle.push(redef);
}
redefined.push(def);
def.references.forEach(reference);
if (node) reference(node);
if (sym instanceof AST_SymbolCatch || sym instanceof AST_SymbolConst) reference(sym);
return true;
function reference(sym) {
@@ -498,6 +676,14 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
sym.thedef = def;
}
}
function in_label(tw) {
var level = 0, parent;
while (parent = tw.parent(level++)) {
if (parent instanceof AST_Block) return parent instanceof AST_Toplevel && !options.toplevel;
if (parent instanceof AST_LabeledStatement) return true;
}
}
});
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {

View File

@@ -144,7 +144,9 @@ function SourceMap(options) {
add(source, gen_line, gen_col, orig_line, orig_col, name);
} : add,
setSourceContent: sources_content ? function(source, content) {
sources_content[source] = content;
if (!(source in sources_content)) {
sources_content[source] = content;
}
} : noop,
toString: function() {
return JSON.stringify({

View File

@@ -82,7 +82,7 @@ TreeTransformer.prototype = new TreeWalker;
if (self.step) self.step = self.step.transform(tw);
self.body = self.body.transform(tw);
});
DEF(AST_ForIn, function(self, tw) {
DEF(AST_ForEnumeration, function(self, tw) {
self.init = self.init.transform(tw);
self.object = self.object.transform(tw);
self.body = self.body.transform(tw);
@@ -116,7 +116,7 @@ TreeTransformer.prototype = new TreeWalker;
if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
});
DEF(AST_Catch, function(self, tw) {
self.argname = self.argname.transform(tw);
if (self.argname) self.argname = self.argname.transform(tw);
self.body = do_list(self.body, tw);
});
DEF(AST_Definitions, function(self, tw) {
@@ -126,11 +126,36 @@ TreeTransformer.prototype = new TreeWalker;
self.name = self.name.transform(tw);
if (self.value) self.value = self.value.transform(tw);
});
DEF(AST_DefaultValue, function(self, tw) {
self.name = self.name.transform(tw);
self.value = self.value.transform(tw);
});
DEF(AST_Lambda, function(self, tw) {
if (self.name) self.name = self.name.transform(tw);
self.argnames = do_list(self.argnames, tw);
if (self.rest) self.rest = self.rest.transform(tw);
self.body = do_list(self.body, tw);
});
function transform_arrow(self, tw) {
self.argnames = do_list(self.argnames, tw);
if (self.rest) self.rest = self.rest.transform(tw);
if (self.value) {
self.value = self.value.transform(tw);
} else {
self.body = do_list(self.body, tw);
}
}
DEF(AST_Arrow, transform_arrow);
DEF(AST_AsyncArrow, transform_arrow);
DEF(AST_Class, function(self, tw) {
if (self.name) self.name = self.name.transform(tw);
if (self.extends) self.extends = self.extends.transform(tw);
self.properties = do_list(self.properties, tw);
});
DEF(AST_ClassProperty, function(self, tw) {
if (self.key instanceof AST_Node) self.key = self.key.transform(tw);
if (self.value) self.value = self.value.transform(tw);
});
DEF(AST_Call, function(self, tw) {
self.expression = self.expression.transform(tw);
self.args = do_list(self.args, tw);
@@ -138,6 +163,12 @@ TreeTransformer.prototype = new TreeWalker;
DEF(AST_Sequence, function(self, tw) {
self.expressions = do_list(self.expressions, tw);
});
DEF(AST_Await, function(self, tw) {
self.expression = self.expression.transform(tw);
});
DEF(AST_Yield, function(self, tw) {
if (self.expression) self.expression = self.expression.transform(tw);
});
DEF(AST_Dot, function(self, tw) {
self.expression = self.expression.transform(tw);
});
@@ -145,6 +176,9 @@ TreeTransformer.prototype = new TreeWalker;
self.expression = self.expression.transform(tw);
self.property = self.property.transform(tw);
});
DEF(AST_Spread, function(self, tw) {
self.expression = self.expression.transform(tw);
});
DEF(AST_Unary, function(self, tw) {
self.expression = self.expression.transform(tw);
});
@@ -160,12 +194,43 @@ TreeTransformer.prototype = new TreeWalker;
DEF(AST_Array, function(self, tw) {
self.elements = do_list(self.elements, tw);
});
DEF(AST_DestructuredArray, function(self, tw) {
self.elements = do_list(self.elements, tw);
if (self.rest) self.rest = self.rest.transform(tw);
});
DEF(AST_DestructuredKeyVal, function(self, tw) {
if (self.key instanceof AST_Node) self.key = self.key.transform(tw);
self.value = self.value.transform(tw);
});
DEF(AST_DestructuredObject, function(self, tw) {
self.properties = do_list(self.properties, tw);
if (self.rest) self.rest = self.rest.transform(tw);
});
DEF(AST_Object, function(self, tw) {
self.properties = do_list(self.properties, tw);
});
DEF(AST_ObjectProperty, function(self, tw) {
if (self.key instanceof AST_Node) self.key = self.key.transform(tw);
self.value = self.value.transform(tw);
});
DEF(AST_ExportDeclaration, function(self, tw) {
self.body = self.body.transform(tw);
});
DEF(AST_ExportDefault, function(self, tw) {
self.body = self.body.transform(tw);
});
DEF(AST_ExportReferences, function(self, tw) {
self.properties = do_list(self.properties, tw);
});
DEF(AST_Import, function(self, tw) {
if (self.all) self.all = self.all.transform(tw);
if (self.default) self.default = self.default.transform(tw);
if (self.properties) self.properties = do_list(self.properties, tw);
});
DEF(AST_Template, function(self, tw) {
if (self.tag) self.tag = self.tag.transform(tw);
self.expressions = do_list(self.expressions, tw);
});
})(function(node, descend) {
node.DEFMETHOD("transform", function(tw, in_list) {
var x, y;

View File

@@ -143,8 +143,9 @@ function push_uniq(array, el) {
}
function string_template(text, props) {
return text.replace(/\{(.+?)\}/g, function(str, p) {
return props && props[p];
return text.replace(/\{([^}]+)\}/g, function(str, p) {
var value = props[p];
return value instanceof AST_Node ? value.print_to_string() : value;
});
}
@@ -237,21 +238,27 @@ function HOP(obj, prop) {
// return true if the node at the top of the stack (that means the
// innermost node in the current output) is lexically the first in
// a statement.
function first_in_statement(stack) {
function first_in_statement(stack, arrow, export_default) {
var node = stack.parent(-1);
for (var i = 0, p; p = stack.parent(i++); node = p) {
if (p.TYPE == "Call") {
if (p.expression === node) continue;
if (is_arrow(p)) {
return arrow && p.value === node;
} else if (p instanceof AST_Binary) {
if (p.left === node) continue;
} else if (p.TYPE == "Call") {
if (p.expression === node) continue;
} else if (p instanceof AST_Conditional) {
if (p.condition === node) continue;
} else if (p instanceof AST_ExportDefault) {
return export_default;
} else if (p instanceof AST_PropAccess) {
if (p.expression === node) continue;
} else if (p instanceof AST_Sequence) {
if (p.expressions[0] === node) continue;
} else if (p instanceof AST_Statement) {
return p.body === node;
} else if (p instanceof AST_SimpleStatement) {
return true;
} else if (p instanceof AST_Template) {
if (p.tag === node) continue;
} else if (p instanceof AST_UnaryPostfix) {
if (p.expression === node) continue;
}

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.11.1",
"version": "3.13.1",
"engines": {
"node": ">=0.8.0"
},

View File

@@ -1,6 +1,6 @@
"use strict";
require("../tools/exit");
require("../tools/tty");
var assert = require("assert");
var child_process = require("child_process");
@@ -10,33 +10,38 @@ var sandbox = require("./sandbox");
var semver = require("semver");
var U = require("./node");
var file = process.argv[2];
var batch = 50;
var dir = path.resolve(path.dirname(module.filename), "compress");
if (file) {
if (process.argv.length > 3) {
var file = process.argv[2];
var start = process.argv[3] | 0;
var minify_options = require("./ufuzz/options.json").map(JSON.stringify);
log("--- {file}", { file: file });
var tests = parse_test(path.resolve(dir, file));
process.exit(Object.keys(tests).filter(function(name) {
process.exit(Object.keys(tests).slice(start, start + batch).filter(function(name) {
return !test_case(tests[name]);
}).length);
} else {
var files = fs.readdirSync(dir).filter(function(name) {
var files = process.argv.length == 3 ? [ process.argv[2] ] : fs.readdirSync(dir).filter(function(name) {
return /\.js$/i.test(name);
});
var failures = 0;
var failed_files = Object.create(null);
(function next() {
var file = files.shift();
if (file) {
child_process.spawn(process.argv[0], [ process.argv[1], file ], {
(function next(file, start, length) {
if (start < length) {
child_process.spawn(process.argv[0], [ process.argv[1], file, start, batch ], {
stdio: [ "ignore", 1, 2 ]
}).on("exit", function(code) {
if (code) {
failures += code;
failed_files[file] = code;
failed_files[file] = true;
}
next();
next(file, start + batch, length);
});
} else if (file = files.shift()) {
log("--- {file}", { file: file });
start = 0;
length = Object.keys(parse_test(path.resolve(dir, file))).length;
next(file, start, length);
} else if (failures) {
console.error();
console.error("!!! Failed " + failures + " test case(s).");
@@ -63,7 +68,6 @@ function make_code(ast, options) {
function parse_test(file) {
var script = fs.readFileSync(file, "utf8");
// TODO try/catch can be removed after fixing https://github.com/mishoo/UglifyJS/issues/348
try {
var ast = U.parse(script, {
filename: file
@@ -210,7 +214,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 = run_code(result.code, toplevel);
var actual = sandbox.run_code(result.code, toplevel);
if (typeof expected != "string" && typeof actual != "string" && expected.name == actual.name) {
actual = expected;
}
@@ -245,11 +249,6 @@ function reminify(orig_options, input_code, input_formatted, stdout) {
return true;
}
function run_code(code, toplevel) {
var result = sandbox.run_code(code, toplevel);
return typeof result == "string" ? result.replace(/\u001b\[\d+m/g, "") : result;
}
function test_case(test) {
log(" Running test [{name}]", { name: test.name });
U.AST_Node.enable_validation();
@@ -315,6 +314,7 @@ function test_case(test) {
if (test.mangle.properties) U.mangle_properties(output, test.mangle.properties);
}
var output_code = make_code(output, output_options);
U.AST_Node.log_function();
if (expect != output_code) {
log([
"!!! failed",
@@ -380,13 +380,13 @@ function test_case(test) {
}
}
if (test.expect_stdout && (!test.node_version || semver.satisfies(process.version, test.node_version))) {
var stdout = [ run_code(input_code), run_code(input_code, true) ];
var stdout = [ sandbox.run_code(input_code), sandbox.run_code(input_code, true) ];
var toplevel = sandbox.has_toplevel({
compress: test.options,
mangle: test.mangle
});
var actual = stdout[toplevel ? 1 : 0];
if (test.expect_stdout === true) {
if (test.expect_stdout === true || test.expect_stdout instanceof Error && test.expect_stdout.name === actual.name) {
test.expect_stdout = actual;
}
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
@@ -409,7 +409,7 @@ function test_case(test) {
});
return false;
}
actual = run_code(output_code, toplevel);
actual = sandbox.run_code(output_code, toplevel);
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
log([
"!!! failed",

View File

@@ -78,7 +78,7 @@ replace_index_strict: {
]
}
replace_index_keep_fargs: {
replace_index_drop_fargs_1: {
options = {
arguments: true,
evaluate: true,
@@ -101,6 +101,13 @@ replace_index_keep_fargs: {
var arguments;
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function() {
var arguments = {
1: "foo",
foo: "bar",
};
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
}
expect: {
var arguments = [];
@@ -114,8 +121,15 @@ replace_index_keep_fargs: {
(function(arguments) {
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
(function() {
(function(argument_0, argument_1) {
var arguments;
console.log(argument_1, argument_1, arguments.foo);
})("bar", 42);
(function() {
var arguments = {
1: "foo",
foo: "bar",
};
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
}
@@ -125,10 +139,11 @@ replace_index_keep_fargs: {
"42 42 undefined",
"a a undefined",
"42 42 undefined",
"foo foo bar",
]
}
replace_index_keep_fargs_strict: {
replace_index_drop_fargs_2: {
options = {
arguments: true,
evaluate: true,
@@ -412,7 +427,7 @@ issue_3273_global_strict_reduce_vars: {
]
}
issue_3273_keep_fargs_false: {
issue_3273_drop_fargs_1: {
options = {
arguments: true,
keep_fargs: false,
@@ -435,10 +450,10 @@ issue_3273_keep_fargs_false: {
expect_stdout: "1"
}
issue_3273_keep_fargs_strict: {
issue_3273_drop_fargs_2: {
options = {
arguments: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
}
input: {
@@ -633,7 +648,7 @@ issue_3282_2_passes: {
issue_3420_1: {
options = {
arguments: true,
keep_fargs: "strict",
keep_fargs: false,
}
input: {
console.log(function() {
@@ -655,7 +670,7 @@ issue_3420_1: {
issue_3420_2: {
options = {
arguments: true,
keep_fargs: "strict",
keep_fargs: false,
}
input: {
var foo = function() {
@@ -675,7 +690,7 @@ issue_3420_2: {
issue_3420_3: {
options = {
arguments: true,
keep_fargs: "strict",
keep_fargs: false,
}
input: {
"use strict";
@@ -697,7 +712,7 @@ issue_3420_3: {
issue_3420_4: {
options = {
arguments: true,
keep_fargs: "strict",
keep_fargs: false,
}
input: {
!function() {
@@ -722,7 +737,7 @@ issue_3420_4: {
issue_3420_5: {
options = {
arguments: true,
keep_fargs: "strict",
keep_fargs: false,
}
input: {
"use strict";
@@ -749,7 +764,7 @@ issue_3420_5: {
issue_3420_6: {
options = {
arguments: true,
keep_fargs: "strict",
keep_fargs: false,
}
input: {
console.log(function() {
@@ -767,7 +782,7 @@ issue_3420_6: {
issue_3420_7: {
options = {
arguments: true,
keep_fargs: "strict",
keep_fargs: false,
}
input: {
"use strict";
@@ -783,3 +798,204 @@ issue_3420_7: {
}
expect_stdout: "true"
}
issue_4200: {
options = {
arguments: true,
keep_fargs: false,
}
input: {
var o = {
get p() {
return arguments[0];
},
};
console.log(o.p);
}
expect: {
var o = {
get p() {
return arguments[0];
},
};
console.log(o.p);
}
expect_stdout: "undefined"
}
issue_4291_1: {
options = {
arguments: true,
keep_fargs: false,
}
input: {
console.log(function() {
arguments[0] = "PASS";
return arguments;
}()[0]);
}
expect: {
console.log(function() {
arguments[0] = "PASS";
return arguments;
}()[0]);
}
expect_stdout: "PASS"
}
issue_4291_2: {
options = {
arguments: true,
keep_fargs: false,
}
input: {
var a = function() {
if (arguments[0])
arguments[1] = "PASS";
return arguments;
}(42);
console.log(a[1], a[0], a.length);
}
expect: {
var a = function(argument_0) {
if (argument_0)
arguments[1] = "PASS";
return arguments;
}(42);
console.log(a[1], a[0], a.length);
}
expect_stdout: "PASS 42 1"
}
issue_4397: {
options = {
arguments: true,
keep_fargs: false,
}
input: {
console.log(typeof function() {
arguments += 0;
return arguments[0];
}());
}
expect: {
console.log(typeof function() {
arguments += 0;
return arguments[0];
}());
}
expect_stdout: "string"
}
issue_4410_1: {
options = {
arguments: true,
conditionals: true,
evaluate: true,
reduce_vars: true,
}
input: {
(function(a) {
console.log(arguments[0] === (a = 0) ? "FAIL" : "PASS");
})(1);
}
expect: {
(function(a) {
console.log(a === (a = 0) ? "FAIL" : "PASS");
})(1);
}
expect_stdout: "PASS"
}
issue_4410_2: {
options = {
arguments: true,
conditionals: true,
evaluate: true,
reduce_vars: true,
}
input: {
(function f(a) {
console.log(arguments[0] === (a = 0) ? "FAIL" : "PASS");
})(1);
}
expect: {
(function f(a) {
console.log(arguments[0] === (a = 0) ? "FAIL" : "PASS");
})(1);
}
expect_stdout: "PASS"
}
issue_4410_3: {
options = {
arguments: true,
}
input: {
var a = 1;
(function f(b) {
a-- && f();
for (var c = 2; c--;)
switch (arguments[0]) {
case b = 42:
case 42:
console.log("PASS");
}
})(null);
}
expect: {
var a = 1;
(function f(b) {
a-- && f();
for (var c = 2; c--;)
switch (arguments[0]) {
case b = 42:
case 42:
console.log("PASS");
}
})(null);
}
expect_stdout: "PASS"
}
issue_4432: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
console.log(function(a) {
for (a in { FAIL: 42 });
return arguments[0];
}() || "PASS");
}
expect: {
console.log(function(a) {
for (a in { FAIL: 42 });
return arguments[0];
}() || "PASS");
}
expect_stdout: "PASS"
}
issue_4696: {
options = {
arguments: true,
keep_fargs: false,
}
input: {
console.log(function() {
for (arguments in [ 42 ]);
for (var a in arguments[0])
return "PASS";
}());
}
expect: {
console.log(function() {
for (arguments in [ 42 ]);
for (var a in arguments[0])
return "PASS";
}());
}
expect_stdout: "PASS"
}

View File

@@ -13,9 +13,10 @@ holes_and_undefined: {
}
}
constant_join: {
constant_join_1: {
options = {
evaluate: true,
side_effects: true,
strings: true,
unsafe: true,
}
@@ -57,7 +58,7 @@ constant_join: {
var c5 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join();
var c6 = [ "1,2,,,foo,bar", baz() ].join();
var d = "foo-3bar-baz";
var e = [].join(foo + bar);
var e = (foo, bar, "");
var f = "";
var g = "";
}
@@ -354,3 +355,72 @@ constructor_good: {
expect_stdout: true
expect_warnings: []
}
unsafe_evaluate_modified_binary: {
options = {
evaluate: true,
reduce_vars: true,
unsafe: true,
}
input: {
(function(a) {
(console && a).push(1);
if (a.length)
console.log("PASS");
})([]);
}
expect: {
(function(a) {
(console && a).push(1);
if (a.length)
console.log("PASS");
})([]);
}
expect_stdout: "PASS"
}
unsafe_evaluate_modified_conditional: {
options = {
evaluate: true,
reduce_vars: true,
unsafe: true,
}
input: {
(function(a) {
(console ? a : []).push(1);
if (a.length)
console.log("PASS");
})([]);
}
expect: {
(function(a) {
(console ? a : []).push(1);
if (a.length)
console.log("PASS");
})([]);
}
expect_stdout: "PASS"
}
unsafe_evaluate_modified_sequence: {
options = {
evaluate: true,
reduce_vars: true,
unsafe: true,
}
input: {
(function(a) {
(0, a).push(1);
if (a.length)
console.log("PASS");
})([]);
}
expect: {
(function(a) {
(0, a).push(1);
if (a.length)
console.log("PASS");
})([]);
}
expect_stdout: "PASS"
}

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

@@ -0,0 +1,805 @@
no_funarg: {
input: {
(() => console.log(42))();
}
expect_exact: "(()=>console.log(42))();"
expect_stdout: "42"
node_version: ">=4"
}
single_funarg: {
input: {
(a => console.log(a))(42);
}
expect_exact: "(a=>console.log(a))(42);"
expect_stdout: "42"
node_version: ">=4"
}
multiple_funargs: {
input: {
((a, b) => console.log(a, b))("foo", "bar");
}
expect_exact: '((a,b)=>console.log(a,b))("foo","bar");'
expect_stdout: "foo bar"
node_version: ">=4"
}
destructured_funarg: {
input: {
(([ a, b, c ]) => console.log(a, b, c))("foo");
}
expect_exact: '(([a,b,c])=>console.log(a,b,c))("foo");'
expect_stdout: "f o o"
node_version: ">=6"
}
await_parentheses: {
input: {
async function f() {
await (a => a);
}
}
expect_exact: "async function f(){await(a=>a)}"
}
for_parentheses_init: {
input: {
for (a => (a in a); console.log(42););
}
expect_exact: "for((a=>a in a);console.log(42););"
expect_stdout: "42"
node_version: ">=4"
}
for_parentheses_condition: {
input: {
for (console.log(42); a => (a in a);)
break;
}
expect_exact: "for(console.log(42);a=>a in a;)break;"
expect_stdout: "42"
node_version: ">=4"
}
for_parentheses_step: {
input: {
for (; console.log(42); a => (a in a));
}
expect_exact: "for(;console.log(42);a=>a in a);"
expect_stdout: "42"
node_version: ">=4"
}
for_assign_parentheses_init: {
input: {
for (f = a => (a in a); console.log(42););
}
expect_exact: "for((f=a=>a in a);console.log(42););"
expect_stdout: "42"
node_version: ">=4"
}
for_assign_parentheses_condition: {
input: {
for (console.log(42); f = a => (a in a);)
break;
}
expect_exact: "for(console.log(42);f=a=>a in a;)break;"
expect_stdout: "42"
node_version: ">=4"
}
for_assign_parentheses_step: {
input: {
for (; console.log(42); f = a => (a in a));
}
expect_exact: "for(;console.log(42);f=a=>a in a);"
expect_stdout: "42"
node_version: ">=4"
}
for_declaration_parentheses_init: {
input: {
for (var f = a => (a in a); console.log(42););
}
expect_exact: "for(var f=(a=>a in a);console.log(42););"
expect_stdout: "42"
node_version: ">=4"
}
for_statement_parentheses_init: {
input: {
for (a => {
a in a;
}; console.log(42););
}
expect_exact: "for(a=>{a in a};console.log(42););"
expect_stdout: "42"
node_version: ">=4"
}
body_call: {
input: {
(() => {
console.log("foo");
console.log("bar");
})();
}
expect_exact: '(()=>{console.log("foo");console.log("bar")})();'
expect_stdout: [
"foo",
"bar",
]
node_version: ">=4"
}
body_conditional: {
input: {
console.log((a => {}) ? "PASS" : "FAIL");
}
expect_exact: 'console.log((a=>{})?"PASS":"FAIL");'
expect_stdout: "PASS"
node_version: ">=4"
}
destructured_object_value: {
input: {
console.log((a => ({} = a))(42));
}
expect_exact: "console.log((a=>({}=a))(42));"
expect_stdout: "42"
node_version: ">=6"
}
function_value: {
input: {
console.log((a => function() {
return a;
})(42)());
}
expect_exact: "console.log((a=>function(){return a})(42)());"
expect_stdout: "42"
node_version: ">=4"
}
in_value: {
input: {
console.log((a => a in {
foo: 42,
})("foo"));
}
expect_exact: 'console.log((a=>a in{foo:42})("foo"));'
expect_stdout: "true"
node_version: ">=4"
}
object_value: {
input: {
console.log((() => ({
4: 2,
}))()[4]);
}
expect_exact: "console.log((()=>({4:2}))()[4]);"
expect_stdout: "2"
node_version: ">=4"
}
object_first_in_value: {
input: {
console.log((a => ({
p: a,
}.p ? "FAIL" : "PASS"))());
}
expect_exact: 'console.log((a=>({p:a}).p?"FAIL":"PASS")());'
expect_stdout: "PASS"
node_version: ">=4"
}
sequence_value: {
input: {
console.log((a => (console.log("foo"), a))("bar"));
}
expect_exact: 'console.log((a=>(console.log("foo"),a))("bar"));'
expect_stdout: [
"foo",
"bar",
]
node_version: ">=4"
}
side_effects_value: {
options = {
side_effects: true,
}
input: {
console.log((a => function() {
return a;
})(42)());
}
expect: {
console.log((a => function() {
return a;
})(42)());
}
expect_stdout: "42"
node_version: ">=4"
}
arrow_property: {
input: {
console.log((a => 42).prototype);
}
expect_exact: "console.log((a=>42).prototype);"
expect_stdout: "undefined"
node_version: ">=4"
}
assign_arrow: {
input: {
var f = a => a;
console.log(f(42));
}
expect_exact: "var f=a=>a;console.log(f(42));"
expect_stdout: "42"
node_version: ">=4"
}
binary_arrow: {
input: {
console.log(4 || (() => 2));
}
expect_exact: "console.log(4||(()=>2));"
expect_stdout: "4"
node_version: ">=4"
}
unary_arrow: {
input: {
console.log(+(() => 42));
}
expect_exact: "console.log(+(()=>42));"
expect_stdout: "NaN"
node_version: ">=4"
}
trailing_comma: {
input: {
((a,) => console.log(a))(42);
}
expect_exact: "(a=>console.log(a))(42);"
expect_stdout: "42"
node_version: ">=4"
}
drop_arguments: {
options = {
arguments: true,
keep_fargs: false,
}
input: {
console.log(function() {
return () => arguments[0];
}("PASS")("FAIL"));
}
expect: {
console.log(function(argument_0) {
return () => argument_0;
}("PASS")("FAIL"));
}
expect_stdout: "PASS"
node_version: ">=4"
}
funarg_arguments: {
options = {
inline: true,
}
input: {
console.log((arguments => arguments)(42));
}
expect: {
console.log(42);
}
expect_stdout: "42"
node_version: ">=4"
}
inline_arguments: {
options = {
inline: true,
}
input: {
console.log(function() {
return () => arguments[0];
}("PASS")("FAIL"));
}
expect: {
console.log(function() {
return () => arguments[0];
}("PASS")("FAIL"));
}
expect_stdout: "PASS"
node_version: ">=4"
}
var_arguments: {
options = {
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
console.log(function() {
return () => {
var arguments = [ "PASS" ];
return arguments;
};
}("FAIL 1")("FAIL 2")[0]);
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
negate: {
options = {
conditionals: true,
}
input: {
if (!console ? 0 : () => 1)
console.log("PASS");
}
expect: {
(console ? () => 1 : 0) && console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
inline_this: {
options = {
inline: true,
}
input: {
var o = {
p: function() {
return function() {
return () => this.q;
}();
},
q: "FAIL",
};
q = "PASS";
console.log(o.p()());
}
expect: {
var o = {
p: function() {
return function() {
return () => this.q;
}();
},
q: "FAIL",
};
q = "PASS";
console.log(o.p()());
}
expect_stdout: "PASS"
node_version: ">=4"
}
trim_body: {
options = {
arrows: true,
if_return: true,
side_effects: true,
}
input: {
var f = a => {
return a;
};
var g = b => void b;
console.log(f("PASS"), g("FAIL"));
}
expect: {
var f = a => a;
var g = b => {};
console.log(f("PASS"), g("FAIL"));
}
expect_stdout: "PASS undefined"
node_version: ">=4"
}
collapse_value: {
options = {
arrows: true,
collapse_vars: true,
keep_fargs: false,
unused: true,
}
input: {
var a = 42;
console.log((b => Math.floor(b))(a));
}
expect: {
var a = 42;
console.log((() => Math.floor(a))());
}
expect_stdout: "42"
node_version: ">=4"
}
collapse_property_lambda: {
options = {
collapse_vars: true,
pure_getters: "strict",
}
input: {
console.log(function f() {
f.g = () => 42;
return f.g();
}());
}
expect: {
console.log(function f() {
return (f.g = () => 42)();
}());
}
expect_stdout: "42"
node_version: ">=4"
}
drop_return: {
options = {
arrows: true,
side_effects: true,
}
input: {
(a => {
while (!console);
return console.log(a);
})(42);
}
expect: {
(a => {
while (!console);
console.log(a);
})(42);
}
expect_stdout: "42"
node_version: ">=4"
}
drop_value: {
options = {
arrows: true,
side_effects: true,
}
input: {
((a, b) => a + b)(console.log(42));
}
expect: {
((a, b) => {})(console.log(42));
}
expect_stdout: "42"
node_version: ">=4"
}
reduce_iife_1: {
options = {
evaluate: true,
keep_fargs: false,
reduce_vars: true,
unused: true,
}
input: {
(a => console.log(a + a))(21);
}
expect: {
(() => console.log(42))();
}
expect_stdout: "42"
node_version: ">=4"
}
reduce_iife_2: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 21;
(() => console.log(a + a))();
}
expect: {
(() => console.log(42))();
}
expect_stdout: "42"
node_version: ">=4"
}
reduce_iife_3: {
options = {
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = "foo";
(() => {
console.log(a);
console.log(a);
})();
a = "bar";
}
expect: {
(() => {
console.log("foo");
console.log("foo");
})();
}
expect_stdout: [
"foo",
"foo",
]
node_version: ">=4"
}
single_use_recursive: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {
return (() => f)();
}
console.log(typeof f());
}
expect: {
console.log(typeof function f() {
return (() => f)();
}());
}
expect_stdout: "function"
node_version: ">=4"
}
issue_4388: {
options = {
inline: true,
toplevel: true,
}
input: {
(arguments => console.log(arguments && arguments))();
}
expect: {
(arguments => console.log(arguments && arguments))();
}
expect_stdout: "undefined"
node_version: ">=4"
}
issue_4390: {
options = {
collapse_vars: true,
}
input: {
function log() {
console.log.apply(console, arguments);
}
var a = 42, b = "FAIL";
b = "PASS";
(c => log(b, c))(a);
log(b);
}
expect: {
function log() {
console.log.apply(console, arguments);
}
var a = 42, b = "FAIL";
b = "PASS";
(c => log(b, c))(a);
log(b);
}
expect_stdout: [
"PASS 42",
"PASS",
]
node_version: ">=4"
}
issue_4401: {
options = {
merge_vars: true,
}
input: {
(function() {
var a = (b => b(a))(console.log || a);
var c = console.log;
c && c(typeof b);
})();
}
expect: {
(function() {
var a = (b => b(a))(console.log || a);
var c = console.log;
c && c(typeof b);
})();
}
expect_stdout: [
"undefined",
"undefined",
]
node_version: ">=4"
}
issue_4448: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
var A;
try {
(arguments => {
arguments[0];
})(A);
} catch (e) {
console.log("PASS");
}
}
expect: {
var A;
try {
(arguments => {
arguments[0];
})(A);
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4476: {
options = {
arguments: true,
}
input: {
(function(a, b) {
(a => {
console.log(arguments[0], a);
})(b);
})("foo", "bar");
}
expect: {
(function(a, b) {
(a => {
console.log(arguments[0], a);
})(b);
})("foo", "bar");
}
expect_stdout: "foo bar"
node_version: ">=4"
}
issue_4666: {
input: {
console.log((a => /[0-9]/.test(a))(42));
}
expect_exact: "console.log((a=>/[0-9]/.test(a))(42));"
expect_stdout: "true"
node_version: ">=4"
}
issue_4685_1: {
options = {
collapse_vars: true,
unused: true,
}
input: {
new function(f) {
if (f() !== this)
console.log("PASS");
}(() => this);
}
expect: {
new function(f) {
if (f() !== this)
console.log("PASS");
}(() => this);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4685_2: {
options = {
reduce_vars: true,
unused: true,
}
input: {
new function(f) {
if (f() !== this)
console.log("PASS");
}(() => {
if (console)
return this;
});
}
expect: {
new function(f) {
if (f() !== this)
console.log("PASS");
}(() => {
if (console)
return this;
});
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4687_1: {
options = {
collapse_vars: true,
unused: true,
}
input: {
new function() {
console.log(function(f) {
return f() === this;
}(() => this) || "PASS");
}
}
expect: {
new function() {
console.log(function(f) {
return f() === this;
}(() => this) || "PASS");
}
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4687_2: {
options = {
reduce_vars: true,
unused: true,
}
input: {
new function() {
console.log(function(f) {
return f() === this;
}(() => {
if (console)
return this;
}) || "PASS");
}
}
expect: {
new function() {
console.log(function(f) {
return f() === this;
}(() => {
if (console)
return this;
}) || "PASS");
}
}
expect_stdout: "PASS"
node_version: ">=4"
}

View File

@@ -1,35 +0,0 @@
ascii_only_true: {
options = {}
beautify = {
ascii_only : true,
ie8 : false,
beautify : false,
}
input: {
function f() {
return "\x000\x001\x007\x008\x00" +
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
}
}
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\0"+"\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\v\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}'
}
ascii_only_false: {
options = {}
beautify = {
ascii_only : false,
ie8 : false,
beautify : false,
}
input: {
function f() {
return "\x000\x001\x007\x008\x00" +
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
}
}
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\0"+"\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
}

View File

@@ -76,9 +76,8 @@ asm_mixed: {
start = start | 0;
end = end | 0;
var sum = 0.0, p = 0, q = 0;
for (p = start << 3, q = end << 3; (p | 0) < (q | 0); p = p + 8 | 0) {
for (p = start << 3, q = end << 3; (p | 0) < (q | 0); p = p + 8 | 0)
sum = sum + +log(values[p >> 3]);
}
return +sum;
}
function geometricMean(start, end) {
@@ -91,7 +90,8 @@ asm_mixed: {
function no_asm_GeometricMean(stdlib, foreign, buffer) {
function logSum(start, end) {
start |= 0, end |= 0;
for (var sum = 0, p = 0, q = 0, p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
for (var sum = 0, p = 0, q = 0, p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0)
sum += +log(values[p >> 3]);
return +sum;
}
function geometricMean(start, end) {

View File

@@ -461,3 +461,17 @@ issue_3949_2: {
}
expect_stdout: "100"
}
issue_4521: {
options = {
assignments: true,
dead_code: true,
}
input: {
var a = (a = 42 | a) ? console.log(a) : 0;
}
expect: {
var a = (a |= 42) ? console.log(a) : 0;
}
expect_stdout: "42"
}

1410
test/compress/awaits.js Normal file

File diff suppressed because it is too large Load Diff

62
test/compress/bigint.js Normal file
View File

@@ -0,0 +1,62 @@
arithmetic: {
input: {
console.log(((1n + 0x2n) * (0o3n - -4n)) >> (5n - 6n));
}
expect_exact: "console.log((1n+0x2n)*(0o3n- -4n)>>5n-6n);"
expect_stdout: "42n"
node_version: ">=10"
}
minus_dot: {
input: {
console.log(typeof -42n.toString(), typeof (-42n).toString());
}
expect_exact: "console.log(typeof-42n.toString(),typeof(-42n).toString());"
expect_stdout: "number string"
node_version: ">=10"
}
evaluate: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log((0xDEAD_BEEFn).toString(16));
}
expect: {
console.log(0xdeadbeefn.toString(16));
}
expect_stdout: "deadbeef"
node_version: ">=10"
}
Number: {
options = {
unsafe: true,
}
input: {
console.log(Number(-0xfeed_dead_beef_badn));
}
expect: {
console.log(+("" + -0xfeed_dead_beef_badn));
}
expect_stdout: "-1148098955808013200"
node_version: ">=10"
}
issue_4590: {
options = {
collapse_vars: true,
}
input: {
A = 1;
0n || console.log("PASS");
}
expect: {
A = 1;
0n || console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=10"
}

View File

@@ -153,3 +153,31 @@ issue_3690: {
}
expect_stdout: "PASS"
}
issue_4374: {
options = {
booleans: true,
conditionals: true,
if_return: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
console.log(f());
function f(a) {
if (null) return 0;
if (a) return 1;
return 0;
}
})();
}
expect: {
(function() {
console.log(function(a) {
return !null && a ? 1 : 0;
}());
})();
}
expect_stdout: "0"
}

1277
test/compress/classes.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -346,9 +346,8 @@ collapse_vars_if: {
return "x" != "Bar" + x / 4 ? g9 : g5;
}
function f3(x) {
if (x) {
if (x)
return 1;
}
return 2;
}
}
@@ -959,8 +958,7 @@ collapse_vars_misc: {
}
expect: {
function f0(o, a, h) {
var b = 3 - a;
return o.run(b)[7] = h;
return o.run(3 - a)[7] = h;
}
function f1(x) { return 5 - x }
function f2(x) { return foo() / (5 - x) }
@@ -2277,8 +2275,8 @@ var_defs: {
}
expect: {
var f1 = function(x, y) {
var r = x + y, z = r * r - r, b = 7;
console.log(z + b);
var r = x + y;
console.log(r * r - r + 7);
};
f1("1", 0);
}
@@ -2908,8 +2906,7 @@ issue_2187_1: {
var a = 1;
!function(foo) {
foo();
var a = 2;
console.log(a);
console.log(2);
}(function() {
console.log(a);
});
@@ -3146,8 +3143,8 @@ issue_2313_2: {
var c = 0;
!function a() {
a && c++;
var a = 0;
a && c++;
var a;
(a = 0) && c++;
}();
console.log(c);
}
@@ -4192,9 +4189,8 @@ issue_2436_11: {
if (isCollection(arg1)) {
var size = arg1, max = arg2, min = 0, res = _randomDataForMatrix(size.valueOf(), min, max, _randomInt);
return size && true === size.isMatrix ? matrix(res) : res;
} else {
} else
return _randomInt(min = arg1, max = arg2);
}
}
}
}
@@ -4275,8 +4271,8 @@ issue_2436_14: {
var b = {};
(function() {
a && function(c, d) {
console.log(c, d);
}(b, a);
console.log(b, d);
}(0, a);
})();
}
expect_stdout: true
@@ -4310,9 +4306,8 @@ issue_2497: {
function sample() {
if (true)
for (var i = 0; i < 1; ++i)
for (var k = 0; k < 1; ++k) {
for (var k = 0; k < 1; ++k)
value = (value = 1) ? value + 1 : 0;
}
else
for (i = 0; i < 1; ++i)
for (k = 0; k < 1; ++k)
@@ -5505,8 +5500,7 @@ collapse_rhs_lhs_2: {
expect: {
var b = 1;
(function f(f) {
f = b;
f[b] = 0;
b[b] = 0;
})();
console.log("PASS");
}
@@ -5612,6 +5606,7 @@ collapse_rhs_array: {
collapse_rhs_boolean_1: {
options = {
collapse_vars: true,
evaluate: true,
}
input: {
var a, b;
@@ -5637,6 +5632,7 @@ collapse_rhs_boolean_1: {
collapse_rhs_boolean_2: {
options = {
collapse_vars: true,
evaluate: true,
}
input: {
var a;
@@ -5671,6 +5667,7 @@ collapse_rhs_boolean_3: {
booleans: true,
collapse_vars: true,
conditionals: true,
evaluate: true,
}
input: {
var a, f, g, h, i, n, s, t, x, y;
@@ -5724,6 +5721,7 @@ collapse_rhs_function: {
collapse_rhs_number: {
options = {
collapse_vars: true,
evaluate: true,
}
input: {
var a, b;
@@ -5803,6 +5801,7 @@ collapse_rhs_regexp: {
collapse_rhs_string: {
options = {
collapse_vars: true,
evaluate: true,
}
input: {
var a, b;
@@ -5878,6 +5877,7 @@ collapse_rhs_this: {
collapse_rhs_undefined: {
options = {
collapse_vars: true,
side_effects: true,
}
input: {
var a, b;
@@ -5999,7 +5999,7 @@ issue_3215_1: {
}());
}
expect: {
console.log(typeof 42);
console.log("number");
}
expect_stdout: "number"
}
@@ -6959,8 +6959,7 @@ sequence_in_iife_2: {
}
expect: {
var a = "foo", b = 42;
b = a;
console.log(a, b);
console.log(a, b = a);
}
expect_stdout: "foo foo"
}
@@ -8559,3 +8558,302 @@ issue_4070: {
}
expect_stdout: "NaN"
}
issue_4242: {
options = {
collapse_vars: true,
conditionals: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function() {
if (console)
var a = function(){}, b = (!1 === console || a)();
}());
}
expect: {
console.log(function() {
console && (!1 === console || function(){})();
}());
}
expect_stdout: "undefined"
}
issue_4248: {
options = {
collapse_vars: true,
}
input: {
var a = 0;
try {
a = 1;
b[1];
} catch (e) {
console.log(a);
}
}
expect: {
var a = 0;
try {
a = 1;
b[1];
} catch (e) {
console.log(a);
}
}
expect_stdout: "1"
}
issue_4430_1: {
options = {
collapse_vars: true,
pure_getters: "strict",
}
input: {
function f(a) {
switch (a = 1, arguments[0]) {
case 1:
return "PASS";
case 2:
return "FAIL";
}
}
console.log(f(2));
}
expect: {
function f(a) {
switch (a = 1, arguments[0]) {
case 1:
return "PASS";
case 2:
return "FAIL";
}
}
console.log(f(2));
}
expect_stdout: "PASS"
}
issue_4430_2: {
options = {
collapse_vars: true,
pure_getters: "strict",
}
input: {
function f(a) {
switch (a = 0, arguments[0]) {
case 0:
return "PASS";
case 1:
return "FAIL";
}
}
console.log(f(1));
}
expect: {
function f(a) {
switch (arguments[a = 0]) {
case 0:
return "PASS";
case 1:
return "FAIL";
}
}
console.log(f(1));
}
expect_stdout: "PASS"
}
collapse_and_assign: {
options = {
collapse_vars: true,
}
input: {
var log = console.log;
var a = {
p: "PASS",
};
console && (a = a.p);
log(a);
}
expect: {
var log = console.log;
var a = {
p: "PASS",
};
log(a = console ? a.p : a);
}
expect_stdout: "PASS"
}
collapse_or_assign: {
options = {
collapse_vars: true,
}
input: {
var log = console.log;
var a = {
p: "PASS",
};
a.q || (a = a.p);
log(a);
}
expect: {
var log = console.log;
var a = {
p: "PASS",
};
log(a = !a.q ? a.p : a);
}
expect_stdout: "PASS"
}
issue_4586_1: {
options = {
collapse_vars: true,
}
input: {
var a = 42;
(function f(b) {
var b = a;
if (b === arguments[0])
console.log("PASS");
})(console);
}
expect: {
var a = 42;
(function f(b) {
var b = a;
if (b === arguments[0])
console.log("PASS");
})(console);
}
expect_stdout: "PASS"
}
issue_4586_2: {
options = {
collapse_vars: true,
}
input: {
var a = 42;
(function f(b) {
b = a;
if (b === arguments[0])
console.log("PASS");
})(console);
}
expect: {
var a = 42;
(function f(b) {
if ((b = a) === arguments[0])
console.log("PASS");
})(console);
}
expect_stdout: "PASS"
}
issue_4732_1: {
options = {
booleans: true,
collapse_vars: true,
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
var a = 0;
(function(b) {
var b = a++;
var c = b ? b && console.log("PASS") : 0;
})(a++);
}
expect: {
var a = 0;
(function(b) {
(b = a++) && (b && console.log("PASS"));
})(a++);
}
expect_stdout: "PASS"
}
issue_4732_2: {
options = {
collapse_vars: true,
conditionals: true,
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
var a = 0;
(function(b) {
var b = a++;
var c = b ? b && console.log("PASS") : 0;
})(a++);
}
expect: {
var a = 0;
(function(b) {
(b = a++) && b && console.log("PASS");
})(a++);
}
expect_stdout: "PASS"
}
dot_in_try: {
options = {
collapse_vars: true,
}
input: {
var o, a = 6, b = 7, c;
try {
c = a * b;
o.p(c);
} catch (e) {
console.log(c);
}
}
expect: {
var o, a = 6, b = 7, c;
try {
c = a * b;
o.p(c);
} catch (e) {
console.log(c);
}
}
expect_stdout: "42"
}
dot_non_local: {
options = {
collapse_vars: true,
}
input: {
var o, a = 6, b = 7, c;
function f() {
c = a * b;
o.p(c);
}
try {
f();
} catch (e) {
console.log(c);
}
}
expect: {
var o, a = 6, b = 7, c;
function f() {
c = a * b;
o.p(c);
}
try {
f();
} catch (e) {
console.log(c);
}
}
expect_stdout: "42"
}

View File

@@ -55,14 +55,15 @@ ifs_3_should_warn: {
}
input: {
var x, y;
if (x && !(x + "1") && y) { // 1
// 1
if (x && !(x + "1") && y) {
var qq;
foo();
} else {
bar();
}
if (x || !!(x + "1") || y) { // 2
// 2
if (x || !!(x + "1") || y) {
foo();
} else {
var jj;
@@ -71,9 +72,25 @@ ifs_3_should_warn: {
}
expect: {
var x, y;
var qq; bar(); // 1
var jj; foo(); // 2
// 1
var qq; bar();
// 2
foo(); var jj;
}
expect_warnings: [
"WARN: + in boolean context always true [test/compress/conditionals.js:3,18]",
"WARN: Boolean && always false [test/compress/conditionals.js:3,12]",
"WARN: Condition left of && always false [test/compress/conditionals.js:3,12]",
"WARN: Condition always false [test/compress/conditionals.js:3,12]",
"WARN: Dropping unreachable code [test/compress/conditionals.js:3,34]",
"WARN: + in boolean context always true [test/compress/conditionals.js:10,19]",
"WARN: Boolean || always true [test/compress/conditionals.js:10,12]",
"WARN: Condition left of || always true [test/compress/conditionals.js:10,12]",
"WARN: Condition always true [test/compress/conditionals.js:10,12]",
"WARN: Dropping unreachable code [test/compress/conditionals.js:12,15]",
"WARN: Dropping side-effect-free statement [test/compress/conditionals.js:3,12]",
"WARN: Dropping side-effect-free statement [test/compress/conditionals.js:10,12]",
]
}
ifs_4: {
@@ -1159,7 +1176,7 @@ issue_1645_2: {
expect_stdout: true
}
condition_symbol_matches_consequent: {
condition_matches_consequent: {
options = {
conditionals: true,
}
@@ -1188,6 +1205,35 @@ condition_symbol_matches_consequent: {
expect_stdout: "3 7 true 4"
}
condition_matches_alternative: {
options = {
conditionals: true,
}
input: {
function foo(x, y) {
return x.p ? y[0] : x.p;
}
function bar() {
return g ? h : g;
}
var g = 4;
var h = 5;
console.log(foo({ p: 3 }, [ null ]), foo({ p: 0 }, [ 7 ]), foo({ p: true } , [ false ]), bar());
}
expect: {
function foo(x, y) {
return x.p && y[0];
}
function bar() {
return g && h;
}
var g = 4;
var h = 5;
console.log(foo({ p: 3 }, [ null ]), foo({ p: 0 }, [ 7 ]), foo({ p: true } , [ false ]), bar());
}
expect_stdout: "null 0 false 5"
}
delete_conditional_1: {
options = {
booleans: true,
@@ -1815,3 +1861,39 @@ issue_3808_2: {
}
expect_stdout: " PASS"
}
object_super: {
options = {
conditionals: true,
}
input: {
Object.setPrototypeOf({
f(a) {
a ? this.g("FAIL") : super.g("FAIL");
},
g(b) {
console.log(b);
},
}, {
g() {
console.log("PASS");
},
}).f();
}
expect: {
Object.setPrototypeOf({
f(a) {
a ? this.g("FAIL") : super.g("FAIL");
},
g(b) {
console.log(b);
},
}, {
g() {
console.log("PASS");
},
}).f();
}
expect_stdout: "PASS"
node_version: ">=4"
}

1500
test/compress/const.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -53,13 +53,17 @@ dead_code_2_should_warn: {
g();
x = 10;
throw new Error("foo");
var x;
function g(){};
{
var x;
function g(){};
}
}
f();
}
expect_stdout: true
node_version: "<=4"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/dead-code.js:8,12]",
]
}
dead_code_constant_boolean_should_warn_more: {
@@ -85,15 +89,27 @@ dead_code_constant_boolean_should_warn_more: {
bar();
}
expect: {
var foo;
function bar() {}
{
var foo;
function bar() {}
}
// nothing for the while
// as for the for, it should keep:
var moo;
var x = 10, y;
var moo;
bar();
}
expect_stdout: true
expect_warnings: [
"WARN: + in boolean context always true [test/compress/dead-code.js:1,33]",
"WARN: Boolean || always true [test/compress/dead-code.js:1,16]",
"WARN: Dropping unreachable code [test/compress/dead-code.js:1,45]",
"WARN: Boolean expression always true [test/compress/dead-code.js:6,47]",
"WARN: Boolean && always false [test/compress/dead-code.js:6,28]",
"WARN: Dropping unreachable code [test/compress/dead-code.js:6,63]",
"WARN: Dropping side-effect-free statement [test/compress/dead-code.js:1,15]",
"WARN: Dropping side-effect-free statement [test/compress/dead-code.js:6,28]",
]
node_version: "<=4"
}
@@ -712,7 +728,7 @@ issue_2749: {
expect: {
var a = 2, c = "PASS";
while (a--)
b = void 0, b ? c = "FAIL" : b = 1;
b = void 0, b ? c = "FAIL" : 1;
var b;
console.log(c);
}
@@ -1362,3 +1378,45 @@ issue_4051: {
}
expect_stdout: "PASS"
}
issue_4366: {
options = {
dead_code: true,
}
input: {
function f() {
return "PASS";
({
p: 42,
get p() {},
});
}
console.log(f());
}
expect: {
function f() {
return "PASS";
}
console.log(f());
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4570: {
options = {
dead_code: true,
inline: true,
}
input: {
var a = function(b) {
return a += b;
}() ? 0 : a;
console.log(a);
}
expect: {
var a = (a += void 0) ? 0 : a;
console.log(a);
}
expect_stdout: "NaN"
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -4,15 +4,16 @@ unused_funarg_1: {
unused: true,
}
input: {
function f(a, b, c, d, e) {
console.log(function f(a, b, c, d, e) {
return a + b;
}
}(14, 28));
}
expect: {
function f(a, b) {
console.log(function(a, b) {
return a + b;
}
}(14, 28));
}
expect_stdout: "42"
}
unused_funarg_2: {
@@ -21,15 +22,16 @@ unused_funarg_2: {
unused: true,
}
input: {
function f(a, b, c, d, e) {
console.log(function f(a, b, c, d, e) {
return a + c;
}
}(14, 21, 28));
}
expect: {
function f(a, b, c) {
console.log(function(a, c) {
return a + c;
}
}(14, 28));
}
expect_stdout: "42"
}
unused_nested_function: {
@@ -357,37 +359,6 @@ drop_toplevel_vars: {
}
}
drop_toplevel_vars_fargs: {
options = {
keep_fargs: false,
toplevel: "vars",
unused: true,
}
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
};
}
a = 2;
function g() {}
function h() {}
console.log(b = 3);
}
expect: {
function f() {
return function() {
2;
};
}
2;
function g() {}
function h() {}
console.log(3);
}
}
drop_toplevel_all: {
options = {
toplevel: true,
@@ -625,13 +596,14 @@ drop_fargs: {
unused: true,
}
input: {
function f(a) {
console.log(function f(a) {
var b = a;
}
}());
}
expect: {
function f() {}
console.log(function() {}());
}
expect_stdout: "undefined"
}
drop_fnames: {
@@ -2027,7 +1999,7 @@ issue_3192_1: {
issue_3192_2: {
options = {
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -2166,6 +2138,7 @@ issue_3497: {
issue_3515_1: {
options = {
collapse_vars: true,
evaluate: true,
reduce_vars: true,
unused: true,
}
@@ -2217,6 +2190,7 @@ issue_3515_2: {
issue_3515_3: {
options = {
collapse_vars: true,
evaluate: true,
unused: true,
}
input: {
@@ -2284,6 +2258,7 @@ function_assign: {
issue_3598: {
options = {
collapse_vars: true,
evaluate: true,
reduce_vars: true,
unused: true,
}
@@ -2435,7 +2410,7 @@ issue_3673: {
issue_3746: {
options = {
keep_fargs: "strict",
keep_fargs: false,
side_effects: true,
unused: true,
}
@@ -2697,8 +2672,7 @@ issue_3956: {
})();
}
expect: {
var c, d;
c += 0,
var d;
console.log(NaN),
d = 1 ^ console.log(1),
console.log(d);
@@ -2713,7 +2687,7 @@ issue_3956: {
issue_3962_1: {
options = {
evaluate: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -2731,13 +2705,13 @@ issue_3962_1: {
}
expect: {
var a = 0;
a = (function(c) {
(function(c) {
do {
console;
0..toString();
} while (0);
if (c) console.log("PASS");
}(1), 0);
})(1);
void 0;
}
expect_stdout: "PASS"
@@ -2745,7 +2719,7 @@ issue_3962_1: {
issue_3962_2: {
options = {
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -2764,13 +2738,13 @@ issue_3962_2: {
}
expect: {
var a = 0;
a = (function(c) {
(function(c) {
do {
console;
0..toString();
} while (0);
if (c) console.log("PASS");
}(1), 0);
})(1);
}
expect_stdout: "PASS"
}
@@ -2827,7 +2801,9 @@ issue_4017: {
var a = 0;
console.log(function() {
c &= 0;
var c = (a++, A = a, 0);
var c;
a++,
A = a;
}());
}
expect_stdout: "undefined"
@@ -2948,7 +2924,7 @@ issue_4133: {
issue_4144: {
options = {
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
unused: true,
}
@@ -2993,6 +2969,38 @@ issue_4146: {
expect_stdout: "function"
}
var_catch_redefined: {
options = {
toplevel: true,
unused: true,
}
input: {
var a = "FAIL";
try {
throw "PASS";
} catch (a) {
function f() {
return a;
}
console.log(a);
}
f();
}
expect: {
var a = "FAIL";
try {
throw "PASS";
} catch (a) {
function f() {
return a;
}
console.log(a);
}
f();
}
expect_stdout: "PASS"
}
single_use_catch_redefined: {
options = {
reduce_vars: true,
@@ -3023,3 +3031,246 @@ single_use_catch_redefined: {
}
expect_stdout: true
}
issue_4184: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function() {
var a = function() {}, b = [ a, 1 && b, a = {} ];
try {
throw 42;
} catch (a) {
{
console.log(a);
}
}
})();
}
expect: {
(function() {
var b = [ function() {}, 1 && b, {} ];
try {
throw 42;
} catch (a) {
console.log(a);
}
})();
}
expect_stdout: "42"
}
issue_4235: {
options = {
inline: true,
reduce_vars: true,
unused: true,
varify: true,
}
input: {
(function() {
{
const f = 0;
}
(function f() {
var f = console.log(f);
})();
})();
}
expect: {
(function() {
f = console.log(f),
void 0;
var f;
})();
}
expect_stdout: "undefined"
}
issue_4404: {
options = {
pure_getters: "strict",
unused: true,
}
input: {
function f(a) {
arguments[0] = "PASS";
console.log(a);
}
f("FAIL");
}
expect: {
function f(a) {
arguments[0] = "PASS";
console.log(a);
}
f("FAIL");
}
expect_stdout: "PASS"
}
issue_4413: {
options = {
reduce_vars: true,
unused: true,
}
input: {
console.log(function f(arguments) {
var arguments = function() {};
return arguments.length;
}());
}
expect: {
console.log(function(arguments) {
return function() {}.length;
}());
}
expect_stdout: "0"
}
issue_4464_1: {
options = {
reduce_vars: true,
unused: true,
}
input: {
function f(a) {
var a = function() {};
return [ arguments, a ];
}
console.log(typeof f()[1]);
}
expect: {
function f(a) {
a = function() {};
return [ arguments, a ];
}
console.log(typeof f()[1]);
}
expect_stdout: "function"
}
issue_4464_2: {
options = {
reduce_vars: true,
unused: true,
}
input: {
function f(a) {
var a = function() {};
return [ arguments, a ];
}
console.log(typeof f(42)[0][0]);
}
expect: {
function f(a) {
a = function() {};
return [ arguments, a ];
}
console.log(typeof f(42)[0][0]);
}
expect_stdout: "function"
}
issue_4464_3: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function a(a) {
var a = function() {};
return [ arguments[0], a ];
})(42).forEach(function(b) {
console.log(typeof b);
});
}
expect: {
(function(a) {
a = function() {};
return [ arguments[0], a ];
})(42).forEach(function(b) {
console.log(typeof b);
});
}
expect_stdout: [
"function",
"function",
]
}
issue_4558_1: {
options = {
evaluate: true,
pure_getters: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = 0;
var b = 1, b = c >>>= a;
var c = 0;
b && 0[a++],
console.log(a);
}
expect: {
var a = 0;
var b = c >>>= a;
var c;
b && a++,
console.log(a);
}
expect_stdout: "0"
}
issue_4558_2: {
options = {
evaluate: true,
ie8: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
var a = 1;
var b = (a = NaN) || (console.log("PASS"), 2);
return a;
})();
}
expect: {
(function() {
var a;
(a = NaN) || console.log("PASS");
return a;
})();
}
expect_stdout: "PASS"
}
issue_4662: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 0;
function f(b, c) {
console.log(b, c);
}
f(++a, a = a, a);
}
expect: {
var a = 0;
(function(b, c) {
console.log(b, c);
})(++a, a = 1);
}
expect_stdout: "1 1"
}

View File

@@ -399,18 +399,18 @@ unsafe_object_accessor: {
function f() {
var a = {
get b() {},
set b() {}
set b(v) {},
};
return {a:a};
return { a: a };
}
}
expect: {
function f() {
var a = {
get b() {},
set b() {}
set b(v) {},
};
return {a:a};
return { a: a };
}
}
}
@@ -703,6 +703,7 @@ prototype_function: {
var g = 0();
var h = 0();
}
expect_stdout: true
}
call_args: {
@@ -846,6 +847,8 @@ unsafe_charAt_noop: {
unsafe: true,
}
input: {
s = "foo";
x = 42;
console.log(
s.charAt(0),
"string".charAt(x),
@@ -853,12 +856,15 @@ unsafe_charAt_noop: {
);
}
expect: {
s = "foo";
x = 42;
console.log(
s[0],
"string"[0 | x],
(typeof x)[0]
s[0] || "",
"string"[0 | x] || "",
(typeof x)[0] || ""
);
}
expect_stdout: "f n"
}
issue_1649: {
@@ -2800,7 +2806,7 @@ operator_in: {
console.log("PASS" in { });
console.log("FAIL" in { });
console.log("toString" in { });
console.log(true);
console.log("toString" in { toString: 3 });
}
expect_stdout: [
"true",
@@ -3014,3 +3020,164 @@ issue_4119_4: {
}
expect_stdout: "PASS"
}
issue_4214: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f(a) {
return function() {
try {
return a;
} finally {
var b = 0;
}
}(a++ && this());
}
var c = f();
console.log(c);
}
expect: {
var c = function(a) {
return function() {
try {
return a;
} finally {}
}(a++ && this());
}();
console.log(c);
}
expect_stdout: "NaN"
}
issue_4271: {
options = {
evaluate: true,
unsafe: true,
}
input: {
({
p: null,
q: (console.log("foo"), 42),
p: function() {}
})[console.log("bar"), "p"] && console.log("PASS");
}
expect: {
({
p: null,
q: (console.log("foo"), 42),
p: function() {}
})[console.log("bar"), "p"],
console.log("PASS");
}
expect_stdout: [
"foo",
"bar",
"PASS",
]
}
issue_4393: {
options = {
evaluate: true,
reduce_vars: true,
}
input: {
(function f(a) {
a = "PASS";
console.log(arguments[0]);
})("FAIL");
}
expect: {
(function f(a) {
a = "PASS";
console.log(arguments[0]);
})("FAIL");
}
expect_stdout: "PASS"
}
issue_4422: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function f(a) {
a = "FAIL 1";
arguments[0] = "PASS";
return a;
}("FAIL 2"));
}
expect: {
console.log(function(a) {
a = "FAIL 1";
arguments[0] = "PASS";
return a;
}("FAIL 2"));
}
expect_stdout: "PASS"
}
issue_4480: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
var a = function f(b) {
b = "FAIL";
arguments[0] = "PASS";
var arguments = 0;
console.log(b);
}(a);
}
expect: {
var a = function(b) {
b = "FAIL";
arguments[0] = "PASS";
var arguments = 0;
console.log(b);
}(a);
}
expect_stdout: "PASS"
}
issue_4552: {
options = {
evaluate: true,
keep_fnames: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = function f(b) {
return function() {
b++;
try {
return b;
} catch (e) {}
}();
}();
console.log(a);
}
expect: {
var a = function f(b) {
return function() {
b++;
try {
return b;
} catch (e) {}
}();
}();
console.log(a);
}
expect_stdout: "NaN"
}

View File

@@ -0,0 +1,125 @@
precedence_1: {
input: {
console.log(-4 ** 3 ** 2);
}
expect_exact: "console.log((-4)**3**2);"
expect_stdout: "-262144"
node_version: ">=8"
}
precedence_2: {
input: {
console.log(-4 ** (3 ** 2));
}
expect_exact: "console.log((-4)**3**2);"
expect_stdout: "-262144"
node_version: ">=8"
}
precedence_3: {
input: {
console.log(-(4 ** 3) ** 2);
}
expect_exact: "console.log((-(4**3))**2);"
expect_stdout: "4096"
node_version: ">=8"
}
precedence_4: {
input: {
console.log((-4 ** 3) ** 2);
}
expect_exact: "console.log(((-4)**3)**2);"
expect_stdout: "4096"
node_version: ">=8"
}
await: {
input: {
(async a => a * await a ** ++a % a)(2).then(console.log);
}
expect_exact: "(async a=>a*(await a)**++a%a)(2).then(console.log);"
expect_stdout: "1"
node_version: ">=8"
}
evaluate: {
options = {
evaluate: true,
}
input: {
console.log(1 + 2 ** 3 - 4);
}
expect: {
console.log(5);
}
expect_stdout: "5"
node_version: ">=8"
}
issue_4664: {
options = {
collapse_vars: true,
evaluate: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function f() {
new function(a) {
console.log(typeof f, a, typeof this);
}((A = 0, (NaN ^ 1) * 2 ** 30), 0);
}
f();
}
expect: {
(function f() {
new function(a) {
console.log(typeof f, 2 ** 30, typeof this);
}(0, A = 0);
})();
}
expect_stdout: "function 1073741824 object"
node_version: ">=8"
}
issue_4715: {
options = {
evaluate: true,
}
input: {
A = 1;
console.log((-0) ** A + 0);
console.log((-0) ** A - 0);
console.log((-0) ** A * 1);
console.log((-0) ** A / 1);
console.log(Math.pow(-0, A) + 0);
console.log(Math.pow(-0, A) - 0);
console.log(Math.pow(-0, A) * 1);
console.log(Math.pow(-0, A) / 1);
}
expect: {
A = 1;
console.log((-0) ** A + 0);
console.log((-0) ** A);
console.log((-0) ** A * 1);
console.log((-0) ** A);
console.log(Math.pow(-0, A) + 0);
console.log(+Math.pow(-0, A));
console.log(+Math.pow(-0, A));
console.log(+Math.pow(-0, A));
}
expect_stdout: [
"0",
"-0",
"-0",
"-0",
"0",
"-0",
"-0",
"-0",
]
node_version: ">=8"
}

466
test/compress/exports.js Normal file
View File

@@ -0,0 +1,466 @@
refs: {
input: {
export {};
export { a, b as B, c as case, d as default };
}
expect_exact: "export{};export{a as a,b as B,c as case,d as default};"
}
var_defs: {
input: {
export const a = 1;
export let b = 2, c = 3;
export var { d, e: [] } = f;
}
expect_exact: "export const a=1;export let b=2,c=3;export var{d:d,e:[]}=f;"
}
defuns: {
input: {
export class A {}
export function e() {}
export function* f(a) {}
export async function g(b, c) {}
export async function* h({}, ...[]) {}
}
expect_exact: "export class A{}export function e(){}export function*f(a){}export async function g(b,c){}export async function*h({},...[]){}"
}
defaults: {
input: {
export default 42;
export default async;
export default (x, y) => x * x;
export default class {};
export default function*(a, b) {};
export default async function f({ c }, ...[ d ]) {};
}
expect_exact: "export default 42;export default async;export default(x,y)=>x*x;export default class{}export default function*(a,b){}export default async function f({c:c},...[d]){}"
}
defaults_parentheses_1: {
input: {
export default function() {
console.log("FAIL");
}(console.log("PASS"));
}
expect_exact: 'export default function(){console.log("FAIL")}console.log("PASS");'
}
defaults_parentheses_2: {
input: {
export default (async function() {
console.log("PASS");
})();
}
expect_exact: 'export default(async function(){console.log("PASS")})();'
}
defaults_parentheses_3: {
input: {
export default (42, "PASS");
}
expect_exact: 'export default(42,"PASS");'
}
defaults_parentheses_4: {
input: {
export default (function f() {});
}
expect_exact: "export default(function f(){});"
}
defaults_parentheses_5: {
input: {
export default (function(a) {
console.log(a[0]);
}`PASS`);
}
expect_exact: "export default(function(a){console.log(a[0])})`PASS`;"
}
defaults_parentheses_6: {
options = {
conditionals: true,
}
input: {
export default !function() {
while (!console);
}() ? "PASS" : "FAIL";
}
expect_exact: 'export default(function(){while(!console);})()?"FAIL":"PASS";'
}
foreign: {
input: {
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";
}
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";'
}
same_quotes: {
beautify = {
beautify: true,
quote_style: 3,
}
input: {
export * from 'foo';
export {} from "bar";
}
expect_exact: [
"export * from 'foo';",
"",
'export {} from "bar";',
]
}
drop_unused: {
options = {
toplevel: true,
unused: true,
}
input: {
export default 42;
export default (x, y) => x * x;
export default class A extends B { get p() { h() } }
export default function*(a, b) {}
export default async function f({ c }, ...[ d ]) {}
export var e;
export function g(x, [ y ], ...z) {}
function h() {}
}
expect: {
export default 42;
export default (x, y) => x * x;
export default class extends B { get p() { h() } }
export default function*(a, b) {}
export default async function({}) {}
export var e;
export function g(x, []) {}
function h() {}
}
}
mangle: {
rename = false
mangle = {
toplevel: true,
}
input: {
const a = 42;
export let b, { foo: c } = a;
export function f(d, { [b]: e }) {
d(e, f);
}
export default a;
export default async function g(x, ...{ [c]: y }) {
(await x)(g, y);
}
}
expect: {
const t = 42;
export let b, { foo: c } = t;
export function f(t, { [b]: o }) {
t(o, f);
}
export default t;
export default async function e(t, ...{ [c]: o}) {
(await t)(e, o);
}
}
}
mangle_rename: {
rename = true
mangle = {
toplevel: true,
}
input: {
const a = 42;
export let b, { foo: c } = a;
export function f(d, { [b]: e }) {
d(e, f);
}
export default a;
export default async function g(x, ...{ [c]: y }) {
(await x)(g, y);
}
}
expect: {
const t = 42;
export let b, { foo: c } = t;
export function f(t, { [b]: o }) {
t(o, f);
}
export default t;
export default async function e(t, ...{ [c]: o}) {
(await t)(e, o);
}
}
}
hoist_exports_1: {
options = {
hoist_exports: true,
}
input: {
export { a };
export var b;
export function f() {}
}
expect: {
var b;
function f() {}
export { a, b, f };
}
}
hoist_exports_2: {
options = {
evaluate: true,
hoist_exports: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
const a = 42;
export let bbb, { foo: ccc } = a;
export function fff(d, { [bbb]: e }) {
d(e, fff);
}
export default a;
export default async function g(x, ...{ [ccc]: y }) {
(await x)(g, y);
}
}
expect: {
let f, { foo: o } = 42;
function c(t, { [f]: a }) {
t(a, c);
}
export default 42;
export default async function e(t, ...{ [o]: a }) {
(await t)(e, a);
};
export { f as bbb, o as ccc, c as fff };
}
}
hoist_vars: {
options = {
hoist_vars: true,
}
input: {
var a;
export var b = 42;
}
expect: {
var a;
export var b = 42;
}
}
keep_return_values: {
options = {
booleans: true,
evaluate: true,
reduce_vars: true,
toplevel: true,
}
input: {
export default function() {
return [];
}
export default function f() {
return null;
}
}
expect: {
export default function() {
return [];
}
export default function f() {
return null;
}
}
}
in_use: {
options = {
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
export function f() {}
f.prototype.p = 42;
}
expect: {
export function f() {}
f.prototype.p = 42;
}
}
in_use_default: {
options = {
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
export default function f() {}
f.prototype.p = 42;
}
expect: {
export default function f() {}
f.prototype.p = 42;
}
}
single_use: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
export function f() {
console.log("PASS");
}
f();
}
expect: {
export function f() {
console.log("PASS");
}
f();
}
}
single_use_default: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
export default function f() {
console.log("PASS");
}
f();
}
expect: {
export default function f() {
console.log("PASS");
}
f();
}
}
single_use_class: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
export class A {}
A.prototype.p = "PASS";
}
expect: {
export class A {}
A.prototype.p = "PASS";
}
}
single_use_class_default: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
export default class A {}
A.prototype.p = "PASS";
}
expect: {
export default class A {}
A.prototype.p = "PASS";
}
}
issue_4742_join_vars_1: {
options = {
join_vars: true,
}
input: {
var a = 42;
export var a;
}
expect: {
var a = 42;
export var a;
}
}
issue_4742_join_vars_2: {
options = {
join_vars: true,
}
input: {
export var a = "foo";
var b;
b = "bar";
}
expect: {
export var a = "foo";
var b, b = "bar";
}
}
issue_4742_unused_1: {
options = {
unused: true,
}
input: {
var a = 42;
export var a;
}
expect: {
var a = 42;
export var a;
}
}
issue_4742_unused_2: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
export var a = "foo";
var a = "bar";
}
expect: {
export var a = "foo";
a = "bar";
}
}
issue_4761: {
input: {
export default "function" == 42;
}
expect_exact: 'export default"function"==42;'
}

File diff suppressed because it is too large Load Diff

View File

@@ -297,6 +297,33 @@ name_collision_3: {
expect_stdout: "true 4 6"
}
name_collision_4: {
options = {
hoist_props: true,
reduce_vars: true,
}
input: {
console.log(function() {
var o = {
p: 0,
q: "PASS",
};
return function(o_p) {
if (!o.p) return o_p;
}(o.q);
}());
}
expect: {
console.log(function() {
var o_p$0 = 0, o_q = "PASS";
return function(o_p) {
if (!o_p$0) return o_p;
}(o_q);
}());
}
expect_stdout: "PASS"
}
contains_this_1: {
options = {
evaluate: true,
@@ -1041,3 +1068,29 @@ issue_4023: {
}
expect_stdout: "true"
}
object_super: {
options = {
hoist_props: true,
reduce_vars: true,
toplevel: true,
}
input: {
var o = {
f(a) {
return a ? console.log("PASS") : super.log("PASS");
},
};
o.f(42);
}
expect: {
var o = {
f(a) {
return a ? console.log("PASS") : super.log("PASS");
},
};
o.f(42);
}
expect_stdout: "PASS"
node_version: ">=4"
}

View File

@@ -89,6 +89,31 @@ sequences_funs: {
}
}
catch_var: {
options = {
dead_code: true,
hoist_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = "PASS";
try {
a;
} catch (a) {
var a = 0;
a;
}
console.log(a);
}
expect: {
var a = "PASS";
console.log(a);
}
expect_stdout: "PASS"
}
issue_2295: {
options = {
collapse_vars: true,
@@ -109,3 +134,109 @@ issue_2295: {
}
}
}
issue_4487: {
options = {
functions: true,
hoist_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 a = console.log(typeof a);
}
a();
}
expect_stdout: "undefined"
}
issue_4489: {
options = {
collapse_vars: true,
evaluate: true,
hoist_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
A = 0;
var o = !0 || null;
for (var k in o);
console.log(k);
}
expect: {
!(A = 0);
for (var k in true);
console.log(k);
}
expect_stdout: "undefined"
}
issue_4517: {
options = {
collapse_vars: true,
hoist_vars: true,
join_vars: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(function() {
var a = 2;
A = a;
var b = typeof !1;
return A + b;
}());
}
expect: {
console.log(function() {
var a = 2;
A = a;
return A + typeof !1;
}());
}
expect_stdout: "2boolean"
}
issue_4736: {
options = {
collapse_vars: true,
evaluate: true,
hoist_vars: true,
merge_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a;
function f() {
(function g() {
var b = (a = 0, 1 << 30);
var c = (a = 0, console.log(b));
var d = c;
})(f);
}
f();
}
expect: {
(function() {
(function() {
0,
console.log(1073741824);
})();
})();
}
expect_stdout: "1073741824"
}

View File

@@ -588,7 +588,6 @@ issue_3197_1: {
ie8: false,
}
input: {
var window = {};
!function() {
function Foo() {
console.log(this instanceof Foo);
@@ -598,7 +597,6 @@ issue_3197_1: {
new window.Foo();
}
expect: {
var window = {};
window.Foo = function o() {
console.log(this instanceof o);
};
@@ -619,7 +617,6 @@ issue_3197_1_ie8: {
ie8: true,
}
input: {
var window = {};
!function() {
function Foo() {
console.log(this instanceof Foo);
@@ -629,7 +626,6 @@ issue_3197_1_ie8: {
new window.Foo();
}
expect: {
var window = {};
window.Foo = function Foo() {
console.log(this instanceof Foo);
};
@@ -2819,3 +2815,133 @@ direct_inline_catch_redefined: {
}
expect_stdout: true
}
issue_4186: {
options = {
dead_code: true,
evaluate: true,
ie8: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
ie8: true,
toplevel: true,
}
input: {
function f() {
(function NaN() {
var a = 1;
while (a--)
try {} finally {
console.log(0/0);
var b;
}
})(f);
}
f();
NaN;
}
expect: {
(function() {
(function NaN() {
var n = 1;
while (n--)
console.log(0/0);
})();
})();
NaN;
}
expect_stdout: "NaN"
}
issue_4235: {
options = {
ie8: true,
unused: true,
}
input: {
try {} catch (e) {}
console.log(function e() {
var e = 0;
}());
}
expect: {
try {} catch (e) {}
console.log(function e() {}());
}
expect_stdout: "undefined"
}
issue_4250: {
options = {
ie8: true,
loops: true,
unused: true,
}
input: {
console.log(function f() {
(function() {
for (f in "f");
})();
return f;
var f;
}());
}
expect: {
console.log(function f() {
(function() {
for (f in "f");
})();
return f;
var f;
}());
}
expect_stdout: "0"
}
issue_4568: {
options = {
ie8: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(typeof f, function(a) {
return a.length;
}([ function f() {} ]));
}
expect: {
console.log(typeof f, function(a) {
return a.length;
}([ function f() {} ]));
}
expect_stdout: "undefined 1"
}
issue_4729: {
options = {
ie8: true,
pure_getters: true,
toplevel: true,
unused: true,
}
input: {
try {
f;
} catch (e) {
var a = a && a[function f() {}];
console.log("PASS");
}
}
expect: {
try {
f;
} catch (e) {
(function f() {});
console.log("PASS");
}
}
expect_stdout: "PASS"
}

202
test/compress/imports.js Normal file
View File

@@ -0,0 +1,202 @@
nought: {
input: {
import "foo";
}
expect_exact: 'import"foo";'
}
default_only: {
input: {
import foo from "bar";
}
expect_exact: 'import foo from"bar";'
}
all_only: {
input: {
import * as foo from "bar";
}
expect_exact: 'import*as foo from"bar";'
}
keys_only: {
input: {
import { as as foo, bar, delete as baz } from "moo";
}
expect_exact: 'import{as as foo,bar as bar,delete as baz}from"moo";'
}
default_all: {
input: {
import foo, * as bar from "baz";
}
expect_exact: 'import foo,*as bar from"baz";'
}
default_keys: {
input: {
import foo, { bar } from "baz";
}
expect_exact: 'import foo,{bar as bar}from"baz";'
}
dynamic: {
input: {
(async a => await import(a))("foo").then(bar);
}
expect_exact: '(async a=>await import(a))("foo").then(bar);'
}
dynamic_nought: {
input: {
import(foo);
}
expect_exact: "import(foo);"
}
import_meta: {
input: {
console.log(import.meta, import.meta.url);
}
expect_exact: "console.log(import.meta,import.meta.url);"
}
same_quotes: {
beautify = {
beautify: true,
quote_style: 3,
}
input: {
import 'foo';
import "bar";
}
expect_exact: [
"import 'foo';",
"",
'import "bar";',
]
}
drop_unused: {
options = {
imports: true,
toplevel: true,
unused: true,
}
input: {
import a, * as b from "foo";
import { c, bar as d } from "baz";
console.log(c);
}
expect: {
import "foo";
import { c as c } from "baz";
console.log(c);
}
}
mangle: {
rename = false
mangle = {
toplevel: true,
}
input: {
import foo, { bar } from "baz";
consoe.log(moo);
import * as moo from "moz";
}
expect: {
import o, { bar as m } from "baz";
consoe.log(r);
import * as r from "moz";
}
}
rename_mangle: {
rename = true
mangle = {
toplevel: true,
}
input: {
import foo, { bar } from "baz";
consoe.log(moo);
import * as moo from "moz";
}
expect: {
import o, { bar as m } from "baz";
consoe.log(r);
import * as r from "moz";
}
}
keep_ref: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
import foo from "bar";
foo();
}
expect: {
import foo from "bar";
foo();
}
}
forbid_merge: {
options = {
merge_vars: true,
toplevel: true,
}
input: {
import A from "foo";
export default class extends A {}
var f = () => () => {};
f();
f();
}
expect: {
import A from "foo";
export default class extends A {}
var f = () => () => {};
f();
f();
}
}
issue_4708_1: {
options = {
imports: true,
toplevel: true,
unused: true,
}
input: {
var a;
import a from "foo";
}
expect: {
var a;
import a from "foo";
}
}
issue_4708_2: {
options = {
imports: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a;
console.log(a);
import a from "foo";
}
expect: {
var a;
console.log(a);
import a from "foo";
}
}

View File

@@ -39,7 +39,7 @@ non_hoisted_function_after_return: {
"WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:11,21]"
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:11,21]",
]
}
@@ -84,19 +84,16 @@ non_hoisted_function_after_return_2a: {
}
}
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:4,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:4,16]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:4,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]",
"INFO: pass 0: last_count: Infinity, count: 36",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
"INFO: pass 0: last_count: Infinity, count: 35",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
"INFO: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
"INFO: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
"INFO: pass 1: last_count: 36, count: 18",
"INFO: pass 1: last_count: 35, count: 18",
]
}
@@ -138,10 +135,7 @@ non_hoisted_function_after_return_2b: {
}
}
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:6,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:6,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,12]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:8,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
]
}
@@ -242,19 +236,16 @@ non_hoisted_function_after_return_2a_strict: {
}
expect_stdout: "5 6"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:5,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:5,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,16]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:5,16]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:8,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:5,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:12,21]",
"INFO: pass 0: last_count: Infinity, count: 47",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:10,12]",
"INFO: pass 0: last_count: Infinity, count: 46",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
"INFO: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
"INFO: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
"INFO: pass 1: last_count: 47, count: 29",
"INFO: pass 1: last_count: 46, count: 29",
]
}
@@ -301,10 +292,7 @@ non_hoisted_function_after_return_2b_strict: {
}
expect_stdout: "5 6"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
]
}

View File

@@ -151,15 +151,18 @@ Infinity_not_in_with_scope: {
unused: true,
}
input: {
var o = { Infinity: 'oInfinity' };
var o = { Infinity: "FAIL" };
var vInfinity = "Infinity";
vInfinity = Infinity;
console.log(vInfinity);
}
expect: {
var o = { Infinity: 'oInfinity' }
var vInfinity = "Infinity"
vInfinity = 1/0
var o = { Infinity: "FAIL" };
var vInfinity = "Infinity";
vInfinity = 1/0;
console.log(vInfinity);
}
expect_stdout: "Infinity"
}
Infinity_in_with_scope: {
@@ -167,15 +170,18 @@ Infinity_in_with_scope: {
unused: true,
}
input: {
var o = { Infinity: 'oInfinity' };
var o = { Infinity: "PASS" };
var vInfinity = "Infinity";
with (o) { vInfinity = Infinity; }
console.log(vInfinity);
}
expect: {
var o = { Infinity: 'oInfinity' }
var vInfinity = "Infinity"
with (o) vInfinity = Infinity
var o = { Infinity: "PASS" };
var vInfinity = "Infinity";
with (o) vInfinity = Infinity;
console.log(vInfinity);
}
expect_stdout: "PASS"
}
assorted_Infinity_NaN_undefined_in_with_scope: {

View File

@@ -2,61 +2,77 @@ keep_name_of_getter: {
options = {
unused: true,
}
input: { a = { get foo () {} } }
expect: { a = { get foo () {} } }
input: {
a = {
get foo() {},
};
}
expect: {
a = {
get foo() {},
};
}
}
keep_name_of_setter: {
options = {
unused: true,
}
input: { a = { set foo () {} } }
expect: { a = { set foo () {} } }
input: {
a = {
set foo(v) {},
};
}
expect: {
a = {
set foo(v) {},
};
}
}
setter_with_operator_keys: {
input: {
var tokenCodes = {
get instanceof(){
var tokenCodes = {
get instanceof() {
return test0;
},
set instanceof(value){
set instanceof(value) {
test0 = value;
},
set typeof(value){
set typeof(value) {
test1 = value;
},
get typeof(){
get typeof() {
return test1;
},
set else(value){
set else(value) {
test2 = value;
},
get else(){
get else() {
return test2;
}
},
};
}
expect: {
var tokenCodes = {
get instanceof(){
var tokenCodes = {
get instanceof() {
return test0;
},
set instanceof(value){
set instanceof(value) {
test0 = value;
},
set typeof(value){
set typeof(value) {
test1 = value;
},
get typeof(){
get typeof() {
return test1;
},
set else(value){
set else(value) {
test2 = value;
},
get else(){
get else() {
return test2;
}
},
};
}
}

View File

@@ -17,7 +17,7 @@ issue_269_1: {
expect: {
var x = {};
console.log(
x + "", +x, !!x,
"" + x, +("" + x), !!x,
"", 0, false
);
}

View File

@@ -463,15 +463,19 @@ drop_fargs: {
var a = 1;
!function(a_1) {
a++;
}(a++ + (a && a.var));
}(a++ + (a && console.log(a)));
console.log(a);
}
expect: {
var a = 1;
++a && a.var, a++;
++a && console.log(a),
a++;
console.log(a);
}
expect_stdout: "3"
expect_stdout: [
"2",
"3",
]
}
keep_fargs: {
@@ -486,13 +490,17 @@ keep_fargs: {
var a = 1;
!function(a_1) {
a++;
}(a++ + (a && a.var));
}(a++ + (a && console.log(a)));
console.log(a);
}
expect: {
var a = 1;
++a && a.var, a++;
++a && console.log(a),
a++;
console.log(a);
}
expect_stdout: "3"
expect_stdout: [
"2",
"3",
]
}

View File

@@ -63,42 +63,81 @@ eval_unused: {
unused: true,
}
input: {
function f1(a, eval, c, d, e) {
return a('c') + eval;
}
function f2(a, b, c, d, e) {
return a + eval('c');
}
function f3(a, eval, c, d, e) {
return a + eval('c');
function o(k) {
return { c: 14 }[k];
}
console.log(function f1(a, eval, c, d, e) {
return a("c") + eval;
}(o, 28, true));
console.log(function f2(a, b, c, d, e) {
return a + eval("c");
}(14, true, 28));
console.log(function f3(a, eval, c, d, e) {
return a + eval("c");
}(28, o, true));
}
expect: {
function f1(a, eval) {
return a('c') + eval;
}
function f2(a, b, c, d, e) {
return a + eval('c');
}
function f3(a, eval, c, d, e) {
return a + eval('c');
function o(k) {
return { c: 14 }[k];
}
console.log(function(a, eval) {
return a("c") + eval;
}(o, 28));
console.log(function f2(a, b, c, d, e) {
return a + eval("c");
}(14, true, 28));
console.log(function f3(a, eval, c, d, e) {
return a + eval("c");
}(28, o, true));
}
expect_stdout: [
"42",
"42",
"42",
]
}
eval_mangle: {
mangle = {
};
input: {
function f1(a, eval, c, d, e) {
return a('c') + eval;
}
function f2(a, b, c, d, e) {
return a + eval('c');
}
function f3(a, eval, c, d, e) {
return a + eval('c');
}
mangle = {}
beautify = {
beautify: true,
}
expect_exact: 'function f1(n,c,e,a,f){return n("c")+c}function f2(a,b,c,d,e){return a+eval("c")}function f3(a,eval,c,d,e){return a+eval("c")}'
input: {
function o(k) {
return { cc: 14 }[k + "c"];
}
console.log(function f1(a, eval, c, d, e) {
return a("c") + eval;
}(o, 28, true));
console.log(function f2(a, b, c, d, e) {
return a + eval("c");
}(14, true, 28));
console.log(function f3(a, eval, c, d, e) {
return a + eval("c");
}(28, o, true));
}
expect_exact: [
"function o(o) {",
" return {",
" cc: 14",
' }[o + "c"];',
"}",
"",
"console.log(function o(c, e, n, r, t) {",
' return c("c") + e;',
"}(o, 28, true));",
"",
"console.log(function f2(a, b, c, d, e) {",
' return a + eval("c");',
"}(14, true, 28));",
"",
"console.log(function f3(a, eval, c, d, e) {",
' return a + eval("c");',
"}(28, o, true));",
]
expect_stdout: [
"42",
"42",
"42",
]
}

View File

@@ -790,7 +790,7 @@ issue_3795: {
dead_code: true,
evaluate: true,
join_vars: true,
keep_fargs: "strict",
keep_fargs: false,
loops: true,
passes: 2,
reduce_vars: true,
@@ -1055,3 +1055,75 @@ issue_3916: {
}
expect_stdout: "object PASS true PASS"
}
assign_var: {
options = {
join_vars: true,
}
input: {
b = "foo";
var a = [ , "bar" ];
console.log(b);
for (var b in a)
console.log(b, a[b]);
}
expect: {
var b = "foo", a = [ , "bar" ], b;
console.log(b);
for (b in a)
console.log(b, a[b]);
}
expect_stdout: [
"foo",
"1 bar",
]
}
assign_for_var: {
options = {
join_vars: true,
}
input: {
i = "foo",
a = new Array(i, "bar");
for (var i = 2; --i >= 0;) {
console.log(a[i]);
for (var a in i);
}
}
expect: {
for (var i = "foo", a = new Array(i, "bar"), i = 2; --i >= 0;) {
console.log(a[i]);
for (var a in i);
}
}
expect_stdout: [
"bar",
"foo",
]
}
assign_sequence_var: {
options = {
join_vars: true,
}
input: {
var a = 0, b = 1;
console.log(a),
a++,
b = 2;
var c = 3;
console.log(a, b, c);
}
expect: {
var a = 0, b = 1;
console.log(a),
a++;
var b = 2, c = 3;
console.log(a, b, c);
}
expect_stdout: [
"0",
"1 2 3",
]
}

View File

@@ -18,43 +18,6 @@ keep_fargs_false: {
function j(e) {}
console.log(h(), i().length, j.length);
}
expect: {
console.log(function f() {
return f.length;
}(), function g() {
return g;
}().length);
function h() {
return h.length;
}
function i() {
return i;
}
function j() {}
console.log(h(), i().length, j.length);
}
}
keep_fargs_strict: {
options = {
keep_fargs: "strict",
unused: true,
}
input: {
console.log(function f(a) {
return f.length;
}(), function g(b) {
return g;
}().length);
function h(c) {
return h.length;
}
function i(d) {
return i;
}
function j(e) {}
console.log(h(), i().length, j.length);
}
expect: {
console.log(function f(a) {
return f.length;
@@ -117,61 +80,11 @@ keep_fargs_true: {
]
}
replace_index: {
options = {
arguments: true,
evaluate: true,
keep_fargs: "strict",
properties: true,
}
input: {
var arguments = [];
console.log(arguments[0]);
(function() {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(arguments) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function() {
var arguments;
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
}
expect: {
var arguments = [];
console.log(arguments[0]);
(function(argument_0, argument_1) {
console.log(argument_1, argument_1, arguments.foo);
})("bar", 42);
(function(a, b) {
console.log(b, b, arguments.foo);
})("bar", 42);
(function(arguments) {
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
(function() {
var arguments;
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
}
expect_stdout: [
"undefined",
"42 42 undefined",
"42 42 undefined",
"a a undefined",
"42 42 undefined",
]
}
replace_index_strict: {
options = {
arguments: true,
evaluate: true,
keep_fargs: "strict",
keep_fargs: false,
properties: true,
reduce_vars: true,
}
@@ -202,7 +115,7 @@ replace_index_strict: {
issue_1858: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
pure_getters: true,
unused: true,
}
@@ -224,7 +137,7 @@ issue_1858: {
issue_2187_2: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -245,7 +158,7 @@ issue_2187_2: {
issue_2203_2: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -280,7 +193,7 @@ issue_2203_2: {
issue_2298: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
@@ -323,7 +236,7 @@ issue_2298: {
issue_2319_1: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -346,7 +259,7 @@ issue_2319_1: {
issue_2319_2: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -371,7 +284,7 @@ issue_2319_2: {
issue_2319_3: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -396,7 +309,7 @@ issue_2319_3: {
issue_2425_1: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -419,7 +332,7 @@ issue_2425_1: {
issue_2425_2: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -442,7 +355,7 @@ issue_2425_2: {
issue_2425_3: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -465,7 +378,7 @@ issue_2425_3: {
issue_2436_13: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
passes: 2,
reduce_vars: true,
unused: true,
@@ -499,7 +412,7 @@ issue_2436_13: {
issue_2506: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
passes: 2,
reduce_vars: true,
unused: true,
@@ -538,7 +451,7 @@ issue_2506: {
issue_2226_1: {
options = {
keep_fargs: "strict",
keep_fargs: false,
side_effects: true,
unused: true,
}
@@ -585,7 +498,7 @@ issue_2226_1: {
issue_2226_2: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
sequences: true,
side_effects: true,
unused: true,
@@ -607,7 +520,7 @@ issue_2226_2: {
issue_2226_3: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
side_effects: true,
unused: true,
}
@@ -627,7 +540,7 @@ issue_2226_3: {
issue_3192: {
options = {
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -657,7 +570,7 @@ issue_3192: {
if_increment: {
options = {
evaluate: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
unused: true,
}
@@ -679,7 +592,7 @@ if_increment: {
try_increment: {
options = {
evaluate: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
unused: true,
}
@@ -703,7 +616,7 @@ try_increment: {
issue_2630_3: {
options = {
inline: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
unused: true,
}
@@ -740,7 +653,7 @@ issue_2630_3: {
issue_3364: {
options = {
functions: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -805,7 +718,7 @@ issue_3364: {
defun_label: {
options = {
keep_fargs: "strict",
keep_fargs: false,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
@@ -837,7 +750,7 @@ defun_label: {
iife_func_side_effects: {
options = {
keep_fargs: "strict",
keep_fargs: false,
reduce_funcs: true,
reduce_vars: true,
unused: true,
@@ -889,7 +802,7 @@ iife_func_side_effects: {
issue_1595_1: {
options = {
evaluate: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_funcs: true,
reduce_vars: true,
unused: true,
@@ -909,7 +822,7 @@ issue_1595_1: {
issue_1595_2: {
options = {
evaluate: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_funcs: true,
reduce_vars: true,
unused: true,
@@ -929,7 +842,7 @@ issue_1595_2: {
issue_1595_3: {
options = {
evaluate: true,
keep_fargs: "strict",
keep_fargs: false,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
@@ -950,7 +863,7 @@ issue_1595_3: {
issue_1595_4: {
options = {
evaluate: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_funcs: true,
reduce_vars: true,
unused: true,
@@ -972,7 +885,7 @@ issue_1595_4: {
duplicate_lambda_defun_name_1: {
options = {
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
}
input: {
@@ -992,7 +905,7 @@ duplicate_lambda_defun_name_1: {
duplicate_lambda_defun_name_2: {
options = {
keep_fargs: "strict",
keep_fargs: false,
passes: 2,
reduce_vars: true,
unused: true,
@@ -1013,7 +926,7 @@ duplicate_lambda_defun_name_2: {
function_name_mangle: {
options = {
keep_fargs: "strict",
keep_fargs: false,
keep_fnames: true,
reduce_vars: true,
unused: true,
@@ -1031,7 +944,7 @@ function_name_mangle: {
function_name_mangle_ie8: {
options = {
keep_fargs: "strict",
keep_fargs: false,
keep_fnames: true,
reduce_vars: true,
unused: true,
@@ -1052,7 +965,7 @@ function_name_mangle_ie8: {
issue_3420_1: {
options = {
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -1075,7 +988,7 @@ issue_3420_1: {
issue_3420_2: {
options = {
inline: true,
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -1096,7 +1009,7 @@ issue_3420_2: {
issue_3420_3: {
options = {
inline: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
unused: true,
}
@@ -1118,7 +1031,7 @@ issue_3420_3: {
issue_3423_1: {
options = {
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -1138,7 +1051,7 @@ issue_3423_1: {
issue_3423_2: {
options = {
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -1165,7 +1078,7 @@ collapse_vars_repeated: {
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: "strict",
keep_fargs: false,
loops: true,
properties: true,
reduce_funcs: true,
@@ -1212,7 +1125,7 @@ collapse_vars_repeated: {
chained_3: {
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -1236,7 +1149,7 @@ replace_all_var_scope: {
rename = true
options = {
collapse_vars: true,
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
mangle = {}
@@ -1265,7 +1178,7 @@ replace_all_var_scope: {
issue_1583: {
options = {
keep_fargs: "strict",
keep_fargs: false,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
@@ -1302,7 +1215,7 @@ issues_3267_1: {
dead_code: true,
evaluate: true,
inline: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -1331,7 +1244,7 @@ issues_3267_1: {
trailing_argument_side_effects: {
options = {
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -1355,7 +1268,7 @@ trailing_argument_side_effects: {
recursive_iife_1: {
options = {
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
unused: true,
}
@@ -1374,7 +1287,7 @@ recursive_iife_1: {
recursive_iife_2: {
options = {
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
unused: true,
}
@@ -1452,3 +1365,37 @@ issue_3619: {
}
expect_stdout: "PASS"
}
issue_4353_1: {
options = {
keep_fargs: false,
reduce_vars: true,
unused: true,
}
input: {
console.log(function f(a) {}.length);
}
expect: {
console.log(function(a) {}.length);
}
expect_stdout: "1"
}
issue_4353_2: {
options = {
keep_fargs: false,
reduce_vars: true,
unused: true,
}
input: {
(function f(a) {
while (console.log("PASS"));
})();
}
expect: {
(function() {
while (console.log("PASS"));
})();
}
expect_stdout: "PASS"
}

View File

@@ -207,3 +207,123 @@ labels_10: {
}
}
}
issue_4466_1: {
mangle = {
v8: false,
}
input: {
A: if (console.log("PASS"))
B:;
else
C:;
}
expect: {
e: if (console.log("PASS"))
l:;
else
l:;
}
expect_stdout: "PASS"
node_version: ">=12"
}
issue_4466_1_v8: {
mangle = {
v8: true,
}
input: {
A: if (console.log("PASS"))
B:;
else
C:;
}
expect: {
e: if (console.log("PASS"))
l:;
else
o:;
}
expect_stdout: "PASS"
node_version: ">=12"
}
issue_4466_2: {
mangle = {
toplevel: false,
v8: false,
}
input: {
if (console.log("PASS"))
A:;
else
B:;
}
expect: {
if (console.log("PASS"))
e:;
else
e:;
}
expect_stdout: "PASS"
}
issue_4466_2_v8: {
mangle = {
toplevel: false,
v8: true,
}
input: {
if (console.log("PASS"))
A:;
else
B:;
}
expect: {
if (console.log("PASS"))
e:;
else
l:;
}
expect_stdout: "PASS"
}
issue_4466_2_toplevel: {
mangle = {
toplevel: true,
v8: false,
}
input: {
if (console.log("PASS"))
A:;
else
B:;
}
expect: {
if (console.log("PASS"))
e:;
else
e:;
}
expect_stdout: "PASS"
}
issue_4466_2_toplevel_v8: {
mangle = {
toplevel: true,
v8: true,
}
input: {
if (console.log("PASS"))
A:;
else
B:;
}
expect: {
if (console.log("PASS"))
e:;
else
e:;
}
expect_stdout: "PASS"
}

1428
test/compress/let.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -201,7 +201,7 @@ evaluate: {
}
}
issue_1532: {
issue_1532_1: {
options = {
evaluate: true,
loops: true,
@@ -210,18 +210,56 @@ issue_1532: {
function f(x, y) {
do {
if (x) break;
foo();
console.log(y);
} while (false);
}
f(null, "PASS");
f(42, "FAIL");
}
expect: {
function f(x, y) {
for (; !x && (console.log(y), false););
}
f(null, "PASS");
f(42, "FAIL");
}
expect_stdout: "PASS"
}
issue_1532_2: {
options = {
evaluate: true,
loops: true,
}
input: {
function f(x, y) {
do {
if (x) {
console.log(x);
break;
}
console.log(y);
} while (false);
}
f(null, "PASS");
f(42, "FAIL");
}
expect: {
function f(x, y) {
do {
if (x) break;
foo();
} while (false);
if (x) {
console.log(x);
break;
}
} while (console.log(y), false);
}
f(null, "PASS");
f(42, "FAIL");
}
expect_stdout: [
"PASS",
"42",
]
}
issue_186: {
@@ -463,14 +501,14 @@ do_switch: {
}
}
in_parenthesis_1: {
in_parentheses_1: {
input: {
for (("foo" in {});0;);
}
expect_exact: 'for(("foo"in{});0;);'
}
in_parenthesis_2: {
in_parentheses_2: {
input: {
for ((function(){ "foo" in {}; });0;);
}
@@ -509,8 +547,8 @@ dead_code_condition: {
console.log(a);
}
expect: {
var c;
var a = 0, b = 5;
var c;
a += 1, 0,
console.log(a);
}
@@ -790,6 +828,21 @@ empty_for_in_prop_init: {
]
}
for_of: {
input: {
var async = [ "PASS", 42 ];
async.p = "FAIL";
for (async of (null, async))
console.log(async);
}
expect_exact: 'var async=["PASS",42];async.p="FAIL";for(async of(null,async))console.log(async);'
expect_stdout: [
"PASS",
"42",
]
node_version: ">=0.12"
}
issue_3631_1: {
options = {
dead_code: true,
@@ -988,7 +1041,7 @@ issue_4075: {
issue_4082: {
options = {
keep_fargs: "strict",
keep_fargs: false,
loops: true,
unused: true,
}
@@ -1012,7 +1065,7 @@ issue_4082: {
issue_4084: {
options = {
keep_fargs: "strict",
keep_fargs: false,
loops: true,
reduce_vars: true,
unused: true,
@@ -1088,3 +1141,187 @@ issue_4091_2: {
}
expect_stdout: "undefined"
}
issue_4182_1: {
options = {
loops: true,
}
input: {
(function() {
do {
try {
return;
} finally {
continue;
}
console.log("FAIL");
} while (0);
console.log("PASS");
})();
}
expect: {
(function() {
do {
try {
return;
} finally {
continue;
}
console.log("FAIL");
} while (0);
console.log("PASS");
})();
}
expect_stdout: "PASS"
}
issue_4182_2: {
options = {
loops: true,
}
input: {
(function() {
L: do {
do {
try {
return;
} finally {
continue L;
}
console.log("FAIL");
} while (0);
console.log("FAIL");
} while (0);
console.log("PASS");
})();
}
expect: {
(function() {
L: do {
do {
try {
return;
} finally {
continue L;
}
} while (console.log("FAIL"), 0);
console.log("FAIL");
} while (0);
console.log("PASS");
})();
}
expect_stdout: "PASS"
}
do_continue: {
options = {
loops: true,
}
input: {
try {
do {
continue;
} while ([ A ]);
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
do {
continue;
} while ([ A ]);
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
}
issue_4240: {
options = {
loops: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function(a) {
function f() {
var o = { PASS: 42 };
for (a in o);
}
(function() {
if (f());
})();
console.log(a);
})();
}
expect: {
(function(a) {
(function() {
if (function() {
for (a in { PASS: 42 });
}());
})();
console.log(a);
})();
}
expect_stdout: "PASS"
}
issue_4355: {
options = {
dead_code: true,
evaluate: true,
loops: true,
passes: 2,
side_effects: true,
unused: true,
}
input: {
while (function() {
var a;
for (a in console.log("PASS"))
var b = 0;
}())
var c;
}
expect: {
(function() {
console.log("PASS");
})();
var c;
}
expect_stdout: "PASS"
}
issue_4564: {
options = {
loops: true,
unused: true,
}
input: {
try {
throw null;
} catch (a) {
var a;
(function() {
for (a in "foo");
})();
console.log(a);
}
}
expect: {
try {
throw null;
} catch (a) {
var a;
(function() {
for (a in "foo");
})();
console.log(a);
}
}
expect_stdout: "2"
}

View File

@@ -327,7 +327,7 @@ issue_4103: {
issue_4107: {
options = {
keep_fargs: "strict",
keep_fargs: false,
merge_vars: true,
reduce_vars: true,
unused: true,
@@ -466,7 +466,7 @@ issue_4112: {
var o = e;
for (e in o);
var a = function() {};
console.log;
console.log(typeof a);
return a;
}
}());
@@ -479,12 +479,15 @@ issue_4112: {
var a = e;
for (e in a);
a = function() {};
console.log;
console.log(typeof a);
return a;
}
}());
}
expect_stdout: "function"
expect_stdout: [
"function",
"function",
]
}
issue_4115: {
@@ -2617,9 +2620,9 @@ issue_4126_1: {
try {
console.log("PASS");
} catch (e) {
var b = a;
var c = a;
} finally {
var c = b;
var c = c;
}
console.log(c);
}
@@ -3008,3 +3011,293 @@ issue_4168_use_strict: {
}
expect_stdout: "PASS true 42"
}
issue_4237_1: {
options = {
merge_vars: true,
}
input: {
console.log(function(a) {
do {
var b = a++;
if (b)
return "FAIL";
continue;
var c = 42;
} while ("undefined" != typeof c);
return "PASS";
}(0));
}
expect: {
console.log(function(a) {
do {
var b = a++;
if (b)
return "FAIL";
continue;
var c = 42;
} while ("undefined" != typeof c);
return "PASS";
}(0));
}
expect_stdout: "PASS"
}
issue_4237_2: {
options = {
dead_code: true,
evaluate: true,
loops: true,
merge_vars: true,
switches: true,
}
input: {
console.log(function(a) {
do {
switch (0) {
case 0:
var b = a++;
default:
while (b)
return "FAIL";
}
try {
var c = 0;
} finally {
continue;
}
var d = 0;
} while ("undefined" != typeof d);
return "PASS";
}(0));
}
expect: {
console.log(function(a) {
do {
switch (0) {
case 0:
var b = a++;
if (b)
return "FAIL";
}
try {
var c = 0;
} finally {
continue;
}
var d = 0;
} while ("undefined" != typeof d);
return "PASS";
}(0));
}
expect_stdout: "PASS"
}
issue_4253: {
options = {
merge_vars: true,
toplevel: true,
}
input: {
switch (0) {
default:
var a = "FAIL";
a = a && a;
try {
break;
} catch (e) {}
var b = 42;
}
console.log(b);
}
expect: {
switch (0) {
default:
var a = "FAIL";
a = a && a;
try {
break;
} catch (e) {}
var b = 42;
}
console.log(b);
}
expect_stdout: "undefined"
}
issue_4255: {
options = {
dead_code: true,
loops: true,
merge_vars: true,
toplevel: true,
}
input: {
L: for (var a = 2; --a;)
for (var b = 0; console.log(b); --b)
break L;
}
expect: {
L: for (var a = 2; --a;) {
var b = 0;
if (console.log(b))
break L;
}
}
expect_stdout: "0"
}
issue_4257: {
options = {
merge_vars: true,
toplevel: true,
}
input: {
var a = 0;
for (var i = 0; i < 2; i++)
switch (--a) {
case 0:
var b = 0;
break;
case 0:
default:
var c = 1 + (0 | (b && A));
console.log(c);
}
}
expect: {
var a = 0;
for (var i = 0; i < 2; i++)
switch (--a) {
case 0:
var b = 0;
break;
case 0:
default:
var c = 1 + (0 | (b && A));
console.log(c);
}
}
expect_stdout: [
"1",
"1",
]
}
issue_4628: {
options = {
merge_vars: true,
}
input: {
(function() {
try {
console;
} finally {
var b = a;
}
for (var a in "foo");
console.log(b);
})();
}
expect: {
(function() {
try {
console;
} finally {
var b = a;
}
for (var a in "foo");
console.log(b);
})();
}
expect_stdout: "undefined"
}
issue_4653: {
options = {
evaluate: true,
merge_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 1, b;
function f(c, d) {
c || console.log(d);
}
f(a++ + (b = b), b |= console.log(a));
}
expect: {
var b = 1;
(function(c, d) {
c || console.log(d);
})(+b + (b = void 0), b |= console.log(2));
}
expect_stdout: [
"2",
"0",
]
}
issue_4759: {
options = {
merge_vars: true,
toplevel: true,
}
input: {
var i = 2, a = 1, b, c, d;
while (i--) {
try {
if (1 != b) {
d = [];
null.p;
c = d;
} else {
b = 0;
a = c;
}
} catch (e) {}
b = a;
}
console.log(a);
}
expect: {
var i = 2, a = 1, b, c, d;
while (i--) {
try {
if (1 != b) {
d = [];
null.p;
c = d;
} else {
b = 0;
a = c;
}
} catch (e) {}
b = a;
}
console.log(a);
}
expect_stdout: "undefined"
}
issue_4761: {
options = {
merge_vars: true,
toplevel: true,
}
input: {
var a = "FAIL", b;
try {
!a && --a && (b = 0)[console] || console.log(b);
} catch (e) {}
}
expect: {
var a = "FAIL", b;
try {
!a && --a && (b = 0)[console] || console.log(b);
} catch (e) {}
}
expect_stdout: "undefined"
}

View File

@@ -85,7 +85,7 @@ new_with_unary_prefix: {
expect_exact: 'var bar=(+new Date).toString(32);';
}
dot_parenthesis_1: {
dot_parentheses_1: {
input: {
console.log(new (Math.random().constructor) instanceof Number);
}
@@ -93,7 +93,7 @@ dot_parenthesis_1: {
expect_stdout: "true"
}
dot_parenthesis_2: {
dot_parentheses_2: {
input: {
console.log(typeof new function(){Math.random()}.constructor);
}

130
test/compress/nullish.js Normal file
View File

@@ -0,0 +1,130 @@
parentheses: {
input: {
(console.log("foo") || console.log("bar") ?? console.log("baz")) && console.log("moo");
}
expect_exact:'((console.log("foo")||console.log("bar"))??console.log("baz"))&&console.log("moo");'
expect_stdout: [
"foo",
"bar",
"baz",
]
node_version: ">=14"
}
evaluate: {
options = {
evaluate: true,
side_effects: true,
}
input: {
void console.log("foo" ?? "bar") ?? console.log("baz");
}
expect: {
console.log("foo"),
console.log("baz");
}
expect_stdout: [
"foo",
"baz",
]
node_version: ">=14"
}
conditional_assignment_1: {
options = {
collapse_vars: true,
}
input: {
console.log(function(a, b) {
b ?? (a = "FAIL");
return a;
}("PASS", !console));
}
expect: {
console.log(function(a, b) {
b ?? (a = "FAIL");
return a;
}("PASS", !console));
}
expect_stdout: "PASS"
node_version: ">=14"
}
conditional_assignment_2: {
options = {
conditionals: true,
}
input: {
var a, b = false;
a = "PASS",
b ?? (a = "FAIL"),
console.log(a);
}
expect: {
var a, b = false;
a = "PASS",
b ?? (a = "FAIL"),
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=14"
}
conditional_assignment_3: {
options = {
conditionals: true,
join_vars: true,
}
input: {
var a, b = false;
a = "PASS",
b ?? (a = "FAIL"),
console.log(a);
}
expect: {
var a, b = false, a = "PASS";
b ?? (a = "FAIL"),
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=14"
}
conditional_assignment_4: {
options = {
side_effects: true,
}
input: {
console.log(function(a) {
!console ?? (a = "FAIL");
return a;
}("PASS"));
}
expect: {
console.log(function(a) {
!console ?? (a = "FAIL");
return a;
}("PASS"));
}
expect_stdout: "PASS"
node_version: ">=14"
}
issue_4679: {
options = {
comparisons: true,
ie8: true,
}
input: {
var a;
if (void 0 === (undefined ?? a))
console.log("PASS");
}
expect: {
var a;
if (void 0 === (undefined ?? a))
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=14"
}

View File

@@ -1,49 +1,100 @@
hex_numbers_in_parentheses_for_prototype_functions: {
parentheses_for_prototype_functions: {
beautify = {
beautify: true,
}
input: {
function f() {
(-2);
(-2).toFixed(0);
(function() {
console.log((-2));
console.log((-2).toFixed(0));
(2);
(2).toFixed(0);
console.log((2));
console.log((2).toFixed(0));
(0.2);
(0.2).toFixed(0);
console.log((0.2));
console.log((0.2).toFixed(0));
(2.34e20);
(2.34e20).toFixed(0);
console.log((2.34e20));
console.log((2.34e20).toFixed(0));
(0.00000002);
(0.00000002).toFixed(0);
console.log((0.00000002));
console.log((0.00000002).toFixed(0));
(1000000000000000128);
(1000000000000000128).toFixed(0);
console.log((1000000000000000128));
console.log((1000000000000000128).toFixed(0));
(-1000000000000000128);
(-1000000000000000128).toFixed(0);
}
console.log((-1000000000000000128));
console.log((-1000000000000000128).toFixed(0));
})();
}
expect_exact: [
"function f() {",
" -2;",
" (-2).toFixed(0);",
" 2;",
" 2..toFixed(0);",
" .2;",
" .2.toFixed(0);",
" 234e18;",
" 234e18.toFixed(0);",
" 2e-8;",
" 2e-8.toFixed(0);",
" 0xde0b6b3a7640080;",
" (0xde0b6b3a7640080).toFixed(0);",
" -0xde0b6b3a7640080;",
" (-0xde0b6b3a7640080).toFixed(0);",
"}",
"(function() {",
" console.log(-2);",
" console.log((-2).toFixed(0));",
" console.log(2);",
" console.log(2..toFixed(0));",
" console.log(.2);",
" console.log(.2.toFixed(0));",
" console.log(234e18);",
" console.log(234e18.toFixed(0));",
" console.log(2e-8);",
" console.log(2e-8.toFixed(0));",
" console.log(0xde0b6b3a7640080);",
" console.log(0xde0b6b3a7640080.toFixed(0));",
" console.log(-0xde0b6b3a7640080);",
" console.log((-0xde0b6b3a7640080).toFixed(0));",
"})();",
]
expect_stdout: true
}
parentheses_for_prototype_functions_galio: {
beautify = {
beautify: true,
galio: true,
}
input: {
(function() {
console.log((-2));
console.log((-2).toFixed(0));
console.log((2));
console.log((2).toFixed(0));
console.log((0.2));
console.log((0.2).toFixed(0));
console.log((2.34e20));
console.log((2.34e20).toFixed(0));
console.log((0.00000002));
console.log((0.00000002).toFixed(0));
console.log((1000000000000000128));
console.log((1000000000000000128).toFixed(0));
console.log((-1000000000000000128));
console.log((-1000000000000000128).toFixed(0));
})();
}
expect_exact: [
"(function() {",
" console.log(-2);",
" console.log((-2).toFixed(0));",
" console.log(2);",
" console.log(2..toFixed(0));",
" console.log(.2);",
" console.log(.2.toFixed(0));",
" console.log(234e18);",
" console.log(234e18.toFixed(0));",
" console.log(2e-8);",
" console.log(2e-8.toFixed(0));",
" console.log(0xde0b6b3a7640080);",
" console.log((0xde0b6b3a7640080).toFixed(0));",
" console.log(-0xde0b6b3a7640080);",
" console.log((-0xde0b6b3a7640080).toFixed(0));",
"})();",
]
expect_stdout: true
}
comparisons: {
@@ -287,7 +338,7 @@ evaluate_3: {
console.log(1 + Number(x) + 2);
}
expect: {
console.log(+x + 3);
console.log(+("" + x) + 3);
}
}
@@ -726,7 +777,7 @@ issue_1710: {
expect_stdout: true
}
unary_binary_parenthesis: {
unary_binary_parentheses: {
options = {
evaluate: true,
}
@@ -1335,3 +1386,75 @@ issue_4142: {
}
expect_stdout: "0"
}
issue_4542_1: {
options = {
evaluate: true,
unsafe_math: true,
}
input: {
console.log(function(a) {
return a / (1 / (a[0] = 2));
}([ 3 ]));
}
expect: {
console.log(function(a) {
return a / (1 / (a[0] = 2));
}([ 3 ]));
}
expect_stdout: "4"
}
issue_4542_2: {
options = {
evaluate: true,
unsafe_math: true,
}
input: {
console.log(function(a) {
return a / (1 / --a[0]);
}([ 3 ]));
}
expect: {
console.log(function(a) {
return a / (1 / --a[0]);
}([ 3 ]));
}
expect_stdout: "4"
}
issue_4542_3: {
options = {
evaluate: true,
unsafe_math: true,
}
input: {
console.log(function(a) {
return a / (0 / (a[0] = 0, 1));
}([ 1 ]));
}
expect: {
console.log(function(a) {
return a / (0 / (a[0] = 0, 1));
}([ 1 ]));
}
expect_stdout: "NaN"
}
issue_4542_4: {
options = {
evaluate: true,
unsafe_math: true,
}
input: {
console.log(function(a) {
return a / (1 / (a.length = 1));
}([ 2, 3 ]));
}
expect: {
console.log(function(a) {
return a / (1 / (a.length = 1));
}([ 2, 3 ]));
}
expect_stdout: "2"
}

View File

@@ -45,8 +45,8 @@ duplicate_key_strict: {
"use strict";
var o = {
a: 1,
b: 2,
a: 3,
b: 2,
};
for (var k in o)
console.log(k, o[k]);
@@ -221,3 +221,303 @@ numeric_literal: {
"8 7 8",
]
}
evaluate_computed_key: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
["foo" + "bar"]: "PASS",
}.foobar);
}
expect: {
console.log({
foobar: "PASS",
}.foobar);
}
expect_stdout: "PASS"
node_version: ">=4"
}
keep_computed_key: {
options = {
side_effects: true,
}
input: {
({
[console.log("PASS")]: 42,
});
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
shorthand_keywords: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var async = 1, get = 2, set = 3, o = {
async,
get,
set,
};
console.log(o.async, o.get, o.set);
}
expect: {
console.log(1, 2, 3);
}
expect_stdout: "1 2 3"
node_version: ">=6"
}
object_super: {
input: {
var o = {
f() {
return super.p;
},
p: "FAIL",
};
Object.setPrototypeOf(o, { p: "PASS" });
console.log(o.f());
}
expect_exact: 'var o={f(){return super.p},p:"FAIL"};Object.setPrototypeOf(o,{p:"PASS"});console.log(o.f());'
expect_stdout: "PASS"
node_version: ">=4"
}
object_super_async: {
input: {
var o = {
async f() {
return super.p;
},
p: "FAIL",
};
Object.setPrototypeOf(o, { p: "PASS" });
o.f().then(console.log);
}
expect_exact: 'var o={async f(){return super.p},p:"FAIL"};Object.setPrototypeOf(o,{p:"PASS"});o.f().then(console.log);'
expect_stdout: "PASS"
node_version: ">=8"
}
object_super_generator: {
input: {
var o = {
*f() {
yield super.p;
},
p: "FAIL",
};
Object.setPrototypeOf(o, { p: "PASS" });
console.log(o.f().next().value);
}
expect_exact: 'var o={*f(){yield super.p},p:"FAIL"};Object.setPrototypeOf(o,{p:"PASS"});console.log(o.f().next().value);'
expect_stdout: "PASS"
node_version: ">=4"
}
object_super_async_generator: {
input: {
var o = {
async *f() {
return super.p;
},
p: "FAIL",
};
Object.setPrototypeOf(o, { p: "PASS" });
o.f().next().then(function(v) {
console.log(v.value, v.done);
});
}
expect_exact: 'var o={async*f(){return super.p},p:"FAIL"};Object.setPrototypeOf(o,{p:"PASS"});o.f().next().then(function(v){console.log(v.value,v.done)});'
expect_stdout: "PASS true"
node_version: ">=10"
}
issue_4269_1: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
get 0() {
return "FAIL";
},
[0]: "PASS",
}[0]);
}
expect: {
console.log({
get 0() {
return "FAIL";
},
[0]: "PASS",
}[0]);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4269_2: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
get [0]() {
return "FAIL";
},
0: "PASS",
}[0]);
}
expect: {
console.log({
get [0]() {
return "FAIL";
},
0: "PASS",
}[0]);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4269_3: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
["foo"]: "bar",
get 42() {
return "FAIL";
},
42: "PASS",
}[42]);
}
expect: {
console.log({
foo: "bar",
get [42]() {
return "FAIL";
},
42: "PASS",
}[42]);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4269_4: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
get 42() {
return "FAIL";
},
["foo"]: "bar",
42: "PASS",
}[42]);
}
expect: {
console.log({
get 42() {
return "FAIL";
},
foo: "bar",
[42]: "PASS",
}[42]);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4269_5: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
get 42() {
return "FAIL";
},
[console]: "bar",
42: "PASS",
}[42]);
}
expect: {
console.log({
get 42() {
return "FAIL";
},
[console]: "bar",
42: "PASS",
}[42]);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4380: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
get 0() {
return "FAIL 1";
},
0: "FAIL 2",
[0]: "PASS",
}[0]);
}
expect: {
console.log({
get 0() {
return "FAIL 1";
},
[0]: ("FAIL 2", "PASS"),
}[0]);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4415: {
options = {
evaluate: true,
objects: true,
}
input: {
console.log({
["00"]: "FAIL",
}[0] || "PASS");
}
expect: {
console.log({
"00": "FAIL",
}[0] || "PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}

View File

@@ -1123,11 +1123,7 @@ new_this: {
}
}.f(42);
}
expect: {
new function(a) {
this.a = a;
}(42);
}
expect: {}
}
issue_2513: {
@@ -1382,3 +1378,25 @@ issue_3389: {
}
expect_stdout: "PASS"
}
object_super: {
options = {
properties: true,
}
input: {
({
f(a) {
return a ? console.log("PASS") : super.log("PASS");
},
}).f(console);
}
expect: {
({
f(a) {
return a ? console.log("PASS") : super.log("PASS");
},
}).f(console);
}
expect_stdout: "PASS"
node_version: ">=4"
}

View File

@@ -685,7 +685,7 @@ issue_3858: {
options = {
collapse_vars: true,
inline: true,
keep_fargs: "strict",
keep_fargs: false,
unused: true,
}
input: {
@@ -711,7 +711,7 @@ inline_pure_call_1: {
options = {
collapse_vars: true,
inline: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -733,7 +733,7 @@ inline_pure_call_2: {
options = {
collapse_vars: true,
inline: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -756,7 +756,7 @@ inline_pure_call_3: {
collapse_vars: true,
evaluate: true,
inline: true,
keep_fargs: "strict",
keep_fargs: false,
passes: 2,
reduce_vars: true,
toplevel: true,

View File

@@ -248,6 +248,35 @@ issue_2110_2: {
expect_stdout: "function"
}
issue_2110_3: {
options = {
collapse_vars: true,
pure_getters: "strict",
reduce_vars: true,
}
input: {
function g() {
return this;
}
console.log(typeof function() {
function f() {}
f.g = g;
return f.g();
}());
}
expect: {
function g() {
return this;
}
console.log(typeof function() {
function f() {}
f.g = g;
return f.g();
}());
}
expect_stdout: "function"
}
set_immutable_1: {
options = {
collapse_vars: true,
@@ -848,9 +877,8 @@ collapse_vars_1_true: {
}
expect: {
function f(a, b) {
for (;;) {
for (;;)
if (a.g() || b.p) break;
}
}
}
}
@@ -980,6 +1008,7 @@ collapse_vars_2_strict: {
collapse_rhs_true: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: true,
}
input: {
@@ -1016,6 +1045,7 @@ collapse_rhs_true: {
collapse_rhs_false: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: false,
}
input: {
@@ -1052,6 +1082,7 @@ collapse_rhs_false: {
collapse_rhs_strict: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
}
input: {
@@ -1088,6 +1119,7 @@ collapse_rhs_strict: {
collapse_rhs_setter: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
}
input: {
@@ -1188,6 +1220,104 @@ drop_arguments: {
expect_stdout: "PASS"
}
lvalues_def: {
options = {
collapse_vars: true,
pure_getters: true,
side_effects: true,
unused: true,
}
input: {
var a = 0, b = 1;
var a = b++, b = +function() {}();
a && a[a++];
console.log(a, b);
}
expect: {
var a = 0, b = 1;
a = b++, b = +void 0;
a && a++;
console.log(a, b);
}
expect_stdout: true
}
side_effects_assign: {
options = {
evaluate: true,
pure_getters: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
}
input: {
var a = typeof void (a && a.in == 1, 0);
console.log(a);
}
expect: {
var a = "undefined";
console.log(a);
}
expect_stdout: "undefined"
}
issue_2062: {
options = {
booleans: true,
collapse_vars: true,
conditionals: true,
pure_getters: true,
side_effects: true,
}
input: {
var a = 1;
if ([ a || a++ + a--, a++ + a--, a && a.var ]);
console.log(a);
}
expect: {
var a = 1;
a || (a++, a--), a++, a--;
console.log(a);
}
expect_stdout: "1"
}
issue_2878: {
options = {
collapse_vars: true,
pure_getters: true,
sequences: true,
}
input: {
var c = 0;
(function(a, b) {
function f2() {
if (a) c++;
}
b = f2();
a = 1;
b && b.b;
f2();
})();
console.log(c);
}
expect: {
var c = 0;
(function(a, b) {
function f2() {
if (a) c++;
}
b = f2(),
a = 1,
f2();
})(),
console.log(c);
}
expect_stdout: "1"
}
issue_3427: {
options = {
assignments: true,
@@ -1209,3 +1339,154 @@ issue_3427: {
expect: {}
expect_stdout: true
}
issue_3490_1: {
options = {
conditionals: true,
dead_code: true,
inline: true,
pure_getters: true,
sequences: true,
side_effects: true,
toplevel: true,
}
input: {
var b = 42, c = "FAIL";
if ({
3: function() {
var a;
return (a && a.p) < this;
}(),
}) c = "PASS";
if (b) while ("" == typeof d);
console.log(c, b);
}
expect: {
var b = 42, c = "FAIL";
if (function() {
var a;
}(), c = "PASS", b) while ("" == typeof d);
console.log(c, b);
}
expect_stdout: "PASS 42"
}
issue_4135: {
options = {
evaluate: true,
inline: true,
merge_vars: true,
pure_getters: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = 0, b = 0;
--b;
a++;
if (!a)
var c = function() {
var d = 0;
function f() {
d && d.p;
}
f();
this;
}(a++);
console.log(a, b, c);
}
expect: {
var a = 0;
0;
a++;
if (!a)
var c = void a++;
console.log(a, -1, c);
}
expect_stdout: "1 -1 undefined"
}
issue_4440: {
options = {
pure_getters: "strict",
side_effects: true,
unused: true,
}
input: {
try {
(function() {
arguments = null;
console.log(arguments.p = "FAIL");
})();
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
(function() {
arguments = null;
console.log(arguments.p = "FAIL");
})();
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
}
issue_4730_1: {
options = {
pure_getters: true,
side_effects: true,
}
input: {
var a;
console.log("PASS") + (a && a[a.p]);
}
expect: {
var a;
console.log("PASS");
}
expect_stdout: "PASS"
}
issue_4730_2: {
options = {
pure_getters: true,
side_effects: true,
}
input: {
var a;
!console.log("PASS") || a && a[a.p];
}
expect: {
var a;
console.log("PASS");
}
expect_stdout: "PASS"
}
issue_4751: {
options = {
pure_getters: true,
side_effects: true,
}
input: {
var o = {
get p() {
console.log("PASS");
},
};
o && o.p;
}
expect: {
var o = {
get p() {
console.log("PASS");
},
};
}
}

View File

@@ -1999,7 +1999,7 @@ issue_1606: {
var a, b;
function g(){};
b = 2;
x(b);
x(2);
}
}
}
@@ -2373,7 +2373,7 @@ redefine_farg_1: {
function f(a) {
return typeof a;
}
function g() {
function g(a) {
return "number";
}
function h(a, b) {
@@ -2460,6 +2460,7 @@ delay_def: {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
@@ -6928,7 +6929,7 @@ issue_3622: {
options = {
evaluate: true,
inline: true,
keep_fargs: "strict",
keep_fargs: false,
reduce_vars: true,
sequences: true,
toplevel: true,
@@ -7196,7 +7197,7 @@ issue_3894: {
issue_3922: {
options = {
evaluate: true,
keep_fargs: "strict",
keep_fargs: false,
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
@@ -7535,3 +7536,98 @@ global_assign: {
}
expect_stdout: "PASS"
}
issue_4188_1: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function() {
try {
while (A)
var a = function() {}, b = a;
} catch (a) {
console.log(function() {
return typeof a;
}(), typeof b);
}
})();
}
expect: {
(function() {
try {
while (A)
var a = function() {}, b = a;
} catch (a) {
console.log(function() {
return typeof a;
}(), typeof b);
}
})();
}
expect_stdout: "object undefined"
}
issue_4188_2: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function() {
try {
throw 42;
} catch (a) {
console.log(function() {
return typeof a;
}(), typeof b);
}
while (!console)
var a = function() {}, b = a;
})();
}
expect: {
(function() {
try {
throw 42;
} catch (a) {
console.log(function() {
return typeof a;
}(), typeof b);
}
while (!console)
var a = function() {}, b = a;
})();
}
expect_stdout: "number undefined"
}
issue_4568: {
options = {
booleans: true,
conditionals: true,
dead_code: true,
evaluate: true,
loops: true,
passes: 2,
reduce_vars: true,
sequences: true,
unused: true,
}
input: {
(function(a) {
a && console.log("FAIL");
if (1)
do {
if (!console.log("PASS")) break;
} while (1);
})(!(0 !== delete NaN));
}
expect: {
(function(a) {
for (a && console.log("FAIL"), 1; console.log("PASS"); ) 1;
})(!(0 !== delete NaN));
}
expect_stdout: "PASS"
}

786
test/compress/rests.js Normal file
View File

@@ -0,0 +1,786 @@
arrow_1: {
input: {
console.log.apply(console, ((...a) => a)("PASS", 42));
}
expect_exact: 'console.log.apply(console,((...a)=>a)("PASS",42));'
expect_stdout: "PASS 42"
node_version: ">=6"
}
arrow_2: {
input: {
console.log.apply(console, ((a, ...b) => b)("FAIL", "PASS", 42));
}
expect_exact: 'console.log.apply(console,((a,...b)=>b)("FAIL","PASS",42));'
expect_stdout: "PASS 42"
node_version: ">=6"
}
arrow_destructured_array_1: {
input: {
console.log.apply(console, (([ ...a ]) => a)("PASS"));
}
expect_exact: 'console.log.apply(console,(([...a])=>a)("PASS"));'
expect_stdout: "P A S S"
node_version: ">=6"
}
arrow_destructured_array_2: {
input: {
console.log.apply(console, (([ a, ...b ]) => b)([ "FAIL", "PASS", 42 ]));
}
expect_exact: 'console.log.apply(console,(([a,...b])=>b)(["FAIL","PASS",42]));'
expect_stdout: "PASS 42"
node_version: ">=6"
}
arrow_destructured_array_3: {
input: {
console.log((([ [ ...a ] = "FAIL" ]) => a)([ "PASS" ]).join("|"));
}
expect_exact: 'console.log((([[...a]="FAIL"])=>a)(["PASS"]).join("|"));'
expect_stdout: "P|A|S|S"
node_version: ">=6"
}
arrow_destructured_object_1: {
input: {
var f = ({ ...a }) => a, o = f({ PASS: 42 });
for (var k in o)
console.log(k, o[k]);
}
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"
}
arrow_destructured_object_2: {
input: {
var f = ({ FAIL: a, ...b }) => b, o = f({ PASS: 42, FAIL: null });
for (var k in o)
console.log(k, o[k]);
}
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"
}
arrow_destructured_object_3: {
input: {
var f = ([ { ...a } = [ "FAIL" ] ]) => a;
var o = f([ "PASS" ]);
for (var k in o)
console.log(k, o[k]);
}
expect_exact: 'var f=([{...a}=["FAIL"]])=>a;var o=f(["PASS"]);for(var k in o)console.log(k,o[k]);'
expect_stdout: [
"0 P",
"1 A",
"2 S",
"3 S",
]
node_version: ">=8"
}
funarg_1: {
input: {
console.log.apply(console, function(...a) {
return a;
}("PASS", 42));
}
expect_exact: 'console.log.apply(console,function(...a){return a}("PASS",42));'
expect_stdout: "PASS 42"
node_version: ">=6"
}
funarg_2: {
input: {
console.log.apply(console, function(a, ...b) {
return b;
}("FAIL", "PASS", 42));
}
expect_exact: 'console.log.apply(console,function(a,...b){return b}("FAIL","PASS",42));'
expect_stdout: "PASS 42"
node_version: ">=6"
}
destructured_array_1: {
input: {
var [ ...a ] = [ "PASS", 42 ];
console.log.apply(console, a);
}
expect_exact: 'var[...a]=["PASS",42];console.log.apply(console,a);'
expect_stdout: "PASS 42"
node_version: ">=6"
}
destructured_array_2: {
input: {
var [ a, ...b ] = [ "FAIL", "PASS", 42 ];
console.log.apply(console, b);
}
expect_exact: 'var[a,...b]=["FAIL","PASS",42];console.log.apply(console,b);'
expect_stdout: "PASS 42"
node_version: ">=6"
}
destructured_object_1: {
input: {
var { ...a } = [ "FAIL", "PASS", 42 ];
console.log(a[1], a[2]);
}
expect_exact: 'var{...a}=["FAIL","PASS",42];console.log(a[1],a[2]);'
expect_stdout: "PASS 42"
node_version: ">=8"
}
destructured_object_2: {
input: {
var { 0: a, ...b } = [ "FAIL", "PASS", 42 ];
console.log(b[1], b[2]);
}
expect_exact: 'var{0:a,...b}=["FAIL","PASS",42];console.log(b[1],b[2]);'
expect_stdout: "PASS 42"
node_version: ">=8"
}
drop_fargs: {
options = {
keep_fargs: false,
rests: true,
unused: true,
}
input: {
console.log(function(a, ...b) {
return b[0];
}("FAIL", "PASS"));
}
expect: {
console.log(function(b) {
return b[0];
}([ "PASS" ]));
}
expect_stdout: "PASS"
node_version: ">=6"
}
inline: {
options = {
inline: true,
toplevel: true,
}
input: {
console.log(function(a, ...[ b, c ]) {
return c + b + a;
}("SS", "A", "P"));
}
expect: {
console.log(([ a, ...[ b, c ] ] = [ "SS", "A", "P" ], c + b + a));
var a, b, c;
}
expect_stdout: "PASS"
node_version: ">=6"
}
retain_var: {
options = {
unused: true,
}
input: {
var [ ...a ] = [ "PASS" ];
console.log(a[0]);
}
expect: {
var [ ...a ] = [ "PASS" ];
console.log(a[0]);
}
expect_stdout: "PASS"
node_version: ">=6"
}
reduce_destructured_array: {
options = {
reduce_vars: true,
rests: true,
toplevel: true,
unused: true,
}
input: {
var [ ...a ] = [ "PASS" ];
console.log(a[0]);
}
expect: {
console.log([ "PASS" ][0]);
}
expect_stdout: "PASS"
node_version: ">=6"
}
reduce_destructured_object: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var { ...a } = [ "PASS" ];
console.log(a[0]);
}
expect: {
var { ...a } = [ "PASS" ];
console.log(a[0]);
}
expect_stdout: "PASS"
node_version: ">=8"
}
retain_destructured_array: {
options = {
toplevel: true,
unused: true,
}
input: {
var [ a, ...b ] = [ "FAIL", "PASS", 42 ];
console.log.apply(console, b);
}
expect: {
var [ , ...b ] = [ "FAIL", "PASS", 42 ];
console.log.apply(console, b);
}
expect_stdout: "PASS 42"
node_version: ">=6"
}
retain_destructured_object_1: {
options = {
toplevel: true,
unused: true,
}
input: {
var { 0: a, ...b } = [ "FAIL", "PASS", 42 ];
for (var k in b)
console.log(k, b[k]);
}
expect: {
var { 0: a, ...b } = [ "FAIL", "PASS", 42 ];
for (var k in b)
console.log(k, b[k]);
}
expect_stdout: [
"1 PASS",
"2 42",
]
node_version: ">=8"
}
retain_destructured_object_2: {
options = {
toplevel: true,
unused: true,
}
input: {
var { foo: [ a ], ...b } = { foo: [ "FAIL" ], bar: "PASS", baz: 42 };
for (var k in b)
console.log(k, b[k]);
}
expect: {
var { foo: [], ...b } = { foo: [ "FAIL" ], bar: "PASS", baz: 42 };
for (var k in b)
console.log(k, b[k]);
}
expect_stdout: [
"bar PASS",
"baz 42",
]
node_version: ">=8"
}
retain_funarg_destructured_array_1: {
options = {
inline: true,
keep_fargs: false,
pure_getters: "strict",
unused: true,
}
input: {
console.log((([ ...a ]) => a)([ "PASS" ])[0]);
}
expect: {
console.log((([ ...a ]) => a)([ "PASS" ])[0]);
}
expect_stdout: "PASS"
node_version: ">=6"
}
retain_funarg_destructured_array_2: {
options = {
unused: true,
}
input: {
console.log(function([ a, ...b ]) {
return b;
}("bar")[1]);
}
expect: {
console.log(function([ , ...b ]) {
return b;
}("bar")[1]);
}
expect_stdout: "r"
node_version: ">=6"
}
retain_funarg_destructured_object_1: {
options = {
inline: true,
keep_fargs: false,
pure_getters: "strict",
unused: true,
}
input: {
console.log((({ ...a }) => a)([ "PASS" ])[0]);
}
expect: {
console.log((({ ...a }) => a)([ "PASS" ])[0]);
}
expect_stdout: "PASS"
node_version: ">=8"
}
retain_funarg_destructured_object_2: {
options = {
unused: true,
}
input: {
console.log(function({ p: a, ... b }) {
return b;
}({ p: "FAIL" }).p || "PASS");
}
expect: {
console.log(function({ p: a, ... b }) {
return b;
}({ p: "FAIL" }).p || "PASS");
}
expect_stdout: "PASS"
node_version: ">=8"
}
drop_unused_call_args_1: {
options = {
rests: true,
unused: true,
}
input: {
(function(...a) {
console.log(a[0]);
})(42, console.log("PASS"));
}
expect: {
(function(a) {
console.log(a[0]);
})([ 42, console.log("PASS") ]);
}
expect_stdout: [
"PASS",
"42",
]
node_version: ">=6"
}
drop_unused_call_args_2: {
options = {
keep_fargs: false,
rests: true,
unused: true,
}
input: {
console.log(function(a, ...b) {
return b;
}(console).length);
}
expect: {
console.log(function(b) {
return b;
}((console, [])).length);
}
expect_stdout: "0"
node_version: ">=6"
}
merge_funarg: {
options = {
merge_vars: true,
}
input: {
(function(...a) {
var b = a.length;
console.log(b);
})();
}
expect: {
(function(...b) {
var b = b.length;
console.log(b);
})();
}
expect_stdout: "0"
node_version: ">=6"
}
merge_funarg_destructured_array: {
options = {
merge_vars: true,
}
input: {
(function([ ...a ]) {
var b = a.length;
console.log(b);
})([]);
}
expect: {
(function([ ...b ]) {
var b = b.length;
console.log(b);
})([]);
}
expect_stdout: "0"
node_version: ">=6"
}
merge_funarg_destructured_object: {
options = {
merge_vars: true,
}
input: {
(function({ ...a }) {
var b = a[0];
console.log(b);
})([ "PASS" ]);
}
expect: {
(function({ ...b }) {
var b = b[0];
console.log(b);
})([ "PASS" ]);
}
expect_stdout: "PASS"
node_version: ">=8"
}
keep_arguments: {
options = {
arguments: true,
keep_fargs: false,
}
input: {
(function(...[ {} ]) {
console.log(arguments[0]);
})("PASS");
}
expect: {
(function(...[ {} ]) {
console.log(arguments[0]);
})("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
drop_rest_array: {
options = {
rests: true,
}
input: {
var [ ...[ a ]] = [ "PASS" ];
console.log(a);
}
expect: {
var [ a ] = [ "PASS" ];
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
drop_rest_arrow: {
options = {
arrows: true,
keep_fargs: false,
reduce_vars: true,
rests: true,
}
input: {
console.log(((...[ a ]) => a)("PASS"));
}
expect: {
console.log((a => a)("PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
drop_rest_lambda: {
options = {
keep_fargs: false,
reduce_vars: true,
rests: true,
toplevel: true,
}
input: {
function f(...[ a ]) {
return a;
}
console.log(f("PASS"), f(42));
}
expect: {
function f(a) {
return a;
}
console.log(f("PASS"), f(42));
}
expect_stdout: "PASS 42"
node_version: ">=6"
}
issue_4525_1: {
options = {
arguments: true,
}
input: {
console.log(function(a, ...[]) {
a = "FAIL";
return arguments[0];
}("PASS"));
}
expect: {
console.log(function(a, ...[]) {
a = "FAIL";
return arguments[0];
}("PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_4525_2: {
options = {
unused: true,
}
input: {
console.log(function(a, ...[]) {
a = "FAIL";
return arguments[0];
}("PASS"));
}
expect: {
console.log(function(a, ...[]) {
a = "FAIL";
return arguments[0];
}("PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_4538: {
options = {
rests: true,
unused: true,
}
input: {
console.log(typeof function f(...a) {
return a.p, f;
}()());
}
expect: {
console.log(typeof function f(...a) {
return a.p, f;
}()());
}
expect_stdout: "function"
node_version: ">=6"
}
issue_4544_1: {
options = {
keep_fnames: true,
side_effects: true,
}
input: {
try {
(function f(...[ {} ]) {})();
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
[ ...[ {} ] ] = [];
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_4544_2: {
options = {
keep_fnames: true,
side_effects: true,
}
input: {
try {
(function f(a, ...[ {} ]) {})([]);
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
[ , ...[ {} ] ] = [ [] ];
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_4562: {
options = {
evaluate: true,
reduce_vars: true,
rests: true,
unsafe: true,
}
input: {
console.log((([ ...[ a ] ]) => a)("foo"));
}
expect: {
console.log((([ a ]) => a)("foo"));
}
expect_stdout: "f"
node_version: ">=6"
}
issue_4575: {
options = {
collapse_vars: true,
ie8: true,
reduce_vars: true,
rests: true,
unused: true,
}
input: {
(function(a) {
var b = a;
var c = function a(...d) {
console.log(d.length);
}();
})();
}
expect: {
(function(a) {
(function a(...d) {
console.log(d.length);
})();
})();
}
expect_stdout: "0"
node_version: ">=6"
}
issue_4621: {
options = {
side_effects: true,
}
input: {
(function f(a, ...{
[console.log(a)]: b,
}) {})("PASS");
}
expect: {
(function f(a, ...{
[console.log(a)]: b,
}) {})("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_4644_1: {
options = {
evaluate: true,
}
input: {
var a = "FAIL";
(function f(b, ...{
[a = "PASS"]: c,
}) {
return b;
})();
console.log(a);
}
expect: {
var a = "FAIL";
(function f(b, ...{
[a = "PASS"]: c,
}) {
return b;
})();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_4644_2: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(function(...a) {
return a[1];
}("FAIL", "PASS"), function(...b) {
return b.length;
}(), function(c, ...d) {
return d[0];
}("FAIL"));
}
expect: {
console.log("PASS", 0, function(c, ...d) {
return d[0];
}("FAIL"));
}
expect_stdout: "PASS 0 undefined"
node_version: ">=6"
}
issue_4666: {
options = {
evaluate: true,
reduce_vars: true,
rests: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var a = 0, b = 0;
var o = ((...c) => a++ + c)(b);
for (var k in o)
b++;
console.log(a, b);
}
expect: {
var a = 0, b = 0;
var o = (c => +a + c)([ b ]);
for(var k in o)
b++;
console.log(1, b);
}
expect_stdout: "1 2"
node_version: ">=6"
}

View File

@@ -13,6 +13,23 @@ console_log: {
]
}
console_log_console: {
input: {
var log = console.log;
log(console);
log(typeof console.log);
}
expect: {
var log = console.log;
log(console);
log(typeof console.log);
}
expect_stdout: [
"{ log: 'function(){}' }",
"function",
]
}
typeof_arguments: {
options = {
evaluate: true,
@@ -81,6 +98,63 @@ log_global: {
expect_stdout: "[object global]"
}
log_nested: {
options = {
unused: true,
}
input: {
var o = { p: 42 };
for (var i = 0; i < 10; i++)
o = {
p: o,
q: function foo() {},
};
console.log(o);
}
expect: {
var o = { p: 42 };
for (var i = 0; i < 10; i++)
o = {
p: o,
q: function() {},
};
console.log(o);
}
expect_stdout: true
}
timers: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var count = 0, interval = 1000, duration = 3210;
var timer = setInterval(function() {
console.log(++count);
}, interval);
setTimeout(function() {
clearInterval(timer);
}, duration);
}
expect: {
var count = 0;
var timer = setInterval(function() {
console.log(++count);
}, 1000);
setTimeout(function() {
clearInterval(timer);
}, 3210);
}
expect_stdout: [
"1",
"2",
"3",
]
node_version: ">=0.12"
}
issue_4054: {
input: {
console.log({

View File

@@ -663,12 +663,21 @@ side_effects_cascade_1: {
if (a < 0) a = 0;
b.a = a;
}
var m = {}, n = {};
f(13, m);
f("foo", n);
console.log(m.a, n.a);
}
expect: {
function f(a, b) {
(a -= 42) < 0 && (a = 0), b.a = a;
b.a = a = (a -= 42) < 0 ? 0 : a;
}
var m = {}, n = {};
f(13, m),
f("foo", n),
console.log(m.a, n.a);
}
expect_stdout: "0 NaN"
}
side_effects_cascade_2: {

View File

@@ -348,8 +348,6 @@ issue_3983_1: {
}
expect: {
var a = "PASS";
g();
function g() {}
console.log(a);
}
expect_stdout: "PASS"
@@ -416,3 +414,204 @@ issue_4008: {
"PASS",
]
}
trim_new: {
options = {
side_effects: true,
}
input: {
new function(a) {
console.log(a);
}("PASS");
}
expect: {
(function(a) {
console.log(a);
})("PASS");
}
expect_stdout: "PASS"
}
issue_4325: {
options = {
keep_fargs: false,
passes: 2,
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
(function f() {
(function(b, c) {
try {
c.p = 0;
} catch (e) {
console.log("PASS");
return b;
}
c;
})(f++);
})();
}
expect: {
(function() {
(function(c) {
try {
c.p = 0;
} catch (e) {
console.log("PASS");
return;
}
})(void 0);
})();
}
expect_stdout: "PASS"
}
issue_4366_1: {
options = {
side_effects: true,
}
input: {
({
p: 42,
get p() {},
q: console.log("PASS"),
});
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4366_2: {
options = {
side_effects: true,
}
input: {
({
set p(v) {},
q: console.log("PASS"),
p: 42,
});
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4668: {
options = {
conditionals: true,
keep_fargs: false,
keep_fnames: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function f(a) {
var b, c;
function g() {
return a = 0 + a, !d || (a = 0);
}
c = g();
}
console.log(f());
var d = 0;
}
expect: {
console.log(function f() {
(function g() {
0;
})();
}());
}
expect_stdout: "undefined"
}
drop_side_effect_free_call: {
options = {
inline: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
function f(a) {
return "PA" + a;
}
f(42);
console.log(f("SS"));
}
expect: {
function f(a) {
return "PA" + a;
}
console.log(f("SS"));
}
expect_stdout: "PASS"
}
issue_4730_1: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
var a;
console.log("PASS") + (a && a[a.p]);
}
expect: {
var a;
console.log("PASS"),
a && a[a.p];
}
expect_stdout: "PASS"
}
issue_4730_2: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
var a;
!console.log("PASS") || a && a[a.p];
}
expect: {
var a;
!console.log("PASS") || a && a[a.p];
}
expect_stdout: "PASS"
}
issue_4751: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
var o = {
get p() {
console.log("PASS");
},
};
o && o.p;
}
expect: {
var o = {
get p() {
console.log("PASS");
},
};
o && o.p;
}
expect_stdout: "PASS"
}

949
test/compress/spreads.js Normal file
View File

@@ -0,0 +1,949 @@
collapse_vars_1: {
options = {
collapse_vars: true,
}
input: {
var a;
[ ...a = "PASS", "PASS"].slice();
console.log(a);
}
expect: {
var a;
[ ...a = "PASS", "PASS"].slice();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
collapse_vars_2: {
options = {
collapse_vars: true,
}
input: {
var a = "FAIL";
try {
a = "PASS";
[ ...42, "PASS"].slice();
} catch (e) {
console.log(a);
}
}
expect: {
var a = "FAIL";
try {
a = "PASS";
[ ...42, "PASS"].slice();
} catch (e) {
console.log(a);
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
collapse_vars_3: {
options = {
collapse_vars: true,
}
input: {
var a = "FAIL";
try {
[ ...(a = "PASS", 42), "PASS"].slice();
} catch (e) {
console.log(a);
}
}
expect: {
var a = "FAIL";
try {
[ ...(a = "PASS", 42), "PASS"].slice();
} catch (e) {
console.log(a);
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
collapse_vars_4: {
options = {
collapse_vars: true,
unused: true,
}
input: {
console.log(function(a) {
return a;
}(...[ "PASS", "FAIL" ]));
}
expect: {
console.log(function(a) {
return a;
}(...[ "PASS", "FAIL" ]));
}
expect_stdout: "PASS"
node_version: ">=6"
}
conditionals_farg: {
options = {
conditionals: true,
}
input: {
function log(msg) {
console.log(msg);
}
var a = 42, b = [ "PASS" ], c = [ "FAIL" ];
a ? log(...b) : log(...c);
}
expect: {
function log(msg) {
console.log(msg);
}
var a = 42, b = [ "PASS" ], c = [ "FAIL" ];
log(...a ? b : c);
}
expect_stdout: "PASS"
node_version: ">=6"
}
dont_inline: {
options = {
inline: true,
}
input: {
console.log(function(a) {
return a;
}(...[ "PASS", "FAIL" ]));
}
expect: {
console.log(function(a) {
return a;
}(...[ "PASS", "FAIL" ]));
}
expect_stdout: "PASS"
node_version: ">=6"
}
do_inline: {
options = {
inline: true,
spreads: true,
}
input: {
console.log(function(a) {
return a;
}(...[ "PASS", "FAIL" ]));
}
expect: {
console.log(("FAIL", "PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
drop_empty_call_1: {
options = {
side_effects: true,
}
input: {
try {
(function() {})(...null);
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
[ ...null ];
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
drop_empty_call_2: {
options = {
side_effects: true,
spreads: true,
}
input: {
(function() {})(...[ console.log("PASS") ]);
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
convert_hole: {
options = {
spreads: true,
}
input: {
console.log(...[ "PASS", , 42 ]);
}
expect: {
console.log("PASS", void 0, 42);
}
expect_stdout: "PASS undefined 42"
node_version: ">=6"
}
keep_property_access: {
options = {
properties: true,
side_effects: true,
}
input: {
console.log(function() {
return [ ..."foo" ][0];
}());
}
expect: {
console.log(function() {
return [ ..."foo" ][0];
}());
}
expect_stdout: "f"
node_version: ">=6"
}
keep_fargs: {
options = {
keep_fargs: false,
unused: true,
}
input: {
var a = [ "PASS" ];
(function(b, c) {
console.log(c);
})(console, ...a);
}
expect: {
var a = [ "PASS" ];
(function(b, c) {
console.log(c);
})(console, ...a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
reduce_vars_1: {
options = {
reduce_vars: true,
unused: true,
}
input: {
console.log(function(b, c) {
return c ? "PASS" : "FAIL";
}(..."foo"));
}
expect: {
console.log(function(b, c) {
return c ? "PASS" : "FAIL";
}(..."foo"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
reduce_vars_2: {
options = {
conditionals: true,
evaluate: true,
reduce_vars: true,
}
input: {
console.log(function(b, c) {
return c ? "PASS" : "FAIL";
}(..."foo"));
}
expect: {
console.log(function(b, c) {
return c ? "PASS" : "FAIL";
}(..."foo"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
convert_setter: {
options = {
objects: true,
spreads: true,
}
input: {
var o = {
...{
set PASS(v) {},
},
};
for (var k in o)
console.log(k, o[k]);
}
expect: {
var o = {
PASS: void 0,
};
for (var k in o)
console.log(k, o[k]);
}
expect_stdout: "PASS undefined"
node_version: ">=8"
}
keep_getter_1: {
options = {
side_effects: true,
}
input: {
({
...{
get p() {
console.log("PASS");
},
},
get q() {
console.log("FAIL");
},
});
}
expect: {
({
...{
get p() {
console.log("PASS");
},
},
});
}
expect_stdout: "PASS"
node_version: ">=8"
}
keep_getter_2: {
options = {
side_effects: true,
}
input: {
({
...(console.log("foo"), {
get p() {
console.log("bar");
},
}),
});
}
expect: {
({
...(console.log("foo"), {
get p() {
console.log("bar");
},
}),
});
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=8"
}
keep_getter_3: {
options = {
side_effects: true,
}
input: {
({
...function() {
return {
get p() {
console.log("PASS");
},
};
}(),
});
}
expect: {
({
...function() {
return {
get p() {
console.log("PASS");
},
};
}(),
});
}
expect_stdout: "PASS"
node_version: ">=8"
}
keep_getter_4: {
options = {
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var o = {
get p() {
console.log("PASS");
},
};
({
q: o,
...o,
});
}
expect: {
var o = {
get p() {
console.log("PASS");
},
};
({
...o,
});
}
expect_stdout: "PASS"
node_version: ">=8"
}
keep_accessor: {
options = {
objects: true,
spreads: true,
}
input: {
var o = {
...{
get p() {
console.log("GET");
return this.r;
},
set q(v) {
console.log("SET", v);
},
r: 42,
},
r: null,
};
for (var k in o)
console.log(k, o[k]);
}
expect: {
var o = {
...{
get p() {
console.log("GET");
return this.r;
},
set q(v) {
console.log("SET", v);
},
r: 42,
},
r: null,
};
for (var k in o)
console.log(k, o[k]);
}
expect_stdout: [
"GET",
"p 42",
"q undefined",
"r null",
]
node_version: ">=8"
}
object_key_order_1: {
options = {
objects: true,
spreads: true,
}
input: {
var o = {
...{},
a: 1,
b: 2,
a: 3,
};
for (var k in o)
console.log(k, o[k]);
}
expect: {
var o = {
a: (1, 3),
b: 2,
};
for (var k in o)
console.log(k, o[k]);
}
expect_stdout: [
"a 3",
"b 2",
]
node_version: ">=8 <=10"
}
object_key_order_2: {
options = {
objects: true,
spreads: true,
}
input: {
var o = {
a: 1,
...{},
b: 2,
a: 3,
};
for (var k in o)
console.log(k, o[k]);
}
expect: {
var o = {
a: (1, 3),
b: 2,
};
for (var k in o)
console.log(k, o[k]);
}
expect_stdout: [
"a 3",
"b 2",
]
node_version: ">=8"
}
object_key_order_3: {
options = {
objects: true,
spreads: true,
}
input: {
var o = {
a: 1,
b: 2,
...{},
a: 3,
};
for (var k in o)
console.log(k, o[k]);
}
expect: {
var o = {
a: (1, 3),
b: 2,
};
for (var k in o)
console.log(k, o[k]);
}
expect_stdout: [
"a 3",
"b 2",
]
node_version: ">=8"
}
object_key_order_4: {
options = {
objects: true,
spreads: true,
}
input: {
var o = {
a: 1,
b: 2,
a: 3,
...{},
};
for (var k in o)
console.log(k, o[k]);
}
expect: {
var o = {
a: (1, 3),
b: 2,
};
for (var k in o)
console.log(k, o[k]);
}
expect_stdout: [
"a 3",
"b 2",
]
node_version: ">=8"
}
object_spread_array: {
options = {
objects: true,
spreads: true,
}
input: {
var o = {
...[ "foo", "bar" ],
};
for (var k in o)
console.log(k, o[k]);
}
expect: {
var o = {
...[ "foo", "bar" ],
};
for (var k in o)
console.log(k, o[k]);
}
expect_stdout: [
"0 foo",
"1 bar",
]
node_version: ">=8"
}
object_spread_string: {
options = {
objects: true,
spreads: true,
}
input: {
var o = {
..."foo",
};
for (var k in o)
console.log(k, o[k]);
}
expect: {
var o = {
..."foo",
};
for (var k in o)
console.log(k, o[k]);
}
expect_stdout: [
"0 f",
"1 o",
"2 o",
]
node_version: ">=8"
}
unused_var_side_effects: {
options = {
unused: true,
}
input: {
(function f(a) {
var b = {
...a,
};
})({
get p() {
console.log("PASS");
},
});
}
expect: {
(function(a) {
({
...a,
});
})({
get p() {
console.log("PASS");
},
});
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_4329: {
options = {
objects: true,
spreads: true,
}
input: {
console.log({
...{
get 0() {
return "FAIL";
},
...{
0: "PASS",
},
},
}[0]);
}
expect: {
console.log({
...{
get 0() {
return "FAIL";
},
[0]: "PASS",
},
}[0]);
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_4331: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var a = "PASS", b;
console,
b = a;
(function() {
a++;
})(...a);
console.log(b);
}
expect: {
var a = "PASS", b;
console;
(function() {
a++;
})(...b = a);
console.log(b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_4342: {
options = {
side_effects: true,
}
input: {
try {
new function() {}(...42);
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
[ ...42 ];
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_4345: {
options = {
objects: true,
spreads: true,
}
input: {
console.log({
...{
get 42() {
return "FAIL";
},
...{},
42: "PASS",
},
}[42]);
}
expect: {
console.log({
...{
get 42() {
return "FAIL";
},
[42]: "PASS",
},
}[42]);
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_4361: {
options = {
reduce_vars: true,
unused: true,
}
input: {
console.log(function() {
var a = console.log("foo");
console;
var b = {
...a,
};
}());
}
expect: {
console.log(function() {
var a = console.log("foo");
console;
({
...a,
});
}());
}
expect_stdout: [
"foo",
"undefined",
]
node_version: ">=8"
}
issue_4363: {
options = {
objects: true,
spreads: true,
}
input: {
({
...{
set [console.log("PASS")](v) {},
},
});
}
expect: {
({
[console.log("PASS")]: void 0,
});
}
expect_stdout: "PASS"
node_version: ">=8"
}
issue_4556: {
options = {
reduce_vars: true,
unused: true,
}
input: {
console.log(function() {
var a = "" + [ a++ ];
var b = [ ...a ];
}());
}
expect: {
console.log(function() {
var a;
}());
}
expect_stdout: "undefined"
node_version: ">=6"
}
issue_4560_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 0;
(function(...{
[a++]: {},
}) {})(2);
console.log(a);
}
expect: {
var a = 0;
(function(...{
[a++]: {},
}) {})(2);
console.log(a);
}
expect_stdout: "1"
node_version: ">=6"
}
issue_4560_2: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 0;
(function(...{
[a++]: {},
}) {})(2);
console.log(a);
}
expect: {
var a = 0;
(function(...{
[a++]: {},
}) {})(2);
console.log(a);
}
expect_stdout: "1"
node_version: ">=6"
}
issue_4560_3: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 0, b;
[ ...{
[a++]: b,
} ] = [ "PASS" ];
console.log(b);
}
expect: {
var a = 0, b;
[ ...{
[a++]: b,
} ] = [ "PASS" ];
console.log(b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_4614: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
try {
(function(...[]) {
var arguments;
arguments[0];
})();
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
(function(...[]) {
var arguments;
arguments[0];
})();
} catch (e) {
console.log("PASS");
}
}
expect_stdout: true
node_version: ">=6"
}

330
test/compress/templates.js Normal file
View File

@@ -0,0 +1,330 @@
simple: {
input: {
console.log(`foo
bar\nbaz`);
}
expect_exact: "console.log(`foo\n bar\\nbaz`);"
expect_stdout: [
"foo",
" bar",
"baz",
]
node_version: ">=4"
}
placeholder: {
input: {
console.log(`foo ${ function(a, b) {
return a * b;
}(6, 7) }`);
}
expect_exact: "console.log(`foo ${function(a,b){return a*b}(6,7)}`);"
expect_stdout: "foo 42"
node_version: ">=4"
}
nested: {
input: {
console.log(`P${`A${"S"}`}S`);
}
expect_exact: 'console.log(`P${`A${"S"}`}S`);'
expect_stdout: "PASS"
node_version: ">=4"
}
tagged: {
input: {
console.log(String.raw`foo\nbar`);
}
expect_exact: "console.log(String.raw`foo\\nbar`);"
expect_stdout: "foo\\nbar"
node_version: ">=4"
}
tagged_chain: {
input: {
function f(strings) {
return strings.join("") || f;
}
console.log(f```${42}``pass`.toUpperCase());
}
expect_exact: 'function f(strings){return strings.join("")||f}console.log(f```${42}``pass`.toUpperCase());'
expect_stdout: "PASS"
node_version: ">=4"
}
tag_parentheses_arrow: {
input: {
console.log((s => s.raw[0])`\tPASS`.slice(2));
}
expect_exact: "console.log((s=>s.raw[0])`\\tPASS`.slice(2));"
expect_stdout: "PASS"
node_version: ">=4"
}
tag_parentheses_new: {
input: {
(new function() {
return console.log;
})`foo`;
}
expect_exact: "(new function(){return console.log})`foo`;"
expect_stdout: true
node_version: ">=4"
}
malformed_escape: {
input: {
(function(s) {
s.forEach((c, i) => console.log(i, c, s.raw[i]));
return () => console.log(arguments);
})`\uFo${42}`();
}
expect_exact: "(function(s){s.forEach((c,i)=>console.log(i,c,s.raw[i]));return()=>console.log(arguments)})`\\uFo${42}`();"
expect_stdout: true
node_version: ">=4"
}
evaluate: {
options = {
evaluate: true,
templates: false,
}
input: {
console.log(`foo ${ function(a, b) {
return a * b;
}(6, 7) }`);
}
expect: {
console.log(`foo ${42}`);
}
expect_stdout: "foo 42"
node_version: ">=4"
}
evaluate_templates: {
options = {
evaluate: true,
templates: true,
}
input: {
console.log(`foo ${ function(a, b) {
return a * b;
}(6, 7) }`);
}
expect: {
console.log("foo 42");
}
expect_stdout: "foo 42"
node_version: ">=4"
}
partial_evaluate: {
options = {
evaluate: true,
templates: true,
}
input: {
console.log(`${6 * 7} foo ${console ? `PA` + "SS" : `FA` + `IL`}`);
}
expect: {
console.log(`42 foo ${console ? "PASS" : "FAIL"}`);
}
expect_stdout: "42 foo PASS"
node_version: ">=4"
}
malformed_evaluate_1: {
options = {
evaluate: true,
templates: true,
}
input: {
console.log(`\67 ${6 * 7}`);
}
expect: {
console.log(`\67 42`);
}
expect_stdout: true
node_version: ">=4"
}
malformed_evaluate_2: {
options = {
evaluate: true,
templates: true,
}
input: {
console.log(`\u0${0}b${5}`);
}
expect: {
console.log(`\u0${0}b5`);
}
expect_stdout: true
node_version: ">=4"
}
malformed_evaluate_3: {
options = {
evaluate: true,
templates: true,
}
input: {
console.log(`\u${0}b${5}`);
}
expect: {
console.log(`\u0b5`);
}
expect_stdout: true
node_version: ">=4"
}
malformed_evaluate_4: {
options = {
evaluate: true,
templates: true,
unsafe: true,
}
input: {
console.log(String.raw`\u0${0}b${5}`);
}
expect: {
console.log("\\u00b5");
}
expect_stdout: "\\u00b5"
node_version: ">=8"
}
unsafe_evaluate: {
options = {
evaluate: true,
templates: true,
unsafe: true,
}
input: {
console.log(String.raw`\uFo`);
}
expect: {
console.log("\\uFo");
}
expect_stdout: "\\uFo"
node_version: ">=8"
}
side_effects: {
options = {
side_effects: true,
}
input: {
`42`;
`${console.log("foo")}`;
console.log`\nbar`;
}
expect: {
console.log("foo");
console.log`\nbar`;
}
expect_stdout: true
node_version: ">=4"
}
unsafe_side_effects: {
options = {
side_effects: true,
unsafe: true,
}
input: {
`42`;
`${console.log("foo")}`;
String.raw`\nbar`;
}
expect: {
console.log("foo");
}
expect_stdout: "foo"
node_version: ">=4"
}
issue_4604: {
options = {
collapse_vars: true,
}
input: {
var a = 0, log = console.log;
a = "FAIL";
(function() {
a = "PASS";
})``;
log(a);
}
expect: {
var a = 0, log = console.log;
a = "FAIL";
(function() {
a = "PASS";
})``;
log(a);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4606: {
options = {
evaluate: true,
templates: true,
}
input: {
console.log(`${typeof A} ${"\r"} ${"\\"} ${"`"}`);
}
expect: {
console.log(`${typeof A} \r \\ \``);
}
expect_stdout: "undefined \r \\ `"
node_version: ">=4"
}
issue_4630: {
options = {
evaluate: true,
templates: true,
}
input: {
console.log(`${/PASS/}`);
}
expect: {
console.log("/PASS/");
}
expect_stdout: "/PASS/"
node_version: ">=4"
}
issue_4676: {
options = {
evaluate: true,
reduce_vars: true,
templates: true,
toplevel: true,
unsafe:true,
unused: true,
}
input: {
function f(a) {
var b = `foo${a = "PASS"}`;
for (var c in f && b)
b.p;
return a;
}
console.log(f("FAIL"));
}
expect: {
console.log(function f(a) {
var b = "fooPASS";
for (var c in f, b)
b.p;
return "PASS";
}());
}
expect_stdout: "PASS"
node_version: ">=4"
}

View File

@@ -1,3 +1,37 @@
ascii_only_false: {
options = {}
beautify = {
ascii_only: false,
}
input: {
console.log(
"\x000\x001\x007\x008\x00",
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff"
);
}
expect_exact: 'console.log("\\x000\\x001\\x007\\x008\\0","\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f","\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\');'
expect_stdout: true
}
ascii_only_true: {
options = {}
beautify = {
ascii_only: true,
}
input: {
console.log(
"\x000\x001\x007\x008\x00",
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff"
);
}
expect_exact: 'console.log("\\x000\\x001\\x007\\x008\\0","\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\v\\f\\r\\x0e\\x0f","\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f",\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\');'
expect_stdout: true
}
unicode_parse_variables: {
options = {}
input: {
@@ -141,3 +175,35 @@ issue_2569: {
}
expect_exact: 'new RegExp("[\\udc42-\\udcaa\\udd74-\\udd96\\ude45-\\ude4f\\udea3-\\udecc]");'
}
surrogate_pair: {
beautify = {
ascii_only: false,
}
input: {
var \u{2f800} = {
\u{2f801}: "\u{100000}",
};
\u{2f800}.\u{2f802} = "\u{100001}";
console.log(typeof \u{2f800}, \u{2f800}.\u{2f801}, \u{2f800}["\u{2f802}"]);
}
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"
}
surrogate_pair_ascii: {
beautify = {
ascii_only: true,
}
input: {
var \u{2f800} = {
\u{2f801}: "\u{100000}",
};
\u{2f800}.\u{2f802} = "\u{100001}";
console.log(typeof \u{2f800}, \u{2f800}.\u{2f801}, \u{2f800}["\u{2f802}"]);
}
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"
}

525
test/compress/varify.js Normal file
View File

@@ -0,0 +1,525 @@
reduce_merge_const: {
options = {
merge_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
varify: true,
}
input: {
const a = console;
console.log(typeof a);
var b = typeof a;
console.log(b);
}
expect: {
var b = console;
console.log(typeof b);
b = typeof b;
console.log(b);
}
expect_stdout: [
"object",
"object",
]
}
reduce_merge_let: {
options = {
merge_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
varify: true,
}
input: {
"use strict";
let a = console;
console.log(typeof a);
var b = typeof a;
console.log(b);
}
expect: {
"use strict";
var b = console;
console.log(typeof b);
b = typeof b;
console.log(b);
}
expect_stdout: [
"object",
"object",
]
node_version: ">=4"
}
reduce_block_const: {
options = {
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
{
const a = typeof console;
console.log(a);
}
}
expect: {
var a = typeof console;
console.log(a);
}
expect_stdout: "object"
}
reduce_block_let: {
options = {
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
"use strict";
{
let a = typeof console;
console.log(a);
}
}
expect: {
"use strict";
var a = typeof console;
console.log(a);
}
expect_stdout: "object"
node_version: ">=4"
}
hoist_props_const: {
options = {
hoist_props: true,
passes: 2,
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
{
const o = {
p: "PASS",
};
console.log(o.p);
}
}
expect: {
var o_p = "PASS";
console.log(o_p);
}
expect_stdout: "PASS"
}
hoist_props_let: {
options = {
hoist_props: true,
passes: 2,
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
"use strict";
{
let o = {
p: "PASS",
};
console.log(o.p);
}
}
expect: {
"use strict";
var o_p = "PASS";
console.log(o_p);
}
expect_stdout: "PASS"
node_version: ">=4"
}
scope_adjustment_const: {
options = {
conditionals: true,
inline: true,
reduce_vars: true,
toplevel: true,
unused: true,
varify: true,
}
input: {
for (var k in [ 42 ])
console.log(function f() {
if (k) {
const a = 0;
}
}());
}
expect: {
for (var k in [ 42 ])
console.log(void (k && 0));
}
expect_stdout: "undefined"
}
scope_adjustment_let: {
options = {
conditionals: true,
inline: true,
reduce_vars: true,
toplevel: true,
unused: true,
varify: true,
}
input: {
"use strict";
for (var k in [ 42 ])
console.log(function f() {
if (k) {
let a = 0;
}
}());
}
expect: {
"use strict";
for (var k in [ 42 ])
console.log(void (k && 0));
}
expect_stdout: "undefined"
node_version: ">=4"
}
issue_4191_const: {
options = {
functions: true,
reduce_vars: true,
toplevel: true,
unused: true,
varify: true,
}
input: {
const a = function() {};
console.log(typeof a, a());
}
expect: {
function a() {};
console.log(typeof a, a());
}
expect_stdout: "function undefined"
}
issue_4191_let: {
options = {
functions: true,
reduce_vars: true,
toplevel: true,
unused: true,
varify: true,
}
input: {
"use strict";
let a = function() {};
console.log(typeof a, a());
}
expect: {
"use strict";
function a() {};
console.log(typeof a, a());
}
expect_stdout: "function undefined"
node_version: ">=4"
}
forin_const_1: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
const o = {
foo: 42,
bar: "PASS",
};
for (const k in o)
console.log(k, o[k]);
}
expect: {
var o = {
foo: 42,
bar: "PASS",
};
for (const k in o)
console.log(k, o[k]);
}
expect_stdout: true
node_version: ">=4"
}
forin_const_2: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
const o = {
p: 42,
q: "PASS",
};
for (const [ k ] in o)
console.log(k, o[k]);
}
expect: {
var o = {
p: 42,
q: "PASS",
}, k;
for ([ k ] in o)
console.log(k, o[k]);
}
expect_stdout: [
"p 42",
"q PASS",
]
node_version: ">=6"
}
forin_let_1: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
"use strict";
let o = {
foo: 42,
bar: "PASS",
};
for (let k in o)
console.log(k, o[k]);
}
expect: {
"use strict";
var o = {
foo: 42,
bar: "PASS",
}, k;
for (k in o)
console.log(k, o[k]);
}
expect_stdout: [
"foo 42",
"bar PASS",
]
node_version: ">=4"
}
forin_let_2: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
let o = {
p: 42,
q: "PASS",
};
for (let [ k ] in o)
console.log(k, o[k]);
}
expect: {
var o = {
p: 42,
q: "PASS",
}, k;
for ([ k ] in o)
console.log(k, o[k]);
}
expect_stdout: [
"p 42",
"q PASS",
]
node_version: ">=6"
}
loop_scope_1: {
options = {
toplevel: true,
varify: true,
}
input: {
"use strict";
var o = { foo: 1, bar: 2 };
for (let i in o) {
console.log(i);
}
for (const j in o)
setTimeout(() => console.log(j), 0);
for (let k in o)
setTimeout(function() {
console.log(k);
}, 0);
}
expect: {
"use strict";
var o = { foo: 1, bar: 2 };
for (var i in o)
console.log(i);
for (const j in o)
setTimeout(() => console.log(j), 0);
for (let k in o)
setTimeout(function() {
console.log(k);
}, 0);
}
expect_stdout: [
"foo",
"bar",
"foo",
"bar",
"foo",
"bar",
]
node_version: ">=4"
}
loop_scope_2: {
options = {
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
"use strict";
var a = [ "foo", "bar" ];
for (var i = 0; i < a.length; i++) {
const x = a[i];
console.log(x);
let y = a[i];
setTimeout(() => console.log(y), 0);
const z = a[i];
setTimeout(function() {
console.log(z);
}, 0);
}
}
expect: {
"use strict";
var a = [ "foo", "bar" ];
for (var i = 0; i < a.length; i++) {
var x = a[i];
console.log(x);
let y = a[i];
setTimeout(() => console.log(y), 0);
const z = a[i];
setTimeout(function() {
console.log(z);
}, 0);
}
}
expect_stdout: [
"foo",
"bar",
"foo",
"foo",
"bar",
"bar",
]
node_version: ">=4"
}
issue_4290_1_const: {
options = {
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
const a = 0;
var a;
}
expect: {
const a = 0;
var a;
}
expect_stdout: true
}
issue_4290_1_let: {
options = {
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
"use strict";
let a = 0;
var a;
}
expect: {
"use strict";
let a = 0;
var a;
}
expect_stdout: true
node_version: ">=4"
}
drop_forin_let: {
options = {
loops: true,
toplevel: true,
unused: true,
varify: true,
}
input: {
"use strict";
for (let a in console.log("PASS"));
}
expect: {
"use strict";
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
default_init: {
options = {
join_vars: true,
reduce_vars: true,
unused: true,
varify: true,
}
input: {
A = "PASS";
(function() {
"use strict";
let a;
a = A;
console.log(a);
})();
}
expect: {
A = "PASS";
(function() {
"use strict";
var a = A;
console.log(a);
})();
}
expect_stdout: "PASS"
node_version: ">=4"
}

952
test/compress/yields.js Normal file
View File

@@ -0,0 +1,952 @@
binary: {
input: {
var a = function*() {
console.log(6 * (yield "PA" + "SS"));
}();
console.log(a.next("FAIL").value);
console.log(a.next(7).done);
}
expect_exact: 'var a=function*(){console.log(6*(yield"PA"+"SS"))}();console.log(a.next("FAIL").value);console.log(a.next(7).done);'
expect_stdout: [
"PASS",
"42",
"true",
]
node_version: ">=4"
}
empty_yield: {
input: {
var a = function*() {
yield;
console.log(yield);
yield
"FAIL 1";
}();
console.log(a.next("FAIL 2").value);
console.log(a.next("FAIL 3").value);
console.log(a.next("PASS").value);
console.log(a.next("FAIL 4").done);
}
expect_exact: 'var a=function*(){yield;console.log(yield);yield;"FAIL 1"}();console.log(a.next("FAIL 2").value);console.log(a.next("FAIL 3").value);console.log(a.next("PASS").value);console.log(a.next("FAIL 4").done);'
expect_stdout: [
"undefined",
"undefined",
"PASS",
"undefined",
"true",
]
node_version: ">=4"
}
empty_yield_conditional: {
input: {
var a = function*() {
console.log((yield) ? yield : yield);
}();
console.log(a.next("FAIL 1").value);
console.log(a.next("FAIL 2").value);
console.log(a.next("PASS").value);
console.log(a.next("FAIL 3").done);
}
expect_exact: 'var a=function*(){console.log((yield)?yield:yield)}();console.log(a.next("FAIL 1").value);console.log(a.next("FAIL 2").value);console.log(a.next("PASS").value);console.log(a.next("FAIL 3").done);'
expect_stdout: [
"undefined",
"undefined",
"PASS",
"undefined",
"true",
]
node_version: ">=4"
}
nested_yield: {
input: {
console.log(function*() {
(yield*
f())
function* f() {
return "FAIL";
}
yield*
f();
yield *f();
}().next().value || "PASS");
}
expect_exact: 'console.log(function*(){yield*f();function*f(){return"FAIL"}yield*f();yield*f()}().next().value||"PASS");'
expect_stdout: "PASS"
node_version: ">=4"
}
pause_resume: {
input: {
function* f() {
console.log(yield "PASS");
}
var a = f();
console.log(a.next("FAIL").value);
console.log(a.next(42).done);
}
expect_exact: 'function*f(){console.log(yield"PASS")}var a=f();console.log(a.next("FAIL").value);console.log(a.next(42).done);'
expect_stdout: [
"PASS",
"42",
"true",
]
node_version: ">=4"
}
arrow_yield: {
input: {
yield = "PASS";
console.log(function*() {
return () => yield || "FAIL";
}().next().value());
}
expect_exact: 'yield="PASS";console.log(function*(){return()=>yield||"FAIL"}().next().value());'
expect_stdout: "PASS"
node_version: ">=4"
}
for_of: {
input: {
function* f() {
if (yield "PASS") yield "FAIL 1";
yield 42;
return "FAIL 2";
}
for (var a of f())
console.log(a);
}
expect_exact: 'function*f(){if(yield"PASS")yield"FAIL 1";yield 42;return"FAIL 2"}for(var a of f())console.log(a);'
expect_stdout: [
"PASS",
"42",
]
node_version: ">=4"
}
for_await_of: {
input: {
async function* f() {
if (yield "PASS") yield "FAIL 1";
yield {
then: function(r) {
r(42);
},
};
return "FAIL 2";
}
(async function(a) {
for await (a of f())
console.log(a);
})();
}
expect_exact: 'async function*f(){if(yield"PASS")yield"FAIL 1";yield{then:function(r){r(42)}};return"FAIL 2"}(async function(a){for await(a of f())console.log(a)})();'
expect_stdout: [
"PASS",
"42",
]
node_version: ">=10"
}
collapse_vars_1: {
options = {
collapse_vars: true,
}
input: {
var a = "FAIL";
(function*() {
a = "PASS";
yield 42;
return "PASS";
})().next();
console.log(a);
}
expect: {
var a = "FAIL";
(function*() {
a = "PASS";
yield 42;
return "PASS";
})().next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=4"
}
collapse_vars_2: {
options = {
collapse_vars: true,
}
input: {
var a = "FAIL";
(function*() {
yield (a = "PASS");
return "PASS";
})().next();
console.log(a);
}
expect: {
var a = "FAIL";
(function*() {
yield (a = "PASS");
return "PASS";
})().next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=4"
}
collapse_vars_3: {
options = {
collapse_vars: true,
}
input: {
var a = "FAIL";
(function*() {
yield (a = "PASS", 42);
return "PASS";
})().next();
console.log(a);
}
expect: {
var a = "FAIL";
(function*() {
yield (a = "PASS", 42);
return "PASS";
})().next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=4"
}
collapse_vars_4: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var a = "FAIL";
var b = function*(c) {
return c;
}(a = "PASS");
console.log(a, b.next().done);
}
expect: {
var a = "FAIL";
var b = function*(c) {
return c;
}(a = "PASS");
console.log(a, b.next().done);
}
expect_stdout: "PASS true"
node_version: ">=4"
}
collapse_property_lambda: {
options = {
collapse_vars: true,
pure_getters: "strict",
}
input: {
console.log(function* f() {
f.g = () => 42;
return f.g();
}().next().value);
}
expect: {
console.log(function* f() {
return (f.g = () => 42)();
}().next().value);
}
expect_stdout: "42"
node_version: ">=4"
}
defun_name: {
input: {
function* yield() {
console.log("PASS");
}
yield().next();
}
expect: {
function* yield() {
console.log("PASS");
}
yield().next();
}
expect_stdout: "PASS"
node_version: ">=4"
}
drop_fname: {
rename = true
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
function* yield() {
console.log("PASS");
}
yield().next();
}
expect: {
(function*() {
console.log("PASS");
})().next();
}
expect_stdout: "PASS"
node_version: ">=4"
}
keep_fname: {
options = {
keep_fnames: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function* yield() {
console.log("PASS");
}
yield().next();
}
expect: {
function* yield() {
console.log("PASS");
}
yield().next();
}
expect_stdout: "PASS"
node_version: ">=4"
}
evaluate: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = function*() {}();
console.log(typeof a);
}
expect: {
var a = function*() {}();
console.log(typeof a);
}
expect_stdout: "object"
node_version: ">=4"
}
functions: {
options = {
functions: true,
reduce_vars: true,
unused: true,
}
input: {
!function*() {
var a = function* a() {
return a && "a";
};
var b = function* x() {
return !!x;
};
var c = function*(c) {
return c;
};
if (yield* c(yield* b(yield* a()))) {
var d = function*() {};
var e = function* y() {
return typeof y;
};
var f = function*(f) {
return f;
};
console.log(yield* a(yield* d()), yield* b(yield* e()), yield* c(yield* f(42)), typeof d, yield* e(), typeof f);
}
}().next();
}
expect: {
!function*() {
function* a() {
return a && "a";
}
function* b() {
return !!b;
}
var c = function*(c) {
return c;
};
if (yield* c(yield* b(yield* a()))) {
function* d() {}
function* e() {
return typeof e;
}
var f = function*(f) {
return f;
};
console.log(yield* a(yield* d()), yield* b(yield* e()), yield* c(yield* f(42)), typeof d, yield* e(), typeof f);
}
}().next();
}
expect_stdout: "a true 42 function function function"
node_version: ">=4"
}
functions_use_strict: {
options = {
functions: true,
reduce_vars: true,
unused: true,
}
input: {
"use strict";
!function*() {
var a = function* a() {
return a && "a";
};
var b = function* x() {
return !!x;
};
var c = function*(c) {
return c;
};
if (yield* c(yield* b(yield* a()))) {
var d = function*() {};
var e = function* y() {
return typeof y;
};
var f = function*(f) {
return f;
};
console.log(yield* a(yield* d()), yield* b(yield* e()), yield* c(yield* f(42)), typeof d, yield* e(), typeof f);
}
}().next();
}
expect: {
"use strict";
!function*() {
function* a() {
return a && "a";
}
function* b() {
return !!b;
}
var c = function*(c) {
return c;
};
if (yield* c(yield* b(yield* a()))) {
var d = function*() {};
var e = function* y() {
return typeof y;
};
var f = function*(f) {
return f;
};
console.log(yield* a(yield* d()), yield* b(yield* e()), yield* c(yield* f(42)), typeof d, yield* e(), typeof f);
}
}().next();
}
expect_stdout: "a true 42 function function function"
node_version: ">=4"
}
negate_iife: {
options = {
negate_iife: true,
side_effects: true,
}
input: {
(function*(a) {
console.log(a);
})("PASS").next();
}
expect: {
!function*(a) {
console.log(a);
}("PASS").next();
}
expect_stdout: "PASS"
node_version: ">=4"
}
reduce_iife_1: {
options = {
reduce_vars: true,
unused: true,
}
input: {
console.log(function*(a) {
yield a;
}(42).next().value);
}
expect: {
console.log(function*(a) {
yield 42;
}().next().value);
}
expect_stdout: "42"
node_version: ">=4"
}
reduce_iife_2: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = "PASS";
(function*() {
a = "FAIL";
})();
console.log(a);
}
expect: {
var a = "PASS";
(function*() {
a = "FAIL";
})();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=4"
}
reduce_single_use_defun: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function* f(a) {
console.log(a);
}
f("PASS").next();
}
expect: {
(function*(a) {
console.log(a);
})("PASS").next();
}
expect_stdout: "PASS"
node_version: ">=4"
}
reduce_tagged: {
options = {
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
function* f() {
function g() {
h`foo`;
}
g();
function h(s) {
console.log(s[0]);
}
h([ "bar" ]);
}
f().next();
}
expect: {
function* f() {
(function() {
h`foo`;
})();
function h(s) {
console.log(s[0]);
}
h([ "bar" ]);
}
f().next();
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=4"
}
reduce_tagged_async: {
options = {
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
async function* f() {
function g() {
h`foo`;
}
g();
function h(s) {
console.log(s[0]);
}
h([ "bar" ]);
}
f().next();
}
expect: {
async function* f() {
(function() {
h`foo`;
})();
function h(s) {
console.log(s[0]);
}
h([ "bar" ]);
}
f().next();
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=10"
}
lift_sequence: {
options = {
sequences: true,
yields: true,
}
input: {
console.log(function*() {
yield (console, "PASS");
}().next().value);
}
expect: {
console.log(function*() {
console, yield "PASS";
}().next().value);
}
expect_stdout: "PASS"
node_version: ">=4"
}
inline_nested_yield: {
options = {
inline: true,
sequences: true,
yields: true,
}
input: {
var a = function*() {
yield* function*() {
yield "foo";
return "FAIL";
}();
}(), b;
do {
b = a.next();
console.log(b.value);
} while (!b.done);
}
expect: {
var a = function*() {
yield "foo",
"FAIL";
}(), b;
do {
b = a.next(),
console.log(b.value);
} while (!b.done);
}
expect_stdout: [
"foo",
"undefined",
]
node_version: ">=4"
}
drop_body: {
options = {
side_effects: true,
yields: true,
}
input: {
(function*([ , a = console.log("foo") ]) {
console.log("bar");
})([ console.log("baz") ]);
}
expect: {
[ [ , [].e = console.log("foo") ] ] = [ [ console.log("baz") ] ];
}
expect_stdout: [
"baz",
"foo",
]
node_version: ">=6"
}
drop_unused_call: {
options = {
inline: true,
side_effects: true,
toplevel: true,
unused: true,
yields: true,
}
input: {
var a = function*(){}(console.log("PASS"));
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4454_1: {
rename = false
options = {
merge_vars: true,
}
input: {
function f(a) {
(function*(b = console.log(a)) {})();
var yield = 42..toString();
console.log(yield);
}
f("PASS");
}
expect: {
function f(a) {
(function*(b = console.log(a)) {})();
var yield = 42..toString();
console.log(yield);
}
f("PASS");
}
expect_stdout: [
"PASS",
"42",
]
node_version: ">=6"
}
issue_4454_2: {
rename = true
options = {
merge_vars: true,
}
input: {
function f(a) {
(function*(b = console.log(a)) {})();
var yield = 42..toString();
console.log(yield);
}
f("PASS");
}
expect: {
function f(b) {
(function*(c = console.log(b)) {})();
var b = 42..toString();
console.log(b);
}
f("PASS");
}
expect_stdout: [
"PASS",
"42",
]
node_version: ">=6"
}
issue_4618: {
options = {
functions: true,
reduce_vars: true,
unused: true,
}
input: {
console.log(typeof function() {
var yield = function* f() {
console || f();
};
console.log;
return yield;
}());
}
expect: {
console.log(typeof function() {
var yield = function* f() {
console || f();
};
console.log;
return yield;
}());
}
expect_stdout: "function"
node_version: ">=4"
}
issue_4623: {
options = {
conditionals: true,
}
input: {
if (console ? function*() {} : 0)
console.log("PASS");
}
expect: {
(console ? function*() {} : 0) && console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4633: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var a = function*() {
(function(log) {
log(typeof this);
})(yield "PASS");
}();
console.log(a.next().value);
a.next(console.log);
}
expect: {
var a = function*() {
(function(log) {
log(typeof this);
})(yield "PASS");
}();
console.log(a.next().value);
a.next(console.log);
}
expect_stdout: [
"PASS",
"object",
]
node_version: ">=4"
}
issue_4639_1: {
options = {
inline: true,
}
input: {
console.log(function*() {
return function() {
return yield => "PASS";
}();
}().next().value());
}
expect: {
console.log(function*() {
return function() {
return yield => "PASS";
}();
}().next().value());
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4639_2: {
options = {
inline: true,
}
input: {
(function*() {
console.log(function() {
return typeof yield;
}());
})().next();
}
expect: {
(function*() {
console.log(function() {
return typeof yield;
}());
})().next();
}
expect_stdout: "undefined"
node_version: ">=4"
}
issue_4641_1: {
options = {
sequences: true,
}
input: {
console.log(typeof async function*() {
try {
console.log("foo");
return;
} finally {
console.log("bar");
}
}().next().then);
}
expect: {
console.log(typeof async function*() {
try {
console.log("foo");
return;
} finally {
console.log("bar");
}
}().next().then);
}
expect_stdout: [
"foo",
"bar",
"function",
]
node_version: ">=10"
}
issue_4641_2: {
options = {
side_effects: 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 0;
} finally {
console.log("PASS");
}
}().next().then);
}
expect_stdout: [
"function",
"PASS",
]
node_version: ">=10"
}

View File

@@ -1,5 +1,6 @@
exports["Compressor"] = Compressor;
exports["defaults"] = defaults;
exports["is_statement"] = is_statement;
exports["JS_Parse_Error"] = JS_Parse_Error;
exports["List"] = List;
exports["mangle_properties"] = mangle_properties;

View File

@@ -0,0 +1,8 @@
function f() {
var { eval } = null;
}
function g() {
"use strict";
var { eval } = 42;
}

View File

@@ -0,0 +1,3 @@
var a = [ 1 ], b;
for (b = 2 of a)
console.log(b);

View File

@@ -0,0 +1,3 @@
var a = [ 1 ];
for (var b = 2 of a)
console.log(b);

View File

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

View File

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

View File

@@ -0,0 +1,3 @@
var o = {};
[ o[1 + .1 + .1] ] = [ 42 ];
console.log(o[1.2]);

View File

@@ -0,0 +1,17 @@
// (beautified)
var o = {};
[ o[1 + .1 + .1] ] = [];
console.log(o);
// output: { '1.2000000000000002': undefined }
//
// minify: { '1.2': undefined }
//
// options: {
// "compress": {
// "unsafe_math": true
// },
// "mangle": false,
// "validate": true
// }

View File

@@ -0,0 +1,7 @@
try {
"foo" in 42;
} catch ({
message,
}) {
console.log(message);
}

View File

@@ -0,0 +1,13 @@
// (beautified)
try {
1 in 0;
} catch (message) {
console.log(message);
}
// output: TypeError: Cannot use 'in' operator to search for '1' in 0
//
// minify: TypeError: Cannot use 'in' operator to search for '0' in 0
//
// options: {
// "mangle": false
// }

View File

@@ -1,5 +1,5 @@
(function f(a) {
do {
console.log(f.length);
} while (console.log(f += 0));
})();
console.log(function(undefined) {
return undefined[function() {
{}
}] || 1 + .1 + .1;
}(42));

View File

@@ -1,19 +1,14 @@
// (beautified)
(function f(a) {
do {
console.log(f.length);
} while (console.log(f += 0));
})();
// output: 1
// function(){}0
console.log(function() {
return 1 + .1 + .1;
}());
// output: 1.2000000000000002
//
// minify: 0
// function(){}0
// minify: 1.2
//
// options: {
// "compress": {
// "keep_fargs": false,
// "unsafe": true
// "unsafe_math": true
// },
// "mangle": false
// }

View File

@@ -1,8 +1,5 @@
console.log(function f(a) {
({
set p(v) {
f++;
}
});
return f.length;
}());
({
set p(v) {
console.log(+v + .1 + .1);
}
}).p = 1;

View File

@@ -1,20 +1,16 @@
// (beautified)
console.log(function f(a) {
({
set p(v) {
f++;
}
});
return f.length;
}());
// output: 1
({
set p(v) {
console.log(1 + .1 + .1);
}
}).p = 0;
// output: 1.2000000000000002
//
// minify: 0
// minify: 1.2
//
// options: {
// "compress": {
// "keep_fargs": false,
// "unsafe": true
// "unsafe_math": true
// },
// "mangle": false
// }

View File

@@ -5,7 +5,7 @@
var site = "https://browserbench.org/JetStream1.1";
if (typeof phantom == "undefined") {
require("../tools/exit");
require("../tools/tty");
var args = process.argv.slice(2);
var debug = args.indexOf("--debug");
if (debug < 0) {
@@ -60,7 +60,7 @@ if (typeof phantom == "undefined") {
var port = server.address().port;
if (debug) {
console.log("http://localhost:" + port + "/");
} else {
} else (function install() {
child_process.spawn(process.platform == "win32" ? "npm.cmd" : "npm", [
"install",
"phantomjs-prebuilt@2.1.14",
@@ -71,7 +71,10 @@ if (typeof phantom == "undefined") {
], {
stdio: [ "ignore", 1, 2 ]
}).on("exit", function(code) {
if (code) throw new Error("npm install failed!");
if (code) {
console.log("npm install failed with code", code);
return install();
}
var program = require("phantomjs-prebuilt").exec(process.argv[1], port);
program.stdout.pipe(process.stdout);
program.stderr.pipe(process.stderr);
@@ -82,7 +85,7 @@ if (typeof phantom == "undefined") {
process.exit(0);
});
});
}
})();
});
server.timeout = 0;
} else {

65
test/mocha/awaits.js Normal file
View File

@@ -0,0 +1,65 @@
var assert = require("assert");
var UglifyJS = require("../node");
describe("async", function() {
it("Should reject `await` as symbol name within async functions only", function() {
[
"function await() {}",
"function(await) {}",
"function() { await; }",
"function() { await:{} }",
"function() { var await; }",
"function() { function await() {} }",
"function() { try {} catch (await) {} }",
].forEach(function(code) {
var ast = UglifyJS.parse("(" + code + ")();");
assert.strictEqual(ast.TYPE, "Toplevel");
assert.strictEqual(ast.body.length, 1);
assert.strictEqual(ast.body[0].TYPE, "SimpleStatement");
assert.strictEqual(ast.body[0].body.TYPE, "Call");
assert.strictEqual(ast.body[0].body.expression.TYPE, "Function");
assert.throws(function() {
UglifyJS.parse("(async " + code + ")();");
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error;
}, code);
});
});
it("Should reject `await` expression outside of async functions", function() {
[
"await 42;",
"function f() { await 42; }",
"async function f() { function g() { await 42; } }",
].forEach(function(code) {
assert.throws(function() {
UglifyJS.parse(code);
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error;
}, code);
});
});
it("Should reject `await` expression directly on computed key of function argument", function() {
[
"function f({ [await 42]: a }) {}",
"async function f({ [await 42]: a }) {}",
].forEach(function(code) {
assert.throws(function() {
UglifyJS.parse(code);
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error;
}, code);
});
});
it("Should accept `await` expression nested within computed key of function argument", function() {
[
"function f({ [async function() { await 42; }()]: a }) {}",
"async function f({ [async function() { await 42; }()]: a }) {}",
].forEach(function(code) {
var ast = UglifyJS.parse(code);
assert.strictEqual(ast.TYPE, "Toplevel");
assert.strictEqual(ast.body.length, 1);
assert.strictEqual(ast.body[0].argnames.length, 1);
assert.strictEqual(ast.body[0].argnames[0].TYPE, "DestructuredObject");
});
});
});

40
test/mocha/bug-report.js Normal file
View File

@@ -0,0 +1,40 @@
var assert = require("assert");
var exec = require("child_process").exec;
describe("UGLIFY_BUG_REPORT", function() {
var env = Object.create(process.env);
env.UGLIFY_BUG_REPORT = 1;
it("Should generate bug report via API", function(done) {
exec('"' + process.argv[0] + '"', { env: env }, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, [
"// UGLIFY_BUG_REPORT",
"// <<undefined>>",
"",
"//-------------------------------------------------------------",
"// INPUT CODE",
"...---...",
"",
].join("\n"));
done();
}).stdin.end('console.log(require("./").minify("...---...").code);');
});
it("Should generate bug report via CLI", function(done) {
exec('"' + process.argv[0] + '" bin/uglifyjs -mc', { env: env }, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, [
"// UGLIFY_BUG_REPORT",
"// {",
'// "mangle": {},',
'// "compress": {}',
"// }",
"",
"//-------------------------------------------------------------",
"// STDIN",
"...---...",
"",
].join("\n"));
done();
}).stdin.end("...---...");
});
});

View File

@@ -56,7 +56,7 @@ describe("bin/uglifyjs", function() {
"--source-map", [
"names=true",
"url=inline",
].join(","),
].join(),
].join(" "), function(err, stdout) {
if (err) throw err;
var expected = [
@@ -84,7 +84,7 @@ describe("bin/uglifyjs", function() {
"--source-map", [
"names=false",
"url=inline",
].join(","),
].join(),
].join(" "), function(err, stdout) {
if (err) throw err;
var expected = [
@@ -171,7 +171,7 @@ describe("bin/uglifyjs", function() {
"content=" + mapFile,
"includeSources",
"url=inline",
].join(","),
].join(),
].join(" ");
var child = exec(command, function(err, stdout) {
@@ -333,11 +333,13 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/invalid/simple.js";
exec(command, function(err, stdout, stderr) {
assert.ok(err);
var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/simple.js:1,12");
assert.strictEqual(lines[1], "function f(a{}");
assert.strictEqual(lines[2], " ^");
assert.strictEqual(lines[3], "ERROR: Unexpected token: punc «{», expected: punc «,»");
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/simple.js:1,12",
"function f(a{}",
" ^",
"ERROR: Unexpected token: punc «{», expected: punc «,»",
].join("\n"));
done();
});
});
@@ -345,11 +347,13 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/invalid/tab.js";
exec(command, function(err, stdout, stderr) {
assert.ok(err);
var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/tab.js:1,12");
assert.strictEqual(lines[1], "\t\tfoo(\txyz, 0abc);");
assert.strictEqual(lines[2], "\t\t \t ^");
assert.strictEqual(lines[3], "ERROR: Invalid syntax: 0abc");
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/tab.js:1,12",
"\t\tfoo(\txyz, 0abc);",
"\t\t \t ^",
"ERROR: Invalid syntax: 0abc",
].join("\n"));
done();
});
});
@@ -357,11 +361,13 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/invalid/eof.js";
exec(command, function(err, stdout, stderr) {
assert.ok(err);
var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/eof.js:2,0");
assert.strictEqual(lines[1], "foo, bar(");
assert.strictEqual(lines[2], " ^");
assert.strictEqual(lines[3], "ERROR: Unexpected token: eof");
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/eof.js:2,0",
"foo, bar(",
" ^",
"ERROR: Unexpected token: eof",
].join("\n"));
done();
});
});
@@ -369,11 +375,13 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/invalid/loop-no-body.js";
exec(command, function(err, stdout, stderr) {
assert.ok(err);
var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/loop-no-body.js:2,0");
assert.strictEqual(lines[1], "for (var i = 0; i < 1; i++) ");
assert.strictEqual(lines[2], " ^");
assert.strictEqual(lines[3], "ERROR: Unexpected token: eof");
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/loop-no-body.js:2,0",
"for (var i = 0; i < 1; i++) ",
" ^",
"ERROR: Unexpected token: eof",
].join("\n"));
done();
});
});
@@ -386,7 +394,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/assign_1.js:1,18",
"console.log(1 || 5--);",
" ^",
"ERROR: Invalid use of -- operator"
"ERROR: Invalid use of -- operator",
].join("\n"));
done();
});
@@ -400,7 +408,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/assign_2.js:1,32",
"console.log(2 || (Math.random() /= 2));",
" ^",
"ERROR: Invalid assignment"
"ERROR: Invalid assignment",
].join("\n"));
done();
});
@@ -414,7 +422,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/assign_3.js:1,17",
"console.log(3 || ++this);",
" ^",
"ERROR: Invalid use of ++ operator"
"ERROR: Invalid use of ++ operator",
].join("\n"));
done();
});
@@ -428,7 +436,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/assign_4.js:1,0",
"++null",
"^",
"ERROR: Invalid use of ++ operator"
"ERROR: Invalid use of ++ operator",
].join("\n"));
done();
});
@@ -442,7 +450,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/dot_1.js:1,2",
"a.=",
" ^",
"ERROR: Unexpected token: operator «=», expected: name"
"ERROR: Unexpected token: operator «=», expected: name",
].join("\n"));
done();
});
@@ -456,7 +464,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/dot_2.js:1,0",
"%.a;",
"^",
"ERROR: Unexpected token: operator «%»"
"ERROR: Unexpected token: operator «%»",
].join("\n"));
done();
});
@@ -470,7 +478,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/dot_3.js:1,2",
"a./();",
" ^",
"ERROR: Unexpected token: operator «/», expected: name"
"ERROR: Unexpected token: operator «/», expected: name",
].join("\n"));
done();
});
@@ -484,7 +492,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/object.js:1,13",
"console.log({%: 1});",
" ^",
"ERROR: Unexpected token: operator «%»"
"ERROR: Unexpected token: operator «%»",
].join("\n"));
done();
});
@@ -498,7 +506,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/delete.js:13,11",
" delete x;",
" ^",
"ERROR: Calling delete on expression not allowed in strict mode"
"ERROR: Calling delete on expression not allowed in strict mode",
].join("\n"));
done();
});
@@ -512,7 +520,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/function_1.js:4,11",
"function g(arguments) {",
" ^",
"ERROR: Unexpected arguments in strict mode"
"ERROR: Unexpected arguments in strict mode",
].join("\n"));
done();
});
@@ -526,7 +534,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/function_2.js:4,9",
"function eval() {",
" ^",
"ERROR: Unexpected eval in strict mode"
"ERROR: Unexpected eval in strict mode",
].join("\n"));
done();
});
@@ -540,7 +548,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/function_3.js:4,10",
"!function arguments() {",
" ^",
"ERROR: Unexpected arguments in strict mode"
"ERROR: Unexpected arguments in strict mode",
].join("\n"));
done();
});
@@ -554,7 +562,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/try.js:7,18",
" try {} catch (eval) {}",
" ^",
"ERROR: Unexpected eval in strict mode"
"ERROR: Unexpected eval in strict mode",
].join("\n"));
done();
});
@@ -568,7 +576,21 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/var.js:7,8",
" var eval;",
" ^",
"ERROR: Unexpected eval in strict mode"
"ERROR: Unexpected eval in strict mode",
].join("\n"));
done();
});
});
it("Should throw syntax error (var { eval })", function(done) {
var command = uglifyjscmd + " test/input/invalid/destructured_var.js";
exec(command, function(err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/destructured_var.js:7,10",
" var { eval } = 42;",
" ^",
"ERROR: Unexpected eval in strict mode",
].join("\n"));
done();
});
@@ -582,7 +604,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/else.js:1,7",
"if (0) else 1;",
" ^",
"ERROR: Unexpected token: keyword «else»"
"ERROR: Unexpected token: keyword «else»",
].join("\n"));
done();
});
@@ -596,7 +618,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/return.js:1,0",
"return 42;",
"^",
"ERROR: 'return' outside of function"
"ERROR: 'return' outside of function",
].join("\n"));
done();
});
@@ -610,7 +632,7 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/for-in_1.js:2,5",
"for (1, 2, a in b) {",
" ^",
"ERROR: Invalid left-hand side in for..in loop"
"ERROR: Invalid left-hand side in for..in/of loop",
].join("\n"));
done();
});
@@ -624,7 +646,35 @@ describe("bin/uglifyjs", function() {
"Parse error at test/input/invalid/for-in_2.js:2,5",
"for (var a, b in c) {",
" ^",
"ERROR: Only one variable declaration allowed in for..in loop"
"ERROR: Only one variable declaration allowed in for..in/of loop",
].join("\n"));
done();
});
});
it("Should throw syntax error (for-of init)", function(done) {
var command = uglifyjscmd + " test/input/invalid/for-of_1.js";
exec(command, function(err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/for-of_1.js:2,5",
"for (b = 2 of a)",
" ^",
"ERROR: Invalid left-hand side in for..in/of loop",
].join("\n"));
done();
});
});
it("Should throw syntax error (for-of var)", function(done) {
var command = uglifyjscmd + " test/input/invalid/for-of_2.js";
exec(command, function(err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/for-of_2.js:2,13",
"for (var b = 2 of a)",
" ^",
"ERROR: No initializers allowed in for..of loop",
].join("\n"));
done();
});
@@ -633,11 +683,13 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/invalid/switch.js";
exec(command, function(err, stdout, stderr) {
assert.ok(err);
var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/switch.js:3,2");
assert.strictEqual(lines[1], " default:");
assert.strictEqual(lines[2], " ^");
assert.strictEqual(lines[3], "ERROR: More than one default clause in switch statement");
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/switch.js:3,2",
" default:",
" ^",
"ERROR: More than one default clause in switch statement",
].join("\n"));
done();
});
});

View File

@@ -259,7 +259,7 @@ describe("comments", function() {
assert.strictEqual(result.code, code);
});
it("Should handle comments around parenthesis correctly", function() {
it("Should handle comments around parentheses correctly", function() {
var code = [
"a();",
"/* foo */",

71
test/mocha/exports.js Normal file
View File

@@ -0,0 +1,71 @@
var assert = require("assert");
var UglifyJS = require("../node");
describe("export", function() {
it("Should reject invalid `export ...` statement syntax", function() {
[
"export *;",
"export A;",
"export 42;",
"export var;",
"export * as A;",
"export A as B;",
"export const A;",
"export function(){};",
].forEach(function(code) {
assert.throws(function() {
UglifyJS.parse(code);
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error;
}, code);
});
});
it("Should reject invalid `export { ... }` statement syntax", function() {
[
"export { * };",
"export { * as A };",
"export { 42 as A };",
"export { A as B-C };",
"export { default as A };",
].forEach(function(code) {
assert.throws(function() {
UglifyJS.parse(code);
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error;
}, code);
});
});
it("Should reject invalid `export default ...` statement syntax", function() {
[
"export default *;",
"export default var;",
"export default A as B;",
].forEach(function(code) {
assert.throws(function() {
UglifyJS.parse(code);
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error;
}, code);
});
});
it("Should reject invalid `export ... from ...` statement syntax", function() {
[
"export from 'path';",
"export * from `path`;",
"export A as B from 'path';",
"export default from 'path';",
"export { A }, B from 'path';",
"export * as A, B from 'path';",
"export * as A, {} from 'path';",
"export { * as A } from 'path';",
"export { 42 as A } from 'path';",
"export { A-B as C } from 'path';",
].forEach(function(code) {
assert.throws(function() {
UglifyJS.parse(code);
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error;
}, code);
});
});
});

View File

@@ -3,7 +3,7 @@ var UglifyJS = require("../node");
describe("Getters and setters", function() {
it("Should not accept operator symbols as getter/setter name", function() {
var illegalOperators = [
[
"++",
"--",
"+",
@@ -42,43 +42,26 @@ describe("Getters and setters", function() {
"&=",
"&&",
"||"
];
var generator = function() {
var results = [];
for (var i in illegalOperators) {
results.push({
code: "var obj = { get " + illegalOperators[i] + "() { return test; }};",
operator: illegalOperators[i],
method: "get"
});
results.push({
code: "var obj = { set " + illegalOperators[i] + "(value) { test = value}};",
operator: illegalOperators[i],
method: "set"
});
}
return results;
};
var testCase = function(data) {
return function() {
UglifyJS.parse(data.code);
};
};
var fail = function(data) {
return function(e) {
].reduce(function(tests, illegalOperator) {
tests.push({
code: "var obj = { get " + illegalOperator + "() { return test; }};",
operator: illegalOperator,
});
tests.push({
code: "var obj = { set " + illegalOperator + "(value) { test = value; }};",
operator: illegalOperator,
});
return tests;
}, []).forEach(function(test) {
assert.throws(function() {
UglifyJS.parse(test.code);
}, test.operator == "=" ? function(e) {
return e instanceof UglifyJS.JS_Parse_Error
&& e.message === "Unexpected token: operator «" + data.operator + "»";
};
};
var errorMessage = function(data) {
return "Expected but didn't get a syntax error while parsing following line:\n" + data.code;
};
var tests = generator();
for (var i = 0; i < tests.length; i++) {
var test = tests[i];
assert.throws(testCase(test), fail(test), errorMessage(test));
}
&& /^Unexpected token: punc «{», expected: punc «.*?»$/.test(e.message);
} : function(e) {
return e instanceof UglifyJS.JS_Parse_Error
&& e.message === "Unexpected token: operator «" + test.operator + "»";
}, "Expected but didn't get a syntax error while parsing following line:\n" + test.code);
});
});
});

28
test/mocha/imports.js Normal file
View File

@@ -0,0 +1,28 @@
var assert = require("assert");
var UglifyJS = require("../node");
describe("import", function() {
it("Should reject invalid `import` statement syntax", function() {
[
"import *;",
"import A;",
"import {};",
"import `path`;",
"import from 'path';",
"import * from 'path';",
"import A as B from 'path';",
"import { A }, B from 'path';",
"import * as A, B from 'path';",
"import * as A, {} from 'path';",
"import { * as A } from 'path';",
"import { 42 as A } from 'path';",
"import { A-B as C } from 'path';",
].forEach(function(code) {
assert.throws(function() {
UglifyJS.parse(code);
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error;
}, code);
});
});
});

View File

@@ -28,4 +28,74 @@ describe("Number literals", function() {
assert.throws(test(inputs[i]), error, inputs[i]);
}
});
it("Should parse binary, hexadecimal, octal and underscore correctly", function() {
[
"42",
"4_2",
"052",
"0o52",
"0O52",
"0o5_2",
"0x2a",
"0X2A",
"0x2_a",
"0b101010",
"0B101010",
"0b101_010",
"0.0000000042e+10",
"0.0000000042E+10",
"0.0_000000042e+10",
"0.0000000042e+1_0",
"0.000_000_004_2e+1_0",
"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,
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, "42;");
});
});
it("Should reject invalid use of underscore", function() {
[
"_42",
"_+42",
"+_42",
].forEach(function(code) {
var node = UglifyJS.parse(code, {
expression: true,
});
assert.ok(!node.is_constant(), code);
assert.ok(!(node instanceof UglifyJS.AST_Statement), code);
});
[
"42_",
"4__2",
"0_52",
"05_2",
"0_o52",
"0o_52",
"0.0000000042_e10",
"0.0000000042e_10",
"0.0000000042e_+10",
"0.0000000042e+_10",
].forEach(function(code) {
assert.throws(function() {
UglifyJS.parse(code);
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error;
}, code);
});
});
it("Should reject invalid syntax under expression=true", function() {
assert.throws(function() {
UglifyJS.parse("42.g", {
expression: true,
});
}, function(e) {
return e instanceof UglifyJS.JS_Parse_Error;
});
});
});

View File

@@ -84,7 +84,7 @@ describe("parentheses", function() {
}
});
it("Should compress leading parenthesis with reasonable performance", function() {
it("Should compress leading parentheses with reasonable performance", function() {
this.timeout(30000);
var code = [
"({}?0:1)&&x();",

View File

@@ -37,8 +37,7 @@ describe("test/reduce.js", function() {
it("Should retain setter arguments", function() {
var result = reduce_test(read("test/input/reduce/setter.js"), {
compress: {
keep_fargs: false,
unsafe: true,
unsafe_math: true,
},
mangle: false,
}, {
@@ -110,28 +109,24 @@ describe("test/reduce.js", function() {
});
it("Should print correct output for irreducible test case", function() {
var result = reduce_test([
"console.log(function f(a) {",
" return f.length;",
"}());",
"console.log(1 + .1 + .1);",
].join("\n"), {
compress: {
keep_fargs: false,
unsafe_math: true,
},
mangle: false,
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"// (beautified)",
"console.log(function f(a) {",
" return f.length;",
"}());",
"// output: 1",
"console.log(1 + .1 + .1);",
"// output: 1.2000000000000002",
"// ",
"// minify: 0",
"// minify: 1.2",
"// ",
"// options: {",
'// "compress": {',
'// "keep_fargs": false',
'// "unsafe_math": true',
"// },",
'// "mangle": false',
"// }",
@@ -299,12 +294,45 @@ describe("test/reduce.js", function() {
"// }",
]).join("\n"));
});
it("Should maintain block-scope for const/let", function() {
if (semver.satisfies(process.version, "<4")) return;
this.timeout(120000);
var code = [
'"use strict";',
"",
"L: for (let a = (1 - .8).toString(); ;) {",
" if (!console.log(a)) {",
" break L;",
" }",
"}",
].join("\n");
var result = reduce_test(code, {
compress: {
unsafe_math: true,
},
mangle: false,
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"// (beautified)",
code,
"// output: 0.19999999999999996",
"// ",
"// minify: 0.2",
"// ",
"// options: {",
'// "compress": {',
'// "unsafe_math": true',
'// },',
'// "mangle": false',
"// }",
].join("\n"));
});
it("Should handle corner cases when intermediate case differs only in Error.message", function() {
if (semver.satisfies(process.version, "<=0.10")) return;
var result = reduce_test(read("test/input/reduce/diff_error.js"), {
compress: {
keep_fargs: false,
unsafe: true,
unsafe_math: true,
},
mangle: false,
}, {
@@ -313,4 +341,24 @@ describe("test/reduce.js", function() {
if (result.error) throw result.error;
assert.strictEqual(result.code, read("test/input/reduce/diff_error.reduced.js"));
});
it("Should maintain valid LHS in destructuring assignments", function() {
if (semver.satisfies(process.version, "<6")) return;
var result = reduce_test(read("test/input/reduce/destructured_assign.js"), {
compress: {
unsafe_math: true,
},
mangle: false,
validate: true,
});
if (result.error) throw result.error;
assert.strictEqual(result.code, read("test/input/reduce/destructured_assign.reduced.js"));
});
it("Should handle destructured catch expressions", function() {
if (semver.satisfies(process.version, "<6")) return;
var result = reduce_test(read("test/input/reduce/destructured_catch.js"), {
mangle: false,
});
if (result.error) throw result.error;
assert.strictEqual(result.code, read("test/input/reduce/destructured_catch.reduced.js"));
});
});

View File

@@ -244,6 +244,39 @@ describe("sourcemaps", function() {
assert.strictEqual(result.code, '(function(){console.log("hello")}).call(this);');
assert.strictEqual(result.map, '{"version":3,"sources":["main.coffee"],"names":["console","log"],"mappings":"CAAA,WAAAA,QAAQC,IAAI"}');
});
it("Should not overwrite existing sourcesContent", function() {
var result = UglifyJS.minify({
"in.js": [
'"use strict";',
"",
"var _window$foo = window.foo,",
" a = _window$foo[0],",
" b = _window$foo[1];",
].join("\n"),
}, {
compress: false,
mangle: false,
sourceMap: {
content: {
version: 3,
sources: [ "in.js" ],
names: [
"window",
"foo",
"a",
"b",
],
mappings: ";;kBAAaA,MAAM,CAACC,G;IAAfC,C;IAAGC,C",
file: "in.js",
sourcesContent: [ "let [a, b] = window.foo;\n" ],
},
includeSources: true,
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, '"use strict";var _window$foo=window.foo,a=_window$foo[0],b=_window$foo[1];');
assert.strictEqual(result.map, '{"version":3,"sources":["in.js"],"sourcesContent":["let [a, b] = window.foo;\\n"],"names":["window","foo","a","b"],"mappings":"6BAAaA,OAAOC,IAAfC,E,eAAGC,E"}');
});
});
describe("sourceMapInline", function() {

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