Compare commits

..

134 Commits

Author SHA1 Message Date
alexlamsl
0934c0e431 v3.18.0 2024-06-10 03:01:35 +03:00
Alex Lam S.L
ca4185a0fd improve ESTree compatibility (#5836)
closes #5834
closes #5835
2024-06-10 01:37:24 +03:00
Alex Lam S.L
e7b9b4aafb workaround function declaration quirks in ES6+ (#5833)
fixes #1666
2024-06-09 00:57:15 +03:00
Alex Lam S.L
3dfb379486 fix corner case in join_vars (#5832)
fixes #5831
2024-06-08 20:15:50 +03:00
Alex Lam S.L
2cb6454b1f fix corner case in merge_vars (#5830)
fixes #5829
2024-06-08 20:15:37 +03:00
Alex Lam S.L
09910771a1 fix corner case in awaits (#5828)
fixes #5791
2024-06-06 04:51:02 +03:00
Alex Lam S.L
c21a8eee7b include Node.js v20 in CI tests (#5827) 2024-06-05 23:49:20 +03:00
Alex Lam S.L
34b6143306 fix scope assignment to switch expressions (#5826)
fixes #5787
fixes #5792
2024-06-05 22:05:16 +03:00
Alex Lam S.L
ffe0fe7762 enhance join_vars (#5824)
closes #5790
2024-06-05 13:46:11 +03:00
forgotPassword
aa7c3389e6 domprops: enableHighAccuracy, maximumAge (#5822) 2024-06-05 04:17:30 +03:00
Alex Lam S.L
30fd331bf1 workaround node & npm issues (#5825)
- upgrade GitHub Actions dependencies
- workaround `sucrase` issues
2024-06-05 03:55:16 +03:00
Alex Lam S.L
f0ca9cfbe6 fix corner case in collapse_vars (#5780)
fixes #5779
2023-01-16 21:30:59 +08:00
Alex Lam S.L
a437a61518 fix corner case in reduce_vars (#5778)
fixes #5777
2023-01-16 21:30:45 +08:00
Alex Lam S.L
57dd3f6a2c fix corner case in evaluate (#5775)
fixes #5774
2023-01-07 20:38:04 +08:00
Alex Lam S.L
f07dc5cfba fix corner case in merge_vars (#5773)
fixes #5772
2023-01-07 18:27:18 +08:00
Alex Lam S.L
358faaacaa fix corner case in merge_vars (#5771)
fixes #5770
2023-01-04 13:17:04 +08:00
Alex Lam S.L
c9117041fa fix corner case in functions & inline (#5767)
fixes #5766
2022-12-27 08:59:16 +08:00
Alex Lam S.L
f2b6f1def0 improve --reduce-test (#5763) 2022-12-13 10:07:15 +08:00
Alex Lam S.L
797184f587 improve CLI interoperability (#5762) 2022-12-11 13:25:06 +08:00
Alex Lam S.L
78242ff21d minor lints (#5761) 2022-12-09 05:55:57 +08:00
Alex Lam S.L
dd88f3866b fix corner case in inline (#5760)
fixes #5759
2022-12-07 11:40:12 +08:00
Alex Lam S.L
17c3ae6cba improve usability (#5758) 2022-12-04 09:10:32 +08:00
Alex Lam S.L
0cbd5ea64a fix corner case in join_vars & loops (#5757)
fixes #5756
2022-12-03 11:44:37 +08:00
Alex Lam S.L
404794f5db fix corner case in if_return (#5755)
fixes #5754
2022-12-02 11:05:36 +08:00
Alex Lam S.L
650e63c8aa improve usability (#5753) 2022-12-02 10:14:07 +08:00
Alex Lam S.L
59e385591c improve interoperability of custom Errors (#5752)
closes #5751
2022-12-02 03:54:00 +08:00
Alex Lam S.L
574ca47666 fix corner case in yields (#5750)
fixes #5749
2022-12-01 05:18:04 +08:00
Alex Lam S.L
548f0938e8 fix corner case in collapse_vars (#5748)
fixes #5747
2022-12-01 03:59:22 +08:00
Alex Lam S.L
2352909c3d fix corner case in join_vars (#5746)
fixes #5745
2022-11-23 21:49:30 +08:00
Alex Lam S.L
4e7744af2d minor lints (#5744) 2022-11-23 07:26:35 +08:00
Alex Lam S.L
aef7065262 fix corner case in inline (#5742)
fixes #5741
2022-11-23 07:26:08 +08:00
Alex Lam S.L
24c3db11e6 minor lints (#5740) 2022-11-23 05:08:42 +08:00
Alex Lam S.L
e5cbd3e0f3 enhance join_vars (#5739) 2022-11-23 01:57:16 +08:00
Alex Lam S.L
68d62a8a31 enable --module by default (#5738)
- fix corner case in `mangle`
2022-11-22 02:25:34 +08:00
Alex Lam S.L
21aff996a5 enhance varify (#5737) 2022-11-21 11:30:02 +08:00
Alex Lam S.L
1d400f1a25 fix corner case in inline (#5736)
fixes #5735
2022-11-14 10:35:26 +08:00
Alex Lam S.L
7f424a55c5 suppress false positives in ufuzz (#5734) 2022-11-14 10:34:43 +08:00
Alex Lam S.L
e37a1489d4 fix corner case in reduce_vars (#5731)
fixes #5730
2022-11-03 13:05:07 +08:00
Alex Lam S.L
2b1c321ac8 fix corner case in evaluate (#5729)
fixes #5728
2022-11-03 12:25:48 +08:00
Alex Lam S.L
8d28052182 fix corner cases in evaluate & side_effects (#5726) 2022-11-01 09:38:33 +08:00
Alex Lam S.L
f40dbd6e33 fix corner case in inline & unused (#5725)
fixes #5724
2022-10-29 10:53:30 +08:00
Alex Lam S.L
7270671687 fix corner case in conditionals (#5723)
fixes #5722
2022-10-29 00:17:59 +08:00
Alex Lam S.L
30bf068768 fix corner case in collapse_vars (#5720)
fixes #5719
2022-10-24 22:16:06 +08:00
Alex Lam S.L
fb1bff2c0a v3.17.4 2022-10-24 01:46:19 +08:00
Alex Lam S.L
19c471c16a fix corner cases in reduce_vars (#5717)
fixes #5716
2022-10-19 23:22:19 +08:00
Alex Lam S.L
8319badea8 fix corner case in merge_vars (#5715)
fixes #5714
2022-10-17 11:19:43 +08:00
Alex Lam S.L
5a5200d657 fix corner case in conditionals (#5713)
fixes #5712
2022-10-14 23:55:08 +08:00
Alex Lam S.L
5411360829 fix corner case in if_return (#5711)
fixes #5710
2022-10-13 22:34:55 +01:00
Alex Lam S.L
7edd10e5e5 fix corner case in unused (#5708)
fixes #5707
2022-10-10 21:45:57 +08:00
Alex Lam S.L
bccb1c3bd9 fix corner case in unused (#5706)
fixes #5705
2022-10-10 08:02:23 +08:00
Alex Lam S.L
ed7051b9bb enhance side_effects & strings (#5704) 2022-10-10 08:01:40 +08:00
Alex Lam S.L
a391897388 enhance conditionals (#5703) 2022-10-08 09:59:33 +08:00
Alex Lam S.L
4a1da492dd v3.17.3 2022-10-06 02:14:42 +08:00
Alex Lam S.L
94a954c3d1 minor clean-ups (#5701) 2022-10-06 02:06:21 +08:00
Alex Lam S.L
be8ccc3ab5 fix corner case in varify (#5698)
fixes #5697
2022-10-04 16:03:24 +08:00
Alex Lam S.L
58d997a3d6 fix corner case in booleans & conditionals (#5696) 2022-10-04 12:58:55 +08:00
Alex Lam S.L
dabcc39b51 fix corner cases in booleans & conditionals (#5695)
fixes #5694
2022-10-03 22:47:15 +08:00
Alex Lam S.L
140e4e0da8 fix corner case in inline (#5693)
fixes #5692
2022-10-03 08:01:56 +08:00
Alex Lam S.L
80fc862547 enhance assignments, booleans & conditionals (#5691) 2022-10-03 08:01:23 +08:00
Alex Lam S.L
6cdc035b2f fix corner case in if_return (#5689)
fixes #5688
2022-09-30 06:49:51 +08:00
Alex Lam S.L
e1e3516397 fix corner case in reduce_vars (#5687) 2022-09-30 02:00:37 +08:00
Alex Lam S.L
bd5fc4cb1b implement mangle.properties.domprops (#5686)
- support destructuring syntax
- fix corner case with comma operator
2022-09-29 12:18:04 +08:00
Alex Lam S.L
a570c00251 fix corner case in conditionals & if_return (#5685)
fixes #5684
2022-09-28 00:04:32 +08:00
Alex Lam S.L
3fa2086681 improve usability of mangle.properties (#5683)
fixes #5682
2022-09-27 13:52:58 +08:00
Alex Lam S.L
8e65413b99 fix corner cases in conditionals & if_return (#5680)
fixes #5679
2022-09-27 01:28:03 +08:00
Alex Lam S.L
8ca40070a4 workaround GitHub Actions quirks (#5678) 2022-09-27 00:16:40 +08:00
Alex Lam S.L
f9b811ce83 v3.17.2 2022-09-26 00:12:51 +08:00
Alex Lam S.L
9ac3879b06 fix corner case in conditionals (#5676) 2022-09-23 11:09:55 +08:00
Alex Lam S.L
37d3e4feaa fix corner case in if_return (#5675) 2022-09-22 23:27:06 +08:00
Alex Lam S.L
43ec350cd2 fix corner case in conditionals (#5674)
fixes #5673
2022-09-22 10:58:44 +08:00
Alex Lam S.L
63b04a687a minor tweaks (#5672) 2022-09-21 23:11:46 +08:00
Alex Lam S.L
9efa02afb6 fix corner case in assignments (#5671)
fixes #5670
2022-09-21 07:56:16 +08:00
Alex Lam S.L
3a6e58109e v3.17.1 2022-09-20 04:13:28 +08:00
Alex Lam S.L
5ac6ec5496 improve usability of --mangle-props (#5669) 2022-09-18 09:37:06 +08:00
Alex Lam S.L
eb22f0101e fix corner case in unused (#5668)
fixes #5663
2022-09-17 13:32:41 +08:00
Alex Lam S.L
e4bff315eb fix corner case in conditionals (#5667)
fixes #5666
2022-09-17 10:42:32 +08:00
Alex Lam S.L
001f6f9719 fix corner case in inline (#5664)
fixes #5662
2022-09-17 08:54:54 +08:00
Alex Lam S.L
e0b302d651 fix corner case in merge_vars (#5661)
fixes #5660
2022-09-14 23:36:54 +08:00
Alex Lam S.L
fa2511f71c tweak ufuzz job scheduling (#5659) 2022-09-11 04:05:21 +08:00
Alex Lam S.L
edf1bf1106 enhance varify (#5658) 2022-09-11 03:28:54 +08:00
Alex Lam S.L
88dfc49683 fix corner case in merge_vars (#5657)
fixes #5656
2022-09-10 04:14:33 +08:00
Alex Lam S.L
9dec612cd5 enhance inline (#5655)
- improve fix for #5653
2022-09-09 04:07:47 +08:00
Alex Lam S.L
02d966d914 fix corner case in hoist_props (#5654)
fixes #5653
2022-09-08 10:55:59 +08:00
Alex Lam S.L
5b5f6e329c fix corner case in ie (#5652)
fixes #5651
2022-09-08 10:49:40 +08:00
Alex Lam S.L
4e4a2f8ed3 fix corner case in if_return (#5650)
fixes #5649
2022-09-08 10:49:05 +08:00
Alex Lam S.L
32bd65a87f support ExtendScript parser quirks (#5648)
closes #1144
2022-09-07 02:28:34 +08:00
Alex Lam S.L
318206d41d suppress false positives in ufuzz (#5647) 2022-09-06 01:33:22 +08:00
Alex Lam S.L
535212c69e allow glob-style input for --in-situ (#5646)
closes #5645
2022-09-05 22:54:35 +08:00
Alex Lam S.L
1d42e9ad55 fix corner case in collapse_vars (#5644)
fixes #5643
2022-09-04 10:10:31 +08:00
Alex Lam S.L
78f354beb8 fix corner case in dead_code (#5642)
fixes #5641
2022-09-04 06:18:25 +08:00
Alex Lam S.L
e012f046bc tweak test cases (#5640) 2022-08-31 12:16:42 +08:00
Alex Lam S.L
f63b7b079d fix corner case in collapse_vars (#5639)
fixes #5638
2022-08-31 08:44:04 +08:00
Alex Lam S.L
d530f9332c enhance awaits (#5637) 2022-08-31 02:51:42 +08:00
Alex Lam S.L
10bc86ba10 enhance reduce_vars (#5636) 2022-08-30 16:00:43 +08:00
Alex Lam S.L
15b608f74c fix corner case in inline (#5635)
fixes #5634
2022-08-30 00:45:35 +08:00
Alex Lam S.L
7c52af0dec workaround quirks from npm (#5633) 2022-08-26 20:08:04 +08:00
Alex Lam S.L
cd97237c59 workaround quirks from GitHub Actions (#5632) 2022-08-26 15:16:03 +08:00
Alex Lam S.L
965e9767e5 workaround quirks from Node.js (#5631) 2022-08-26 06:25:44 +08:00
Alex Lam S.L
41a7000745 workaround quirks from GitHub Actions (#5630) 2022-08-26 02:35:53 +08:00
Alex Lam S.L
9cdc1ef6c2 fix corner case in unused (#5629)
fixes #5628
2022-08-25 05:01:12 +08:00
Alex Lam S.L
4db81065ee fix corner case in hoist_vars (#5627)
fixes #5626
2022-08-24 00:19:47 +08:00
Alex Lam S.L
4653e8aec0 improve diagnostics on top_retain & mangle.properties (#5622)
closes #5618
2022-08-19 02:32:21 +08:00
Alex Lam S.L
ac002b6338 fix corner case in reduce_vars (#5624)
fixes #5623
2022-08-19 02:31:48 +08:00
Alex Lam S.L
9eea3a673a provide diagnostic details on --mangle-props (#5621)
closes #5618
2022-08-17 22:22:30 +08:00
Alex Lam S.L
d6d2f5ced2 enhance reduce_vars (#5616)
closes #5614
2022-08-17 09:25:59 +08:00
Alex Lam S.L
887e086890 fix corner case in if_return (#5620)
fixes #5619
2022-08-17 09:10:33 +08:00
Alex Lam S.L
8602d1ba17 v3.17.0 2022-08-17 03:45:32 +08:00
Alex Lam S.L
dd90135944 fix corner case in pure_getters (#5617) 2022-08-14 02:54:06 +08:00
Alex Lam S.L
612701a706 tweak ufuzz test case generation (#5615) 2022-08-12 03:55:54 +08:00
Alex Lam S.L
503532cf77 workaround sporadic I/O lags in GitHub Actions (#5613) 2022-08-10 07:36:14 +08:00
Alex Lam S.L
6c0e522922 workaround sporadic I/O lags in GitHub Actions (#5612) 2022-08-10 04:33:32 +08:00
Alex Lam S.L
9d37276986 tweak ufuzz test case generation (#5611) 2022-08-10 00:20:20 +08:00
Alex Lam S.L
5a4cd09938 enhance inline (#5610) 2022-08-09 22:54:29 +08:00
Alex Lam S.L
c32fe26b8d fix corner case in merge_vars (#5609) 2022-08-09 10:18:11 +08:00
Alex Lam S.L
2c3c4ec323 improve source mapping accuracy (#5608) 2022-08-09 02:02:43 +08:00
Alex Lam S.L
f451a7ad79 implement --expression (#5607) 2022-08-08 03:42:18 +08:00
Alex Lam S.L
07953b36b0 update dependencies (#5605) 2022-08-06 13:16:47 +08:00
Alex Lam S.L
387c69b194 minor clean-ups (#5604) 2022-08-06 10:45:44 +08:00
Alex Lam S.L
a9d9af53e9 fix corner case in if_return (#5603)
fixes #5602
2022-08-06 07:56:20 +08:00
Alex Lam S.L
8a07f1202c expand builtins exclusions (#5601)
closes #5600
2022-08-05 13:37:02 +08:00
Alex Lam S.L
41b65af6e2 fix corner cases with static modifier (#5599) 2022-08-05 02:48:21 +08:00
Alex Lam S.L
884842cd6c fix corner case in if_return (#5598)
fixes #5597
2022-08-04 06:50:51 +08:00
Alex Lam S.L
8076d66ae5 fix corner case in if_return (#5596)
fixes #5595
2022-08-03 20:07:55 +08:00
Alex Lam S.L
64e3ceec3b enhance if_return (#5594) 2022-08-03 07:37:31 +08:00
Alex Lam S.L
672cdfa57a enhance conditionals (#5593) 2022-08-02 19:01:57 +08:00
Alex Lam S.L
e39f33e41b fix corner cases in if_return (#5590)
fixes #5589
fixes #5591
fixes #5592
2022-07-31 02:45:52 +08:00
Alex Lam S.L
6667440aaf enhance if_return (#5588)
fixes #5587
2022-07-30 20:53:46 +08:00
Alex Lam S.L
ab5c7e6863 fix corner cases in if_return (#5585)
fixes #5583
fixes #5584
fixes #5586
2022-07-30 16:07:19 +08:00
Alex Lam S.L
08c386f363 enhance if_return (#5582) 2022-07-30 05:25:17 +08:00
Alex Lam S.L
937a672879 fix corner case in mangle (#5581)
fixes #5580
2022-07-29 03:04:10 +08:00
Alex Lam S.L
513995f57d fix corner case in inline & reduce_vars (#5579) 2022-07-28 23:53:11 +08:00
Alex Lam S.L
db6fd6db3e enhance side_effects (#5578) 2022-07-28 04:06:11 +08:00
Alex Lam S.L
da930affd2 fix corner case in inline (#5577)
fixes #5576
2022-07-26 10:46:54 +08:00
Alex Lam S.L
996836b67e enhance conditionals (#5575) 2022-07-26 01:49:45 +08:00
100 changed files with 9397 additions and 1529 deletions

View File

@@ -9,11 +9,11 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
options: options:
- '-mb braces'
- '--ie -c' - '--ie -c'
- '-mc' - '-mb braces'
- '-p acorn --toplevel -mco spidermonkey' - '--toplevel -mc'
- '--toplevel -mc passes=3,pure_getters,unsafe' - '-p acorn -mco spidermonkey'
- '-mc passes=3,pure_getters,unsafe'
script: script:
- acorn.sh - acorn.sh
- bootstrap.sh - bootstrap.sh
@@ -50,7 +50,7 @@ jobs:
OPTIONS: ${{ matrix.options }} OPTIONS: ${{ matrix.options }}
SCRIPT: ${{ matrix.script }} SCRIPT: ${{ matrix.script }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: Perform uglify, build & test - name: Perform uglify, build & test
shell: bash shell: bash
run: | run: |

View File

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

18
.github/workflows/moz.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: ESTree
on:
pull_request:
push:
branches: [ master ]
jobs:
test:
name: fuzzing
runs-on: ubuntu-latest
env:
NODE: latest
steps:
- uses: actions/checkout@v4
- name: Perform tests
shell: bash
run: |
. ./test/release/install.sh
node test/mozilla-ast.js 5000

View File

@@ -32,7 +32,7 @@ jobs:
env: env:
NODE: ${{ matrix.node }} NODE: ${{ matrix.node }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: Perform fuzzing - name: Perform fuzzing
shell: bash shell: bash
run: | run: |

View File

@@ -3,7 +3,7 @@ Contributing
## Documentation ## Documentation
Every new feature and API change should be accompanied by a README additon. Every new feature and API change should be accompanied by a README addition.
## Testing ## Testing

View File

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

View File

@@ -54,8 +54,6 @@ a double dash to prevent input files being used as option arguments:
modules and Userscripts that may modules and Userscripts that may
be anonymous function wrapped (IIFE) be anonymous function wrapped (IIFE)
by the .user.js engine `caller`. by the .user.js engine `caller`.
`expression` Parse a single expression, rather than
a program (for parsing JSON).
`spidermonkey` Assume input files are SpiderMonkey `spidermonkey` Assume input files are SpiderMonkey
AST format (as JSON). AST format (as JSON).
-c, --compress [options] Enable compressor/specify compressor options: -c, --compress [options] Enable compressor/specify compressor options:
@@ -111,6 +109,8 @@ a double dash to prevent input files being used as option arguments:
-d, --define <expr>[=value] Global definitions. -d, --define <expr>[=value] Global definitions.
-e, --enclose [arg[:value]] Embed everything in a big function, with configurable -e, --enclose [arg[:value]] Embed everything in a big function, with configurable
argument(s) & value(s). argument(s) & value(s).
--expression Parse a single expression, rather than a program
(for parsing JSON).
--ie Support non-standard Internet Explorer. --ie Support non-standard Internet Explorer.
Equivalent to setting `ie: true` in `minify()` Equivalent to setting `ie: true` in `minify()`
for `compress`, `mangle` and `output` options. for `compress`, `mangle` and `output` options.
@@ -119,6 +119,8 @@ a double dash to prevent input files being used as option arguments:
--keep-fnames Do not mangle/drop function names. Useful for --keep-fnames Do not mangle/drop function names. Useful for
code relying on Function.prototype.name. code relying on Function.prototype.name.
--module Process input as ES module (implies --toplevel) --module Process input as ES module (implies --toplevel)
--no-module Avoid optimizations which may alter runtime behavior
under prior versions of JavaScript.
--name-cache <file> File to hold mangled name mappings. --name-cache <file> File to hold mangled name mappings.
--self Build UglifyJS as a library (implies --wrap UglifyJS) --self Build UglifyJS as a library (implies --wrap UglifyJS)
--source-map [options] Enable source map/specify source map options: --source-map [options] Enable source map/specify source map options:
@@ -327,7 +329,7 @@ unquoted style (`o.foo`). Example:
// stuff.js // stuff.js
var o = { var o = {
"foo": 1, "foo": 1,
bar: 3 bar: 3,
}; };
o.foo += o.bar; o.foo += o.bar;
console.log(o.foo); console.log(o.foo);
@@ -339,6 +341,16 @@ $ uglifyjs stuff.js --mangle-props keep_quoted -c -m
var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo); var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);
``` ```
If the minified output will be processed again by UglifyJS, consider specifying
`keep_quoted_props` so the same property names are preserved:
```bash
$ uglifyjs stuff.js --mangle-props keep_quoted -c -m -O keep_quoted_props
```
```javascript
var o={"foo":1,o:3};o.foo+=o.o,console.log(o.foo);
```
### Debugging property name mangling ### Debugging property name mangling
You can also pass `--mangle-props debug` in order to mangle property names You can also pass `--mangle-props debug` in order to mangle property names
@@ -504,6 +516,8 @@ if (result.error) throw result.error;
- `compress` (default: `{}`) — pass `false` to skip compressing entirely. - `compress` (default: `{}`) — pass `false` to skip compressing entirely.
Pass an object to specify custom [compress options](#compress-options). Pass an object to specify custom [compress options](#compress-options).
- `expression` (default: `false`) — parse as a single expression, e.g. JSON.
- `ie` (default: `false`) — enable workarounds for Internet Explorer bugs. - `ie` (default: `false`) — enable workarounds for Internet Explorer bugs.
- `keep_fargs` (default: `false`) — pass `true` to prevent discarding or mangling - `keep_fargs` (default: `false`) — pass `true` to prevent discarding or mangling
@@ -518,9 +532,9 @@ if (result.error) throw result.error;
- `mangle.properties` (default: `false`) — a subcategory of the mangle option. - `mangle.properties` (default: `false`) — a subcategory of the mangle option.
Pass an object to specify custom [mangle property options](#mangle-properties-options). Pass an object to specify custom [mangle property options](#mangle-properties-options).
- `module` (default: `false`) — set to `true` if you wish to process input as - `module` (default: `true`) — process input as ES module, i.e. implicit
ES module, i.e. implicit `"use strict";` and support for top-level `await`, `"use strict";` and support for top-level `await`. When explicitly specified,
alongside with `toplevel` enabled. also enables `toplevel`.
- `nameCache` (default: `null`) — pass an empty object `{}` or a previously - `nameCache` (default: `null`) — pass an empty object `{}` or a previously
used `nameCache` object if you wish to cache mangled variable and used `nameCache` object if you wish to cache mangled variable and
@@ -633,10 +647,8 @@ to be `false` and all symbol names will be omitted.
- `bare_returns` (default: `false`) — support top level `return` statements - `bare_returns` (default: `false`) — support top level `return` statements
- `expression` (default: `false`) — parse as a single expression, e.g. JSON
- `html5_comments` (default: `true`) — process HTML comment as workaround for - `html5_comments` (default: `true`) — process HTML comment as workaround for
browsers which do not recognise `<script>` tags browsers which do not recognize `<script>` tags
- `module` (default: `false`) — set to `true` if you wish to process input as - `module` (default: `false`) — set to `true` if you wish to process input as
ES module, i.e. implicit `"use strict";` and support for top-level `await`. ES module, i.e. implicit `"use strict";` and support for top-level `await`.
@@ -740,10 +752,10 @@ to be `false` and all symbol names will be omitted.
- `merge_vars` (default: `true`) — combine and reuse variables. - `merge_vars` (default: `true`) — combine and reuse variables.
- `module` (default: `false`) — set to `true` if you wish to process input as - `module` (default: `false`) — set to `true` if you wish to process input as
ES module, i.e. implicit `"use strict";` alongside with `toplevel` enabled. ES module, i.e. implicit `"use strict";`.
- `negate_iife` (default: `true`) — negate "Immediately-Called Function Expressions" - `negate_iife` (default: `true`) — negate "Immediately-Called Function Expressions"
where the return value is discarded, to avoid the parens that the where the return value is discarded, to avoid the parentheses that the
code generator would insert. code generator would insert.
- `objects` (default: `true`) — compact duplicate keys in object literals. - `objects` (default: `true`) — compact duplicate keys in object literals.
@@ -841,7 +853,7 @@ to be `false` and all symbol names will be omitted.
- `unused` (default: `true`) — drop unreferenced functions and variables (simple - `unused` (default: `true`) — drop unreferenced functions and variables (simple
direct variable assignments do not count as references unless set to `"keep_assign"`) direct variable assignments do not count as references unless set to `"keep_assign"`)
- `varify` (default: `true`) — convert block-scoped declaractions into `var` - `varify` (default: `true`) — convert block-scoped declarations into `var`
whenever safe to do so whenever safe to do so
- `yields` (default: `true`) — apply optimizations to `yield` expressions - `yields` (default: `true`) — apply optimizations to `yield` expressions
@@ -881,12 +893,15 @@ UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
### Mangle properties options ### Mangle properties options
- `builtins` (default: `false`) — Use `true` to allow the mangling of builtin - `builtins` (default: `false`) — Use `true` to allow the mangling of built-in
DOM properties. Not recommended to override this setting. properties of JavaScript API. Not recommended to override this setting.
- `debug` (default: `false`) — Mangle names with the original name still present. - `debug` (default: `false`) — Mangle names with the original name still present.
Pass an empty string `""` to enable, or a non-empty string to set the debug suffix. Pass an empty string `""` to enable, or a non-empty string to set the debug suffix.
- `domprops` (default: `false`) — Use `true` to allow the mangling of properties
commonly found in Document Object Model. Not recommended to override this setting.
- `keep_fargs` (default: `false`) — Use `true` to prevent mangling of function - `keep_fargs` (default: `false`) — Use `true` to prevent mangling of function
arguments. arguments.
@@ -912,9 +927,8 @@ can pass additional arguments that control the code output:
regexps (affects directives with non-ascii characters becoming invalid) regexps (affects directives with non-ascii characters becoming invalid)
- `beautify` (default: `true`) — whether to actually beautify the output. - `beautify` (default: `true`) — whether to actually beautify the output.
Passing `-b` will set this to true, but you might need to pass `-b` even Passing `-b` will set this to true. Use `-O` if you want to generate minified
when you want to generate minified code, in order to specify additional code and specify additional arguments.
arguments, so you can use `-b beautify=false` to override it.
- `braces` (default: `false`) — always insert braces in `if`, `for`, - `braces` (default: `false`) — always insert braces in `if`, `for`,
`do`, `while` or `with` statements, even if their body is a single `do`, `while` or `with` statements, even if their body is a single
@@ -930,6 +944,9 @@ can pass additional arguments that control the code output:
} }
``` ```
- `extendscript` (default: `false`) — enable workarounds for Adobe ExtendScript
bugs
- `galio` (default: `false`) — enable workarounds for ANT Galio bugs - `galio` (default: `false`) — enable workarounds for ANT Galio bugs
- `indent_level` (default: `4`) — indent by specified number of spaces or the - `indent_level` (default: `4`) — indent by specified number of spaces or the
@@ -1446,3 +1463,17 @@ To allow for better optimizations, the compiler makes various assumptions:
// Actual: TypeError: invalid assignment to const 'f' // Actual: TypeError: invalid assignment to const 'f'
``` ```
UglifyJS may modify the input which in turn may suppress those errors. UglifyJS may modify the input which in turn may suppress those errors.
- Adobe ExtendScript will give incorrect results with the following:
```javascript
alert(true ? "PASS" : false ? "FAIL" : null);
// Expected: "PASS"
// Actual: "FAIL"
```
UglifyJS may modify the input which in turn may suppress those errors.
- Adobe ExtendScript will give incorrect results with the following:
```javascript
alert(42 ? null ? "FAIL" : "PASS" : "FAIL");
// Expected: "PASS"
// Actual: SyntaxError: Expected: :
```
UglifyJS may modify the input which in turn may suppress those errors.

View File

@@ -104,10 +104,12 @@ function process_option(name, no_value) {
" --config-file <file> Read minify() options from JSON file.", " --config-file <file> Read minify() options from JSON file.",
" -d, --define <expr>[=value] Global definitions.", " -d, --define <expr>[=value] Global definitions.",
" -e, --enclose [arg[,...][:value[,...]]] Embed everything in a big function, with configurable argument(s) & value(s).", " -e, --enclose [arg[,...][:value[,...]]] Embed everything in a big function, with configurable argument(s) & value(s).",
" --expression Parse a single expression, rather than a program.",
" --ie Support non-standard Internet Explorer.", " --ie Support non-standard Internet Explorer.",
" --keep-fargs Do not mangle/drop function arguments.", " --keep-fargs Do not mangle/drop function arguments.",
" --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name.", " --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name.",
" --module Process input as ES module (implies --toplevel)", " --module Process input as ES module (implies --toplevel).",
" --no-module Process input with improved JavaScript compatibility.",
" --name-cache <file> File to hold mangled name mappings.", " --name-cache <file> File to hold mangled name mappings.",
" --rename Force symbol expansion.", " --rename Force symbol expansion.",
" --no-rename Disable symbol expansion.", " --no-rename Disable symbol expansion.",
@@ -151,9 +153,9 @@ function process_option(name, no_value) {
options[name] = read_value(); options[name] = read_value();
break; break;
case "annotations": case "annotations":
case "expression":
case "ie": case "ie":
case "ie8": case "ie8":
case "module":
case "timings": case "timings":
case "toplevel": case "toplevel":
case "v8": case "v8":
@@ -199,6 +201,12 @@ function process_option(name, no_value) {
if (typeof options.mangle != "object") options.mangle = {}; if (typeof options.mangle != "object") options.mangle = {};
options.mangle.properties = parse_js(read_value(), options.mangle.properties); options.mangle.properties = parse_js(read_value(), options.mangle.properties);
break; break;
case "module":
options.module = true;
break;
case "no-module":
options.module = false;
break;
case "name-cache": case "name-cache":
nameCache = read_value(true); nameCache = read_value(true);
options.nameCache = JSON.parse(read_file(nameCache, "{}")); options.nameCache = JSON.parse(read_file(nameCache, "{}"));
@@ -236,17 +244,6 @@ if (specified["beautify"] && specified["output-opts"]) fatal("--beautify cannot
[ "compress", "mangle" ].forEach(function(name) { [ "compress", "mangle" ].forEach(function(name) {
if (!(name in options)) options[name] = false; if (!(name in options)) options[name] = false;
}); });
if (options.mangle && options.mangle.properties) {
if (options.mangle.properties.domprops) {
delete options.mangle.properties.domprops;
} else {
if (typeof options.mangle.properties != "object") options.mangle.properties = {};
if (!Array.isArray(options.mangle.properties.reserved)) options.mangle.properties.reserved = [];
require("../tools/domprops").forEach(function(name) {
UglifyJS.push_uniq(options.mangle.properties.reserved, name);
});
}
}
if (/^ast|spidermonkey$/.test(output)) { if (/^ast|spidermonkey$/.test(output)) {
if (typeof options.output != "object") options.output = {}; if (typeof options.output != "object") options.output = {};
options.output.ast = true; options.output.ast = true;
@@ -276,6 +273,8 @@ if (specified["self"]) {
if (paths.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed"); if (paths.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
if (!options.wrap) options.wrap = "UglifyJS"; if (!options.wrap) options.wrap = "UglifyJS";
paths = UglifyJS.FILES; paths = UglifyJS.FILES;
} else if (paths.length) {
paths = simple_glob(paths);
} }
if (specified["in-situ"]) { if (specified["in-situ"]) {
if (output && output != "spidermonkey" || specified["reduce-test"] || specified["self"]) { if (output && output != "spidermonkey" || specified["reduce-test"] || specified["self"]) {
@@ -290,7 +289,7 @@ if (specified["in-situ"]) {
run(); run();
}); });
} else if (paths.length) { } else if (paths.length) {
simple_glob(paths).forEach(function(name) { paths.forEach(function(name) {
files[convert_path(name)] = read_file(name); files[convert_path(name)] = read_file(name);
}); });
run(); run();
@@ -302,9 +301,19 @@ if (specified["in-situ"]) {
process.stdin.setEncoding("utf8"); process.stdin.setEncoding("utf8");
process.stdin.once("data", function() { process.stdin.once("data", function() {
clearTimeout(timerId); clearTimeout(timerId);
}).on("data", function(chunk) { }).on("data", process.stdin.isTTY ? function(chunk) {
// emulate console input termination via Ctrl+D / Ctrl+Z
var match = /[\x04\x1a]\r?\n?$/.exec(chunk);
if (match) {
chunks.push(chunk.slice(0, -match[0].length));
process.stdin.pause();
process.stdin.emit("end");
} else {
chunks.push(chunk); chunks.push(chunk);
}).on("end", function() { }
} : function(chunk) {
chunks.push(chunk);
}).once("end", function() {
files = { STDIN: chunks.join("") }; files = { STDIN: chunks.join("") };
run(); run();
}); });
@@ -489,16 +498,20 @@ function fatal(message) {
// A file glob function that only supports "*" and "?" wildcards in the basename. // A file glob function that only supports "*" and "?" wildcards in the basename.
// Example: "foo/bar/*baz??.*.js" // Example: "foo/bar/*baz??.*.js"
// Argument `glob` may be a string or an array of strings. // Argument `paths` must be an array of strings.
// Returns an array of strings. Garbage in, garbage out. // Returns an array of strings. Garbage in, garbage out.
function simple_glob(glob) { function simple_glob(paths) {
if (Array.isArray(glob)) { return paths.reduce(function(paths, glob) {
return [].concat.apply([], glob.map(simple_glob)); if (/\*|\?/.test(glob)) {
}
if (glob.match(/\*|\?/)) {
var dir = path.dirname(glob); var dir = path.dirname(glob);
try { try {
var entries = fs.readdirSync(dir); var entries = fs.readdirSync(dir).filter(function(name) {
try {
return fs.statSync(path.join(dir, name)).isFile();
} catch (ex) {
return false;
}
});
} catch (ex) {} } catch (ex) {}
if (entries) { if (entries) {
var pattern = "^" + path.basename(glob) var pattern = "^" + path.basename(glob)
@@ -507,15 +520,20 @@ function simple_glob(glob) {
.replace(/\?/g, "[^/\\\\]") + "$"; .replace(/\?/g, "[^/\\\\]") + "$";
var mod = process.platform === "win32" ? "i" : ""; var mod = process.platform === "win32" ? "i" : "";
var rx = new RegExp(pattern, mod); var rx = new RegExp(pattern, mod);
var results = entries.sort().filter(function(name) { var results = entries.filter(function(name) {
return rx.test(name); return rx.test(name);
}).map(function(name) { }).sort().map(function(name) {
return path.join(dir, name); return path.join(dir, name);
}); });
if (results.length) return results; if (results.length) {
[].push.apply(paths, results);
return paths;
} }
} }
return [ glob ]; }
paths.push(glob);
return paths;
}, []);
} }
function read_file(path, default_value) { function read_file(path, default_value) {

View File

@@ -128,12 +128,7 @@ var AST_Node = DEFNODE("Node", "start end", {
var marker = {}; var marker = {};
this.walk(new TreeWalker(function(node) { this.walk(new TreeWalker(function(node) {
if (node.validate_visited === marker) { if (node.validate_visited === marker) {
throw new Error(string_template("cannot reuse {type} from [{file}:{line},{col}]", { throw new Error(string_template("cannot reuse AST_{TYPE} from [{start}]", node));
type: "AST_" + node.TYPE,
file: node.start.file,
line: node.start.line,
col: node.start.col,
}));
} }
node.validate_visited = marker; node.validate_visited = marker;
})); }));
@@ -337,7 +332,7 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
var AST_BlockScope = DEFNODE("BlockScope", "_var_names enclosed functions make_def parent_scope variables", { var AST_BlockScope = DEFNODE("BlockScope", "_var_names enclosed functions make_def parent_scope variables", {
$documentation: "Base class for all statements introducing a lexical scope", $documentation: "Base class for all statements introducing a lexical scope",
$propdoc: { $propdoc: {
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes", enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any inner scopes",
functions: "[Dictionary/S] like `variables`, but only lists function declarations", functions: "[Dictionary/S] like `variables`, but only lists function declarations",
parent_scope: "[AST_Scope?/S] link to the parent scope", parent_scope: "[AST_Scope?/S] link to the parent scope",
variables: "[Dictionary/S] a map of name ---> SymbolDef for all variables/functions defined in this scope", variables: "[Dictionary/S] a map of name ---> SymbolDef for all variables/functions defined in this scope",
@@ -1524,7 +1519,7 @@ var AST_New = DEFNODE("New", null, {
var AST_Sequence = DEFNODE("Sequence", "expressions", { var AST_Sequence = DEFNODE("Sequence", "expressions", {
$documentation: "A sequence expression (comma-separated expressions)", $documentation: "A sequence expression (comma-separated expressions)",
$propdoc: { $propdoc: {
expressions: "[AST_Node*] array of expressions (at least two)" expressions: "[AST_Node*] array of expressions (at least two)",
}, },
_equals: function(node) { _equals: function(node) {
return all_equals(this.expressions, node.expressions); return all_equals(this.expressions, node.expressions);
@@ -1573,8 +1568,11 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression optional property termina
}, },
}); });
var AST_Dot = DEFNODE("Dot", null, { var AST_Dot = DEFNODE("Dot", "quoted", {
$documentation: "A dotted property access expression", $documentation: "A dotted property access expression",
$propdoc: {
quoted: "[boolean] whether property is transformed from a quoted string",
},
walk: function(visitor) { walk: function(visitor) {
var node = this; var node = this;
visitor.visit(node, function() { visitor.visit(node, function() {
@@ -1623,7 +1621,7 @@ var AST_Unary = DEFNODE("Unary", "operator expression", {
$documentation: "Base class for unary expressions", $documentation: "Base class for unary expressions",
$propdoc: { $propdoc: {
operator: "[string] the operator", operator: "[string] the operator",
expression: "[AST_Node] expression that this unary operator applies to" expression: "[AST_Node] expression that this unary operator applies to",
}, },
_equals: function(node) { _equals: function(node) {
return this.operator == node.operator return this.operator == node.operator

File diff suppressed because it is too large Load Diff

View File

@@ -76,19 +76,20 @@ function minify(files, options) {
annotations: undefined, annotations: undefined,
compress: {}, compress: {},
enclose: false, enclose: false,
expression: false,
ie: false, ie: false,
ie8: false, ie8: false,
keep_fargs: false, keep_fargs: false,
keep_fnames: false, keep_fnames: false,
mangle: {}, mangle: {},
module: false, module: undefined,
nameCache: null, nameCache: null,
output: {}, output: {},
parse: {}, parse: {},
rename: undefined, rename: undefined,
sourceMap: false, sourceMap: false,
timings: false, timings: false,
toplevel: !!(options && options["module"]), toplevel: options && !options["expression"] && options["module"] ? true : undefined,
v8: false, v8: false,
validate: false, validate: false,
warnings: false, warnings: false,
@@ -98,12 +99,14 @@ function minify(files, options) {
if (options.validate) AST_Node.enable_validation(); if (options.validate) AST_Node.enable_validation();
var timings = options.timings && { start: Date.now() }; var timings = options.timings && { start: Date.now() };
if (options.annotations !== undefined) set_shorthand("annotations", options, [ "compress", "output" ]); if (options.annotations !== undefined) set_shorthand("annotations", options, [ "compress", "output" ]);
if (options.expression) set_shorthand("expression", options, [ "compress", "parse" ]);
if (options.ie8) options.ie = options.ie || options.ie8; if (options.ie8) options.ie = options.ie || options.ie8;
if (options.ie) set_shorthand("ie", options, [ "compress", "mangle", "output", "rename" ]); if (options.ie) set_shorthand("ie", options, [ "compress", "mangle", "output", "rename" ]);
if (options.keep_fargs) set_shorthand("keep_fargs", options, [ "compress", "mangle", "rename" ]); if (options.keep_fargs) set_shorthand("keep_fargs", options, [ "compress", "mangle", "rename" ]);
if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle", "rename" ]); if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle", "rename" ]);
if (options.module === undefined && !options.ie) options.module = true;
if (options.module) set_shorthand("module", options, [ "compress", "parse" ]); if (options.module) set_shorthand("module", options, [ "compress", "parse" ]);
if (options.toplevel) set_shorthand("toplevel", options, [ "compress", "mangle", "rename" ]); if (options.toplevel !== undefined) set_shorthand("toplevel", options, [ "compress", "mangle", "rename" ]);
if (options.v8) set_shorthand("v8", options, [ "mangle", "output", "rename" ]); if (options.v8) set_shorthand("v8", options, [ "mangle", "output", "rename" ]);
if (options.webkit) set_shorthand("webkit", options, [ "compress", "mangle", "output", "rename" ]); if (options.webkit) set_shorthand("webkit", options, [ "compress", "mangle", "output", "rename" ]);
var quoted_props; var quoted_props;
@@ -153,13 +156,11 @@ function minify(files, options) {
}, options.warnings == "verbose"); }, options.warnings == "verbose");
if (timings) timings.parse = Date.now(); if (timings) timings.parse = Date.now();
var toplevel; var toplevel;
if (files instanceof AST_Toplevel) { options.parse = options.parse || {};
if (files instanceof AST_Node) {
toplevel = files; toplevel = files;
} else { } else {
if (typeof files == "string") { if (typeof files == "string") files = [ files ];
files = [ files ];
}
options.parse = options.parse || {};
options.parse.toplevel = null; options.parse.toplevel = null;
var source_map_content = options.sourceMap && options.sourceMap.content; var source_map_content = options.sourceMap && options.sourceMap.content;
if (typeof source_map_content == "string" && source_map_content != "inline") { if (typeof source_map_content == "string" && source_map_content != "inline") {
@@ -171,17 +172,14 @@ function minify(files, options) {
options.parse.toplevel = toplevel = parse(files[name], options.parse); options.parse.toplevel = toplevel = parse(files[name], options.parse);
if (source_map_content == "inline") { if (source_map_content == "inline") {
var inlined_content = read_source_map(name, toplevel); var inlined_content = read_source_map(name, toplevel);
if (inlined_content) { if (inlined_content) options.sourceMap.orig[name] = parse_source_map(inlined_content);
options.sourceMap.orig[name] = parse_source_map(inlined_content);
}
} else if (source_map_content) { } else if (source_map_content) {
options.sourceMap.orig[name] = source_map_content; options.sourceMap.orig[name] = source_map_content;
} }
} }
} }
if (quoted_props) { if (options.parse.expression) toplevel = toplevel.wrap_expression();
reserve_quoted_keys(toplevel, quoted_props); if (quoted_props) reserve_quoted_keys(toplevel, quoted_props);
}
[ "enclose", "wrap" ].forEach(function(action) { [ "enclose", "wrap" ].forEach(function(action) {
var option = options[action]; var option = options[action];
if (!option) return; if (!option) return;
@@ -208,7 +206,9 @@ function minify(files, options) {
toplevel.mangle_names(options.mangle); toplevel.mangle_names(options.mangle);
} }
if (timings) timings.properties = Date.now(); if (timings) timings.properties = Date.now();
if (quoted_props) reserve_quoted_keys(toplevel, quoted_props);
if (options.mangle && options.mangle.properties) mangle_properties(toplevel, options.mangle.properties); if (options.mangle && options.mangle.properties) mangle_properties(toplevel, options.mangle.properties);
if (options.parse.expression) toplevel = toplevel.unwrap_expression();
if (timings) timings.output = Date.now(); if (timings) timings.output = Date.now();
var result = {}; var result = {};
var output = defaults(options.output, { var output = defaults(options.output, {

View File

@@ -125,6 +125,16 @@
body: normalize_directives(from_moz(M.body).body), body: normalize_directives(from_moz(M.body).body),
}); });
}, },
CallExpression: function(M) {
return new AST_Call({
start: my_start_token(M),
end: my_end_token(M),
expression: from_moz(M.callee),
args: M.arguments.map(from_moz),
optional: M.optional,
pure: M.pure,
});
},
ClassDeclaration: function(M) { ClassDeclaration: function(M) {
return new AST_DefClass({ return new AST_DefClass({
start: my_start_token(M), start: my_start_token(M),
@@ -458,7 +468,7 @@
end: my_end_token(M), end: my_end_token(M),
}; };
if (M.bigint) { if (M.bigint) {
args.value = M.bigint.toLowerCase() + "n"; args.value = M.bigint.toLowerCase();
return new AST_BigInt(args); return new AST_BigInt(args);
} }
var val = M.value; var val = M.value;
@@ -631,7 +641,6 @@
map("AssignmentPattern", AST_DefaultValue, "left>name, right>value"); map("AssignmentPattern", AST_DefaultValue, "left>name, right>value");
map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
map("NewExpression", AST_New, "callee>expression, arguments@args, pure=pure"); map("NewExpression", AST_New, "callee>expression, arguments@args, pure=pure");
map("CallExpression", AST_Call, "callee>expression, arguments@args, optional=optional, pure=pure");
map("SequenceExpression", AST_Sequence, "expressions@expressions"); map("SequenceExpression", AST_Sequence, "expressions@expressions");
map("SpreadElement", AST_Spread, "argument>expression"); map("SpreadElement", AST_Spread, "argument>expression");
map("ObjectExpression", AST_Object, "properties@properties"); map("ObjectExpression", AST_Object, "properties@properties");
@@ -668,6 +677,7 @@
type: "ArrowFunctionExpression", type: "ArrowFunctionExpression",
async: is_async(M), async: is_async(M),
params: params, params: params,
expression: !!M.value,
body: M.value ? to_moz(M.value) : to_moz_scope("BlockStatement", M), body: M.value ? to_moz(M.value) : to_moz_scope("BlockStatement", M),
}; };
return { return {
@@ -680,6 +690,21 @@
}; };
}); });
def_to_moz(AST_Call, function To_Moz_CallExpression(M) {
var expr = M.expression;
if (M.args.length == 1 && expr instanceof AST_SymbolRef && expr.name == "import") return {
type: "ImportExpression",
source: to_moz(M.args[0]),
};
return {
type: "CallExpression",
callee: to_moz(expr),
arguments: M.args.map(to_moz),
optional: M.optional,
pure: M.pure,
};
});
def_to_moz(AST_DefClass, function To_Moz_ClassDeclaration(M) { def_to_moz(AST_DefClass, function To_Moz_ClassDeclaration(M) {
return { return {
type: "ClassDeclaration", type: "ClassDeclaration",
@@ -767,6 +792,7 @@
def_to_moz(AST_Directive, function To_Moz_Directive(M) { def_to_moz(AST_Directive, function To_Moz_Directive(M) {
return { return {
type: "ExpressionStatement", type: "ExpressionStatement",
directive: M.value,
expression: set_moz_loc(M, { expression: set_moz_loc(M, {
type: "Literal", type: "Literal",
value: M.value, value: M.value,
@@ -787,7 +813,6 @@
type: "TryStatement", type: "TryStatement",
block: to_moz_block(M), block: to_moz_block(M),
handler: to_moz(M.bcatch), handler: to_moz(M.bcatch),
guardedHandlers: [],
finalizer: to_moz(M.bfinally), finalizer: to_moz(M.bfinally),
}; };
}); });
@@ -796,7 +821,6 @@
return { return {
type: "CatchClause", type: "CatchClause",
param: to_moz(M.argname), param: to_moz(M.argname),
guard: null,
body: to_moz_block(M), body: to_moz_block(M),
}; };
}); });
@@ -805,6 +829,7 @@
return { return {
type: "ExportNamedDeclaration", type: "ExportNamedDeclaration",
declaration: to_moz(M.body), declaration: to_moz(M.body),
specifiers: [],
}; };
}); });
@@ -954,6 +979,8 @@
type: "Property", type: "Property",
kind: "init", kind: "init",
computed: computed, computed: computed,
method: false,
shorthand: false,
key: key, key: key,
value: to_moz(M.value), value: to_moz(M.value),
}; };
@@ -990,6 +1017,7 @@
kind: kind, kind: kind,
computed: computed, computed: computed,
method: M instanceof AST_ObjectMethod, method: M instanceof AST_ObjectMethod,
shorthand: false,
key: key, key: key,
value: to_moz(M.value), value: to_moz(M.value),
}; };
@@ -1043,8 +1071,8 @@
var value = M.value; var value = M.value;
return { return {
type: "Literal", type: "Literal",
bigint: value.slice(0, -1), bigint: value,
raw: value, raw: value + "n",
}; };
}); });

View File

@@ -55,6 +55,7 @@ function OutputStream(options) {
beautify : false, beautify : false,
braces : false, braces : false,
comments : false, comments : false,
extendscript : false,
galio : false, galio : false,
ie : false, ie : false,
indent_level : 4, indent_level : 4,
@@ -75,7 +76,7 @@ function OutputStream(options) {
wrap_iife : false, wrap_iife : false,
}, true); }, true);
// Convert comment option to RegExp if neccessary and set up comments filter // Convert comment option to RegExp if necessary and set up comments filter
var comment_filter = return_false; // Default case, throw all comments away var comment_filter = return_false; // Default case, throw all comments away
if (options.comments) { if (options.comments) {
var comments = options.comments; var comments = options.comments;
@@ -406,10 +407,11 @@ function OutputStream(options) {
print(";"); print(";");
} }
function with_block(cont) { function with_block(cont, end) {
print("{"); print("{");
newline(); newline();
with_indent(cont); with_indent(cont);
add_mapping(end);
indent(); indent();
print("}"); print("}");
} }
@@ -699,6 +701,7 @@ function OutputStream(options) {
if (p instanceof AST_Class) return true; if (p instanceof AST_Class) return true;
// (x++)[y] // (x++)[y]
// (typeof x).y // (typeof x).y
// https://github.com/mishoo/UglifyJS/issues/115
if (p instanceof AST_PropAccess) return p.expression === this; if (p instanceof AST_PropAccess) return p.expression === this;
// (~x)`foo` // (~x)`foo`
if (p instanceof AST_Template) return p.tag === this; if (p instanceof AST_Template) return p.tag === this;
@@ -874,7 +877,9 @@ function OutputStream(options) {
return needs_parens_assign_cond(this, output); return needs_parens_assign_cond(this, output);
}); });
PARENS(AST_Conditional, function(output) { PARENS(AST_Conditional, function(output) {
return needs_parens_assign_cond(this, output); return needs_parens_assign_cond(this, output)
// https://github.com/mishoo/UglifyJS/issues/1144
|| output.option("extendscript") && output.parent() instanceof AST_Conditional;
}); });
PARENS(AST_Yield, function(output) { PARENS(AST_Yield, function(output) {
return needs_parens_assign_cond(this, output); return needs_parens_assign_cond(this, output);
@@ -953,7 +958,7 @@ function OutputStream(options) {
if (self.body.length > 0) { if (self.body.length > 0) {
output.with_block(function() { output.with_block(function() {
display_body(self.body, false, output, allow_directives); display_body(self.body, false, output, allow_directives);
}); }, self.end);
} else print_braced_empty(self, output); } else print_braced_empty(self, output);
} }
DEFPRINT(AST_BlockStatement, function(output) { DEFPRINT(AST_BlockStatement, function(output) {
@@ -992,7 +997,7 @@ function OutputStream(options) {
if (self.init instanceof AST_Definitions) { if (self.init instanceof AST_Definitions) {
self.init.print(output); self.init.print(output);
} else { } else {
parenthesize_for_noin(self.init, output, true); parenthesize_for_no_in(self.init, output, true);
} }
output.print(";"); output.print(";");
output.space(); output.space();
@@ -1088,7 +1093,7 @@ function OutputStream(options) {
print_entry(i); print_entry(i);
} }
output.newline(); output.newline();
}); }, self.end);
output.space(); output.space();
output.print("from"); output.print("from");
output.space(); output.space();
@@ -1352,7 +1357,7 @@ function OutputStream(options) {
if (i < last && branch.body.length > 0) if (i < last && branch.body.length > 0)
output.newline(); output.newline();
}); });
}); }, self.end);
}); });
function print_branch_body(self, output) { function print_branch_body(self, output) {
output.newline(); output.newline();
@@ -1408,7 +1413,7 @@ function OutputStream(options) {
print_braced(this, output); print_braced(this, output);
}); });
function print_definitinos(type) { function print_definitions(type) {
return function(output) { return function(output) {
var self = this; var self = this;
output.print(type); output.print(type);
@@ -1421,15 +1426,15 @@ function OutputStream(options) {
if (!(p instanceof AST_IterationStatement && p.init === self)) output.semicolon(); if (!(p instanceof AST_IterationStatement && p.init === self)) output.semicolon();
}; };
} }
DEFPRINT(AST_Const, print_definitinos("const")); DEFPRINT(AST_Const, print_definitions("const"));
DEFPRINT(AST_Let, print_definitinos("let")); DEFPRINT(AST_Let, print_definitions("let"));
DEFPRINT(AST_Var, print_definitinos("var")); DEFPRINT(AST_Var, print_definitions("var"));
function parenthesize_for_noin(node, output, noin) { function parenthesize_for_no_in(node, output, no_in) {
var parens = false; var parens = false;
// need to take some precautions here: // need to take some precautions here:
// https://github.com/mishoo/UglifyJS/issues/60 // https://github.com/mishoo/UglifyJS/issues/60
if (noin) node.walk(new TreeWalker(function(node) { if (no_in) node.walk(new TreeWalker(function(node) {
if (parens) return true; if (parens) return true;
if (node instanceof AST_Binary && node.operator == "in") return parens = true; if (node instanceof AST_Binary && node.operator == "in") return parens = true;
if (node instanceof AST_Scope && !(is_arrow(node) && node.value)) return true; if (node instanceof AST_Scope && !(is_arrow(node) && node.value)) return true;
@@ -1445,8 +1450,8 @@ function OutputStream(options) {
output.print("="); output.print("=");
output.space(); output.space();
var p = output.parent(1); var p = output.parent(1);
var noin = p instanceof AST_For || p instanceof AST_ForEnumeration; var no_in = p instanceof AST_For || p instanceof AST_ForEnumeration;
parenthesize_for_noin(self.value, output, noin); parenthesize_for_no_in(self.value, output, no_in);
} }
}); });
@@ -1472,14 +1477,12 @@ function OutputStream(options) {
output.print("/*@__PURE__*/"); output.print("/*@__PURE__*/");
} }
function print_call_args(self, output) { function print_call_args(self, output) {
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
output.add_mapping(self.start);
}
output.with_parens(function() { output.with_parens(function() {
self.args.forEach(function(expr, i) { self.args.forEach(function(expr, i) {
if (i) output.comma(); if (i) output.comma();
expr.print(output); expr.print(output);
}); });
output.add_mapping(self.end);
}); });
} }
DEFPRINT(AST_Call, function(output) { DEFPRINT(AST_Call, function(output) {
@@ -1514,11 +1517,12 @@ function OutputStream(options) {
var expr = self.expression; var expr = self.expression;
expr.print(output); expr.print(output);
var prop = self.property; var prop = self.property;
if (output.option("ie") && RESERVED_WORDS[prop]) { if (output.option("ie") && RESERVED_WORDS[prop] || self.quoted && output.option("keep_quoted_props")) {
output.print(self.optional ? "?.[" : "["); if (self.optional) output.print("?.");
output.with_square(function() {
output.add_mapping(self.end); output.add_mapping(self.end);
output.print_string(prop); output.print_string(prop);
output.print("]"); });
} else { } else {
if (expr instanceof AST_Number && !/[ex.)]/i.test(output.last())) output.print("."); if (expr instanceof AST_Number && !/[ex.)]/i.test(output.last())) output.print(".");
output.print(self.optional ? "?." : "."); output.print(self.optional ? "?." : ".");
@@ -1530,9 +1534,10 @@ function OutputStream(options) {
DEFPRINT(AST_Sub, function(output) { DEFPRINT(AST_Sub, function(output) {
var self = this; var self = this;
self.expression.print(output); self.expression.print(output);
output.print(self.optional ? "?.[" : "["); if (self.optional) output.print("?.");
output.with_square(function() {
self.property.print(output); self.property.print(output);
output.print("]"); });
}); });
DEFPRINT(AST_Spread, function(output) { DEFPRINT(AST_Spread, function(output) {
output.print("..."); output.print("...");
@@ -1551,8 +1556,10 @@ function OutputStream(options) {
exp.print(output); exp.print(output);
}); });
DEFPRINT(AST_UnaryPostfix, function(output) { DEFPRINT(AST_UnaryPostfix, function(output) {
this.expression.print(output); var self = this;
output.print(this.operator); self.expression.print(output);
output.add_mapping(self.end);
output.print(self.operator);
}); });
DEFPRINT(AST_Binary, function(output) { DEFPRINT(AST_Binary, function(output) {
var self = this; var self = this;
@@ -1645,7 +1652,8 @@ function OutputStream(options) {
value.print(output); value.print(output);
}); });
DEFPRINT(AST_DestructuredObject, function(output) { DEFPRINT(AST_DestructuredObject, function(output) {
var props = this.properties, len = props.length, rest = this.rest; var self = this;
var props = self.properties, len = props.length, rest = self.rest;
if (len || rest) output.with_block(function() { if (len || rest) output.with_block(function() {
props.forEach(function(prop, i) { props.forEach(function(prop, i) {
if (i) { if (i) {
@@ -1665,8 +1673,8 @@ function OutputStream(options) {
rest.print(output); rest.print(output);
} }
output.newline(); output.newline();
}); }, self.end);
else print_braced_empty(this, output); else print_braced_empty(self, output);
}); });
function print_properties(self, output, no_comma) { function print_properties(self, output, no_comma) {
var props = self.properties; var props = self.properties;
@@ -1680,7 +1688,7 @@ function OutputStream(options) {
prop.print(output); prop.print(output);
}); });
output.newline(); output.newline();
}); }, self.end);
else print_braced_empty(self, output); else print_braced_empty(self, output);
} }
DEFPRINT(AST_Object, function(output) { DEFPRINT(AST_Object, function(output) {
@@ -1775,6 +1783,9 @@ function OutputStream(options) {
output.print(self.strings[i]); output.print(self.strings[i]);
output.print("`"); output.print("`");
}); });
DEFPRINT(AST_BigInt, function(output) {
output.print(this.value + "n");
});
DEFPRINT(AST_Constant, function(output) { DEFPRINT(AST_Constant, function(output) {
output.print("" + this.value); output.print("" + this.value);
}); });
@@ -1890,7 +1901,7 @@ function OutputStream(options) {
output.indent(); output.indent();
stmt.print(output); stmt.print(output);
output.newline(); output.newline();
}); }, stmt.end);
} }
/* -----[ source map generators ]----- */ /* -----[ source map generators ]----- */
@@ -1913,22 +1924,27 @@ function OutputStream(options) {
// or if we should add even more. // or if we should add even more.
DEFMAP([ DEFMAP([
AST_Array, AST_Array,
AST_Await,
AST_BlockStatement, AST_BlockStatement,
AST_Catch, AST_Catch,
AST_Constant, AST_Constant,
AST_Debugger, AST_Debugger,
AST_Definitions, AST_Definitions,
AST_Destructured, AST_Destructured,
AST_Directive,
AST_Finally, AST_Finally,
AST_Jump, AST_Jump,
AST_Lambda, AST_Lambda,
AST_New, AST_New,
AST_Object, AST_Object,
AST_Spread,
AST_StatementWithBody, AST_StatementWithBody,
AST_Symbol, AST_Symbol,
AST_Switch, AST_Switch,
AST_SwitchBranch, AST_SwitchBranch,
AST_Try, AST_Try,
AST_UnaryPrefix,
AST_Yield,
], function(output) { ], function(output) {
output.add_mapping(this.start); output.add_mapping(this.start);
}); });

View File

@@ -207,11 +207,14 @@ function JS_Parse_Error(message, filename, line, col, pos) {
this.line = line; this.line = line;
this.col = col; this.col = col;
this.pos = pos; this.pos = pos;
try {
throw new SyntaxError(message, filename, line, col);
} catch (cause) {
configure_error_stack(this, cause);
} }
JS_Parse_Error.prototype = Object.create(Error.prototype); }
JS_Parse_Error.prototype = Object.create(SyntaxError.prototype);
JS_Parse_Error.prototype.constructor = JS_Parse_Error; JS_Parse_Error.prototype.constructor = JS_Parse_Error;
JS_Parse_Error.prototype.name = "SyntaxError";
configure_error_stack(JS_Parse_Error);
function js_error(message, filename, line, col, pos) { function js_error(message, filename, line, col, pos) {
throw new JS_Parse_Error(message, filename, line, col, pos); throw new JS_Parse_Error(message, filename, line, col, pos);
@@ -391,7 +394,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
var valid = parse_js_number(num); var valid = parse_js_number(num);
if (isNaN(valid)) parse_error("Invalid syntax: " + num); if (isNaN(valid)) parse_error("Invalid syntax: " + num);
if (has_dot || has_e || peek() != "n") return token("num", valid); if (has_dot || has_e || peek() != "n") return token("num", valid);
return token("bigint", num.toLowerCase() + next()); next();
return token("bigint", num.toLowerCase());
} }
function read_escaped_char(in_string) { function read_escaped_char(in_string) {
@@ -782,7 +786,7 @@ function parse($TEXT, options) {
else if (!optional && !can_insert_semicolon()) expect(";"); else if (!optional && !can_insert_semicolon()) expect(";");
} }
function parenthesised() { function parenthesized() {
expect("("); expect("(");
var exp = expression(); var exp = expression();
expect(")"); expect(")");
@@ -920,18 +924,18 @@ function parse($TEXT, options) {
next(); next();
var body = in_loop(statement); var body = in_loop(statement);
expect_token("keyword", "while"); expect_token("keyword", "while");
var condition = parenthesised(); var condition = parenthesized();
semicolon(true); semicolon(true);
return new AST_Do({ return new AST_Do({
body : body, body : body,
condition : condition condition : condition,
}); });
case "while": case "while":
next(); next();
return new AST_While({ return new AST_While({
condition : parenthesised(), condition : parenthesized(),
body : in_loop(statement) body : in_loop(statement),
}); });
case "for": case "for":
@@ -959,15 +963,13 @@ function parse($TEXT, options) {
value = expression(); value = expression();
semicolon(); semicolon();
} }
return new AST_Return({ return new AST_Return({ value: value });
value: value
});
case "switch": case "switch":
next(); next();
return new AST_Switch({ return new AST_Switch({
expression : parenthesised(), expression : parenthesized(),
body : in_loop(switch_body_) body : in_loop(switch_body_),
}); });
case "throw": case "throw":
@@ -976,9 +978,7 @@ function parse($TEXT, options) {
croak("Illegal newline after 'throw'"); croak("Illegal newline after 'throw'");
var value = expression(); var value = expression();
semicolon(); semicolon();
return new AST_Throw({ return new AST_Throw({ value: value });
value: value
});
case "try": case "try":
next(); next();
@@ -996,8 +996,8 @@ function parse($TEXT, options) {
} }
next(); next();
return new AST_With({ return new AST_With({
expression : parenthesised(), expression : parenthesized(),
body : statement() body : statement(),
}); });
} }
} }
@@ -1056,13 +1056,13 @@ function parse($TEXT, options) {
return stat; return stat;
} }
function has_modifier(name) { function has_modifier(name, no_nlb) {
if (!is("name", name)) return; if (!is("name", name)) return;
var token = peek(); var token = peek();
if (!token) return; if (!token) return;
if (is_token(token, "operator", "=")) return; if (is_token(token, "operator", "=")) return;
if (token.type == "punc" && /^[(;}]$/.test(token.value)) return; if (token.type == "punc" && /^[(;}]$/.test(token.value)) return;
if (has_newline_before(token)) return; if (no_nlb && has_newline_before(token)) return;
return next(); return next();
} }
@@ -1092,7 +1092,7 @@ function parse($TEXT, options) {
} }
var start = S.token; var start = S.token;
var fixed = !!has_modifier("static"); var fixed = !!has_modifier("static");
var async = has_modifier("async"); var async = has_modifier("async", true);
if (is("operator", "*")) { if (is("operator", "*")) {
next(); next();
var internal = is("name") && /^#/.test(S.token.value); var internal = is("name") && /^#/.test(S.token.value);
@@ -1421,15 +1421,15 @@ function parse($TEXT, options) {
}; };
function if_() { function if_() {
var cond = parenthesised(), body = statement(), belse = null; var cond = parenthesized(), body = statement(), alt = null;
if (is("keyword", "else")) { if (is("keyword", "else")) {
next(); next();
belse = statement(); alt = statement();
} }
return new AST_If({ return new AST_If({
condition : cond, condition : cond,
body : body, body : body,
alternative : belse alternative : alt,
}); });
} }
@@ -2171,9 +2171,9 @@ function parse($TEXT, options) {
token_error(sym.start, "Unexpected " + sym.name + " in strict mode"); token_error(sym.start, "Unexpected " + sym.name + " in strict mode");
} }
function as_symbol(type, noerror) { function as_symbol(type, no_error) {
if (!is("name")) { if (!is("name")) {
if (!noerror) croak("Name expected"); if (!no_error) croak("Name expected");
return null; return null;
} }
var sym = _make_symbol(type, S.token); var sym = _make_symbol(type, S.token);
@@ -2409,20 +2409,20 @@ function parse($TEXT, options) {
return new ctor({ operator: op, expression: expr }); return new ctor({ operator: op, expression: expr });
} }
var expr_op = function(left, min_prec, no_in) { var expr_op = function(left, min_precision, no_in) {
var op = is("operator") ? S.token.value : null; var op = is("operator") ? S.token.value : null;
if (op == "in" && no_in) op = null; if (op == "in" && no_in) op = null;
var prec = op != null ? PRECEDENCE[op] : null; var precision = op != null ? PRECEDENCE[op] : null;
if (prec != null && prec > min_prec) { if (precision != null && precision > min_precision) {
next(); next();
var right = expr_op(maybe_unary(no_in), op == "**" ? prec - 1 : prec, no_in); var right = expr_op(maybe_unary(no_in), op == "**" ? precision - 1 : precision, no_in);
return expr_op(new AST_Binary({ return expr_op(new AST_Binary({
start : left.start, start : left.start,
left : left, left : left,
operator : op, operator : op,
right : right, right : right,
end : right.end end : right.end,
}), min_prec, no_in); }), min_precision, no_in);
} }
return left; return left;
}; };

View File

@@ -43,10 +43,11 @@
"use strict"; "use strict";
var builtins = function() { function get_builtins() {
var names = new Dictionary(); var names = new Dictionary();
// NaN will be included due to Number.NaN // constants
[ [
"NaN",
"null", "null",
"true", "true",
"false", "false",
@@ -54,37 +55,85 @@ var builtins = function() {
"-Infinity", "-Infinity",
"undefined", "undefined",
].forEach(add); ].forEach(add);
// global functions
[ [
Array, "encodeURI",
Boolean, "encodeURIComponent",
Date, "escape",
Error, "eval",
Function, "decodeURI",
Math, "decodeURIComponent",
Number, "isFinite",
Object, "isNaN",
RegExp, "parseFloat",
String, "parseInt",
].forEach(function(ctor) { "unescape",
].forEach(add);
// global constructors & objects
var global = Function("return this")();
[
"Array",
"ArrayBuffer",
"Atomics",
"BigInt",
"Boolean",
"console",
"DataView",
"Date",
"Error",
"Function",
"Int8Array",
"Intl",
"JSON",
"Map",
"Math",
"Number",
"Object",
"Promise",
"Proxy",
"Reflect",
"RegExp",
"Set",
"String",
"Symbol",
"WebAssembly",
].forEach(function(name) {
add(name);
var ctor = global[name];
if (!ctor) return;
Object.getOwnPropertyNames(ctor).map(add); Object.getOwnPropertyNames(ctor).map(add);
if (ctor.prototype) { if (typeof ctor != "function") return;
if (ctor.__proto__) Object.getOwnPropertyNames(ctor.__proto__).map(add);
if (ctor.prototype) Object.getOwnPropertyNames(ctor.prototype).map(add);
try {
Object.getOwnPropertyNames(new ctor()).map(add); Object.getOwnPropertyNames(new ctor()).map(add);
Object.getOwnPropertyNames(ctor.prototype).map(add); } catch (e) {
try {
Object.getOwnPropertyNames(ctor()).map(add);
} catch (e) {}
} }
}); });
return names; return (get_builtins = function() {
return names.clone();
})();
function add(name) { function add(name) {
names.set(name, true); names.set(name, true);
} }
}(); }
function reserve_quoted_keys(ast, reserved) { function reserve_quoted_keys(ast, reserved) {
ast.walk(new TreeWalker(function(node) { ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ClassProperty) { if (node instanceof AST_ClassProperty
if (node.start && node.start.quote) add(node.key); || node instanceof AST_DestructuredKeyVal
} else if (node instanceof AST_ObjectProperty) { || node instanceof AST_ObjectProperty) {
if (node.start && node.start.quote) add(node.key); if (node.key instanceof AST_Node) {
addStrings(node.key, add);
} else if (node.start && node.start.quote) {
add(node.key);
}
} else if (node instanceof AST_Dot) {
if (node.quoted) add(node.property);
} else if (node instanceof AST_Sub) { } else if (node instanceof AST_Sub) {
addStrings(node.property, add); addStrings(node.property, add);
} }
@@ -111,12 +160,16 @@ function mangle_properties(ast, options) {
builtins: false, builtins: false,
cache: null, cache: null,
debug: false, debug: false,
domprops: false,
keep_quoted: false, keep_quoted: false,
regex: null, regex: null,
reserved: null, reserved: null,
}, true); }, true);
var reserved = options.builtins ? new Dictionary() : builtins.clone(); var reserved = options.builtins ? new Dictionary() : get_builtins();
if (!options.domprops && typeof domprops !== "undefined") domprops.forEach(function(name) {
reserved.set(name, true);
});
if (Array.isArray(options.reserved)) options.reserved.forEach(function(name) { if (Array.isArray(options.reserved)) options.reserved.forEach(function(name) {
reserved.set(name, true); reserved.set(name, true);
}); });
@@ -135,7 +188,7 @@ function mangle_properties(ast, options) {
var regex = options.regex; var regex = options.regex;
// note debug is either false (disabled), or a string of the debug suffix to use (enabled). // note debug is either false (disabled), or a string of the debug suffix to use (enabled).
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true' // note debug may be enabled as an empty string, which is falsy. Also treat passing 'true'
// the same as passing an empty string. // the same as passing an empty string.
var debug = options.debug !== false; var debug = options.debug !== false;
var debug_suffix; var debug_suffix;
@@ -146,9 +199,7 @@ function mangle_properties(ast, options) {
// step 1: find candidates to mangle // step 1: find candidates to mangle
ast.walk(new TreeWalker(function(node) { ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_Binary) { if (node.TYPE == "Call") {
if (node.operator == "in") addStrings(node.left, add);
} else if (node.TYPE == "Call") {
var exp = node.expression; var exp = node.expression;
if (exp instanceof AST_Dot) switch (exp.property) { if (exp instanceof AST_Dot) switch (exp.property) {
case "defineProperty": case "defineProperty":
@@ -165,14 +216,18 @@ function mangle_properties(ast, options) {
addStrings(node.args[0], add); addStrings(node.args[0], add);
break; break;
} }
} else if (node instanceof AST_ClassProperty) { } else if (node instanceof AST_ClassProperty
if (typeof node.key == "string") add(node.key); || node instanceof AST_DestructuredKeyVal
|| node instanceof AST_ObjectProperty) {
if (node.key instanceof AST_Node) {
addStrings(node.key, add);
} else {
add(node.key);
}
} else if (node instanceof AST_Dot) { } else if (node instanceof AST_Dot) {
add(node.property); if (is_lhs(node, this.parent())) add(node.property);
} else if (node instanceof AST_ObjectProperty) {
if (typeof node.key == "string") add(node.key);
} else if (node instanceof AST_Sub) { } else if (node instanceof AST_Sub) {
addStrings(node.property, add); if (is_lhs(node, this.parent())) addStrings(node.property, add);
} }
})); }));
@@ -197,12 +252,16 @@ function mangle_properties(ast, options) {
mangleStrings(node.args[0]); mangleStrings(node.args[0]);
break; break;
} }
} else if (node instanceof AST_ClassProperty) { } else if (node instanceof AST_ClassProperty
if (typeof node.key == "string") node.key = mangle(node.key); || node instanceof AST_DestructuredKeyVal
|| node instanceof AST_ObjectProperty) {
if (node.key instanceof AST_Node) {
mangleStrings(node.key);
} else {
node.key = mangle(node.key);
}
} else if (node instanceof AST_Dot) { } else if (node instanceof AST_Dot) {
node.property = mangle(node.property); node.property = mangle(node.property);
} else if (node instanceof AST_ObjectProperty) {
if (typeof node.key == "string") node.key = mangle(node.key);
} else if (node instanceof AST_Sub) { } else if (node instanceof AST_Sub) {
if (!options.keep_quoted) mangleStrings(node.property); if (!options.keep_quoted) mangleStrings(node.property);
} }
@@ -217,8 +276,14 @@ function mangle_properties(ast, options) {
} }
function should_mangle(name) { function should_mangle(name) {
if (reserved.has(name)) return false; if (reserved.has(name)) {
if (regex && !regex.test(name)) return false; AST_Node.info("Preserving reserved property {this}", name);
return false;
}
if (regex && !regex.test(name)) {
AST_Node.info("Preserving excluded property {this}", name);
return false;
}
return cache.has(name) || names_to_mangle.has(name); return cache.has(name) || names_to_mangle.has(name);
} }
@@ -243,12 +308,16 @@ function mangle_properties(ast, options) {
if (/^#/.test(name)) mangled = "#" + mangled; if (/^#/.test(name)) mangled = "#" + mangled;
cache.set(name, mangled); cache.set(name, mangled);
} }
AST_Node.info("Mapping property {name} to {mangled}", {
mangled: mangled,
name: name,
});
return mangled; return mangled;
} }
function mangleStrings(node) { function mangleStrings(node) {
if (node instanceof AST_Sequence) { if (node instanceof AST_Sequence) {
mangleStrings(node.expressions.tail_node()); mangleStrings(node.tail_node());
} else if (node instanceof AST_String) { } else if (node instanceof AST_String) {
node.value = mangle(node.value); node.value = mangle(node.value);
} else if (node instanceof AST_Conditional) { } else if (node instanceof AST_Conditional) {

View File

@@ -68,9 +68,7 @@ SymbolDef.prototype = {
var cache = this.global && options.cache && options.cache.props; var cache = this.global && options.cache && options.cache.props;
if (cache && cache.has(this.name)) { if (cache && cache.has(this.name)) {
this.mangled_name = cache.get(this.name); this.mangled_name = cache.get(this.name);
} else if (this.unmangleable(options)) { } else if (!this.unmangleable(options)) {
names_in_use(this.scope, options).set(this.name, true);
} else {
var def = this.redefined(); var def = this.redefined();
if (def) { if (def) {
this.mangled_name = def.mangled_name || def.name; this.mangled_name = def.mangled_name || def.name;
@@ -180,6 +178,13 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
}); });
return true; return true;
} }
if (node instanceof AST_Switch) {
node.expression.walk(tw);
walk_scope(function() {
walk_body(node, tw);
});
return true;
}
if (node instanceof AST_SwitchBranch) { if (node instanceof AST_SwitchBranch) {
node.init_vars(scope); node.init_vars(scope);
descend(); descend();
@@ -286,7 +291,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
// ensure mangling works if `catch` reuses a scope variable // ensure mangling works if `catch` reuses a scope variable
var redef = def.redefined(); var redef = def.redefined();
if (redef) for (var s = node.scope; s; s = s.parent_scope) { if (redef) for (var s = node.scope; s; s = s.parent_scope) {
push_uniq(s.enclosed, redef); if (!push_uniq(s.enclosed, redef)) break;
if (s === redef.scope) break; if (s === redef.scope) break;
} }
} else if (node instanceof AST_SymbolConst) { } else if (node instanceof AST_SymbolConst) {
@@ -369,8 +374,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
// pass 3: fix up any scoping issue with IE8 // pass 3: fix up any scoping issue with IE8
if (options.ie) self.walk(new TreeWalker(function(node) { if (options.ie) self.walk(new TreeWalker(function(node) {
if (node instanceof AST_SymbolCatch) { if (node instanceof AST_SymbolCatch) {
var scope = node.thedef.defun; var def = node.thedef;
if (scope.name instanceof AST_SymbolLambda && scope.name.name == node.name) { var scope = def.defun;
if (def.name != "arguments" && scope.name instanceof AST_SymbolLambda && scope.name.name == def.name) {
scope = scope.parent_scope.resolve(); scope = scope.parent_scope.resolve();
} }
redefine(node, scope); redefine(node, scope);
@@ -438,35 +444,43 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
} }
}); });
function init_block_vars(scope, parent) { function init_block_vars(scope, parent, orig) {
scope.enclosed = []; // variables from this or outer scope(s) that are referenced from this or inner scopes // variables from this or outer scope(s) that are referenced from this or inner scopes
scope.parent_scope = parent; // the parent scope (null if this is the top level) scope.enclosed = orig ? orig.enclosed.slice() : [];
scope.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) // 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) scope.functions = orig ? orig.functions.clone() : new Dictionary();
if (parent) scope.make_def = parent.make_def; // top-level tracking of SymbolDef instances // map name to AST_SymbolVar (variables defined in this scope; includes functions)
scope.variables = orig ? orig.variables.clone() : new Dictionary();
if (!parent) return;
// top-level tracking of SymbolDef instances
scope.make_def = parent.make_def;
// the parent scope (null if this is the top level)
scope.parent_scope = parent;
} }
function init_scope_vars(scope, parent) { function init_scope_vars(scope, parent, orig) {
init_block_vars(scope, parent); init_block_vars(scope, parent, orig);
scope.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` // 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.uses_eval = false;
// will be set to true if this or some nested scope uses the `with` statement
scope.uses_with = false;
} }
AST_BlockScope.DEFMETHOD("init_vars", function(parent_scope) { AST_BlockScope.DEFMETHOD("init_vars", function(parent, orig) {
init_block_vars(this, parent_scope); init_block_vars(this, parent, orig);
}); });
AST_Scope.DEFMETHOD("init_vars", function(parent_scope) { AST_Scope.DEFMETHOD("init_vars", function(parent, orig) {
init_scope_vars(this, parent_scope); init_scope_vars(this, parent, orig);
}); });
AST_Arrow.DEFMETHOD("init_vars", function(parent_scope) { AST_Arrow.DEFMETHOD("init_vars", function(parent, orig) {
init_scope_vars(this, parent_scope); init_scope_vars(this, parent, orig);
return this; return this;
}); });
AST_AsyncArrow.DEFMETHOD("init_vars", function(parent_scope) { AST_AsyncArrow.DEFMETHOD("init_vars", function(parent, orig) {
init_scope_vars(this, parent_scope); init_scope_vars(this, parent, orig);
}); });
AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) { AST_Lambda.DEFMETHOD("init_vars", function(parent, orig) {
init_scope_vars(this, parent_scope); init_scope_vars(this, parent, orig);
this.uses_arguments = false; this.uses_arguments = false;
this.def_variable(new AST_SymbolFunarg({ this.def_variable(new AST_SymbolFunarg({
name: "arguments", name: "arguments",
@@ -480,7 +494,7 @@ AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) {
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) { AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
var def = this.definition(); var def = this.definition();
for (var s = this.scope; s; s = s.parent_scope) { for (var s = this.scope; s; s = s.parent_scope) {
push_uniq(s.enclosed, def); if (!push_uniq(s.enclosed, def)) break;
if (!options) { if (!options) {
s._var_names = undefined; s._var_names = undefined;
} else { } else {
@@ -642,8 +656,12 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
}, true); }, true);
} }
var to_mangle = node.to_mangle = []; var to_mangle = node.to_mangle = [];
node.variables.each(function(def) { node.variables.each(function(def, name) {
if (!defer_redef(def)) to_mangle.push(def); if (def.unmangleable(options)) {
names_in_use(node, options).set(name, true);
} else if (!defer_redef(def)) {
to_mangle.push(def);
}
}); });
descend(); descend();
if (options.cache && node instanceof AST_Toplevel) { if (options.cache && node instanceof AST_Toplevel) {
@@ -704,7 +722,12 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
} }
redefined.push(def); redefined.push(def);
def.references.forEach(reference); def.references.forEach(reference);
if (sym instanceof AST_SymbolCatch || sym instanceof AST_SymbolConst) reference(sym); if (sym instanceof AST_SymbolCatch || sym instanceof AST_SymbolConst) {
reference(sym);
def.redefined = function() {
return redef;
};
}
return true; return true;
function reference(sym) { function reference(sym) {

View File

@@ -55,28 +55,41 @@ function find_if(func, array) {
for (var i = array.length; --i >= 0;) if (func(array[i])) return array[i]; for (var i = array.length; --i >= 0;) if (func(array[i])) return array[i];
} }
function configure_error_stack(fn) { function configure_error_stack(ex, cause) {
Object.defineProperty(fn.prototype, "stack", { var stack = ex.name + ": " + ex.message;
Object.defineProperty(ex, "stack", {
get: function() { get: function() {
var err = new Error(this.message); if (cause) {
err.name = this.name; cause.name = "" + ex.name;
try { stack = "" + cause.stack;
throw err; var msg = "" + cause.message;
} catch (e) { cause = null;
return e.stack; var index = stack.indexOf(msg);
if (index < 0) {
index = 0;
} else {
index += msg.length;
index = stack.indexOf("\n", index) + 1;
} }
stack = stack.slice(0, index) + stack.slice(stack.indexOf("\n", index) + 1);
} }
return stack;
},
}); });
} }
function DefaultsError(msg, defs) { function DefaultsError(msg, defs) {
this.message = msg; this.message = msg;
this.defs = defs; this.defs = defs;
try {
throw new Error(msg);
} catch (cause) {
configure_error_stack(this, cause);
}
} }
DefaultsError.prototype = Object.create(Error.prototype); DefaultsError.prototype = Object.create(Error.prototype);
DefaultsError.prototype.constructor = DefaultsError; DefaultsError.prototype.constructor = DefaultsError;
DefaultsError.prototype.name = "DefaultsError"; DefaultsError.prototype.name = "DefaultsError";
configure_error_stack(DefaultsError);
function defaults(args, defs, croak) { function defaults(args, defs, croak) {
if (croak) for (var i in args) { if (croak) for (var i in args) {
@@ -127,8 +140,10 @@ function push_uniq(array, el) {
function string_template(text, props) { function string_template(text, props) {
return text.replace(/\{([^{}]+)\}/g, function(str, p) { return text.replace(/\{([^{}]+)\}/g, function(str, p) {
var value = props[p]; var value = p == "this" ? props : props[p];
return value instanceof AST_Node ? value.print_to_string() : value; if (value instanceof AST_Node) return value.print_to_string();
if (value instanceof AST_Token) return value.file + ":" + value.line + "," + value.col;
return value;
}); });
} }

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit", "description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)", "author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"version": "3.16.3", "version": "3.18.0",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=0.8.0"
}, },

View File

@@ -3,6 +3,7 @@
"use strict"; "use strict";
require("../tools/tty");
var createHash = require("crypto").createHash; var createHash = require("crypto").createHash;
var fetch = require("./fetch"); var fetch = require("./fetch");
var spawn = require("child_process").spawn; var spawn = require("child_process").spawn;

View File

@@ -60,8 +60,9 @@ function log() {
console.log("%s", tmpl.apply(null, arguments)); console.log("%s", tmpl.apply(null, arguments));
} }
function make_code(ast, options) { function make_code(ast, options, expression) {
var stream = U.OutputStream(options); var stream = U.OutputStream(options);
if (expression) ast = ast.clone(true).unwrap_expression();
ast.print(stream); ast.print(stream);
return stream.get(); return stream.get();
} }
@@ -125,6 +126,17 @@ function parse_test(file) {
croak(node); croak(node);
} }
var name = node.left.name; var name = node.left.name;
assert.ok([
"beautify",
"expression",
"mangle",
"options",
"rename",
].indexOf(name) >= 0, tmpl("Unsupported setting {name} [{line},{col}]", {
name: name,
line: node.start.line,
col: node.start.col,
}));
test[name] = evaluate(node.right); test[name] = evaluate(node.right);
return true; return true;
} }
@@ -178,9 +190,18 @@ function parse_test(file) {
// Try to reminify original input with standard options // Try to reminify original input with standard options
// to see if it matches expect_stdout. // to see if it matches expect_stdout.
function reminify(orig_options, input_code, input_formatted, stdout) { function reminify(expression, orig_options, input_code, input_formatted, stdout) {
for (var i = 0; i < minify_options.length; i++) { for (var i = 0; i < minify_options.length; i++) {
var options = JSON.parse(minify_options[i]); var options = JSON.parse(minify_options[i]);
if (expression) {
if (!options.parse || typeof options.parse != "object") options.parse = {};
options.parse.expression = true;
if (options.compress == null) options.compress = {};
if (options.compress) {
if (typeof options.compress != "object") options.compress = {};
options.compress.expression = true;
}
}
[ [
"keep_fargs", "keep_fargs",
"keep_fnames", "keep_fnames",
@@ -210,7 +231,7 @@ function reminify(orig_options, input_code, input_formatted, stdout) {
} else { } else {
var toplevel = sandbox.has_toplevel(options); var toplevel = sandbox.has_toplevel(options);
var expected = stdout[toplevel ? 1 : 0]; var expected = stdout[toplevel ? 1 : 0];
var actual = sandbox.run_code(result.code, toplevel); var actual = run_code(expression, result.code, toplevel);
if (typeof expected != "string" && typeof actual != "string" && expected.name == actual.name) { if (typeof expected != "string" && typeof actual != "string" && expected.name == actual.name) {
actual = expected; actual = expected;
} }
@@ -245,18 +266,25 @@ function reminify(orig_options, input_code, input_formatted, stdout) {
return true; return true;
} }
function run_code(expression, code, toplevel) {
return sandbox.run_code(expression ? "console.log(" + code + ");" : code, toplevel);
}
function test_case(test) { function test_case(test) {
log(" Running test [{name}]", { name: test.name }); log(" Running test [{name}]", { name: test.name });
U.AST_Node.enable_validation(); U.AST_Node.enable_validation();
var output_options = test.beautify || {}; var output_options = test.beautify || {};
var expect; var expect;
if (test.expect) { if (test.expect) {
expect = make_code(to_toplevel(test.expect, test.mangle), output_options); expect = to_toplevel(test.expect, test.mangle, test.expression);
expect = make_code(expect, output_options, test.expression);
} else { } else {
expect = test.expect_exact; expect = test.expect_exact;
} }
var input = to_toplevel(test.input, test.mangle); var input = to_toplevel(test.input, test.mangle, test.expression);
var input_code = make_code(input); var input_code = make_code(input, {
keep_quoted_props: true,
}, test.expression);
var input_formatted = make_code(test.input, { var input_formatted = make_code(test.input, {
annotations: true, annotations: true,
beautify: true, beautify: true,
@@ -266,7 +294,7 @@ function test_case(test) {
}); });
try { try {
input.validate_ast(); input.validate_ast();
U.parse(input_code); U.parse(input_code, { expression: test.expression });
} catch (ex) { } catch (ex) {
log([ log([
"!!! Cannot parse input", "!!! Cannot parse input",
@@ -292,8 +320,9 @@ function test_case(test) {
warnings_emitted.push(text); warnings_emitted.push(text);
}, /"INFO: /.test(expected_warnings)); }, /"INFO: /.test(expected_warnings));
} }
var quoted_props;
if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) { if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) {
var quoted_props = test.mangle.properties.reserved; quoted_props = test.mangle.properties.reserved;
if (!Array.isArray(quoted_props)) quoted_props = []; if (!Array.isArray(quoted_props)) quoted_props = [];
test.mangle.properties.reserved = quoted_props; test.mangle.properties.reserved = quoted_props;
U.reserve_quoted_keys(input, quoted_props); U.reserve_quoted_keys(input, quoted_props);
@@ -308,9 +337,10 @@ function test_case(test) {
if (test.mangle) { if (test.mangle) {
output.compute_char_frequency(test.mangle); output.compute_char_frequency(test.mangle);
output.mangle_names(test.mangle); output.mangle_names(test.mangle);
if (quoted_props) U.reserve_quoted_keys(input, quoted_props);
if (test.mangle.properties) U.mangle_properties(output, test.mangle.properties); if (test.mangle.properties) U.mangle_properties(output, test.mangle.properties);
} }
var output_code = make_code(output, output_options); var output_code = make_code(output, output_options, test.expression);
U.AST_Node.log_function(); U.AST_Node.log_function();
if (expect != output_code) { if (expect != output_code) {
log([ log([
@@ -333,7 +363,7 @@ function test_case(test) {
// expect == output // expect == output
try { try {
output.validate_ast(); output.validate_ast();
U.parse(output_code); U.parse(output_code, { expression: test.expression });
} catch (ex) { } catch (ex) {
log([ log([
"!!! Test matched expected result but cannot parse output", "!!! Test matched expected result but cannot parse output",
@@ -377,7 +407,7 @@ function test_case(test) {
} }
} }
if (test.expect_stdout && (!test.node_version || semver.satisfies(process.version, test.node_version))) { if (test.expect_stdout && (!test.node_version || semver.satisfies(process.version, test.node_version))) {
var stdout = [ sandbox.run_code(input_code), sandbox.run_code(input_code, true) ]; var stdout = [ run_code(test.expression, input_code), run_code(test.expression, input_code, true) ];
var toplevel = sandbox.has_toplevel({ var toplevel = sandbox.has_toplevel({
compress: test.options, compress: test.options,
mangle: test.mangle mangle: test.mangle
@@ -406,7 +436,7 @@ function test_case(test) {
}); });
return false; return false;
} }
actual = sandbox.run_code(output_code, toplevel); actual = run_code(test.expression, output_code, toplevel);
if (!sandbox.same_stdout(test.expect_stdout, actual)) { if (!sandbox.same_stdout(test.expect_stdout, actual)) {
log([ log([
"!!! failed", "!!! failed",
@@ -427,7 +457,7 @@ function test_case(test) {
}); });
return false; return false;
} }
if (!reminify(test.options, input_code, input_formatted, stdout)) { if (!reminify(test.expression, test.options, input_code, input_formatted, stdout)) {
return false; return false;
} }
} }
@@ -438,20 +468,30 @@ function tmpl() {
return U.string_template.apply(null, arguments); return U.string_template.apply(null, arguments);
} }
function to_toplevel(input, mangle_options) { function to_toplevel(input, mangle_options, expression) {
if (!(input instanceof U.AST_BlockStatement)) throw new Error("Unsupported input syntax"); if (!(input instanceof U.AST_BlockStatement)) throw new Error("Unsupported input syntax");
var directive = true;
var offset = input.start.line; var offset = input.start.line;
var tokens = []; var tokens = [];
var toplevel = new U.AST_Toplevel(input.transform(new U.TreeTransformer(function(node) { input.walk(new U.TreeWalker(function(node) {
if (U.push_uniq(tokens, node.start)) node.start.line -= offset; if (U.push_uniq(tokens, node.start)) node.start.line -= offset;
if (!directive || node === input) return; if (U.push_uniq(tokens, node.end)) node.end.line -= offset;
}));
var toplevel;
if (!expression) {
var directive = true;
toplevel = new U.AST_Toplevel(input.transform(new U.TreeTransformer(function(node) {
if (!directive) return node;
if (node === input) return;
if (node instanceof U.AST_SimpleStatement && node.body instanceof U.AST_String) { if (node instanceof U.AST_SimpleStatement && node.body instanceof U.AST_String) {
return new U.AST_Directive(node.body); return new U.AST_Directive(node.body);
} else {
directive = false;
} }
directive = false;
}))); })));
} else if (input.body.length == 1) {
toplevel = input.body[0].wrap_expression();
} else {
throw new Error("Invalid expression");
}
toplevel.figure_out_scope(mangle_options); toplevel.figure_out_scope(mangle_options);
return toplevel; return toplevel;
} }

View File

@@ -668,6 +668,87 @@ single_use_recursive: {
node_version: ">=4" node_version: ">=4"
} }
inline_iife_within_arrow: {
options = {
arrows: true,
inline: true,
}
input: {
var f = () => console.log(function(a) {
return Math.ceil(a);
}(Math.random()));
f();
}
expect: {
var f = () => {
return console.log((a = Math.random(), Math.ceil(a)));
var a;
};
f();
}
expect_stdout: "1"
node_version: ">=4"
}
instanceof_lambda_1: {
options = {
evaluate: true,
side_effects: true,
}
input: {
console.log(42 instanceof (() => {}));
}
expect: {
console.log(false);
}
expect_stdout: "false"
node_version: ">=4"
}
instanceof_lambda_2: {
options = {
evaluate: true,
side_effects: false,
}
input: {
console.log(null instanceof (() => {}));
}
expect: {
console.log((null, () => {}, false));
}
expect_stdout: "false"
node_version: ">=4"
}
instanceof_lambda_3: {
options = {
evaluate: true,
side_effects: true,
}
input: {
console.log({} instanceof (() => {}));
}
expect: {
console.log({} instanceof (() => {}));
}
expect_stdout: TypeError("Function has non-object prototype 'undefined' in instanceof check")
node_version: ">=4"
}
instanceof_lambda_4: {
options = {
side_effects: true,
}
input: {
({ p: "foo" }) instanceof (() => {});
}
expect: {
[] instanceof (() => {});
}
expect_stdout: TypeError("Function has non-object prototype 'undefined' in instanceof check")
node_version: ">=4"
}
issue_4388: { issue_4388: {
options = { options = {
inline: true, inline: true,
@@ -1212,3 +1293,28 @@ issue_5495: {
expect_stdout: "undefined" expect_stdout: "undefined"
node_version: ">=4" node_version: ">=4"
} }
issue_5653: {
options = {
arrows: true,
hoist_props: true,
passes: 2,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
console.log((a => {
a = { p: console };
return a++;
})());
}
expect: {
console.log((a => {
return console, +{};
})());
}
expect_stdout: "NaN"
node_version: ">=4"
}

View File

@@ -290,6 +290,45 @@ increment_decrement_2: {
expect_stdout: "42" expect_stdout: "42"
} }
lazily_chained_assignments: {
options = {
assignments: true,
collapse_vars: true,
conditionals: true,
unused: true,
}
input: {
function f(a) {
if (a = console.log("foo"))
a = console.log("bar");
return a;
}
function g(b) {
if (b = console.log("baz"))
;
else
b = console.log("moo");
return b;
}
console.log(f(), g());
}
expect: {
function f(a) {
return console.log("foo") && console.log("bar");
}
function g(b) {
return console.log("baz") || console.log("moo");
}
console.log(f(), g());
}
expect_stdout: [
"foo",
"baz",
"moo",
"undefined undefined",
]
}
issue_3375_1: { issue_3375_1: {
options = { options = {
assignments: true, assignments: true,
@@ -803,3 +842,23 @@ issue_4924_2: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=15" node_version: ">=15"
} }
issue_5670: {
options = {
assignments: true,
evaluate: true,
reduce_vars: true,
}
input: {
(function(a, b) {
a && a && (a = b += "") || console.log("PASS");
})();
}
expect: {
(function(a, b) {
a = a,
console.log("PASS");
})();
}
expect_stdout: "PASS"
}

View File

@@ -529,6 +529,7 @@ inline_block_await: {
inline_block_await_async: { inline_block_await_async: {
options = { options = {
awaits: true,
inline: true, inline: true,
} }
input: { input: {
@@ -1347,7 +1348,7 @@ functions_inner_var: {
node_version: ">=8" node_version: ">=8"
} }
instanceof_lambda: { instanceof_lambda_1: {
options = { options = {
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
@@ -1362,6 +1363,50 @@ instanceof_lambda: {
node_version: ">=8" node_version: ">=8"
} }
instanceof_lambda_2: {
options = {
evaluate: true,
side_effects: false,
}
input: {
console.log(null instanceof async function() {});
}
expect: {
console.log((null, async function() {}, false));
}
expect_stdout: "false"
node_version: ">=8"
}
instanceof_lambda_3: {
options = {
evaluate: true,
side_effects: true,
}
input: {
console.log({} instanceof async function() {});
}
expect: {
console.log({} instanceof async function() {});
}
expect_stdout: TypeError("Function has non-object prototype 'undefined' in instanceof check")
node_version: ">=8"
}
instanceof_lambda_4: {
options = {
side_effects: true,
}
input: {
({ p: "foo" }) instanceof async function() {};
}
expect: {
[] instanceof async function() {};
}
expect_stdout: TypeError("Function has non-object prototype 'undefined' in instanceof check")
node_version: ">=8"
}
issue_4335_1: { issue_4335_1: {
options = { options = {
inline: true, inline: true,
@@ -2747,6 +2792,7 @@ issue_5177: {
issue_5250: { issue_5250: {
options = { options = {
awaits: true,
inline: true, inline: true,
} }
input: { input: {
@@ -2855,6 +2901,7 @@ issue_5298: {
issue_5305_1: { issue_5305_1: {
options = { options = {
awaits: true,
inline: true, inline: true,
} }
input: { input: {
@@ -2888,6 +2935,7 @@ issue_5305_1: {
issue_5305_2: { issue_5305_2: {
options = { options = {
awaits: true,
inline: true, inline: true,
} }
input: { input: {
@@ -3078,6 +3126,7 @@ issue_5506: {
issue_5528_1: { issue_5528_1: {
options = { options = {
awaits: true,
inline: true, inline: true,
} }
input: { input: {
@@ -3113,6 +3162,7 @@ issue_5528_1: {
issue_5528_2: { issue_5528_2: {
options = { options = {
awaits: true,
inline: true, inline: true,
} }
input: { input: {
@@ -3148,6 +3198,7 @@ issue_5528_2: {
issue_5528_3: { issue_5528_3: {
options = { options = {
awaits: true,
inline: true, inline: true,
} }
input: { input: {
@@ -3188,6 +3239,7 @@ issue_5528_3: {
issue_5528_4: { issue_5528_4: {
options = { options = {
awaits: true,
inline: true, inline: true,
} }
input: { input: {
@@ -3229,3 +3281,427 @@ issue_5528_4: {
] ]
node_version: ">=8" node_version: ">=8"
} }
issue_5634_1: {
options = {
awaits: true,
inline: true,
}
input: {
var a = "foo";
(async function() {
(async function() {
try {
return {
then(resolve) {
console.log("bar");
resolve();
console.log("baz");
},
};
} finally {
a = "moo";
}
})();
})();
console.log(a);
}
expect: {
var a = "foo";
(async function() {
(async function() {
try {
return {
then(resolve) {
console.log("bar");
resolve();
console.log("baz");
},
};
} finally {
a = "moo";
}
})();
})();
console.log(a);
}
expect_stdout: [
"moo",
"bar",
"baz",
]
node_version: ">=8"
}
issue_5634_1_side_effects: {
options = {
awaits: true,
inline: true,
side_effects: true,
}
input: {
var a = "foo";
(async function() {
(async function() {
try {
return {
then(resolve) {
console.log("bar");
resolve();
console.log("baz");
},
};
} finally {
a = "moo";
}
})();
})();
console.log(a);
}
expect: {
var a = "foo";
(async function() {
try {
return {
then(resolve) {
console.log("bar");
resolve();
console.log("baz");
},
};
} finally {
a = "moo";
}
})();
console.log(a);
}
expect_stdout: [
"moo",
"bar",
"baz",
]
node_version: ">=8"
}
issue_5634_2: {
options = {
awaits: true,
inline: true,
}
input: {
var a = "foo";
(async function() {
await async function() {
try {
return {
then(resolve) {
console.log("bar");
resolve();
console.log("baz");
},
};
} finally {
a = "moo";
}
}();
})();
console.log(a);
}
expect: {
var a = "foo";
(async function() {
await async function() {
try {
return {
then(resolve) {
console.log("bar");
resolve();
console.log("baz");
},
};
} finally {
a = "moo";
}
}();
})();
console.log(a);
}
expect_stdout: [
"moo",
"bar",
"baz",
]
node_version: ">=8"
}
issue_5634_2_side_effects: {
options = {
awaits: true,
inline: true,
side_effects: true,
}
input: {
var a = "foo";
(async function() {
await async function() {
try {
return {
then(resolve) {
console.log("bar");
resolve();
console.log("baz");
},
};
} finally {
a = "moo";
}
}();
})();
console.log(a);
}
expect: {
var a = "foo";
(async function() {
try {
return {
then(resolve) {
console.log("bar");
resolve();
console.log("baz");
},
};
} finally {
a = "moo";
}
})();
console.log(a);
}
expect_stdout: [
"moo",
"bar",
"baz",
]
node_version: ">=8"
}
issue_5634_3: {
options = {
awaits: true,
inline: true,
}
input: {
var a = "foo";
(async function() {
return async function() {
try {
return {
then(resolve) {
console.log("bar");
resolve();
console.log("baz");
},
};
} finally {
a = "moo";
}
}();
})();
console.log(a);
}
expect: {
var a = "foo";
(async function() {
return async function() {
try {
return {
then(resolve) {
console.log("bar");
resolve();
console.log("baz");
},
};
} finally {
a = "moo";
}
}();
})();
console.log(a);
}
expect_stdout: [
"moo",
"bar",
"baz",
]
node_version: ">=8"
}
issue_5634_3_side_effects: {
options = {
awaits: true,
inline: true,
side_effects: true,
}
input: {
var a = "foo";
(async function() {
return async function() {
try {
return {
then(resolve) {
console.log("bar");
resolve();
console.log("baz");
},
};
} finally {
a = "moo";
}
}();
})();
console.log(a);
}
expect: {
var a = "foo";
(async function() {
try {
return {
then(resolve) {
console.log("bar");
resolve();
console.log("baz");
},
};
} finally {
a = "moo";
}
})();
console.log(a);
}
expect_stdout: [
"moo",
"bar",
"baz",
]
node_version: ">=8"
}
issue_5692_1: {
options = {
awaits: true,
inline: true,
}
input: {
(async function() {
(async function() {
for await (var k of []);
})();
console.log("foo");
})();
console.log("bar");
}
expect: {
(async function() {
(async function() {
for await (var k of []);
})();
console.log("foo");
})();
console.log("bar");
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=10"
}
issue_5692_2: {
options = {
awaits: true,
inline: true,
}
input: {
(async function() {
(async function() {
for (var k of []);
})();
console.log("foo");
})();
console.log("bar");
}
expect: {
(async function() {
for (var k of []);
console.log("foo");
})();
console.log("bar");
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=8"
}
issue_5791: {
options = {
awaits: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
(async function() {
async function f() {
try {
await {
then(resolve) {
setImmediate(() => {
console.log("foo");
resolve();
});
},
};
} catch (e) {
console.log("FAIL", e);
}
}
async function g() {
try {
await f();
} catch (e) {}
}
await g();
console.log("bar");
})();
}
expect: {
(async function() {
await async function() {
try {
await async function() {
try {
await {
then(resolve) {
setImmediate(() => {
console.log("foo");
resolve();
});
},
};
} catch (e) {
console.log("FAIL", e);
}
}();
} catch (e) {}
}();
console.log("bar");
})();
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=8"
}

View File

@@ -90,3 +90,17 @@ issue_4801: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=10.4.0" node_version: ">=10.4.0"
} }
issue_5728: {
options = {
evaluate: true,
}
input: {
console.log("" + 4n + 2);
}
expect: {
console.log("42");
}
expect_stdout: "42"
node_version: ">=10.4.0"
}

View File

@@ -47,3 +47,45 @@ keep_some_blocks: {
} else stuff(); } else stuff();
} }
} }
issue_1666: {
input: {
var a = 42;
{
function a() {}
a();
}
console.log("PASS");
}
expect: {
var a = 42;
{
function a() {}
a();
}
console.log("PASS");
}
expect_stdout: true
}
issue_1666_strict: {
input: {
"use strict";
var a = 42;
{
function a() {}
a();
}
console.log("PASS");
}
expect: {
"use strict";
var a = 42;
{
function a() {}
a();
}
console.log("PASS");
}
expect_stdout: true
}

View File

@@ -80,6 +80,25 @@ de_morgan_1c: {
expect_stdout: "true" expect_stdout: "true"
} }
de_morgan_1d: {
options = {
booleans: true,
}
input: {
function f(a) {
return (a = false) || a;
}
console.log(f(null), f(42));
}
expect: {
function f(a) {
return a = !1;
}
console.log(f(null), f(42));
}
expect_stdout: "false false"
}
de_morgan_2a: { de_morgan_2a: {
options = { options = {
booleans: true, booleans: true,
@@ -181,6 +200,31 @@ de_morgan_2d: {
] ]
} }
de_morgan_2e: {
options = {
booleans: true,
conditionals: true,
}
input: {
function f(a, b) {
return (a && b) && b;
}
console.log(f(null), f(null, {}));
console.log(f(42), f(42, {}));
}
expect: {
function f(a, b) {
return a && b;
}
console.log(f(null), f(null, {}));
console.log(f(42), f(42, {}));
}
expect_stdout: [
"null null",
"undefined {}",
]
}
de_morgan_3a: { de_morgan_3a: {
options = { options = {
booleans: true, booleans: true,
@@ -786,3 +830,37 @@ issue_5469: {
} }
expect_stdout: "undefined" expect_stdout: "undefined"
} }
issue_5694_1: {
options = {
booleans: true,
conditionals: true,
}
input: {
var Infinity;
// Node.js v0.12~6 (vm): 42
console.log((Infinity = 42) && Infinity);
}
expect: {
var Infinity;
console.log((Infinity = 42) && Infinity);
}
expect_stdout: true
}
issue_5694_2: {
options = {
booleans: true,
conditionals: true,
}
input: {
var undefined;
// Node.js v0.12~6 (vm): NaN
console.log(("foo", ++undefined) || undefined);
}
expect: {
var undefined;
console.log(("foo", ++undefined) || undefined);
}
expect_stdout: true
}

View File

@@ -241,6 +241,94 @@ class_super: {
node_version: ">=4" node_version: ">=4"
} }
static_newline_1: {
input: {
class A {
static
P
}
console.log("P" in A, "static" in A);
console.log("P" in new A(), "static" in new A());
}
expect_exact: 'class A{static P}console.log("P"in A,"static"in A);console.log("P"in new A,"static"in new A);'
expect_stdout: [
"true false",
"false false",
]
node_version: ">=12"
}
static_newline_2: {
input: {
class A {
static
static
P
}
console.log("P" in A, "static" in A);
console.log("P" in new A(), "static" in new A());
}
expect_exact: 'class A{static static;P}console.log("P"in A,"static"in A);console.log("P"in new A,"static"in new A);'
expect_stdout: [
"false true",
"true false",
]
node_version: ">=12"
}
static_newline_3: {
input: {
class A {
static
static
static
P
}
console.log("P" in A, "static" in A);
console.log("P" in new A(), "static" in new A());
}
expect_exact: 'class A{static static;static P}console.log("P"in A,"static"in A);console.log("P"in new A,"static"in new A);'
expect_stdout: [
"true true",
"false false",
]
node_version: ">=12"
}
static_newline_4: {
input: {
class A {
static
static
static
static
P
}
console.log("P" in A, "static" in A);
console.log("P" in new A(), "static" in new A());
}
expect_exact: 'class A{static static;static static;P}console.log("P"in A,"static"in A);console.log("P"in new A,"static"in new A);'
expect_stdout: [
"false true",
"true false",
]
node_version: ">=12"
}
static_newline_init: {
input: {
class A {
static
{
console.log("PASS");
}
}
}
expect_exact: 'class A{static{console.log("PASS")}}'
expect_stdout: "PASS"
node_version: ">=16"
}
static_init: { static_init: {
input: { input: {
var a = "foo"; var a = "foo";
@@ -511,6 +599,7 @@ drop_extends: {
inline: true, inline: true,
passes: 2, passes: 2,
pure_getters: "strict", pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
sequences: true, sequences: true,
side_effects: true, side_effects: true,
@@ -658,6 +747,56 @@ separate_name: {
node_version: ">=4" node_version: ">=4"
} }
static_getter: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
"use strict";
(class {
static get p() {
console.log("PASS");
};
}).p;
}
expect: {
"use strict";
(class {
static get p() {
console.log("PASS");
};
}).p;
}
expect_stdout: "PASS"
node_version: ">=4"
}
static_setter: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
"use strict";
(class {
static set p(v) {
console.log(v);
};
}).p = "PASS";
}
expect: {
"use strict";
(class {
static set p(v) {
console.log(v);
};
}).p = "PASS";
}
expect_stdout: "PASS"
node_version: ">=4"
}
static_side_effects: { static_side_effects: {
options = { options = {
inline: true, inline: true,
@@ -783,6 +922,7 @@ single_use_3: {
single_use_4: { single_use_4: {
options = { options = {
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
unused: true, unused: true,
@@ -1025,9 +1165,9 @@ collapse_rhs_static: {
"use strict"; "use strict";
var a = "FAIL"; var a = "FAIL";
class A { class A {
static p = a = "PASS"; static p = "PASS";
} }
console.log(a); console.log(a = "PASS");
} }
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=12" node_version: ">=12"
@@ -1365,6 +1505,218 @@ keep_instanceof_3: {
node_version: ">=4" node_version: ">=4"
} }
keep_field_reference_1: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
function f() {}
class A {
p = f;
}
console.log(new A().p === new A().p ? "PASS" : "FAIL");
}
expect: {
"use strict";
function f() {}
class A {
p = f;
}
console.log(new A().p === new A().p ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=12"
}
keep_field_reference_2: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
function f() {}
var A = class {
p = f;
};
console.log(new A().p === new A().p ? "PASS" : "FAIL");
}
expect: {
"use strict";
function f() {}
var A = class {
p = f;
};
console.log(new A().p === new A().p ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=12"
}
keep_field_reference_3: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
class A {}
class B {
p = A;
}
console.log(new B().p === new B().p ? "PASS" : "FAIL");
}
expect: {
"use strict";
class A {}
class B {
p = A;
}
console.log(new B().p === new B().p ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=12"
}
keep_field_reference_4: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var A = class {};
var B = class {
p = A;
};
console.log(new B().p === new B().p ? "PASS" : "FAIL");
}
expect: {
"use strict";
var A = class {};
var B = class {
p = A;
};
console.log(new B().p === new B().p ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=12"
}
keep_static_field_reference_1: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
function f() {}
class A {
static P = f;
}
console.log(A.P === A.P ? "PASS" : "FAIL");
}
expect: {
"use strict";
class A {
static P = function() {};
}
console.log(A.P === A.P ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=12"
}
keep_static_field_reference_2: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
function f() {}
var A = class {
static P = f;
};
console.log(A.P === A.P ? "PASS" : "FAIL");
}
expect: {
"use strict";
var A = class {
static P = function() {};
};
console.log(A.P === A.P ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=12"
}
keep_static_field_reference_3: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
class A {}
class B {
static P = A;
}
console.log(B.P === B.P ? "PASS" : "FAIL");
}
expect: {
"use strict";
class B {
static P = class {};
}
console.log(B.P === B.P ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=12"
}
keep_static_field_reference_4: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var A = class {};
var B = class {
static P = A;
};
console.log(B.P === B.P ? "PASS" : "FAIL");
}
expect: {
"use strict";
var B = class {
static P = class {};
};
console.log(B.P === B.P ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=12"
}
issue_805_1: { issue_805_1: {
options = { options = {
inline: true, inline: true,
@@ -2026,6 +2378,7 @@ issue_4829_2: {
mangle_properties: { mangle_properties: {
mangle = { mangle = {
properties: { properties: {
domprops: true,
keep_quoted: true, keep_quoted: true,
}, },
} }
@@ -2062,6 +2415,14 @@ mangle_properties: {
console.log(A.s, new A().e); console.log(A.s, new A().e);
} }
expect_stdout: "PASS 42" expect_stdout: "PASS 42"
expect_warnings: [
"INFO: Preserving reserved property q",
"INFO: Mapping property #P to #t",
"INFO: Mapping property Q to s",
"INFO: Mapping property #p to #i",
"INFO: Mapping property r to e",
"INFO: Preserving reserved property log",
]
node_version: ">=14.6" node_version: ">=14.6"
} }
@@ -2166,6 +2527,7 @@ issue_4962_1: {
options = { options = {
ie: true, ie: true,
inline: true, inline: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -2197,6 +2559,7 @@ issue_4962_1_strict: {
options = { options = {
ie: true, ie: true,
inline: true, inline: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -2224,6 +2587,7 @@ issue_4962_1_strict_direct: {
options = { options = {
ie: true, ie: true,
inline: true, inline: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -2255,6 +2619,7 @@ issue_4962_2: {
options = { options = {
ie: true, ie: true,
inline: true, inline: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -2286,6 +2651,7 @@ issue_4962_2_strict: {
options = { options = {
ie: true, ie: true,
inline: true, inline: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -2314,6 +2680,7 @@ issue_4962_2_strict_direct: {
options = { options = {
ie: true, ie: true,
inline: true, inline: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -2348,6 +2715,7 @@ issue_4962_2_strict_direct_inline: {
ie: true, ie: true,
inline: true, inline: true,
passes: 2, passes: 2,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -2731,6 +3099,7 @@ issue_5053_4: {
issue_5082_1: { issue_5082_1: {
options = { options = {
inline: true, inline: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -2763,6 +3132,7 @@ issue_5082_1: {
issue_5082_1_strict: { issue_5082_1_strict: {
options = { options = {
inline: true, inline: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -2796,6 +3166,7 @@ issue_5082_2: {
options = { options = {
inline: true, inline: true,
passes: 2, passes: 2,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -2829,6 +3200,7 @@ issue_5082_2_static: {
options = { options = {
inline: true, inline: true,
passes: 2, passes: 2,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -3440,3 +3812,221 @@ issue_5531_3: {
expect_stdout: "foo" expect_stdout: "foo"
node_version: ">=16" node_version: ">=16"
} }
issue_5662: {
options = {
inline: true,
reduce_vars: true,
}
input: {
console.log(new (function() {
var g = function(a) {
return a;
};
return class {
h(b) {
return g(b);
}
};
}())().h("PASS"));
}
expect: {
console.log(new (function() {
var g = function(a) {
return a;
};
return class {
h(b) {
return g(b);
}
};
}())().h("PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5682_class_key: {
mangle = {
properties: true,
}
input: {
"use strict";
function f(a) {
return "foo" in a;
}
class A {
foo() {}
}
console.log(f(new A()) ? "PASS" : "FAIL");
}
expect: {
"use strict";
function f(o) {
return "o" in o;
}
class A {
o() {}
}
console.log(f(new A()) ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5682_class_key_computed: {
mangle = {
properties: true,
}
input: {
"use strict";
function f(a) {
return "foo" in a;
}
class A {
["foo"]() {}
}
console.log(f(new A()) ? "PASS" : "FAIL");
}
expect: {
"use strict";
function f(o) {
return "o" in o;
}
class A {
["o"]() {}
}
console.log(f(new A()) ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5724: {
options = {
arrows: true,
inline: true,
keep_fargs: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
class A {
static P = function(a) {
console.log(a, a);
}(a);
}
}
expect: {
"use strict";
(function(a) {
console.log(a, a);
})(a);
}
expect_stdout: ReferenceError("a is not defined")
node_version: ">=12"
}
issue_5735_1: {
options = {
inline: true,
}
input: {
console.log(typeof function(a) {
return class {
static P = { ...a };
};
}([ 42..p ] = []));
}
expect: {
console.log(typeof function(a) {
return class {
static P = { ...a };
};
}([ 42..p ] = []));
}
expect_stdout: "function"
node_version: ">=12"
}
issue_5735_2: {
options = {
inline: true,
}
input: {
console.log(typeof function(a) {
return class {
p = a;
};
}(console.log("PASS")));
}
expect: {
console.log(typeof function(a) {
return class {
p = a;
};
}(console.log("PASS")));
}
expect_stdout: [
"PASS",
"function",
]
node_version: ">=12"
}
issue_5747_1: {
options = {
collapse_vars: true,
}
input: {
"use strict";
(async function() {
var a = await 42;
class A {
static P = a && console.log(typeof this);
}
})();
}
expect: {
"use strict";
(async function() {
var a = await 42;
class A {
static P = a && console.log(typeof this);
}
})();
}
expect_stdout: "function"
node_version: ">=12"
}
issue_5747_2: {
options = {
collapse_vars: true,
}
input: {
"use strict";
(async function() {
var a = await 42;
class A {
static {
a && console.log(typeof this);
}
}
})();
}
expect: {
"use strict";
(async function() {
var a = await 42;
class A {
static {
a && console.log(typeof this);
}
}
})();
}
expect_stdout: "function"
node_version: ">=16"
}

View File

@@ -9321,12 +9321,11 @@ issue_4874: {
})(a = 42); })(a = 42);
} }
expect: { expect: {
var a;
null; null;
(function(b) { (function(b) {
for (var c in a && a[console.log("PASS")]) for (var c in 42, 42[console.log("PASS")])
console; console;
})(a = 42); })();
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
@@ -9865,7 +9864,8 @@ issue_5276: {
} }
expect: { expect: {
var a = A = "PASS"; var a = A = "PASS";
a.p = a.p + null - 42; a.p += null;
a.p -= 42;
console.log(a); console.log(a);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -10001,3 +10001,286 @@ issue_5568: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_5638_1: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a;
console;
a = [ 42 ];
console || FAIL(a);
console.log(a++);
}
expect: {
var a;
console;
a = [ 42 ];
console || FAIL(a);
console.log(a++);
}
expect_stdout: "42"
}
issue_5638_2: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a;
console;
a = [ 6 ];
console || FAIL(a);
console.log(a *= 7);
}
expect: {
var a;
console;
a = [ 6 ];
console || FAIL(a);
console.log(a *= 7);
}
expect_stdout: "42"
}
issue_5638_3: {
options = {
collapse_vars: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var a = { foo: 42 }, b;
for (var k in a) {
b = a[k];
log(k || b, b++);
}
}
expect: {
var log = console.log;
var a = { foo: 42 }, b;
for (var k in a) {
b = a[k];
log(k || b, b++);
}
}
expect_stdout: "foo 42"
}
issue_5638_4: {
options = {
collapse_vars: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var a = { foo: 6 }, b;
for (var k in a) {
b = a[k];
log(k || b, b *= 7);
}
}
expect: {
var log = console.log;
var a = { foo: 6 }, b;
for (var k in a) {
b = a[k];
log(k || b, b *= 7);
}
}
expect_stdout: "foo 42"
}
issue_5643: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 3, b;
a *= 7;
b = !!this;
console || console.log(b);
console.log(a * ++b);
}
expect: {
var a = 3, b;
a *= 7;
b = !!this;
console || console.log(b);
console.log(a * ++b);
}
expect_stdout: "42"
}
issue_5719: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 42, b;
switch (b = a) {
case a:
case b:
case a++:
}
console.log(a === b++ ? "PASS" : "FAIL");
}
expect: {
var a = 42, b;
switch (b = a) {
case a:
case b:
case a++:
}
console.log(a === b++ ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
}
issue_5779: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
}
input: {
var a = A = "foo";
a.p = 42;
if (a && !a.p)
console.log("PASS");
}
expect: {
var a = A = "foo";
a.p = 42;
if (a, !a.p)
console.log("PASS");
}
expect_stdout: "PASS"
}
issue_1666: {
options = {
collapse_vars: true,
}
input: {
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect: {
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect_stdout: true
}
issue_1666_strict: {
options = {
collapse_vars: true,
}
input: {
"use strict";
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect: {
"use strict";
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect_stdout: true
}
issue_1666_undefined: {
options = {
collapse_vars: true,
}
input: {
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect: {
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect_stdout: true
}
issue_1666_undefined_strict: {
options = {
collapse_vars: true,
}
input: {
"use strict";
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect: {
"use strict";
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect_stdout: true
}

View File

@@ -275,6 +275,7 @@ issue_2857_3: {
issue_2857_4: { issue_2857_4: {
options = { options = {
comparisons: true, comparisons: true,
conditionals: true,
} }
input: { input: {
function f(a, p) { function f(a, p) {
@@ -305,6 +306,7 @@ issue_2857_4: {
issue_2857_5: { issue_2857_5: {
options = { options = {
comparisons: true, comparisons: true,
conditionals: true,
} }
input: { input: {
function f(a, p) { function f(a, p) {
@@ -528,6 +530,7 @@ nullish_assign: {
nullish_chain: { nullish_chain: {
options = { options = {
comparisons: true, comparisons: true,
conditionals: true,
} }
input: { input: {
var a; var a;

View File

@@ -12,7 +12,7 @@ concat_1: {
var e = 1 + x() + 2 + "X" + 3 + "boo"; var e = 1 + x() + 2 + "X" + 3 + "boo";
// be careful with concatentation with "\0" with octal-looking strings. // be careful with concatenation with "\0" with octal-looking strings.
var f = "\0" + 360 + "\0" + 8 + "\0"; var f = "\0" + 360 + "\0" + 8 + "\0";
} }
expect: { expect: {
@@ -273,6 +273,23 @@ concat_9: {
expect_stdout: true expect_stdout: true
} }
concat_sequence: {
options = {
collapse_vars: true,
strings: true,
toplevel: true,
unused: true,
}
input: {
var a;
console.log(12 + (a = null, "34" + a));
}
expect: {
console.log(12 + "34" + null);
}
expect_stdout: "1234null"
}
issue_3689: { issue_3689: {
options = { options = {
strings: true, strings: true,

View File

@@ -278,6 +278,159 @@ merge_tail_2: {
] ]
} }
merge_tail_3: {
options = {
conditionals: true,
reduce_vars: true,
unused: true,
}
input: {
(function(a, b) {
if (b = a.shift())
console.log(b);
else {
if (b = a.shift())
while (console.log("foo"));
console.log(b);
}
})([ false, "bar" ]);
}
expect: {
(function(a, b) {
if (!(b = a.shift()) && (b = a.shift()))
while (console.log("foo"));
console.log(b);
})([ false, "bar" ]);
}
expect_stdout: [
"foo",
"bar",
]
}
merge_tail_sequence_1: {
options = {
conditionals: true,
}
input: {
function f(a) {
var b = "foo";
if (a) {
while (console.log("bar"));
console.log(b);
} else {
c = "baz";
while (console.log(c));
console.log("bar"),
console.log(b);
var c;
}
}
f();
f(42);
}
expect: {
function f(a) {
var b = "foo";
if (a)
while (console.log("bar"));
else {
c = "baz";
while (console.log(c));
console.log("bar");
var c;
}
console.log(b);
}
f();
f(42);
}
expect_stdout: [
"baz",
"bar",
"foo",
"bar",
"foo",
]
}
merge_tail_sequence_2: {
options = {
conditionals: true,
}
input: {
function f(a) {
var b = "foo";
if (a) {
console.log("bar");
console.log(b);
} else {
c = "baz";
while (console.log(c));
console.log("bar"),
console.log(b);
var c;
}
}
f();
f(42);
}
expect: {
function f(a) {
var b = "foo";
if (!a) {
c = "baz";
while (console.log(c));
var c;
}
console.log("bar");
console.log(b);
}
f();
f(42);
}
expect_stdout: [
"baz",
"bar",
"foo",
"bar",
"foo",
]
}
merge_tail_sequence_3: {
options = {
conditionals: true,
reduce_vars: true,
unused: true,
}
input: {
(function(a, b) {
if (b = a.shift())
console.log("foo"),
console.log(b);
else {
if (b = a.shift())
while (console.log("bar"));
console.log(b);
}
})([ false, "baz" ]);
}
expect: {
(function(a, b) {
if (b = a.shift())
console.log("foo");
else if (b = a.shift())
while (console.log("bar"));
console.log(b);
})([ false, "baz" ]);
}
expect_stdout: [
"bar",
"baz",
]
}
cond_1: { cond_1: {
options = { options = {
conditionals: true, conditionals: true,
@@ -1086,6 +1239,52 @@ trivial_boolean_ternary_expressions : {
} }
} }
extendscript_1: {
beautify = {
extendscript: true,
}
input: {
var alert = console.log;
function f(a, b) {
return a ? b ? "foo" : "bar" : "baz";
}
alert(f());
alert(f(42));
alert(f(null, true));
alert(f([], {}));
}
expect_exact: 'var alert=console.log;function f(a,b){return a?(b?"foo":"bar"):"baz"}alert(f());alert(f(42));alert(f(null,true));alert(f([],{}));'
expect_stdout: [
"baz",
"bar",
"baz",
"foo",
]
}
extendscript_2: {
beautify = {
extendscript: true,
}
input: {
var alert = console.log;
function f(a, b) {
return a ? "foo" : b ? "bar" : "baz";
}
alert(f());
alert(f(42));
alert(f(null, true));
alert(f([], {}));
}
expect_exact: 'var alert=console.log;function f(a,b){return a?"foo":(b?"bar":"baz")}alert(f());alert(f(42));alert(f(null,true));alert(f([],{}));'
expect_stdout: [
"baz",
"foo",
"bar",
"foo",
]
}
issue_1154: { issue_1154: {
options = { options = {
booleans: true, booleans: true,
@@ -1343,6 +1542,398 @@ condition_matches_alternative: {
expect_stdout: "null 0 false 5" expect_stdout: "null 0 false 5"
} }
condition_sequence_1: {
options = {
conditionals: true,
sequences: true,
}
input: {
function f(x, y) {
return (console.log(x), x) ? x : y;
}
console.log(f("foo", "bar"));
console.log(f(null, "baz"));
console.log(f(42));
console.log(f());
}
expect: {
function f(x, y) {
return console.log(x), x || y;
}
console.log(f("foo", "bar")),
console.log(f(null, "baz")),
console.log(f(42)),
console.log(f());
}
expect_stdout: [
"foo",
"foo",
"null",
"baz",
"42",
"42",
"undefined",
"undefined",
]
}
condition_sequence_2: {
options = {
conditionals: true,
sequences: true,
}
input: {
function f(x, y) {
return (console.log(y), y) ? x : y;
}
console.log(f("foo", "bar"));
console.log(f(null, "baz"));
console.log(f(42));
console.log(f());
}
expect: {
function f(x, y) {
return console.log(y), y && x;
}
console.log(f("foo", "bar")),
console.log(f(null, "baz")),
console.log(f(42)),
console.log(f());
}
expect_stdout: [
"bar",
"foo",
"baz",
"null",
"undefined",
"undefined",
"undefined",
"undefined",
]
}
combine_tail_sequence: {
options = {
conditionals: true,
}
input: {
var n = {
f: function() {
console.log("foo");
return this.p;
},
p: "FAIL 1",
};
var o = {
f: function() {
console.log("foz");
return this.p;
},
p: "FAIL 2",
};
var p = "PASS";
function g(a) {
return a
? (console.log("baa"), (console.log("bar"), (console.log("baz"), n).f)())
: (console.log("moo"), (console.log("mor"), (console.log("moz"), o).f)());
}
console.log(g());
console.log(g(42));
}
expect: {
var n = {
f: function() {
console.log("foo");
return this.p;
},
p: "FAIL 1",
};
var o = {
f: function() {
console.log("foz");
return this.p;
},
p: "FAIL 2",
};
var p = "PASS";
function g(a) {
return (0, (a
? (console.log("baa"), console.log("bar"), console.log("baz"), n)
: (console.log("moo"), console.log("mor"), console.log("moz"), o)).f)();
}
console.log(g());
console.log(g(42));
}
expect_stdout: [
"moo",
"mor",
"moz",
"foz",
"PASS",
"baa",
"bar",
"baz",
"foo",
"PASS",
]
}
consequent_sequence_1: {
options = {
conditionals: true,
}
input: {
function f(x, y, a) {
return x ? (console.log("seq"), y && a) : a;
}
console.log(f(false, false, 1));
console.log(f(false, true, 2));
console.log(f(true, false, 3));
console.log(f(true, true, 4));
}
expect: {
function f(x, y, a) {
return (!x || (console.log("seq"), y)) && a;
}
console.log(f(false, false, 1));
console.log(f(false, true, 2));
console.log(f(true, false, 3));
console.log(f(true, true, 4));
}
expect_stdout: [
"1",
"2",
"seq",
"false",
"seq",
"4",
]
}
consequent_sequence_2: {
options = {
conditionals: true,
}
input: {
function f(x, y, a) {
return x ? (console.log("seq"), y || a) : a;
}
console.log(f(false, false, 1));
console.log(f(false, true, 2));
console.log(f(true, false, 3));
console.log(f(true, true, 4));
}
expect: {
function f(x, y, a) {
return x && (console.log("seq"), y) || a;
}
console.log(f(false, false, 1));
console.log(f(false, true, 2));
console.log(f(true, false, 3));
console.log(f(true, true, 4));
}
expect_stdout: [
"1",
"2",
"seq",
"3",
"seq",
"true",
]
}
consequent_sequence_3: {
options = {
conditionals: true,
}
input: {
function f(x, y, a, b) {
return x ? (console.log("seq"), y ? a : b) : b;
}
console.log(f(false, false, 1, -1));
console.log(f(false, true, 2, -2));
console.log(f(true, false, 3, -3));
console.log(f(true, true, 4, -4));
}
expect: {
function f(x, y, a, b) {
return x && (console.log("seq"), y) ? a : b;
}
console.log(f(false, false, 1, -1));
console.log(f(false, true, 2, -2));
console.log(f(true, false, 3, -3));
console.log(f(true, true, 4, -4));
}
expect_stdout: [
"-1",
"-2",
"seq",
"-3",
"seq",
"4",
]
}
consequent_sequence_4: {
options = {
conditionals: true,
}
input: {
function f(x, y, a, b) {
return x ? (console.log("seq"), y ? a : b) : a;
}
console.log(f(false, false, 1, -1));
console.log(f(false, true, 2, -2));
console.log(f(true, false, 3, -3));
console.log(f(true, true, 4, -4));
}
expect: {
function f(x, y, a, b) {
return !x || (console.log("seq"), y) ? a : b;
}
console.log(f(false, false, 1, -1));
console.log(f(false, true, 2, -2));
console.log(f(true, false, 3, -3));
console.log(f(true, true, 4, -4));
}
expect_stdout: [
"1",
"2",
"seq",
"-3",
"seq",
"4",
]
}
alternative_sequence_1: {
options = {
conditionals: true,
}
input: {
function f(x, y, a) {
return x ? a : (console.log("seq"), y && a);
}
console.log(f(false, false, 1));
console.log(f(false, true, 2));
console.log(f(true, false, 3));
console.log(f(true, true, 4));
}
expect: {
function f(x, y, a) {
return (x || (console.log("seq"), y)) && a;
}
console.log(f(false, false, 1));
console.log(f(false, true, 2));
console.log(f(true, false, 3));
console.log(f(true, true, 4));
}
expect_stdout: [
"seq",
"false",
"seq",
"2",
"3",
"4",
]
}
alternative_sequence_2: {
options = {
conditionals: true,
}
input: {
function f(x, y, a) {
return x ? a : (console.log("seq"), y || a);
}
console.log(f(false, false, 1));
console.log(f(false, true, 2));
console.log(f(true, false, 3));
console.log(f(true, true, 4));
}
expect: {
function f(x, y, a) {
return !x && (console.log("seq"), y) || a;
}
console.log(f(false, false, 1));
console.log(f(false, true, 2));
console.log(f(true, false, 3));
console.log(f(true, true, 4));
}
expect_stdout: [
"seq",
"1",
"seq",
"true",
"3",
"4",
]
}
alternative_sequence_3: {
options = {
conditionals: true,
}
input: {
function f(x, y, a, b) {
return x ? a : (console.log("seq"), y ? a : b);
}
console.log(f(false, false, 1, -1));
console.log(f(false, true, 2, -2));
console.log(f(true, false, 3, -3));
console.log(f(true, true, 4, -4));
}
expect: {
function f(x, y, a, b) {
return x || (console.log("seq"), y) ? a : b;
}
console.log(f(false, false, 1, -1));
console.log(f(false, true, 2, -2));
console.log(f(true, false, 3, -3));
console.log(f(true, true, 4, -4));
}
expect_stdout: [
"seq",
"-1",
"seq",
"2",
"3",
"4",
]
}
alternative_sequence_4: {
options = {
conditionals: true,
}
input: {
function f(x, y, a, b) {
return x ? b : (console.log("seq"), y ? a : b);
}
console.log(f(false, false, 1, -1));
console.log(f(false, true, 2, -2));
console.log(f(true, false, 3, -3));
console.log(f(true, true, 4, -4));
}
expect: {
function f(x, y, a, b) {
return !x && (console.log("seq"), y) ? a : b;
}
console.log(f(false, false, 1, -1));
console.log(f(false, true, 2, -2));
console.log(f(true, false, 3, -3));
console.log(f(true, true, 4, -4));
}
expect_stdout: [
"seq",
"-1",
"seq",
"2",
"-3",
"-4",
]
}
delete_conditional_1: { delete_conditional_1: {
options = { options = {
booleans: true, booleans: true,
@@ -2350,3 +2941,150 @@ issue_5546_3: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_5666_1: {
options = {
conditionals: true,
reduce_vars: true,
unused: true,
}
input: {
var a;
(function() {
var b = a;
a ? a = b : (b++, a = b);
})();
console.log(a);
}
expect: {
var a;
(function() {
var b = a;
a = (a ? 0 : b++, b);
})();
console.log(a);
}
expect_stdout: "NaN"
}
issue_5666_2: {
options = {
conditionals: true,
reduce_vars: true,
unused: true,
}
input: {
var a = "foo";
(function() {
var b = a;
a ? (b++, a = b) : a = b;
})();
console.log(a);
}
expect: {
var a = "foo";
(function() {
var b = a;
a = (a ? b++ : 0, b);
})();
console.log(a);
}
expect_stdout: "NaN"
}
issue_5673_1: {
options = {
conditionals: true,
reduce_vars: true,
unused: true,
}
input: {
var a = "PASS", b = null;
console.log(function(c) {
return c || (b ? c : (c = a) && c);
}());
}
expect: {
var a = "PASS", b = null;
console.log(function(c) {
return c || (b || (c = a)) && c;
}());
}
expect_stdout: "PASS"
}
issue_5673_2: {
options = {
conditionals: true,
reduce_vars: true,
unused: true,
}
input: {
var a = "PASS";
console.log(function(b) {
return (b = a) ? b : (b = a) && b;
}());
}
expect: {
var a = "PASS";
console.log(function(b) {
return a || (b = a) && b;
}());
}
expect_stdout: "PASS"
}
issue_5694: {
options = {
conditionals: true,
}
input: {
FORCE_EXEC = "async()=>{}";
var a = "foo";
// Node.js v0.12~6 (vm): foo
console.log((NaN = a) ? NaN : 42);
}
expect: {
FORCE_EXEC = "async()=>{}";
var a = "foo";
console.log((NaN = a) ? NaN : 42);
}
expect_stdout: "NaN"
}
issue_5712: {
options = {
booleans: true,
conditionals: true,
evaluate: true,
}
input: {
var a = 0;
a || (++a).toString() && a && console.log("PASS");
}
expect: {
var a = 0;
a || (++a).toString() && a && console.log("PASS");
}
expect_stdout: "PASS"
}
issue_5722: {
options = {
conditionals: true,
evaluate: true,
keep_fnames: true,
side_effects: true,
}
input: {
var a = true;
a && function f() {
return 42;
}(a++) ? null + (console.log("PASS") && a++) : "";
}
expect: {
var a = true;
a && (void a++, console.log("PASS")) && a++;
}
expect_stdout: "PASS"
}

View File

@@ -2011,3 +2011,223 @@ issue_5516: {
} }
expect_stdout: "function" expect_stdout: "function"
} }
issue_5580_1: {
mangle = {}
input: {
"use strict";
console.log(function(a, b, c) {
try {
FAIL;
} catch (e) {
return function() {
var d = e, i, j;
{
const e = j;
}
return a;
}();
} finally {
const e = 42;
}
}("PASS"));
}
expect: {
"use strict";
console.log(function(r, n, t) {
try {
FAIL;
} catch (o) {
return function() {
var n = o, t, c;
{
const o = c;
}
return r;
}();
} finally {
const c = 42;
}
}("PASS"));
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5580_2: {
options = {
inline: true,
reduce_vars: true,
varify: true,
}
input: {
"use strict";
(function() {
try {
throw "PASS";
} catch (e) {
return function() {
console.log(e);
{
const e = "FAIL 1";
}
}();
} finally {
const e = "FAIL 2";
}
})();
}
expect: {
"use strict";
(function() {
try {
throw "PASS";
} catch (e) {
console.log(e);
{
const e = "FAIL 1";
}
return;
} finally {
var e = "FAIL 2";
}
})();
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5591: {
options = {
dead_code: true,
if_return: true,
}
input: {
"use strict";
function f(a) {
switch (console.log("foo")) {
case console.log("bar"):
if (console.log("baz"))
return;
else {
const a = 42;
return;
}
break;
case null:
FAIL;
}
}
f();
}
expect: {
"use strict";
function f(a) {
switch (console.log("foo")) {
case console.log("bar"):
if (console.log("baz"))
return;
else {
const a = 42;
return;
}
case null:
FAIL;
}
}
f();
}
expect_stdout: [
"foo",
"bar",
"baz",
]
node_version: ">=4"
}
issue_5656: {
options = {
collapse_vars: true,
merge_vars: true,
}
input: {
console.log(function(a) {
var b = a;
b++;
{
const a = b;
}
}());
}
expect: {
console.log(function(a) {
var b = a;
{
const a = ++b;
}
}());
}
expect_stdout: true
}
issue_5660: {
options = {
merge_vars: true,
side_effects: true,
}
input: {
function f() {
try {
a;
var b;
return b;
} catch (e) {
var a = "FAIL";
const b = null;
return a;
}
}
console.log(f());
}
expect: {
function f() {
try {
var b;
return b;
} catch (e) {
var a = "FAIL";
const b = null;
return a;
}
}
console.log(f());
}
expect_stdout: true
}
issue_5787: {
options = {
unused: true,
}
input: {
console.log(function() {
const a = 42;
switch (a) {
case 42:
const a = "PASS";
return a;
}
}());
}
expect: {
console.log(function() {
const a = 42;
switch (a) {
case 42:
const a = "PASS";
return a;
}
}());
}
expect_stdout: true
}

View File

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

View File

@@ -668,6 +668,8 @@ drop_fargs: {
hoist_vars: { hoist_vars: {
options = { options = {
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
var a = "PASS"; var a = "PASS";
@@ -675,8 +677,7 @@ hoist_vars: {
console.log(a, b); console.log(a, b);
} }
expect: { expect: {
var a = "PASS"; var a = "PASS", [ b = 42 ] = [];
var [ b = 42 ] = [];
console.log(a, b); console.log(a, b);
} }
expect_stdout: "PASS 42" expect_stdout: "PASS 42"
@@ -1718,7 +1719,7 @@ issue_4540: {
node_version: ">=6" node_version: ">=6"
} }
issue_4548: { issue_4548_1: {
options = { options = {
merge_vars: true, merge_vars: true,
toplevel: true, toplevel: true,
@@ -1744,6 +1745,32 @@ issue_4548: {
node_version: ">=6" node_version: ">=6"
} }
issue_4548_2: {
options = {
merge_vars: true,
toplevel: true,
}
input: {
A = "foo";
var a = A;
var [ b = c = "bar" ] = [ console, console.log(a) ];
console.log(c);
var c;
}
expect: {
A = "foo";
var a = A;
var [ b = c = "bar" ] = [ console, console.log(a) ];
console.log(c);
var c;
}
expect_stdout: [
"foo",
"undefined",
]
node_version: ">=6"
}
issue_4588_1_unused: { issue_4588_1_unused: {
options = { options = {
unused: true, unused: true,
@@ -2086,7 +2113,7 @@ issue_5246_1: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
expect_warnings: [ expect_warnings: [
"INFO: Dropping unused default argument {}=42 [test/compress/default-values.js:1,29]", "INFO: Dropping unused default argument {} [test/compress/default-values.js:1,29]",
] ]
node_version: ">=6" node_version: ">=6"
} }
@@ -2478,7 +2505,7 @@ issue_5463: {
var a, b, b; var a, b, b;
console.log("PASS") && ( console.log("PASS") && (
b = a = void 0, b = a = void 0,
b = [a = FAIL] = a && a b = [a = FAIL] = a
); );
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -2686,7 +2713,7 @@ issue_5533_2_drop_fargs: {
try { try {
(function() { (function() {
for (;;) { for (;;) {
var [ [] = [] ] = []; var [ [ , ] = [] ] = [];
throw "PASS"; throw "PASS";
} }
})(); })();
@@ -3009,10 +3036,74 @@ issue_5566_5: {
(function(a, f = function() { (function(a, f = function() {
return a; return a;
}) { }) {
var b, a = "foo"; var a, b;
a = "foo";
console.log(a, f()); console.log(a, f());
})("bar"); })("bar");
} }
expect_stdout: "foo bar" expect_stdout: "foo bar"
node_version: ">=6" node_version: ">=6"
} }
issue_5651: {
options = {
ie: true,
unused: true,
}
input: {
console.log(function arguments(a = "FAIL") {
try {} catch (arguments) {
var arguments;
}
return arguments[0];
}());
}
expect: {
console.log(function arguments(a = "FAIL") {
try {} catch (arguments) {
var arguments;
}
return arguments[0];
}());
}
expect_stdout: true
node_version: ">=6"
}
issue_5774: {
options = {
collapse_vars: true,
conditionals: true,
evaluate: true,
join_vars: true,
reduce_vars: true,
sequences: true,
unsafe: true,
}
input: {
(function() {
while (console.log("PASS")) {
if (console) {
a = void 0;
var b = void 0;
var c = void 0;
([ a = 0 ] = [ b, b ]);
var a;
}
}
})();
}
expect: {
(function() {
while (console.log("PASS")) {
var a, b, c, a;
console && (
c = b = a = void 0,
[ a = 0 ] = [ a, a ]
);
}
})();
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -1306,7 +1306,7 @@ keep_reference: {
} }
expect: { expect: {
var a = [ {}, 42 ]; var a = [ {}, 42 ];
var [ b ] = a; var b = a[0];
console.log(a[0] === b ? "PASS" : "FAIL"); console.log(a[0] === b ? "PASS" : "FAIL");
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -1652,6 +1652,8 @@ fn_name_unused: {
hoist_vars: { hoist_vars: {
options = { options = {
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
var a = "PASS"; var a = "PASS";
@@ -1659,8 +1661,7 @@ hoist_vars: {
console.log(a, b); console.log(a, b);
} }
expect: { expect: {
var a = "PASS"; var a = "PASS", b = [ 42 ][0];
var [ b ] = [ 42 ];
console.log(a, b); console.log(a, b);
} }
expect_stdout: "PASS 42" expect_stdout: "PASS 42"
@@ -1736,6 +1737,23 @@ singleton_side_effects: {
node_version: ">=6" node_version: ">=6"
} }
mangle_properties: {
mangle = {
properties: {
domprops: true,
},
}
input: {
function f({ p: a }) {
return a;
}
console.log(f({ p: "PASS" }));
}
expect_exact: 'function f({n}){return n}console.log(f({n:"PASS"}));'
expect_stdout: "PASS"
node_version: ">=6"
}
issue_4280: { issue_4280: {
options = { options = {
evaluate: true, evaluate: true,
@@ -1902,8 +1920,8 @@ issue_4288: {
console.log(typeof b); console.log(typeof b);
}()]: a, }()]: a,
}) { }) {
var b = a; var a = a;
b++; a++;
} }
f(0); f(0);
} }
@@ -2076,17 +2094,16 @@ issue_4312: {
console.log(a); console.log(a);
} }
expect: { expect: {
var a;
b = "PASS", b = "PASS",
c = "FAIL", c = "FAIL",
[ [
{ {
[a = b]: d, [c = b]: d,
}, },
] = [ c && c ], ] = [ c && c ],
void 0; void 0;
var b, c, d; var b, c, d;
console.log(a); console.log(c);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=6" node_version: ">=6"
@@ -3844,3 +3861,28 @@ issue_5573: {
] ]
node_version: ">=6" node_version: ">=6"
} }
issue_5651: {
options = {
ie: true,
unused: true,
}
input: {
console.log(function arguments({}) {
try {} catch (arguments) {
var arguments;
}
return arguments[0];
}("PASS"));
}
expect: {
console.log(function arguments({}) {
try {} catch (arguments) {
var arguments;
}
return arguments[0];
}("PASS"));
}
expect_stdout: true
node_version: ">=6"
}

View File

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

View File

@@ -409,6 +409,15 @@ drop_toplevel_retain: {
a = 2; a = 2;
console.log(3); console.log(3);
} }
expect_stdout: "3"
expect_warnings: [
"INFO: Retaining variable a",
"INFO: Retaining variable f",
"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]",
"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]",
"INFO: Dropping unused function g [test/compress/drop-unused.js:8,17]",
"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]",
]
} }
drop_toplevel_retain_array: { drop_toplevel_retain_array: {
@@ -442,6 +451,15 @@ drop_toplevel_retain_array: {
a = 2; a = 2;
console.log(3); console.log(3);
} }
expect_stdout: "3"
expect_warnings: [
"INFO: Retaining variable a",
"INFO: Retaining variable f",
"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]",
"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]",
"INFO: Dropping unused function g [test/compress/drop-unused.js:8,17]",
"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]",
]
} }
drop_toplevel_retain_regex: { drop_toplevel_retain_regex: {
@@ -471,6 +489,15 @@ drop_toplevel_retain_regex: {
a = 2; a = 2;
console.log(3); console.log(3);
} }
expect_stdout: "3"
expect_warnings: [
"INFO: Retaining variable a",
"INFO: Retaining variable f",
"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]",
"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]",
"INFO: Dropping unused function g [test/compress/drop-unused.js:8,17]",
"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]",
]
} }
drop_toplevel_all_retain: { drop_toplevel_all_retain: {
@@ -501,6 +528,15 @@ drop_toplevel_all_retain: {
a = 2; a = 2;
console.log(3); console.log(3);
} }
expect_stdout: "3"
expect_warnings: [
"INFO: Retaining variable a",
"INFO: Retaining variable f",
"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]",
"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]",
"INFO: Dropping unused function g [test/compress/drop-unused.js:8,17]",
"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]",
]
} }
drop_toplevel_funcs_retain: { drop_toplevel_funcs_retain: {
@@ -532,6 +568,12 @@ drop_toplevel_funcs_retain: {
function g() {} function g() {}
console.log(b = 3); console.log(b = 3);
} }
expect_stdout: "3"
expect_warnings: [
"INFO: Retaining variable a",
"INFO: Retaining variable f",
"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]",
]
} }
drop_toplevel_vars_retain: { drop_toplevel_vars_retain: {
@@ -564,6 +606,13 @@ drop_toplevel_vars_retain: {
function h() {} function h() {}
console.log(3); console.log(3);
} }
expect_stdout: "3"
expect_warnings: [
"INFO: Retaining variable a",
"INFO: Retaining variable f",
"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]",
"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]",
]
} }
drop_toplevel_keep_assign: { drop_toplevel_keep_assign: {
@@ -1829,7 +1878,7 @@ issue_2846: {
var c = function(a, b) { var c = function(a, b) {
a = 0; a = 0;
b && b(a); b && b(a);
return a++; return +a;
}(); }();
console.log(c); console.log(c);
} }
@@ -2927,14 +2976,12 @@ issue_4025: {
console.log(a, b, d); console.log(a, b, d);
} }
expect: { expect: {
var c = 0;
try { try {
console.log(c); console.log(0);
} finally { } finally {
var d = c + 1; 0;
c = 0;
} }
console.log(1, 1, d); console.log(1, 1, 1);
} }
expect_stdout: [ expect_stdout: [
"0", "0",
@@ -3647,7 +3694,7 @@ issue_5224: {
(function() { (function() {
var a = "FAIL 1"; var a = "FAIL 1";
null; null;
a = console.log(a); console.log(a);
})(function() { })(function() {
console.log(1 / 0); console.log(1 / 0);
a; a;

View File

@@ -560,3 +560,23 @@ issue_5444: {
export var a = console; export var a = console;
} }
} }
issue_5628: {
options = {
unused: true,
}
input: {
var a;
export default function f() {
for (a in 42);
}
console.log(a);
}
expect: {
var a;
export default function f() {
for (a in 42);
}
console.log(a);
}
}

View File

@@ -5512,6 +5512,40 @@ substitute_use_strict: {
] ]
} }
substitute_assignment: {
options = {
evaluate: true,
inline: true,
passes: 2,
properties: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function f(a, b, c) {
a[b] = c;
}
var o = {};
f(o, 42, null);
f(o, "foo", "bar");
for (var k in o)
console.log(k, o[k]);
}
expect: {
var o = {};
o[42] = null;
o.foo = "bar";
for (var k in o)
console.log(k, o[k]);
}
expect_stdout: [
"42 null",
"foo bar",
]
}
issue_3833_1: { issue_3833_1: {
options = { options = {
inline: 3, inline: 3,
@@ -8629,6 +8663,7 @@ module_inline: {
inline: true, inline: true,
module: true, module: true,
reduce_vars: true, reduce_vars: true,
toplevel: true,
} }
input: { input: {
var a = f; var a = f;
@@ -8646,3 +8681,139 @@ module_inline: {
} }
expect_stdout: "true" expect_stdout: "true"
} }
single_use_inline_collision: {
options = {
inline: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
var a = "PASS";
(function() {
var f = function() {
while (console.log(a));
};
(function() {
(function() {
f();
})();
(function(a) {
a || a("FAIL");
})(console.log);
})();
})();
}
expect: {
var a = "PASS";
(function() {
(function() {
while (console.log(a));
return;
})();
(function(a) {
a || a("FAIL");
})(console.log);
return;
})();
}
expect_stdout: "PASS"
}
issue_5692: {
options = {
inline: true,
}
input: {
(function() {
while (console.log("PASS"))
if (console)
return;
})();
}
expect: {
(function() {
while (console.log("PASS"))
if (console)
return;
})();
}
expect_stdout: "PASS"
}
issue_5766_1: {
options = {
booleans: true,
evaluate: true,
functions: true,
inline: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
log = function(a) {
console.log(typeof a);
};
do {
(function() {
try {
var f = function() {};
log(f && f);
} catch (e) {}
})();
} while (0);
}
expect: {
log = function(a) {
console.log(typeof a);
};
do {
try {
function f() {}
log(f);
} catch (e) {}
} while (0);
}
expect_stdout: "function"
}
issue_5766_2: {
options = {
evaluate: true,
functions: true,
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
log = function(a) {
console.log(typeof a);
};
do {
(function() {
try {
var f = function() {};
log(f && f);
} catch (e) {}
})();
} while (0);
}
expect: {
log = function(a) {
console.log(typeof a);
};
do {
try {
function f() {}
log(f);
} catch (e) {}
} while (0);
}
expect_stdout: "function"
}

View File

@@ -462,6 +462,11 @@ issue_2473_1: {
var x = {}; var x = {};
var y = []; var y = [];
} }
expect_warnings: [
"INFO: Retaining variable x",
"INFO: Retaining variable y",
"WARN: Dropping unused variable z [test/compress/hoist_props.js:3,12]",
]
} }
issue_2473_2: { issue_2473_2: {
@@ -484,6 +489,11 @@ issue_2473_2: {
var x = {}; var x = {};
var y = []; var y = [];
} }
expect_warnings: [
"INFO: Retaining variable x",
"INFO: Retaining variable y",
"WARN: Dropping unused variable z [test/compress/hoist_props.js:3,12]",
]
} }
issue_2473_3: { issue_2473_3: {
@@ -509,6 +519,9 @@ issue_2473_3: {
console.log(o.a, o.b); console.log(o.a, o.b);
} }
expect_stdout: "1 2" expect_stdout: "1 2"
expect_warnings: [
"INFO: Retaining variable o",
]
} }
issue_2473_4: { issue_2473_4: {
@@ -535,6 +548,9 @@ issue_2473_4: {
})(); })();
} }
expect_stdout: "1 2" expect_stdout: "1 2"
expect_warnings: [
"INFO: Dropping unused variable o [test/compress/hoist_props.js:2,16]",
]
} }
issue_2508_1: { issue_2508_1: {

View File

@@ -2,6 +2,8 @@ statements: {
options = { options = {
hoist_funs: false, hoist_funs: false,
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
function f() { function f() {
@@ -25,6 +27,8 @@ statements_funs: {
options = { options = {
hoist_funs: true, hoist_funs: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
function f() { function f() {
@@ -48,6 +52,8 @@ sequences: {
options = { options = {
hoist_funs: false, hoist_funs: false,
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
function f() { function f() {
@@ -71,6 +77,8 @@ sequences_funs: {
options = { options = {
hoist_funs: true, hoist_funs: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
function f() { function f() {
@@ -108,7 +116,8 @@ catch_var: {
console.log(a); console.log(a);
} }
expect: { expect: {
var a = "PASS"; a = "PASS";
var a;
console.log(a); console.log(a);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -118,6 +127,8 @@ issue_2295: {
options = { options = {
collapse_vars: true, collapse_vars: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
function foo(o) { function foo(o) {
@@ -139,6 +150,7 @@ issue_4487_1: {
options = { options = {
functions: true, functions: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
keep_fnames: true, keep_fnames: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
@@ -163,6 +175,7 @@ issue_4487_2: {
options = { options = {
functions: true, functions: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
keep_fnames: true, keep_fnames: true,
passes: 2, passes: 2,
reduce_vars: true, reduce_vars: true,
@@ -188,6 +201,7 @@ issue_4487_3: {
options = { options = {
functions: true, functions: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
keep_fnames: true, keep_fnames: true,
passes: 3, passes: 3,
reduce_vars: true, reduce_vars: true,
@@ -248,8 +262,7 @@ issue_4517: {
} }
expect: { expect: {
console.log(function() { console.log(function() {
var a = 2; return (A = 2) + typeof !1;
return (A = a) + typeof !1;
}()); }());
} }
expect_stdout: "2boolean" expect_stdout: "2boolean"
@@ -260,6 +273,7 @@ issue_4736: {
collapse_vars: true, collapse_vars: true,
evaluate: true, evaluate: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
merge_vars: true, merge_vars: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
@@ -279,7 +293,7 @@ issue_4736: {
expect: { expect: {
(function() { (function() {
(function() { (function() {
0, 0;
console.log(1 << 30); console.log(1 << 30);
})(); })();
})(); })();
@@ -291,6 +305,7 @@ issue_4839: {
options = { options = {
evaluate: true, evaluate: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
keep_fargs: false, keep_fargs: false,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
@@ -317,6 +332,7 @@ issue_4859: {
options = { options = {
evaluate: true, evaluate: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
keep_infinity: true, keep_infinity: true,
merge_vars: true, merge_vars: true,
reduce_vars: true, reduce_vars: true,
@@ -441,7 +457,7 @@ issue_4898: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_5187: { issue_5187_1: {
options = { options = {
hoist_props: true, hoist_props: true,
hoist_vars: true, hoist_vars: true,
@@ -459,6 +475,37 @@ issue_5187: {
} }
f(); f();
} }
expect: {
(function() {
var a, b;
a = 42;
do {
b = { 0: a++ };
} while (console.log(b[b ^= 0]));
})();
}
expect_stdout: "42"
}
issue_5187_2: {
options = {
hoist_props: true,
hoist_vars: true,
join_vars: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function f() {
var a = 42;
do {
var b = { 0: a++ };
} while (console.log(b[b ^= 0]));
}
f();
}
expect: { expect: {
(function() { (function() {
var b, a = 42; var b, a = 42;
@@ -547,9 +594,9 @@ issue_5411_1: {
console.log(b); console.log(b);
} }
expect: { expect: {
var b, c, a = "PASS"; var a, b, c;
b++; b++;
b = a; b = a = "PASS";
c = c && c[b]; c = c && c[b];
console.log(b); console.log(b);
} }
@@ -577,7 +624,7 @@ issue_5411_2: {
var b, c; var b, c;
b++; b++;
b = "PASS", b = "PASS",
c = c && c[b]; c;
console.log(b); console.log(b);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -596,6 +643,30 @@ issue_5411_3: {
var a = A = a; var a = A = a;
console.log(A); console.log(A);
} }
expect: {
var a;
a = console;
a = A = ++a;
console.log(A);
}
expect_stdout: "NaN"
}
issue_5411_4: {
options = {
collapse_vars: true,
hoist_vars: true,
join_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = console;
a++;
var a = A = a;
console.log(A);
}
expect: { expect: {
var a = console; var a = console;
a = A = ++a; a = A = ++a;
@@ -603,3 +674,130 @@ issue_5411_3: {
} }
expect_stdout: "NaN" expect_stdout: "NaN"
} }
issue_5626: {
options = {
conditionals: true,
evaluate: true,
hoist_vars: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = function() {
return console.log(arguments[0]), 42;
}("PASS") ? null : "foo";
for (var b in a)
FAIL;
}
expect: {
(function() {
console.log(arguments[0]);
}("PASS"));
for (var b in null)
FAIL;
}
expect_stdout: "PASS"
}
issue_5638_1: {
options = {
collapse_vars: true,
hoist_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = "FAIL";
var a = [ 42 ];
console || FAIL(a);
console.log(a++);
}
expect: {
var a;
a = "FAIL";
a = [ 42 ];
console || FAIL(a);
console.log(a++);
}
expect_stdout: "42"
}
issue_5638_2: {
options = {
collapse_vars: true,
hoist_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = "FAIL";
var a = [ 6 ];
console || FAIL(a);
console.log(a *= 7);
}
expect: {
var a;
a = "FAIL";
a = [ 6 ];
console || FAIL(a);
console.log(a *= 7);
}
expect_stdout: "42"
}
issue_5638_3: {
options = {
collapse_vars: true,
hoist_vars: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var o = { foo: 42 };
for (var k in o) {
var v = o[k];
log(k || v, v++);
}
}
expect: {
var log, o, k, v;
log = console.log;
for (k in o = { foo: 42 }) {
v = o[k];
log(k || v, v++);
}
}
expect_stdout: "foo 42"
}
issue_5638_4: {
options = {
collapse_vars: true,
hoist_vars: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var o = { foo: 6 };
for (var k in o) {
var v = o[k];
log(k || v, v *= 7);
}
}
expect: {
var log, o, k, v;
log = console.log;
for (k in o = { foo: 6 }) {
v = o[k];
log(k || v, v *= 7);
}
}
expect_stdout: "foo 42"
}

File diff suppressed because it is too large Load Diff

View File

@@ -140,12 +140,12 @@ mangle: {
} }
input: { input: {
import foo, { bar } from "baz"; import foo, { bar } from "baz";
consoe.log(moo); console.log(moo);
import * as moo from "moz"; import * as moo from "moz";
} }
expect: { expect: {
import o, { bar as m } from "baz"; import o, { bar as m } from "baz";
consoe.log(r); console.log(r);
import * as r from "moz"; import * as r from "moz";
} }
} }
@@ -157,16 +157,44 @@ rename_mangle: {
} }
input: { input: {
import foo, { bar } from "baz"; import foo, { bar } from "baz";
consoe.log(moo); console.log(moo);
import * as moo from "moz"; import * as moo from "moz";
} }
expect: { expect: {
import o, { bar as m } from "baz"; import o, { bar as m } from "baz";
consoe.log(r); console.log(r);
import * as r from "moz"; import * as r from "moz";
} }
} }
mangle_export_import: {
mangle = {
toplevel: true,
}
input: {
export let o = A;
import { p as A } from "foo";
}
expect: {
export let o = p;
import { p } from "foo";
}
}
mangle_import_export: {
mangle = {
toplevel: true,
}
input: {
import { p as A } from "foo";
export let o = A;
}
expect: {
import { p } from "foo";
export let o = p;
}
}
keep_ref: { keep_ref: {
options = { options = {
reduce_vars: true, reduce_vars: true,

View File

@@ -1,6 +1,7 @@
issue_1321_no_debug: { issue_1321_no_debug: {
mangle = { mangle = {
properties: { properties: {
domprops: true,
keep_quoted: true, keep_quoted: true,
}, },
} }
@@ -23,6 +24,7 @@ issue_1321_debug: {
mangle = { mangle = {
properties: { properties: {
debug: "", debug: "",
domprops: true,
keep_quoted: true, keep_quoted: true,
}, },
} }
@@ -44,6 +46,7 @@ issue_1321_debug: {
issue_1321_with_quoted: { issue_1321_with_quoted: {
mangle = { mangle = {
properties: { properties: {
domprops: true,
keep_quoted: false, keep_quoted: false,
}, },
} }

View File

@@ -1,5 +1,5 @@
/** /**
* There was an incorrect sort behaviour documented in issue #143: * There was an incorrect sort behavior documented in issue #143:
* (x = f(…)) <= x → x >= (x = f(…)) * (x = f(…)) <= x → x >= (x = f(…))
* *
* For example, let the equation be: * For example, let the equation be:
@@ -12,37 +12,54 @@
* a >= (a = parseInt('100')) → 99 >= 100 → false * a >= (a = parseInt('100')) → 99 >= 100 → false
*/ */
tranformation_sort_order_equal: { transformation_sort_order_equal: {
options = { options = {
comparisons: true, comparisons: true,
} }
input: {
input: { (a = parseInt('100')) == a } console.log((a = parseInt("100")) == a);
expect: { (a = parseInt('100')) == a } }
expect: {
console.log((a = parseInt("100")) == a);
}
expect_stdout: "true"
} }
tranformation_sort_order_unequal: { transformation_sort_order_unequal: {
options = { options = {
comparisons: true, comparisons: true,
} }
input: {
input: { (a = parseInt('100')) != a } console.log((a = parseInt("100")) != a);
expect: { (a = parseInt('100')) != a } }
expect: {
console.log((a = parseInt("100")) != a);
}
expect_stdout: "false"
} }
tranformation_sort_order_lesser_or_equal: { transformation_sort_order_lesser_or_equal: {
options = { options = {
comparisons: true, comparisons: true,
} }
input: {
input: { (a = parseInt('100')) <= a } console.log((a = parseInt("100")) <= a);
expect: { (a = parseInt('100')) <= a }
} }
tranformation_sort_order_greater_or_equal: { expect: {
console.log((a = parseInt("100")) <= a);
}
expect_stdout: "true"
}
transformation_sort_order_greater_or_equal: {
options = { options = {
comparisons: true, comparisons: true,
} }
input: {
input: { (a = parseInt('100')) >= a } console.log((a = parseInt("100")) >= a);
expect: { (a = parseInt('100')) >= a } }
expect: {
console.log((a = parseInt("100")) >= a);
}
expect_stdout: "true"
} }

View File

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

View File

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

View File

@@ -15,7 +15,7 @@ collapse: {
var a; var a;
b = c(); b = c();
a = typeof b === 'function' ? b() : b; a = typeof b === 'function' ? b() : b;
return 'stirng' == typeof a && d(); return 'string' == typeof a && d();
} }
function f3(c) { function f3(c) {
var a; var a;
@@ -41,7 +41,7 @@ collapse: {
return void 0 !== ('function' === typeof b ? b() : b) && c(); return void 0 !== ('function' === typeof b ? b() : b) && c();
} }
function f2(b) { function f2(b) {
return 'stirng' == typeof ('function' === typeof (b = c()) ? b() : b) && d(); return 'string' == typeof ('function' === typeof (b = c()) ? b() : b) && d();
} }
function f3(c) { function f3(c) {
var a; var a;

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

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

View File

@@ -68,6 +68,7 @@ drop_console_2: {
} }
drop_value: { drop_value: {
expression = true
options = { options = {
expression: true, expression: true,
side_effects: true, side_effects: true,
@@ -106,6 +107,7 @@ wrongly_optimized: {
} }
negate_iife_1: { negate_iife_1: {
expression = true
options = { options = {
expression: true, expression: true,
negate_iife: true, negate_iife: true,
@@ -119,6 +121,7 @@ negate_iife_1: {
} }
negate_iife_3: { negate_iife_3: {
expression = true
options = { options = {
conditionals: true, conditionals: true,
expression: true, expression: true,
@@ -133,6 +136,7 @@ negate_iife_3: {
} }
negate_iife_3_off: { negate_iife_3_off: {
expression = true
options = { options = {
conditionals: true, conditionals: true,
expression: true, expression: true,
@@ -215,6 +219,7 @@ negate_iife_5_off: {
} }
issue_1254_negate_iife_true: { issue_1254_negate_iife_true: {
expression = true
options = { options = {
expression: true, expression: true,
negate_iife: true, negate_iife: true,
@@ -226,11 +231,12 @@ issue_1254_negate_iife_true: {
}; };
})()(); })()();
} }
expect_exact: '(function(){return function(){console.log("test")}})()();' expect_exact: 'function(){return function(){console.log("test")}}()()'
expect_stdout: true expect_stdout: true
} }
issue_1254_negate_iife_nested: { issue_1254_negate_iife_nested: {
expression = true
options = { options = {
expression: true, expression: true,
negate_iife: true, negate_iife: true,
@@ -242,7 +248,7 @@ issue_1254_negate_iife_nested: {
}; };
})()()()()(); })()()()()();
} }
expect_exact: '(function(){return function(){console.log("test")}})()()()()();' expect_exact: 'function(){return function(){console.log("test")}}()()()()()'
expect_stdout: true expect_stdout: true
} }

View File

@@ -1,6 +1,7 @@
dont_reuse_prop: { dont_reuse_prop: {
mangle = { mangle = {
properties: { properties: {
domprops: true,
regex: /asd/, regex: /asd/,
}, },
} }
@@ -19,11 +20,17 @@ dont_reuse_prop: {
console.log(obj.a); console.log(obj.a);
} }
expect_stdout: "123" expect_stdout: "123"
expect_warnings: [
"INFO: Preserving excluded property a",
"INFO: Mapping property asd to b",
"INFO: Preserving reserved property log",
]
} }
unmangleable_props_should_always_be_reserved: { unmangleable_props_should_always_be_reserved: {
mangle = { mangle = {
properties: { properties: {
domprops: true,
regex: /asd/, regex: /asd/,
}, },
} }
@@ -42,4 +49,9 @@ unmangleable_props_should_always_be_reserved: {
console.log(obj.a); console.log(obj.a);
} }
expect_stdout: "123" expect_stdout: "123"
expect_warnings: [
"INFO: Preserving excluded property a",
"INFO: Mapping property asd to b",
"INFO: Preserving reserved property log",
]
} }

View File

@@ -1,6 +1,7 @@
keep_var_for_in: { keep_var_for_in: {
options = { options = {
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true, unused: true,
} }
input: { input: {

View File

@@ -16,6 +16,105 @@ join_vars_assign: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
join_array_assignments_1: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function () {
var a = ["foo", , "bar"];
a[1] = "baz";
a[7] = "moo";
a[0] = "moz";
return a;
}().join());
}
expect: {
console.log(function () {
var a = [("foo", "moz"), "baz", "bar", , , , , "moo"];
return a;
}().join());
}
expect_stdout: "moz,baz,bar,,,,,moo"
}
join_array_assignments_2: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function () {
var a = ["foo"];
a[1] = "bar";
a[7] = "baz";
a[2] = "moo";
return a;
}().join());
}
expect: {
console.log(function () {
var a = ["foo", "bar"];
a[7] = "baz";
a[2] = "moo";
return a;
}().join());
}
expect_stdout: "foo,bar,moo,,,,,baz"
}
join_array_assignments_3: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function () {
var a = ["foo"];
a[1] = "bar";
a.b = "baz";
a[2] = "moo";
return a;
}().join());
}
expect: {
console.log(function () {
var a = ["foo", "bar"];
a.b = "baz";
a[2] = "moo";
return a;
}().join());
}
expect_stdout: true
}
join_array_assignments_4: {
options = {
evaluate: true,
join_vars: true,
side_effects: true,
}
input: {
console.log(function () {
var a = ["foo"];
a[0] = "bar";
a[1] = a;
a[2] = "baz";
return a;
}().join());
}
expect: {
console.log(function () {
var a = ["bar"];
a[1] = a;
a[2] = "baz";
return a;
}().join());
}
expect_stdout: true
}
join_object_assignments_1: { join_object_assignments_1: {
options = { options = {
evaluate: true, evaluate: true,
@@ -570,7 +669,7 @@ inlined_assignments: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
inilne_for: { inline_for: {
options = { options = {
inline: true, inline: true,
join_vars: true, join_vars: true,
@@ -590,7 +689,7 @@ inilne_for: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
inilne_var: { inline_var: {
options = { options = {
inline: true, inline: true,
join_vars: true, join_vars: true,
@@ -1394,3 +1493,18 @@ issue_5175: {
} }
expect_stdout: "PASS PASS" expect_stdout: "PASS PASS"
} }
issue_5831: {
options = {
evaluate: true,
join_vars: true,
}
input: {
var a = [ console.log("PASS") ];
a[0] = 42;
}
expect: {
var a = [ (console.log("PASS"), 42) ];
}
expect_stdout: "PASS"
}

View File

@@ -1130,6 +1130,130 @@ default_init: {
node_version: ">=4" node_version: ">=4"
} }
join_let_var_1: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
var a = "foo";
let b = "bar";
for (var c of [ a, b ])
console.log(c);
}
expect: {
"use strict";
let a = "foo", b = "bar";
for (var c of [ a, b ])
console.log(c);
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=4"
}
join_let_var_2: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
let a = "foo";
var b = "bar";
for (let c of [ a, b ])
console.log(c);
}
expect: {
"use strict";
let a = "foo", b = "bar";
for (let c of [ a, b ])
console.log(c);
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=4"
}
keep_let_var_1: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
var a = "foo";
let b = "bar";
for (var c of [ a, b ])
console.log(c);
function f() {
return a;
}
console.log(f(f));
}
expect: {
"use strict";
var a = "foo", c;
let b = "bar";
for (c of [ a, b ])
console.log(c);
function f() {
return a;
}
console.log(f(f));
}
expect_stdout: [
"foo",
"bar",
"foo",
]
node_version: ">=4"
}
keep_let_var_2: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
let a = "foo";
var b = "bar";
for (let c of [ a, b ])
console.log(c);
function f() {
return b;
}
console.log(f(f));
}
expect: {
"use strict";
let a = "foo";
var b = "bar";
for (let c of [ a, b ])
console.log(c);
function f() {
return b;
}
console.log(f(f));
}
expect_stdout: [
"foo",
"bar",
"bar",
]
node_version: ">=4"
}
issue_4191: { issue_4191: {
options = { options = {
functions: true, functions: true,
@@ -2122,3 +2246,323 @@ issue_5476: {
expect_stdout: "undefined" expect_stdout: "undefined"
node_version: ">=4" node_version: ">=4"
} }
issue_5591: {
options = {
dead_code: true,
if_return: true,
}
input: {
"use strict";
function f(a) {
switch (console.log("foo")) {
case console.log("bar"):
if (console.log("baz"))
return;
else {
let a;
return;
}
break;
case null:
FAIL;
}
}
f();
}
expect: {
"use strict";
function f(a) {
switch (console.log("foo")) {
case console.log("bar"):
if (console.log("baz"))
return;
else {
let a;
return;
}
case null:
FAIL;
}
}
f();
}
expect_stdout: [
"foo",
"bar",
"baz",
]
node_version: ">=4"
}
issue_5741: {
options = {
inline: true,
join_vars: true,
reduce_vars: true,
}
input: {
"use strict";
(function(a) {
let b = function() {
var c = a;
console.log(c);
}();
function g() {
a++;
b;
}
})("PASS");
}
expect: {
"use strict";
(function(a) {
let b = (c = a, void console.log(c));
var c;
function g() {
a++;
b;
}
})("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5745_1: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
{
let f = function() {
return f && "PASS";
};
var a = f();
}
a;
console.log(a);
}
expect: {
"use strict";
{
let f = function() {
return f && "PASS";
};
var a = f();
}
a;
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5745_2: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
{
let f = function() {
return f && "PASS";
};
var a = f();
a;
console.log(a);
}
}
expect: {
"use strict";
{
let f = function() {
return f && "PASS";
}, a = f();
a;
console.log(a);
}
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5756_1: {
options = {
join_vars: true,
loops: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
do {
function f() {
return b;
}
var a = "PASS".toString();
let b;
console.log(a);
} while (!console);
}
expect: {
"use strict";
do {
function f() {
return b;
}
let a = "PASS".toString(), b;
console.log(a);
} while (!console);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5756_2: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
function f() {
let a = console.log("PASS");
{
var b;
for (var c in b) {
b;
var c = function() {
a;
};
}
}
}
f();
}
expect: {
"use strict";
(function() {
let a = console.log("PASS"), b;
for (c in b) {
b;
var c = function() {
a;
};
}
})();
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5756_3: {
options = {
module: true,
reduce_vars: true,
toplevel: true,
unused: true,
varify: true,
}
input: {
"use strict";
console.log(f()());
function f() {
const a = "PASS";
return function() {
return a;
};
}
}
expect: {
"use strict";
console.log(function() {
let a = "PASS";
return function() {
return a;
};
}()());
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5759: {
options = {
collapse_vars: true,
inline: true,
join_vars: true,
reduce_vars: true,
unused: true,
}
input: {
"use strict";
function f() {
for (var a in [ true ]) {
let b;
(function() {
var c = void 0;
b;
console.log(c);
var d = null;
console.log(c);
})();
}
}
f();
}
expect: {
"use strict";
function f() {
for (var a in [ true ]) {
let b;
var c = c = void 0;
b;
console.log(c);
console.log(c);
}
}
f();
}
expect_stdout: [
"undefined",
"undefined",
]
node_version: ">=4"
}
issue_5787: {
options = {
unused: true,
}
input: {
console.log(function() {
let a = 42;
switch (a) {
case 42:
// Node.js v4 (vm): SyntaxError: Identifier 'a' has already been declared
let a = "PASS";
return a;
}
}());
}
expect: {
console.log(function() {
let a = 42;
switch (a) {
case 42:
let a = "PASS";
return a;
}
}());
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -3845,3 +3845,158 @@ issue_5471_2: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_5714: {
options = {
inline: true,
join_vars: true,
loops: true,
merge_vars: true,
unused: true,
}
input: {
"use strict";
console.log(function() {
var i = 1;
while (i--) {
var a = function f(b) {
console.log(b);
var c = function(d) {
console.log(typeof d);
}(console);
}();
var e = 42;
}
return e;
}());
}
expect: {
"use strict";
console.log(function() {
for (var i = 1; i--;) {
var b = void 0;
console.log(b);
b = console,
console.log(typeof b);
var e = 42;
}
return e;
}());
}
expect_stdout: [
"undefined",
"object",
"42",
]
}
issue_5770_1: {
options = {
dead_code: true,
loops: true,
merge_vars: true,
toplevel: true,
}
input: {
L: do {
if (console)
for (var a = "FAIL 1"; a; a--)
continue L;
var b = "FAIL 2";
} while (console.log(b || "PASS"));
}
expect: {
L: do {
if (console) {
var a = "FAIL 1";
if (a)
continue L;
}
var b = "FAIL 2";
} while (console.log(b || "PASS"));
}
expect_stdout: "PASS"
}
issue_5770_2: {
options = {
conditionals: true,
dead_code: true,
if_return: true,
loops: true,
merge_vars: true,
toplevel: true,
}
input: {
L: do {
for (var a = "FAIL 1"; a; a--)
continue L;
var b = "FAIL 2";
} while (console.log(b || "PASS"));
}
expect: {
L: do {
var a = "FAIL 1";
var b;
} while (a || (b = "FAIL 2"), console.log(b || "PASS"));
}
expect_stdout: "PASS"
}
issue_5772_1: {
options = {
dead_code: true,
merge_vars: true,
loops: true,
}
input: {
(function(a) {
while (--a)
return;
var b = console.log("foo") && (c = 42) ? 0 : console.log(c);
var c = b;
})();
}
expect: {
(function(a) {
if (--a)
return;
var a = console.log("foo") && (c = 42) ? 0 : console.log(c);
var c = a;
})();
}
expect_stdout: [
"foo",
"undefined",
]
}
issue_5772_2: {
options = {
dead_code: true,
merge_vars: true,
loops: true,
}
input: {
(function(a) {
while (--a)
return;
var b;
var c = console.log("foo") && (b = 1) ? 2 : 3;
console.log(b, c);
})();
}
expect: {
(function(a) {
if (--a)
return;
var b;
var a = console.log("foo") && (b = 1) ? 2 : 3;
console.log(b, a);
})();
}
expect_stdout: [
"foo",
"undefined 3",
]
}

View File

@@ -344,3 +344,43 @@ issue_5266: {
] ]
node_version: ">=14" node_version: ">=14"
} }
issue_5829_1: {
options = {
merge_vars: true,
}
input: {
(function f(a) {
var b;
(!a ?? (b = 0)) || console.log(b || "PASS");
})("FAIL");
}
expect: {
(function f(a) {
var b;
(!a ?? (b = 0)) || console.log(b || "PASS");
})("FAIL");
}
expect_stdout: "PASS"
node_version: ">=14"
}
issue_5829_2: {
options = {
merge_vars: true,
}
input: {
(function f(a) {
var b;
(a ?? (b = 0)) && console.log(b || "PASS");
})("FAIL");
}
expect: {
(function f(a) {
var b;
(a ?? (b = 0)) && console.log(b || "PASS");
})("FAIL");
}
expect_stdout: "PASS"
node_version: ">=14"
}

View File

@@ -173,7 +173,9 @@ numeric_literal: {
side_effects: true, side_effects: true,
} }
mangle = { mangle = {
properties: true, properties: {
domprops: true,
},
} }
beautify = { beautify = {
beautify: true, beautify: true,

View File

@@ -133,6 +133,7 @@ evaluate_string_length: {
mangle_properties_1: { mangle_properties_1: {
mangle = { mangle = {
properties: { properties: {
domprops: true,
keep_quoted: false, keep_quoted: false,
}, },
} }
@@ -147,17 +148,18 @@ mangle_properties_1: {
a["a"] = "bar"; a["a"] = "bar";
a.b = "red"; a.b = "red";
x = {o: 10}; x = {o: 10};
a.r(x.o, a.a); a.run(x.o, a.a);
a['r']({b: "blue", a: "baz"}); a['run']({b: "blue", a: "baz"});
} }
} }
mangle_properties_2: { mangle_properties_2: {
mangle = { mangle = {
properties: { properties: {
domprops: true,
reserved: [ reserved: [
"value", "value",
] ],
}, },
} }
input: { input: {
@@ -199,6 +201,24 @@ mangle_properties_2: {
] ]
} }
mangle_properties_3: {
mangle = {
properties: true,
}
input: {
console.log({
[(console, "foo")]: "PASS",
}.foo);
}
expect: {
console.log({
[(console, "o")]: "PASS",
}.o);
}
expect_stdout: "PASS"
node_version: ">=4"
}
mangle_unquoted_properties: { mangle_unquoted_properties: {
options = { options = {
evaluate: true, evaluate: true,
@@ -206,6 +226,8 @@ mangle_unquoted_properties: {
} }
mangle = { mangle = {
properties: { properties: {
builtins: true,
domprops: true,
keep_quoted: true, keep_quoted: true,
}, },
} }
@@ -305,7 +327,9 @@ mangle_debug_suffix_keep_quoted: {
} }
mangle = { mangle = {
properties: { properties: {
builtins: true,
debug: "XYZ", debug: "XYZ",
domprops: true,
keep_quoted: true, keep_quoted: true,
reserved: [], reserved: [],
}, },
@@ -351,6 +375,68 @@ mangle_debug_suffix_keep_quoted: {
} }
} }
keep_substituted_property: {
options = {
evaluate: true,
properties: true,
reduce_vars: true,
}
mangle = {
properties: {
keep_quoted: true,
},
}
input: {
var o = { p: [] };
function f(b) {
return o[b];
}
function g() {
var a = "p";
return o[a] === f(a);
}
console.log(g() ? "PASS" : "FAIL");
}
expect: {
var o = { p: [] };
function f(n) {
return o[n];
}
function g() {
var n = "p";
return o.p === f(n);
}
console.log(g() ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
}
keep_substituted_property_quotes: {
options = {
evaluate: true,
properties: true,
reduce_vars: true,
}
beautify = {
keep_quoted_props: true,
}
input: {
function f(o) {
var a = "p";
return o[a];
}
console.log(f({ p: "PASS" }));
}
expect: {
function f(o) {
var a = "p";
return o["p"];
}
console.log(f({ p: "PASS" }));
}
expect_stdout: "PASS"
}
first_256_chars_as_properties: { first_256_chars_as_properties: {
beautify = { beautify = {
ascii_only: true, ascii_only: true,
@@ -897,12 +983,15 @@ issue_2256: {
}, },
} }
input: { input: {
({ "keep": 1 }); ({ "keep": 42 });
g.keep = g.change; global.keep = global.change = "PASS";
console.log(keep);
} }
expect: { expect: {
g.keep = g.g; global.keep = global.l = "PASS";
console.log(keep);
} }
expect_stdout: "PASS"
} }
lhs_prop_1: { lhs_prop_1: {
@@ -1578,3 +1667,163 @@ issue_5177: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=4" node_version: ">=4"
} }
issue_5682_in_1: {
mangle = {
properties: true,
}
input: {
function f(a) {
return "foo" in a;
}
var o = {};
var p = "foo";
o[p] = 42;
console.log(f(o) ? "PASS" : "FAIL");
}
expect: {
function f(o) {
return "foo" in o;
}
var o = {};
var p = "foo";
o[p] = 42;
console.log(f(o) ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
}
issue_5682_in_2: {
mangle = {
properties: true,
}
input: {
function f(a) {
return "foo" in a;
}
var o = { foo: 42 };
console.log(f(o) ? "PASS" : "FAIL");
}
expect: {
function f(o) {
return "o" in o;
}
var o = { o: 42 };
console.log(f(o) ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
}
issue_5682_dot_1: {
mangle = {
properties: true,
}
input: {
function f(a) {
return a.foo;
}
var o = {};
var p = "foo";
o[p] = "PASS";
console.log(f(o));
}
expect: {
function f(o) {
return o.foo;
}
var o = {};
var p = "foo";
o[p] = "PASS";
console.log(f(o));
}
expect_stdout: "PASS"
}
issue_5682_dot_2: {
mangle = {
properties: true,
}
input: {
function f(a) {
return a.foo;
}
var o = { foo: "PASS" };
console.log(f(o));
}
expect: {
function f(o) {
return o.o;
}
var o = { o: "PASS" };
console.log(f(o));
}
expect_stdout: "PASS"
}
issue_5682_dot_2_computed: {
mangle = {
properties: true,
}
input: {
function f(a) {
return a.foo;
}
var o = { ["foo"]: "PASS" };
console.log(f(o));
}
expect: {
function f(o) {
return o.o;
}
var o = { ["o"]: "PASS" };
console.log(f(o));
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5682_sub_1: {
mangle = {
properties: true,
}
input: {
function f(a) {
return a["foo"];
}
var o = {};
var p = "foo";
o[p] = "PASS";
console.log(f(o));
}
expect: {
function f(o) {
return o["foo"];
}
var o = {};
var p = "foo";
o[p] = "PASS";
console.log(f(o));
}
expect_stdout: "PASS"
}
issue_5682_sub_2: {
mangle = {
properties: true,
}
input: {
function f(a) {
return a["foo"];
}
var o = { foo: "PASS" };
console.log(f(o));
}
expect: {
function f(o) {
return o["o"];
}
var o = { o: "PASS" };
console.log(f(o));
}
expect_stdout: "PASS"
}

View File

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

View File

@@ -1540,10 +1540,12 @@ this_toString: {
issue_4803: { issue_4803: {
options = { options = {
hoist_vars: true, hoist_vars: true,
join_vars: true,
pure_getters: "strict", pure_getters: "strict",
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
toplevel: true, toplevel: true,
unused: true,
} }
input: { input: {
var o = { var o = {

View File

@@ -2488,7 +2488,7 @@ side_effects_assign: {
console.log(a); console.log(a);
} }
expect: { expect: {
var a = typeof void (a && a.in); var a = "undefined";
console.log(a); console.log(a);
} }
expect_stdout: "undefined" expect_stdout: "undefined"
@@ -2530,7 +2530,8 @@ pure_getters_2: {
var a = a && a.b; var a = a && a.b;
} }
expect: { expect: {
var a = a && a.b; var a;
a && a.b;
} }
} }
@@ -5424,7 +5425,7 @@ issue_2774: {
get a() { get a() {
var b; var b;
(b = true) && b.c; (b = true) && b.c;
b = void 0; void 0;
} }
}.a); }.a);
} }
@@ -7896,3 +7897,452 @@ issue_5434: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_5623: {
options = {
collapse_vars: true,
evaluate: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
var a = 0;
function f() {
var b = a;
a = b;
}
f && f((a++ && a).toString());
console.log(a);
}
expect: {
var a = 0;
function f() {
var b;
a = a;
}
f((a++ && a).toString());
console.log(a);
}
expect_stdout: "1"
}
issue_5716_1: {
options = {
collapse_vars: true,
inline: true,
merge_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a;
function f() {
var b = [ c, c ], c = function() {
return b++ + (a = b);
}();
}
f();
console.log(a);
}
expect: {
c = [ c, c ],
void (c = ++c);
var c;
console.log(c);
}
expect_stdout: "NaN"
}
issue_5716_2: {
options = {
collapse_vars: true,
inline: true,
merge_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a;
function f() {
var b = [ c, c ], c = function() {
return (b += 4) + (a = b += 2);
}();
}
f();
console.log(a);
}
expect: {
void (c = c = (c = [ c, c ]) + 4 + 2);
var c;
console.log(c);
}
expect_stdout: ",42"
}
issue_5716_3: {
options = {
assignments: true,
collapse_vars: true,
inline: true,
merge_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a;
function f() {
var b = [ c, c ], c = function() {
return (b = b + 4) + (a = b += 2);
}();
}
f();
console.log(a);
}
expect: {
void (c = c = (c = [ c, c ]) + 4 + 2);
var c;
console.log(c);
}
expect_stdout: ",42"
}
issue_5716_4: {
options = {
assignments: true,
collapse_vars: true,
inline: true,
merge_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a;
function f() {
var b = [ c, c ], c = function() {
return (b = true | b) + (a = b *= 42);
}();
}
f();
console.log(a);
}
expect: {
void (c = c = ((c = [ c, c ]) | true) * 42);
var c;
console.log(c);
}
expect_stdout: "42"
}
issue_5716_5: {
options = {
assignments: true,
reduce_vars: true,
}
input: {
console.log(function() {
return 0 || (a = 42 | a);
var a = function() {
return a;
};
}());
}
expect: {
console.log(function() {
return 0 || (a |= 42);
var a = function() {
return a;
};
}());
}
expect_stdout: "42"
}
issue_5730_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = "PASS";
L: {
var f = function() {
console.log(a);
};
}
f();
a++;
}
expect: {
var a = "PASS";
var f = function() {
console.log(a);
};
f();
a++;
}
expect_stdout: "PASS"
}
issue_5730_2: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = "PASS";
try {
var f = function() {
console.log(a);
};
} finally {}
f();
a++;
}
expect: {
var a = "PASS";
try {
var f = function() {
console.log(a);
};
} finally {}
f();
a++;
}
expect_stdout: "PASS"
}
issue_5730_3: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var f, a = "PASS";
L: {
f = function() {
console.log(a);
};
}
f();
a++;
}
expect: {
var f, a = "PASS";
f = function() {
console.log(a);
};
f();
a++;
}
expect_stdout: "PASS"
}
issue_5777_1: {
options = {
reduce_vars: true,
unused: true,
}
input: {
function f() {
(function(a) {
function g() {
h();
}
g();
a = function() {};
function h() {
console.log(a);
}
})("PASS");
}
f();
}
expect: {
function f() {
(function(a) {
(function() {
h();
})();
a = function() {};
function h() {
console.log(a);
}
})("PASS");
}
f();
}
expect_stdout: "PASS"
}
issue_5777_2: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f(a) {
(function() {
function g() {
h();
}
g();
a = function() {};
function h() {
console.log(a);
}
})();
}
f("PASS");
}
expect: {
(function(a) {
(function() {
(function() {
h();
})();
a = function() {};
function h() {
console.log(a);
}
})();
})("PASS");
}
expect_stdout: "PASS"
}
issue_1666: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect: {
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect_stdout: true
}
issue_1666_strict: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect: {
"use strict";
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect_stdout: true
}
issue_1666_undefined: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect: {
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect_stdout: true
}
issue_1666_undefined_strict: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect: {
"use strict";
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect_stdout: true
}

View File

@@ -739,3 +739,55 @@ issue_3480_ie8_toplevel: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_5787_1: {
rename = true
input: {
console.log(function() {
const a = 42;
switch (a) {
case 42:
const a = "PASS";
return a;
}
}());
}
expect: {
console.log(function() {
const a = 42;
switch (a) {
case 42:
const a = "PASS";
return a;
}
}());
}
expect_stdout: true
}
issue_5787_2: {
rename = true
input: {
console.log(function() {
let a = 42;
switch (a) {
case 42:
// Node.js v4 (vm): SyntaxError: Identifier 'a' has already been declared
let a = "PASS";
return a;
}
}());
}
expect: {
console.log(function() {
let a = 42;
switch (a) {
case 42:
let b = "PASS";
return b;
}
}());
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -1624,3 +1624,21 @@ issue_5552_4: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=6" node_version: ">=6"
} }
issue_5705: {
options = {
reduce_vars: true,
rests: true,
unused: true,
}
input: {
(function(...a) {
var b = { ...a };
})(console.log("PASS"));
}
expect: {
(function() {})(console.log("PASS"));
}
expect_stdout: "PASS"
node_version: ">=8.3.0"
}

View File

@@ -125,6 +125,7 @@ log_nested: {
timers: { timers: {
options = { options = {
evaluate: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
unused: true, unused: true,
@@ -132,26 +133,22 @@ timers: {
input: { input: {
var count = 0, interval = 1000, duration = 3210; var count = 0, interval = 1000, duration = 3210;
var timer = setInterval(function() { var timer = setInterval(function() {
console.log(++count); if (!count++) setTimeout(function() {
}, interval);
setTimeout(function() {
clearInterval(timer); clearInterval(timer);
console.log(count <= 4 ? "PASS" : "FAIL");
}, duration); }, duration);
}, interval);
} }
expect: { expect: {
var count = 0; var count = 0;
var timer = setInterval(function() { var timer = setInterval(function() {
console.log(++count); if (!count++) setTimeout(function() {
}, 1000);
setTimeout(function() {
clearInterval(timer); clearInterval(timer);
console.log(count <= 4 ? "PASS" : "FAIL");
}, 3210); }, 3210);
}, 1000);
} }
expect_stdout: [ expect_stdout: "PASS"
"1",
"2",
"3",
]
node_version: ">=0.12" node_version: ">=0.12"
} }

View File

@@ -318,6 +318,32 @@ unsafe_string_replace: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
unsafe_Object_call: {
options = {
side_effects: true,
unsafe: true,
}
input: {
var o = {
f: function(a) {
console.log(a ? this.p : "FAIL 1");
},
p: "FAIL 2",
}, p = "PASS";
Object(o.f)(42);
}
expect: {
var o = {
f: function(a) {
console.log(a ? this.p : "FAIL 1");
},
p: "FAIL 2",
}, p = "PASS";
(0, o.f)(42);
}
expect_stdout: "PASS"
}
drop_value: { drop_value: {
options = { options = {
side_effects: true, side_effects: true,

View File

@@ -1203,3 +1203,53 @@ issue_5382: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=8.3.0" node_version: ">=8.3.0"
} }
issue_5602: {
options = {
collapse_vars: true,
conditionals: true,
evaluate: true,
if_return: true,
inline: true,
passes: 2,
sequences: true,
spreads: true,
unused: true,
}
input: {
(function() {
try {
var b = function(c) {
if (c)
return FAIL;
var d = 42;
}(...[ null, A = 0 ]);
} catch (e) {
b();
}
})();
console.log(A);
}
expect: {
(function() {
try {
var b = void (A = 0);
} catch (e) {
b();
}
})(),
console.log(A);
}
expect_stdout: "0"
expect_warnings: [
"INFO: Dropping unused variable d [test/compress/spreads.js:6,24]",
"INFO: Collapsing c [test/compress/spreads.js:4,24]",
"INFO: Dropping unused variable c [test/compress/spreads.js:3,33]",
"INFO: pass 0: last_count: Infinity, count: 27",
"WARN: Condition always false [test/compress/spreads.js:4,20]",
"INFO: Collapsing null [test/compress/spreads.js:7,23]",
"INFO: Collapsing 0 [test/compress/spreads.js:3,24]",
"INFO: pass 1: last_count: 27, count: 22",
]
node_version: ">=6"
}

View File

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

View File

@@ -194,6 +194,43 @@ scope_adjustment_let: {
node_version: ">=4" node_version: ">=4"
} }
escaped_const: {
options = {
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
const log = console.log;
log("PASS");
}
expect: {
var log = console.log;
log("PASS");
}
expect_stdout: "PASS"
}
escaped_let: {
options = {
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
"use strict";
let log = console.log;
log("PASS");
}
expect: {
"use strict";
var log = console.log;
log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_4191_const: { issue_4191_const: {
options = { options = {
functions: true, functions: true,
@@ -292,6 +329,42 @@ forin_const_2: {
node_version: ">=6" node_version: ">=6"
} }
forin_const_3: {
options = {
module: true,
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
"use strict";
const o = {
p: 42,
q: "PASS",
};
for (const k in o)
(function f() {
console.log(k, o[k]);
})();
}
expect: {
"use strict";
let o = {
p: 42,
q: "PASS",
};
for (let k in o)
(function f() {
console.log(k, o[k]);
})();
}
expect_stdout: [
"p 42",
"q PASS",
]
node_version: ">=4"
}
forin_let_1: { forin_let_1: {
options = { options = {
join_vars: true, join_vars: true,
@@ -645,3 +718,165 @@ issue_5516: {
expect_stdout: "function" expect_stdout: "function"
node_version: ">=4" node_version: ">=4"
} }
issue_5697_1: {
options = {
if_return: true,
inline: true,
reduce_vars: true,
unused: true,
varify: true,
}
input: {
console.log(function() {
f();
return typeof a;
function f() {
(function() {
for (var k in { foo: 42 }) {
const a = k;
console.log(a);
}
})();
}
}());
}
expect: {
console.log(function() {
(function() {
for (var k in { foo: 42 }) {
var a = k;
console.log(a);
}
})();
return typeof a;
}());
}
expect_stdout: [
"foo",
"undefined",
]
}
issue_5697_2: {
options = {
if_return: true,
inline: true,
reduce_vars: true,
unused: true,
varify: true,
}
input: {
"use strict";
console.log(function() {
f();
return typeof a;
function f() {
(function() {
for (var k in { foo: 42 }) {
let a = k;
console.log(a);
}
})();
}
}());
}
expect: {
"use strict";
console.log(function() {
(function() {
for (var k in { foo: 42 }) {
var a = k;
console.log(a);
}
})();
return typeof a;
}());
}
expect_stdout: [
"foo",
"undefined",
]
node_version: ">=4"
}
issue_5697_3: {
options = {
inline: true,
reduce_vars: true,
side_effects: true,
unused: true,
varify: true,
}
input: {
console.log(function() {
f();
return typeof a;
function f() {
(function() {
for (var k in { foo: 42 }) {
const a = k;
console.log(a);
}
})();
}
}());
}
expect: {
console.log(function() {
(function() {
for (var k in { foo: 42 }) {
var a = k;
console.log(a);
}
})();
return typeof a;
}());
}
expect_stdout: [
"foo",
"undefined",
]
}
issue_5697_4: {
options = {
inline: true,
reduce_vars: true,
side_effects: true,
unused: true,
varify: true,
}
input: {
"use strict";
console.log(function() {
f();
return typeof a;
function f() {
(function() {
for (var k in { foo: 42 }) {
let a = k;
console.log(a);
}
})();
}
}());
}
expect: {
"use strict";
console.log(function() {
(function() {
for (var k in { foo: 42 }) {
var a = k;
console.log(a);
}
})();
return typeof a;
}());
}
expect_stdout: [
"foo",
"undefined",
]
node_version: ">=4"
}

View File

@@ -896,7 +896,7 @@ dont_inline_nested: {
node_version: ">=4" node_version: ">=4"
} }
drop_body: { drop_body_1: {
options = { options = {
side_effects: true, side_effects: true,
yields: true, yields: true,
@@ -906,6 +906,27 @@ drop_body: {
console.log("bar"); console.log("bar");
})([ console.log("baz") ]); })([ console.log("baz") ]);
} }
expect: {
void ([ [ , [][0] = console.log("foo") ] ] = [ [ console.log("baz") ] ]);
}
expect_stdout: [
"baz",
"foo",
]
node_version: ">=6"
}
drop_body_2: {
options = {
passes: 2,
side_effects: true,
yields: true,
}
input: {
(function*([ , a = console.log("foo") ]) {
console.log("bar");
})([ console.log("baz") ]);
}
expect: { expect: {
[ [ , [][0] = console.log("foo") ] ] = [ [ console.log("baz") ] ]; [ [ , [][0] = console.log("foo") ] ] = [ [ console.log("baz") ] ];
} }
@@ -1701,3 +1722,488 @@ issue_5526: {
] ]
node_version: ">=10" node_version: ">=10"
} }
issue_5576: {
options = {
inline: true,
}
input: {
(async function*() {
try {
(function() {
while (console.log("foo"));
})();
} finally {
console.log("bar");
}
})().next();
console.log("baz");
}
expect: {
(async function*() {
try {
while (console.log("foo"));
} finally {
console.log("bar");
}
})().next();
console.log("baz");
}
expect_stdout: [
"foo",
"bar",
"baz",
]
node_version: ">=10"
}
issue_5663: {
options = {
toplevel: true,
unused: true,
}
input: {
var [ , a ] = function*() {
console.log("foo");
yield console.log("bar");
console.log("baz");
yield console.log("moo");
console.log("moz");
yield FAIL;
}();
}
expect: {
var [ , , ] = function*() {
console.log("foo");
yield console.log("bar");
console.log("baz");
yield console.log("moo");
console.log("moz");
yield FAIL;
}();
}
expect_stdout: [
"foo",
"bar",
"baz",
"moo",
]
node_version: ">=6"
}
issue_5679_1: {
options = {
conditionals: true,
}
input: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return;
else
return;
} finally {
a = "PASS";
}
}
f().next();
console.log(a);
}
expect: {
var a = "FAIL";
async function* f(b) {
try {
b;
return;
} finally {
a = "PASS";
}
}
f().next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5679_2: {
options = {
conditionals: true,
}
input: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return undefined;
else
return;
} finally {
a = "PASS";
}
}
f().next();
console.log(a);
}
expect: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return void 0;
return;
} finally {
a = "PASS";
}
}
f().next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5679_3: {
options = {
conditionals: true,
}
input: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return;
else
return undefined;
} finally {
a = "PASS";
}
}
f(42).next();
console.log(a);
}
expect: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return;
return void 0;
} finally {
a = "PASS";
}
}
f(42).next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5679_4: {
options = {
conditionals: true,
}
input: {
var a = "PASS";
async function* f(b) {
try {
if (b)
return undefined;
else
return undefined;
} finally {
a = "FAIL";
}
}
f(null).next();
console.log(a);
}
expect: {
var a = "PASS";
async function* f(b) {
try {
return b, void 0;
} finally {
a = "FAIL";
}
}
f(null).next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5679_5: {
options = {
conditionals: true,
if_return: true,
}
input: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return console;
else
return;
} finally {
a = "PASS";
}
}
f().next();
console.log(a);
}
expect: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return console;
return;
} finally {
a = "PASS";
}
}
f().next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5679_6: {
options = {
conditionals: true,
if_return: true,
}
input: {
var a = "PASS";
async function* f(b) {
try {
if (b)
return;
else
return console;
} finally {
a = "FAIL";
}
}
f().next();
console.log(a);
}
expect: {
var a = "PASS";
async function* f(b) {
try {
if (!b)
return console;
} finally {
a = "FAIL";
}
}
f().next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5684: {
options = {
conditionals: true,
if_return: true,
}
input: {
(async function*() {
switch (42) {
default:
if (console.log("PASS"))
return;
return null;
case false:
}
})().next();
}
expect: {
(async function*() {
switch (42) {
default:
return console.log("PASS") ? void 0 : null;
case false:
}
})().next();
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5707_1: {
options = {
hoist_props: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
yields: true,
}
input: {
var a, b;
function* f(c = (b = 42, console.log("PASS"))) {}
b = f();
}
expect: {
(function(c = console.log("PASS")) {})();
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5707_2: {
options = {
hoist_props: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
yields: true,
}
input: {
var a, b;
function* f(c = (b = 42, console.log("PASS"))) {}
b = f();
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5710: {
options = {
conditionals: true,
if_return: true,
}
input: {
(async function*() {
try {
switch (42) {
case 42:
{
if (console.log("PASS"))
return;
return null;
}
break;
}
} finally {}
})().next();
}
expect: {
(async function*() {
try {
switch (42) {
case 42:
if (console.log("PASS"))
return;
return null;
break;
}
} finally {}
})().next();
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5749_1: {
options = {
collapse_vars: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
yields: true,
}
input: {
var a;
function* f() {}
a = f(new function() {
var b = a |= 0, c = a += console.log("PASS");
}());
}
expect: {
(function() {})(function() {
console.log("PASS");
}());
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5749_2: {
options = {
collapse_vars: true,
inline: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
yields: true,
}
input: {
var a;
function* f() {}
a = f(new function() {
var b = a |= 0, c = a += console.log("PASS");
}());
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5754: {
options = {
if_return: true,
}
input: {
async function* f(a, b) {
try {
if (a)
return void 0;
} finally {
console.log(b);
}
}
f(42, "foo").next();
f(null, "bar").next();
console.log("baz");
}
expect: {
async function* f(a, b) {
try {
if (a)
return void 0;
} finally {
console.log(b);
}
}
f(42, "foo").next();
f(null, "bar").next();
console.log("baz");
}
expect_stdout: [
"bar",
"baz",
"foo",
]
node_version: ">=10"
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,16 +1,10 @@
// (beautified) // (beautified)
var b = 0;
var expr2 = (0 - 1 - .1 - .1).toString(); var expr2 = (0 - 1 - .1 - .1).toString();
for (var key2 in expr2) { console.log(expr2);
--b; // output: -1.2000000000000002
}
console.log(b);
// output: -19
// //
// minify: -4 // minify: -1.2
// //
// options: { // options: {
// "compress": { // "compress": {

View File

@@ -14,7 +14,7 @@ if (typeof phantom == "undefined") {
args.splice(debug, 1); args.splice(debug, 1);
debug = true; debug = true;
} }
if (!args.length) args.push("-mcb", "beautify=false,webkit"); if (!args.length) args.push("-mcO", "webkit");
args.unshift("bin/uglifyjs"); args.unshift("bin/uglifyjs");
args.push("--validate", "--timings"); args.push("--validate", "--timings");
var child_process = require("child_process"); var child_process = require("child_process");
@@ -62,7 +62,11 @@ if (typeof phantom == "undefined") {
var cmd = process.platform == "win32" ? "npm.cmd" : "npm"; var cmd = process.platform == "win32" ? "npm.cmd" : "npm";
function npm(args, done) { function npm(args, done) {
child_process.spawn(cmd, args, { stdio: [ "ignore", 1, 2 ] }).on("exit", done); args.push("--loglevel=error");
child_process.spawn(cmd, args, {
shell: true,
stdio: [ "ignore", 1, 2 ],
}).on("exit", done);
} }
(function install() { (function install() {
@@ -72,9 +76,12 @@ if (typeof phantom == "undefined") {
"is-my-json-valid@2.20.5", "is-my-json-valid@2.20.5",
"phantomjs-prebuilt@2.1.14", "phantomjs-prebuilt@2.1.14",
"--no-audit", "--no-audit",
"--no-fund",
"--no-optional", "--no-optional",
"--no-save", "--no-save",
"--no-strict-ssl",
"--no-update-notifier", "--no-update-notifier",
"--production",
], function(code) { ], function(code) {
if (code) { if (code) {
console.log("npm install failed with code", code); console.log("npm install failed with code", code);

View File

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

View File

@@ -53,6 +53,23 @@ describe("bin/uglifyjs", function() {
done(); done();
}); });
}); });
it("Should work with --expression", function(done) {
exec([
uglifyjscmd,
"--expression",
"--compress",
"--mangle",
].join(" "), function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function(n){for(;n(););return 42}(A)\n");
done();
}).stdin.end([
"function(x) {",
" while (x()) {}",
" return 42;",
"}(A)",
].join("\n"));
});
it("Should work with --source-map names=true", function(done) { it("Should work with --source-map names=true", function(done) {
exec([ exec([
uglifyjscmd, uglifyjscmd,
@@ -69,7 +86,7 @@ describe("bin/uglifyjs", function() {
" q: b", " q: b",
"};", "};",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,",
].join("\n") ].join("\n");
assert.strictEqual(stdout.slice(0, expected.length), expected); assert.strictEqual(stdout.slice(0, expected.length), expected);
var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim())); var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim()));
assert.deepEqual(map.names, [ "obj", "p", "a", "q", "b" ]); assert.deepEqual(map.names, [ "obj", "p", "a", "q", "b" ]);
@@ -97,7 +114,7 @@ describe("bin/uglifyjs", function() {
" q: b", " q: b",
"};", "};",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,",
].join("\n") ].join("\n");
assert.strictEqual(stdout.slice(0, expected.length), expected); assert.strictEqual(stdout.slice(0, expected.length), expected);
var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim())); var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim()));
assert.deepEqual(map.names, []); assert.deepEqual(map.names, []);
@@ -126,7 +143,7 @@ describe("bin/uglifyjs", function() {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, [
"var bar=function(){function foo(bar){return bar}return foo}();", "var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxHQUNYLENBRUEsT0FBT0MsR0FDVixFQUFFIn0=",
"", "",
].join("\n")); ].join("\n"));
done(); done();
@@ -189,7 +206,13 @@ describe("bin/uglifyjs", function() {
}, 1000); }, 1000);
}); });
it("Should work with --keep-fargs (mangle only)", function(done) { it("Should work with --keep-fargs (mangle only)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fargs -m'; var command = [
uglifyjscmd,
"test/input/issue-1431/sample.js",
"--keep-fargs",
"--mangle",
"--no-module",
].join(" ");
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(){function n(a){return a*a}return x(n)}}function g(op){return op(1)+op(2)}console.log(f(g)()==5);\n"); assert.strictEqual(stdout, "function f(x){return function(){function n(a){return a*a}return x(n)}}function g(op){return op(1)+op(2)}console.log(f(g)()==5);\n");
@@ -197,7 +220,14 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with --keep-fargs (mangle & compress)", function(done) { it("Should work with --keep-fargs (mangle & compress)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fargs -m -c'; var command = [
uglifyjscmd,
"test/input/issue-1431/sample.js",
"--keep-fargs",
"--mangle",
"--no-module",
"--compress",
].join(" ");
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(){return x(function(a){return a*a})}}function g(op){return op(1)+op(2)}console.log(5==f(g)());\n"); assert.strictEqual(stdout, "function f(x){return function(){return x(function(a){return a*a})}}function g(op){return op(1)+op(2)}console.log(5==f(g)());\n");
@@ -205,7 +235,12 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with keep_fargs under mangler options", function(done) { it("Should work with keep_fargs under mangler options", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep_fargs=true'; var command = [
uglifyjscmd,
"test/input/issue-1431/sample.js",
"--mangle", "keep_fargs=true",
"--no-module",
].join(" ");
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(){function n(a){return a*a}return x(n)}}function g(op){return op(1)+op(2)}console.log(f(g)()==5);\n"); assert.strictEqual(stdout, "function f(x){return function(){function n(a){return a*a}return x(n)}}function g(op){return op(1)+op(2)}console.log(f(g)()==5);\n");
@@ -213,7 +248,12 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with --keep-fnames (mangle only)", function(done) { it("Should work with --keep-fnames (mangle only)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m'; var command = [
uglifyjscmd,
"test/input/issue-1431/sample.js",
"--keep-fnames",
"--mangle",
].join(" ");
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n"); assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
@@ -221,7 +261,14 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with --keep-fnames (mangle & compress)", function(done) { it("Should work with --keep-fnames (mangle & compress)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c'; var command = [
uglifyjscmd,
"test/input/issue-1431/sample.js",
"--keep-fnames",
"--mangle",
"--no-module",
"--compress",
].join(" ");
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(n){return function(){return n(function n(r){return r*r})}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n"); assert.strictEqual(stdout, "function f(n){return function(){return n(function n(r){return r*r})}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n");
@@ -313,7 +360,7 @@ describe("bin/uglifyjs", function() {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, [
"var bar=function(){function foo(bar){return bar}return foo}();", "var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxHQUNYLENBRUEsT0FBT0MsR0FDVixFQUFFIn0=",
"", "",
].join("\n")); ].join("\n"));
var stderrLines = stderr.split("\n"); var stderrLines = stderr.split("\n");
@@ -333,7 +380,7 @@ describe("bin/uglifyjs", function() {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, [
"var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();", "var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUVBLE1BQWNDLFFBQVFDLElBQUksRUFBRSxJQUFPLElBQUlGLElDQW5ELElBQUlHLElBQU0sV0FDTixTQUFTQyxJQUFLRCxLQUNWLE9BQU9BLElBR1gsT0FBT0MsSUFMRCJ9", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUVBLE1BQWNDLFFBQVFDLElBQUksRUFBRSxDQUFDLENBQUUsRUFBSSxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxHQUNYLENBRUEsT0FBT0MsR0FDVixFQUFFIn0=",
"", "",
].join("\n")); ].join("\n"));
var stderrLines = stderr.split("\n"); var stderrLines = stderr.split("\n");
@@ -540,7 +587,11 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should throw syntax error (delete x)", function(done) { it("Should throw syntax error (delete x)", function(done) {
var command = uglifyjscmd + " test/input/invalid/delete.js"; var command = [
uglifyjscmd,
"test/input/invalid/delete.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -554,7 +605,11 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should throw syntax error (function g(arguments))", function(done) { it("Should throw syntax error (function g(arguments))", function(done) {
var command = uglifyjscmd + " test/input/invalid/function_1.js"; var command = [
uglifyjscmd,
"test/input/invalid/function_1.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -568,7 +623,11 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should throw syntax error (function eval())", function(done) { it("Should throw syntax error (function eval())", function(done) {
var command = uglifyjscmd + " test/input/invalid/function_2.js"; var command = [
uglifyjscmd,
"test/input/invalid/function_2.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -582,7 +641,11 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should throw syntax error (iife arguments())", function(done) { it("Should throw syntax error (iife arguments())", function(done) {
var command = uglifyjscmd + " test/input/invalid/function_3.js"; var command = [
uglifyjscmd,
"test/input/invalid/function_3.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -596,7 +659,11 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should throw syntax error (catch (eval))", function(done) { it("Should throw syntax error (catch (eval))", function(done) {
var command = uglifyjscmd + " test/input/invalid/try.js"; var command = [
uglifyjscmd,
"test/input/invalid/try.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -610,7 +677,11 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should throw syntax error (var eval)", function(done) { it("Should throw syntax error (var eval)", function(done) {
var command = uglifyjscmd + " test/input/invalid/var.js"; var command = [
uglifyjscmd,
"test/input/invalid/var.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -624,7 +695,11 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should throw syntax error (var { eval })", function(done) { it("Should throw syntax error (var { eval })", function(done) {
var command = uglifyjscmd + " test/input/invalid/destructured_var.js"; var command = [
uglifyjscmd,
"test/input/invalid/destructured_var.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -774,7 +849,7 @@ describe("bin/uglifyjs", function() {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, [
'"use strict";var foo=function foo(x){return"foo "+x};console.log(foo("bar"));', '"use strict";var foo=function foo(x){return"foo "+x};console.log(foo("bar"));',
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiYUFBQSxJQUFJQSxJQUFNLFNBQU5BLElBQU1DLEdBQUEsTUFBSyxPQUFTQSxHQUN4QkMsUUFBUUMsSUFBSUgsSUFBSSJ9", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiYUFBQSxJQUFJQSxJQUFNLFNBQU5BLElBQU1DLEdBQUEsTUFBSyxPQUFTQSxDQUFkLEVBQ1ZDLFFBQVFDLElBQUlILElBQUksS0FBSixDQUFaIn0=",
"" ""
].join("\n")); ].join("\n"));
done(); done();
@@ -790,14 +865,15 @@ describe("bin/uglifyjs", function() {
var command = [ var command = [
uglifyjscmd, uglifyjscmd,
"test/input/issue-2310/input.js", "test/input/issue-2310/input.js",
"-c", "--compress",
"--no-module",
"--source-map", "url=inline", "--source-map", "url=inline",
].join(" "); ].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, [
'function foo(){return function(){console.log("PASS")}}foo()();', 'function foo(){return function(){console.log("PASS")}}foo()();',
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIiwiZiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsTUFDTCxPQUFPLFdBQ0hDLFFBQVFDLElBQUksU0FLUkYsS0FDUkcifQ==", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxNQUNMLE9BQU8sV0FDSEMsUUFBUUMsSUFBSSxNQUFNLENBQ3RCLENBQ0osQ0FHWUYsSUFBSSxFQUNWIn0=",
"" ""
].join("\n")); ].join("\n"));
done(); done();
@@ -823,7 +899,12 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with --mangle reserved=[]", function(done) { it("Should work with --mangle reserved=[]", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=[callback]"; var command = [
uglifyjscmd,
"test/input/issue-505/input.js",
"--mangle", "reserved=[callback]",
"--no-module",
].join(" ");
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'function test(callback){"aaaaaaaaaaaaaaaa";callback(err,data);callback(err,data)}\n'); assert.strictEqual(stdout, 'function test(callback){"aaaaaaaaaaaaaaaa";callback(err,data);callback(err,data)}\n');
@@ -831,7 +912,12 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with --mangle reserved=false", function(done) { it("Should work with --mangle reserved=false", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=false"; var command = [
uglifyjscmd,
"test/input/issue-505/input.js",
"--mangle", "reserved=false",
"--no-module",
].join(" ");
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'function test(a){"aaaaaaaaaaaaaaaa";a(err,data);a(err,data)}\n'); assert.strictEqual(stdout, 'function test(a){"aaaaaaaaaaaaaaaa";a(err,data);a(err,data)}\n');
@@ -848,7 +934,12 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with mangle.properties.regex from --config-file", function(done) { it("Should work with mangle.properties.regex from --config-file", function(done) {
var command = uglifyjscmd + " test/input/issue-3315/input.js --config-file test/input/issue-3315/config.json"; var command = [
uglifyjscmd,
"test/input/issue-3315/input.js",
"--config-file", "test/input/issue-3315/config.json",
"--no-module",
].join(" ");
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'function f(){"aaaaaaaaaa";var a={prop:1,t:2};return a.prop+a.t}\n'); assert.strictEqual(stdout, 'function f(){"aaaaaaaaaa";var a={prop:1,t:2};return a.prop+a.t}\n');
@@ -865,7 +956,12 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with explicit --rename", function(done) { it("Should work with explicit --rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js --rename"; var command = [
uglifyjscmd,
"test/input/rename/input.js",
"--no-module",
"--rename",
].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(a){return b(a);function b(c){return c+c}}\n"); assert.strictEqual(stdout, "function f(a){return b(a);function b(c){return c+c}}\n");
@@ -873,7 +969,14 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with explicit --no-rename", function(done) { it("Should work with explicit --no-rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2 --no-rename"; var command = [
uglifyjscmd,
"test/input/rename/input.js",
"--compress", "passes=2",
"--mangle",
"--no-module",
"--no-rename",
].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(n){return function(n){return n+n}(n)}\n"); assert.strictEqual(stdout, "function f(n){return function(n){return n+n}(n)}\n");
@@ -881,7 +984,13 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with implicit --rename", function(done) { it("Should work with implicit --rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2"; var command = [
uglifyjscmd,
"test/input/rename/input.js",
"--compress", "passes=2",
"--mangle",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(n){return n+n}\n"); assert.strictEqual(stdout, "function f(n){return n+n}\n");
@@ -889,7 +998,12 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with implicit --no-rename", function(done) { it("Should work with implicit --no-rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js -c passes=2"; var command = [
uglifyjscmd,
"test/input/rename/input.js",
"--compress", "passes=2",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(x){return x+x}(x)}\n"); assert.strictEqual(stdout, "function f(x){return function(x){return x+x}(x)}\n");
@@ -954,12 +1068,7 @@ describe("bin/uglifyjs", function() {
]).join("\n"); ]).join("\n");
exec(uglifyjscmd + " -mc", function(err, stdout) { exec(uglifyjscmd + " -mc", function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, "console.log(function(){var p={p:25},n={p:121},o={p:1024};return p.p+n.p+o.p}());\n");
"console.log(function(){",
"var p={p:25},n={p:121},o={p:1024};",
"return p.p+n.p+o.p",
"}());\n",
].join(""));
assert.strictEqual(run_code(stdout), run_code(code)); assert.strictEqual(run_code(stdout), run_code(code));
done(); done();
}).stdin.end(code); }).stdin.end(code);

View File

@@ -400,7 +400,7 @@ describe("comments", function() {
assert.strictEqual(ast.print_to_string({comments: "all"}), "/*!test1*/\n/*test2*/\n//!test3\n//test4\n//test5\n//!test6\n//test7\n//!test8"); assert.strictEqual(ast.print_to_string({comments: "all"}), "/*!test1*/\n/*test2*/\n//!test3\n//test4\n//test5\n//!test6\n//test7\n//!test8");
}); });
it("Should be able to filter commments with the 'some' option", function() { it("Should be able to filter comments with the 'some' option", function() {
var ast = UglifyJS.parse("// foo\n/*@preserve*/\n// bar\n/*@license*/\n//@license with the wrong comment type\n/*@cc_on something*/"); var ast = UglifyJS.parse("// foo\n/*@preserve*/\n// bar\n/*@license*/\n//@license with the wrong comment type\n/*@cc_on something*/");
assert.strictEqual(ast.print_to_string({comments: "some"}), "/*@preserve*/\n/*@license*/\n/*@cc_on something*/"); assert.strictEqual(ast.print_to_string({comments: "some"}), "/*@preserve*/\n/*@license*/\n/*@cc_on something*/");
}); });
@@ -476,7 +476,9 @@ describe("comments", function() {
for (var i = 1; i <= 5000; ++i) js += "// " + i + "\n"; for (var i = 1; i <= 5000; ++i) js += "// " + i + "\n";
for (; i <= 10000; ++i) js += "/* " + i + " */ /**/"; for (; i <= 10000; ++i) js += "/* " + i + " */ /**/";
js += "x; }"; js += "x; }";
var result = UglifyJS.minify(js, { mangle: false }); var result = UglifyJS.minify(js, {
mangle: false,
});
assert.strictEqual(result.code, "function lots_of_comments(x){return 7-x}"); assert.strictEqual(result.code, "function lots_of_comments(x){return 7-x}");
}); });
}); });

View File

@@ -348,7 +348,7 @@ describe("Directives", function() {
'"use strict";doSomething("foo");' '"use strict";doSomething("foo");'
], ],
[ [
// Nothing gets optimised in the compressor because "use asm" is the first statement // Nothing gets optimized in the compressor because "use asm" is the first statement
'"use asm";"use\\x20strict";1+1;', '"use asm";"use\\x20strict";1+1;',
'"use asm";"use\\x20strict";1+1;' '"use asm";"use\\x20strict";1+1;'
], ],
@@ -373,7 +373,9 @@ describe("Directives", function() {
'function f(){}' 'function f(){}'
], ],
].forEach(function(test) { ].forEach(function(test) {
var result = UglifyJS.minify(test[0]); var result = UglifyJS.minify(test[0], {
module: false,
});
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, test[1], test[0]); assert.strictEqual(result.code, test[1], test[0]);
}); });

View File

@@ -5,31 +5,44 @@ var path = require("path");
describe("bin/uglifyjs with input file globs", function() { describe("bin/uglifyjs with input file globs", function() {
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs'; var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
it("bin/uglifyjs with one input file extension glob.", function(done) { it("bin/uglifyjs with one input file extension glob.", function(done) {
var command = uglifyjscmd + ' "test/input/issue-1242/foo.*" -cm'; var command = [
uglifyjscmd,
'"test/input/issue-1242/foo.*"',
"--compress",
"--mangle",
"--no-module",
].join(" ");
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'var print=console.log.bind(console);function foo(o){print("Foo:",2*o)}\n'); assert.strictEqual(stdout, 'var print=console.log.bind(console);function foo(o){print("Foo:",2*o)}\n');
done(); done();
}); });
}); });
it("bin/uglifyjs with one input file name glob.", function(done) { it("bin/uglifyjs with one input file name glob.", function(done) {
var command = uglifyjscmd + ' "test/input/issue-1242/b*.es5" -cm'; var command = [
uglifyjscmd,
'"test/input/issue-1242/b*.es5"',
"--compress",
"--mangle",
"--no-module",
].join(" ");
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'function bar(n){return 3*n}function baz(n){return n/2}\n'); assert.strictEqual(stdout, 'function bar(n){return 3*n}function baz(n){return n/2}\n');
done(); done();
}); });
}); });
it("bin/uglifyjs with multiple input file globs.", function(done) { it("bin/uglifyjs with multiple input file globs.", function(done) {
var command = uglifyjscmd + ' "test/input/issue-1242/???.es5" "test/input/issue-1242/*.js" -mc toplevel,passes=3'; var command = [
uglifyjscmd,
'"test/input/issue-1242/???.es5"',
'"test/input/issue-1242/*.js"',
"--compress", "toplevel,passes=3",
"--mangle",
"--no-module",
].join(" ");
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'var print=console.log.bind(console);print("qux",9,6),print("Foo:",22);\n'); assert.strictEqual(stdout, 'var print=console.log.bind(console);print("qux",9,6),print("Foo:",22);\n');
done(); done();
}); });

View File

@@ -12,17 +12,16 @@ describe("let", function() {
s += '}'; s += '}';
var result = UglifyJS.minify(s, { var result = UglifyJS.minify(s, {
compress: false, compress: false,
}).code; });
if (result.error) throw result.error;
// Verify that select keywords and reserved keywords not produced // Verify that select keywords and reserved keywords not produced
[ [
"do", "do",
"let", "let",
"var", "var",
].forEach(function(name) { ].forEach(function(name) {
assert.strictEqual(result.indexOf("var " + name + "="), -1); assert.strictEqual(result.code.indexOf("var " + name + "="), -1);
}); });
// Verify that the variable names that appeared immediately before // Verify that the variable names that appeared immediately before
// and after the erroneously generated variable name still exist // and after the erroneously generated variable name still exist
// to show the test generated enough symbols. // to show the test generated enough symbols.
@@ -31,27 +30,29 @@ describe("let", function() {
"eet", "fet", "eet", "fet",
"rar", "oar", "rar", "oar",
].forEach(function(name) { ].forEach(function(name) {
assert.notStrictEqual(result.indexOf("var " + name + "="), -1); assert.notStrictEqual(result.code.indexOf("var " + name + "="), -1);
}); });
}); });
it("Should quote mangled properties that are reserved keywords", function() { it("Should quote mangled properties that are reserved keywords", function() {
var s = '"rrrrrnnnnniiiiiaaaaa";'; var s = '"rrrrrnnnnniiiiiaaaaa";';
for (var i = 0; i < 18000; i++) { for (var i = 0; i < 18000; i++) {
s += "v.b" + i + ";"; s += "v.b" + i + "=v;";
} }
var result = UglifyJS.minify(s, { var result = UglifyJS.minify(s, {
compress: false, compress: false,
ie: true, ie: true,
mangle: { mangle: {
properties: true, properties: {
} domprops: true,
}).code; },
},
});
if (result.error) throw result.error;
[ [
"in", "in",
"var", "var",
].forEach(function(name) { ].forEach(function(name) {
assert.notStrictEqual(result.indexOf(name), -1); assert.notStrictEqual(result.code.indexOf('v["' + name + '"]'), -1);
assert.notStrictEqual(result.indexOf('v["' + name + '"]'), -1);
}); });
}); });
it("Should parse `let` as name correctly", function() { it("Should parse `let` as name correctly", function() {

View File

@@ -6,8 +6,10 @@ describe("Input file as map", function() {
var jsMap = { var jsMap = {
'/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};' '/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};'
}; };
var result = UglifyJS.minify(jsMap, {sourceMap: true}); var result = UglifyJS.minify(jsMap, {
sourceMap: true,
});
if (result.error) throw result.error;
var map = JSON.parse(result.map); var map = JSON.parse(result.map);
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};'); assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
assert.deepEqual(map.sources, ['/scripts/foo.js']); assert.deepEqual(map.sources, ['/scripts/foo.js']);
@@ -26,8 +28,10 @@ describe("Input file as map", function() {
'var foo = {"x": 1, y: 2, \'z\': 3};', 'var foo = {"x": 1, y: 2, \'z\': 3};',
'var bar = 15;' 'var bar = 15;'
]; ];
var result = UglifyJS.minify(jsSeq, {sourceMap: true}); var result = UglifyJS.minify(jsSeq, {
sourceMap: true,
});
if (result.error) throw result.error;
var map = JSON.parse(result.map); var map = JSON.parse(result.map);
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3},bar=15;'); assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3},bar=15;');
assert.deepEqual(map.sources, ['0', '1']); assert.deepEqual(map.sources, ['0', '1']);
@@ -37,8 +41,12 @@ describe("Input file as map", function() {
var jsMap = { var jsMap = {
'/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};' '/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};'
}; };
var result = UglifyJS.minify(jsMap, {sourceMap: {includeSources: true}}); var result = UglifyJS.minify(jsMap, {
sourceMap: {
includeSources: true,
},
});
if (result.error) throw result.error;
var map = JSON.parse(result.map); var map = JSON.parse(result.map);
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};'); assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
assert.deepEqual(map.sourcesContent, ['var foo = {"x": 1, y: 2, \'z\': 3};']); assert.deepEqual(map.sourcesContent, ['var foo = {"x": 1, y: 2, \'z\': 3};']);

View File

@@ -48,8 +48,8 @@ describe("minify", function() {
var result = UglifyJS.minify(code, { var result = UglifyJS.minify(code, {
mangle: { mangle: {
cache: cache, cache: cache,
toplevel: true toplevel: true,
} },
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
original += code; original += code;
@@ -79,9 +79,9 @@ describe("minify", function() {
var code = read("test/input/issue-1242/" + file); var code = read("test/input/issue-1242/" + file);
var result = UglifyJS.minify(code, { var result = UglifyJS.minify(code, {
mangle: { mangle: {
toplevel: true toplevel: true,
}, },
nameCache: cache nameCache: cache,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
original += code; original += code;
@@ -110,10 +110,12 @@ describe("minify", function() {
var result = UglifyJS.minify(code, { var result = UglifyJS.minify(code, {
compress: false, compress: false,
mangle: { mangle: {
properties: true, properties: {
toplevel: true domprops: true,
}, },
nameCache: cache toplevel: true,
},
nameCache: cache,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
original += code; original += code;
@@ -160,8 +162,9 @@ describe("minify", function() {
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};'; var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
var result = UglifyJS.minify(js, { var result = UglifyJS.minify(js, {
output: { output: {
keep_quoted_props: true keep_quoted_props: true,
}}); },
});
assert.strictEqual(result.code, 'var foo={"x":1,y:2,"z":3};'); assert.strictEqual(result.code, 'var foo={"x":1,y:2,"z":3};');
}); });
it("Should preserve quote styles when quote_style is 3", function() { it("Should preserve quote styles when quote_style is 3", function() {
@@ -169,8 +172,9 @@ describe("minify", function() {
var result = UglifyJS.minify(js, { var result = UglifyJS.minify(js, {
output: { output: {
keep_quoted_props: true, keep_quoted_props: true,
quote_style: 3 quote_style: 3,
}}); },
});
assert.strictEqual(result.code, 'var foo={"x":1,y:2,\'z\':3};'); assert.strictEqual(result.code, 'var foo={"x":1,y:2,\'z\':3};');
}); });
it("Should not preserve quotes in object literals when disabled", function() { it("Should not preserve quotes in object literals when disabled", function() {
@@ -178,8 +182,9 @@ describe("minify", function() {
var result = UglifyJS.minify(js, { var result = UglifyJS.minify(js, {
output: { output: {
keep_quoted_props: false, keep_quoted_props: false,
quote_style: 3 quote_style: 3,
}}); },
});
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};'); assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
}); });
}); });
@@ -188,32 +193,30 @@ describe("minify", function() {
it("Shouldn't mangle quoted properties", function() { it("Shouldn't mangle quoted properties", function() {
var js = 'a["foo"] = "bar"; a.color = "red"; x = {"bar": 10};'; var js = 'a["foo"] = "bar"; a.color = "red"; x = {"bar": 10};';
var result = UglifyJS.minify(js, { var result = UglifyJS.minify(js, {
compress: { compress: true,
properties: false
},
mangle: { mangle: {
properties: { properties: {
keep_quoted: true domprops: true,
} keep_quoted: true,
},
}, },
output: { output: {
keep_quoted_props: true, keep_quoted_props: true,
quote_style: 3 quote_style: 3,
} },
}); });
assert.strictEqual(result.code, assert.strictEqual(result.code, 'a["foo"]="bar",a.a="red",x={"bar":10};');
'a["foo"]="bar",a.a="red",x={"bar":10};');
}); });
it("Should not mangle quoted property within dead code", function() { it("Should not mangle quoted property within dead code", function() {
var result = UglifyJS.minify('({ "keep": 1 }); g.keep = g.change;', { var result = UglifyJS.minify('({ "keep": 1 }); g.keep = g.change = 42;', {
mangle: { mangle: {
properties: { properties: {
keep_quoted: true keep_quoted: true,
} },
} },
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, "g.keep=g.g;"); assert.strictEqual(result.code, "g.keep=g.g=42;");
}); });
}); });
@@ -223,7 +226,7 @@ describe("minify", function() {
output: { output: {
comments: "all", comments: "all",
beautify: false, beautify: false,
} },
}); });
var code = result.code; var code = result.code;
assert.strictEqual(code, "// comment1 comment2\nbar();"); assert.strictEqual(code, "// comment1 comment2\nbar();");
@@ -233,7 +236,7 @@ describe("minify", function() {
output: { output: {
comments: "all", comments: "all",
beautify: false, beautify: false,
} },
}); });
var code = result.code; var code = result.code;
assert.strictEqual(code, "var a=function(){foo()}();"); assert.strictEqual(code, "var a=function(){foo()}();");
@@ -301,7 +304,7 @@ describe("minify", function() {
compress: false, compress: false,
mangle: false, mangle: false,
output: { output: {
ast: true ast: true,
}, },
}).ast; }).ast;
assert.strictEqual(ast.TYPE, "Toplevel"); assert.strictEqual(ast.TYPE, "Toplevel");
@@ -312,9 +315,9 @@ describe("minify", function() {
var stat = ast.body[0].body[0]; var stat = ast.body[0].body[0];
UglifyJS.minify(ast, { UglifyJS.minify(ast, {
compress: { compress: {
sequences: false sequences: false,
}, },
mangle: false mangle: false,
}); });
assert.ok(stat.body); assert.ok(stat.body);
assert.strictEqual(stat.print_to_string(), "a=x()"); assert.strictEqual(stat.print_to_string(), "a=x()");

View File

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

View File

@@ -236,9 +236,9 @@ describe("test/reduce.js", function() {
}); });
it("Should report trailing whitespace difference in stringified format", function() { it("Should report trailing whitespace difference in stringified format", function() {
var code = [ var code = [
"for (var a in (1 - .8).toString()) {", "[].forEach.call((1 - .8).toString(), function() {",
" console.log();", " console.log();",
"}", "});",
].join("\n"); ].join("\n");
var result = reduce_test(code, { var result = reduce_test(code, {
compress: { compress: {
@@ -333,6 +333,7 @@ describe("test/reduce.js", function() {
unsafe_math: true, unsafe_math: true,
}, },
mangle: false, mangle: false,
module: false,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, [ assert.strictEqual(result.code, [
@@ -346,7 +347,8 @@ describe("test/reduce.js", function() {
'// "compress": {', '// "compress": {',
'// "unsafe_math": true', '// "unsafe_math": true',
'// },', '// },',
'// "mangle": false', '// "mangle": false,',
'// "module": false',
"// }", "// }",
].join("\n")); ].join("\n"));
}); });
@@ -449,6 +451,27 @@ describe("test/reduce.js", function() {
].join("\n")); ].join("\n"));
}); });
it("Should transform `export default function` correctly", function() { it("Should transform `export default function` correctly", function() {
if (semver.satisfies(process.version, "<8")) return;
var code = [
"export default function f(a) {",
" for (var k in a)",
" console.log(k);",
" (async function() {})();",
"}",
"f(this);",
].join("\n");
var result = reduce_test(code, {
mangle: false,
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"// Can't reproduce test failure",
"// minify options: {",
'// "mangle": false',
"// }",
].join("\n"));
});
it("Should transform `export default (function)` correctly", function() {
var code = [ var code = [
"for (var k in this)", "for (var k in this)",
" console.log(k);", " console.log(k);",

View File

@@ -23,7 +23,7 @@ function get_map() {
"names": [], "names": [],
"mappings": ";;AAAA,IAAI,MAAM,SAAN,GAAM;AAAA,SAAK,SAAS,CAAd;AAAA,CAAV;AACA,QAAQ,GAAR,CAAY,IAAI,KAAJ,CAAZ", "mappings": ";;AAAA,IAAI,MAAM,SAAN,GAAM;AAAA,SAAK,SAAS,CAAd;AAAA,CAAV;AACA,QAAQ,GAAR,CAAY,IAAI,KAAJ,CAAZ",
"file": "bundle.js", "file": "bundle.js",
"sourcesContent": ["let foo = x => \"foo \" + x;\nconsole.log(foo(\"bar\"));"] "sourcesContent": [ "let foo = x => \"foo \" + x;\nconsole.log(foo(\"bar\"));" ],
}; };
} }
@@ -42,7 +42,7 @@ function prepare_map(sourceMap) {
sourceMap: { sourceMap: {
content: sourceMap, content: sourceMap,
includeSources: true, includeSources: true,
} },
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
return JSON.parse(result.map); return JSON.parse(result.map);
@@ -112,7 +112,7 @@ describe("sourcemaps", function() {
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, "class A{static P=42;set#q(s){}}"); assert.strictEqual(result.code, "class A{static P=42;set#q(s){}}");
assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["A","P","#q","v"],"mappings":"MAAMA,EACFC,SAAW,GACXC,MAAOC"}'); assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["A","P","#q","v"],"mappings":"MAAMA,EACFC,SAAW,GACXC,MAAOC,IACX"}');
}); });
it("Should mark array/object literals", function() { it("Should mark array/object literals", function() {
var result = UglifyJS.minify([ var result = UglifyJS.minify([
@@ -124,7 +124,7 @@ describe("sourcemaps", function() {
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, "({}).wat([]);"); assert.strictEqual(result.code, "({}).wat([]);");
assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["wat"],"mappings":"CAAU,IACNA,IAAI"}'); assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["wat"],"mappings":"CAAU,IACNA,IAAI,EAAE"}');
}); });
it("Should give correct sourceRoot", function() { it("Should give correct sourceRoot", function() {
var code = "console.log(42);"; var code = "console.log(42);";
@@ -135,7 +135,7 @@ describe("sourcemaps", function() {
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, code); assert.strictEqual(result.code, code);
assert.strictEqual(result.map, '{"version":3,"sourceRoot":"//foo.bar/","sources":["0"],"names":["console","log"],"mappings":"AAAAA,QAAQC,IAAI"}'); assert.strictEqual(result.map, '{"version":3,"sourceRoot":"//foo.bar/","sources":["0"],"names":["console","log"],"mappings":"AAAAA,QAAQC,IAAI,EAAE"}');
}); });
it("Should produce same source map with DOS or UNIX line endings", function() { it("Should produce same source map with DOS or UNIX line endings", function() {
var code = [ var code = [
@@ -160,8 +160,8 @@ describe("sourcemaps", function() {
sourceMap: { sourceMap: {
content: read("test/input/issue-1236/simple.js.map"), content: read("test/input/issue-1236/simple.js.map"),
filename: "simple.min.js", filename: "simple.min.js",
includeSources: true includeSources: true,
} },
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
var map = JSON.parse(result.map); var map = JSON.parse(result.map);
@@ -175,8 +175,8 @@ describe("sourcemaps", function() {
sourceMap: { sourceMap: {
content: "inline", content: "inline",
includeSources: true, includeSources: true,
url: "inline" url: "inline",
} },
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code + "\n", read("test/input/issue-520/output.js")); assert.strictEqual(result.code + "\n", read("test/input/issue-520/output.js"));
@@ -185,7 +185,7 @@ describe("sourcemaps", function() {
var result = UglifyJS.minify(read("test/input/issue-1323/sample.js"), { var result = UglifyJS.minify(read("test/input/issue-1323/sample.js"), {
mangle: false, mangle: false,
sourceMap: { sourceMap: {
content: "inline" content: "inline",
}, },
warnings: true, warnings: true,
}); });
@@ -206,7 +206,7 @@ describe("sourcemaps", function() {
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, [ assert.strictEqual(result.code, [
"var Foo=function(){console.log(3)},bar=(new Foo,function(o){return o});", "var Foo=function(){console.log(3)},bar=(new Foo,function(o){return o});",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwiMSJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFdBQWdCQyxRQUFRQyxJQUFJLElDQWxDQyxLREEyQyxJQUFJSCxJQ0MvQyxTQUFjRyxHQUNWLE9BQU9BIn0=", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwiMSJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFdBQWdCQyxRQUFRQyxJQUFJLENBQUcsQ0FBRSxFQ0F2Q0MsS0RBMkMsSUFBSUgsSUNDL0MsU0FBY0csR0FDVixPQUFPQSxDQUNYIn0=",
].join("\n")); ].join("\n"));
assert.deepEqual(result.warnings, [ "WARN: inline source map not found: 1" ]); assert.deepEqual(result.warnings, [ "WARN: inline source map not found: 1" ]);
}); });
@@ -239,13 +239,13 @@ describe("sourcemaps", function() {
sourceMap: { sourceMap: {
content: "inline", content: "inline",
includeSources: true, includeSources: true,
url: "inline" url: "inline",
} },
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code + "\n", read("test/input/issue-3294/output.js")); assert.strictEqual(result.code + "\n", read("test/input/issue-3294/output.js"));
}); });
it("Should work in presence of unrecognised annotations", function() { it("Should work in presence of unrecognized annotations", function() {
var result = UglifyJS.minify(read("test/input/issue-3441/input.js"), { var result = UglifyJS.minify(read("test/input/issue-3441/input.js"), {
compress: false, compress: false,
mangle: false, mangle: false,
@@ -255,7 +255,7 @@ describe("sourcemaps", function() {
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, '(function(){console.log("hello")}).call(this);'); 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"}'); assert.strictEqual(result.map, '{"version":3,"sources":["main.coffee"],"names":["console","log"],"mappings":"CAAA,WAAAA,QAAQC,IAAI,OAAZ"}');
}); });
it("Should not overwrite existing sourcesContent", function() { it("Should not overwrite existing sourcesContent", function() {
var result = UglifyJS.minify({ var result = UglifyJS.minify({
@@ -296,16 +296,16 @@ describe("sourcemaps", function() {
it("Should append source map to output js when sourceMapInline is enabled", function() { it("Should append source map to output js when sourceMapInline is enabled", function() {
var result = UglifyJS.minify('var a = function(foo) { return foo; };', { var result = UglifyJS.minify('var a = function(foo) { return foo; };', {
sourceMap: { sourceMap: {
url: "inline" url: "inline",
} },
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
var code = result.code; var code = result.code;
assert.strictEqual(code, "var a=function(n){return n};\n" + assert.strictEqual(code, "var a=function(n){return n};\n" +
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BIn0="); "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BLENBQUsifQ==");
}); });
it("Should not append source map to output js when sourceMapInline is not enabled", function() { it("Should not append source map to output js when sourceMapInline is not enabled", function() {
var result = UglifyJS.minify('var a = function(foo) { return foo; };'); var result = UglifyJS.minify("var a = function(foo) { return foo; };");
if (result.error) throw result.error; if (result.error) throw result.error;
var code = result.code; var code = result.code;
assert.strictEqual(code, "var a=function(n){return n};"); assert.strictEqual(code, "var a=function(n){return n};");
@@ -316,11 +316,11 @@ describe("sourcemaps", function() {
directives: false, directives: false,
}, },
output: { output: {
max_line_len: 20 max_line_len: 20,
}, },
sourceMap: { sourceMap: {
url: "inline" url: "inline",
} },
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, read("test/input/issue-505/output.js")); assert.strictEqual(result.code, read("test/input/issue-505/output.js"));
@@ -334,7 +334,7 @@ describe("sourcemaps", function() {
sourceMap: { sourceMap: {
includeSources: true, includeSources: true,
url: "inline", url: "inline",
} },
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
var map = JSON.parse(result.map); var map = JSON.parse(result.map);
@@ -348,7 +348,7 @@ describe("sourcemaps", function() {
sourceMap: { sourceMap: {
content: "inline", content: "inline",
includeSources: true, includeSources: true,
} },
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
map = JSON.parse(result.map); map = JSON.parse(result.map);

View File

@@ -1,6 +1,6 @@
var fs = require("fs"); var fs = require("fs");
new Function("exports", require("../tools/node").FILES.map(function(file) { new Function("domprops", "exports", require("../tools/node").FILES.map(function(file) {
if (/exports\.js$/.test(file)) file = require.resolve("./exports"); if (/exports\.js$/.test(file)) file = require.resolve("./exports");
return fs.readFileSync(file, "utf8"); return fs.readFileSync(file, "utf8");
}).join("\n\n"))(exports); }).join("\n\n"))(require("../tools/domprops.json"), exports);

View File

@@ -20,6 +20,9 @@ Error.stackTraceLimit = Infinity;
module.exports = function reduce_test(testcase, minify_options, reduce_options) { module.exports = function reduce_test(testcase, minify_options, reduce_options) {
minify_options = minify_options || {}; minify_options = minify_options || {};
reduce_options = reduce_options || {}; reduce_options = reduce_options || {};
var parse_options = {
module: minify_options.module || minify_options.module === undefined,
}
var print_options = {}; var print_options = {};
[ [
"ie", "ie",
@@ -160,6 +163,11 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
return expr instanceof U.AST_Spread ? expr.expression : expr; return expr instanceof U.AST_Spread ? expr.expression : expr;
} }
} }
else if (node instanceof U.AST_Await) {
node.start._permute++;
CHANGED = true;
return node.expression;
}
else if (node instanceof U.AST_Binary) { else if (node instanceof U.AST_Binary) {
var permute = ((node.start._permute += step) * steps | 0) % 4; var permute = ((node.start._permute += step) * steps | 0) % 4;
var expr = [ var expr = [
@@ -185,7 +193,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
} }
else if (node instanceof U.AST_BlockStatement) { else if (node instanceof U.AST_BlockStatement) {
if (in_list && node.body.filter(function(node) { if (in_list && node.body.filter(function(node) {
return node instanceof U.AST_Const; return node instanceof U.AST_Const || node instanceof U.AST_Let;
}).length == 0) { }).length == 0) {
node.start._permute++; node.start._permute++;
CHANGED = true; CHANGED = true;
@@ -327,19 +335,21 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
} }
else if (node instanceof U.AST_ForEnumeration) { else if (node instanceof U.AST_ForEnumeration) {
var expr; var expr;
switch ((node.start._permute * steps | 0) % 3) { switch ((node.start._permute * steps | 0) % 4) {
case 0: case 0:
if (node.init instanceof U.AST_Definitions) {
if (node.init instanceof U.AST_Const) break;
if (node.init.definitions[0].name instanceof U.AST_Destructured) break;
}
expr = node.init;
break;
case 1:
expr = node.object; expr = node.object;
break; break;
case 1:
expr = wrap_with_console_log(node.object);
break;
case 2: case 2:
if (!has_loopcontrol(node.body, node, parent)) expr = node.body; if (has_loopcontrol(node.body, node, parent)) break;
expr = node.body;
break;
case 3:
if (!(node.init instanceof U.AST_Var)) break;
if (node.init.definitions[0].name instanceof U.AST_Destructured) break;
expr = node.init;
break; break;
} }
node.start._permute += step; node.start._permute += step;
@@ -353,9 +363,17 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
node.condition, node.condition,
node.body, node.body,
node.alternative, node.alternative,
][ (node.start._permute * steps | 0) % 3 ]; node,
][ (node.start._permute * steps | 0) % 4 ];
node.start._permute += step; node.start._permute += step;
if (expr) { if (expr === node) {
if (node.alternative) {
expr = node.clone();
expr.alternative = null;
CHANGED = true;
return expr;
}
} else if (expr) {
// replace if statement with its condition, then block or else block // replace if statement with its condition, then block or else block
CHANGED = true; CHANGED = true;
return to_statement(expr); return to_statement(expr);
@@ -461,7 +479,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
} }
} }
else if (node instanceof U.AST_VarDef) { else if (node instanceof U.AST_VarDef) {
if (node.value) { if (node.value && !(node.name instanceof U.AST_Destructured || parent instanceof U.AST_Const)) {
node.start._permute++; node.start._permute++;
CHANGED = true; CHANGED = true;
return new U.AST_VarDef({ return new U.AST_VarDef({
@@ -534,7 +552,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
var before_iterations, diff_error_message, passes = 3, testcase_ast; var before_iterations, diff_error_message, passes = 3, testcase_ast;
for (var pass = 1; pass <= passes; pass++) { for (var pass = 1; pass <= passes; pass++) {
if (before_iterations !== testcase) { if (before_iterations !== testcase) {
testcase_ast = U.parse(testcase); testcase_ast = U.parse(testcase, parse_options);
if (diff_error_message === testcase) { if (diff_error_message === testcase) {
// only difference detected is in error message, so expose that and try again // only difference detected is in error message, so expose that and try again
testcase_ast.transform(new U.TreeTransformer(function(node, descend) { testcase_ast.transform(new U.TreeTransformer(function(node, descend) {
@@ -556,7 +574,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
testcase = code; testcase = code;
differs = diff; differs = diff;
} else { } else {
testcase_ast = U.parse(testcase); testcase_ast = U.parse(testcase, parse_options);
} }
} }
diff_error_message = null; diff_error_message = null;
@@ -616,6 +634,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
var beautified = U.minify(testcase, { var beautified = U.minify(testcase, {
compress: false, compress: false,
mangle: false, mangle: false,
module: minify_options.module,
output: function() { output: function() {
var options = JSON.parse(JSON.stringify(print_options)); var options = JSON.parse(JSON.stringify(print_options));
options.beautify = true; options.beautify = true;
@@ -768,7 +787,7 @@ function run_code(code, toplevel, result_cache, timeout) {
if (!value) { if (!value) {
var start = Date.now(); var start = Date.now();
result_cache[key] = value = { result_cache[key] = value = {
result: sandbox.run_code(sandbox.patch_module_statements(code), toplevel, timeout), result: sandbox.run_code(code, toplevel, timeout),
elapsed: Date.now() - start, elapsed: Date.now() - start,
}; };
} }
@@ -796,13 +815,7 @@ function compare_run_code(code, minify_options, result_cache, max_timeout) {
}; };
function run(code, timeout) { function run(code, timeout) {
if (minify_options.module) code = [ return run_code(sandbox.patch_module_statements(code, minify_options.module), toplevel, result_cache, timeout);
'"use strict";',
"(async()=>{",
code,
'})().catch(e=>process.on("exit",()=>{throw e}));',
].join("\n");
return run_code(code, toplevel, result_cache, timeout);
} }
} }

View File

@@ -1,11 +1,8 @@
require("./run")([ require("./run")([
"-b", "-mb braces",
"-b braces", "--toplevel -c",
"-m", "--no-module -mc",
"-mc passes=3",
"-mc passes=3,toplevel",
"-mc passes=3,unsafe", "-mc passes=3,unsafe",
"-mc keep_fargs=false,passes=3",
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto", "-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
].map(function(options) { ].map(function(options) {
var args = options.split(/ /); var args = options.split(/ /);

View File

@@ -41,6 +41,11 @@ rm -rf tmp/buble \
@@ -309 +309 @@ export default class BlockStatement extends Node { @@ -309 +309 @@ export default class BlockStatement extends Node {
- let cont = false; // TODO implement proper continue... - let cont = false; // TODO implement proper continue...
+ let cont = !declarations; // TODO implement proper continue... + let cont = !declarations; // TODO implement proper continue...
--- a/src/program/types/VariableDeclaration.js
+++ b/src/program/types/VariableDeclaration.js
@@ -38 +38 @@ export default class VariableDeclaration extends Node {
- code.remove(c, declarator.id.start);
+ code.remove(c, declarator.id.start, lastDeclaratorIsPattern);
EOF EOF
ERR=$?; if [ "$ERR" != "0" ]; then echo "Error: $ERR"; exit $ERR; fi ERR=$?; if [ "$ERR" != "0" ]; then echo "Error: $ERR"; exit $ERR; fi
minify_in_situ "src" \ minify_in_situ "src" \

View File

@@ -36,7 +36,7 @@ EOF
} }
if [ $NATIVE ]; then unset -f timeout; fi if [ $NATIVE ]; then unset -f timeout; fi
while !(git clone --branch v1.6.0 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs); do while !(git clone --branch v1.6.2 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs); do
rm -rf ~/.nvs rm -rf ~/.nvs
done done
while ! timeout 60 bash -c ". ~/.nvs/nvs.sh add $NODE && nvs use $NODE"; do while ! timeout 60 bash -c ". ~/.nvs/nvs.sh add $NODE && nvs use $NODE"; do
@@ -48,7 +48,10 @@ done
nvs use $NODE nvs use $NODE
node --version node --version
npm config set audit false npm config set audit false
npm config set optional false npm config set fund false
npm config set loglevel error
npm config set omit optional || true
npm config set optional false || true
npm config set save false npm config set save false
npm config set strict-ssl false npm config set strict-ssl false
npm config set update-notifier false npm config set update-notifier false

View File

@@ -4,6 +4,7 @@ require("./run")([
].map(function(options) { ].map(function(options) {
var args = options.split(/ /); var args = options.split(/ /);
args.unshift("test/jetstream.js"); args.unshift("test/jetstream.js");
args.push("-b", "beautify=false,webkit"); args.push("-O", "webkit");
args.push("--no-module");
return args; return args;
})); }));

View File

@@ -35,18 +35,27 @@ npm_install() {
done done
} }
workaround() {
FILE="$1"
echo 'Monkey patching' $FILE
CODE=`cat $FILE`
sed -E 's/for ?\((var [^;{]+;)/\1for\(;/g' > $FILE <<EOF
$CODE
EOF
}
rm -rf tmp/sucrase \ rm -rf tmp/sucrase \
&& git clone https://github.com/alangpierce/sucrase.git tmp/sucrase \ && git clone https://github.com/alangpierce/sucrase.git tmp/sucrase \
&& cd tmp/sucrase \ && cd tmp/sucrase \
&& rm -rf .git/hooks \ && rm -rf .git/hooks \
&& git checkout 38b66f3009feb76750a799deea211adcc83574f1 \ && git checkout 7284b3733aa114b3f4f5371e36ff5a4704ec860e \
&& patch -l -p1 <<EOF && patch -l -p1 <<EOF
--- a/package.json --- a/package.json
+++ b/package.json +++ b/package.json
@@ -25 +24,0 @@ @@ -25 +24,0 @@
- "prepublishOnly": "yarn clean && yarn build", - "prepublishOnly": "yarn clean && yarn build",
@@ -65 +63,0 @@ @@ -69 +67,0 @@
- "test262-harness": "^6.5.0", - "test262-harness": "^10.0.0",
--- a/script/build.ts --- a/script/build.ts
+++ b/script/build.ts +++ b/script/build.ts
@@ -16 +15,0 @@ async function main(): Promise<void> { @@ -16 +15,0 @@ async function main(): Promise<void> {
@@ -57,11 +66,11 @@ rm -rf tmp/sucrase \
- () => buildIntegration("./integrations/webpack-loader"), - () => buildIntegration("./integrations/webpack-loader"),
- () => buildIntegration("./integrations/webpack-object-rest-spread-plugin"), - () => buildIntegration("./integrations/webpack-object-rest-spread-plugin"),
- () => buildWebsite(), - () => buildWebsite(),
@@ -66,3 +59,0 @@ async function buildSucrase(): Promise<void> { @@ -62,3 +55,0 @@ async function buildSucrase(): Promise<void> {
- // Also add in .d.ts files from tsc, which only need to be compiled once. - // Also add in .d.ts files from tsc, which only need to be compiled once.
- await run(\`\${TSC} --project ./src --outDir ./dist-types\`); - await run(\`\${TSC} --project ./src --outDir ./dist-types\`);
- await mergeDirectoryContents("./dist-types/src", "./dist"); - await mergeDirectoryContents("./dist-types/src", "./dist/types");
@@ -70 +61 @@ async function buildSucrase(): Promise<void> { @@ -66 +57 @@ async function buildSucrase(): Promise<void> {
- await run("yarn link"); - await run("yarn link");
+ await run("npm link"); + await run("npm link");
--- a/src/identifyShadowedGlobals.ts --- a/src/identifyShadowedGlobals.ts
@@ -70,28 +79,38 @@ rm -rf tmp/sucrase \
+export { identifyShadowedGlobals as HACK }; +export { identifyShadowedGlobals as HACK };
--- a/src/parser/tokenizer/state.ts --- a/src/parser/tokenizer/state.ts
+++ b/src/parser/tokenizer/state.ts +++ b/src/parser/tokenizer/state.ts
@@ -100,0 +101 @@ export default class State { @@ -106,0 +107 @@ export default class State {
+export { State as HACK }; +export { State as HACK };
--- a/src/transformers/JSXTransformer.ts --- a/src/transformers/JSXTransformer.ts
+++ b/src/transformers/JSXTransformer.ts +++ b/src/transformers/JSXTransformer.ts
@@ -253,0 +254 @@ export default class JSXTransformer extends Transformer { @@ -560,0 +561 @@ export default class JSXTransformer extends Transformer {
+export { JSXTransformer as HACK }; +export { JSXTransformer as HACK };
--- a/src/util/getClassInfo.ts --- a/src/util/getClassInfo.ts
+++ b/src/util/getClassInfo.ts +++ b/src/util/getClassInfo.ts
@@ -164,0 +165 @@ export default function getClassInfo( @@ -195,0 +196 @@ export default function getClassInfo(
+export { getClassInfo as HACK }; +export { getClassInfo as HACK };
--- a/src/util/getDeclarationInfo.ts --- a/src/util/getDeclarationInfo.ts
+++ b/src/util/getDeclarationInfo.ts +++ b/src/util/getDeclarationInfo.ts
@@ -40,0 +41 @@ export default function getDeclarationInfo(tokens: TokenProcessor): DeclarationI @@ -40,0 +41 @@ export default function getDeclarationInfo(tokens: TokenProcessor): DeclarationI
+export { getDeclarationInfo as HACK }; +export { getDeclarationInfo as HACK };
--- a/src/util/getImportExportSpecifierInfo.ts
+++ b/src/util/getImportExportSpecifierInfo.ts
@@ -87,0 +88 @@ export default function getImportExportSpecifierInfo(
+export { getImportExportSpecifierInfo as HACK };
--- a/src/util/getJSXPragmaInfo.ts --- a/src/util/getJSXPragmaInfo.ts
+++ b/src/util/getJSXPragmaInfo.ts +++ b/src/util/getJSXPragmaInfo.ts
@@ -14,0 +15 @@ export default function getJSXPragmaInfo(options: Options): JSXPragmaInfo { @@ -14,0 +15 @@ export default function getJSXPragmaInfo(options: Options): JSXPragmaInfo {
+export { getJSXPragmaInfo as HACK }; +export { getJSXPragmaInfo as HACK };
--- a/test/source-maps-test.ts
+++ b/test/source-maps-test.ts
@@ -26,0 +27 @@ var _a = require('./a'); var _a2 = _interopRequireDefault(_a);
+delete result.sourceMap.ignoreList;
EOF EOF
ERR=$?; if [ "$ERR" != "0" ]; then echo "Error: $ERR"; exit $ERR; fi ERR=$?; if [ "$ERR" != "0" ]; then echo "Error: $ERR"; exit $ERR; fi
npm_install esbuild-wasm@0.8.56 \ npm_install esbuild-wasm@0.8.56 \
&& minify_in_situ "src" \ && minify_in_situ "src" \
&& workaround src/parser/plugins/typescript.ts\
&& workaround src/transformers/CJSImportTransformer.ts\
&& rm -rf node_modules \ && rm -rf node_modules \
&& npm_install \ && npm_install \
&& npm run clean \ && npm run clean \

View File

@@ -25,7 +25,7 @@ exports.run_code = semver.satisfies(process.version, "0.8") ? function(code, top
} while (prev !== stdout); } while (prev !== stdout);
return stdout; return stdout;
} : semver.satisfies(process.version, "<0.12") ? run_code_vm : function(code, toplevel, timeout) { } : semver.satisfies(process.version, "<0.12") ? run_code_vm : function(code, toplevel, timeout) {
if ([ var stdout = ([
/\b(async[ \t]+function|Promise|setImmediate|setInterval|setTimeout)\b/, /\b(async[ \t]+function|Promise|setImmediate|setInterval|setTimeout)\b/,
/\basync([ \t]+|[ \t]*#)[^\s()[\]{}#:;,.&|!~=*%/+-]+(\s*\(|[ \t]*=>)/, /\basync([ \t]+|[ \t]*#)[^\s()[\]{}#:;,.&|!~=*%/+-]+(\s*\(|[ \t]*=>)/,
/\basync[ \t]*\*[ \t]*[^\s()[\]{}#:;,.&|!~=*%/+-]+\s*\(/, /\basync[ \t]*\*[ \t]*[^\s()[\]{}#:;,.&|!~=*%/+-]+\s*\(/,
@@ -33,11 +33,9 @@ exports.run_code = semver.satisfies(process.version, "0.8") ? function(code, top
/\basync[ \t]*\([\s\S]*?\)[ \t]*=>/, /\basync[ \t]*\([\s\S]*?\)[ \t]*=>/,
].some(function(pattern) { ].some(function(pattern) {
return pattern.test(code); return pattern.test(code);
})) { }) ? run_code_exec : run_code_vm)(code, toplevel, timeout);
return run_code_exec(code, toplevel, timeout); var len = typeof stdout == "string" && stdout.length;
} else { return len > 1000 ? stdout.slice(0, 1000) + "…《" + len + "》" : stdout;
return run_code_vm(code, toplevel, timeout);
}
}; };
exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) { exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
if (typeof expected != typeof actual) return false; if (typeof expected != typeof actual) return false;
@@ -51,13 +49,22 @@ exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expec
} : function(expected, actual) { } : function(expected, actual) {
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual); return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);
}; };
exports.patch_module_statements = function(code) { exports.patch_module_statements = function(code, module) {
if (module || module === undefined && /\bawait\b/.test(code)) {
code = [
"(async()=>{",
code,
'})().catch(e=>process.on("exit",()=>{throw e}));',
];
if (module) code.unshift('"use strict";');
code = code.join("\n");
}
var count = 0, has_default = "", imports = [], strict_mode = ""; var count = 0, has_default = "", imports = [], strict_mode = "";
code = code.replace(/^\s*("|')use strict\1\s*;?/, function(match) { code = code.replace(/^\s*("|')use strict\1\s*;?/, function(match) {
strict_mode = match; strict_mode = match;
return ""; return "";
}).replace(/\bexport(?:\s*\{[^{}]*}\s*?(?:$|\n|;)|\s+default\b(?:\s*(\(|\{|class\s*\{|class\s+(?=extends\b)|(?:async\s+)?function\s*(?:\*\s*)?\())?|\b)/g, function(match, header) { }).replace(/\bexport(?:\s*\{[^{}]*}\s*?(?:$|\n|;)|\s+default\b(?:\s*(\(|\{|class\s*\{|class\s+(?=extends\b)|(?:async\s+)?function\s*(?:\*\s*)?\())?|\b)/g, function(match, header) {
if (/^export\s+default/.test(match)) has_default = "var _uglify_export_default_;"; if (/^export\s+default/.test(match)) has_default = "function _uglify_export_default_() {}";
if (!header) return ""; if (!header) return "";
if (header.length == 1) return "0, " + header; if (header.length == 1) return "0, " + header;
var name = "_uglify_export_default_"; var name = "_uglify_export_default_";
@@ -286,6 +293,7 @@ function run_code_exec(code, toplevel, timeout) {
var result = spawnSync(process.argv[0], [ '--max-old-space-size=2048' ], { var result = spawnSync(process.argv[0], [ '--max-old-space-size=2048' ], {
encoding: "utf8", encoding: "utf8",
input: code, input: code,
maxBuffer: 1073741824,
stdio: "pipe", stdio: "pipe",
timeout: timeout || 5000, timeout: timeout || 5000,
}); });

View File

@@ -2,15 +2,18 @@ var get = require("https").get;
var parse = require("url").parse; var parse = require("url").parse;
var base, token, run_number; var base, token, run_number;
var expires = Date.now() + (6 * 60 - 10) * 60 * 1000;
exports.init = function(url, auth, num) { exports.init = function(url, auth, num) {
base = url; base = url;
token = auth; token = auth;
run_number = num; run_number = num;
}; };
exports.should_stop = function(callback) { exports.should_stop = function(callback) {
if (Date.now() > expires) return callback();
read(base + "/actions/runs?per_page=100", function(reply) { read(base + "/actions/runs?per_page=100", function(reply) {
if (!reply || !Array.isArray(reply.workflow_runs)) return; var runs = verify(reply, "workflow_runs").filter(function(workflow) {
var runs = reply.workflow_runs.sort(function(a, b) { return workflow.status != "completed";
}).sort(function(a, b) {
return b.run_number - a.run_number; return b.run_number - a.run_number;
}); });
var found = false, remaining = 20; var found = false, remaining = 20;
@@ -19,15 +22,13 @@ exports.should_stop = function(callback) {
do { do {
workflow = runs.pop(); workflow = runs.pop();
if (!workflow) return; if (!workflow) return;
if (is_cron(workflow) && workflow.run_number == run_number) found = true; if (!is_cron(workflow)) break;
} while (!found && workflow.status == "completed"); if (workflow.run_number == run_number) found = true;
} while (!found);
read(workflow.jobs_url, function(reply) { read(workflow.jobs_url, function(reply) {
if (!reply || !Array.isArray(reply.jobs)) return; verify(reply, "jobs").forEach(function(job) {
if (!reply.jobs.every(function(job) { if (job.status != "completed") remaining--;
if (job.status == "completed") return true; });
remaining--;
return found || !is_cron(workflow);
})) return;
if (remaining >= 0) { if (remaining >= 0) {
next(); next();
} else { } else {
@@ -70,3 +71,12 @@ function read(url, callback) {
done(); done();
}); });
} }
function verify(reply, field) {
if (!reply) return [];
var values = reply[field];
if (!Array.isArray(values)) return [];
return values.filter(function(value) {
return value;
});
}

View File

@@ -371,9 +371,16 @@ var in_class = 0;
var called = Object.create(null); var called = Object.create(null);
var labels = 10000; var labels = 10000;
function rng(max) { function rng(limit) {
var r = randomBytes(2).readUInt16LE(0) / 65536; var r = randomBytes(2).readUInt16LE(0) / 65536;
return Math.floor(max * r); return Math.floor(limit * r);
}
function get_num(max) {
if (rng(max + 1) == 0) return 0;
var i = 1;
while (i < max && rng(2)) i++;
return i;
} }
function strictMode() { function strictMode() {
@@ -425,7 +432,7 @@ function createTopLevelCode() {
if (rng(2)) { if (rng(2)) {
s.push(createStatements(3, MAX_GENERATION_RECURSION_DEPTH, CANNOT_THROW, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, 0)); s.push(createStatements(3, MAX_GENERATION_RECURSION_DEPTH, CANNOT_THROW, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, 0));
} else { } else {
s.push(createFunctions(rng(MAX_GENERATED_TOPLEVELS_PER_RUN) + 1, MAX_GENERATION_RECURSION_DEPTH, DEFUN_OK, CANNOT_THROW, 0)); s.push(createFunctions(MAX_GENERATED_TOPLEVELS_PER_RUN, MAX_GENERATION_RECURSION_DEPTH, DEFUN_OK, CANNOT_THROW, 0));
} }
}); });
// preceding `null` makes for a cleaner output (empty string still shows up etc) // preceding `null` makes for a cleaner output (empty string still shows up etc)
@@ -438,7 +445,7 @@ function createTopLevelCode() {
function createFunctions(n, recurmax, allowDefun, canThrow, stmtDepth) { function createFunctions(n, recurmax, allowDefun, canThrow, stmtDepth) {
if (--recurmax < 0) { return ";"; } if (--recurmax < 0) { return ";"; }
var s = ""; var s = "";
while (n-- > 0) { for (var i = get_num(n - 1) + 1; --i >= 0;) {
s += createFunction(recurmax, allowDefun, canThrow, stmtDepth) + "\n"; s += createFunction(recurmax, allowDefun, canThrow, stmtDepth) + "\n";
} }
return s; return s;
@@ -455,7 +462,7 @@ function createParams(was_async, was_generator, noDuplicate) {
if (!generator) generator = was_generator; if (!generator) generator = was_generator;
var len = unique_vars.length; var len = unique_vars.length;
var params = []; var params = [];
for (var n = rng(4); --n >= 0;) { for (var i = get_num(3); --i >= 0;) {
var name = createVarName(MANDATORY); var name = createVarName(MANDATORY);
if (noDuplicate || in_class) unique_vars.push(name); if (noDuplicate || in_class) unique_vars.push(name);
params.push(name); params.push(name);
@@ -470,7 +477,7 @@ function createArgs(recurmax, stmtDepth, canThrow, noTemplate) {
recurmax--; recurmax--;
if (SUPPORT.template && !noTemplate && rng(20) == 0) return createTemplateLiteral(recurmax, stmtDepth, canThrow); if (SUPPORT.template && !noTemplate && rng(20) == 0) return createTemplateLiteral(recurmax, stmtDepth, canThrow);
var args = []; var args = [];
for (var n = rng(4); --n >= 0;) switch (SUPPORT.spread ? rng(50) : 3) { for (var i = get_num(3); --i >= 0;) switch (SUPPORT.spread ? rng(50) : 3) {
case 0: case 0:
case 1: case 1:
var name = getVarName(); var name = getVarName();
@@ -850,7 +857,7 @@ function createFunction(recurmax, allowDefun, canThrow, stmtDepth) {
s.push(defns()); s.push(defns());
if (rng(5) === 0) { if (rng(5) === 0) {
// functions with functions. lower the recursion to prevent a mess. // functions with functions. lower the recursion to prevent a mess.
s.push(createFunctions(rng(5) + 1, Math.ceil(recurmax * 0.7), DEFUN_OK, canThrow, stmtDepth)); s.push(createFunctions(5, Math.ceil(recurmax * 0.7), DEFUN_OK, canThrow, stmtDepth));
} else { } else {
// functions with statements // functions with statements
s.push(_createStatements(3, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth)); s.push(_createStatements(3, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth));
@@ -880,9 +887,9 @@ function createFunction(recurmax, allowDefun, canThrow, stmtDepth) {
} }
function _createStatements(n, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) { function _createStatements(n, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {
if (--recurmax < 0) { return ";"; } if (--recurmax < 0) return ";";
var s = ""; var s = "";
while (--n > 0) { for (var i = get_num(n); --i >= 0;) {
s += createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + "\n"; s += createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + "\n";
} }
return s; return s;
@@ -963,7 +970,7 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
switch (target) { switch (target) {
case STMT_BLOCK: case STMT_BLOCK:
var label = createLabel(canBreak); var label = createLabel(canBreak);
return label.target + "{" + createStatements(rng(5) + 1, recurmax, canThrow, label.break, canContinue, cannotReturn, stmtDepth) + "}"; return label.target + "{" + createStatements(5, recurmax, canThrow, label.break, canContinue, cannotReturn, stmtDepth) + "}";
case STMT_IF_ELSE: case STMT_IF_ELSE:
return "if (" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ")" + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + (rng(2) ? " else " + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) : ""); return "if (" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ")" + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + (rng(2) ? " else " + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) : "");
case STMT_DO_WHILE: case STMT_DO_WHILE:
@@ -1076,7 +1083,7 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
s += " * as " + createImportAlias(); s += " * as " + createImportAlias();
} else { } else {
var names = []; var names = [];
for (var i = rng(4); --i >= 0;) { for (var i = get_num(3); --i >= 0;) {
var name = createImportAlias(); var name = createImportAlias();
names.push(rng(2) ? getDotKey() + " as " + name : name); names.push(rng(2) ? getDotKey() + " as " + name : name);
} }
@@ -1135,7 +1142,7 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
} }
case STMT_FUNC_EXPR: case STMT_FUNC_EXPR:
// "In non-strict mode code, functions can only be declared at top level, inside a block, or ..." // "In non-strict mode code, functions can only be declared at top level, inside a block, or ..."
// (dont both with func decls in `if`; it's only a parser thing because you cant call them without a block) // (don't make func decls in `if`; it's only a parser thing because you can't call them without a block)
return "{" + createFunction(recurmax, NO_DEFUN, canThrow, stmtDepth) + "}"; return "{" + createFunction(recurmax, NO_DEFUN, canThrow, stmtDepth) + "}";
case STMT_TRY: case STMT_TRY:
// catch var could cause some problems // catch var could cause some problems
@@ -1184,7 +1191,7 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
} }
if (n !== 0) s += [ if (n !== 0) s += [
" finally { ", " finally { ",
createStatements(rng(5) + 1, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth), createStatements(5, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),
" }", " }",
].join(""); ].join("");
return s; return s;
@@ -1204,7 +1211,7 @@ function createSwitchParts(recurmax, n, canThrow, canBreak, canContinue, cannotR
if (hadDefault || rng(5) > 0) { if (hadDefault || rng(5) > 0) {
s.push( s.push(
"case " + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ":", "case " + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ":",
_createStatements(rng(3) + 1, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth), _createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),
rng(10) > 0 ? " break;" : "/* fall-through */", rng(10) > 0 ? " break;" : "/* fall-through */",
"" ""
); );
@@ -1212,7 +1219,7 @@ function createSwitchParts(recurmax, n, canThrow, canBreak, canContinue, cannotR
hadDefault = true; hadDefault = true;
s.push( s.push(
"default:", "default:",
_createStatements(rng(3) + 1, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth), _createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),
"" ""
); );
} }
@@ -1343,7 +1350,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
"(" + params + "{", "(" + params + "{",
strictMode(), strictMode(),
defns(), defns(),
_createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth) _createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth)
); );
suffix = "})"; suffix = "})";
} else { } else {
@@ -1375,7 +1382,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
s.push( s.push(
"(" + makeFunction(name) + "(){", "(" + makeFunction(name) + "(){",
strictMode(), strictMode(),
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth), createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
rng(2) ? "})" : "})()" + invokeGenerator(save_generator) rng(2) ? "})" : "})()" + invokeGenerator(save_generator)
); );
} }
@@ -1384,7 +1391,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
s.push( s.push(
"+" + makeFunction(name) + "(){", "+" + makeFunction(name) + "(){",
strictMode(), strictMode(),
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth), createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
"}()" + invokeGenerator(save_generator) "}()" + invokeGenerator(save_generator)
); );
break; break;
@@ -1392,7 +1399,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
s.push( s.push(
"!" + makeFunction(name) + "(){", "!" + makeFunction(name) + "(){",
strictMode(), strictMode(),
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth), createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
"}()" + invokeGenerator(save_generator) "}()" + invokeGenerator(save_generator)
); );
break; break;
@@ -1400,7 +1407,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
s.push( s.push(
"void " + makeFunction(name) + "(){", "void " + makeFunction(name) + "(){",
strictMode(), strictMode(),
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth), createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
"}()" + invokeGenerator(save_generator) "}()" + invokeGenerator(save_generator)
); );
break; break;
@@ -1416,10 +1423,10 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
var add_new_target = SUPPORT.new_target && VALUES.indexOf("new.target") < 0; var add_new_target = SUPPORT.new_target && VALUES.indexOf("new.target") < 0;
if (add_new_target) VALUES.push("new.target"); if (add_new_target) VALUES.push("new.target");
s.push(defns()); s.push(defns());
if (instantiate) for (var i = rng(4); --i >= 0;) { if (instantiate) for (var i = get_num(3); --i >= 0;) {
s.push((in_class ? "if (this) " : "") + createThisAssignment(recurmax, stmtDepth, canThrow)); s.push((in_class ? "if (this) " : "") + createThisAssignment(recurmax, stmtDepth, canThrow));
} }
s.push(_createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth)); s.push(_createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth));
if (add_new_target) VALUES.splice(VALUES.indexOf("new.target"), 1); if (add_new_target) VALUES.splice(VALUES.indexOf("new.target"), 1);
}); });
generator = save_generator; generator = save_generator;
@@ -1565,7 +1572,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
function createArrayLiteral(recurmax, stmtDepth, canThrow) { function createArrayLiteral(recurmax, stmtDepth, canThrow) {
recurmax--; recurmax--;
var arr = []; var arr = [];
for (var i = rng(6); --i >= 0;) switch (SUPPORT.spread ? rng(50) : 3 + rng(47)) { for (var i = get_num(5); --i >= 0;) switch (SUPPORT.spread ? rng(50) : 3 + rng(47)) {
case 0: case 0:
case 1: case 1:
var name = getVarName(); var name = getVarName();
@@ -1594,7 +1601,7 @@ function createTemplateLiteral(recurmax, stmtDepth, canThrow) {
recurmax--; recurmax--;
var s = []; var s = [];
addText(); addText();
for (var i = rng(6); --i >= 0;) { for (var i = get_num(5); --i >= 0;) {
s.push("${", createExpression(recurmax, COMMA_OK, stmtDepth, canThrow), "}"); s.push("${", createExpression(recurmax, COMMA_OK, stmtDepth, canThrow), "}");
addText(); addText();
} }
@@ -1749,7 +1756,7 @@ function createObjectFunction(recurmax, stmtDepth, canThrow, internal, isClazz)
s.push(_createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, stmtDepth)); s.push(_createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, stmtDepth));
if (internal == "super") s.push("super" + createArgs(recurmax, stmtDepth, canThrow, NO_TEMPLATE) + ";"); if (internal == "super") s.push("super" + createArgs(recurmax, stmtDepth, canThrow, NO_TEMPLATE) + ";");
allow_this = save_allow; allow_this = save_allow;
if (/^(constructor|super)$/.test(internal) || rng(10) == 0) for (var i = rng(4); --i >= 0;) { if (/^(constructor|super)$/.test(internal) || rng(10) == 0) for (var i = get_num(3); --i >= 0;) {
s.push(rng(2) ? createSuperAssignment(recurmax, stmtDepth, canThrow) : createThisAssignment(recurmax, stmtDepth, canThrow)); s.push(rng(2) ? createSuperAssignment(recurmax, stmtDepth, canThrow) : createThisAssignment(recurmax, stmtDepth, canThrow));
} }
s.push(_createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth), "}"); s.push(_createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth), "}");
@@ -1768,7 +1775,7 @@ function createObjectLiteral(recurmax, stmtDepth, canThrow) {
var obj = [ "({" ]; var obj = [ "({" ];
var offset = SUPPORT.spread_object ? 0 : SUPPORT.computed_key ? 2 : 4; var offset = SUPPORT.spread_object ? 0 : SUPPORT.computed_key ? 2 : 4;
var has_proto = false; var has_proto = false;
for (var i = rng(6); --i >= 0;) switch (offset + rng(50 - offset)) { for (var i = get_num(5); --i >= 0;) switch (offset + rng(50 - offset)) {
case 0: case 0:
obj.push("..." + getVarName() + ","); obj.push("..." + getVarName() + ",");
break; break;
@@ -1815,7 +1822,7 @@ function createClassLiteral(recurmax, stmtDepth, canThrow, name) {
} }
s += " {\n"; s += " {\n";
var declared = []; var declared = [];
for (var i = rng(6); --i >= 0;) { for (var i = get_num(5); --i >= 0;) {
var fixed = false; var fixed = false;
if (rng(5) == 0) { if (rng(5) == 0) {
fixed = true; fixed = true;
@@ -1849,7 +1856,7 @@ function createClassLiteral(recurmax, stmtDepth, canThrow, name) {
generator = false; generator = false;
s += [ s += [
"{ ", "{ ",
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, stmtDepth), createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, stmtDepth),
" }\n", " }\n",
].join(""); ].join("");
generator = save_generator; generator = save_generator;
@@ -2106,13 +2113,7 @@ if (require.main !== module) {
} }
function run_code(code, toplevel, timeout) { function run_code(code, toplevel, timeout) {
if (async && has_await) code = [ return sandbox.run_code(sandbox.patch_module_statements(code, async && has_await), toplevel, timeout);
'"use strict";',
"(async()=>{",
code,
'})().catch(e=>process.on("exit",()=>{throw e}));',
].join("\n");
return sandbox.run_code(sandbox.patch_module_statements(code), toplevel, timeout);
} }
function writeln(stream, msg) { function writeln(stream, msg) {
@@ -2132,7 +2133,7 @@ function errorln(msg) {
function try_beautify(code, toplevel, result, printfn, options) { function try_beautify(code, toplevel, result, printfn, options) {
var o = JSON.parse(beautify_options); var o = JSON.parse(beautify_options);
if (async && has_await) o.module = true; o.module = !!(async && has_await);
var beautified = UglifyJS.minify(code, o); var beautified = UglifyJS.minify(code, o);
if (beautified.error) { if (beautified.error) {
printfn("// !!! beautify failed !!!"); printfn("// !!! beautify failed !!!");
@@ -2261,6 +2262,7 @@ function log(options) {
var reduce_options = JSON.parse(options); var reduce_options = JSON.parse(options);
reduce_options.validate = true; reduce_options.validate = true;
var reduced = reduce_test(original_code, reduce_options, { var reduced = reduce_test(original_code, reduce_options, {
max_timeout: max_timeout,
verbose: false, verbose: false,
}).code; }).code;
if (reduced) { if (reduced) {
@@ -2522,6 +2524,7 @@ beautify_options = JSON.stringify(beautify_options);
minify_options = minify_options.map(JSON.stringify); minify_options = minify_options.map(JSON.stringify);
var original_code, original_result, original_erred; var original_code, original_result, original_erred;
var uglify_code, uglify_result, ok; var uglify_code, uglify_result, ok;
var max_timeout = 10000;
for (var round = 1; round <= num_iterations; round++) { for (var round = 1; round <= num_iterations; round++) {
process.stdout.write(round + " of " + num_iterations + "\r"); process.stdout.write(round + " of " + num_iterations + "\r");
@@ -2539,13 +2542,19 @@ for (var round = 1; round <= num_iterations; round++) {
println("original result:"); println("original result:");
println(result); println(result);
println(); println();
if (is_error_timeout(result)) orig_result[toplevel] = result = run_code(original_code, toplevel, max_timeout);
// skip over test cases which take too long to run
if (is_error_timeout(result)) return true;
// ignore v8 parser bug // ignore v8 parser bug
return bug_async_arrow_rest(result) if (bug_async_arrow_rest(result)) return true;
// ignore Node.js `__proto__` quirks // ignore Node.js `__proto__` quirks
|| bug_proto_stream(result) if (bug_proto_stream(result)) return true;
// ignore runtime platform bugs // ignore runtime platform bugs
|| result.message == "Script execution aborted."; if (result.message == "Script execution aborted.") return true;
})) continue; })) {
num_iterations++;
continue;
}
minify_options.forEach(function(options) { minify_options.forEach(function(options) {
var o = JSON.parse(options); var o = JSON.parse(options);
if (async && has_await) { if (async && has_await) {
@@ -2568,23 +2577,11 @@ for (var round = 1; round <= num_iterations; round++) {
if (!ok && uglify_erred && bug_proto_stream(uglify_result)) ok = true; if (!ok && uglify_erred && bug_proto_stream(uglify_result)) ok = true;
// ignore runtime platform bugs // ignore runtime platform bugs
if (!ok && uglify_erred && uglify_result.message == "Script execution aborted.") ok = true; if (!ok && uglify_erred && uglify_result.message == "Script execution aborted.") ok = true;
// handle difference caused by time-outs
if (!ok) {
if (original_erred && is_error_timeout(original_result)) {
if (uglify_erred && is_error_timeout(uglify_result)) {
// ignore difference in error message
ok = true;
} else {
// ignore spurious time-outs // ignore spurious time-outs
if (!orig_result[toplevel ? 3 : 2]) orig_result[toplevel ? 3 : 2] = run_code(original_code, toplevel, 10000); if (!ok && uglify_erred && is_error_timeout(uglify_result)) {
ok = sandbox.same_stdout(orig_result[toplevel ? 3 : 2], uglify_result); var waited_result = run_code(uglify_code, toplevel, max_timeout);
}
} else if (uglify_erred && is_error_timeout(uglify_result)) {
// ignore spurious time-outs
var waited_result = run_code(uglify_code, toplevel, 10000);
ok = sandbox.same_stdout(original_result, waited_result); ok = sandbox.same_stdout(original_result, waited_result);
} }
}
// ignore declaration order of global variables // ignore declaration order of global variables
if (!ok && !toplevel) { if (!ok && !toplevel) {
if (!(original_erred && original_result.name == "SyntaxError") && !(uglify_erred && uglify_result.name == "SyntaxError")) { if (!(original_erred && original_result.name == "SyntaxError") && !(uglify_erred && uglify_result.name == "SyntaxError")) {

View File

@@ -2,6 +2,7 @@
{ {
"compress": false, "compress": false,
"mangle": false, "mangle": false,
"module": false,
"output": { "output": {
"beautify": true, "beautify": true,
"braces": true "braces": true
@@ -9,14 +10,19 @@
"rename": true "rename": true
}, },
{ {
"compress": false "compress": false,
"module": false
}, },
{ {
"mangle": false "mangle": false,
"module": false
},
{
"module": false
}, },
{},
{ {
"ie": true, "ie": true,
"module": false,
"toplevel": true "toplevel": true
}, },
{ {
@@ -28,6 +34,7 @@
}, },
"keep_fargs": true, "keep_fargs": true,
"keep_fnames": true, "keep_fnames": true,
"module": false,
"toplevel": true "toplevel": true
}, },
{ {
@@ -39,6 +46,7 @@
"unsafe_math": true, "unsafe_math": true,
"unsafe_proto": true, "unsafe_proto": true,
"unsafe_regexp": true "unsafe_regexp": true
} },
"module": false
} }
] ]

View File

@@ -4323,6 +4323,7 @@
"enable", "enable",
"enableBackground", "enableBackground",
"enableDelegations", "enableDelegations",
"enableHighAccuracy",
"enableStyleSheetsForSet", "enableStyleSheetsForSet",
"enableVertexAttribArray", "enableVertexAttribArray",
"enabled", "enabled",
@@ -5553,6 +5554,7 @@
"maxWidth", "maxWidth",
"maxZoom", "maxZoom",
"maximize", "maximize",
"maximumAge",
"maximumFractionDigits", "maximumFractionDigits",
"measure", "measure",
"measureText", "measureText",

View File

@@ -15,13 +15,13 @@ exports.FILES = [
require.resolve("./exports.js"), require.resolve("./exports.js"),
]; ];
new Function("exports", function() { new Function("domprops", "exports", function() {
var code = exports.FILES.map(function(file) { var code = exports.FILES.map(function(file) {
return fs.readFileSync(file, "utf8"); return fs.readFileSync(file, "utf8");
}); });
code.push("exports.describe_ast = " + describe_ast.toString()); code.push("exports.describe_ast = " + describe_ast.toString());
return code.join("\n\n"); return code.join("\n\n");
}())(exports); }())(require("./domprops.json"), exports);
function to_comment(value) { function to_comment(value) {
if (typeof value != "string") value = JSON.stringify(value, function(key, value) { if (typeof value != "string") value = JSON.stringify(value, function(key, value) {
@@ -100,7 +100,7 @@ function infer_options(options) {
exports.default_options = function() { exports.default_options = function() {
var defs = infer_options({ 0: 0 }); var defs = infer_options({ 0: 0 });
Object.keys(defs).forEach(function(component) { Object.keys(defs).forEach(function(component) {
var options = {}; var options = { module: false };
options[component] = { 0: 0 }; options[component] = { 0: 0 };
if (options = infer_options(options)) { if (options = infer_options(options)) {
defs[component] = options; defs[component] = options;

View File

@@ -6,7 +6,7 @@ try {
} catch (e) { } catch (e) {
// ensure output buffers are flushed before process termination // ensure output buffers are flushed before process termination
var exit = process.exit; var exit = process.exit;
process.exit = function() { if ("bufferSize" in process.stdout) process.exit = function() {
var args = [].slice.call(arguments); var args = [].slice.call(arguments);
process.once("uncaughtException", function() { process.once("uncaughtException", function() {
(function callback() { (function callback() {