Compare commits
354 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92d1391e5e | ||
|
|
b4ff6d0f2d | ||
|
|
9882a9f4af | ||
|
|
40f36b9e01 | ||
|
|
6e105c5ca6 | ||
|
|
af35cd32f2 | ||
|
|
7de8daa4b1 | ||
|
|
305a4bdcee | ||
|
|
3472cf1a90 | ||
|
|
6d4c0fa6fa | ||
|
|
3cca0d6249 | ||
|
|
12ac49b970 | ||
|
|
8c670cae93 | ||
|
|
0e3da27727 | ||
|
|
13cdc167a2 | ||
|
|
51803cdcb2 | ||
|
|
8fa470c17c | ||
|
|
90410f9fc3 | ||
|
|
ef3831437d | ||
|
|
171c544705 | ||
|
|
3c609e2f4a | ||
|
|
f0ae03ed39 | ||
|
|
31c6b45036 | ||
|
|
3ac533e644 | ||
|
|
38a46c86d7 | ||
|
|
0f0759ec15 | ||
|
|
7f501f9fed | ||
|
|
72844eb5a4 | ||
|
|
09d93cc6c8 | ||
|
|
dd1374aa8a | ||
|
|
fdf2e8c5b0 | ||
|
|
a9d934ab4e | ||
|
|
2a053710bd | ||
|
|
219aac6a84 | ||
|
|
2039185051 | ||
|
|
ad27c14202 | ||
|
|
a62b086184 | ||
|
|
335456cf77 | ||
|
|
d64d0b0bec | ||
|
|
3ac575f2e8 | ||
|
|
d33a3a3253 | ||
|
|
d7456a2dc2 | ||
|
|
d97672613d | ||
|
|
30761eede5 | ||
|
|
fb30aeccaf | ||
|
|
226aa1f76b | ||
|
|
6e235602fb | ||
|
|
980fcbb56b | ||
|
|
375ebe316d | ||
|
|
2500930234 | ||
|
|
2f0da2ff05 | ||
|
|
83a3cbf151 | ||
|
|
da8d154571 | ||
|
|
e33c727e8b | ||
|
|
f886b3fb2b | ||
|
|
b1cc15e85b | ||
|
|
3aa765e429 | ||
|
|
93d084a1d1 | ||
|
|
c7a3e09407 | ||
|
|
09525c7530 | ||
|
|
a7e15fe73c | ||
|
|
a31c27c7cf | ||
|
|
1caf7c7bd2 | ||
|
|
0eb0c9b388 | ||
|
|
7dc61cdc89 | ||
|
|
af1b2f30c9 | ||
|
|
37b4fc7e31 | ||
|
|
da85d102e3 | ||
|
|
35fe1092d3 | ||
|
|
f2d486e771 | ||
|
|
fee677786e | ||
|
|
aa83ecdb3b | ||
|
|
a153176469 | ||
|
|
1c6384b6a5 | ||
|
|
e8db526f51 | ||
|
|
fa13ed4391 | ||
|
|
23f0dca992 | ||
|
|
45ab3b51d8 | ||
|
|
49670d216b | ||
|
|
e2237d8cd2 | ||
|
|
91f078fe35 | ||
|
|
a546cb881d | ||
|
|
84d5dffd9f | ||
|
|
a8e286f7e1 | ||
|
|
9b05494ebc | ||
|
|
30ef20a208 | ||
|
|
a4002ef467 | ||
|
|
9d758a216b | ||
|
|
af13f8dd2c | ||
|
|
88423f2574 | ||
|
|
ee632a5519 | ||
|
|
dfe47bcc42 | ||
|
|
6d3dcaa59e | ||
|
|
1bc0df1569 | ||
|
|
a98ba994bd | ||
|
|
cd671221c5 | ||
|
|
bce3919748 | ||
|
|
61b66e83f1 | ||
|
|
a5db8cd14c | ||
|
|
2021c2fa3e | ||
|
|
484d3fd8c7 | ||
|
|
3bf8699f95 | ||
|
|
58c24f8007 | ||
|
|
e61bc34eb1 | ||
|
|
8b2cfd45fa | ||
|
|
ae9f56be10 | ||
|
|
9aed0e3a73 | ||
|
|
88850a6e05 | ||
|
|
9e881407bd | ||
|
|
3188db7b90 | ||
|
|
a82ca62b66 | ||
|
|
e9465717ab | ||
|
|
e89031f1af | ||
|
|
596fad182e | ||
|
|
ed69adedcd | ||
|
|
1dbf7d4a3a | ||
|
|
2a9d0fc6fb | ||
|
|
45db96679e | ||
|
|
1d15f51238 | ||
|
|
ed7c82fa5e | ||
|
|
3b273cecac | ||
|
|
d764b6cc3b | ||
|
|
08c4729eb4 | ||
|
|
5561d3e7f3 | ||
|
|
491d6ce1d5 | ||
|
|
cd55eeb77c | ||
|
|
3230952d57 | ||
|
|
df3bb8028a | ||
|
|
28b7b15da1 | ||
|
|
aa37b19698 | ||
|
|
02e889e449 | ||
|
|
486ce00b8e | ||
|
|
eb481cee8c | ||
|
|
fbc9d8009b | ||
|
|
04fd3d90f8 | ||
|
|
a489f8cb5e | ||
|
|
e2e4b7fb37 | ||
|
|
c97ad98f92 | ||
|
|
b24eb22c6b | ||
|
|
06ba4e2ce8 | ||
|
|
0eb4577a82 | ||
|
|
43498769f0 | ||
|
|
60c0bc1e6b | ||
|
|
6a5c63e1e3 | ||
|
|
d47ea77811 | ||
|
|
7840746bd9 | ||
|
|
49ea629f3f | ||
|
|
13c72a986c | ||
|
|
08af3eae44 | ||
|
|
27bdcbbd83 | ||
|
|
2c4d7d66ef | ||
|
|
d1cc5270a3 | ||
|
|
75c5b6029b | ||
|
|
fa14a9cfcd | ||
|
|
aeb9ea5ac2 | ||
|
|
798841be82 | ||
|
|
cc6eb4b15f | ||
|
|
14eee81dc6 | ||
|
|
55ebb27878 | ||
|
|
87046410ef | ||
|
|
f9b3198714 | ||
|
|
48b62393a4 | ||
|
|
a00f8dade7 | ||
|
|
9daa2fb6f5 | ||
|
|
8d81d264f4 | ||
|
|
5ef7060098 | ||
|
|
938368ba21 | ||
|
|
fe2f1965d6 | ||
|
|
30ed8f5580 | ||
|
|
dc9e7cd1fe | ||
|
|
76f40e2528 | ||
|
|
8024f7f7a8 | ||
|
|
eb7fa25270 | ||
|
|
ee7647dc67 | ||
|
|
bd2f53bc8b | ||
|
|
e8a7956b6f | ||
|
|
2b24dc25fb | ||
|
|
35cc5aa06f | ||
|
|
c1dd49e075 | ||
|
|
c76ee4b868 | ||
|
|
e23bf48052 | ||
|
|
7e0ad232b0 | ||
|
|
63adfb1590 | ||
|
|
f9806b43c3 | ||
|
|
c4c9c6d37d | ||
|
|
33f3b0c1d9 | ||
|
|
abb8ae02a5 | ||
|
|
97728c4f0b | ||
|
|
f74b7f7401 | ||
|
|
b06fd8a933 | ||
|
|
1bb0804d60 | ||
|
|
998245ffd6 | ||
|
|
7a033bb825 | ||
|
|
a441b00951 | ||
|
|
88985a46ed | ||
|
|
34ead0430b | ||
|
|
66ab2df97f | ||
|
|
b656f7c083 | ||
|
|
873db281e8 | ||
|
|
6bf1486935 | ||
|
|
ffa1943177 | ||
|
|
ac429dc8e1 | ||
|
|
3766d5c962 | ||
|
|
20f9a1d908 | ||
|
|
dcb74f558e | ||
|
|
0794aaa2c2 | ||
|
|
74801de315 | ||
|
|
f80d5b8c9e | ||
|
|
d900006973 | ||
|
|
39f849590b | ||
|
|
818738beec | ||
|
|
bc2a4a3bb8 | ||
|
|
a4a8ccea8c | ||
|
|
36dcfa3e82 | ||
|
|
94f33570e3 | ||
|
|
44d6912a55 | ||
|
|
3a4497a1c3 | ||
|
|
3ee13cae02 | ||
|
|
99cf3a38c5 | ||
|
|
3ae24329eb | ||
|
|
01b13d797c | ||
|
|
306e8e9873 | ||
|
|
9577c8c1b7 | ||
|
|
925a0ca1a0 | ||
|
|
b694bfa351 | ||
|
|
a2fc32c64b | ||
|
|
88504ab869 | ||
|
|
e38754e802 | ||
|
|
eb6f32bfc3 | ||
|
|
f110601fb4 | ||
|
|
2a508c6e5f | ||
|
|
fd6144d95b | ||
|
|
60d4e7b09f | ||
|
|
b38838c6bf | ||
|
|
708973e51d | ||
|
|
dac9e69f9e | ||
|
|
39aa33749b | ||
|
|
da68ec6e19 | ||
|
|
15a3ebd467 | ||
|
|
9110fac9a2 | ||
|
|
83f42ede36 | ||
|
|
0ce71bbec0 | ||
|
|
46d142cbf6 | ||
|
|
38c3bcf9a0 | ||
|
|
6e9afdc94f | ||
|
|
c4d28e3b2a | ||
|
|
77261e1ee0 | ||
|
|
903a5df9a5 | ||
|
|
c810ecd081 | ||
|
|
dce9dfce0e | ||
|
|
3d72663689 | ||
|
|
a2b16e89a4 | ||
|
|
b35f4c5a83 | ||
|
|
41eb4f1725 | ||
|
|
94bc221669 | ||
|
|
822d298a55 | ||
|
|
273c6020ba | ||
|
|
1b07f64057 | ||
|
|
80d9c44b22 | ||
|
|
dc0cd088cf | ||
|
|
c69c026728 | ||
|
|
b5f4e1187f | ||
|
|
827bcec186 | ||
|
|
d105ab9722 | ||
|
|
b39228892d | ||
|
|
ff72eaa3c3 | ||
|
|
0a1c9b34ce | ||
|
|
03e968be62 | ||
|
|
421bb7083a | ||
|
|
bdc8ef2218 | ||
|
|
bca52fcba2 | ||
|
|
d6d31cbb5a | ||
|
|
a051846d22 | ||
|
|
3485472866 | ||
|
|
c8d60d6983 | ||
|
|
6092bf23de | ||
|
|
7052ce5aef | ||
|
|
d13b71297e | ||
|
|
457f958af3 | ||
|
|
53517db3e4 | ||
|
|
c13caf4876 | ||
|
|
fbfa6178a6 | ||
|
|
5315dd95b0 | ||
|
|
31a7bf2a22 | ||
|
|
f0a29902ac | ||
|
|
0d820e4c0a | ||
|
|
f01f580d6c | ||
|
|
c01ff76288 | ||
|
|
83a42716c3 | ||
|
|
2557148bba | ||
|
|
dd22eda888 | ||
|
|
f4c77886e7 | ||
|
|
df547ffd97 | ||
|
|
70551febc8 | ||
|
|
44499a6643 | ||
|
|
470a7d4df1 | ||
|
|
551420132c | ||
|
|
b0040ba654 | ||
|
|
c93ca6ee53 | ||
|
|
df506439b1 | ||
|
|
36b2d35bf3 | ||
|
|
79c60032a5 | ||
|
|
a3754068dd | ||
|
|
2ba5f391e0 | ||
|
|
87119e44a0 | ||
|
|
b499e03f82 | ||
|
|
a478f275e4 | ||
|
|
e9e76dcf04 | ||
|
|
0dcedad2d5 | ||
|
|
36a430cd1e | ||
|
|
41a6eb892a | ||
|
|
91d87ae663 | ||
|
|
5beb7e4797 | ||
|
|
46caaa82ba | ||
|
|
5d258259a4 | ||
|
|
14c35739dd | ||
|
|
f5ceff6e4b | ||
|
|
4d6771b9b1 | ||
|
|
d17191111a | ||
|
|
0ff607cb80 | ||
|
|
1988495d71 | ||
|
|
fdc10086da | ||
|
|
746f5f6c62 | ||
|
|
d83d3d741a | ||
|
|
99ac73a635 | ||
|
|
a2e4c2fd97 | ||
|
|
94785e8e14 | ||
|
|
4dbdac9c31 | ||
|
|
78c8efd851 | ||
|
|
af310ba2d0 | ||
|
|
2f3930d1b9 | ||
|
|
d1a78920d9 | ||
|
|
d9cd3d33c8 | ||
|
|
22b47cdd63 | ||
|
|
4cf612dc9f | ||
|
|
a19d31dd33 | ||
|
|
01d6e0f223 | ||
|
|
ab050e7a94 | ||
|
|
75aa6ef848 | ||
|
|
519a00bd8a | ||
|
|
3ff0feddee | ||
|
|
74396acc86 | ||
|
|
036bca980c | ||
|
|
18c2b1841b | ||
|
|
fe19ab7c57 | ||
|
|
9074f05129 | ||
|
|
04fbb1f949 | ||
|
|
bf7e4ca1a3 | ||
|
|
d68ddc31f9 | ||
|
|
500e31e03b | ||
|
|
bef856addb | ||
|
|
9a6faf365b | ||
|
|
e915832a36 | ||
|
|
0593892d6e |
35
.github/workflows/ci.yml
vendored
35
.github/workflows/ci.yml
vendored
@@ -1,31 +1,48 @@
|
||||
name: CI
|
||||
on: [ push, pull_request ]
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [ master ]
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
node: [ "0.8", "0.10", "0.12", "4", "6", "8", "10", "12", latest ]
|
||||
os: [ ubuntu-latest, windows-latest ]
|
||||
node: [ "0.10", 0.12, 4, 6, 8, 10, latest ]
|
||||
script: [ compress, mocha, release/benchmark, release/jetstream ]
|
||||
name: ${{ matrix.os }} ${{ matrix.node }} ${{ matrix.script }}
|
||||
exclude:
|
||||
- node: "0.8"
|
||||
script: release/benchmark
|
||||
- node: "0.8"
|
||||
script: release/jetstream
|
||||
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
NODE: ${{ matrix.node }}
|
||||
TYPE: ${{ matrix.script }}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/cache@v1
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: tmp
|
||||
key: tmp ${{ matrix.script }}
|
||||
- name: Perform tests
|
||||
shell: bash
|
||||
run: |
|
||||
git clone --branch v1.5.3 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add $NODE && nvs use $NODE'; do
|
||||
cd ~/.nvs
|
||||
while !(git clean -xdf); do echo "'git clean' failed - retrying..."; done
|
||||
cd -
|
||||
done
|
||||
. ~/.nvs/nvs.sh --version
|
||||
nvs add $NODE
|
||||
nvs use $NODE
|
||||
node --version
|
||||
npm --version --no-update-notifier
|
||||
npm install --no-audit --no-optional --no-save --no-update-notifier
|
||||
npm config set audit false
|
||||
npm config set optional false
|
||||
npm config set save false
|
||||
npm config set strict-ssl false
|
||||
npm config set update-notifier false
|
||||
npm --version
|
||||
while !(npm install); do echo "'npm install' failed - retrying..."; done
|
||||
node test/$TYPE
|
||||
|
||||
35
.github/workflows/ufuzz.yml
vendored
35
.github/workflows/ufuzz.yml
vendored
@@ -1,7 +1,13 @@
|
||||
name: Fuzzing
|
||||
on:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "*/15 * * * *"
|
||||
- cron: "*/5 * * * *"
|
||||
env:
|
||||
BASE_URL: https://api.github.com/repos/${{ github.repository }}
|
||||
CAUSE: ${{ github.event_name }}
|
||||
RUN_NUM: ${{ github.run_number }}
|
||||
TOKEN: ${{ github.token }}
|
||||
jobs:
|
||||
ufuzz:
|
||||
strategy:
|
||||
@@ -11,15 +17,28 @@ jobs:
|
||||
name: ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Perform fuzzing
|
||||
shell: bash
|
||||
run: |
|
||||
git clone --branch v1.5.3 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add 8 && nvs use 8'; do
|
||||
cd ~/.nvs
|
||||
while !(git clean -xdf); do echo "'git clean' failed - retrying..."; done
|
||||
cd -
|
||||
done
|
||||
. ~/.nvs/nvs.sh --version
|
||||
nvs add 10
|
||||
nvs use 10
|
||||
nvs use 8
|
||||
node --version
|
||||
npm --version --no-update-notifier
|
||||
npm install --no-audit --no-optional --no-save --no-update-notifier
|
||||
node test/ufuzz/job 3600000
|
||||
npm config set audit false
|
||||
npm config set optional false
|
||||
npm config set save false
|
||||
npm config set strict-ssl false
|
||||
npm config set update-notifier false
|
||||
npm --version
|
||||
while !(npm install); do echo "'npm install' failed - retrying..."; done
|
||||
if [[ $CAUSE == "schedule" ]]; then
|
||||
node test/ufuzz/job $BASE_URL $TOKEN $RUN_NUM
|
||||
else
|
||||
node test/ufuzz/job 5000
|
||||
fi
|
||||
|
||||
67
README.md
67
README.md
@@ -4,8 +4,8 @@ UglifyJS 3
|
||||
UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.
|
||||
|
||||
#### Note:
|
||||
- **`uglify-js@3` has a simplified [API](#api-reference) and [CLI](#command-line-usage) that is not backwards compatible with [`uglify-js@2`](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
|
||||
- **Documentation for UglifyJS `2.x` releases can be found [here](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
|
||||
- **`uglify-js@3` has a simplified [API](#api-reference) and [CLI](#command-line-usage) that is not backwards compatible with [`uglify-js@2`](https://github.com/mishoo/UglifyJS/tree/v2.x)**.
|
||||
- **Documentation for UglifyJS `2.x` releases can be found [here](https://github.com/mishoo/UglifyJS/tree/v2.x)**.
|
||||
- `uglify-js` only supports JavaScript (ECMAScript 5).
|
||||
- To minify ECMAScript 2015 or above, transpile using tools like [Babel](https://babeljs.io/).
|
||||
|
||||
@@ -87,6 +87,7 @@ a double dash to prevent input files being used as option arguments:
|
||||
`wrap_iife` Wrap IIFEs in parenthesis. Note: you may
|
||||
want to disable `negate_iife` under
|
||||
compressor options.
|
||||
-O, --output-opts [options] Specify output options (`beautify` disabled by default).
|
||||
-o, --output <file> Output file path (default STDOUT). Specify `ast` or
|
||||
`spidermonkey` to write UglifyJS or SpiderMonkey AST
|
||||
as JSON to STDOUT respectively.
|
||||
@@ -125,6 +126,7 @@ a double dash to prevent input files being used as option arguments:
|
||||
`includeSources` Pass this flag if you want to include
|
||||
the content of source files in the
|
||||
source map as sourcesContent property.
|
||||
`names` Include symbol names in the source map.
|
||||
`root` Path to the original source to be included in
|
||||
the source map.
|
||||
`url` If specified, path to the source map to append in
|
||||
@@ -158,6 +160,9 @@ Additional options:
|
||||
|
||||
- `--source-map "root='<URL>'"` to pass the URL where the original files can be found.
|
||||
|
||||
- `--source-map "names=false"` to omit symbol names if you want to reduce size
|
||||
of the source map file.
|
||||
|
||||
- `--source-map "url='<URL>'"` to specify the URL where the source map can be found.
|
||||
Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
|
||||
`//# sourceMappingURL=` directive.
|
||||
@@ -207,17 +212,16 @@ Example:
|
||||
To enable the mangler you need to pass `--mangle` (`-m`). The following
|
||||
(comma-separated) options are supported:
|
||||
|
||||
- `toplevel` (default `false`) -- mangle names declared in the top level scope.
|
||||
- `eval` (default `false`) -- mangle names visible in scopes where `eval` or
|
||||
`with` are used.
|
||||
|
||||
- `eval` (default `false`) -- mangle names visible in scopes where `eval` or `with` are used.
|
||||
- `reserved` (default: `[]`) -- when mangling is enabled but you want to
|
||||
prevent certain names from being mangled, you can declare those names with
|
||||
`--mangle reserved` — pass a comma-separated list of names. For example:
|
||||
|
||||
When mangling is enabled but you want to prevent certain names from being
|
||||
mangled, you can declare those names with `--mangle reserved` — pass a
|
||||
comma-separated list of names. For example:
|
||||
uglifyjs ... -m reserved=['$','require','exports']
|
||||
|
||||
uglifyjs ... -m reserved=['$','require','exports']
|
||||
|
||||
to prevent the `require`, `exports` and `$` names from being changed.
|
||||
to prevent the `require`, `exports` and `$` names from being changed.
|
||||
|
||||
### CLI mangling property names (`--mangle-props`)
|
||||
|
||||
@@ -592,6 +596,9 @@ var result = UglifyJS.minify({"compiled.js": "compiled code"}, {
|
||||
|
||||
If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.url`.
|
||||
|
||||
If you wish to reduce file size of the source map, set option `sourceMap.names`
|
||||
to be `false` and all symbol names will be omitted.
|
||||
|
||||
## Parse options
|
||||
|
||||
- `bare_returns` (default `false`) -- support top level `return` statements
|
||||
@@ -649,8 +656,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
- `hoist_props` (default: `true`) -- hoist properties from constant object and
|
||||
array literals into regular variables subject to a set of constraints. For example:
|
||||
`var o={p:1, q:2}; f(o.p, o.q);` is converted to `f(1, 2);`. Note: `hoist_props`
|
||||
works best with `mangle` enabled, the `compress` option `passes` set to `2` or higher,
|
||||
and the `compress` option `toplevel` enabled.
|
||||
works best with `toplevel` and `mangle` enabled, alongside with `compress` option
|
||||
`passes` set to `2` or higher.
|
||||
|
||||
- `hoist_vars` (default: `false`) -- hoist `var` declarations (this is `false`
|
||||
by default because it seems to increase the size of the output in general)
|
||||
@@ -681,6 +688,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops
|
||||
when we can statically determine the condition.
|
||||
|
||||
- `merge_vars` (default: `true`) -- combine and reuse variables.
|
||||
|
||||
- `negate_iife` (default: `true`) -- negate "Immediately-Called Function Expressions"
|
||||
where the return value is discarded, to avoid the parens that the
|
||||
code generator would insert.
|
||||
@@ -735,6 +744,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
|
||||
example: `/*@__PURE__*/foo();`
|
||||
|
||||
- `strings` (default: `true`) -- compact string concatenations.
|
||||
|
||||
- `switches` (default: `true`) -- de-duplicate and remove unreachable `switch` branches
|
||||
|
||||
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or
|
||||
@@ -845,8 +856,14 @@ can pass additional arguments that control the code output:
|
||||
statement.
|
||||
|
||||
- `comments` (default `false`) -- pass `true` or `"all"` to preserve all
|
||||
comments, `"some"` to preserve some comments, a regular expression string
|
||||
(e.g. `/^!/`) or a function.
|
||||
comments, `"some"` to preserve multi-line comments that contain `@cc_on`,
|
||||
`@license`, or `@preserve` (case-insensitive), a regular expression string
|
||||
(e.g. `/^!/`), or a function which returns `boolean`, e.g.
|
||||
```js
|
||||
function(node, comment) {
|
||||
return comment.value.indexOf("@type " + node.TYPE) >= 0;
|
||||
}
|
||||
```
|
||||
|
||||
- `indent_level` (default `4`)
|
||||
|
||||
@@ -897,7 +914,7 @@ can pass additional arguments that control the code output:
|
||||
|
||||
- `wrap_iife` (default `false`) -- pass `true` to wrap immediately invoked
|
||||
function expressions. See
|
||||
[#640](https://github.com/mishoo/UglifyJS2/issues/640) for more details.
|
||||
[#640](https://github.com/mishoo/UglifyJS/issues/640) for more details.
|
||||
|
||||
# Miscellaneous
|
||||
|
||||
@@ -1056,8 +1073,8 @@ var result = UglifyJS.minify(ast, {
|
||||
### Working with Uglify AST
|
||||
|
||||
Transversal and transformation of the native AST can be performed through
|
||||
[`TreeWalker`](https://github.com/mishoo/UglifyJS2/blob/master/lib/ast.js) and
|
||||
[`TreeTransformer`](https://github.com/mishoo/UglifyJS2/blob/master/lib/transform.js)
|
||||
[`TreeWalker`](https://github.com/mishoo/UglifyJS/blob/master/lib/ast.js) and
|
||||
[`TreeTransformer`](https://github.com/mishoo/UglifyJS/blob/master/lib/transform.js)
|
||||
respectively.
|
||||
|
||||
### ESTree / SpiderMonkey AST
|
||||
@@ -1141,3 +1158,19 @@ To allow for better optimizations, the compiler makes various assumptions:
|
||||
- Object properties can be added, removed and modified (not prevented with
|
||||
`Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
|
||||
`Object.preventExtensions()` or `Object.seal()`).
|
||||
- When `toplevel` is enabled, UglifyJS effectively assumes input code is wrapped
|
||||
within `function(){ ... }`, thus forbids aliasing of declared global variables:
|
||||
```js
|
||||
A = "FAIL";
|
||||
var B = "FAIL";
|
||||
// can be `global`, `self`, `window` etc.
|
||||
var top = function() {
|
||||
return this;
|
||||
}();
|
||||
// "PASS"
|
||||
top.A = "PASS";
|
||||
console.log(A);
|
||||
// "FAIL" after compress and/or mangle
|
||||
top.B = "PASS";
|
||||
console.log(B);
|
||||
```
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
build: off
|
||||
matrix:
|
||||
fast_finish: true
|
||||
test_script:
|
||||
- echo No longer in use
|
||||
468
bin/uglifyjs
468
bin/uglifyjs
@@ -8,160 +8,252 @@ require("../tools/exit");
|
||||
var fs = require("fs");
|
||||
var info = require("../package.json");
|
||||
var path = require("path");
|
||||
var program = require("commander");
|
||||
var UglifyJS = require("../tools/node");
|
||||
|
||||
var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
|
||||
var files = {};
|
||||
var options = {
|
||||
compress: false,
|
||||
mangle: false
|
||||
var options = {};
|
||||
var short_forms = {
|
||||
b: "beautify",
|
||||
c: "compress",
|
||||
d: "define",
|
||||
e: "enclose",
|
||||
h: "help",
|
||||
m: "mangle",
|
||||
o: "output",
|
||||
O: "output-opts",
|
||||
p: "parse",
|
||||
v: "version",
|
||||
V: "version",
|
||||
};
|
||||
program.version(info.name + " " + info.version);
|
||||
program.parseArgv = program.parse;
|
||||
program.parse = undefined;
|
||||
if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
|
||||
else if (process.argv.indexOf("options") >= 0) program.helpInformation = function() {
|
||||
var text = [];
|
||||
var options = UglifyJS.default_options();
|
||||
for (var option in options) {
|
||||
text.push("--" + (option == "output" ? "beautify" : option == "sourceMap" ? "source-map" : option) + " options:");
|
||||
text.push(format_object(options[option]));
|
||||
text.push("");
|
||||
var args = process.argv.slice(2);
|
||||
var paths = [];
|
||||
var output, nameCache;
|
||||
var specified = {};
|
||||
while (args.length) {
|
||||
var arg = args.shift();
|
||||
if (arg[0] != "-") {
|
||||
paths.push(arg);
|
||||
} else if (arg == "--") {
|
||||
paths = paths.concat(args);
|
||||
break;
|
||||
} else if (arg[1] == "-") {
|
||||
process_option(arg.slice(2));
|
||||
} else [].forEach.call(arg.slice(1), function(letter, index, arg) {
|
||||
if (!(letter in short_forms)) fatal("invalid option -" + letter);
|
||||
process_option(short_forms[letter], index + 1 < arg.length);
|
||||
});
|
||||
}
|
||||
|
||||
function process_option(name, no_value) {
|
||||
specified[name] = true;
|
||||
switch (name) {
|
||||
case "help":
|
||||
switch (read_value()) {
|
||||
case "ast":
|
||||
print(UglifyJS.describe_ast());
|
||||
break;
|
||||
case "options":
|
||||
var text = [];
|
||||
var toplevels = [];
|
||||
var padding = "";
|
||||
var defaults = UglifyJS.default_options();
|
||||
for (var name in defaults) {
|
||||
var option = defaults[name];
|
||||
if (option && typeof option == "object") {
|
||||
text.push("--" + ({
|
||||
output: "beautify",
|
||||
sourceMap: "source-map",
|
||||
}[name] || name) + " options:");
|
||||
text.push(format_object(option));
|
||||
text.push("");
|
||||
} else {
|
||||
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
|
||||
toplevels.push([ {
|
||||
keep_fnames: "keep-fnames",
|
||||
nameCache: "name-cache",
|
||||
}[name] || name, option ]);
|
||||
}
|
||||
}
|
||||
toplevels.forEach(function(tokens) {
|
||||
text.push("--" + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
|
||||
});
|
||||
print(text.join("\n"));
|
||||
break;
|
||||
default:
|
||||
print([
|
||||
"Usage: uglifyjs [files...] [options]",
|
||||
"",
|
||||
"Options:",
|
||||
" -h, --help Print usage information.",
|
||||
" `--help options` for details on available options.",
|
||||
" -v, -V, --version Print version number.",
|
||||
" -p, --parse <options> Specify parser options.",
|
||||
" -c, --compress [options] Enable compressor/specify compressor options.",
|
||||
" -m, --mangle [options] Mangle names/specify mangler options.",
|
||||
" --mangle-props [options] Mangle properties/specify mangler options.",
|
||||
" -b, --beautify [options] Beautify output/specify output options.",
|
||||
" -O, --output-opts <options> Output options (beautify disabled).",
|
||||
" -o, --output <file> Output file (default STDOUT).",
|
||||
" --comments [filter] Preserve copyright comments in the output.",
|
||||
" --config-file <file> Read minify() options from JSON file.",
|
||||
" -d, --define <expr>[=value] Global definitions.",
|
||||
" -e, --enclose [arg[,...][:value[,...]]] Embed everything in a big function, with configurable argument(s) & value(s).",
|
||||
" --ie8 Support non-standard Internet Explorer 8.",
|
||||
" --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name.",
|
||||
" --name-cache <file> File to hold mangled name mappings.",
|
||||
" --rename Force symbol expansion.",
|
||||
" --no-rename Disable symbol expansion.",
|
||||
" --self Build UglifyJS as a library (implies --wrap UglifyJS)",
|
||||
" --source-map [options] Enable source map/specify source map options.",
|
||||
" --timings Display operations run time on STDERR.",
|
||||
" --toplevel Compress and/or mangle variables in toplevel scope.",
|
||||
" --validate Perform validation during AST manipulations.",
|
||||
" --verbose Print diagnostic messages.",
|
||||
" --warn Print warning messages.",
|
||||
" --wrap <name> Embed everything as a function with “exports” corresponding to “name” globally.",
|
||||
" --reduce-test Reduce a standalone test case (assumes cloned repository).",
|
||||
].join("\n"));
|
||||
}
|
||||
process.exit();
|
||||
case "version":
|
||||
print(info.name + " " + info.version);
|
||||
process.exit();
|
||||
case "config-file":
|
||||
var config = JSON.parse(read_file(read_value(true)));
|
||||
if (config.mangle && config.mangle.properties && config.mangle.properties.regex) {
|
||||
config.mangle.properties.regex = UglifyJS.parse(config.mangle.properties.regex, {
|
||||
expression: true,
|
||||
}).value;
|
||||
}
|
||||
for (var key in config) if (!(key in options)) options[key] = config[key];
|
||||
break;
|
||||
case "compress":
|
||||
case "mangle":
|
||||
options[name] = parse_js(read_value(), options[name]);
|
||||
break;
|
||||
case "source-map":
|
||||
options.sourceMap = parse_js(read_value(), options.sourceMap);
|
||||
break;
|
||||
case "enclose":
|
||||
options[name] = read_value();
|
||||
break;
|
||||
case "ie8":
|
||||
case "timings":
|
||||
case "toplevel":
|
||||
case "validate":
|
||||
options[name] = true;
|
||||
break;
|
||||
case "keep-fnames":
|
||||
options.keep_fnames = true;
|
||||
break;
|
||||
case "wrap":
|
||||
options[name] = read_value(true);
|
||||
break;
|
||||
case "verbose":
|
||||
options.warnings = "verbose";
|
||||
break;
|
||||
case "warn":
|
||||
if (!options.warnings) options.warnings = true;
|
||||
break;
|
||||
case "beautify":
|
||||
options.output = parse_js(read_value(), options.output);
|
||||
if (!("beautify" in options.output)) options.output.beautify = true;
|
||||
break;
|
||||
case "output-opts":
|
||||
options.output = parse_js(read_value(true), options.output);
|
||||
break;
|
||||
case "comments":
|
||||
if (typeof options.output != "object") options.output = {};
|
||||
options.output.comments = read_value();
|
||||
if (options.output.comments === true) options.output.comments = "some";
|
||||
break;
|
||||
case "define":
|
||||
if (typeof options.compress != "object") options.compress = {};
|
||||
options.compress.global_defs = parse_js(read_value(true), options.compress.global_defs, "define");
|
||||
break;
|
||||
case "mangle-props":
|
||||
if (typeof options.mangle != "object") options.mangle = {};
|
||||
options.mangle.properties = parse_js(read_value(), options.mangle.properties);
|
||||
break;
|
||||
case "name-cache":
|
||||
nameCache = read_value(true);
|
||||
options.nameCache = JSON.parse(read_file(nameCache, "{}"));
|
||||
break;
|
||||
case "output":
|
||||
output = read_value(true);
|
||||
break;
|
||||
case "parse":
|
||||
options.parse = parse_js(read_value(true), options.parse);
|
||||
break;
|
||||
case "rename":
|
||||
options.rename = true;
|
||||
break;
|
||||
case "no-rename":
|
||||
options.rename = false;
|
||||
break;
|
||||
case "reduce-test":
|
||||
case "self":
|
||||
break;
|
||||
default:
|
||||
fatal("invalid option --" + name);
|
||||
}
|
||||
return text.join("\n");
|
||||
};
|
||||
program.option("-p, --parse <options>", "Specify parser options.", parse_js());
|
||||
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js());
|
||||
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
|
||||
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
|
||||
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js());
|
||||
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
||||
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
||||
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
||||
program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("define"));
|
||||
program.option("-e, --enclose [arg[,...][:value[,...]]]", "Embed everything in a big function, with configurable argument(s) & value(s).");
|
||||
program.option("--ie8", "Support non-standard Internet Explorer 8.");
|
||||
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
|
||||
program.option("--name-cache <file>", "File to hold mangled name mappings.");
|
||||
program.option("--rename", "Force symbol expansion.");
|
||||
program.option("--no-rename", "Disable symbol expansion.");
|
||||
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
|
||||
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_js());
|
||||
program.option("--timings", "Display operations run time on STDERR.");
|
||||
program.option("--toplevel", "Compress and/or mangle variables in toplevel scope.");
|
||||
program.option("--verbose", "Print diagnostic messages.");
|
||||
program.option("--warn", "Print warning messages.");
|
||||
program.option("--wrap <name>", "Embed everything as a function with “exports” corresponding to “name” globally.");
|
||||
program.arguments("[files...]").parseArgv(process.argv);
|
||||
if (program.configFile) {
|
||||
options = JSON.parse(read_file(program.configFile));
|
||||
if (options.mangle && options.mangle.properties && options.mangle.properties.regex) {
|
||||
options.mangle.properties.regex = UglifyJS.parse(options.mangle.properties.regex, {
|
||||
expression: true
|
||||
}).getValue();
|
||||
|
||||
function read_value(required) {
|
||||
if (no_value || !args.length || args[0][0] == "-") {
|
||||
if (required) fatal("missing option argument for --" + name);
|
||||
return true;
|
||||
}
|
||||
return args.shift();
|
||||
}
|
||||
}
|
||||
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
||||
fatal("cannot write source map to STDOUT");
|
||||
}
|
||||
[
|
||||
"compress",
|
||||
"enclose",
|
||||
"ie8",
|
||||
"mangle",
|
||||
"sourceMap",
|
||||
"toplevel",
|
||||
"wrap"
|
||||
].forEach(function(name) {
|
||||
if (name in program) {
|
||||
options[name] = program[name];
|
||||
}
|
||||
if (!output && options.sourceMap && options.sourceMap.url != "inline") fatal("cannot write source map to STDOUT");
|
||||
if (specified["beautify"] && specified["output-opts"]) fatal("--beautify cannot be used with --output-opts");
|
||||
[ "compress", "mangle" ].forEach(function(name) {
|
||||
if (!(name in options)) options[name] = false;
|
||||
});
|
||||
if (program.verbose) {
|
||||
options.warnings = "verbose";
|
||||
} else if (program.warn) {
|
||||
options.warnings = true;
|
||||
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 (output == "ast") options.output = {
|
||||
ast: true,
|
||||
code: false,
|
||||
};
|
||||
if (options.parse && (options.parse.acorn || options.parse.spidermonkey)
|
||||
&& options.sourceMap && options.sourceMap.content == "inline") {
|
||||
fatal("inline source map only works with built-in parser");
|
||||
}
|
||||
if (options.warnings) {
|
||||
UglifyJS.AST_Node.log_function(print_error, options.warnings == "verbose");
|
||||
delete options.warnings;
|
||||
}
|
||||
if (program.beautify) {
|
||||
options.output = typeof program.beautify == "object" ? program.beautify : {};
|
||||
if (!("beautify" in options.output)) {
|
||||
options.output.beautify = true;
|
||||
}
|
||||
}
|
||||
if (program.comments) {
|
||||
if (typeof options.output != "object") options.output = {};
|
||||
options.output.comments = typeof program.comments == "string" ? program.comments : "some";
|
||||
}
|
||||
if (program.define) {
|
||||
if (typeof options.compress != "object") options.compress = {};
|
||||
if (typeof options.compress.global_defs != "object") options.compress.global_defs = {};
|
||||
for (var expr in program.define) {
|
||||
options.compress.global_defs[expr] = program.define[expr];
|
||||
}
|
||||
}
|
||||
if (program.keepFnames) {
|
||||
options.keep_fnames = true;
|
||||
}
|
||||
if (program.mangleProps) {
|
||||
if (program.mangleProps.domprops) {
|
||||
delete program.mangleProps.domprops;
|
||||
} else {
|
||||
if (typeof program.mangleProps != "object") program.mangleProps = {};
|
||||
if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
|
||||
require("../tools/domprops").forEach(function(name) {
|
||||
UglifyJS.push_uniq(program.mangleProps.reserved, name);
|
||||
});
|
||||
}
|
||||
if (typeof options.mangle != "object") options.mangle = {};
|
||||
options.mangle.properties = program.mangleProps;
|
||||
}
|
||||
if (program.nameCache) {
|
||||
options.nameCache = JSON.parse(read_file(program.nameCache, "{}"));
|
||||
}
|
||||
if (program.output == "ast") {
|
||||
options.output = {
|
||||
ast: true,
|
||||
code: false
|
||||
};
|
||||
}
|
||||
if (program.parse) {
|
||||
if (!program.parse.acorn && !program.parse.spidermonkey) {
|
||||
options.parse = program.parse;
|
||||
} else if (program.sourceMap && program.sourceMap.content == "inline") {
|
||||
fatal("inline source map only works with built-in parser");
|
||||
}
|
||||
}
|
||||
if (~program.rawArgs.indexOf("--rename")) {
|
||||
options.rename = true;
|
||||
} else if (!program.rename) {
|
||||
options.rename = false;
|
||||
}
|
||||
var convert_path = function(name) {
|
||||
return name;
|
||||
};
|
||||
if (typeof program.sourceMap == "object" && "base" in program.sourceMap) {
|
||||
if (typeof options.sourceMap == "object" && "base" in options.sourceMap) {
|
||||
convert_path = function() {
|
||||
var base = program.sourceMap.base;
|
||||
var base = options.sourceMap.base;
|
||||
delete options.sourceMap.base;
|
||||
return function(name) {
|
||||
return path.relative(base, name);
|
||||
};
|
||||
}();
|
||||
}
|
||||
if (program.self) {
|
||||
if (program.args.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
|
||||
if (specified["self"]) {
|
||||
if (paths.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
|
||||
if (!options.wrap) options.wrap = "UglifyJS";
|
||||
simple_glob(UglifyJS.FILES).forEach(function(name) {
|
||||
files[convert_path(name)] = read_file(name);
|
||||
});
|
||||
run();
|
||||
} else if (program.args.length) {
|
||||
simple_glob(program.args).forEach(function(name) {
|
||||
paths = UglifyJS.FILES;
|
||||
}
|
||||
if (paths.length) {
|
||||
simple_glob(paths).forEach(function(name) {
|
||||
files[convert_path(name)] = read_file(name);
|
||||
});
|
||||
run();
|
||||
@@ -182,15 +274,14 @@ function convert_ast(fn) {
|
||||
}
|
||||
|
||||
function run() {
|
||||
var content = program.sourceMap && program.sourceMap.content;
|
||||
var content = options.sourceMap && options.sourceMap.content;
|
||||
if (content && content != "inline") {
|
||||
UglifyJS.AST_Node.info("Using input source map: " + content);
|
||||
options.sourceMap.content = read_file(content, content);
|
||||
}
|
||||
if (program.timings) options.timings = true;
|
||||
try {
|
||||
if (program.parse) {
|
||||
if (program.parse.acorn) {
|
||||
if (options.parse) {
|
||||
if (options.parse.acorn) {
|
||||
files = convert_ast(function(toplevel, name) {
|
||||
return require("acorn").parse(files[name], {
|
||||
locations: true,
|
||||
@@ -198,7 +289,7 @@ function run() {
|
||||
sourceFile: name
|
||||
});
|
||||
});
|
||||
} else if (program.parse.spidermonkey) {
|
||||
} else if (options.parse.spidermonkey) {
|
||||
files = convert_ast(function(toplevel, name) {
|
||||
var obj = JSON.parse(files[name]);
|
||||
if (!toplevel) return obj;
|
||||
@@ -210,7 +301,18 @@ function run() {
|
||||
} catch (ex) {
|
||||
fatal(ex);
|
||||
}
|
||||
var result = UglifyJS.minify(files, options);
|
||||
var result;
|
||||
if (specified["reduce-test"]) {
|
||||
// load on demand - assumes cloned repository
|
||||
var reduce_test = require("../test/reduce");
|
||||
if (Object.keys(files).length != 1) fatal("can only test on a single file");
|
||||
result = reduce_test(files[Object.keys(files)[0]], options, {
|
||||
log: print_error,
|
||||
verbose: true,
|
||||
});
|
||||
} else {
|
||||
result = UglifyJS.minify(files, options);
|
||||
}
|
||||
if (result.error) {
|
||||
var ex = result.error;
|
||||
if (ex.name == "SyntaxError") {
|
||||
@@ -239,10 +341,8 @@ function run() {
|
||||
print_error(format_object(ex.defs));
|
||||
}
|
||||
fatal(ex);
|
||||
} else if (program.output == "ast") {
|
||||
if (!options.compress && !options.mangle) {
|
||||
result.ast.figure_out_scope({});
|
||||
}
|
||||
} else if (output == "ast") {
|
||||
if (!options.compress && !options.mangle) result.ast.figure_out_scope({});
|
||||
print(JSON.stringify(result.ast, function(key, value) {
|
||||
if (value) switch (key) {
|
||||
case "thedef":
|
||||
@@ -268,26 +368,22 @@ function run() {
|
||||
}
|
||||
return value;
|
||||
}, 2));
|
||||
} else if (program.output == "spidermonkey") {
|
||||
} else if (output == "spidermonkey") {
|
||||
print(JSON.stringify(UglifyJS.minify(result.code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ast: true,
|
||||
code: false
|
||||
}
|
||||
},
|
||||
}).ast.to_mozilla_ast(), null, 2));
|
||||
} else if (program.output) {
|
||||
fs.writeFileSync(program.output, result.code);
|
||||
if (result.map) {
|
||||
fs.writeFileSync(program.output + ".map", result.map);
|
||||
}
|
||||
} else if (output) {
|
||||
fs.writeFileSync(output, result.code);
|
||||
if (result.map) fs.writeFileSync(output + ".map", result.map);
|
||||
} else {
|
||||
print(result.code);
|
||||
}
|
||||
if (program.nameCache) {
|
||||
fs.writeFileSync(program.nameCache, JSON.stringify(options.nameCache));
|
||||
}
|
||||
if (nameCache) fs.writeFileSync(nameCache, JSON.stringify(options.nameCache));
|
||||
if (result.timings) for (var phase in result.timings) {
|
||||
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
|
||||
}
|
||||
@@ -323,7 +419,7 @@ function simple_glob(glob) {
|
||||
.replace(/\?/g, "[^/\\\\]") + "$";
|
||||
var mod = process.platform === "win32" ? "i" : "";
|
||||
var rx = new RegExp(pattern, mod);
|
||||
var results = entries.filter(function(name) {
|
||||
var results = entries.sort().filter(function(name) {
|
||||
return rx.test(name);
|
||||
}).map(function(name) {
|
||||
return path.join(dir, name);
|
||||
@@ -343,47 +439,45 @@ function read_file(path, default_value) {
|
||||
}
|
||||
}
|
||||
|
||||
function parse_js(flag) {
|
||||
return function(value, options) {
|
||||
options = options || {};
|
||||
try {
|
||||
UglifyJS.parse(value, {
|
||||
expression: true
|
||||
}).walk(new UglifyJS.TreeWalker(function(node) {
|
||||
if (node instanceof UglifyJS.AST_Assign) {
|
||||
var name = node.left.print_to_string();
|
||||
var value = node.right;
|
||||
if (flag) {
|
||||
options[name] = value;
|
||||
} else if (value instanceof UglifyJS.AST_Array) {
|
||||
options[name] = value.elements.map(to_string);
|
||||
} else {
|
||||
options[name] = to_string(value);
|
||||
}
|
||||
return true;
|
||||
function parse_js(value, options, flag) {
|
||||
if (!options || typeof options != "object") options = {};
|
||||
if (typeof value == "string") try {
|
||||
UglifyJS.parse(value, {
|
||||
expression: true
|
||||
}).walk(new UglifyJS.TreeWalker(function(node) {
|
||||
if (node instanceof UglifyJS.AST_Assign) {
|
||||
var name = node.left.print_to_string();
|
||||
var value = node.right;
|
||||
if (flag) {
|
||||
options[name] = value;
|
||||
} else if (value instanceof UglifyJS.AST_Array) {
|
||||
options[name] = value.elements.map(to_string);
|
||||
} else {
|
||||
options[name] = to_string(value);
|
||||
}
|
||||
if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_PropAccess) {
|
||||
var name = node.print_to_string();
|
||||
options[name] = true;
|
||||
return true;
|
||||
}
|
||||
if (!(node instanceof UglifyJS.AST_Sequence)) throw node;
|
||||
|
||||
function to_string(value) {
|
||||
return value instanceof UglifyJS.AST_Constant ? value.getValue() : value.print_to_string({
|
||||
quote_keys: true
|
||||
});
|
||||
}
|
||||
}));
|
||||
} catch (ex) {
|
||||
if (flag) {
|
||||
fatal("cannot parse arguments for '" + flag + "': " + value);
|
||||
} else {
|
||||
options[value] = null;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_PropAccess) {
|
||||
var name = node.print_to_string();
|
||||
options[name] = true;
|
||||
return true;
|
||||
}
|
||||
if (!(node instanceof UglifyJS.AST_Sequence)) throw node;
|
||||
|
||||
function to_string(value) {
|
||||
return value instanceof UglifyJS.AST_Constant ? value.value : value.print_to_string({
|
||||
quote_keys: true
|
||||
});
|
||||
}
|
||||
}));
|
||||
} catch (ex) {
|
||||
if (flag) {
|
||||
fatal("cannot parse arguments for '" + flag + "': " + value);
|
||||
} else {
|
||||
options[value] = null;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
function skip_key(key) {
|
||||
|
||||
641
lib/ast.js
641
lib/ast.js
File diff suppressed because it is too large
Load Diff
3952
lib/compress.js
3952
lib/compress.js
File diff suppressed because it is too large
Load Diff
@@ -85,9 +85,11 @@ function minify(files, options) {
|
||||
sourceMap: false,
|
||||
timings: false,
|
||||
toplevel: false,
|
||||
validate: false,
|
||||
warnings: false,
|
||||
wrap: false,
|
||||
}, true);
|
||||
if (options.validate) AST_Node.enable_validation();
|
||||
var timings = options.timings && {
|
||||
start: Date.now()
|
||||
};
|
||||
@@ -129,6 +131,7 @@ function minify(files, options) {
|
||||
content: null,
|
||||
filename: null,
|
||||
includeSources: false,
|
||||
names: true,
|
||||
root: null,
|
||||
url: null,
|
||||
}, true);
|
||||
@@ -138,7 +141,7 @@ function minify(files, options) {
|
||||
warnings.push(warning);
|
||||
}, options.warnings == "verbose");
|
||||
if (timings) timings.parse = Date.now();
|
||||
var source_maps, toplevel;
|
||||
var toplevel;
|
||||
if (files instanceof AST_Toplevel) {
|
||||
toplevel = files;
|
||||
} else {
|
||||
@@ -151,19 +154,17 @@ function minify(files, options) {
|
||||
if (typeof source_map_content == "string" && source_map_content != "inline") {
|
||||
source_map_content = parse_source_map(source_map_content);
|
||||
}
|
||||
source_maps = source_map_content && Object.create(null);
|
||||
if (source_map_content) options.sourceMap.orig = Object.create(null);
|
||||
for (var name in files) if (HOP(files, name)) {
|
||||
options.parse.filename = name;
|
||||
options.parse.toplevel = toplevel = parse(files[name], options.parse);
|
||||
if (source_maps) {
|
||||
if (source_map_content == "inline") {
|
||||
var inlined_content = read_source_map(name, toplevel);
|
||||
if (inlined_content) {
|
||||
source_maps[name] = parse_source_map(inlined_content);
|
||||
}
|
||||
} else {
|
||||
source_maps[name] = source_map_content;
|
||||
if (source_map_content == "inline") {
|
||||
var inlined_content = read_source_map(name, toplevel);
|
||||
if (inlined_content) {
|
||||
options.sourceMap.orig[name] = parse_source_map(inlined_content);
|
||||
}
|
||||
} else if (source_map_content) {
|
||||
options.sourceMap.orig[name] = source_map_content;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,13 +178,17 @@ function minify(files, options) {
|
||||
toplevel = toplevel[action](option);
|
||||
files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
|
||||
});
|
||||
if (options.validate) toplevel.validate_ast();
|
||||
if (timings) timings.rename = Date.now();
|
||||
if (options.rename) {
|
||||
toplevel.figure_out_scope(options.mangle);
|
||||
toplevel.expand_names(options.mangle);
|
||||
}
|
||||
if (timings) timings.compress = Date.now();
|
||||
if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
|
||||
if (options.compress) {
|
||||
toplevel = new Compressor(options.compress).compress(toplevel);
|
||||
if (options.validate) toplevel.validate_ast();
|
||||
}
|
||||
if (timings) timings.scope = Date.now();
|
||||
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
||||
if (timings) timings.mangle = Date.now();
|
||||
@@ -192,9 +197,7 @@ function minify(files, options) {
|
||||
toplevel.mangle_names(options.mangle);
|
||||
}
|
||||
if (timings) timings.properties = Date.now();
|
||||
if (options.mangle && options.mangle.properties) {
|
||||
toplevel = mangle_properties(toplevel, options.mangle.properties);
|
||||
}
|
||||
if (options.mangle && options.mangle.properties) mangle_properties(toplevel, options.mangle.properties);
|
||||
if (timings) timings.output = Date.now();
|
||||
var result = {};
|
||||
if (options.output.ast) {
|
||||
@@ -202,19 +205,13 @@ function minify(files, options) {
|
||||
}
|
||||
if (!HOP(options.output, "code") || options.output.code) {
|
||||
if (options.sourceMap) {
|
||||
options.output.source_map = SourceMap({
|
||||
file: options.sourceMap.filename,
|
||||
orig: source_maps,
|
||||
root: options.sourceMap.root
|
||||
});
|
||||
options.output.source_map = SourceMap(options.sourceMap);
|
||||
if (options.sourceMap.includeSources) {
|
||||
if (files instanceof AST_Toplevel) {
|
||||
throw new Error("original source content unavailable");
|
||||
} else for (var name in files) if (HOP(files, name)) {
|
||||
options.output.source_map.get().setSourceContent(name, files[name]);
|
||||
options.output.source_map.setSourceContent(name, files[name]);
|
||||
}
|
||||
} else {
|
||||
options.output.source_map.get()._sourcesContents = null;
|
||||
}
|
||||
}
|
||||
delete options.output.ast;
|
||||
@@ -260,5 +257,7 @@ function minify(files, options) {
|
||||
return result;
|
||||
} catch (ex) {
|
||||
return { error: ex };
|
||||
} finally {
|
||||
AST_Node.disable_validation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
https://github.com/mishoo/UglifyJS
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
var args = {
|
||||
start : my_start_token(key),
|
||||
end : my_end_token(M.value),
|
||||
key : key.type == "Identifier" ? key.name : key.value,
|
||||
key : "" + key[key.type == "Identifier" ? "name" : "value"],
|
||||
value : from_moz(M.value)
|
||||
};
|
||||
if (M.kind == "init") return new AST_ObjectKeyVal(args);
|
||||
@@ -212,7 +212,14 @@
|
||||
end : my_end_token(M),
|
||||
name : M.name
|
||||
});
|
||||
}
|
||||
},
|
||||
ThisExpression: function(M) {
|
||||
return new AST_This({
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M),
|
||||
name : "this",
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
MOZ_TO_ME.UpdateExpression =
|
||||
@@ -245,7 +252,6 @@
|
||||
map("VariableDeclarator", AST_VarDef, "id>name, init>value");
|
||||
map("CatchClause", AST_Catch, "param>argname, body%body");
|
||||
|
||||
map("ThisExpression", AST_This);
|
||||
map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
|
||||
map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
|
||||
map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
|
||||
@@ -407,6 +413,10 @@
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_This, function To_Moz_ThisExpression() {
|
||||
return { type: "ThisExpression" };
|
||||
});
|
||||
|
||||
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
|
||||
var flags = M.value.toString().match(/[gimuy]*$/)[0];
|
||||
var value = "/" + M.value.raw_source + "/" + flags;
|
||||
|
||||
543
lib/output.js
543
lib/output.js
@@ -1,7 +1,7 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
https://github.com/mishoo/UglifyJS
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
@@ -43,8 +43,6 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/;
|
||||
|
||||
function is_some_comments(comment) {
|
||||
// multiline comment
|
||||
return comment.type == "comment2" && /@preserve|@license|@cc_on/i.test(comment.value);
|
||||
@@ -102,7 +100,7 @@ function OutputStream(options) {
|
||||
}
|
||||
}
|
||||
|
||||
var indentation = 0;
|
||||
var indentation = options.indent_start;
|
||||
var current_col = 0;
|
||||
var current_line = 1;
|
||||
var current_pos = 0;
|
||||
@@ -121,15 +119,20 @@ function OutputStream(options) {
|
||||
});
|
||||
} : function(str) {
|
||||
var s = "";
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
if (is_surrogate_pair_head(str[i]) && !is_surrogate_pair_tail(str[i + 1])
|
||||
|| is_surrogate_pair_tail(str[i]) && !is_surrogate_pair_head(str[i - 1])) {
|
||||
s += "\\u" + str.charCodeAt(i).toString(16);
|
||||
} else {
|
||||
s += str[i];
|
||||
for (var i = 0, j = 0; i < str.length; i++) {
|
||||
var code = str.charCodeAt(i);
|
||||
if (is_surrogate_pair_head(code)) {
|
||||
if (is_surrogate_pair_tail(str.charCodeAt(i + 1))) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
} else if (!is_surrogate_pair_tail(code)) {
|
||||
continue;
|
||||
}
|
||||
s += str.slice(j, i) + "\\u" + code.toString(16);
|
||||
j = i + 1;
|
||||
}
|
||||
return s;
|
||||
return j == 0 ? str : s + str.slice(j);
|
||||
};
|
||||
|
||||
function make_string(str, quote) {
|
||||
@@ -188,10 +191,6 @@ function OutputStream(options) {
|
||||
return name;
|
||||
}
|
||||
|
||||
function make_indent(back) {
|
||||
return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
|
||||
}
|
||||
|
||||
/* -----[ beautification/minification ]----- */
|
||||
|
||||
var has_parens = false;
|
||||
@@ -269,7 +268,7 @@ function OutputStream(options) {
|
||||
}
|
||||
}
|
||||
newline_insert = -1;
|
||||
var prev = last.charAt(last.length - 1);
|
||||
var prev = last.slice(-1);
|
||||
if (might_need_semicolon) {
|
||||
might_need_semicolon = false;
|
||||
|
||||
@@ -298,16 +297,17 @@ function OutputStream(options) {
|
||||
}
|
||||
|
||||
if (might_need_space) {
|
||||
if ((is_identifier_char(prev)
|
||||
&& (is_identifier_char(ch) || ch == "\\"))
|
||||
if (is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\")
|
||||
|| (ch == "/" && ch == prev)
|
||||
|| ((ch == "+" || ch == "-") && ch == last))
|
||||
{
|
||||
|| ((ch == "+" || ch == "-") && ch == last)
|
||||
|| str == "--" && last == "!"
|
||||
|| str == "in" && prev == "/"
|
||||
|| last == "--" && ch == ">") {
|
||||
OUTPUT += " ";
|
||||
current_col++;
|
||||
current_pos++;
|
||||
}
|
||||
might_need_space = false;
|
||||
if (prev != "<" || str != "!") might_need_space = false;
|
||||
}
|
||||
|
||||
if (mapping_token) {
|
||||
@@ -322,7 +322,7 @@ function OutputStream(options) {
|
||||
}
|
||||
|
||||
OUTPUT += str;
|
||||
has_parens = str[str.length - 1] == "(";
|
||||
has_parens = str.slice(-1) == "(";
|
||||
current_pos += str.length;
|
||||
var a = str.split(/\r?\n/), n = a.length - 1;
|
||||
current_line += n;
|
||||
@@ -341,9 +341,7 @@ function OutputStream(options) {
|
||||
};
|
||||
|
||||
var indent = options.beautify ? function(half) {
|
||||
if (options.beautify) {
|
||||
print(make_indent(half ? 0.5 : 0));
|
||||
}
|
||||
print(repeat_string(" ", half ? indentation - (options.indent_level >> 1) : indentation));
|
||||
} : noop;
|
||||
|
||||
var with_indent = options.beautify ? function(col, cont) {
|
||||
@@ -378,7 +376,7 @@ function OutputStream(options) {
|
||||
};
|
||||
|
||||
function force_semicolon() {
|
||||
might_need_semicolon = false;
|
||||
if (might_need_semicolon) print(";");
|
||||
print(";");
|
||||
}
|
||||
|
||||
@@ -571,9 +569,9 @@ function OutputStream(options) {
|
||||
get : get,
|
||||
toString : get,
|
||||
indent : indent,
|
||||
indentation : function() { return indentation },
|
||||
current_width : function() { return current_col - indentation },
|
||||
should_break : function() { return options.width && this.current_width() >= options.width },
|
||||
should_break : readonly ? noop : function() {
|
||||
return options.width && current_col - indentation >= options.width;
|
||||
},
|
||||
has_parens : function() { return has_parens },
|
||||
newline : newline,
|
||||
print : print,
|
||||
@@ -585,17 +583,7 @@ function OutputStream(options) {
|
||||
force_semicolon : force_semicolon,
|
||||
to_utf8 : to_utf8,
|
||||
print_name : function(name) { print(make_name(name)) },
|
||||
print_string : function(str, quote, escape_directive) {
|
||||
var encoded = encode_string(str, quote);
|
||||
if (escape_directive === true && encoded.indexOf("\\") === -1) {
|
||||
// Insert semicolons to break directive prologue
|
||||
if (!EXPECT_DIRECTIVE.test(OUTPUT)) {
|
||||
force_semicolon();
|
||||
}
|
||||
force_semicolon();
|
||||
}
|
||||
print(encoded);
|
||||
},
|
||||
print_string : function(str, quote) { print(encode_string(str, quote)) },
|
||||
next_indent : next_indent,
|
||||
with_indent : with_indent,
|
||||
with_block : with_block,
|
||||
@@ -633,23 +621,10 @@ function OutputStream(options) {
|
||||
nodetype.DEFMETHOD("_codegen", generator);
|
||||
}
|
||||
|
||||
var in_directive = false;
|
||||
var active_scope = null;
|
||||
var use_asm = null;
|
||||
var use_asm = false;
|
||||
|
||||
AST_Node.DEFMETHOD("print", function(stream, force_parens) {
|
||||
var self = this, generator = self._codegen;
|
||||
if (self instanceof AST_Scope) {
|
||||
active_scope = self;
|
||||
} else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") {
|
||||
use_asm = active_scope;
|
||||
}
|
||||
function doit() {
|
||||
stream.prepend_comments(self);
|
||||
self.add_source_map(stream);
|
||||
generator(self, stream);
|
||||
stream.append_comments(self);
|
||||
}
|
||||
var self = this;
|
||||
stream.push_node(self);
|
||||
if (force_parens || self.needs_parens(stream)) {
|
||||
stream.with_parens(doit);
|
||||
@@ -657,12 +632,14 @@ function OutputStream(options) {
|
||||
doit();
|
||||
}
|
||||
stream.pop_node();
|
||||
if (self === use_asm) {
|
||||
use_asm = null;
|
||||
|
||||
function doit() {
|
||||
stream.prepend_comments(self);
|
||||
self.add_source_map(stream);
|
||||
self._codegen(stream);
|
||||
stream.append_comments(self);
|
||||
}
|
||||
});
|
||||
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
|
||||
|
||||
AST_Node.DEFMETHOD("print_to_string", function(options) {
|
||||
var s = OutputStream(options);
|
||||
this.print(s);
|
||||
@@ -705,78 +682,66 @@ function OutputStream(options) {
|
||||
|
||||
PARENS(AST_Unary, function(output) {
|
||||
var p = output.parent();
|
||||
return p instanceof AST_PropAccess && p.expression === this
|
||||
|| p instanceof AST_Call && p.expression === this;
|
||||
return (p instanceof AST_Call || p instanceof AST_PropAccess) && p.expression === this;
|
||||
});
|
||||
|
||||
PARENS(AST_Sequence, function(output) {
|
||||
var p = output.parent();
|
||||
// (foo, bar)() or foo(1, (2, 3), 4)
|
||||
return p instanceof AST_Call
|
||||
// !(foo, bar, baz)
|
||||
|| p instanceof AST_Unary
|
||||
// [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
|
||||
return p instanceof AST_Array
|
||||
// 1 + (2, 3) + 4 ==> 8
|
||||
|| p instanceof AST_Binary
|
||||
// var a = (1, 2), b = a + a; ==> b == 4
|
||||
|| p instanceof AST_VarDef
|
||||
// (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
|
||||
|| p instanceof AST_PropAccess && p.expression === this
|
||||
// [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
|
||||
|| p instanceof AST_Array
|
||||
// { foo: (1, 2) }.foo ==> 2
|
||||
|| p instanceof AST_ObjectProperty
|
||||
// new (foo, bar) or foo(1, (2, 3), 4)
|
||||
|| p instanceof AST_Call
|
||||
// (false, true) ? (a = 10, b = 20) : (c = 30)
|
||||
// ==> 20 (side effect, set a := 10 and b := 20)
|
||||
|| p instanceof AST_Conditional;
|
||||
|| p instanceof AST_Conditional
|
||||
// { foo: (1, 2) }.foo ==> 2
|
||||
|| p instanceof AST_ObjectProperty
|
||||
// (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
|
||||
|| p instanceof AST_PropAccess && p.expression === this
|
||||
// !(foo, bar, baz)
|
||||
|| p instanceof AST_Unary
|
||||
// var a = (1, 2), b = a + a; ==> b == 4
|
||||
|| p instanceof AST_VarDef;
|
||||
});
|
||||
|
||||
PARENS(AST_Binary, function(output) {
|
||||
var p = output.parent();
|
||||
// (foo && bar)()
|
||||
if (p instanceof AST_Call && p.expression === this)
|
||||
return true;
|
||||
// typeof (foo && bar)
|
||||
if (p instanceof AST_Unary)
|
||||
return true;
|
||||
// (foo && bar)["prop"], (foo && bar).prop
|
||||
if (p instanceof AST_PropAccess && p.expression === this)
|
||||
return true;
|
||||
// this deals with precedence: 3 * (2 + 1)
|
||||
if (p instanceof AST_Binary) {
|
||||
var po = p.operator, pp = PRECEDENCE[po];
|
||||
var so = this.operator, sp = PRECEDENCE[so];
|
||||
if (pp > sp
|
||||
|| (pp == sp
|
||||
&& this === p.right)) {
|
||||
return true;
|
||||
}
|
||||
return pp > sp || (pp == sp && this === p.right);
|
||||
}
|
||||
// (foo && bar)()
|
||||
if (p instanceof AST_Call) return p.expression === this;
|
||||
// (foo && bar)["prop"], (foo && bar).prop
|
||||
if (p instanceof AST_PropAccess) return p.expression === this;
|
||||
// typeof (foo && bar)
|
||||
if (p instanceof AST_Unary) return true;
|
||||
});
|
||||
|
||||
PARENS(AST_PropAccess, function(output) {
|
||||
var node = this;
|
||||
var p = output.parent();
|
||||
if (p instanceof AST_New && p.expression === this) {
|
||||
// i.e. new (foo.bar().baz)
|
||||
if (p instanceof AST_New && p.expression === node) {
|
||||
// i.e. new (foo().bar)
|
||||
//
|
||||
// if there's one call into this subtree, then we need
|
||||
// parens around it too, otherwise the call will be
|
||||
// interpreted as passing the arguments to the upper New
|
||||
// expression.
|
||||
var parens = false;
|
||||
this.walk(new TreeWalker(function(node) {
|
||||
if (parens || node instanceof AST_Scope) return true;
|
||||
if (node instanceof AST_Call) {
|
||||
parens = true;
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
return parens;
|
||||
do {
|
||||
node = node.expression;
|
||||
} while (node instanceof AST_PropAccess);
|
||||
return node.TYPE == "Call";
|
||||
}
|
||||
});
|
||||
|
||||
PARENS(AST_Call, function(output) {
|
||||
var p = output.parent();
|
||||
if (p instanceof AST_New && p.expression === this) return true;
|
||||
if (p instanceof AST_New) return p.expression === this;
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=123506
|
||||
if (output.option('webkit')) {
|
||||
var g = output.parent(1);
|
||||
@@ -789,49 +754,56 @@ function OutputStream(options) {
|
||||
});
|
||||
|
||||
PARENS(AST_New, function(output) {
|
||||
if (need_constructor_parens(this, output)) return false;
|
||||
var p = output.parent();
|
||||
if (!need_constructor_parens(this, output)
|
||||
&& (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]()
|
||||
|| p instanceof AST_Call && p.expression === this)) // (new foo)(bar)
|
||||
return true;
|
||||
// (new foo)(bar)
|
||||
if (p instanceof AST_Call) return p.expression === this;
|
||||
// (new Date).getTime(), (new Date)["getTime"]()
|
||||
return p instanceof AST_PropAccess;
|
||||
});
|
||||
|
||||
PARENS(AST_Number, function(output) {
|
||||
var p = output.parent();
|
||||
if (p instanceof AST_PropAccess && p.expression === this) {
|
||||
var value = this.getValue();
|
||||
if (value < 0 || /^0/.test(make_num(value))) {
|
||||
return true;
|
||||
}
|
||||
var value = this.value;
|
||||
// https://github.com/mishoo/UglifyJS/issues/115
|
||||
// https://github.com/mishoo/UglifyJS/pull/1009
|
||||
return value < 0 || /^0/.test(make_num(value));
|
||||
}
|
||||
});
|
||||
|
||||
PARENS([ AST_Assign, AST_Conditional ], function(output) {
|
||||
var p = output.parent();
|
||||
// !(a = false) → true
|
||||
if (p instanceof AST_Unary)
|
||||
return true;
|
||||
// 1 + (a = 2) + 3 → 6, side effect setting a = 2
|
||||
if (p instanceof AST_Binary && !(p instanceof AST_Assign))
|
||||
return true;
|
||||
if (p instanceof AST_Binary) return !(p instanceof AST_Assign);
|
||||
// (a = func)() —or— new (a = Object)()
|
||||
if (p instanceof AST_Call && p.expression === this)
|
||||
return true;
|
||||
if (p instanceof AST_Call) return p.expression === this;
|
||||
// (a = foo) ? bar : baz
|
||||
if (p instanceof AST_Conditional && p.condition === this)
|
||||
return true;
|
||||
if (p instanceof AST_Conditional) return p.condition === this;
|
||||
// (a = foo)["prop"] —or— (a = foo).prop
|
||||
if (p instanceof AST_PropAccess && p.expression === this)
|
||||
return true;
|
||||
if (p instanceof AST_PropAccess) return p.expression === this;
|
||||
// !(a = false) → true
|
||||
if (p instanceof AST_Unary) return true;
|
||||
});
|
||||
|
||||
/* -----[ PRINTERS ]----- */
|
||||
|
||||
DEFPRINT(AST_Directive, function(self, output) {
|
||||
output.print_string(self.value, self.quote);
|
||||
DEFPRINT(AST_Directive, function(output) {
|
||||
var quote = this.quote;
|
||||
var value = this.value;
|
||||
switch (output.option("quote_style")) {
|
||||
case 0:
|
||||
case 2:
|
||||
if (value.indexOf('"') == -1) quote = '"';
|
||||
break;
|
||||
case 1:
|
||||
if (value.indexOf("'") == -1) quote = "'";
|
||||
break;
|
||||
}
|
||||
output.print(quote + value + quote);
|
||||
output.semicolon();
|
||||
});
|
||||
DEFPRINT(AST_Debugger, function(self, output) {
|
||||
DEFPRINT(AST_Debugger, function(output) {
|
||||
output.print("debugger");
|
||||
output.semicolon();
|
||||
});
|
||||
@@ -840,51 +812,48 @@ function OutputStream(options) {
|
||||
|
||||
function display_body(body, is_toplevel, output, allow_directives) {
|
||||
var last = body.length - 1;
|
||||
in_directive = allow_directives;
|
||||
var in_directive = allow_directives;
|
||||
var was_asm = use_asm;
|
||||
body.forEach(function(stmt, i) {
|
||||
if (in_directive === true && !(stmt instanceof AST_Directive ||
|
||||
stmt instanceof AST_EmptyStatement ||
|
||||
(stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String)
|
||||
)) {
|
||||
in_directive = false;
|
||||
}
|
||||
if (!(stmt instanceof AST_EmptyStatement)) {
|
||||
output.indent();
|
||||
stmt.print(output);
|
||||
if (!(i == last && is_toplevel)) {
|
||||
output.newline();
|
||||
if (is_toplevel) output.newline();
|
||||
if (in_directive) {
|
||||
if (stmt instanceof AST_Directive) {
|
||||
if (stmt.value == "use asm") use_asm = true;
|
||||
} else if (!(stmt instanceof AST_EmptyStatement)) {
|
||||
if (stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String) {
|
||||
output.force_semicolon();
|
||||
}
|
||||
in_directive = false;
|
||||
}
|
||||
}
|
||||
if (in_directive === true &&
|
||||
stmt instanceof AST_SimpleStatement &&
|
||||
stmt.body instanceof AST_String
|
||||
) {
|
||||
in_directive = false;
|
||||
}
|
||||
if (stmt instanceof AST_EmptyStatement) return;
|
||||
output.indent();
|
||||
stmt.print(output);
|
||||
if (i == last && is_toplevel) return;
|
||||
output.newline();
|
||||
if (is_toplevel) output.newline();
|
||||
});
|
||||
in_directive = false;
|
||||
use_asm = was_asm;
|
||||
}
|
||||
|
||||
AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
|
||||
force_statement(this.body, output);
|
||||
});
|
||||
|
||||
DEFPRINT(AST_Statement, function(self, output) {
|
||||
self.body.print(output);
|
||||
DEFPRINT(AST_Statement, function(output) {
|
||||
this.body.print(output);
|
||||
output.semicolon();
|
||||
});
|
||||
DEFPRINT(AST_Toplevel, function(self, output) {
|
||||
display_body(self.body, true, output, true);
|
||||
DEFPRINT(AST_Toplevel, function(output) {
|
||||
display_body(this.body, true, output, true);
|
||||
output.print("");
|
||||
});
|
||||
DEFPRINT(AST_LabeledStatement, function(self, output) {
|
||||
self.label.print(output);
|
||||
DEFPRINT(AST_LabeledStatement, function(output) {
|
||||
this.label.print(output);
|
||||
output.colon();
|
||||
self.body.print(output);
|
||||
this.body.print(output);
|
||||
});
|
||||
DEFPRINT(AST_SimpleStatement, function(self, output) {
|
||||
self.body.print(output);
|
||||
DEFPRINT(AST_SimpleStatement, function(output) {
|
||||
this.body.print(output);
|
||||
output.semicolon();
|
||||
});
|
||||
function print_braced_empty(self, output) {
|
||||
@@ -901,13 +870,14 @@ function OutputStream(options) {
|
||||
});
|
||||
} else print_braced_empty(self, output);
|
||||
}
|
||||
DEFPRINT(AST_BlockStatement, function(self, output) {
|
||||
print_braced(self, output);
|
||||
DEFPRINT(AST_BlockStatement, function(output) {
|
||||
print_braced(this, output);
|
||||
});
|
||||
DEFPRINT(AST_EmptyStatement, function(self, output) {
|
||||
DEFPRINT(AST_EmptyStatement, function(output) {
|
||||
output.semicolon();
|
||||
});
|
||||
DEFPRINT(AST_Do, function(self, output) {
|
||||
DEFPRINT(AST_Do, function(output) {
|
||||
var self = this;
|
||||
output.print("do");
|
||||
output.space();
|
||||
make_block(self.body, output);
|
||||
@@ -919,7 +889,8 @@ function OutputStream(options) {
|
||||
});
|
||||
output.semicolon();
|
||||
});
|
||||
DEFPRINT(AST_While, function(self, output) {
|
||||
DEFPRINT(AST_While, function(output) {
|
||||
var self = this;
|
||||
output.print("while");
|
||||
output.space();
|
||||
output.with_parens(function() {
|
||||
@@ -928,7 +899,8 @@ function OutputStream(options) {
|
||||
output.space();
|
||||
self._do_print_body(output);
|
||||
});
|
||||
DEFPRINT(AST_For, function(self, output) {
|
||||
DEFPRINT(AST_For, function(output) {
|
||||
var self = this;
|
||||
output.print("for");
|
||||
output.space();
|
||||
output.with_parens(function() {
|
||||
@@ -957,7 +929,8 @@ function OutputStream(options) {
|
||||
output.space();
|
||||
self._do_print_body(output);
|
||||
});
|
||||
DEFPRINT(AST_ForIn, function(self, output) {
|
||||
DEFPRINT(AST_ForIn, function(output) {
|
||||
var self = this;
|
||||
output.print("for");
|
||||
output.space();
|
||||
output.with_parens(function() {
|
||||
@@ -970,7 +943,8 @@ function OutputStream(options) {
|
||||
output.space();
|
||||
self._do_print_body(output);
|
||||
});
|
||||
DEFPRINT(AST_With, function(self, output) {
|
||||
DEFPRINT(AST_With, function(output) {
|
||||
var self = this;
|
||||
output.print("with");
|
||||
output.space();
|
||||
output.with_parens(function() {
|
||||
@@ -981,7 +955,7 @@ function OutputStream(options) {
|
||||
});
|
||||
|
||||
/* -----[ functions ]----- */
|
||||
AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword) {
|
||||
DEFPRINT(AST_Lambda, function(output, nokeyword) {
|
||||
var self = this;
|
||||
if (!nokeyword) {
|
||||
output.print("function");
|
||||
@@ -999,32 +973,23 @@ function OutputStream(options) {
|
||||
output.space();
|
||||
print_braced(self, output, true);
|
||||
});
|
||||
DEFPRINT(AST_Lambda, function(self, output) {
|
||||
self._do_print(output);
|
||||
});
|
||||
|
||||
/* -----[ jumps ]----- */
|
||||
function print_jump(output, kind, target) {
|
||||
output.print(kind);
|
||||
if (target) {
|
||||
output.space();
|
||||
target.print(output);
|
||||
}
|
||||
output.semicolon();
|
||||
function print_jump(kind, prop) {
|
||||
return function(output) {
|
||||
output.print(kind);
|
||||
var target = this[prop];
|
||||
if (target) {
|
||||
output.space();
|
||||
target.print(output);
|
||||
}
|
||||
output.semicolon();
|
||||
};
|
||||
}
|
||||
|
||||
DEFPRINT(AST_Return, function(self, output) {
|
||||
print_jump(output, "return", self.value);
|
||||
});
|
||||
DEFPRINT(AST_Throw, function(self, output) {
|
||||
print_jump(output, "throw", self.value);
|
||||
});
|
||||
DEFPRINT(AST_Break, function(self, output) {
|
||||
print_jump(output, "break", self.label);
|
||||
});
|
||||
DEFPRINT(AST_Continue, function(self, output) {
|
||||
print_jump(output, "continue", self.label);
|
||||
});
|
||||
DEFPRINT(AST_Return, print_jump("return", "value"));
|
||||
DEFPRINT(AST_Throw, print_jump("throw", "value"));
|
||||
DEFPRINT(AST_Break, print_jump("break", "label"));
|
||||
DEFPRINT(AST_Continue, print_jump("continue", "label"));
|
||||
|
||||
/* -----[ if ]----- */
|
||||
function make_then(self, output) {
|
||||
@@ -1053,7 +1018,8 @@ function OutputStream(options) {
|
||||
}
|
||||
force_statement(self.body, output);
|
||||
}
|
||||
DEFPRINT(AST_If, function(self, output) {
|
||||
DEFPRINT(AST_If, function(output) {
|
||||
var self = this;
|
||||
output.print("if");
|
||||
output.space();
|
||||
output.with_parens(function() {
|
||||
@@ -1075,7 +1041,8 @@ function OutputStream(options) {
|
||||
});
|
||||
|
||||
/* -----[ switch ]----- */
|
||||
DEFPRINT(AST_Switch, function(self, output) {
|
||||
DEFPRINT(AST_Switch, function(output) {
|
||||
var self = this;
|
||||
output.print("switch");
|
||||
output.space();
|
||||
output.with_parens(function() {
|
||||
@@ -1093,28 +1060,30 @@ function OutputStream(options) {
|
||||
});
|
||||
});
|
||||
});
|
||||
AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output) {
|
||||
function print_branch_body(self, output) {
|
||||
output.newline();
|
||||
this.body.forEach(function(stmt) {
|
||||
self.body.forEach(function(stmt) {
|
||||
output.indent();
|
||||
stmt.print(output);
|
||||
output.newline();
|
||||
});
|
||||
});
|
||||
DEFPRINT(AST_Default, function(self, output) {
|
||||
}
|
||||
DEFPRINT(AST_Default, function(output) {
|
||||
output.print("default:");
|
||||
self._do_print_body(output);
|
||||
print_branch_body(this, output);
|
||||
});
|
||||
DEFPRINT(AST_Case, function(self, output) {
|
||||
DEFPRINT(AST_Case, function(output) {
|
||||
var self = this;
|
||||
output.print("case");
|
||||
output.space();
|
||||
self.expression.print(output);
|
||||
output.print(":");
|
||||
self._do_print_body(output);
|
||||
print_branch_body(self, output);
|
||||
});
|
||||
|
||||
/* -----[ exceptions ]----- */
|
||||
DEFPRINT(AST_Try, function(self, output) {
|
||||
DEFPRINT(AST_Try, function(output) {
|
||||
var self = this;
|
||||
output.print("try");
|
||||
output.space();
|
||||
print_braced(self, output);
|
||||
@@ -1127,7 +1096,8 @@ function OutputStream(options) {
|
||||
self.bfinally.print(output);
|
||||
}
|
||||
});
|
||||
DEFPRINT(AST_Catch, function(self, output) {
|
||||
DEFPRINT(AST_Catch, function(output) {
|
||||
var self = this;
|
||||
output.print("catch");
|
||||
output.space();
|
||||
output.with_parens(function() {
|
||||
@@ -1136,13 +1106,14 @@ function OutputStream(options) {
|
||||
output.space();
|
||||
print_braced(self, output);
|
||||
});
|
||||
DEFPRINT(AST_Finally, function(self, output) {
|
||||
DEFPRINT(AST_Finally, function(output) {
|
||||
output.print("finally");
|
||||
output.space();
|
||||
print_braced(self, output);
|
||||
print_braced(this, output);
|
||||
});
|
||||
|
||||
DEFPRINT(AST_Var, function(self, output) {
|
||||
DEFPRINT(AST_Var, function(output) {
|
||||
var self = this;
|
||||
output.print("var");
|
||||
output.space();
|
||||
self.definitions.forEach(function(def, i) {
|
||||
@@ -1156,7 +1127,7 @@ function OutputStream(options) {
|
||||
function parenthesize_for_noin(node, output, noin) {
|
||||
var parens = false;
|
||||
// need to take some precautions here:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/60
|
||||
// https://github.com/mishoo/UglifyJS/issues/60
|
||||
if (noin) node.walk(new TreeWalker(function(node) {
|
||||
if (parens || node instanceof AST_Scope) return true;
|
||||
if (node instanceof AST_Binary && node.operator == "in") {
|
||||
@@ -1167,7 +1138,8 @@ function OutputStream(options) {
|
||||
node.print(output, parens);
|
||||
}
|
||||
|
||||
DEFPRINT(AST_VarDef, function(self, output) {
|
||||
DEFPRINT(AST_VarDef, function(output) {
|
||||
var self = this;
|
||||
self.name.print(output);
|
||||
if (self.value) {
|
||||
output.space();
|
||||
@@ -1180,10 +1152,7 @@ function OutputStream(options) {
|
||||
});
|
||||
|
||||
/* -----[ other expressions ]----- */
|
||||
DEFPRINT(AST_Call, function(self, output) {
|
||||
self.expression.print(output);
|
||||
if (self instanceof AST_New && !need_constructor_parens(self, output))
|
||||
return;
|
||||
function print_call_args(self, output) {
|
||||
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
|
||||
output.add_mapping(self.start);
|
||||
}
|
||||
@@ -1193,14 +1162,20 @@ function OutputStream(options) {
|
||||
expr.print(output);
|
||||
});
|
||||
});
|
||||
}
|
||||
DEFPRINT(AST_Call, function(output) {
|
||||
this.expression.print(output);
|
||||
print_call_args(this, output);
|
||||
});
|
||||
DEFPRINT(AST_New, function(self, output) {
|
||||
DEFPRINT(AST_New, function(output) {
|
||||
var self = this;
|
||||
output.print("new");
|
||||
output.space();
|
||||
AST_Call.prototype._codegen(self, output);
|
||||
self.expression.print(output);
|
||||
if (need_constructor_parens(self, output)) print_call_args(self, output);
|
||||
});
|
||||
DEFPRINT(AST_Sequence, function(self, output) {
|
||||
self.expressions.forEach(function(node, index) {
|
||||
DEFPRINT(AST_Sequence, function(output) {
|
||||
this.expressions.forEach(function(node, index) {
|
||||
if (index > 0) {
|
||||
output.comma();
|
||||
if (output.should_break()) {
|
||||
@@ -1211,7 +1186,8 @@ function OutputStream(options) {
|
||||
node.print(output);
|
||||
});
|
||||
});
|
||||
DEFPRINT(AST_Dot, function(self, output) {
|
||||
DEFPRINT(AST_Dot, function(output) {
|
||||
var self = this;
|
||||
var expr = self.expression;
|
||||
expr.print(output);
|
||||
var prop = self.property;
|
||||
@@ -1221,7 +1197,7 @@ function OutputStream(options) {
|
||||
output.print_string(prop);
|
||||
output.print("]");
|
||||
} else {
|
||||
if (expr instanceof AST_Number && expr.getValue() >= 0) {
|
||||
if (expr instanceof AST_Number && expr.value >= 0) {
|
||||
if (!/[xa-f.)]/i.test(output.last())) {
|
||||
output.print(".");
|
||||
}
|
||||
@@ -1232,54 +1208,38 @@ function OutputStream(options) {
|
||||
output.print_name(prop);
|
||||
}
|
||||
});
|
||||
DEFPRINT(AST_Sub, function(self, output) {
|
||||
self.expression.print(output);
|
||||
DEFPRINT(AST_Sub, function(output) {
|
||||
this.expression.print(output);
|
||||
output.print("[");
|
||||
self.property.print(output);
|
||||
this.property.print(output);
|
||||
output.print("]");
|
||||
});
|
||||
DEFPRINT(AST_UnaryPrefix, function(self, output) {
|
||||
var op = self.operator;
|
||||
DEFPRINT(AST_UnaryPrefix, function(output) {
|
||||
var op = this.operator;
|
||||
var exp = this.expression;
|
||||
output.print(op);
|
||||
if (/^[a-z]/i.test(op)
|
||||
|| (/[+-]$/.test(op)
|
||||
&& self.expression instanceof AST_UnaryPrefix
|
||||
&& /^[+-]/.test(self.expression.operator))) {
|
||||
&& exp instanceof AST_UnaryPrefix
|
||||
&& /^[+-]/.test(exp.operator))) {
|
||||
output.space();
|
||||
}
|
||||
self.expression.print(output);
|
||||
exp.print(output);
|
||||
});
|
||||
DEFPRINT(AST_UnaryPostfix, function(self, output) {
|
||||
self.expression.print(output);
|
||||
output.print(self.operator);
|
||||
DEFPRINT(AST_UnaryPostfix, function(output) {
|
||||
this.expression.print(output);
|
||||
output.print(this.operator);
|
||||
});
|
||||
DEFPRINT(AST_Binary, function(self, output) {
|
||||
var op = self.operator;
|
||||
DEFPRINT(AST_Binary, function(output) {
|
||||
var self = this;
|
||||
self.left.print(output);
|
||||
if (op[0] == ">" /* ">>" ">>>" ">" ">=" */
|
||||
&& self.left instanceof AST_UnaryPostfix
|
||||
&& self.left.operator == "--") {
|
||||
// space is mandatory to avoid outputting -->
|
||||
output.print(" ");
|
||||
} else {
|
||||
// the space is optional depending on "beautify"
|
||||
output.space();
|
||||
}
|
||||
output.print(op);
|
||||
if ((op == "<" || op == "<<")
|
||||
&& self.right instanceof AST_UnaryPrefix
|
||||
&& self.right.operator == "!"
|
||||
&& self.right.expression instanceof AST_UnaryPrefix
|
||||
&& self.right.expression.operator == "--") {
|
||||
// space is mandatory to avoid outputting <!--
|
||||
output.print(" ");
|
||||
} else {
|
||||
// the space is optional depending on "beautify"
|
||||
output.space();
|
||||
}
|
||||
output.space();
|
||||
output.print(self.operator);
|
||||
output.space();
|
||||
self.right.print(output);
|
||||
});
|
||||
DEFPRINT(AST_Conditional, function(self, output) {
|
||||
DEFPRINT(AST_Conditional, function(output) {
|
||||
var self = this;
|
||||
self.condition.print(output);
|
||||
output.space();
|
||||
output.print("?");
|
||||
@@ -1291,10 +1251,10 @@ function OutputStream(options) {
|
||||
});
|
||||
|
||||
/* -----[ literals ]----- */
|
||||
DEFPRINT(AST_Array, function(self, output) {
|
||||
output.with_square(function() {
|
||||
var a = self.elements, len = a.length;
|
||||
if (len > 0) output.space();
|
||||
DEFPRINT(AST_Array, function(output) {
|
||||
var a = this.elements, len = a.length;
|
||||
output.with_square(len > 0 ? function() {
|
||||
output.space();
|
||||
a.forEach(function(exp, i) {
|
||||
if (i) output.comma();
|
||||
exp.print(output);
|
||||
@@ -1304,12 +1264,13 @@ function OutputStream(options) {
|
||||
if (i === len - 1 && exp instanceof AST_Hole)
|
||||
output.comma();
|
||||
});
|
||||
if (len > 0) output.space();
|
||||
});
|
||||
output.space();
|
||||
} : noop);
|
||||
});
|
||||
DEFPRINT(AST_Object, function(self, output) {
|
||||
if (self.properties.length > 0) output.with_block(function() {
|
||||
self.properties.forEach(function(prop, i) {
|
||||
DEFPRINT(AST_Object, function(output) {
|
||||
var props = this.properties;
|
||||
if (props.length > 0) output.with_block(function() {
|
||||
props.forEach(function(prop, i) {
|
||||
if (i) {
|
||||
output.print(",");
|
||||
output.newline();
|
||||
@@ -1319,7 +1280,7 @@ function OutputStream(options) {
|
||||
});
|
||||
output.newline();
|
||||
});
|
||||
else print_braced_empty(self, output);
|
||||
else print_braced_empty(this, output);
|
||||
});
|
||||
|
||||
function print_property_name(key, quote, output) {
|
||||
@@ -1338,53 +1299,61 @@ function OutputStream(options) {
|
||||
}
|
||||
}
|
||||
|
||||
DEFPRINT(AST_ObjectKeyVal, function(self, output) {
|
||||
DEFPRINT(AST_ObjectKeyVal, function(output) {
|
||||
var self = this;
|
||||
print_property_name(self.key, self.quote, output);
|
||||
output.colon();
|
||||
self.value.print(output);
|
||||
});
|
||||
AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, output) {
|
||||
output.print(type);
|
||||
output.space();
|
||||
print_property_name(this.key.name, this.quote, output);
|
||||
this.value._do_print(output, true);
|
||||
});
|
||||
DEFPRINT(AST_ObjectSetter, function(self, output) {
|
||||
self._print_getter_setter("set", output);
|
||||
});
|
||||
DEFPRINT(AST_ObjectGetter, function(self, output) {
|
||||
self._print_getter_setter("get", output);
|
||||
});
|
||||
DEFPRINT(AST_Symbol, function(self, output) {
|
||||
var def = self.definition();
|
||||
output.print_name(def && def.mangled_name || self.name);
|
||||
function print_accessor(type) {
|
||||
return function(output) {
|
||||
var self = this;
|
||||
output.print(type);
|
||||
output.space();
|
||||
print_property_name(self.key.name, self.quote, output);
|
||||
self.value._codegen(output, true);
|
||||
};
|
||||
}
|
||||
DEFPRINT(AST_ObjectGetter, print_accessor("get"));
|
||||
DEFPRINT(AST_ObjectSetter, print_accessor("set"));
|
||||
DEFPRINT(AST_Symbol, function(output) {
|
||||
var def = this.definition();
|
||||
output.print_name(def && def.mangled_name || this.name);
|
||||
});
|
||||
DEFPRINT(AST_Hole, noop);
|
||||
DEFPRINT(AST_This, function(self, output) {
|
||||
DEFPRINT(AST_This, function(output) {
|
||||
output.print("this");
|
||||
});
|
||||
DEFPRINT(AST_Constant, function(self, output) {
|
||||
output.print(self.getValue());
|
||||
DEFPRINT(AST_Constant, function(output) {
|
||||
output.print(this.value);
|
||||
});
|
||||
DEFPRINT(AST_String, function(self, output) {
|
||||
output.print_string(self.getValue(), self.quote, in_directive);
|
||||
DEFPRINT(AST_String, function(output) {
|
||||
output.print_string(this.value, this.quote);
|
||||
});
|
||||
DEFPRINT(AST_Number, function(self, output) {
|
||||
if (use_asm && self.start && self.start.raw != null) {
|
||||
output.print(self.start.raw);
|
||||
DEFPRINT(AST_Number, function(output) {
|
||||
var start = this.start;
|
||||
if (use_asm && start && start.raw != null) {
|
||||
output.print(start.raw);
|
||||
} else {
|
||||
output.print(make_num(self.getValue()));
|
||||
output.print(make_num(this.value));
|
||||
}
|
||||
});
|
||||
|
||||
DEFPRINT(AST_RegExp, function(self, output) {
|
||||
var regexp = self.getValue();
|
||||
DEFPRINT(AST_RegExp, function(output) {
|
||||
var regexp = this.value;
|
||||
var str = regexp.toString();
|
||||
var end = str.lastIndexOf("/");
|
||||
if (regexp.raw_source) {
|
||||
str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
|
||||
str = "/" + regexp.raw_source + str.slice(end);
|
||||
} else if (end == 1) {
|
||||
str = "/(?:)" + str.slice(end);
|
||||
} else if (str.indexOf("/", 1) < end) {
|
||||
str = "/" + str.slice(1, end).replace(/\\\\|[^/]?\//g, function(match) {
|
||||
return match[0] == "\\" ? match : match.slice(0, -1) + "\\/";
|
||||
}) + str.slice(end);
|
||||
}
|
||||
output.print(output.to_utf8(str).replace(/\\(?:\0(?![0-9])|[^\0])/g, function(seq) {
|
||||
switch (seq[1]) {
|
||||
output.print(output.to_utf8(str).replace(/\\(?:\0(?![0-9])|[^\0])/g, function(match) {
|
||||
switch (match[1]) {
|
||||
case "\n": return "\\n";
|
||||
case "\r": return "\\r";
|
||||
case "\t": return "\t";
|
||||
@@ -1394,7 +1363,7 @@ function OutputStream(options) {
|
||||
case "\x0B": return "\v";
|
||||
case "\u2028": return "\\u2028";
|
||||
case "\u2029": return "\\u2029";
|
||||
default: return seq;
|
||||
default: return match;
|
||||
}
|
||||
}).replace(/[\n\r\u2028\u2029]/g, function(c) {
|
||||
switch (c) {
|
||||
@@ -1405,7 +1374,7 @@ function OutputStream(options) {
|
||||
}
|
||||
}));
|
||||
var p = output.parent();
|
||||
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
|
||||
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === this)
|
||||
output.print(" ");
|
||||
});
|
||||
|
||||
@@ -1489,7 +1458,6 @@ function OutputStream(options) {
|
||||
AST_Node,
|
||||
// since the label symbol will mark it
|
||||
AST_LabeledStatement,
|
||||
AST_Toplevel,
|
||||
], noop);
|
||||
|
||||
// XXX: I'm not exactly sure if we need it for all of these nodes,
|
||||
@@ -1501,7 +1469,6 @@ function OutputStream(options) {
|
||||
AST_Constant,
|
||||
AST_Debugger,
|
||||
AST_Definitions,
|
||||
AST_Directive,
|
||||
AST_Finally,
|
||||
AST_Jump,
|
||||
AST_Lambda,
|
||||
|
||||
46
lib/parse.js
46
lib/parse.js
@@ -1,7 +1,7 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
https://github.com/mishoo/UglifyJS
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
@@ -44,11 +44,14 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with';
|
||||
var KEYWORDS_ATOM = 'false null true';
|
||||
var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface let long native package private protected public short static super synchronized this throws transient volatile yield'
|
||||
+ " " + KEYWORDS_ATOM + " " + KEYWORDS;
|
||||
var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case';
|
||||
var KEYWORDS = "break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with";
|
||||
var KEYWORDS_ATOM = "false null true";
|
||||
var RESERVED_WORDS = [
|
||||
"abstract boolean byte char class double enum export extends final float goto implements import int interface let long native package private protected public short static super synchronized this throws transient volatile yield",
|
||||
KEYWORDS_ATOM,
|
||||
KEYWORDS,
|
||||
].join(" ");
|
||||
var KEYWORDS_BEFORE_EXPRESSION = "return new delete throw else case";
|
||||
|
||||
KEYWORDS = makePredicate(KEYWORDS);
|
||||
RESERVED_WORDS = makePredicate(RESERVED_WORDS);
|
||||
@@ -133,14 +136,10 @@ function is_letter(code) {
|
||||
}
|
||||
|
||||
function is_surrogate_pair_head(code) {
|
||||
if (typeof code == "string")
|
||||
code = code.charCodeAt(0);
|
||||
return code >= 0xd800 && code <= 0xdbff;
|
||||
}
|
||||
|
||||
function is_surrogate_pair_tail(code) {
|
||||
if (typeof code == "string")
|
||||
code = code.charCodeAt(0);
|
||||
return code >= 0xdc00 && code <= 0xdfff;
|
||||
}
|
||||
|
||||
@@ -245,16 +244,16 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
if (signal_eof && !ch)
|
||||
throw EX_EOF;
|
||||
if (NEWLINE_CHARS[ch]) {
|
||||
S.newline_before = S.newline_before || !in_string;
|
||||
++S.line;
|
||||
S.col = 0;
|
||||
if (!in_string && ch == "\r" && peek() == "\n") {
|
||||
// treat a \r\n sequence as a single \n
|
||||
++S.pos;
|
||||
S.line++;
|
||||
if (!in_string) S.newline_before = true;
|
||||
if (ch == "\r" && peek() == "\n") {
|
||||
// treat `\r\n` as `\n`
|
||||
S.pos++;
|
||||
ch = "\n";
|
||||
}
|
||||
} else {
|
||||
++S.col;
|
||||
S.col++;
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
@@ -442,7 +441,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function() {
|
||||
var regex_allowed = S.regex_allowed;
|
||||
var i = find("*/", true);
|
||||
var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, '\n');
|
||||
var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, "\n");
|
||||
// update stream position
|
||||
forward(text.length /* doesn't count \r\n as 2 char while S.pos - i does */ + 2);
|
||||
S.comments_before.push(token("comment2", text, true));
|
||||
@@ -790,9 +789,10 @@ function parse($TEXT, options) {
|
||||
var dir = S.in_directives;
|
||||
var body = expression(true);
|
||||
if (dir) {
|
||||
var token = body.start;
|
||||
if (body instanceof AST_String && token.raw.indexOf("\\") == -1) {
|
||||
S.input.add_directive(token.value);
|
||||
if (body instanceof AST_String) {
|
||||
var value = body.start.raw.slice(1, -1);
|
||||
S.input.add_directive(value);
|
||||
body.value = value;
|
||||
} else {
|
||||
S.in_directives = dir = false;
|
||||
}
|
||||
@@ -951,7 +951,7 @@ function parse($TEXT, options) {
|
||||
if (!(stat instanceof AST_IterationStatement)) {
|
||||
// check for `continue` that refers to this label.
|
||||
// those should be reported as syntax errors.
|
||||
// https://github.com/mishoo/UglifyJS2/issues/287
|
||||
// https://github.com/mishoo/UglifyJS/issues/287
|
||||
label.references.forEach(function(ref) {
|
||||
if (ref instanceof AST_Continue) {
|
||||
ref = ref.label.start;
|
||||
@@ -1095,7 +1095,7 @@ function parse($TEXT, options) {
|
||||
|
||||
function switch_body_() {
|
||||
expect("{");
|
||||
var a = [], cur = null, branch = null, tmp;
|
||||
var a = [], branch, cur, default_branch, tmp;
|
||||
while (!is("punc", "}")) {
|
||||
if (is("eof")) expect_token("punc", "}");
|
||||
if (is("keyword", "case")) {
|
||||
@@ -1110,12 +1110,14 @@ function parse($TEXT, options) {
|
||||
expect(":");
|
||||
} else if (is("keyword", "default")) {
|
||||
if (branch) branch.end = prev();
|
||||
if (default_branch) croak("More than one default clause in switch statement");
|
||||
cur = [];
|
||||
branch = new AST_Default({
|
||||
start : (tmp = S.token, next(), expect(":"), tmp),
|
||||
body : cur
|
||||
});
|
||||
a.push(branch);
|
||||
default_branch = branch;
|
||||
} else {
|
||||
if (!cur) unexpected();
|
||||
cur.push(statement());
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
https://github.com/mishoo/UglifyJS
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
@@ -43,7 +43,8 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
function find_builtins(reserved) {
|
||||
var builtins = function() {
|
||||
var names = [];
|
||||
// NaN will be included due to Number.NaN
|
||||
[
|
||||
"null",
|
||||
@@ -67,19 +68,21 @@ function find_builtins(reserved) {
|
||||
].forEach(function(ctor) {
|
||||
Object.getOwnPropertyNames(ctor).map(add);
|
||||
if (ctor.prototype) {
|
||||
Object.getOwnPropertyNames(new ctor()).map(add);
|
||||
Object.getOwnPropertyNames(ctor.prototype).map(add);
|
||||
}
|
||||
});
|
||||
return makePredicate(names);
|
||||
|
||||
function add(name) {
|
||||
push_uniq(reserved, name);
|
||||
names.push(name);
|
||||
}
|
||||
}
|
||||
}();
|
||||
|
||||
function reserve_quoted_keys(ast, reserved) {
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_ObjectKeyVal && node.quote) {
|
||||
add(node.key);
|
||||
if (node instanceof AST_ObjectKeyVal) {
|
||||
if (node.quote) add(node.key);
|
||||
} else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, add);
|
||||
}
|
||||
@@ -91,17 +94,14 @@ function reserve_quoted_keys(ast, reserved) {
|
||||
}
|
||||
|
||||
function addStrings(node, add) {
|
||||
node.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_Sequence) {
|
||||
addStrings(node.tail_node(), add);
|
||||
} else if (node instanceof AST_String) {
|
||||
add(node.value);
|
||||
} else if (node instanceof AST_Conditional) {
|
||||
addStrings(node.consequent, add);
|
||||
addStrings(node.alternative, add);
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
if (node instanceof AST_Conditional) {
|
||||
addStrings(node.consequent, add);
|
||||
addStrings(node.alternative, add);
|
||||
} else if (node instanceof AST_Sequence) {
|
||||
addStrings(node.tail_node(), add);
|
||||
} else if (node instanceof AST_String) {
|
||||
add(node.value);
|
||||
}
|
||||
}
|
||||
|
||||
function mangle_properties(ast, options) {
|
||||
@@ -110,21 +110,21 @@ function mangle_properties(ast, options) {
|
||||
cache: null,
|
||||
debug: false,
|
||||
keep_quoted: false,
|
||||
only_cache: false,
|
||||
regex: null,
|
||||
reserved: null,
|
||||
}, true);
|
||||
|
||||
var reserved = options.reserved;
|
||||
if (!Array.isArray(reserved)) reserved = [];
|
||||
if (!options.builtins) find_builtins(reserved);
|
||||
var reserved = Object.create(options.builtins ? null : builtins);
|
||||
if (Array.isArray(options.reserved)) options.reserved.forEach(function(name) {
|
||||
reserved[name] = true;
|
||||
});
|
||||
|
||||
var cname = -1;
|
||||
var cache;
|
||||
if (options.cache) {
|
||||
cache = options.cache.props;
|
||||
cache.each(function(mangled_name) {
|
||||
push_uniq(reserved, mangled_name);
|
||||
cache.each(function(name) {
|
||||
reserved[name] = true;
|
||||
});
|
||||
} else {
|
||||
cache = new Dictionary();
|
||||
@@ -139,62 +139,92 @@ function mangle_properties(ast, options) {
|
||||
var debug_suffix;
|
||||
if (debug) debug_suffix = options.debug === true ? "" : options.debug;
|
||||
|
||||
var names_to_mangle = [];
|
||||
var unmangleable = [];
|
||||
var names_to_mangle = Object.create(null);
|
||||
var unmangleable = Object.create(reserved);
|
||||
|
||||
// step 1: find candidates to mangle
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_ObjectKeyVal) {
|
||||
if (node instanceof AST_Binary) {
|
||||
if (node.operator == "in") addStrings(node.left, add);
|
||||
} else if (node.TYPE == "Call") {
|
||||
var exp = node.expression;
|
||||
if (exp instanceof AST_Dot) switch (exp.property) {
|
||||
case "defineProperty":
|
||||
case "getOwnPropertyDescriptor":
|
||||
if (node.args.length < 2) break;
|
||||
exp = exp.expression;
|
||||
if (!(exp instanceof AST_SymbolRef)) break;
|
||||
if (exp.name != "Object") break;
|
||||
if (!exp.definition().undeclared) break;
|
||||
addStrings(node.args[1], add);
|
||||
break;
|
||||
case "hasOwnProperty":
|
||||
if (node.args.length < 1) break;
|
||||
addStrings(node.args[0], add);
|
||||
break;
|
||||
}
|
||||
} else if (node instanceof AST_Dot) {
|
||||
add(node.property);
|
||||
} else if (node instanceof AST_ObjectKeyVal) {
|
||||
add(node.key);
|
||||
} else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter, since KeyVal is handled above
|
||||
add(node.key.name);
|
||||
} else if (node instanceof AST_Dot) {
|
||||
add(node.property);
|
||||
} else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, add);
|
||||
} else if (node instanceof AST_Call
|
||||
&& node.expression.print_to_string() == "Object.defineProperty") {
|
||||
addStrings(node.args[1], add);
|
||||
}
|
||||
}));
|
||||
|
||||
// step 2: transform the tree, renaming properties
|
||||
return ast.transform(new TreeTransformer(function(node) {
|
||||
if (node instanceof AST_ObjectKeyVal) {
|
||||
// step 2: renaming properties
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_Binary) {
|
||||
if (node.operator == "in") mangleStrings(node.left);
|
||||
} else if (node.TYPE == "Call") {
|
||||
var exp = node.expression;
|
||||
if (exp instanceof AST_Dot) switch (exp.property) {
|
||||
case "defineProperty":
|
||||
case "getOwnPropertyDescriptor":
|
||||
if (node.args.length < 2) break;
|
||||
exp = exp.expression;
|
||||
if (!(exp instanceof AST_SymbolRef)) break;
|
||||
if (exp.name != "Object") break;
|
||||
if (!exp.definition().undeclared) break;
|
||||
mangleStrings(node.args[1]);
|
||||
break;
|
||||
case "hasOwnProperty":
|
||||
if (node.args.length < 1) break;
|
||||
mangleStrings(node.args[0]);
|
||||
break;
|
||||
}
|
||||
} else if (node instanceof AST_Dot) {
|
||||
node.property = mangle(node.property);
|
||||
} else if (node instanceof AST_ObjectKeyVal) {
|
||||
node.key = mangle(node.key);
|
||||
} else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter
|
||||
node.key.name = mangle(node.key.name);
|
||||
} else if (node instanceof AST_Dot) {
|
||||
node.property = mangle(node.property);
|
||||
} else if (!options.keep_quoted && node instanceof AST_Sub) {
|
||||
node.property = mangleStrings(node.property);
|
||||
} else if (node instanceof AST_Call
|
||||
&& node.expression.print_to_string() == "Object.defineProperty") {
|
||||
node.args[1] = mangleStrings(node.args[1]);
|
||||
} else if (node instanceof AST_Sub) {
|
||||
if (!options.keep_quoted) mangleStrings(node.property);
|
||||
}
|
||||
}));
|
||||
|
||||
// only function declarations after this line
|
||||
|
||||
function can_mangle(name) {
|
||||
if (unmangleable.indexOf(name) >= 0) return false;
|
||||
if (reserved.indexOf(name) >= 0) return false;
|
||||
if (options.only_cache) return cache.has(name);
|
||||
if (unmangleable[name]) return false;
|
||||
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function should_mangle(name) {
|
||||
if (reserved[name]) return false;
|
||||
if (regex && !regex.test(name)) return false;
|
||||
if (reserved.indexOf(name) >= 0) return false;
|
||||
return cache.has(name) || names_to_mangle.indexOf(name) >= 0;
|
||||
return cache.has(name) || names_to_mangle[name];
|
||||
}
|
||||
|
||||
function add(name) {
|
||||
if (can_mangle(name)) push_uniq(names_to_mangle, name);
|
||||
if (!should_mangle(name)) push_uniq(unmangleable, name);
|
||||
if (can_mangle(name)) names_to_mangle[name] = true;
|
||||
if (!should_mangle(name)) unmangleable[name] = true;
|
||||
}
|
||||
|
||||
function mangle(name) {
|
||||
@@ -218,17 +248,13 @@ function mangle_properties(ast, options) {
|
||||
}
|
||||
|
||||
function mangleStrings(node) {
|
||||
return node.transform(new TreeTransformer(function(node) {
|
||||
if (node instanceof AST_Sequence) {
|
||||
var last = node.expressions.length - 1;
|
||||
node.expressions[last] = mangleStrings(node.expressions[last]);
|
||||
} else if (node instanceof AST_String) {
|
||||
node.value = mangle(node.value);
|
||||
} else if (node instanceof AST_Conditional) {
|
||||
node.consequent = mangleStrings(node.consequent);
|
||||
node.alternative = mangleStrings(node.alternative);
|
||||
}
|
||||
return node;
|
||||
}));
|
||||
if (node instanceof AST_Sequence) {
|
||||
mangleStrings(node.expressions.tail_node());
|
||||
} else if (node instanceof AST_String) {
|
||||
node.value = mangle(node.value);
|
||||
} else if (node instanceof AST_Conditional) {
|
||||
mangleStrings(node.consequent);
|
||||
mangleStrings(node.alternative);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
137
lib/scope.js
137
lib/scope.js
@@ -1,7 +1,7 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
https://github.com/mishoo/UglifyJS
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
@@ -43,23 +43,21 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
function SymbolDef(scope, orig, init) {
|
||||
function SymbolDef(id, scope, orig, init) {
|
||||
this.eliminated = 0;
|
||||
this.global = false;
|
||||
this.id = id;
|
||||
this.init = init;
|
||||
this.lambda = orig instanceof AST_SymbolLambda;
|
||||
this.mangled_name = null;
|
||||
this.name = orig.name;
|
||||
this.orig = [ orig ];
|
||||
this.init = init;
|
||||
this.eliminated = 0;
|
||||
this.scope = scope;
|
||||
this.references = [];
|
||||
this.replaced = 0;
|
||||
this.global = false;
|
||||
this.mangled_name = null;
|
||||
this.scope = scope;
|
||||
this.undeclared = false;
|
||||
this.id = SymbolDef.next_id++;
|
||||
this.lambda = orig instanceof AST_SymbolLambda;
|
||||
}
|
||||
|
||||
SymbolDef.next_id = 1;
|
||||
|
||||
SymbolDef.prototype = {
|
||||
unmangleable: function(options) {
|
||||
return this.global && !options.toplevel
|
||||
@@ -98,8 +96,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
|
||||
// pass 1: setup scope chaining and handle definitions
|
||||
var self = this;
|
||||
var scope = self.parent_scope = null;
|
||||
var defun = null;
|
||||
var next_def_id = 0;
|
||||
var scope = self.parent_scope = null;
|
||||
var tw = new TreeWalker(function(node, descend) {
|
||||
if (node instanceof AST_Catch) {
|
||||
var save_scope = scope;
|
||||
@@ -151,6 +150,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
scope.def_variable(node).defun = defun;
|
||||
}
|
||||
});
|
||||
self.make_def = function(orig, init) {
|
||||
return new SymbolDef(++next_def_id, this, orig, init);
|
||||
};
|
||||
self.walk(tw);
|
||||
|
||||
// pass 2: find back references and eval
|
||||
@@ -162,17 +164,22 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
}
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
var name = node.name;
|
||||
if (name == "eval" && tw.parent() instanceof AST_Call) {
|
||||
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
|
||||
s.uses_eval = true;
|
||||
}
|
||||
}
|
||||
var sym = node.scope.find_variable(name);
|
||||
if (!sym) {
|
||||
sym = self.def_global(node);
|
||||
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
|
||||
sym.scope.uses_arguments = true;
|
||||
}
|
||||
if (name == "eval") {
|
||||
var parent = tw.parent();
|
||||
if (parent.TYPE == "Call" && parent.expression === node) {
|
||||
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
|
||||
s.uses_eval = true;
|
||||
}
|
||||
} else if (sym.undeclared) {
|
||||
self.uses_eval = true;
|
||||
}
|
||||
}
|
||||
node.thedef = sym;
|
||||
node.reference(options);
|
||||
return true;
|
||||
@@ -219,8 +226,14 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
var redef;
|
||||
while (redef = new_def.redefined()) new_def = redef;
|
||||
} else {
|
||||
new_def = self.globals.get(name) || scope.def_variable(node);
|
||||
new_def = self.globals.get(name);
|
||||
}
|
||||
if (new_def) {
|
||||
new_def.orig.push(node);
|
||||
} else {
|
||||
new_def = scope.def_variable(node);
|
||||
}
|
||||
old_def.defun = new_def.scope;
|
||||
old_def.orig.concat(old_def.references).forEach(function(node) {
|
||||
node.thedef = new_def;
|
||||
node.reference(options);
|
||||
@@ -235,7 +248,7 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
|
||||
if (globals.has(name)) {
|
||||
return globals.get(name);
|
||||
} else {
|
||||
var g = new SymbolDef(this, node);
|
||||
var g = this.make_def(node);
|
||||
g.undeclared = true;
|
||||
g.global = true;
|
||||
globals.set(name, g);
|
||||
@@ -243,24 +256,30 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
|
||||
}
|
||||
});
|
||||
|
||||
function init_scope_vars(scope, parent) {
|
||||
scope.cname = -1; // the current index for mangling functions/variables
|
||||
scope.enclosed = []; // variables from this or outer scope(s) that are referenced from this or inner scopes
|
||||
scope.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
|
||||
scope.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
||||
scope.parent_scope = parent; // the parent scope (null if this is the top level)
|
||||
scope.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
|
||||
scope.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
||||
if (parent) scope.make_def = parent.make_def; // top-level tracking of SymbolDef instances
|
||||
}
|
||||
|
||||
AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
|
||||
this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
||||
this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
|
||||
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
||||
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
|
||||
this.parent_scope = parent_scope; // the parent scope
|
||||
this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
|
||||
this.cname = -1; // the current index for mangling functions/variables
|
||||
init_scope_vars(this, parent_scope);
|
||||
});
|
||||
|
||||
AST_Lambda.DEFMETHOD("init_scope_vars", function() {
|
||||
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
|
||||
AST_Lambda.DEFMETHOD("init_scope_vars", function(parent_scope) {
|
||||
init_scope_vars(this, parent_scope);
|
||||
this.uses_arguments = false;
|
||||
this.def_variable(new AST_SymbolFunarg({
|
||||
name: "arguments",
|
||||
start: this.start,
|
||||
end: this.end
|
||||
end: this.end,
|
||||
}));
|
||||
return this;
|
||||
});
|
||||
|
||||
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
|
||||
@@ -300,7 +319,7 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
|
||||
def.orig.push(symbol);
|
||||
if (def.init instanceof AST_Function) def.init = init;
|
||||
} else {
|
||||
def = new SymbolDef(this, symbol, init);
|
||||
def = this.make_def(symbol, init);
|
||||
this.variables.set(symbol.name, def);
|
||||
def.global = !this.parent_scope;
|
||||
}
|
||||
@@ -316,7 +335,7 @@ AST_Toplevel.DEFMETHOD("resolve", return_this);
|
||||
function names_in_use(scope, options) {
|
||||
var names = scope.names_in_use;
|
||||
if (!names) {
|
||||
scope.names_in_use = names = Object.create(scope.mangled_names || null);
|
||||
scope.names_in_use = names = Object.create(null);
|
||||
scope.cname_holes = [];
|
||||
var cache = options.cache && options.cache.props;
|
||||
scope.enclosed.forEach(function(def) {
|
||||
@@ -350,7 +369,7 @@ function next_mangled_name(scope, options, def) {
|
||||
name = base54(holes[i]);
|
||||
if (names[name]) continue;
|
||||
holes.splice(i, 1);
|
||||
scope.names_in_use[name] = true;
|
||||
in_use[name] = true;
|
||||
return name;
|
||||
}
|
||||
while (true) {
|
||||
@@ -359,7 +378,7 @@ function next_mangled_name(scope, options, def) {
|
||||
if (!names[name]) break;
|
||||
holes.push(scope.cname);
|
||||
}
|
||||
scope.names_in_use[name] = true;
|
||||
in_use[name] = true;
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -371,18 +390,10 @@ AST_Symbol.DEFMETHOD("unmangleable", function(options) {
|
||||
// labels are always mangleable
|
||||
AST_Label.DEFMETHOD("unmangleable", return_false);
|
||||
|
||||
AST_Symbol.DEFMETHOD("unreferenced", function() {
|
||||
return !this.definition().references.length && !this.scope.pinned();
|
||||
});
|
||||
|
||||
AST_Symbol.DEFMETHOD("definition", function() {
|
||||
return this.thedef;
|
||||
});
|
||||
|
||||
AST_Symbol.DEFMETHOD("global", function() {
|
||||
return this.definition().global;
|
||||
});
|
||||
|
||||
function _default_mangler_options(options) {
|
||||
options = defaults(options, {
|
||||
eval : false,
|
||||
@@ -408,7 +419,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
||||
var lname = -1;
|
||||
|
||||
if (options.cache && options.cache.props) {
|
||||
var mangled_names = this.mangled_names = Object.create(null);
|
||||
var mangled_names = names_in_use(this, options);
|
||||
options.cache.props.each(function(mangled_name) {
|
||||
mangled_names[mangled_name] = true;
|
||||
});
|
||||
@@ -428,6 +439,11 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
||||
if (options.cache && node instanceof AST_Toplevel) {
|
||||
node.globals.each(mangle);
|
||||
}
|
||||
if (node instanceof AST_Defun && tw.has_directive("use asm")) {
|
||||
var sym = new AST_SymbolRef(node.name);
|
||||
sym.scope = node;
|
||||
sym.reference(options);
|
||||
}
|
||||
node.variables.each(function(def) {
|
||||
if (!defer_redef(def)) mangle(def);
|
||||
});
|
||||
@@ -475,7 +491,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
||||
|
||||
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
|
||||
var cache = options.cache && options.cache.props;
|
||||
var avoid = Object.create(null);
|
||||
var avoid = Object.create(RESERVED_WORDS);
|
||||
options.reserved.forEach(to_avoid);
|
||||
this.globals.each(add_def);
|
||||
this.walk(new TreeWalker(function(node) {
|
||||
@@ -512,7 +528,7 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
||||
var name;
|
||||
do {
|
||||
name = base54(cname++);
|
||||
} while (avoid[name] || RESERVED_WORDS[name]);
|
||||
} while (avoid[name]);
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -523,11 +539,8 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
||||
var redef = def.redefined();
|
||||
var name = redef ? redef.rename || redef.name : next_name();
|
||||
def.rename = name;
|
||||
def.orig.forEach(function(sym) {
|
||||
sym.name = name;
|
||||
});
|
||||
def.references.forEach(function(sym) {
|
||||
sym.name = name;
|
||||
def.orig.concat(def.references).forEach(function(sym) {
|
||||
if (sym.definition() === def) sym.name = name;
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -540,22 +553,24 @@ AST_Sequence.DEFMETHOD("tail_node", function() {
|
||||
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
|
||||
options = _default_mangler_options(options);
|
||||
base54.reset();
|
||||
var fn = AST_Symbol.prototype.add_source_map;
|
||||
try {
|
||||
AST_Node.prototype.print = function(stream, force_parens) {
|
||||
this._print(stream, force_parens);
|
||||
if (this instanceof AST_Symbol && !this.unmangleable(options)) {
|
||||
base54.consider(this.name, -1);
|
||||
} else if (options.properties) {
|
||||
if (this instanceof AST_Dot) {
|
||||
base54.consider(this.property, -1);
|
||||
} else if (this instanceof AST_Sub) {
|
||||
skip_string(this.property);
|
||||
}
|
||||
}
|
||||
AST_Symbol.prototype.add_source_map = function() {
|
||||
if (!this.unmangleable(options)) base54.consider(this.name, -1);
|
||||
};
|
||||
if (options.properties) {
|
||||
AST_Dot.prototype.add_source_map = function() {
|
||||
base54.consider(this.property, -1);
|
||||
};
|
||||
AST_Sub.prototype.add_source_map = function() {
|
||||
skip_string(this.property);
|
||||
};
|
||||
}
|
||||
base54.consider(this.print_to_string(), 1);
|
||||
} finally {
|
||||
AST_Node.prototype.print = AST_Node.prototype._print;
|
||||
AST_Symbol.prototype.add_source_map = fn;
|
||||
delete AST_Dot.prototype.add_source_map;
|
||||
delete AST_Sub.prototype.add_source_map;
|
||||
}
|
||||
base54.sort();
|
||||
|
||||
|
||||
191
lib/sourcemap.js
191
lib/sourcemap.js
@@ -1,7 +1,7 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
https://github.com/mishoo/UglifyJS
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
@@ -43,62 +43,149 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
// a small wrapper around fitzgen's source-map library
|
||||
function SourceMap(options) {
|
||||
options = defaults(options, {
|
||||
file: null,
|
||||
root: null,
|
||||
orig: null,
|
||||
orig_line_diff: 0,
|
||||
dest_line_diff: 0,
|
||||
}, true);
|
||||
var generator = new MOZ_SourceMap.SourceMapGenerator({
|
||||
file: options.file,
|
||||
sourceRoot: options.root
|
||||
});
|
||||
var maps = options.orig && Object.create(null);
|
||||
if (maps) for (var source in options.orig) {
|
||||
var map = new MOZ_SourceMap.SourceMapConsumer(options.orig[source]);
|
||||
if (Array.isArray(options.orig[source].sources)) {
|
||||
map._sources.toArray().forEach(function(source) {
|
||||
var sourceContent = map.sourceContentFor(source, true);
|
||||
if (sourceContent) generator.setSourceContent(source, sourceContent);
|
||||
});
|
||||
var vlq_char = characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
|
||||
var vlq_bits = vlq_char.reduce(function(map, ch, bits) {
|
||||
map[ch] = bits;
|
||||
return map;
|
||||
}, Object.create(null));
|
||||
|
||||
function vlq_decode(indices, str) {
|
||||
var value = 0;
|
||||
var shift = 0;
|
||||
for (var i = 0, j = 0; i < str.length; i++) {
|
||||
var bits = vlq_bits[str[i]];
|
||||
value += (bits & 31) << shift;
|
||||
if (bits & 32) {
|
||||
shift += 5;
|
||||
} else {
|
||||
indices[j++] += value & 1 ? 0x80000000 | -(value >> 1) : value >> 1;
|
||||
value = shift = 0;
|
||||
}
|
||||
maps[source] = map;
|
||||
}
|
||||
return {
|
||||
add: function(source, gen_line, gen_col, orig_line, orig_col, name) {
|
||||
var map = maps && maps[source];
|
||||
if (map) {
|
||||
var info = map.originalPositionFor({
|
||||
line: orig_line,
|
||||
column: orig_col
|
||||
return j;
|
||||
}
|
||||
|
||||
function vlq_encode(num) {
|
||||
var result = "";
|
||||
num = Math.abs(num) << 1 | num >>> 31;
|
||||
do {
|
||||
var bits = num & 31;
|
||||
if (num >>>= 5) bits |= 32;
|
||||
result += vlq_char[bits];
|
||||
} while (num);
|
||||
return result;
|
||||
}
|
||||
|
||||
function create_array_map() {
|
||||
var map = Object.create(null);
|
||||
var array = [];
|
||||
array.index = function(name) {
|
||||
if (!HOP(map, name)) {
|
||||
map[name] = array.length;
|
||||
array.push(name);
|
||||
}
|
||||
return map[name];
|
||||
};
|
||||
return array;
|
||||
}
|
||||
|
||||
function SourceMap(options) {
|
||||
var sources = create_array_map();
|
||||
var sources_content = options.includeSources && Object.create(null);
|
||||
var names = create_array_map();
|
||||
var mappings = "";
|
||||
if (options.orig) Object.keys(options.orig).forEach(function(name) {
|
||||
var map = options.orig[name];
|
||||
var indices = [ 0, 0, 1, 0, 0 ];
|
||||
options.orig[name] = {
|
||||
names: map.names,
|
||||
mappings: map.mappings.split(/;/).map(function(line) {
|
||||
indices[0] = 0;
|
||||
return line.split(/,/).map(function(segment) {
|
||||
return indices.slice(0, vlq_decode(indices, segment));
|
||||
});
|
||||
if (info.source === null) return;
|
||||
source = info.source;
|
||||
orig_line = info.line;
|
||||
orig_col = info.column;
|
||||
name = info.name || name;
|
||||
}
|
||||
generator.addMapping({
|
||||
name: name,
|
||||
source: source,
|
||||
generated: {
|
||||
line: gen_line + options.dest_line_diff,
|
||||
column: gen_col
|
||||
},
|
||||
original: {
|
||||
line: orig_line + options.orig_line_diff,
|
||||
column: orig_col
|
||||
}),
|
||||
sources: map.sources,
|
||||
};
|
||||
if (!sources_content || !map.sourcesContent) return;
|
||||
for (var i = 0; i < map.sources.length; i++) {
|
||||
var content = map.sourcesContent[i];
|
||||
if (content) sources_content[map.sources[i]] = content;
|
||||
}
|
||||
});
|
||||
var prev_source;
|
||||
var generated_line = 1;
|
||||
var generated_column = 0;
|
||||
var source_index = 0;
|
||||
var original_line = 1;
|
||||
var original_column = 0;
|
||||
var name_index = 0;
|
||||
return {
|
||||
add: options.orig ? function(source, gen_line, gen_col, orig_line, orig_col, name) {
|
||||
var map = options.orig[source];
|
||||
if (map) {
|
||||
var segments = map.mappings[orig_line - 1];
|
||||
if (!segments) return;
|
||||
var indices;
|
||||
for (var i = 0; i < segments.length; i++) {
|
||||
var col = segments[i][0];
|
||||
if (orig_col >= col) indices = segments[i];
|
||||
if (orig_col <= col) break;
|
||||
}
|
||||
});
|
||||
},
|
||||
get: function() {
|
||||
return generator;
|
||||
},
|
||||
if (!indices || indices.length < 4) {
|
||||
source = null;
|
||||
} else {
|
||||
source = map.sources[indices[1]];
|
||||
orig_line = indices[2];
|
||||
orig_col = indices[3];
|
||||
if (indices.length > 4) name = map.names[indices[4]];
|
||||
}
|
||||
}
|
||||
add(source, gen_line, gen_col, orig_line, orig_col, name);
|
||||
} : add,
|
||||
setSourceContent: sources_content ? function(source, content) {
|
||||
sources_content[source] = content;
|
||||
} : noop,
|
||||
toString: function() {
|
||||
return JSON.stringify(generator.toJSON());
|
||||
return JSON.stringify({
|
||||
version: 3,
|
||||
file: options.filename || undefined,
|
||||
sourceRoot: options.root || undefined,
|
||||
sources: sources,
|
||||
sourcesContent: sources_content ? sources.map(function(source) {
|
||||
return sources_content[source] || null;
|
||||
}) : undefined,
|
||||
names: names,
|
||||
mappings: mappings,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function add(source, gen_line, gen_col, orig_line, orig_col, name) {
|
||||
if (prev_source == null && source == null) return;
|
||||
prev_source = source;
|
||||
if (generated_line < gen_line) {
|
||||
generated_column = 0;
|
||||
do {
|
||||
mappings += ";";
|
||||
} while (++generated_line < gen_line);
|
||||
} else if (mappings) {
|
||||
mappings += ",";
|
||||
}
|
||||
mappings += vlq_encode(gen_col - generated_column);
|
||||
generated_column = gen_col;
|
||||
if (source == null) return;
|
||||
var src_idx = sources.index(source);
|
||||
mappings += vlq_encode(src_idx - source_index);
|
||||
source_index = src_idx;
|
||||
mappings += vlq_encode(orig_line - original_line);
|
||||
original_line = orig_line;
|
||||
mappings += vlq_encode(orig_col - original_column);
|
||||
original_column = orig_col;
|
||||
if (options.names && name != null) {
|
||||
var name_idx = names.index(name);
|
||||
mappings += vlq_encode(name_idx - name_index);
|
||||
name_index = name_idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
https://github.com/mishoo/UglifyJS
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
@@ -52,7 +52,7 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
|
||||
(function(DEF) {
|
||||
function do_list(list, tw) {
|
||||
return MAP(list, function(node) {
|
||||
return List(list, function(node) {
|
||||
return node.transform(tw, true);
|
||||
});
|
||||
}
|
||||
|
||||
81
lib/utils.js
81
lib/utils.js
@@ -1,7 +1,7 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
https://github.com/mishoo/UglifyJS
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
@@ -87,15 +87,13 @@ DefaultsError.prototype.name = "DefaultsError";
|
||||
configure_error_stack(DefaultsError);
|
||||
|
||||
function defaults(args, defs, croak) {
|
||||
if (args === true) args = {};
|
||||
var ret = args || {};
|
||||
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
|
||||
throw new DefaultsError("`" + i + "` is not a supported option", defs);
|
||||
if (croak) for (var i in args) {
|
||||
if (HOP(args, i) && !HOP(defs, i)) throw new DefaultsError("`" + i + "` is not a supported option", defs);
|
||||
}
|
||||
for (var i in defs) if (HOP(defs, i)) {
|
||||
ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
|
||||
for (var i in args) {
|
||||
if (HOP(args, i)) defs[i] = args[i];
|
||||
}
|
||||
return ret;
|
||||
return defs;
|
||||
}
|
||||
|
||||
function merge(obj, ext) {
|
||||
@@ -113,50 +111,31 @@ function return_true() { return true; }
|
||||
function return_this() { return this; }
|
||||
function return_null() { return null; }
|
||||
|
||||
var MAP = (function() {
|
||||
function MAP(a, f, backwards) {
|
||||
var ret = [], top = [], i;
|
||||
function doit() {
|
||||
var List = (function() {
|
||||
function List(a, f) {
|
||||
var ret = [];
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
var val = f(a[i], i);
|
||||
var is_last = val instanceof Last;
|
||||
if (is_last) val = val.v;
|
||||
if (val instanceof AtTop) {
|
||||
val = val.v;
|
||||
if (val instanceof Splice) {
|
||||
top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
|
||||
} else {
|
||||
top.push(val);
|
||||
}
|
||||
} else if (val !== skip) {
|
||||
if (val instanceof Splice) {
|
||||
ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
|
||||
} else {
|
||||
ret.push(val);
|
||||
}
|
||||
}
|
||||
return is_last;
|
||||
}
|
||||
if (Array.isArray(a)) {
|
||||
if (backwards) {
|
||||
for (i = a.length; --i >= 0;) if (doit()) break;
|
||||
ret.reverse();
|
||||
top.reverse();
|
||||
if (val === skip) continue;
|
||||
if (val instanceof Splice) {
|
||||
ret.push.apply(ret, val.v);
|
||||
} else {
|
||||
for (i = 0; i < a.length; ++i) if (doit()) break;
|
||||
ret.push(val);
|
||||
}
|
||||
} else {
|
||||
for (i in a) if (HOP(a, i)) if (doit()) break;
|
||||
}
|
||||
return top.concat(ret);
|
||||
return ret;
|
||||
}
|
||||
MAP.at_top = function(val) { return new AtTop(val) };
|
||||
MAP.splice = function(val) { return new Splice(val) };
|
||||
MAP.last = function(val) { return new Last(val) };
|
||||
var skip = MAP.skip = {};
|
||||
function AtTop(val) { this.v = val }
|
||||
function Splice(val) { this.v = val }
|
||||
function Last(val) { this.v = val }
|
||||
return MAP;
|
||||
List.is_op = function(val) {
|
||||
return val === skip || val instanceof Splice;
|
||||
};
|
||||
List.splice = function(val) {
|
||||
return new Splice(val);
|
||||
};
|
||||
var skip = List.skip = {};
|
||||
function Splice(val) {
|
||||
this.v = val;
|
||||
}
|
||||
return List;
|
||||
})();
|
||||
|
||||
function push_uniq(array, el) {
|
||||
@@ -185,7 +164,7 @@ function makePredicate(words) {
|
||||
|
||||
function all(array, predicate) {
|
||||
for (var i = array.length; --i >= 0;)
|
||||
if (!predicate(array[i]))
|
||||
if (!predicate(array[i], i))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -217,6 +196,12 @@ Dictionary.prototype = {
|
||||
return this;
|
||||
},
|
||||
has: function(key) { return ("$" + key) in this._values },
|
||||
all: function(predicate) {
|
||||
for (var i in this._values)
|
||||
if (!predicate(this._values[i], i.substr(1)))
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
each: function(f) {
|
||||
for (var i in this._values)
|
||||
f(this._values[i], i.substr(1));
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.7.1",
|
||||
"version": "3.11.0",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
@@ -11,7 +11,7 @@
|
||||
"Alex Lam <alexlamsl@gmail.com>",
|
||||
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
|
||||
],
|
||||
"repository": "mishoo/UglifyJS2",
|
||||
"repository": "mishoo/UglifyJS",
|
||||
"main": "tools/node.js",
|
||||
"bin": {
|
||||
"uglifyjs": "bin/uglifyjs"
|
||||
@@ -22,10 +22,6 @@
|
||||
"tools",
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"commander": "~2.20.3",
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"acorn": "~7.1.0",
|
||||
"semver": "~6.3.0"
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
|
||||
var createHash = require("crypto").createHash;
|
||||
var fetch = require("./fetch");
|
||||
var fork = require("child_process").fork;
|
||||
var spawn = require("child_process").spawn;
|
||||
var zlib = require("zlib");
|
||||
var args = process.argv.slice(2);
|
||||
if (!args.length) {
|
||||
args.push("-mc");
|
||||
}
|
||||
if (!args.length) args.push("-mc");
|
||||
args.unshift("bin/uglifyjs");
|
||||
args.push("--timings");
|
||||
var urls = [
|
||||
"https://code.jquery.com/jquery-3.4.1.js",
|
||||
@@ -70,18 +69,20 @@ urls.forEach(function(url) {
|
||||
};
|
||||
fetch(url, function(err, res) {
|
||||
if (err) throw err;
|
||||
var uglifyjs = fork("bin/uglifyjs", args, { silent: true });
|
||||
var uglifyjs = spawn(process.argv[0], args, { silent: true });
|
||||
res.on("data", function(data) {
|
||||
results[url].input += data.length;
|
||||
}).pipe(uglifyjs.stdin);
|
||||
var sha1 = createHash("sha1");
|
||||
uglifyjs.stdout.on("data", function(data) {
|
||||
results[url].output += data.length;
|
||||
}).pipe(zlib.createGzip({
|
||||
level: zlib.Z_BEST_COMPRESSION
|
||||
})).on("data", function(data) {
|
||||
results[url].gzip += data.length;
|
||||
}).pipe(createHash("sha1")).on("data", function(data) {
|
||||
results[url].sha1 = data.toString("hex");
|
||||
sha1.update(data);
|
||||
}).on("end", function() {
|
||||
results[url].sha1 = sha1.digest("hex");
|
||||
done();
|
||||
});
|
||||
uglifyjs.stderr.setEncoding("utf8");
|
||||
|
||||
@@ -63,7 +63,7 @@ function make_code(ast, options) {
|
||||
|
||||
function parse_test(file) {
|
||||
var script = fs.readFileSync(file, "utf8");
|
||||
// TODO try/catch can be removed after fixing https://github.com/mishoo/UglifyJS2/issues/348
|
||||
// TODO try/catch can be removed after fixing https://github.com/mishoo/UglifyJS/issues/348
|
||||
try {
|
||||
var ast = U.parse(script, {
|
||||
filename: file
|
||||
@@ -188,6 +188,7 @@ function reminify(orig_options, input_code, input_formatted, stdout) {
|
||||
}
|
||||
});
|
||||
var options_formatted = JSON.stringify(options, null, 4);
|
||||
options.validate = true;
|
||||
var result = U.minify(input_code, options);
|
||||
if (result.error) {
|
||||
log([
|
||||
@@ -207,8 +208,9 @@ function reminify(orig_options, input_code, input_formatted, stdout) {
|
||||
});
|
||||
return false;
|
||||
} else {
|
||||
var expected = stdout[options.toplevel ? 1 : 0];
|
||||
var actual = run_code(result.code, options.toplevel);
|
||||
var toplevel = sandbox.has_toplevel(options);
|
||||
var expected = stdout[toplevel ? 1 : 0];
|
||||
var actual = run_code(result.code, toplevel);
|
||||
if (typeof expected != "string" && typeof actual != "string" && expected.name == actual.name) {
|
||||
actual = expected;
|
||||
}
|
||||
@@ -250,6 +252,7 @@ function run_code(code, toplevel) {
|
||||
|
||||
function test_case(test) {
|
||||
log(" Running test [{name}]", { name: test.name });
|
||||
U.AST_Node.enable_validation();
|
||||
var output_options = test.beautify || {};
|
||||
var expect;
|
||||
if (test.expect) {
|
||||
@@ -266,6 +269,7 @@ function test_case(test) {
|
||||
quote_style: 3,
|
||||
});
|
||||
try {
|
||||
input.validate_ast();
|
||||
U.parse(input_code);
|
||||
} catch (ex) {
|
||||
log([
|
||||
@@ -308,12 +312,10 @@ function test_case(test) {
|
||||
if (test.mangle) {
|
||||
output.compute_char_frequency(test.mangle);
|
||||
output.mangle_names(test.mangle);
|
||||
if (test.mangle.properties) {
|
||||
output = U.mangle_properties(output, test.mangle.properties);
|
||||
}
|
||||
if (test.mangle.properties) U.mangle_properties(output, test.mangle.properties);
|
||||
}
|
||||
output = make_code(output, output_options);
|
||||
if (expect != output) {
|
||||
var output_code = make_code(output, output_options);
|
||||
if (expect != output_code) {
|
||||
log([
|
||||
"!!! failed",
|
||||
"---INPUT---",
|
||||
@@ -326,14 +328,15 @@ function test_case(test) {
|
||||
"",
|
||||
].join("\n"), {
|
||||
input: input_formatted,
|
||||
output: output,
|
||||
output: output_code,
|
||||
expected: expect
|
||||
});
|
||||
return false;
|
||||
}
|
||||
// expect == output
|
||||
try {
|
||||
U.parse(output);
|
||||
output.validate_ast();
|
||||
U.parse(output_code);
|
||||
} catch (ex) {
|
||||
log([
|
||||
"!!! Test matched expected result but cannot parse output",
|
||||
@@ -347,7 +350,7 @@ function test_case(test) {
|
||||
"",
|
||||
].join("\n"), {
|
||||
input: input_formatted,
|
||||
output: output,
|
||||
output: output_code,
|
||||
error: ex,
|
||||
});
|
||||
return false;
|
||||
@@ -378,7 +381,10 @@ function test_case(test) {
|
||||
}
|
||||
if (test.expect_stdout && (!test.node_version || semver.satisfies(process.version, test.node_version))) {
|
||||
var stdout = [ run_code(input_code), run_code(input_code, true) ];
|
||||
var toplevel = test.options.toplevel;
|
||||
var toplevel = sandbox.has_toplevel({
|
||||
compress: test.options,
|
||||
mangle: test.mangle
|
||||
});
|
||||
var actual = stdout[toplevel ? 1 : 0];
|
||||
if (test.expect_stdout === true) {
|
||||
test.expect_stdout = actual;
|
||||
@@ -403,7 +409,7 @@ function test_case(test) {
|
||||
});
|
||||
return false;
|
||||
}
|
||||
actual = run_code(output, toplevel);
|
||||
actual = run_code(output_code, toplevel);
|
||||
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
|
||||
log([
|
||||
"!!! failed",
|
||||
|
||||
@@ -243,20 +243,18 @@ issue_3273: {
|
||||
arguments: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
(function(a) {
|
||||
console.log(arguments[0], a);
|
||||
arguments[0]++;
|
||||
console.log(arguments[0], a);
|
||||
}
|
||||
f(0);
|
||||
})(0);
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
(function(a) {
|
||||
console.log(a, a);
|
||||
a++;
|
||||
console.log(a, a);
|
||||
}
|
||||
f(0);
|
||||
})(0);
|
||||
}
|
||||
expect_stdout: [
|
||||
"0 0",
|
||||
@@ -264,26 +262,43 @@ issue_3273: {
|
||||
]
|
||||
}
|
||||
|
||||
issue_3273_no_call_arg: {
|
||||
options = {
|
||||
arguments: true,
|
||||
}
|
||||
input: {
|
||||
(function(a) {
|
||||
arguments[0] = "FAIL";
|
||||
console.log(a);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(a) {
|
||||
arguments[0] = "FAIL";
|
||||
console.log(a);
|
||||
})();
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_3273_reduce_vars: {
|
||||
options = {
|
||||
arguments: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
(function(a) {
|
||||
console.log(arguments[0], a);
|
||||
arguments[0]++;
|
||||
console.log(arguments[0], a);
|
||||
}
|
||||
f(0);
|
||||
})(0);
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
(function(a) {
|
||||
console.log(a, a);
|
||||
a++;
|
||||
console.log(a, a);
|
||||
}
|
||||
f(0);
|
||||
})(0);
|
||||
}
|
||||
expect_stdout: [
|
||||
"0 0",
|
||||
@@ -296,22 +311,20 @@ issue_3273_local_strict: {
|
||||
arguments: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
(function(a) {
|
||||
"use strict";
|
||||
console.log(arguments[0], a);
|
||||
arguments[0]++;
|
||||
console.log(arguments[0], a);
|
||||
}
|
||||
f(0);
|
||||
})(0);
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
(function(a) {
|
||||
"use strict";
|
||||
console.log(arguments[0], a);
|
||||
arguments[0]++;
|
||||
console.log(arguments[0], a);
|
||||
}
|
||||
f(0);
|
||||
})(0);
|
||||
}
|
||||
expect_stdout: [
|
||||
"0 0",
|
||||
@@ -325,22 +338,20 @@ issue_3273_local_strict_reduce_vars: {
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
(function(a) {
|
||||
"use strict";
|
||||
console.log(arguments[0], a);
|
||||
arguments[0]++;
|
||||
console.log(arguments[0], a);
|
||||
}
|
||||
f(0);
|
||||
})(0);
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
(function(a) {
|
||||
"use strict";
|
||||
console.log(arguments[0], a);
|
||||
arguments[0]++;
|
||||
console.log(arguments[0], a);
|
||||
}
|
||||
f(0);
|
||||
})(0);
|
||||
}
|
||||
expect_stdout: [
|
||||
"0 0",
|
||||
@@ -354,21 +365,19 @@ issue_3273_global_strict: {
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function f(a) {
|
||||
(function(a) {
|
||||
console.log(arguments[0], a);
|
||||
arguments[0]++;
|
||||
console.log(arguments[0], a);
|
||||
}
|
||||
f(0);
|
||||
})(0);
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function f(a) {
|
||||
(function(a) {
|
||||
console.log(arguments[0], a);
|
||||
arguments[0]++;
|
||||
console.log(arguments[0], a);
|
||||
}
|
||||
f(0);
|
||||
})(0);
|
||||
}
|
||||
expect_stdout: [
|
||||
"0 0",
|
||||
@@ -383,21 +392,19 @@ issue_3273_global_strict_reduce_vars: {
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function f(a) {
|
||||
(function(a) {
|
||||
console.log(arguments[0], a);
|
||||
arguments[0]++;
|
||||
console.log(arguments[0], a);
|
||||
}
|
||||
f(0);
|
||||
})(0);
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function f(a) {
|
||||
(function(a) {
|
||||
console.log(arguments[0], a);
|
||||
arguments[0]++;
|
||||
console.log(arguments[0], a);
|
||||
}
|
||||
f(0);
|
||||
})(0);
|
||||
}
|
||||
expect_stdout: [
|
||||
"0 0",
|
||||
|
||||
@@ -16,6 +16,7 @@ holes_and_undefined: {
|
||||
constant_join: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
strings: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
@@ -65,6 +66,7 @@ constant_join: {
|
||||
constant_join_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
strings: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
@@ -94,9 +96,11 @@ constant_join_2: {
|
||||
constant_join_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
strings: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var foo, bar, baz;
|
||||
var a = [ null ].join();
|
||||
var b = [ , ].join();
|
||||
var c = [ , 1, , 3 ].join();
|
||||
@@ -111,6 +115,7 @@ constant_join_3: {
|
||||
var l = [ foo, bar + "baz" ].join("");
|
||||
}
|
||||
expect: {
|
||||
var foo, bar, baz;
|
||||
var a = "";
|
||||
var b = "";
|
||||
var c = ",1,,3";
|
||||
|
||||
@@ -91,12 +91,11 @@ asm_mixed: {
|
||||
function no_asm_GeometricMean(stdlib, foreign, buffer) {
|
||||
function logSum(start, end) {
|
||||
start |= 0, end |= 0;
|
||||
var sum = 0, p = 0, q = 0;
|
||||
for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
|
||||
for (var sum = 0, p = 0, q = 0, p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
|
||||
return +sum;
|
||||
}
|
||||
function geometricMean(start, end) {
|
||||
return start |= 0, end |= 0, +exp(logSum(start, end) / (end - start | 0));
|
||||
return start |= 0, end |= 0, +exp(+logSum(start, end) / (end - start | 0));
|
||||
}
|
||||
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
|
||||
return { geometricMean: geometricMean };
|
||||
@@ -166,3 +165,69 @@ asm_nested_functions: {
|
||||
}
|
||||
expect_exact: '0;function a(){"use asm";0.0}0;function b(){0;function c(){"use asm";0.0}0;function d(){0}0}0;'
|
||||
}
|
||||
|
||||
issue_3636_1: {
|
||||
mangle = {}
|
||||
input: {
|
||||
function n(stdlib, foreign, buffer) {
|
||||
"use asm";
|
||||
function add(x, y) {
|
||||
x = x | 0;
|
||||
y = y | 0;
|
||||
return x + y | 0;
|
||||
}
|
||||
return {
|
||||
add: add
|
||||
};
|
||||
}
|
||||
console.log(new n().add("foo", 42));
|
||||
}
|
||||
expect: {
|
||||
function n(o, e, u) {
|
||||
"use asm";
|
||||
function d(n, o) {
|
||||
n = n | 0;
|
||||
o = o | 0;
|
||||
return n + o | 0;
|
||||
}
|
||||
return {
|
||||
add: d
|
||||
};
|
||||
}
|
||||
console.log(new n().add("foo", 42));
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_3636_2: {
|
||||
mangle = {}
|
||||
input: {
|
||||
var n = function(stdlib, foreign, buffer) {
|
||||
"use asm";
|
||||
function add(x, y) {
|
||||
x = x | 0;
|
||||
y = y | 0;
|
||||
return x + y | 0;
|
||||
}
|
||||
return {
|
||||
add: add
|
||||
};
|
||||
};
|
||||
console.log(new n().add("foo", 42));
|
||||
}
|
||||
expect: {
|
||||
var n = function(n, o, e) {
|
||||
"use asm";
|
||||
function r(n, o) {
|
||||
n = n | 0;
|
||||
o = o | 0;
|
||||
return n + o | 0;
|
||||
}
|
||||
return {
|
||||
add: r
|
||||
};
|
||||
};
|
||||
console.log(new n().add("foo", 42));
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
@@ -407,3 +407,57 @@ issue_3429_2: {
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_3949_1: {
|
||||
options = {
|
||||
assignments: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a = 42;
|
||||
function f() {
|
||||
var b = a;
|
||||
b = b >> 2;
|
||||
return 100 + b;
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect: {
|
||||
var a = 42;
|
||||
function f() {
|
||||
var b = a;
|
||||
b >>= 2;
|
||||
return 100 + b;
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect_stdout: "110"
|
||||
}
|
||||
|
||||
issue_3949_2: {
|
||||
options = {
|
||||
assignments: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a = 42;
|
||||
function f() {
|
||||
var b = a;
|
||||
b = 5 & b;
|
||||
return 100 + b;
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect: {
|
||||
var a = 42;
|
||||
function f() {
|
||||
var b = a;
|
||||
b &= 5;
|
||||
return 100 + b;
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect_stdout: "100"
|
||||
}
|
||||
@@ -86,3 +86,70 @@ issue_3465_3: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2737_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(bar) {
|
||||
for (;bar();) break;
|
||||
})(function qux() {
|
||||
return console.log("PASS"), qux;
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
(function(bar) {
|
||||
for (;bar();) break;
|
||||
})(function() {
|
||||
return console.log("PASS"), 1;
|
||||
});
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3658: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f() {
|
||||
console || f();
|
||||
return "PASS";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function f() {
|
||||
console || f();
|
||||
return "PASS";
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3690: {
|
||||
options = {
|
||||
booleans: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
return function() {
|
||||
return a = [ this ];
|
||||
}() ? "PASS" : "FAIL";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
return function() {
|
||||
return 1;
|
||||
}() ? "PASS" : "FAIL";
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -33,10 +33,10 @@ unsafe_comps: {
|
||||
}
|
||||
expect: {
|
||||
var obj1, obj2;
|
||||
obj2 < obj1 ? g1() : f1();
|
||||
obj1 < obj2 ? f2() : g2();
|
||||
obj1 < obj2 ? g3() : f3();
|
||||
obj2 < obj1 ? f4() : g4();
|
||||
(obj2 < obj1 ? g1 : f1)();
|
||||
(obj1 < obj2 ? f2 : g2)();
|
||||
(obj1 < obj2 ? g3 : f3)();
|
||||
(obj2 < obj1 ? f4 : g4)();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +93,59 @@ self_comparison_2: {
|
||||
expect_stdout: "false true"
|
||||
}
|
||||
|
||||
self_comparison_3: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
function f() {
|
||||
var b = a;
|
||||
a = null;
|
||||
return b;
|
||||
}
|
||||
for (var i = 0; i < 2; i++)
|
||||
console.log(f() === f());
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
function f() {
|
||||
var b = a;
|
||||
a = null;
|
||||
return b;
|
||||
}
|
||||
for (var i = 0; i < 2; i++)
|
||||
console.log(f() === f());
|
||||
}
|
||||
expect_stdout: [
|
||||
"false",
|
||||
"true",
|
||||
]
|
||||
}
|
||||
|
||||
self_comparison_4: {
|
||||
options = {
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
console.log(o == o, o != o);
|
||||
console.log(o === o, o !== o);
|
||||
}
|
||||
expect: {
|
||||
console.log(!0, !1);
|
||||
console.log(!0, !1);
|
||||
}
|
||||
expect_stdout: [
|
||||
"true false",
|
||||
"true false",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2857_1: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
|
||||
@@ -26,7 +26,9 @@ concat_1: {
|
||||
}
|
||||
|
||||
concat_2: {
|
||||
options = {}
|
||||
options = {
|
||||
strings: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
1 + (2 + 3),
|
||||
@@ -55,7 +57,9 @@ concat_2: {
|
||||
}
|
||||
|
||||
concat_3: {
|
||||
options = {}
|
||||
options = {
|
||||
strings: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
1 + 2 + (3 + 4 + 5),
|
||||
@@ -84,7 +88,9 @@ concat_3: {
|
||||
}
|
||||
|
||||
concat_4: {
|
||||
options = {}
|
||||
options = {
|
||||
strings: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
1 + "2" + (3 + 4 + 5),
|
||||
@@ -113,7 +119,9 @@ concat_4: {
|
||||
}
|
||||
|
||||
concat_5: {
|
||||
options = {}
|
||||
options = {
|
||||
strings: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
"1" + 2 + (3 + 4 + 5),
|
||||
@@ -142,7 +150,9 @@ concat_5: {
|
||||
}
|
||||
|
||||
concat_6: {
|
||||
options = {}
|
||||
options = {
|
||||
strings: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
"1" + "2" + (3 + 4 + 5),
|
||||
@@ -171,6 +181,9 @@ concat_6: {
|
||||
}
|
||||
|
||||
concat_7: {
|
||||
options = {
|
||||
strings: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
"" + 1,
|
||||
@@ -197,6 +210,9 @@ concat_7: {
|
||||
}
|
||||
|
||||
concat_8: {
|
||||
options = {
|
||||
strings: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
1 + "",
|
||||
@@ -221,3 +237,55 @@ concat_8: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
concat_9: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
strings: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = "foo";
|
||||
console.log(
|
||||
12 + (34 + a),
|
||||
null + (34 + a),
|
||||
12 + (null + a),
|
||||
false + (34 + a),
|
||||
12 + (false + a),
|
||||
"bar" + (34 + a),
|
||||
12 + ("bar" + a)
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var a = "foo";
|
||||
console.log(
|
||||
"1234" + a,
|
||||
"null34" + a,
|
||||
"12null" + a,
|
||||
!1 + (34 + a),
|
||||
12 + (!1 + a),
|
||||
"bar34" + a,
|
||||
"12bar" + a
|
||||
);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_3689: {
|
||||
options = {
|
||||
strings: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
return a + ("" + (a[0] = 0));
|
||||
}([]));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
return a + ("" + (a[0] = 0));
|
||||
}([]));
|
||||
}
|
||||
expect_stdout: "00"
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ ifs_2: {
|
||||
}
|
||||
expect: {
|
||||
foo ? x() : bar ? y() : baz && z();
|
||||
foo ? x() : bar ? y() : baz ? z() : t();
|
||||
(foo ? x : bar ? y : baz ? z : t)();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,11 +289,50 @@ cond_5: {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
some_condition() && some_other_condition() ? do_something() : alternate();
|
||||
(some_condition() && some_other_condition() ? do_something : alternate)();
|
||||
some_condition() && some_other_condition() && do_something();
|
||||
}
|
||||
}
|
||||
|
||||
cond_6: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
x ? a : b;
|
||||
x ? a : a;
|
||||
|
||||
x ? y ? a : b : c;
|
||||
x ? y ? a : a : b;
|
||||
x ? y ? a : b : b;
|
||||
x ? y ? a : b : a;
|
||||
x ? y ? a : a : a;
|
||||
|
||||
x ? a : y ? b : c;
|
||||
x ? a : y ? a : b;
|
||||
x ? a : y ? b : b;
|
||||
x ? a : y ? b : a;
|
||||
x ? a : y ? a : a;
|
||||
}
|
||||
expect: {
|
||||
x ? a : b;
|
||||
x, a;
|
||||
|
||||
x ? y ? a : b : c;
|
||||
x ? (y, a) : b;
|
||||
x && y ? a : b;
|
||||
!x || y ? a : b;
|
||||
x && y, a;
|
||||
|
||||
x ? a : y ? b : c;
|
||||
x || y ? a : b;
|
||||
x ? a : (y, b);
|
||||
!x && y ? b : a;
|
||||
!x && y, a;
|
||||
}
|
||||
}
|
||||
|
||||
cond_7: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
@@ -663,6 +702,109 @@ cond_9: {
|
||||
}
|
||||
}
|
||||
|
||||
cond_10: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
if (1 == a) return "foo";
|
||||
if (2 == a) return "foo";
|
||||
if (3 == a) return "foo";
|
||||
if (4 == a) return 42;
|
||||
if (5 == a) return "foo";
|
||||
if (6 == a) return "foo";
|
||||
return "bar";
|
||||
}
|
||||
console.log(f(1), f(2), f(3), f(4), f(5), f(6), f(7));
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
return 1 == a || 2 == a || 3 == a ? "foo" : 4 == a ? 42 : 5 == a || 6 == a ? "foo" : "bar";
|
||||
}
|
||||
console.log(f(1), f(2), f(3), f(4), f(5), f(6), f(7));
|
||||
}
|
||||
expect_stdout: "foo foo foo 42 foo foo bar"
|
||||
}
|
||||
|
||||
cond_11: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
p: "foo",
|
||||
q: function() {
|
||||
return this.p;
|
||||
}
|
||||
};
|
||||
function f() {
|
||||
return "bar";
|
||||
}
|
||||
function g(a) {
|
||||
return a ? f() : o.q();
|
||||
}
|
||||
console.log(g(0), g(1));
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
p: "foo",
|
||||
q: function() {
|
||||
return this.p;
|
||||
}
|
||||
};
|
||||
function f() {
|
||||
return "bar";
|
||||
}
|
||||
function g(a) {
|
||||
return a ? f() : o.q();
|
||||
}
|
||||
console.log(g(0), g(1));
|
||||
}
|
||||
expect_stdout: "foo bar"
|
||||
}
|
||||
|
||||
cond_12: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
x ? y && a : a;
|
||||
x ? y || a : a;
|
||||
x ? a : y && a;
|
||||
x ? a : y || a;
|
||||
}
|
||||
expect: {
|
||||
(!x || y) && a;
|
||||
x && y || a;
|
||||
(x || y) && a;
|
||||
!x && y || a;
|
||||
}
|
||||
}
|
||||
|
||||
cond_13: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
x ? y(a) : z(a);
|
||||
x ? y.f(a) : z.f(a);
|
||||
x ? y.f(a) : z.g(a);
|
||||
x ? y.f()(a) : z.g()(a);
|
||||
x ? y.f.u(a) : z.g.u(a);
|
||||
x ? y.f().u(a) : z.g().u(a);
|
||||
}
|
||||
expect: {
|
||||
(x ? y : z)(a);
|
||||
(x ? y : z).f(a);
|
||||
x ? y.f(a) : z.g(a);
|
||||
(x ? y.f() : z.g())(a);
|
||||
(x ? y.f : z.g).u(a);
|
||||
(x ? y.f() : z.g()).u(a);
|
||||
}
|
||||
}
|
||||
|
||||
ternary_boolean_consequent: {
|
||||
options = {
|
||||
booleans: true,
|
||||
@@ -1120,11 +1262,11 @@ issue_2535_1: {
|
||||
expect: {
|
||||
y();
|
||||
x() && y();
|
||||
(x(), 1) && y();
|
||||
x(), y();
|
||||
x() && y();
|
||||
x() && y();
|
||||
x() && y();
|
||||
(x(), 0) && y();
|
||||
x();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1264,7 +1406,7 @@ hoist_decl: {
|
||||
}
|
||||
expect: {
|
||||
var a, b;
|
||||
x() ? y() : z();
|
||||
(x() ? y : z)();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1515,3 +1657,161 @@ issue_3576: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3668: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
try {
|
||||
var undefined = typeof f;
|
||||
if (!f) return undefined;
|
||||
return;
|
||||
} catch (e) {
|
||||
return "FAIL";
|
||||
}
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
try {
|
||||
var undefined = typeof f;
|
||||
return f ? void 0 : undefined;
|
||||
} catch (e) {
|
||||
return "FAIL";
|
||||
}
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
conditional_assignments_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b, c, d) {
|
||||
a = b;
|
||||
if (c) a = d;
|
||||
return a;
|
||||
}
|
||||
function g(a, b, c, d) {
|
||||
a = b;
|
||||
if (c); else a = d;
|
||||
return a;
|
||||
}
|
||||
console.log(f(0, "FAIL", 1, "PASS"), g(0, "PASS", 1, "FAIL"));
|
||||
}
|
||||
expect: {
|
||||
function f(a, b, c, d) {
|
||||
return a = c ? d : b, a;
|
||||
}
|
||||
function g(a, b, c, d) {
|
||||
return a = c ? b : d, a;
|
||||
}
|
||||
console.log(f(0, "FAIL", 1, "PASS"), g(0, "PASS", 1, "FAIL"));
|
||||
}
|
||||
expect_stdout: "PASS PASS"
|
||||
}
|
||||
|
||||
conditional_assignments_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
function f1(b, c, d) {
|
||||
a = b;
|
||||
if (c) a = d;
|
||||
return a;
|
||||
}
|
||||
function f2(a, c, d) {
|
||||
a = b;
|
||||
if (c) a = d;
|
||||
return a;
|
||||
}
|
||||
function f3(a, b, d) {
|
||||
a = b;
|
||||
if (c) a = d;
|
||||
return a;
|
||||
}
|
||||
function f4(a, b, c) {
|
||||
a = b;
|
||||
if (c) a = d;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f1(b, c, d) {
|
||||
return a = c ? d : b, a;
|
||||
}
|
||||
function f2(a, c, d) {
|
||||
return a = b, c && (a = d), a;
|
||||
}
|
||||
function f3(a, b, d) {
|
||||
return a = b, c && (a = d), a;
|
||||
}
|
||||
function f4(a, b, c) {
|
||||
return a = b, c && (a = d), a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
conditional_assignments_3: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a, b) {
|
||||
a = "PASS";
|
||||
if (b) a = a;
|
||||
return a;
|
||||
}(0, 1));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a, b) {
|
||||
return a = "PASS", b && (a = a), a;
|
||||
}(0, 1));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3808_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
a = "PASS", [] + "" && (a = "FAIL");
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
a = [] + "" ? "FAIL" : "PASS";
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3808_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
console.log((a = "PASS", [] + "" && (a = "FAIL")), a);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
console.log((a = "PASS", [] + "" && (a = "FAIL")), a);
|
||||
}
|
||||
expect_stdout: " PASS"
|
||||
}
|
||||
|
||||
@@ -97,6 +97,66 @@ dead_code_constant_boolean_should_warn_more: {
|
||||
node_version: "<=4"
|
||||
}
|
||||
|
||||
trim_try: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
var a;
|
||||
} catch (e) {
|
||||
console.log("FAIL");
|
||||
} finally {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
trim_finally_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
console.log("PASS");
|
||||
} finally {
|
||||
var a;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS");
|
||||
var a;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
trim_finally_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
console.log("PASS");
|
||||
} catch (e) {
|
||||
} finally {
|
||||
var a;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
console.log("PASS");
|
||||
var a;
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
try_catch_finally: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
@@ -130,10 +190,7 @@ try_catch_finally: {
|
||||
a = 3;
|
||||
console.log("PASS");
|
||||
}();
|
||||
try {
|
||||
console.log(a);
|
||||
} finally {
|
||||
}
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
@@ -141,207 +198,6 @@ try_catch_finally: {
|
||||
]
|
||||
}
|
||||
|
||||
accessor: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
get a() {},
|
||||
set a(v){
|
||||
this.b = 2;
|
||||
},
|
||||
b: 1
|
||||
});
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2233_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
Array.isArray;
|
||||
Boolean;
|
||||
console.log;
|
||||
Date;
|
||||
decodeURI;
|
||||
decodeURIComponent;
|
||||
encodeURI;
|
||||
encodeURIComponent;
|
||||
Error.name;
|
||||
escape;
|
||||
eval;
|
||||
EvalError;
|
||||
Function.length;
|
||||
isFinite;
|
||||
isNaN;
|
||||
JSON;
|
||||
Math.random;
|
||||
Number.isNaN;
|
||||
parseFloat;
|
||||
parseInt;
|
||||
RegExp;
|
||||
Object.defineProperty;
|
||||
String.fromCharCode;
|
||||
RangeError;
|
||||
ReferenceError;
|
||||
SyntaxError;
|
||||
TypeError;
|
||||
unescape;
|
||||
URIError;
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
global_timeout_and_interval_symbols: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
// These global symbols do not exist in the test sandbox
|
||||
// and must be tested separately.
|
||||
clearInterval;
|
||||
clearTimeout;
|
||||
setInterval;
|
||||
setTimeout;
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2233_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var RegExp;
|
||||
Array.isArray;
|
||||
RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Math.sin;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2233_3: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var RegExp;
|
||||
Array.isArray;
|
||||
RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Math.sin;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
UndeclaredGlobal;
|
||||
}
|
||||
}
|
||||
|
||||
global_fns: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
Boolean(1, 2);
|
||||
decodeURI(1, 2);
|
||||
decodeURIComponent(1, 2);
|
||||
Date(1, 2);
|
||||
encodeURI(1, 2);
|
||||
encodeURIComponent(1, 2);
|
||||
Error(1, 2);
|
||||
escape(1, 2);
|
||||
EvalError(1, 2);
|
||||
isFinite(1, 2);
|
||||
isNaN(1, 2);
|
||||
Number(1, 2);
|
||||
Object(1, 2);
|
||||
parseFloat(1, 2);
|
||||
parseInt(1, 2);
|
||||
RangeError(1, 2);
|
||||
ReferenceError(1, 2);
|
||||
String(1, 2);
|
||||
SyntaxError(1, 2);
|
||||
TypeError(1, 2);
|
||||
unescape(1, 2);
|
||||
URIError(1, 2);
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect_stdout: [
|
||||
"SyntaxError",
|
||||
"SyntaxError",
|
||||
"RangeError",
|
||||
]
|
||||
}
|
||||
|
||||
collapse_vars_assignment: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
@@ -380,7 +236,7 @@ collapse_vars_lvalues_drop_assign: {
|
||||
}
|
||||
}
|
||||
|
||||
collapse_vars_misc1: {
|
||||
collapse_vars_misc: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
dead_code: true,
|
||||
@@ -863,23 +719,6 @@ issue_2749: {
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
unsafe_builtin: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
(!w).constructor(x);
|
||||
Math.abs(y);
|
||||
[ 1, 2, z ].valueOf();
|
||||
}
|
||||
expect: {
|
||||
w, x;
|
||||
y;
|
||||
z;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2860_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
@@ -941,24 +780,6 @@ issue_2929: {
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
unsafe_string_replace: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
"foo".replace("f", function() {
|
||||
console.log("PASS");
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
"foo".replace("f", function() {
|
||||
console.log("PASS");
|
||||
});
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3402: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
@@ -1066,6 +887,7 @@ issue_3552: {
|
||||
unreachable_assign: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
strings: true,
|
||||
}
|
||||
input: {
|
||||
console.log(A = "P" + (A = "A" + (B = "S" + (A = B = "S"))), A, B);
|
||||
@@ -1127,3 +949,416 @@ issue_3578: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3830_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
set p(v) {
|
||||
o = o.p = o = v;
|
||||
}
|
||||
};
|
||||
o.p = "PASS";
|
||||
console.log(o);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
set p(v) {
|
||||
o = o.p = o = v;
|
||||
}
|
||||
};
|
||||
o.p = "PASS";
|
||||
console.log(o);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3830_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
var a = "FAIL";
|
||||
var o = {
|
||||
set FAIL(v) {
|
||||
a = o[a] = a = v;
|
||||
}
|
||||
};
|
||||
o[a] = "PASS";
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "FAIL";
|
||||
var o = {
|
||||
set FAIL(v) {
|
||||
a = o[a] = a = v;
|
||||
}
|
||||
};
|
||||
o[a] = "PASS";
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3830_3: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return a;
|
||||
}
|
||||
var a = "FAIL";
|
||||
var o = {
|
||||
set FAIL(v) {
|
||||
a = o[f()] = a = v;
|
||||
}
|
||||
};
|
||||
o[f()] = "PASS";
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return a;
|
||||
}
|
||||
var a = "FAIL";
|
||||
var o = {
|
||||
set FAIL(v) {
|
||||
a = o[f()] = a = v;
|
||||
}
|
||||
};
|
||||
o[f()] = "PASS";
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3830_4: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return o;
|
||||
}
|
||||
var a = "FAIL";
|
||||
var o = {
|
||||
set FAIL(v) {
|
||||
a = f()[a] = a = v;
|
||||
}
|
||||
};
|
||||
f()[a] = "PASS";
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return o;
|
||||
}
|
||||
var a = "FAIL";
|
||||
var o = {
|
||||
set FAIL(v) {
|
||||
a = f()[a] = a = v;
|
||||
}
|
||||
};
|
||||
f()[a] = "PASS";
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3830_5: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return o;
|
||||
}
|
||||
function g() {
|
||||
return a;
|
||||
}
|
||||
var a = "FAIL";
|
||||
var o = {
|
||||
set FAIL(v) {
|
||||
a = f()[g()] = a = v;
|
||||
}
|
||||
};
|
||||
f()[g()] = "PASS";
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return o;
|
||||
}
|
||||
function g() {
|
||||
return a;
|
||||
}
|
||||
var a = "FAIL";
|
||||
var o = {
|
||||
set FAIL(v) {
|
||||
a = f()[g()] = a = v;
|
||||
}
|
||||
};
|
||||
f()[g()] = "PASS";
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3830_6: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return o;
|
||||
}
|
||||
function g() {
|
||||
return a;
|
||||
}
|
||||
function h(v) {
|
||||
a = f()[g()] = a = v;
|
||||
}
|
||||
var a = "FAIL";
|
||||
var o = {
|
||||
set FAIL(v) {
|
||||
h(v);
|
||||
}
|
||||
};
|
||||
o.FAIL = "PASS";
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return o;
|
||||
}
|
||||
function g() {
|
||||
return a;
|
||||
}
|
||||
function h(v) {
|
||||
a = f()[g()] = a = v;
|
||||
}
|
||||
var a = "FAIL";
|
||||
var o = {
|
||||
set FAIL(v) {
|
||||
h(v);
|
||||
}
|
||||
};
|
||||
o.FAIL = "PASS";
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
redundant_assignments: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
var a = a = "PASS", b = "FAIL";
|
||||
b = b = "PASS";
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS", b = "FAIL";
|
||||
b = "PASS";
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "PASS PASS"
|
||||
}
|
||||
|
||||
self_assignments_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS";
|
||||
a = a;
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS";
|
||||
a;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
self_assignments_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = "q", o = {
|
||||
p: "PASS",
|
||||
};
|
||||
o.p = o.p;
|
||||
o[a] = o[a];
|
||||
console.log(o.p, o[a]);
|
||||
}
|
||||
expect: {
|
||||
var a = "q", o = {
|
||||
p: "PASS",
|
||||
};
|
||||
console.log(o.p, o[a]);
|
||||
}
|
||||
expect_stdout: "PASS undefined"
|
||||
}
|
||||
|
||||
self_assignments_3: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = "q", o = {
|
||||
p: "FAIL",
|
||||
get q() {
|
||||
return "PASS";
|
||||
},
|
||||
set q(v) {
|
||||
this.p = v;
|
||||
},
|
||||
};
|
||||
o.p = o.p;
|
||||
o[a] = o[a];
|
||||
console.log(o.p, o[a]);
|
||||
}
|
||||
expect: {
|
||||
var a = "q", o = {
|
||||
p: "FAIL",
|
||||
get q() {
|
||||
return "PASS";
|
||||
},
|
||||
set q(v) {
|
||||
this.p = v;
|
||||
},
|
||||
};
|
||||
o.p = o.p;
|
||||
o[a] = o[a];
|
||||
console.log(o.p, o[a]);
|
||||
}
|
||||
expect_stdout: "PASS PASS"
|
||||
}
|
||||
|
||||
self_assignments_4: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var i = 0, l = [ "PASS" ];
|
||||
l[0] = l[0];
|
||||
l[i] = l[i];
|
||||
console.log(l[0], i);
|
||||
}
|
||||
expect: {
|
||||
var i = 0, l = [ "PASS" ];
|
||||
console.log(l[0], i);
|
||||
}
|
||||
expect_stdout: "PASS 0"
|
||||
}
|
||||
|
||||
self_assignments_5: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
passes: 3,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var i = 0, l = [ "FAIL", "PASS" ];
|
||||
l[0] = l[0];
|
||||
l[i] = l[i];
|
||||
l[i++] = l[i++];
|
||||
console.log(l[0], i);
|
||||
}
|
||||
expect: {
|
||||
var i = 0, l = [ "FAIL", "PASS" ];
|
||||
l[0];
|
||||
l[0];
|
||||
l[0] = l[1];
|
||||
console.log(l[0], 2);
|
||||
}
|
||||
expect_stdout: "PASS 2"
|
||||
}
|
||||
|
||||
self_assignments_6: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
p: "PASS",
|
||||
};
|
||||
console.log(o.p = o.p);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
p: "PASS",
|
||||
};
|
||||
console.log(o.p);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3967: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
var a = "FAIL";
|
||||
try {
|
||||
a = 0 in (a = "PASS");
|
||||
} catch (e) {}
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "FAIL";
|
||||
try {
|
||||
a = 0 in (a = "PASS");
|
||||
} catch (e) {}
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4051: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
delete (A = A);
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
delete (A = A);
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ simple_statement_is_not_a_directive: {
|
||||
drop_lone_use_strict: {
|
||||
options = {
|
||||
directives: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
@@ -66,10 +66,8 @@ drop_lone_use_strict: {
|
||||
function f1() {
|
||||
}
|
||||
function f2() {
|
||||
"use strict";
|
||||
function f3() {
|
||||
}
|
||||
}
|
||||
(function() {})();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,3 +91,41 @@ issue_3166: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
valid_after_invalid_1: {
|
||||
input: {
|
||||
console.log(typeof function() {
|
||||
"use\x20strict";
|
||||
"use strict";
|
||||
return this;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof function() {
|
||||
"use\x20strict";
|
||||
"use strict";
|
||||
return this;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
valid_after_invalid_2: {
|
||||
options = {
|
||||
directives: true,
|
||||
}
|
||||
input: {
|
||||
console.log(typeof function() {
|
||||
"use\x20strict";
|
||||
"use strict";
|
||||
return this;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof function() {
|
||||
"use strict";
|
||||
return this;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
@@ -699,18 +699,6 @@ iife: {
|
||||
}
|
||||
}
|
||||
|
||||
drop_value: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(1, [2, foo()], 3, {a:1, b:bar()});
|
||||
}
|
||||
expect: {
|
||||
foo(), bar();
|
||||
}
|
||||
}
|
||||
|
||||
issue_1539: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
@@ -1203,10 +1191,10 @@ issue_2105_1: {
|
||||
input: {
|
||||
!function(factory) {
|
||||
factory();
|
||||
}( function() {
|
||||
}(function() {
|
||||
return function(fn) {
|
||||
fn()().prop();
|
||||
}( function() {
|
||||
}(function() {
|
||||
function bar() {
|
||||
var quux = function() {
|
||||
console.log("PASS");
|
||||
@@ -1217,7 +1205,7 @@ issue_2105_1: {
|
||||
return { prop: foo };
|
||||
}
|
||||
return bar;
|
||||
} );
|
||||
});
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
@@ -1247,10 +1235,10 @@ issue_2105_2: {
|
||||
input: {
|
||||
!function(factory) {
|
||||
factory();
|
||||
}( function() {
|
||||
}(function() {
|
||||
return function(fn) {
|
||||
fn()().prop();
|
||||
}( function() {
|
||||
}(function() {
|
||||
function bar() {
|
||||
var quux = function() {
|
||||
console.log("PASS");
|
||||
@@ -1261,7 +1249,7 @@ issue_2105_2: {
|
||||
return { prop: foo };
|
||||
}
|
||||
return bar;
|
||||
} );
|
||||
});
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
@@ -1270,6 +1258,44 @@ issue_2105_2: {
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2105_3: {
|
||||
options = {
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function(factory) {
|
||||
factory();
|
||||
}(function() {
|
||||
return function(fn) {
|
||||
fn()().prop();
|
||||
}(function() {
|
||||
function bar() {
|
||||
var quux = function() {
|
||||
console.log("PASS");
|
||||
}, foo = function() {
|
||||
console.log;
|
||||
quux();
|
||||
};
|
||||
return { prop: foo };
|
||||
}
|
||||
return bar;
|
||||
});
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
!void void {
|
||||
prop: function() {
|
||||
console.log;
|
||||
void console.log("PASS");
|
||||
}
|
||||
}.prop();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2226_1: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
@@ -1704,7 +1730,7 @@ chained_3: {
|
||||
expect: {
|
||||
console.log(function(a, b) {
|
||||
var c = b;
|
||||
b++;
|
||||
+b;
|
||||
return c;
|
||||
}(0, 2));
|
||||
}
|
||||
@@ -1971,7 +1997,7 @@ issue_3146_4: {
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3192: {
|
||||
issue_3192_1: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
@@ -1999,6 +2025,26 @@ issue_3192: {
|
||||
]
|
||||
}
|
||||
|
||||
issue_3192_2: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
(function(a) {
|
||||
console.log(a = "foo", arguments[0]);
|
||||
})("bar");
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
(function() {
|
||||
console.log("foo", arguments[0]);
|
||||
})("bar");
|
||||
}
|
||||
expect_stdout: "foo bar"
|
||||
}
|
||||
|
||||
issue_3233: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
@@ -2135,8 +2181,7 @@ issue_3515_1: {
|
||||
expect: {
|
||||
var c = 0;
|
||||
(function() {
|
||||
this[c++] = 0;
|
||||
for (var key20 in !0);
|
||||
for (var key20 in !(this[c++] = 0));
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
@@ -2259,10 +2304,691 @@ issue_3598: {
|
||||
try {
|
||||
(function() {
|
||||
a = "PASS";
|
||||
var c = (void (c.p = 0))[!1];
|
||||
(void ((void 0).p = 0))[!1];
|
||||
})();
|
||||
} catch (e) {}
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
self_assign: {
|
||||
options = {
|
||||
passes: 2,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function d(a) {
|
||||
a = a;
|
||||
}
|
||||
function e(a, b) {
|
||||
a = b;
|
||||
b = a;
|
||||
}
|
||||
function f(a, b, c) {
|
||||
a = b;
|
||||
b = c;
|
||||
c = a;
|
||||
}
|
||||
function g(a, b, c) {
|
||||
a = a * b + c;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function d(a) {}
|
||||
function e(a, b) {}
|
||||
function f(a, b, c) {}
|
||||
function g(a, b, c) {}
|
||||
}
|
||||
}
|
||||
|
||||
function_argument_reference: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1, b = 42;
|
||||
function f(a) {
|
||||
b <<= a;
|
||||
}
|
||||
f();
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = 1, b = 42;
|
||||
function f(a) {
|
||||
b <<= a;
|
||||
}
|
||||
f();
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "1 42"
|
||||
}
|
||||
|
||||
function_parameter_ie8: {
|
||||
options = {
|
||||
ie8: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
var a;
|
||||
function f() {
|
||||
console.log("PASS");
|
||||
}
|
||||
f(a = 1 + a);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
(function() {
|
||||
console.log("PASS");
|
||||
})();
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3664: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var a, b = (a = (a = [ b && console.log("FAIL") ]).p = 0, 0);
|
||||
return "PASS";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var b = ([ b && console.log("FAIL") ].p = 0, 0);
|
||||
return "PASS";
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3673: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
(a = [ a ]).p = 42;
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
(a = [ a ]).p = 42;
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3746: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
A;
|
||||
} catch (e) {
|
||||
var e;
|
||||
}
|
||||
(function f(a) {
|
||||
e = a;
|
||||
})();
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
A;
|
||||
} catch (e) {
|
||||
var e;
|
||||
}
|
||||
(function(a) {
|
||||
e = a;
|
||||
})();
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
drop_duplicated_side_effects: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
for (var i = 1; i--;)
|
||||
var a = 0, b = ++a;
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
for (var i = 1; i--;)
|
||||
a = 0, ++a;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
drop_duplicated_var_catch: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
try {
|
||||
x();
|
||||
} catch (a) {
|
||||
var a, a;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
try {
|
||||
x();
|
||||
} catch (a) {
|
||||
var a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_3802_1: {
|
||||
options = {
|
||||
functions: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
a += 0;
|
||||
var a = function() {};
|
||||
console.log(typeof a);
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
a += 0;
|
||||
a = function() {};
|
||||
console.log(typeof a);
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
issue_3802_2: {
|
||||
options = {
|
||||
functions: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
a += 0;
|
||||
var a = function() {};
|
||||
console.log(typeof a);
|
||||
}
|
||||
expect: {
|
||||
0;
|
||||
var a = function() {};
|
||||
console.log(typeof a);
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
issue_3899: {
|
||||
options = {
|
||||
assignments: true,
|
||||
evaluate: true,
|
||||
functions: true,
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
a = a + 1;
|
||||
var a = function f(b) {
|
||||
return function() {
|
||||
return b;
|
||||
};
|
||||
}(2);
|
||||
console.log(typeof a);
|
||||
}
|
||||
expect: {
|
||||
function a() {
|
||||
return 2;
|
||||
}
|
||||
console.log(typeof a);
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
cross_scope_assign_chain: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a, b = 0;
|
||||
(function() {
|
||||
a = b;
|
||||
a++;
|
||||
while (b++);
|
||||
})();
|
||||
console.log(a ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
var a, b = 0;
|
||||
(function() {
|
||||
a = b;
|
||||
a++;
|
||||
while (b++);
|
||||
})();
|
||||
console.log(a ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
assign_if_assign_read: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(a) {
|
||||
var b;
|
||||
do {
|
||||
b = "FAIL";
|
||||
if (Array.isArray(a)) {
|
||||
b = a[0];
|
||||
console.log(b);
|
||||
}
|
||||
} while (!console);
|
||||
})([ "PASS" ]);
|
||||
}
|
||||
expect: {
|
||||
(function(a) {
|
||||
var b;
|
||||
do {
|
||||
"FAIL";
|
||||
if (Array.isArray(a)) {
|
||||
b = a[0];
|
||||
console.log(b);
|
||||
}
|
||||
} while (!console);
|
||||
})([ "PASS" ]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3951: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = console.log("PASS");
|
||||
console.log(a);
|
||||
a = "0";
|
||||
console.log(a.p = 0);
|
||||
a && a;
|
||||
}
|
||||
expect: {
|
||||
var a = console.log("PASS");
|
||||
console.log(a);
|
||||
a = "0";
|
||||
console.log(a.p = 0);
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"undefined",
|
||||
"0",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3956: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(a) {
|
||||
function f(b) {
|
||||
console.log(b);
|
||||
a = 1;
|
||||
}
|
||||
var c = f(c += 0);
|
||||
(function(d) {
|
||||
console.log(d);
|
||||
})(console.log(a) ^ 1, c);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
var c, d;
|
||||
c += 0,
|
||||
console.log(NaN),
|
||||
d = 1 ^ console.log(1),
|
||||
console.log(d);
|
||||
}
|
||||
expect_stdout: [
|
||||
"NaN",
|
||||
"1",
|
||||
"1",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3962_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
function f(b, c) {
|
||||
do {
|
||||
var d = console + e, e = 0..toString() === b;
|
||||
} while (0);
|
||||
if (c) console.log("PASS");
|
||||
}
|
||||
var a = f(a--, 1);
|
||||
a;
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
a = (function(c) {
|
||||
do {
|
||||
console;
|
||||
0..toString();
|
||||
} while (0);
|
||||
if (c) console.log("PASS");
|
||||
}(1), 0);
|
||||
void 0;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3962_2: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
function f(b, c) {
|
||||
do {
|
||||
var d = console + e, e = 0..toString() === b;
|
||||
} while (0);
|
||||
if (c) console.log("PASS");
|
||||
}
|
||||
var a = f(a--, 1);
|
||||
a;
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
a = (function(c) {
|
||||
do {
|
||||
console;
|
||||
0..toString();
|
||||
} while (0);
|
||||
if (c) console.log("PASS");
|
||||
}(1), 0);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3986: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b = 0;
|
||||
(function() {
|
||||
try {
|
||||
throw 42;
|
||||
} catch (e) {
|
||||
a++;
|
||||
}
|
||||
b = b && 0;
|
||||
})(b *= a);
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b = 0;
|
||||
(function() {
|
||||
try {
|
||||
throw 42;
|
||||
} catch (e) {
|
||||
a++;
|
||||
}
|
||||
b = b && 0;
|
||||
})(b *= a);
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
issue_4017: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
console.log(function f() {
|
||||
var b = c &= 0;
|
||||
var c = a++ + (A = a);
|
||||
var d = c && c[f];
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
console.log(function() {
|
||||
c &= 0;
|
||||
var c = (a++, A = a, 0);
|
||||
}());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_4025: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b = 0, c = 0, d = a++;
|
||||
try {
|
||||
var e = console.log(c), f = b;
|
||||
} finally {
|
||||
var d = b = 1, d = c + 1;
|
||||
c = 0;
|
||||
}
|
||||
console.log(a, b, d);
|
||||
}
|
||||
expect: {
|
||||
var c = 0;
|
||||
try {
|
||||
console.log(c);
|
||||
} finally {
|
||||
var d = c + 1;
|
||||
c = 0;
|
||||
}
|
||||
console.log(1, 1, d);
|
||||
}
|
||||
expect_stdout: [
|
||||
"0",
|
||||
"1 1 1",
|
||||
]
|
||||
}
|
||||
|
||||
forin_var_1: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var k;
|
||||
for (k in [ 1, 2 ])
|
||||
console.log(k);
|
||||
for (k in { PASS: 3 })
|
||||
console.log(k);
|
||||
console.log(k);
|
||||
}
|
||||
expect: {
|
||||
for (var k in [ 1, 2 ])
|
||||
console.log(k);
|
||||
for (k in { PASS: 3 })
|
||||
console.log(k);
|
||||
console.log(k);
|
||||
}
|
||||
expect_stdout: [
|
||||
"0",
|
||||
"1",
|
||||
"PASS",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
forin_var_2: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
switch (0) {
|
||||
case function() {
|
||||
for (a in 0);
|
||||
}:
|
||||
var b = 0;
|
||||
}
|
||||
for (var c = 0; a;);
|
||||
var a;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
switch (0) {
|
||||
case function() {
|
||||
for (a in 0);
|
||||
}:
|
||||
}
|
||||
for (; a;);
|
||||
var a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_4133: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
merge_vars: true,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
var b = [ a-- ], c = b && b[c];
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var b = 1;
|
||||
console.log(0);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
issue_4144: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(a, b) {
|
||||
var b = console, c = ++b;
|
||||
})(console.log("PASS"), 0);
|
||||
}
|
||||
expect: {
|
||||
(function(b) {
|
||||
b = console,
|
||||
++b;
|
||||
})(console.log("PASS"));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4146: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b) {
|
||||
function g() {}
|
||||
var a = g;
|
||||
var c = b;
|
||||
c.p;
|
||||
console.log(typeof a);
|
||||
}
|
||||
f("FAIL", 42);
|
||||
}
|
||||
expect: {
|
||||
(function(a, b) {
|
||||
a = function () {};
|
||||
var c = b;
|
||||
c.p;
|
||||
console.log(typeof a);
|
||||
})(0, 42);
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
@@ -558,34 +558,51 @@ unsafe_array: {
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
[1, , 3][1],
|
||||
[1, 2, 3, a] + 1,
|
||||
[1, 2, 3, 4] + 1,
|
||||
[1, 2, 3, a][0] + 1,
|
||||
[1, 2, 3, 4][0] + 1,
|
||||
[1, 2, 3, 4][6 - 5] + 1,
|
||||
[1, , 3, 4][6 - 5] + 1,
|
||||
[[1, 2], [3, 4]][0] + 1,
|
||||
[[1, 2], [3, 4]][6 - 5][1] + 1,
|
||||
[[1, 2], , [3, 4]][6 - 5][1] + 1
|
||||
);
|
||||
var a = "PASS";
|
||||
Array.prototype[1] = a;
|
||||
console.log([, ].length);
|
||||
console.log("" + [, , ]);
|
||||
console.log([1, , 3][1]);
|
||||
console.log([1, 2, 3, a] + 1);
|
||||
console.log([1, 2, 3, 4] + 1);
|
||||
console.log([1, 2, 3, a][0] + 1);
|
||||
console.log([1, 2, 3, 4][0] + 1);
|
||||
console.log([1, 2, 3, 4][6 - 5] + 1);
|
||||
console.log([1, , 3, 4][6 - 5] + 1);
|
||||
console.log([[1, 2], [3, 4]][0] + 1);
|
||||
console.log([[1, 2], [3, 4]][6 - 5][1] + 1);
|
||||
console.log([[1, 2], , [3, 4]][6 - 5][1] + 1);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
void 0,
|
||||
[1, 2, 3, a] + 1,
|
||||
"1,2,3,41",
|
||||
[1, 2, 3, a][0] + 1,
|
||||
2,
|
||||
3,
|
||||
NaN,
|
||||
"1,21",
|
||||
5,
|
||||
(void 0)[1] + 1
|
||||
);
|
||||
var a = "PASS";
|
||||
Array.prototype[1] = a;
|
||||
console.log([, ].length);
|
||||
console.log("" + [, , ]);
|
||||
console.log([1, , 3][1]);
|
||||
console.log([1, 2, 3, a] + 1);
|
||||
console.log("1,2,3,41");
|
||||
console.log([1, 2, 3, a][0] + 1);
|
||||
console.log(2);
|
||||
console.log(3);
|
||||
console.log([1, , 3, 4][1] + 1);
|
||||
console.log("1,21");
|
||||
console.log(5);
|
||||
console.log([[1, 2], , [3, 4]][1][1] + 1);
|
||||
}
|
||||
expect_stdout: true
|
||||
expect_stdout: [
|
||||
"1",
|
||||
",PASS",
|
||||
"PASS",
|
||||
"1,2,3,PASS1",
|
||||
"1,2,3,41",
|
||||
"2",
|
||||
"2",
|
||||
"3",
|
||||
"PASS1",
|
||||
"1,21",
|
||||
"5",
|
||||
"A1",
|
||||
]
|
||||
}
|
||||
|
||||
unsafe_string: {
|
||||
@@ -1579,9 +1596,9 @@ issue_2968_1: {
|
||||
expect: {
|
||||
var c = "FAIL";
|
||||
(function() {
|
||||
b = -(a = 42),
|
||||
void ((a <<= 0) && (a[(c = "PASS", 0 >>> (b += 1))] = 0));
|
||||
var a, b;
|
||||
a = 42,
|
||||
void ((a <<= 0) && (a[(c = "PASS", 0)] = 0));
|
||||
var a;
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
@@ -2161,3 +2178,839 @@ collapse_vars_regexp: {
|
||||
"abbb",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3738: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log(1 / (0 + ([] - 1) % 1));
|
||||
}
|
||||
expect: {
|
||||
console.log(1 / (0 + ([] - 1) % 1));
|
||||
}
|
||||
expect_stdout: "Infinity"
|
||||
}
|
||||
|
||||
issue_3755: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
console.log((/4/.exec(1 + (!0 - 5 / "23")) || 0).p);
|
||||
}
|
||||
expect: {
|
||||
console.log((/4/.exec(!0 - 5 / "23" + 1), 0).p);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
void_side_effects: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = void console.log("PASS");
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS");
|
||||
console.log(void 0);
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"undefined",
|
||||
]
|
||||
}
|
||||
|
||||
no_returns: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = function() {
|
||||
console.log("PASS");
|
||||
}();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
console.log("PASS");
|
||||
})();
|
||||
console.log(void 0);
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"undefined",
|
||||
]
|
||||
}
|
||||
|
||||
void_returns: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = function f() {
|
||||
function g(b) {
|
||||
if (b) console.log("FAIL");
|
||||
}
|
||||
while (1) {
|
||||
console.log("PASS");
|
||||
try {
|
||||
if (console) return;
|
||||
} catch (e) {
|
||||
return g(e);
|
||||
}
|
||||
}
|
||||
}();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
function g(b) {
|
||||
if (b) console.log("FAIL");
|
||||
}
|
||||
while (1) {
|
||||
console.log("PASS");
|
||||
try {
|
||||
if (console) return;
|
||||
} catch (e) {
|
||||
return g(e);
|
||||
}
|
||||
}
|
||||
})();
|
||||
console.log(void 0);
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"undefined",
|
||||
]
|
||||
}
|
||||
|
||||
void_returns_recursive: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = function f() {
|
||||
function g(b) {
|
||||
return f();
|
||||
}
|
||||
while (1) {
|
||||
console.log("PASS");
|
||||
try {
|
||||
if (console) return;
|
||||
} catch (e) {
|
||||
return g(e);
|
||||
}
|
||||
}
|
||||
}();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = function f() {
|
||||
function g(b) {
|
||||
return f();
|
||||
}
|
||||
while (1) {
|
||||
console.log("PASS");
|
||||
try {
|
||||
if (console) return;
|
||||
} catch (e) {
|
||||
return g();
|
||||
}
|
||||
}
|
||||
}();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"undefined",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3878_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var b = function(a) {
|
||||
return (a = 0) == (a && this > (a += 0));
|
||||
}();
|
||||
console.log(b ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
console.log(true ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3878_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = "foo";
|
||||
a++ + a;
|
||||
a && a;
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "foo";
|
||||
a++ + a;
|
||||
a;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
issue_3882: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return console.log(a++), a && this;
|
||||
}
|
||||
var b = f();
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var b = function(a) {
|
||||
return console.log(a++), a && this;
|
||||
}();
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: [
|
||||
"NaN",
|
||||
"NaN",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3887: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(b) {
|
||||
try {
|
||||
b-- && console.log("PASS");
|
||||
} catch (a_2) {}
|
||||
})(1);
|
||||
}
|
||||
expect: {
|
||||
(function(b) {
|
||||
try {
|
||||
1, console.log("PASS");
|
||||
} catch (a_2) {}
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3903: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS";
|
||||
function f(b, c) {
|
||||
return console, c;
|
||||
}
|
||||
var d = f(f(), a = a);
|
||||
console.log(d);
|
||||
}
|
||||
expect: {
|
||||
function f(b, c) {
|
||||
return console, c;
|
||||
}
|
||||
f(f(), "PASS");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3905: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
passes: 2,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(a, a) {
|
||||
return console.log(a = 0), a && console.log("FAIL");
|
||||
})("foo", 42);
|
||||
}
|
||||
expect: {
|
||||
(function(a, a) {
|
||||
return console.log(a = 0), a && console.log("FAIL");
|
||||
})("foo", 42);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
issue_3920: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = function(b) {
|
||||
return (b[b = 0] = 0) >= (b ? 0 : 1);
|
||||
}("foo");
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
(function(b) {
|
||||
"foo"[0] = 0;
|
||||
})();
|
||||
console.log(false);
|
||||
}
|
||||
expect_stdout: "false"
|
||||
}
|
||||
|
||||
inlined_increment_prefix: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
(function() {
|
||||
++a;
|
||||
})();
|
||||
console.log(a += 0);
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
void ++a;
|
||||
console.log(1);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
inlined_increment_postfix: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
(function() {
|
||||
a++;
|
||||
})();
|
||||
console.log(a += 0);
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
void a++;
|
||||
console.log(1);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
compound_assignment_to_property: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
1 + (0..p >>= 0) && console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
1 + (0..p >>= 0),
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2208_assign: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
a = 42;
|
||||
console.log({
|
||||
p: function() {
|
||||
return function() {
|
||||
return this.a;
|
||||
}();
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect: {
|
||||
a = 42;
|
||||
console.log({
|
||||
p: function() {
|
||||
return function() {
|
||||
return this.a;
|
||||
}();
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_2208_postfix: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
a = 41;
|
||||
a++;
|
||||
console.log({
|
||||
p: function() {
|
||||
return function() {
|
||||
return this.a;
|
||||
}();
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect: {
|
||||
a = 41;
|
||||
a++;
|
||||
console.log({
|
||||
p: function() {
|
||||
return function() {
|
||||
return this.a;
|
||||
}();
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_2208_prefix: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
a = 43;
|
||||
--a;
|
||||
console.log({
|
||||
p: function() {
|
||||
return function() {
|
||||
return this.a;
|
||||
}();
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect: {
|
||||
a = 43;
|
||||
--a;
|
||||
console.log({
|
||||
p: function() {
|
||||
return function() {
|
||||
return this.a;
|
||||
}();
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_3933: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(a, b) {
|
||||
a && (b ^= 1) && console.log("PASS");
|
||||
})(1);
|
||||
}
|
||||
expect: {
|
||||
(function(a, b) {
|
||||
1, 1, console.log("PASS");
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3935: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f(a) {
|
||||
return a++;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(NaN);
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
issue_3937: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var a = 123;
|
||||
(a++ + (b = a))[b] ? 0 ? a : b : 0 ? a : b;
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = 123;
|
||||
(a++ + (b = a))[b], 0, b;
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "124 124"
|
||||
}
|
||||
|
||||
issue_3944: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
function f() {
|
||||
while (function() {
|
||||
var a = 0 == (b && b.p), b = console.log(a);
|
||||
}());
|
||||
f;
|
||||
}
|
||||
f();
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
void function f() {
|
||||
while (a = 0 == (a = void 0), console.log(a), void 0);
|
||||
var a;
|
||||
f;
|
||||
}();
|
||||
}
|
||||
expect_stdout: "false"
|
||||
}
|
||||
|
||||
issue_3953: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
(a += 0 * (a = 0)) && console.log("PASS");
|
||||
}
|
||||
f(1);
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
(a += 0 * (a = 0)) && console.log("PASS");
|
||||
}
|
||||
f(1);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3988: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(b) {
|
||||
return ("" + (b &= 0))[b && this];
|
||||
}
|
||||
var a = f();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = function(b) {
|
||||
return ("" + (b &= 0))[b && this];
|
||||
}();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
operator_in: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
Object.prototype.PASS = 0;
|
||||
console.log(0 in [ 1 ]);
|
||||
console.log(0 in [ , ]);
|
||||
console.log(0 / 0 in { NaN: 2 });
|
||||
console.log("PASS" in { });
|
||||
console.log("FAIL" in { });
|
||||
console.log("toString" in { });
|
||||
console.log("toString" in { toString: 3 });
|
||||
}
|
||||
expect: {
|
||||
Object.prototype.PASS = 0;
|
||||
console.log(true);
|
||||
console.log(0 in [ , ]);
|
||||
console.log(true);
|
||||
console.log("PASS" in { });
|
||||
console.log("FAIL" in { });
|
||||
console.log("toString" in { });
|
||||
console.log(true);
|
||||
}
|
||||
expect_stdout: [
|
||||
"true",
|
||||
"false",
|
||||
"true",
|
||||
"true",
|
||||
"false",
|
||||
"true",
|
||||
"true",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3997: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = function f(b) {
|
||||
return b[b += this] = b;
|
||||
}(0);
|
||||
console.log(typeof a);
|
||||
}
|
||||
expect: {
|
||||
var a = function f(b) {
|
||||
return b[b += this] = b;
|
||||
}(0);
|
||||
console.log(typeof a);
|
||||
}
|
||||
expect_stdout: "string"
|
||||
}
|
||||
|
||||
issue_4035: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
(function() {
|
||||
var b = --a;
|
||||
console.log(delete (0 + b));
|
||||
console.log(delete (1 * b));
|
||||
console.log(delete (b + 0));
|
||||
console.log(delete (b - 0));
|
||||
console.log(delete (b / 1));
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
(function() {
|
||||
var b = --a;
|
||||
console.log((0 + b, true));
|
||||
console.log((1 * b, true));
|
||||
console.log((0 + b, true));
|
||||
console.log((b - 0, true));
|
||||
console.log((b / 1, true));
|
||||
})();
|
||||
}
|
||||
expect_stdout: [
|
||||
"true",
|
||||
"true",
|
||||
"true",
|
||||
"true",
|
||||
"true",
|
||||
]
|
||||
}
|
||||
|
||||
issue_4067: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
(function(a) {
|
||||
(function(b) {
|
||||
b[0] += 0;
|
||||
console.log(+a);
|
||||
})(a);
|
||||
})([]);
|
||||
}
|
||||
expect: {
|
||||
(function(a) {
|
||||
(function(b) {
|
||||
b[0] += 0;
|
||||
console.log(+a);
|
||||
})(a);
|
||||
})([]);
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
issue_4077: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log((a = []) - (a[0]++, 1) || "PASS");
|
||||
}
|
||||
expect: {
|
||||
console.log((a = []) - (a[0]++, 1) || "PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4119_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var a, b;
|
||||
b = a = [];
|
||||
a[0] += 0;
|
||||
if (+b + 1) {
|
||||
console.log("FAIL");
|
||||
} else {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a, b;
|
||||
b = a = [];
|
||||
a[0] += 0;
|
||||
+b + 1 ? console.log("FAIL") : console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4119_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
(function(b) {
|
||||
a[0] += 0;
|
||||
console.log(+b + 1 ? "FAIL" : "PASS");
|
||||
})(a = []);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
(function(b) {
|
||||
a[0] += 0;
|
||||
console.log(+b + 1 ? "FAIL" : "PASS");
|
||||
})(a = []);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4119_3: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var a, b;
|
||||
b = a = {
|
||||
p: 42,
|
||||
};
|
||||
delete a.p;
|
||||
console.log(b.p ? "FAIL" : "PASS");
|
||||
}
|
||||
expect: {
|
||||
var a, b;
|
||||
b = a = {
|
||||
p: 42,
|
||||
};
|
||||
delete a.p;
|
||||
console.log(b.p ? "FAIL" : "PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4119_4: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a, b;
|
||||
b = a = {
|
||||
p: 42,
|
||||
};
|
||||
delete a.p;
|
||||
console.log(!b ? "FAIL" : "PASS");
|
||||
}
|
||||
expect: {
|
||||
var a, b;
|
||||
b = a = {
|
||||
p: 42,
|
||||
};
|
||||
delete a.p;
|
||||
console.log((b, 0, "PASS"));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,20 @@ must_replace: {
|
||||
}
|
||||
}
|
||||
|
||||
repeated_nodes: {
|
||||
options = {
|
||||
global_defs: {
|
||||
"@N": "rand()",
|
||||
},
|
||||
}
|
||||
input: {
|
||||
console.log(N, N);
|
||||
}
|
||||
expect: {
|
||||
console.log(rand(), rand());
|
||||
}
|
||||
}
|
||||
|
||||
keyword: {
|
||||
options = {
|
||||
global_defs: {
|
||||
|
||||
@@ -664,7 +664,7 @@ issue_2519: {
|
||||
}
|
||||
expect: {
|
||||
function testFunc() {
|
||||
return 1 * ((6 + 5) / 2);
|
||||
return +((6 + 5) / 2);
|
||||
}
|
||||
console.log(testFunc());
|
||||
}
|
||||
@@ -767,18 +767,17 @@ issue_3071_1: {
|
||||
var obj = {};
|
||||
obj.one = 1;
|
||||
obj.two = 2;
|
||||
console.log(obj.one);
|
||||
console.log(obj.one, obj.two);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
console.log(1);
|
||||
console.log(1, 2);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
expect_stdout: "1 2"
|
||||
}
|
||||
|
||||
issue_3071_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
@@ -793,19 +792,18 @@ issue_3071_2: {
|
||||
obj = {};
|
||||
obj.one = 1;
|
||||
obj.two = 2;
|
||||
console.log(obj.one);
|
||||
console.log(obj.one, obj.two);
|
||||
var obj;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
console.log(1);
|
||||
console.log(1, 2);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
expect_stdout: "1 2"
|
||||
}
|
||||
|
||||
issue_3071_2_toplevel: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
@@ -821,14 +819,14 @@ issue_3071_2_toplevel: {
|
||||
obj = {};
|
||||
obj.one = 1;
|
||||
obj.two = 2;
|
||||
console.log(obj.one);
|
||||
console.log(obj.one, obj.two);
|
||||
var obj;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
console.log(1);
|
||||
console.log(1, 2);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
expect_stdout: "1 2"
|
||||
}
|
||||
|
||||
issue_3071_3: {
|
||||
@@ -914,3 +912,132 @@ issue_3440: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3868: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(function(t) {
|
||||
t = {};
|
||||
({
|
||||
get p() {},
|
||||
q: (console.log("PASS"), +t),
|
||||
}).r;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(t) {
|
||||
t = {};
|
||||
({
|
||||
get p() {},
|
||||
q: (console.log("PASS"), +t),
|
||||
}).r;
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3871: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
do {
|
||||
var b = {
|
||||
get null() {
|
||||
c;
|
||||
}
|
||||
};
|
||||
} while (!b);
|
||||
return "PASS";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
do {
|
||||
var b = {
|
||||
get null() {
|
||||
c;
|
||||
}
|
||||
};
|
||||
} while (!b);
|
||||
return "PASS";
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3945_1: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
o.p;
|
||||
var o = {
|
||||
q: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
o.p;
|
||||
var o = {
|
||||
q: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_3945_2: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
console.log(typeof o);
|
||||
var o = {
|
||||
p: 0,
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof o);
|
||||
var o = {
|
||||
p: 0,
|
||||
};
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_4023: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
typeofs: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a = function() {
|
||||
return { p: 0 };
|
||||
}();
|
||||
return console.log("undefined" != typeof a);
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
console.log(void 0 !== {});
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
@@ -1,55 +1,107 @@
|
||||
html_comment_in_expression: {
|
||||
input: {
|
||||
function f(a, b, x, y) { return a < !--b && x-- > y; }
|
||||
(function(a, b) {
|
||||
console.log(a < !--b && a-- > b, a, b);
|
||||
})(1, 2);
|
||||
}
|
||||
expect_exact: "function f(a,b,x,y){return a< !--b&&x-- >y}";
|
||||
expect_exact: "(function(a,b){console.log(a<! --b&&a-- >b,a,b)})(1,2);"
|
||||
expect_stdout: "false 1 1"
|
||||
}
|
||||
|
||||
html_comment_in_less_than: {
|
||||
input: {
|
||||
function f(a, b) { return a < !--b; }
|
||||
(function(a, b, c) {
|
||||
console.log(
|
||||
a < !--b,
|
||||
a < !--b + c,
|
||||
a + b < !--c,
|
||||
a, b, c
|
||||
);
|
||||
})(1, 2, 3);
|
||||
}
|
||||
expect_exact: "function f(a,b){return a< !--b}";
|
||||
expect_exact: "(function(a,b,c){console.log(a<! --b,a<! --b+c,a+b<! --c,a,b,c)})(1,2,3);"
|
||||
expect_stdout: "false true false 1 0 2"
|
||||
}
|
||||
|
||||
html_comment_in_left_shift: {
|
||||
input: {
|
||||
function f(a, b) { return a << !--b; }
|
||||
(function(a, b, c) {
|
||||
console.log(
|
||||
a << !--b,
|
||||
a << !--b + c,
|
||||
a + b << !--c,
|
||||
a, b, c
|
||||
);
|
||||
})(1, 2, 3);
|
||||
}
|
||||
expect_exact: "function f(a,b){return a<< !--b}";
|
||||
}
|
||||
|
||||
html_comment_in_right_shift: {
|
||||
input: {
|
||||
function f(a, b) { return a-- >> b; }
|
||||
}
|
||||
expect_exact: "function f(a,b){return a-- >>b}";
|
||||
}
|
||||
|
||||
html_comment_in_zero_fill_right_shift: {
|
||||
input: {
|
||||
function f(a, b) { return a-- >>> b; }
|
||||
}
|
||||
expect_exact: "function f(a,b){return a-- >>>b}";
|
||||
expect_exact: "(function(a,b,c){console.log(a<<! --b,a<<! --b+c,a+b<<! --c,a,b,c)})(1,2,3);"
|
||||
expect_stdout: "1 16 1 1 0 2"
|
||||
}
|
||||
|
||||
html_comment_in_greater_than: {
|
||||
input: {
|
||||
function f(a, b) { return a-- > b; }
|
||||
(function(a, b, c) {
|
||||
console.log(
|
||||
a-- > b,
|
||||
a-- > b + c,
|
||||
a + b-- > c,
|
||||
a, b, c
|
||||
);
|
||||
})(1, 2, 3);
|
||||
}
|
||||
expect_exact: "function f(a,b){return a-- >b}";
|
||||
expect_exact: "(function(a,b,c){console.log(a-- >b,a-- >b+c,a+b-- >c,a,b,c)})(1,2,3);"
|
||||
expect_stdout: "false false false -1 1 3"
|
||||
}
|
||||
|
||||
html_comment_in_greater_than_or_equal: {
|
||||
input: {
|
||||
function f(a, b) { return a-- >= b; }
|
||||
(function(a, b, c) {
|
||||
console.log(
|
||||
a-- >= b,
|
||||
a-- >= b + c,
|
||||
a + b-- >= c,
|
||||
a, b, c
|
||||
);
|
||||
})(1, 2, 3);
|
||||
}
|
||||
expect_exact: "function f(a,b){return a-- >=b}";
|
||||
expect_exact: "(function(a,b,c){console.log(a-- >=b,a-- >=b+c,a+b-- >=c,a,b,c)})(1,2,3);"
|
||||
expect_stdout: "false false false -1 1 3"
|
||||
}
|
||||
|
||||
html_comment_in_right_shift: {
|
||||
input: {
|
||||
(function(a, b, c) {
|
||||
console.log(
|
||||
a-- >> b,
|
||||
a-- >> b + c,
|
||||
a + b-- >> c,
|
||||
a, b, c
|
||||
);
|
||||
})(1, 2, 3);
|
||||
}
|
||||
expect_exact: "(function(a,b,c){console.log(a-- >>b,a-- >>b+c,a+b-- >>c,a,b,c)})(1,2,3);"
|
||||
expect_stdout: "0 0 0 -1 1 3"
|
||||
}
|
||||
|
||||
html_comment_in_zero_fill_right_shift: {
|
||||
input: {
|
||||
(function(a, b, c) {
|
||||
console.log(
|
||||
a-- >>> b,
|
||||
a-- >>> b + c,
|
||||
a + b-- >>> c,
|
||||
a, b, c
|
||||
);
|
||||
})(1, 2, 3);
|
||||
}
|
||||
expect_exact: "(function(a,b,c){console.log(a-- >>>b,a-- >>>b+c,a+b-- >>>c,a,b,c)})(1,2,3);"
|
||||
expect_stdout: "0 0 0 -1 1 3"
|
||||
}
|
||||
|
||||
html_comment_in_string_literal: {
|
||||
input: {
|
||||
function f() { return "<!--HTML-->comment in<!--string literal-->"; }
|
||||
console.log("<!--HTML-->comment in<!--string literal-->".length);
|
||||
}
|
||||
expect_exact: 'function f(){return"\\x3c!--HTML--\\x3ecomment in\\x3c!--string literal--\\x3e"}';
|
||||
expect_exact: 'console.log("\\x3c!--HTML--\\x3ecomment in\\x3c!--string literal--\\x3e".length);'
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
@@ -2223,13 +2223,13 @@ issue_3523_rename_ie8: {
|
||||
expect: {
|
||||
var a = 0, b, c = "FAIL";
|
||||
(function() {
|
||||
var c, n, t, o, a, r, f, i, u, e, h, l, v, y;
|
||||
var c, n, t, o, a, r, e, f, i, u, h, l, v, y;
|
||||
})();
|
||||
try {
|
||||
throw 0;
|
||||
} catch (e) {
|
||||
(function() {
|
||||
(function n() {
|
||||
(function e() {
|
||||
c = "PASS";
|
||||
})();
|
||||
})();
|
||||
@@ -2361,3 +2361,356 @@ issue_3542: {
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3703: {
|
||||
options = {
|
||||
ie8: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS";
|
||||
function f() {
|
||||
var b;
|
||||
function g() {
|
||||
a = "FAIL";
|
||||
}
|
||||
var c = g;
|
||||
function h() {
|
||||
f;
|
||||
}
|
||||
a ? b |= c : b.p;
|
||||
}
|
||||
f();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS";
|
||||
(function() {
|
||||
var b;
|
||||
var c = function() {
|
||||
a = "FAIL";
|
||||
};
|
||||
a ? b |= c : b.p;
|
||||
})();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3750: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
(function(a) {
|
||||
return function a() {
|
||||
return a && console.log("PASS");
|
||||
}();
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(a) {
|
||||
return function a() {
|
||||
return a && console.log("PASS");
|
||||
}();
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3823: {
|
||||
options = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
for (var i = 0; i < 1; i++) {
|
||||
var a = a ? function f() {
|
||||
f;
|
||||
} : 0;
|
||||
console.log("PASS", typeof f);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (var i = 0; i < 1; i++) {
|
||||
(function f() {
|
||||
f;
|
||||
});
|
||||
console.log("PASS", typeof f);
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS undefined"
|
||||
}
|
||||
|
||||
issue_3825: {
|
||||
options = {
|
||||
ie8: true,
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log({}[void (0..length ? 1 : 2)]);
|
||||
}
|
||||
expect: {
|
||||
console.log({}[void 0]);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_3889: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
ie8: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
a = 0;
|
||||
(function a() {
|
||||
var a;
|
||||
console.log(a);
|
||||
})();
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
a = 0;
|
||||
(function a() {
|
||||
var a;
|
||||
console.log(a);
|
||||
})();
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_3918: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
ie8: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
if (console.log("PASS")) {
|
||||
var a = function f() {
|
||||
f.p;
|
||||
try {
|
||||
console.log("FAIL");
|
||||
} catch (e) {}
|
||||
}, b = a;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
console.log("PASS") && (a = function f() {
|
||||
f.p;
|
||||
try {
|
||||
console.log("FAIL");
|
||||
} catch (o) {}
|
||||
}, a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3999: {
|
||||
rename = true
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
(function f() {
|
||||
for (var i = 0; i < 2; i++)
|
||||
try {
|
||||
f[0];
|
||||
} catch (f) {
|
||||
var f = 0;
|
||||
console.log(i);
|
||||
}
|
||||
})();
|
||||
})(typeof f);
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
(function f() {
|
||||
for (var o = 0; o < 2; o++)
|
||||
try {
|
||||
f[0];
|
||||
} catch (f) {
|
||||
var f = 0;
|
||||
console.log(o);
|
||||
}
|
||||
})();
|
||||
})(typeof f);
|
||||
}
|
||||
expect_stdout: [
|
||||
"0",
|
||||
"1",
|
||||
]
|
||||
}
|
||||
|
||||
issue_4001: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
ie8: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
function f() {
|
||||
return a;
|
||||
var b;
|
||||
}
|
||||
var c = f();
|
||||
(function g() {
|
||||
c[42];
|
||||
f;
|
||||
})();
|
||||
(function a() {});
|
||||
}(42));
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return a;
|
||||
}
|
||||
var a;
|
||||
console.log((a = 42, void f()[42], void function a() {}));
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_4015: {
|
||||
rename = true
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var n, a = 0, b;
|
||||
function f() {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (b) {
|
||||
(function g() {
|
||||
(function b() {
|
||||
a++;
|
||||
})();
|
||||
})();
|
||||
}
|
||||
}
|
||||
f();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var n, o = 0, c;
|
||||
function t() {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (c) {
|
||||
(function n() {
|
||||
(function c() {
|
||||
o++;
|
||||
})();
|
||||
})();
|
||||
}
|
||||
}
|
||||
t();
|
||||
console.log(o);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_4019: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = function() {
|
||||
try {
|
||||
console.log("FAIL");
|
||||
} catch (b) {}
|
||||
}, a = (console.log(a.length), ++a);
|
||||
}
|
||||
expect: {
|
||||
var o = function() {
|
||||
try {
|
||||
console.log("FAIL");
|
||||
} catch (o) {}
|
||||
}, o = (console.log(o.length), ++o);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
issue_4028: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
function a() {
|
||||
try {
|
||||
A;
|
||||
} catch (e) {}
|
||||
}
|
||||
var b = a += a;
|
||||
console.log(typeof b);
|
||||
}
|
||||
expect: {
|
||||
function a() {
|
||||
try {
|
||||
A;
|
||||
} catch (a) {}
|
||||
}
|
||||
var b = a += a;
|
||||
console.log(typeof b);
|
||||
}
|
||||
expect_stdout: "string"
|
||||
}
|
||||
|
||||
issue_2737: {
|
||||
options = {
|
||||
ie8: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(a) {
|
||||
a();
|
||||
})(function f() {
|
||||
console.log(typeof f);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
(function(a) {
|
||||
a();
|
||||
})(function f() {
|
||||
console.log(typeof f);
|
||||
});
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
@@ -573,3 +573,93 @@ issue_3600: {
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
iife_if_return_simple: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
inline: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
if (console)
|
||||
return console.log("PASS");
|
||||
console.log("FAIL");
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
console ? console.log("PASS") : console.log("FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
nested_if_break: {
|
||||
options = {
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
for (var i = 0; i < 3; i++)
|
||||
L1: if ("number" == typeof i) {
|
||||
if (0 === i) break L1;
|
||||
console.log(i);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (var i = 0; i < 3; i++)
|
||||
L1: if ("number" == typeof i)
|
||||
if (0 !== i) console.log(i);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
nested_if_continue: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
function f(n) {
|
||||
var i = 0;
|
||||
do {
|
||||
if ("number" == typeof n) {
|
||||
if (0 === n) {
|
||||
console.log("even", i);
|
||||
continue;
|
||||
}
|
||||
if (1 === n) {
|
||||
console.log("odd", i);
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
} while (0 <= (n -= 2));
|
||||
}
|
||||
f(37);
|
||||
f(42);
|
||||
}
|
||||
expect: {
|
||||
function f(n) {
|
||||
for (var i = 0;
|
||||
"number" == typeof n
|
||||
&& (0 !== n
|
||||
? 1 !== n
|
||||
? i++
|
||||
: console.log("odd", i)
|
||||
: console.log("even", i)),
|
||||
0 <= (n -= 2););
|
||||
}
|
||||
f(37);
|
||||
f(42);
|
||||
}
|
||||
expect_stdout: [
|
||||
"odd 18",
|
||||
"even 21",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ non_hoisted_function_after_return: {
|
||||
}
|
||||
expect: {
|
||||
function foo(x) {
|
||||
return x ? bar() : baz();
|
||||
return (x ? bar : baz)();
|
||||
function bar() { return 7 }
|
||||
function baz() { return 8 }
|
||||
}
|
||||
@@ -90,13 +90,13 @@ non_hoisted_function_after_return_2a: {
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
|
||||
"WARN: Dropping unused variable a [test/compress/issue-1034.js:4,20]",
|
||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]",
|
||||
"INFO: pass 0: last_count: Infinity, count: 37",
|
||||
"INFO: pass 0: last_count: Infinity, count: 36",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
|
||||
"INFO: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
|
||||
"INFO: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
|
||||
"INFO: pass 1: last_count: 37, count: 18",
|
||||
"INFO: pass 1: last_count: 36, count: 18",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ non_hoisted_function_after_return_strict: {
|
||||
expect: {
|
||||
"use strict";
|
||||
function foo(x) {
|
||||
return x ? bar() : baz();
|
||||
return (x ? bar : baz)();
|
||||
function bar() { return 7 }
|
||||
function baz() { return 8 }
|
||||
}
|
||||
@@ -248,13 +248,13 @@ non_hoisted_function_after_return_2a_strict: {
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,16]",
|
||||
"WARN: Dropping unused variable a [test/compress/issue-1034.js:5,20]",
|
||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:12,21]",
|
||||
"INFO: pass 0: last_count: Infinity, count: 48",
|
||||
"INFO: pass 0: last_count: Infinity, count: 47",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:10,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
|
||||
"INFO: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
|
||||
"INFO: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
|
||||
"INFO: pass 1: last_count: 48, count: 29",
|
||||
"INFO: pass 1: last_count: 47, count: 29",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,9 @@ issue_1639_1: {
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
|
||||
if (--b, 0) var ignore = 0;
|
||||
for (var a = 100, b = 10, L1 = 5, ignore; --L1 > 0;) {
|
||||
--b;
|
||||
}
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "100 6"
|
||||
|
||||
@@ -35,11 +35,7 @@ f7: {
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_exact: [
|
||||
"var b = 10;",
|
||||
"",
|
||||
"!function() {",
|
||||
" b = 100;",
|
||||
"}(), console.log(100, b);",
|
||||
"console.log(100, 100);",
|
||||
]
|
||||
expect_stdout: true
|
||||
expect_stdout: "100 100"
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ mangle_props: {
|
||||
obj[1/0],
|
||||
obj["Infinity"],
|
||||
obj[-1/0],
|
||||
obj[-1/0],
|
||||
obj[-(1/0)],
|
||||
obj["-Infinity"],
|
||||
obj[null],
|
||||
obj["null"]
|
||||
|
||||
@@ -1,98 +1,111 @@
|
||||
issue_269_1: {
|
||||
options = {
|
||||
options = {
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
f(
|
||||
String(x),
|
||||
Number(x),
|
||||
Boolean(x),
|
||||
input: {
|
||||
var x = {};
|
||||
console.log(
|
||||
String(x),
|
||||
Number(x),
|
||||
Boolean(x),
|
||||
|
||||
String(),
|
||||
Number(),
|
||||
Boolean()
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
f(
|
||||
x + '', +x, !!x,
|
||||
'', 0, false
|
||||
);
|
||||
}
|
||||
String(),
|
||||
Number(),
|
||||
Boolean()
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
console.log(
|
||||
x + "", +x, !!x,
|
||||
"", 0, false
|
||||
);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_269_dangers: {
|
||||
options = {
|
||||
options = {
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
f(
|
||||
String(x, x),
|
||||
Number(x, x),
|
||||
Boolean(x, x)
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
f(String(x, x), Number(x, x), Boolean(x, x));
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
console.log(
|
||||
String(x, x),
|
||||
Number(x, x),
|
||||
Boolean(x, x)
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
console.log(String(x, x), Number(x, x), Boolean(x, x));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_269_in_scope: {
|
||||
options = {
|
||||
options = {
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var String, Number, Boolean;
|
||||
f(
|
||||
String(x),
|
||||
Number(x, x),
|
||||
Boolean(x)
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var String, Number, Boolean;
|
||||
f(String(x), Number(x, x), Boolean(x));
|
||||
}
|
||||
input: {
|
||||
var String, Number, Boolean;
|
||||
var x = {};
|
||||
console.log(
|
||||
String(x),
|
||||
Number(x, x),
|
||||
Boolean(x)
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var String, Number, Boolean;
|
||||
var x = {};
|
||||
console.log(String(x), Number(x, x), Boolean(x));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
strings_concat: {
|
||||
options = {
|
||||
options = {
|
||||
strings: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
f(
|
||||
String(x + 'str'),
|
||||
String('str' + x)
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
f(
|
||||
x + 'str',
|
||||
'str' + x
|
||||
);
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
console.log(
|
||||
String(x + "str"),
|
||||
String("str" + x)
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
console.log(
|
||||
x + "str",
|
||||
"str" + x
|
||||
);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
regexp: {
|
||||
options = {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
RegExp("foo");
|
||||
RegExp("bar", "ig");
|
||||
RegExp(foo);
|
||||
RegExp("bar", ig);
|
||||
RegExp("should", "fail");
|
||||
}
|
||||
expect: {
|
||||
/foo/;
|
||||
/bar/ig;
|
||||
RegExp(foo);
|
||||
RegExp("bar", ig);
|
||||
RegExp("should", "fail");
|
||||
}
|
||||
expect_warnings: [
|
||||
'WARN: Error converting RegExp("should","fail") [test/compress/issue-269.js:5,2]',
|
||||
]
|
||||
input: {
|
||||
RegExp("foo");
|
||||
RegExp("bar", "ig");
|
||||
RegExp(foo);
|
||||
RegExp("bar", ig);
|
||||
RegExp("should", "fail");
|
||||
}
|
||||
expect: {
|
||||
/foo/;
|
||||
/bar/ig;
|
||||
RegExp(foo);
|
||||
RegExp("bar", ig);
|
||||
RegExp("should", "fail");
|
||||
}
|
||||
expect_warnings: [
|
||||
'WARN: Error converting RegExp("should","fail") [test/compress/issue-269.js:5,8]',
|
||||
]
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ warn: {
|
||||
}().length);
|
||||
}
|
||||
expect_warnings: [
|
||||
"WARN: Function.prototype.caller not supported [test/compress/issue-2719.js:5,19]",
|
||||
"WARN: Function.prototype.arguments not supported [test/compress/issue-2719.js:5,19]",
|
||||
"WARN: Function.prototype.caller not supported [test/compress/issue-2719.js:5,19]",
|
||||
]
|
||||
}
|
||||
|
||||
128
test/compress/issue-3768.js
Normal file
128
test/compress/issue-3768.js
Normal file
@@ -0,0 +1,128 @@
|
||||
mangle: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var e = eval, x = 42;
|
||||
(function() {
|
||||
console.log(e("typeof x"));
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
var e = eval, x = 42;
|
||||
(function() {
|
||||
console.log(e("typeof x"));
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
compress: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var a = 42;
|
||||
return eval("typeof a");
|
||||
}(), function(e) {
|
||||
var a = null;
|
||||
return e("typeof a");
|
||||
}(eval), function(eval) {
|
||||
var a = false;
|
||||
return eval("typeof a");
|
||||
}(eval), function(f) {
|
||||
var a = "STRING";
|
||||
var eval = f;
|
||||
return eval("typeof a");
|
||||
}(eval), function(g) {
|
||||
var a = eval;
|
||||
function eval() {
|
||||
return g;
|
||||
}
|
||||
return eval()("typeof a");
|
||||
}(eval));
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var a = 42;
|
||||
return eval("typeof a");
|
||||
}(), (0, eval)("typeof a"), function(eval) {
|
||||
var a = false;
|
||||
return eval("typeof a");
|
||||
}(eval), function(f) {
|
||||
var a = "STRING";
|
||||
var eval = f;
|
||||
return eval("typeof a");
|
||||
}(eval), function(g) {
|
||||
var a = eval;
|
||||
function eval() {
|
||||
return g;
|
||||
}
|
||||
return eval()("typeof a");
|
||||
}(eval));
|
||||
}
|
||||
expect_stdout: "number undefined boolean string undefined"
|
||||
}
|
||||
|
||||
call_arg_1: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var z = "foo";
|
||||
(function() {
|
||||
var z = false;
|
||||
(function(e) {
|
||||
var z = 42;
|
||||
e("console.log(typeof z)");
|
||||
})(eval);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
var z = "foo";
|
||||
(function() {
|
||||
var o = false;
|
||||
(function(o) {
|
||||
var a = 42;
|
||||
o("console.log(typeof z)");
|
||||
})(eval);
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
call_arg_2: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
function eval() {
|
||||
console.log("PASS");
|
||||
}
|
||||
var z = "foo";
|
||||
(function() {
|
||||
var z = false;
|
||||
(function(e) {
|
||||
var z = 42;
|
||||
e("console.log(typeof z)");
|
||||
})(eval);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
function n() {
|
||||
console.log("PASS");
|
||||
}
|
||||
var o = "foo";
|
||||
(function() {
|
||||
var o = false;
|
||||
(function(o) {
|
||||
var n = 42;
|
||||
o("console.log(typeof z)");
|
||||
})(n);
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
@@ -16,7 +16,6 @@ wrongly_optimized: {
|
||||
function func() {
|
||||
foo();
|
||||
}
|
||||
// TODO: optimize to `func(), bar()`
|
||||
(func(), 1) && bar();
|
||||
func(), 1, bar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ cond_5: {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
some_condition() && some_other_condition() ? do_something() : alternate();
|
||||
(some_condition() && some_other_condition() ? do_something : alternate)();
|
||||
if (some_condition() && some_other_condition()) do_something();
|
||||
}
|
||||
}
|
||||
@@ -84,6 +84,7 @@ wrongly_optimized: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
expression: true,
|
||||
}
|
||||
@@ -99,8 +100,8 @@ wrongly_optimized: {
|
||||
function func() {
|
||||
foo();
|
||||
}
|
||||
// TODO: optimize to `func(), bar()`
|
||||
if (func(), 1) bar();
|
||||
func(), 1;
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ remove_sequence: {
|
||||
(0, 1, _decorators.logThis)();
|
||||
}
|
||||
expect: {
|
||||
eval();
|
||||
(0, eval)();
|
||||
logThis();
|
||||
(0, _decorators.logThis)();
|
||||
}
|
||||
|
||||
@@ -53,20 +53,23 @@ this_binding_conditionals: {
|
||||
this_binding_collapse_vars: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
var c = a; c();
|
||||
var d = a.b; d();
|
||||
var e = eval; e();
|
||||
function f() {
|
||||
"use strict";
|
||||
var c = a; c();
|
||||
var d = a.b; d();
|
||||
var e = eval; e();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
a();
|
||||
(0, a.b)();
|
||||
(0, eval)();
|
||||
function f() {
|
||||
"use strict";
|
||||
a();
|
||||
(0, a.b)();
|
||||
(0, eval)();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +100,7 @@ this_binding_side_effects: {
|
||||
(function(foo) {
|
||||
foo();
|
||||
(0, foo.bar)();
|
||||
eval("console.log(foo);");
|
||||
(0, eval)("console.log(foo);");
|
||||
}());
|
||||
(function(foo) {
|
||||
"use strict";
|
||||
@@ -144,7 +147,7 @@ this_binding_sequences: {
|
||||
return eval("this");
|
||||
}()),
|
||||
console.log(typeof function() {
|
||||
return eval("this");
|
||||
return (0, eval)("this");
|
||||
}()),
|
||||
console.log(typeof function() {
|
||||
"use strict";
|
||||
|
||||
1057
test/compress/join_vars.js
Normal file
1057
test/compress/join_vars.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -306,8 +306,6 @@ issue_2298: {
|
||||
expect: {
|
||||
!function() {
|
||||
(function() {
|
||||
var a = undefined;
|
||||
var undefined = a++;
|
||||
try {
|
||||
!function() {
|
||||
(void 0)[1] = "foo";
|
||||
@@ -728,7 +726,7 @@ issue_2630_3: {
|
||||
(function() {
|
||||
(function f1() {
|
||||
f2();
|
||||
--x >= 0 && f1({});
|
||||
--x >= 0 && f1();
|
||||
})(a++);
|
||||
function f2() {
|
||||
a++;
|
||||
@@ -873,13 +871,13 @@ iife_func_side_effects: {
|
||||
function z() {
|
||||
console.log("z");
|
||||
}
|
||||
(function(a, b) {
|
||||
(function(b) {
|
||||
return function() {
|
||||
console.log("FAIL");
|
||||
} + b();
|
||||
})(x(), function() {
|
||||
})((x(), function() {
|
||||
return y();
|
||||
}, z());
|
||||
}), z());
|
||||
}
|
||||
expect_stdout: [
|
||||
"x",
|
||||
@@ -1155,3 +1153,302 @@ issue_3423_2: {
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
collapse_vars_repeated: {
|
||||
options = {
|
||||
booleans: true,
|
||||
collapse_vars: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
keep_fargs: "strict",
|
||||
loops: true,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
var dummy = 3, a = 5, unused = 2, a = 1, a = 3;
|
||||
return -a;
|
||||
}
|
||||
function f2(x) {
|
||||
var a = 3, a = x;
|
||||
return a;
|
||||
}
|
||||
(function(x) {
|
||||
var a = "GOOD" + x, e = "BAD", k = "!", e = a;
|
||||
console.log(e + k);
|
||||
})("!"),
|
||||
(function(x) {
|
||||
var a = "GOOD" + x, e = "BAD" + x, k = "!", e = a;
|
||||
console.log(e + k);
|
||||
})("!");
|
||||
}
|
||||
expect: {
|
||||
function f1() {
|
||||
return -3;
|
||||
}
|
||||
function f2(x) {
|
||||
return x;
|
||||
}
|
||||
(function() {
|
||||
console.log("GOOD!!");
|
||||
})(),
|
||||
(function() {
|
||||
console.log("GOOD!!");
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
chained_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a, b) {
|
||||
var c = a, c = b;
|
||||
b++;
|
||||
return c;
|
||||
}(1, 2));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(b) {
|
||||
var c = 1, c = b;
|
||||
b++;
|
||||
return c;
|
||||
}(2));
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
replace_all_var_scope: {
|
||||
rename = true
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
unused: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
var a = 100, b = 10;
|
||||
(function(r, a) {
|
||||
switch (~a) {
|
||||
case (b += a):
|
||||
case a++:
|
||||
}
|
||||
})(--b, a);
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = 100, b = 10;
|
||||
(function(c) {
|
||||
switch (~a) {
|
||||
case (b += a):
|
||||
case c++:
|
||||
}
|
||||
})((--b, a));
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "100 109"
|
||||
}
|
||||
|
||||
issue_1583: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function m(t) {
|
||||
(function(e) {
|
||||
t = e();
|
||||
})(function() {
|
||||
return (function(a) {
|
||||
return a;
|
||||
})(function(a) {});
|
||||
});
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function m(t) {
|
||||
(function() {
|
||||
(function() {
|
||||
return (function() {
|
||||
return function(a) {};
|
||||
})();
|
||||
})();
|
||||
})();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issues_3267_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(x) {
|
||||
x();
|
||||
})(function() {
|
||||
(function(i) {
|
||||
if (i)
|
||||
return console.log("PASS");
|
||||
throw "FAIL";
|
||||
})(Object());
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
if (Object())
|
||||
return console.log("PASS");
|
||||
throw "FAIL";
|
||||
}();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
trailing_argument_side_effects: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return "FAIL";
|
||||
}
|
||||
console.log(function(a, b) {
|
||||
return b || "PASS";
|
||||
}(f()));
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return "FAIL";
|
||||
}
|
||||
console.log(function(b) {
|
||||
return b || "PASS";
|
||||
}(void f()));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
recursive_iife_1: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f(a, b) {
|
||||
return b || f("FAIL", "PASS");
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function f(a, b) {
|
||||
return b || f(0, "PASS");
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
recursive_iife_2: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f(a, b) {
|
||||
return b || f("FAIL", "PASS");
|
||||
}(null, 0));
|
||||
}
|
||||
expect: {
|
||||
console.log(function f(a, b) {
|
||||
return b || f(0, "PASS");
|
||||
}(0, 0));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
recursive_iife_3: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1, c = "PASS";
|
||||
(function() {
|
||||
function f(b, d, e) {
|
||||
a-- && f(null, 42, 0);
|
||||
e && (c = "FAIL");
|
||||
d && d.p;
|
||||
}
|
||||
var a_1 = f();
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var a = 1, c = "PASS";
|
||||
(function() {
|
||||
(function f(b, d, e) {
|
||||
a-- && f(0, 42, 0);
|
||||
e && (c = "FAIL");
|
||||
d && d.p;
|
||||
})();
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3619: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1, b = "FAIL";
|
||||
(function f(c, d) {
|
||||
function g() {
|
||||
d && (b = "PASS", 0 <= --a && g());
|
||||
0 <= --a && f(0, "function");
|
||||
}
|
||||
g();
|
||||
})();
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var a = 1, b = "FAIL";
|
||||
(function f(c, d) {
|
||||
function g() {
|
||||
d && (b = "PASS", 0 <= --a && g());
|
||||
0 <= --a && f(0, "function");
|
||||
}
|
||||
g();
|
||||
})();
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ labels_1: {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
out: {
|
||||
@@ -21,6 +22,7 @@ labels_2: {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
out: {
|
||||
@@ -61,6 +63,7 @@ labels_4: {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
out: for (var i = 0; i < 5; ++i) {
|
||||
@@ -105,6 +108,9 @@ labels_5: {
|
||||
}
|
||||
|
||||
labels_6: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
out: break out;
|
||||
};
|
||||
@@ -159,6 +165,7 @@ labels_9: {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
out: while (foo) {
|
||||
|
||||
@@ -6,7 +6,7 @@ while_becomes_for: {
|
||||
while (foo()) bar();
|
||||
}
|
||||
expect: {
|
||||
for (; foo(); ) bar();
|
||||
for (;foo();) bar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ drop_if_break_1: {
|
||||
if (foo()) break;
|
||||
}
|
||||
expect: {
|
||||
for (; !foo(););
|
||||
for (;!foo(););
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ drop_if_break_2: {
|
||||
if (foo()) break;
|
||||
}
|
||||
expect: {
|
||||
for (; bar() && !foo(););
|
||||
for (;bar() && !foo(););
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ drop_if_break_4: {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (; bar() && (x(), y(), !foo());) z(), k();
|
||||
for (;bar() && (x(), y(), !foo());) z(), k();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ drop_if_else_break_1: {
|
||||
for (;;) if (foo()) bar(); else break;
|
||||
}
|
||||
expect: {
|
||||
for (; foo(); ) bar();
|
||||
for (;foo();) bar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ drop_if_else_break_2: {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (; bar() && foo();) baz();
|
||||
for (;bar() && foo();) baz();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ drop_if_else_break_3: {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (; bar() && foo();) {
|
||||
for (;bar() && foo();) {
|
||||
baz();
|
||||
stuff1();
|
||||
stuff2();
|
||||
@@ -138,7 +138,7 @@ drop_if_else_break_4: {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (; bar() && (x(), y(), foo());) baz(), z(), k();
|
||||
for (;bar() && (x(), y(), foo());) baz(), z(), k();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,13 +523,13 @@ issue_2740_1: {
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
for (; ; ) break;
|
||||
for (a(); ; ) break;
|
||||
for (; b(); ) break;
|
||||
for (c(); d(); ) break;
|
||||
for (; ; e()) break;
|
||||
for (f(); ; g()) break;
|
||||
for (; h(); i()) break;
|
||||
for (;;) break;
|
||||
for (a();;) break;
|
||||
for (;b();) break;
|
||||
for (c(); d();) break;
|
||||
for (;;e()) break;
|
||||
for (f();; g()) break;
|
||||
for (;h(); i()) break;
|
||||
for (j(); k(); l()) break;
|
||||
}
|
||||
expect: {
|
||||
@@ -549,6 +549,7 @@ issue_2740_2: {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
L1: while (x()) {
|
||||
@@ -564,6 +565,7 @@ issue_2740_3: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
L1: for (var x = 0; x < 3; x++) {
|
||||
@@ -574,9 +576,11 @@ issue_2740_3: {
|
||||
console.log(x, y);
|
||||
}
|
||||
expect: {
|
||||
L1: for (var x = 0; x < 3; x++)
|
||||
for (var y = 0; y < 2; y++)
|
||||
L1: for (var x = 0; x < 3; x++) {
|
||||
var y = 0;
|
||||
if (y < 2)
|
||||
break L1;
|
||||
}
|
||||
console.log(x, y);
|
||||
}
|
||||
expect_stdout: "0 0"
|
||||
@@ -587,6 +591,7 @@ issue_2740_4: {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
L1: for (var x = 0; x < 3; x++) {
|
||||
@@ -611,6 +616,7 @@ issue_2740_5: {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
L1: for (var x = 0; x < 3; x++) {
|
||||
@@ -668,7 +674,7 @@ issue_3371: {
|
||||
function a() {
|
||||
console.log("PASS");
|
||||
}
|
||||
for (; a(); );
|
||||
for (;a(););
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -750,6 +756,335 @@ empty_for_in_side_effects: {
|
||||
expect_warnings: [
|
||||
"WARN: Dropping unused variable b [test/compress/loops.js:4,16]",
|
||||
"INFO: Dropping unused loop variable a [test/compress/loops.js:1,17]",
|
||||
"WARN: Side effects in object of for-in loop [test/compress/loops.js:1,17]",
|
||||
"WARN: Side effects in object of for-in loop [test/compress/loops.js:2,17]",
|
||||
]
|
||||
}
|
||||
|
||||
empty_for_in_prop_init: {
|
||||
options = {
|
||||
loops: true,
|
||||
pure_getters: "strict",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f() {
|
||||
var a = "bar";
|
||||
for ((a, f)[a] in console.log("foo"));
|
||||
return a;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var a = "bar";
|
||||
console.log("foo");
|
||||
return a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"bar",
|
||||
]
|
||||
expect_warnings: [
|
||||
"INFO: Dropping unused loop variable f [test/compress/loops.js:3,21]",
|
||||
"WARN: Side effects in object of for-in loop [test/compress/loops.js:3,30]",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3631_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var c = 0;
|
||||
L: do {
|
||||
for (;;) continue L;
|
||||
var b = 1;
|
||||
} while (b && c++);
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = 0;
|
||||
do {
|
||||
var b;
|
||||
} while (b && c++);
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
issue_3631_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
L: for (var a = 1; a--; console.log(b)) {
|
||||
for (;;) continue L;
|
||||
var b = "FAIL";
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (var a = 1; a--; console.log(b))
|
||||
var b;
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
loop_if_break: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b) {
|
||||
try {
|
||||
while (a) {
|
||||
if (b) {
|
||||
break;
|
||||
var c = 42;
|
||||
console.log(c);
|
||||
} else {
|
||||
var d = false;
|
||||
throw d;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("E:", e);
|
||||
}
|
||||
console.log(a, b, c, d);
|
||||
}
|
||||
f(0, 0);
|
||||
f(0, 1);
|
||||
f(1, 0);
|
||||
f(1, 1);
|
||||
}
|
||||
expect: {
|
||||
function f(a, b) {
|
||||
try {
|
||||
for (;a && !b;) {
|
||||
var d = false;
|
||||
throw d;
|
||||
var c;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("E:", e);
|
||||
}
|
||||
console.log(a, b, c, d);
|
||||
}
|
||||
f(0, 0);
|
||||
f(0, 1);
|
||||
f(1, 0);
|
||||
f(1, 1);
|
||||
}
|
||||
expect_stdout: [
|
||||
"0 0 undefined undefined",
|
||||
"0 1 undefined undefined",
|
||||
"E: false",
|
||||
"1 0 undefined false",
|
||||
"1 1 undefined undefined",
|
||||
]
|
||||
}
|
||||
|
||||
loop_return: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
while (a) return 42;
|
||||
return "foo";
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
if (a) return 42;
|
||||
return "foo";
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect_stdout: "foo 42"
|
||||
}
|
||||
|
||||
issue_3634_1: {
|
||||
options = {
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
var b = 0;
|
||||
L: while (++b < 2)
|
||||
while (1)
|
||||
if (b) break L;
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var b = 0;
|
||||
L: for (;++b < 2;)
|
||||
for (;1;)
|
||||
if (b) break L;
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3634_2: {
|
||||
options = {
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
var b = 0;
|
||||
L: while (++b < 2)
|
||||
while (1)
|
||||
if (!b)
|
||||
continue L;
|
||||
else
|
||||
break L;
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var b = 0;
|
||||
L: for (;++b < 2;)
|
||||
for (;1;)
|
||||
if (!b)
|
||||
continue L;
|
||||
else
|
||||
break L;
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_4075: {
|
||||
options = {
|
||||
loops: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = "FAIL";
|
||||
(function() {
|
||||
for (a in { PASS: 0 });
|
||||
})()
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "FAIL";
|
||||
(function() {
|
||||
for (a in { PASS: 0 });
|
||||
})()
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4082: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
loops: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS";
|
||||
(function(a) {
|
||||
for (a in "foo")
|
||||
var b;
|
||||
})();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS";
|
||||
(function(a) {
|
||||
for (a in "foo");
|
||||
})();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4084: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
loops: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
function f(a) {
|
||||
var b = a++;
|
||||
for (a in "foo");
|
||||
}
|
||||
f();
|
||||
return typeof a;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
(function() {
|
||||
0;
|
||||
})();
|
||||
return typeof a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_4091_1: {
|
||||
options = {
|
||||
loops: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
throw "FAIL";
|
||||
} catch (e) {
|
||||
for (var e in 42);
|
||||
}
|
||||
console.log(e && e);
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
throw "FAIL";
|
||||
} catch (e) {
|
||||
var e;
|
||||
}
|
||||
console.log(e && e);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_4091_2: {
|
||||
options = {
|
||||
loops: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
throw "FAIL";
|
||||
} catch (e) {
|
||||
for (e in 42);
|
||||
var e;
|
||||
}
|
||||
console.log(e && e);
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
throw "FAIL";
|
||||
} catch (e) {
|
||||
var e;
|
||||
}
|
||||
console.log(e && e);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
2862
test/compress/merge_vars.js
Normal file
2862
test/compress/merge_vars.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -91,7 +91,7 @@ evaluate_1: {
|
||||
expect: {
|
||||
console.log(
|
||||
x + 1 + 2,
|
||||
1 * x * 2,
|
||||
2 * +x,
|
||||
+x + 1 + 2,
|
||||
1 + x + 2 + 3,
|
||||
3 | x,
|
||||
@@ -130,7 +130,7 @@ evaluate_1_unsafe_math: {
|
||||
expect: {
|
||||
console.log(
|
||||
x + 1 + 2,
|
||||
2 * x,
|
||||
2 * +x,
|
||||
+x + 3,
|
||||
1 + x + 2 + 3,
|
||||
3 | x,
|
||||
@@ -148,45 +148,52 @@ evaluate_1_unsafe_math: {
|
||||
evaluate_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unsafe_math: false,
|
||||
}
|
||||
input: {
|
||||
var x = "42", y = null;
|
||||
[
|
||||
x + 1 + 2,
|
||||
x * 1 * 2,
|
||||
+x + 1 + 2,
|
||||
1 + x + 2 + 3,
|
||||
1 | x | 2 | 3,
|
||||
1 + x-- + 2 + 3,
|
||||
1 + (x*y + 2) + 3,
|
||||
1 + (2 + x + 3),
|
||||
1 + (2 + ~x + 3),
|
||||
-y + (2 + ~x + 3),
|
||||
1 & (2 & x & 3),
|
||||
1 + (2 + (x |= 0) + 3),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
function f(num) {
|
||||
var x = "" + num, y = null;
|
||||
[
|
||||
x + 1 + 2,
|
||||
x * 1 * 2,
|
||||
+x + 1 + 2,
|
||||
1 + x + 2 + 3,
|
||||
1 | x | 2 | 3,
|
||||
1 + x-- + 2 + 3,
|
||||
1 + (x*y + 2) + 3,
|
||||
1 + (2 + x + 3),
|
||||
1 + (2 + ~x + 3),
|
||||
-y + (2 + ~x + 3),
|
||||
1 & (2 & x & 3),
|
||||
1 + (2 + (x |= 0) + 3),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
f(42);
|
||||
}
|
||||
expect: {
|
||||
var x = "42", y = null;
|
||||
[
|
||||
x + 1 + 2,
|
||||
1 * x * 2,
|
||||
+x + 1 + 2,
|
||||
1 + x + 2 + 3,
|
||||
3 | x,
|
||||
1 + x-- + 2 + 3,
|
||||
x*y + 2 + 1 + 3,
|
||||
1 + (2 + x + 3),
|
||||
2 + ~x + 3 + 1,
|
||||
2 + ~x + 3 - y,
|
||||
0 & x,
|
||||
2 + (x |= 0) + 3 + 1,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
function f(num) {
|
||||
var x = "" + num, y = null;
|
||||
[
|
||||
x + "12",
|
||||
2 * x,
|
||||
+x + 1 + 2,
|
||||
1 + x + "23",
|
||||
3 | x,
|
||||
1 + x-- + 2 + 3,
|
||||
x*y + 2 + 1 + 3,
|
||||
2 + x + 3 + 1,
|
||||
2 + ~x + 3 + 1,
|
||||
2 + ~x + 3,
|
||||
0 & x,
|
||||
2 + (x |= 0) + 3 + 1,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
f(42);
|
||||
}
|
||||
expect_stdout: [
|
||||
"string 4212",
|
||||
@@ -207,45 +214,52 @@ evaluate_2: {
|
||||
evaluate_2_unsafe_math: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var x = "42", y = null;
|
||||
[
|
||||
x + 1 + 2,
|
||||
x * 1 * 2,
|
||||
+x + 1 + 2,
|
||||
1 + x + 2 + 3,
|
||||
1 | x | 2 | 3,
|
||||
1 + x-- + 2 + 3,
|
||||
1 + (x*y + 2) + 3,
|
||||
1 + (2 + x + 3),
|
||||
1 + (2 + ~x + 3),
|
||||
-y + (2 + ~x + 3),
|
||||
1 & (2 & x & 3),
|
||||
1 + (2 + (x |= 0) + 3),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
function f(num) {
|
||||
var x = "" + num, y = null;
|
||||
[
|
||||
x + 1 + 2,
|
||||
x * 1 * 2,
|
||||
+x + 1 + 2,
|
||||
1 + x + 2 + 3,
|
||||
1 | x | 2 | 3,
|
||||
1 + x-- + 2 + 3,
|
||||
1 + (x*y + 2) + 3,
|
||||
1 + (2 + x + 3),
|
||||
1 + (2 + ~x + 3),
|
||||
-y + (2 + ~x + 3),
|
||||
1 & (2 & x & 3),
|
||||
1 + (2 + (x |= 0) + 3),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
f(42);
|
||||
}
|
||||
expect: {
|
||||
var x = "42", y = null;
|
||||
[
|
||||
x + 1 + 2,
|
||||
2 * x,
|
||||
+x + 3,
|
||||
1 + x + 2 + 3,
|
||||
3 | x,
|
||||
6 + x--,
|
||||
x*y + 6,
|
||||
1 + (2 + x + 3),
|
||||
6 + ~x,
|
||||
5 + ~x - y,
|
||||
0 & x,
|
||||
6 + (x |= 0),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
function f(num) {
|
||||
var x = "" + num, y = null;
|
||||
[
|
||||
x + "12",
|
||||
2 * x,
|
||||
+x + 3,
|
||||
1 + x + "23",
|
||||
3 | x,
|
||||
6 + x--,
|
||||
x*y + 6,
|
||||
6 + x,
|
||||
6 + ~x,
|
||||
5 + ~x,
|
||||
0 & x,
|
||||
6 + (x |= 0),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
f(42);
|
||||
}
|
||||
expect_stdout: [
|
||||
"string 4212",
|
||||
@@ -310,45 +324,52 @@ evaluate_4: {
|
||||
evaluate_5: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unsafe_math: false,
|
||||
}
|
||||
input: {
|
||||
var a = "1";
|
||||
[
|
||||
+a + 2 + 3,
|
||||
+a + 2 - 3,
|
||||
+a - 2 + 3,
|
||||
+a - 2 - 3,
|
||||
2 + +a + 3,
|
||||
2 + +a - 3,
|
||||
2 - +a + 3,
|
||||
2 - +a - 3,
|
||||
2 + 3 + +a,
|
||||
2 + 3 - +a,
|
||||
2 - 3 + +a,
|
||||
2 - 3 - +a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
function f(num) {
|
||||
var a = "" + num;
|
||||
[
|
||||
+a + 2 + 3,
|
||||
+a + 2 - 3,
|
||||
+a - 2 + 3,
|
||||
+a - 2 - 3,
|
||||
2 + +a + 3,
|
||||
2 + +a - 3,
|
||||
2 - +a + 3,
|
||||
2 - +a - 3,
|
||||
2 + 3 + +a,
|
||||
2 + 3 - +a,
|
||||
2 - 3 + +a,
|
||||
2 - 3 - +a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
f(1);
|
||||
}
|
||||
expect: {
|
||||
var a = "1";
|
||||
[
|
||||
+a + 2 + 3,
|
||||
+a + 2 - 3,
|
||||
a - 2 + 3,
|
||||
a - 2 - 3,
|
||||
+a + 2 + 3,
|
||||
+a + 2 - 3,
|
||||
2 - a + 3,
|
||||
2 - a - 3,
|
||||
+a + 5,
|
||||
5 - a,
|
||||
+a - 1,
|
||||
-1 - a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
function f(num) {
|
||||
var a = "" + num;
|
||||
[
|
||||
+a + 2 + 3,
|
||||
+a + 2 - 3,
|
||||
a - 2 + 3,
|
||||
a - 2 - 3,
|
||||
+a + 2 + 3,
|
||||
+a + 2 - 3,
|
||||
2 - a + 3,
|
||||
2 - a - 3,
|
||||
+a + 5,
|
||||
5 - a,
|
||||
+a - 1,
|
||||
-1 - a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
f(1);
|
||||
}
|
||||
expect_stdout: [
|
||||
"number 6",
|
||||
@@ -369,45 +390,52 @@ evaluate_5: {
|
||||
evaluate_5_unsafe_math: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = "1";
|
||||
[
|
||||
+a + 2 + 3,
|
||||
+a + 2 - 3,
|
||||
+a - 2 + 3,
|
||||
+a - 2 - 3,
|
||||
2 + +a + 3,
|
||||
2 + +a - 3,
|
||||
2 - +a + 3,
|
||||
2 - +a - 3,
|
||||
2 + 3 + +a,
|
||||
2 + 3 - +a,
|
||||
2 - 3 + +a,
|
||||
2 - 3 - +a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
function f(num) {
|
||||
var a = "" + num;
|
||||
[
|
||||
+a + 2 + 3,
|
||||
+a + 2 - 3,
|
||||
+a - 2 + 3,
|
||||
+a - 2 - 3,
|
||||
2 + +a + 3,
|
||||
2 + +a - 3,
|
||||
2 - +a + 3,
|
||||
2 - +a - 3,
|
||||
2 + 3 + +a,
|
||||
2 + 3 - +a,
|
||||
2 - 3 + +a,
|
||||
2 - 3 - +a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
f(1);
|
||||
}
|
||||
expect: {
|
||||
var a = "1";
|
||||
[
|
||||
+a + 5,
|
||||
+a + -1,
|
||||
a - -1,
|
||||
a - 5,
|
||||
+a + 5,
|
||||
+a + -1,
|
||||
5 - a,
|
||||
-1 - a,
|
||||
+a + 5,
|
||||
5 - a,
|
||||
+a - 1,
|
||||
-1 - a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
function f(num) {
|
||||
var a = "" + num;
|
||||
[
|
||||
+a + 5,
|
||||
+a + -1,
|
||||
a - -1,
|
||||
a - 5,
|
||||
+a + 5,
|
||||
+a + -1,
|
||||
5 - a,
|
||||
-1 - a,
|
||||
+a + 5,
|
||||
5 - a,
|
||||
+a - 1,
|
||||
-1 - a,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
f(1);
|
||||
}
|
||||
expect_stdout: [
|
||||
"number 6",
|
||||
@@ -546,37 +574,44 @@ evaluate_6_unsafe_math: {
|
||||
evaluate_7: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unsafe_math: false,
|
||||
}
|
||||
input: {
|
||||
var x = "42", y;
|
||||
[
|
||||
+x + 2 + (3 + !y),
|
||||
+x + 2 + (3 - !y),
|
||||
+x + 2 - (3 + !y),
|
||||
+x + 2 - (3 - !y),
|
||||
+x - 2 + (3 + !y),
|
||||
+x - 2 + (3 - !y),
|
||||
+x - 2 - (3 + !y),
|
||||
+x - 2 - (3 - !y),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
function f(num, y) {
|
||||
var x = "" + num;
|
||||
[
|
||||
+x + 2 + (3 + !y),
|
||||
+x + 2 + (3 - !y),
|
||||
+x + 2 - (3 + !y),
|
||||
+x + 2 - (3 - !y),
|
||||
+x - 2 + (3 + !y),
|
||||
+x - 2 + (3 - !y),
|
||||
+x - 2 - (3 + !y),
|
||||
+x - 2 - (3 - !y),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
f(42);
|
||||
}
|
||||
expect: {
|
||||
var x = "42", y;
|
||||
[
|
||||
+x + 2 + (3 + !y),
|
||||
+x + 2 + (3 - !y),
|
||||
+x + 2 - (3 + !y),
|
||||
+x + 2 - (3 - !y),
|
||||
x - 2 + (3 + !y),
|
||||
x - 2 + (3 - !y),
|
||||
x - 2 - (3 + !y),
|
||||
x - 2 - (3 - !y),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
function f(num, y) {
|
||||
var x = "" + num;
|
||||
[
|
||||
+x + 2 + (3 + !y),
|
||||
+x + 2 + (3 - !y),
|
||||
+x + 2 - (3 + !y),
|
||||
+x + 2 - (3 - !y),
|
||||
x - 2 + (3 + !y),
|
||||
x - 2 + (3 - !y),
|
||||
x - 2 - (3 + !y),
|
||||
x - 2 - (3 - !y),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
f(42);
|
||||
}
|
||||
expect_stdout: [
|
||||
"number 48",
|
||||
@@ -593,37 +628,44 @@ evaluate_7: {
|
||||
evaluate_7_unsafe_math: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var x = "42", y;
|
||||
[
|
||||
+x + 2 + (3 + !y),
|
||||
+x + 2 + (3 - !y),
|
||||
+x + 2 - (3 + !y),
|
||||
+x + 2 - (3 - !y),
|
||||
+x - 2 + (3 + !y),
|
||||
+x - 2 + (3 - !y),
|
||||
+x - 2 - (3 + !y),
|
||||
+x - 2 - (3 - !y),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
function f(num, y) {
|
||||
var x = "" + num;
|
||||
[
|
||||
+x + 2 + (3 + !y),
|
||||
+x + 2 + (3 - !y),
|
||||
+x + 2 - (3 + !y),
|
||||
+x + 2 - (3 - !y),
|
||||
+x - 2 + (3 + !y),
|
||||
+x - 2 + (3 - !y),
|
||||
+x - 2 - (3 + !y),
|
||||
+x - 2 - (3 - !y),
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
f(42);
|
||||
}
|
||||
expect: {
|
||||
var x = "42", y;
|
||||
[
|
||||
+x + 5 + !y,
|
||||
+x + 5 - !y,
|
||||
+x + -1 - !y,
|
||||
+x + -1 + !y,
|
||||
x - -1 + !y,
|
||||
x - -1 - !y,
|
||||
x - 5 - !y,
|
||||
x - 5 + !y,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
function f(num, y) {
|
||||
var x = "" + num;
|
||||
[
|
||||
+x + 5 + !y,
|
||||
+x + 5 - !y,
|
||||
+x + -1 - !y,
|
||||
+x + -1 + !y,
|
||||
x - -1 + !y,
|
||||
x - -1 - !y,
|
||||
x - 5 - !y,
|
||||
x - 5 + !y,
|
||||
].forEach(function(n) {
|
||||
console.log(typeof n, n);
|
||||
});
|
||||
}
|
||||
f(42);
|
||||
}
|
||||
expect_stdout: [
|
||||
"number 48",
|
||||
@@ -637,6 +679,22 @@ evaluate_7_unsafe_math: {
|
||||
]
|
||||
}
|
||||
|
||||
evaluate_8_unsafe_math: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = [ "42" ];
|
||||
console.log(a * (1 / 7));
|
||||
}
|
||||
expect: {
|
||||
var a = [ "42" ];
|
||||
console.log(+a / 7);
|
||||
}
|
||||
expect_stdout: "6"
|
||||
}
|
||||
|
||||
NaN_redefined: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -669,6 +727,9 @@ issue_1710: {
|
||||
}
|
||||
|
||||
unary_binary_parenthesis: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
var v = [ 0, 1, NaN, Infinity, null, undefined, true, false, "", "foo", /foo/ ];
|
||||
v.forEach(function(x) {
|
||||
@@ -979,3 +1040,298 @@ unsafe_math_swap_constant: {
|
||||
}
|
||||
expect_stdout: "6 6 7 6 6 8 9 10"
|
||||
}
|
||||
|
||||
identity_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
0 + a;
|
||||
a + 0;
|
||||
0 - a;
|
||||
a - 0;
|
||||
1 * a;
|
||||
a * 1;
|
||||
1 / a;
|
||||
a / 1;
|
||||
}
|
||||
expect: {
|
||||
0 + a;
|
||||
a + 0;
|
||||
0 - a;
|
||||
+a;
|
||||
+a;
|
||||
+a;
|
||||
1 / a;
|
||||
+a;
|
||||
}
|
||||
}
|
||||
|
||||
identity_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
0 + !a;
|
||||
!a + 0;
|
||||
0 - !a;
|
||||
!a - 0;
|
||||
1 * !a;
|
||||
!a * 1;
|
||||
1 / !a;
|
||||
!a / 1;
|
||||
}
|
||||
expect: {
|
||||
+!a;
|
||||
+!a;
|
||||
0 - !a;
|
||||
+!a;
|
||||
+!a;
|
||||
+!a;
|
||||
1 / !a;
|
||||
+!a;
|
||||
}
|
||||
}
|
||||
|
||||
identity_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
0 + --a;
|
||||
--a + 0;
|
||||
0 - --a;
|
||||
--a - 0;
|
||||
1 * --a;
|
||||
--a * 1;
|
||||
1 / --a;
|
||||
--a / 1;
|
||||
}
|
||||
expect: {
|
||||
--a;
|
||||
--a;
|
||||
0 - --a;
|
||||
--a;
|
||||
--a;
|
||||
--a;
|
||||
1 / --a;
|
||||
--a;
|
||||
}
|
||||
}
|
||||
|
||||
issue_3653: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log(0 - (console && 0));
|
||||
console.log(0 + (0 - (console && 0)));
|
||||
console.log(0 - (0 - (console && 0)));
|
||||
console.log(1 * (0 - (console && 0)));
|
||||
console.log(1 / (0 - (console && 0)));
|
||||
console.log((0 - (console && 0)) + 0);
|
||||
console.log((0 - (console && 0)) - 0);
|
||||
console.log((0 - (console && 0)) * 1);
|
||||
console.log((0 - (console && 0)) / 1);
|
||||
}
|
||||
expect: {
|
||||
console.log(0 - (console && 0));
|
||||
console.log(0 - (console && 0));
|
||||
console.log(0 - (0 - (console && 0)));
|
||||
console.log(0 - (console && 0));
|
||||
console.log(1 / (0 - (console && 0)));
|
||||
console.log(0 - (console && 0));
|
||||
console.log(0 - (console && 0));
|
||||
console.log(0 - (console && 0));
|
||||
console.log(0 - (console && 0));
|
||||
}
|
||||
expect_stdout: [
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"Infinity",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3655: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log(0 + 0 * -[].length);
|
||||
console.log(0 + (0 + 0 * -[].length));
|
||||
console.log(0 - (0 + 0 * -[].length));
|
||||
console.log(1 * (0 + 0 * -[].length));
|
||||
console.log(1 / (0 + 0 * -[].length));
|
||||
console.log((0 + 0 * -[].length) + 0);
|
||||
console.log((0 + 0 * -[].length) - 0);
|
||||
console.log((0 + 0 * -[].length) * 1);
|
||||
console.log((0 + 0 * -[].length) / 1);
|
||||
}
|
||||
expect: {
|
||||
console.log(0 + 0 * -[].length);
|
||||
console.log(0 + 0 * -[].length);
|
||||
console.log(0 - (0 + 0 * -[].length));
|
||||
console.log(0 + 0 * -[].length);
|
||||
console.log(1 / (0 + 0 * -[].length));
|
||||
console.log(0 + 0 * -[].length);
|
||||
console.log(0 + 0 * -[].length);
|
||||
console.log(0 + 0 * -[].length);
|
||||
console.log(0 + 0 * -[].length);
|
||||
}
|
||||
expect_stdout: [
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"Infinity",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3676_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = [];
|
||||
console.log(false - (a - (a[1] = 42)));
|
||||
}
|
||||
expect: {
|
||||
var a = [];
|
||||
console.log(false - (a - (a[1] = 42)));
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
issue_3676_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
console.log(false - ((a = []) - (a[1] = 42)));
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
console.log(false - ((a = []) - (a[1] = 42)));
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
issue_3682_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = -0;
|
||||
console.log(1 / (a - 1 + 1));
|
||||
}
|
||||
expect: {
|
||||
var a = -0;
|
||||
console.log(1 / (a - 1 + 1));
|
||||
}
|
||||
expect_stdout: "Infinity"
|
||||
}
|
||||
|
||||
issue_3682_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = -0, b = 1;
|
||||
console.log(1 / (a - (b - b)));
|
||||
}
|
||||
expect: {
|
||||
var a = -0, b = 1;
|
||||
console.log(1 / (a - (b - b)));
|
||||
}
|
||||
expect_stdout: "-Infinity"
|
||||
}
|
||||
|
||||
issue_3682_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
var a = -0, b = 1, c = -1;
|
||||
console.log(1 / (a - (+b + +c)));
|
||||
}
|
||||
expect: {
|
||||
var a = -0, b = 1, c = -1;
|
||||
console.log(1 / (a - (+b + +c)));
|
||||
}
|
||||
expect_stdout: "-Infinity"
|
||||
}
|
||||
|
||||
issue_3684: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log(1 / (-1 * (0 & console) + 0));
|
||||
console.log(1 / ((0 & console) / -1 + 0));
|
||||
}
|
||||
expect: {
|
||||
console.log(1 / (-1 * (0 & console) + 0));
|
||||
console.log(1 / ((0 & console) / -1 + 0));
|
||||
}
|
||||
expect_stdout: [
|
||||
"Infinity",
|
||||
"Infinity",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3695: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
var a = [];
|
||||
console.log(+(a * (a[0] = false)));
|
||||
}
|
||||
expect: {
|
||||
var a = [];
|
||||
console.log(+(a * (a[0] = false)));
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
issue_4137: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log(+(A = []) * (A[0] = 1));
|
||||
}
|
||||
expect: {
|
||||
console.log(+(A = []) * (A[0] = 1));
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
issue_4142: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log("" + +(0 === console));
|
||||
}
|
||||
expect: {
|
||||
console.log("" + +(0 === console));
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ evaluate_string_length: {
|
||||
}
|
||||
}
|
||||
|
||||
mangle_properties: {
|
||||
mangle_properties_1: {
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: false,
|
||||
@@ -152,6 +152,53 @@ mangle_properties: {
|
||||
}
|
||||
}
|
||||
|
||||
mangle_properties_2: {
|
||||
mangle = {
|
||||
properties: {
|
||||
reserved: [
|
||||
"value",
|
||||
]
|
||||
},
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
prop1: 1,
|
||||
};
|
||||
Object.defineProperty(o, "prop2", {
|
||||
value: 2,
|
||||
});
|
||||
Object.defineProperties(o, {
|
||||
prop3: {
|
||||
value: 3,
|
||||
},
|
||||
});
|
||||
console.log("prop1", o.prop1, "prop1" in o);
|
||||
console.log("prop2", o.prop2, o.hasOwnProperty("prop2"));
|
||||
console.log("prop3", o.prop3, Object.getOwnPropertyDescriptor(o, "prop3").value);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
o: 1,
|
||||
};
|
||||
Object.defineProperty(o, "p", {
|
||||
value: 2,
|
||||
});
|
||||
Object.defineProperties(o, {
|
||||
r: {
|
||||
value: 3,
|
||||
},
|
||||
});
|
||||
console.log("prop1", o.o, "o" in o);
|
||||
console.log("prop2", o.p, o.hasOwnProperty("p"));
|
||||
console.log("prop3", o.r, Object.getOwnPropertyDescriptor(o, "r").value);
|
||||
}
|
||||
expect_stdout: [
|
||||
"prop1 1 true",
|
||||
"prop2 2 true",
|
||||
"prop3 3 3",
|
||||
]
|
||||
}
|
||||
|
||||
mangle_unquoted_properties: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -817,6 +864,29 @@ issue_2208_5: {
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_2208_6: {
|
||||
options = {
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
a = 42;
|
||||
console.log(("FAIL", {
|
||||
p: function() {
|
||||
return this.a;
|
||||
}
|
||||
}.p)());
|
||||
}
|
||||
expect: {
|
||||
a = 42;
|
||||
console.log(function() {
|
||||
return this.a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_2256: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
@@ -1023,16 +1093,22 @@ array_hole: {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
[ 1, 2, , 3][1],
|
||||
[ 1, 2, , 3][2],
|
||||
[ 1, 2, , 3][3]
|
||||
);
|
||||
Array.prototype[2] = "PASS";
|
||||
console.log([ 1, 2, , 3 ][1]);
|
||||
console.log([ 1, 2, , 3 ][2]);
|
||||
console.log([ 1, 2, , 3 ][3]);
|
||||
}
|
||||
expect: {
|
||||
console.log(2, void 0, 3);
|
||||
Array.prototype[2] = "PASS";
|
||||
console.log(2);
|
||||
console.log([ , , , ][2]);
|
||||
console.log(3);
|
||||
}
|
||||
expect_stdout: "2 undefined 3"
|
||||
expect_stdout: [
|
||||
"2",
|
||||
"PASS",
|
||||
"3",
|
||||
]
|
||||
}
|
||||
|
||||
new_this: {
|
||||
@@ -1120,558 +1196,6 @@ const_prop_assign_pure: {
|
||||
}
|
||||
}
|
||||
|
||||
join_object_assignments_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var x = {
|
||||
a: 1,
|
||||
c: (console.log("c"), "C"),
|
||||
};
|
||||
x.b = 2;
|
||||
x[3] = function() {
|
||||
console.log(x);
|
||||
},
|
||||
x["a"] = /foo/,
|
||||
x.bar = x;
|
||||
return x;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var x = {
|
||||
a: 1,
|
||||
c: (console.log("c"), "C"),
|
||||
b: 2,
|
||||
3: function() {
|
||||
console.log(x);
|
||||
},
|
||||
a: /foo/,
|
||||
};
|
||||
x.bar = x;
|
||||
return x;
|
||||
}());
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
join_object_assignments_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
join_vars: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
foo: 1,
|
||||
};
|
||||
o.bar = 2;
|
||||
o.baz = 3;
|
||||
console.log(o.foo, o.bar + o.bar, o.foo * o.bar * o.baz);
|
||||
}
|
||||
expect: {
|
||||
console.log(1, 4, 6);
|
||||
}
|
||||
expect_stdout: "1 4 6"
|
||||
}
|
||||
|
||||
join_object_assignments_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
a: "PASS",
|
||||
}, a = o.a;
|
||||
o.a = "FAIL";
|
||||
return a;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
a: "PASS",
|
||||
}, a = o.a;
|
||||
o.a = "FAIL";
|
||||
return a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
join_object_assignments_4: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
var o;
|
||||
console.log(o);
|
||||
o = {};
|
||||
o.a = "foo";
|
||||
console.log(o.b);
|
||||
o.b = "bar";
|
||||
console.log(o.a);
|
||||
}
|
||||
expect: {
|
||||
var o;
|
||||
console.log(o),
|
||||
o = {
|
||||
a: "foo",
|
||||
},
|
||||
console.log(o.b),
|
||||
o.b = "bar",
|
||||
console.log(o.a);
|
||||
}
|
||||
expect_stdout: [
|
||||
"undefined",
|
||||
"undefined",
|
||||
"foo",
|
||||
]
|
||||
}
|
||||
|
||||
join_object_assignments_return_1: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3
|
||||
};
|
||||
return o.q = "foo";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3,
|
||||
q: "foo"
|
||||
};
|
||||
return o.q;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "foo"
|
||||
}
|
||||
|
||||
join_object_assignments_return_2: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3
|
||||
};
|
||||
return o.q = /foo/,
|
||||
o.r = "bar";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3,
|
||||
q: /foo/,
|
||||
r: "bar"
|
||||
};
|
||||
return o.r;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "bar"
|
||||
}
|
||||
|
||||
join_object_assignments_return_3: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3
|
||||
};
|
||||
return o.q = "foo",
|
||||
o.p += "",
|
||||
console.log(o.q),
|
||||
o.p;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3,
|
||||
q: "foo"
|
||||
};
|
||||
return o.p += "",
|
||||
console.log(o.q),
|
||||
o.p;
|
||||
}());
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"3",
|
||||
]
|
||||
}
|
||||
|
||||
join_object_assignments_for: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3
|
||||
};
|
||||
for (o.q = "foo"; console.log(o.q););
|
||||
return o.p;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
for (var o = {
|
||||
p: 3,
|
||||
q: "foo"
|
||||
}; console.log(o.q););
|
||||
return o.p;
|
||||
}());
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"3",
|
||||
]
|
||||
}
|
||||
|
||||
join_object_assignments_if: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {};
|
||||
if (o.a = "PASS") return o.a;
|
||||
}())
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o = { a: "PASS" };
|
||||
if (o.a) return o.a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
join_object_assignments_forin: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {};
|
||||
for (var a in o.a = "PASS", o)
|
||||
return o[a];
|
||||
}())
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o = { a: "PASS" };
|
||||
for (var a in o)
|
||||
return o[a];
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
join_object_assignments_negative: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[0] = 0;
|
||||
o[-0] = 1;
|
||||
o[-1] = 2;
|
||||
console.log(o[0], o[-0], o[-1]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
0: 0,
|
||||
0: 1,
|
||||
"-1": 2
|
||||
};
|
||||
console.log(o[0], o[-0], o[-1]);
|
||||
}
|
||||
expect_stdout: "1 1 2"
|
||||
}
|
||||
|
||||
join_object_assignments_NaN_1: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[NaN] = 1;
|
||||
o[0/0] = 2;
|
||||
console.log(o[NaN], o[NaN]);
|
||||
}
|
||||
expect: {
|
||||
var o = {};
|
||||
o[NaN] = 1;
|
||||
o[0/0] = 2;
|
||||
console.log(o[NaN], o[NaN]);
|
||||
}
|
||||
expect_stdout: "2 2"
|
||||
}
|
||||
|
||||
join_object_assignments_NaN_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[NaN] = 1;
|
||||
o[0/0] = 2;
|
||||
console.log(o[NaN], o[NaN]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
NaN: 1,
|
||||
NaN: 2
|
||||
};
|
||||
console.log(o.NaN, o.NaN);
|
||||
}
|
||||
expect_stdout: "2 2"
|
||||
}
|
||||
|
||||
join_object_assignments_null_0: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[null] = 1;
|
||||
console.log(o[null]);
|
||||
}
|
||||
expect: {
|
||||
var o = {};
|
||||
o[null] = 1;
|
||||
console.log(o[null]);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
join_object_assignments_null_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[null] = 1;
|
||||
console.log(o[null]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
null: 1
|
||||
};
|
||||
console.log(o.null);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
join_object_assignments_void_0: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[void 0] = 1;
|
||||
console.log(o[void 0]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
undefined: 1
|
||||
};
|
||||
console.log(o[void 0]);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
join_object_assignments_undefined_1: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[undefined] = 1;
|
||||
console.log(o[undefined]);
|
||||
}
|
||||
expect: {
|
||||
var o = {};
|
||||
o[void 0] = 1;
|
||||
console.log(o[void 0]);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
join_object_assignments_undefined_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[undefined] = 1;
|
||||
console.log(o[undefined]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
undefined : 1
|
||||
};
|
||||
console.log(o[void 0]);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
join_object_assignments_Infinity: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[Infinity] = 1;
|
||||
o[1/0] = 2;
|
||||
o[-Infinity] = 3;
|
||||
o[-1/0] = 4;
|
||||
console.log(o[Infinity], o[1/0], o[-Infinity], o[-1/0]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
Infinity: 1,
|
||||
Infinity: 2,
|
||||
"-Infinity": 3,
|
||||
"-Infinity": 4
|
||||
};
|
||||
console.log(o[1/0], o[1/0], o[-1/0], o[-1/0]);
|
||||
}
|
||||
expect_stdout: "2 2 4 4"
|
||||
}
|
||||
|
||||
join_object_assignments_regex: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[/rx/] = 1;
|
||||
console.log(o[/rx/]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
"/rx/": 1
|
||||
};
|
||||
console.log(o[/rx/]);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_2816: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
var o = {
|
||||
a: 1
|
||||
};
|
||||
o.b = 2;
|
||||
o.a = 3;
|
||||
o.c = 4;
|
||||
console.log(o.a, o.b, o.c);
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2
|
||||
};
|
||||
o.a = 3;
|
||||
o.c = 4;
|
||||
console.log(o.a, o.b, o.c);
|
||||
}
|
||||
expect_stdout: "3 2 4"
|
||||
}
|
||||
|
||||
issue_2893_1: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
get a() {
|
||||
return "PASS";
|
||||
},
|
||||
};
|
||||
o.a = "FAIL";
|
||||
console.log(o.a);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
get a() {
|
||||
return "PASS";
|
||||
},
|
||||
};
|
||||
o.a = "FAIL";
|
||||
console.log(o.a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2893_2: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
set a(v) {
|
||||
this.b = v;
|
||||
},
|
||||
b: "FAIL",
|
||||
};
|
||||
o.a = "PASS";
|
||||
console.log(o.b);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
set a(v) {
|
||||
this.b = v;
|
||||
},
|
||||
b: "FAIL",
|
||||
};
|
||||
o.a = "PASS";
|
||||
console.log(o.b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_869_1: {
|
||||
mangle = {
|
||||
properties: {
|
||||
@@ -1833,36 +1357,6 @@ issue_3188_3: {
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
join_expr: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
var c = "FAIL";
|
||||
(function() {
|
||||
var a = 0;
|
||||
switch ((a = {}) && (a.b = 0)) {
|
||||
case 0:
|
||||
c = "PASS";
|
||||
}
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = "FAIL";
|
||||
(function() {
|
||||
var a = 0;
|
||||
switch (a = { b: 0 }, a.b) {
|
||||
case 0:
|
||||
c = "PASS";
|
||||
}
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3389: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
|
||||
@@ -136,7 +136,7 @@ relational: {
|
||||
side_effects :true,
|
||||
}
|
||||
input: {
|
||||
foo() in foo();
|
||||
foo() in new foo();
|
||||
foo() instanceof bar();
|
||||
foo() < "bar";
|
||||
bar() > foo();
|
||||
@@ -680,3 +680,130 @@ issue_3325_2: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3858: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var f = function(a) {
|
||||
return /*@__PURE__*/ function(b) {
|
||||
console.log(b);
|
||||
}(a);
|
||||
};
|
||||
f("PASS");
|
||||
}
|
||||
expect: {
|
||||
var f = function(a) {
|
||||
return function() {
|
||||
console.log(a);
|
||||
}();
|
||||
};
|
||||
f("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
inline_pure_call_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var f = function(a) {
|
||||
return /*@__PURE__*/ function(b) {
|
||||
console.log(b);
|
||||
}(a);
|
||||
};
|
||||
f("PASS");
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
inline_pure_call_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var f = function(a) {
|
||||
return /*@__PURE__*/ function(b) {
|
||||
console.log(b);
|
||||
}(a);
|
||||
};
|
||||
var a = f("PASS");
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
inline_pure_call_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var f = function(a) {
|
||||
return /*@__PURE__*/ function(b) {
|
||||
console.log(b);
|
||||
}(a);
|
||||
};
|
||||
var a = f("PASS");
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = function() {
|
||||
console.log("PASS");
|
||||
}();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"undefined",
|
||||
]
|
||||
}
|
||||
|
||||
inline_pure_call_4: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = /*@__PURE__*/ function() {
|
||||
return console.log("PASS"), 42;
|
||||
}();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = function() {
|
||||
return console.log("PASS"), 42;
|
||||
}();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"42",
|
||||
]
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -186,3 +186,290 @@ issue_3434_3: {
|
||||
/\nfo\n[\n]o\bbb/;
|
||||
}
|
||||
}
|
||||
|
||||
issue_3434_4: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
[
|
||||
[ "", RegExp("") ],
|
||||
[ "/", RegExp("/") ],
|
||||
[ "//", RegExp("//") ],
|
||||
[ "\/", RegExp("\\/") ],
|
||||
[ "///", RegExp("///") ],
|
||||
[ "/\/", RegExp("/\\/") ],
|
||||
[ "\//", RegExp("\\//") ],
|
||||
[ "\\/", RegExp("\\\\/") ],
|
||||
[ "////", RegExp("////") ],
|
||||
[ "//\/", RegExp("//\\/") ],
|
||||
[ "/\//", RegExp("/\\//") ],
|
||||
[ "/\\/", RegExp("/\\\\/") ],
|
||||
[ "\///", RegExp("\\///") ],
|
||||
[ "\/\/", RegExp("\\/\\/") ],
|
||||
[ "\\//", RegExp("\\\\//") ],
|
||||
[ "\\\/", RegExp("\\\\\\/") ],
|
||||
].forEach(function(test) {
|
||||
console.log(test[1].test("\\"), test[1].test(test[0]));
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
[
|
||||
[ "", /(?:)/ ],
|
||||
[ "/", /\// ],
|
||||
[ "//", /\/\// ],
|
||||
[ "/", /\// ],
|
||||
[ "///", /\/\/\// ],
|
||||
[ "//", /\/\// ],
|
||||
[ "//", /\/\// ],
|
||||
[ "\\/", /\\\// ],
|
||||
[ "////", /\/\/\/\// ],
|
||||
[ "///", /\/\/\// ],
|
||||
[ "///", /\/\/\// ],
|
||||
[ "/\\/", /\/\\\// ],
|
||||
[ "///", /\/\/\// ],
|
||||
[ "//", /\/\// ],
|
||||
[ "\\//", /\\\/\// ],
|
||||
[ "\\/", /\\\// ],
|
||||
].forEach(function(test) {
|
||||
console.log(test[1].test("\\"), test[1].test(test[0]));
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"true true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
"false true",
|
||||
]
|
||||
}
|
||||
|
||||
exec: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
while (/a/.exec("AAA"))
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
for (;null;)
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
exec_global: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
while (/a/g.exec("AAA"))
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
for (;null;)
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
test: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
while (/a/.test("AAA"))
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
while (false)
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
test_global: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
while (/a/g.test("AAA"))
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
while (false)
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
var_exec: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var r = /a/;
|
||||
while (r.exec("AAA"))
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
var r = /a/;
|
||||
for (;null;)
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
var_exec_global: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var r = /a/g;
|
||||
while (r.exec("aaa"))
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
var r = /a/g;
|
||||
for (;r.exec("aaa");)
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"PASS",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
var_test: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var r = /a/;
|
||||
while (r.test("AAA"))
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
var r = /a/;
|
||||
while (false)
|
||||
console.log("FAIL");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
var_test_global: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var r = /a/g;
|
||||
while (r.test("aaa"))
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
var r = /a/g;
|
||||
while (r.test("aaa"))
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"PASS",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
lazy_boolean: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
passes: 2,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
/b/.exec({}) && console.log("PASS");
|
||||
/b/.test({}) && console.log("PASS");
|
||||
/b/g.exec({}) && console.log("PASS");
|
||||
/b/g.test({}) && console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS");
|
||||
console.log("PASS");
|
||||
console.log("PASS");
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"PASS",
|
||||
"PASS",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
reset_state_between_evaluate: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
passes: 2,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
for (var a in /[abc4]/g.exec("a"))
|
||||
return "PASS";
|
||||
return "FAIL";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
for (var a in /[abc4]/g.exec("a"))
|
||||
return "PASS";
|
||||
return "FAIL";
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -80,3 +80,21 @@ log_global: {
|
||||
}
|
||||
expect_stdout: "[object global]"
|
||||
}
|
||||
|
||||
issue_4054: {
|
||||
input: {
|
||||
console.log({
|
||||
set p(v) {
|
||||
throw "FAIL";
|
||||
},
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
console.log({
|
||||
set p(v) {
|
||||
throw "FAIL";
|
||||
},
|
||||
});
|
||||
}
|
||||
expect_stdout: "{ p: [Setter] }"
|
||||
}
|
||||
|
||||
@@ -877,7 +877,7 @@ for_init_var: {
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
forin: {
|
||||
forin_1: {
|
||||
options = {
|
||||
sequences: true,
|
||||
}
|
||||
@@ -895,6 +895,49 @@ forin: {
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
forin_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
p: 1,
|
||||
q: 2,
|
||||
};
|
||||
var k = "k";
|
||||
for ((console.log("exp"), o)[function() {
|
||||
console.log("prop");
|
||||
return k;
|
||||
}()] in function() {
|
||||
console.log("obj");
|
||||
return o;
|
||||
}())
|
||||
console.log(o.k, o[o.k]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
p: 1,
|
||||
q: 2,
|
||||
};
|
||||
for ((console.log("exp"), o)[console.log("prop"), "k"] in console.log("obj"), o)
|
||||
console.log(o.k, o[o.k]);
|
||||
}
|
||||
expect_stdout: [
|
||||
"obj",
|
||||
"exp",
|
||||
"prop",
|
||||
"p 1",
|
||||
"exp",
|
||||
"prop",
|
||||
"q 2",
|
||||
]
|
||||
}
|
||||
|
||||
call: {
|
||||
options = {
|
||||
sequences: true,
|
||||
@@ -910,15 +953,23 @@ call: {
|
||||
console.log(this === b ? "bar" : "baz");
|
||||
};
|
||||
(a, b)();
|
||||
(a, b).c();
|
||||
(a, b.c)();
|
||||
(a, b)["c"]();
|
||||
(a, b["c"])();
|
||||
(a, function() {
|
||||
console.log(this === a);
|
||||
})();
|
||||
new (a, b)();
|
||||
new (a, b).c();
|
||||
new (a, b.c)();
|
||||
new (a, b)["c"]();
|
||||
new (a, b["c"])();
|
||||
new (a, function() {
|
||||
console.log(this === a);
|
||||
})();
|
||||
console.log(typeof (a, b).c);
|
||||
console.log(typeof (a, b)["c"]);
|
||||
}
|
||||
expect: {
|
||||
var a = function() {
|
||||
@@ -931,23 +982,39 @@ call: {
|
||||
console.log(this === b ? "bar" : "baz");
|
||||
},
|
||||
b(),
|
||||
b.c(),
|
||||
(a, b.c)(),
|
||||
b["c"](),
|
||||
(a, b["c"])(),
|
||||
function() {
|
||||
console.log(this === a);
|
||||
}(),
|
||||
new b(),
|
||||
new b.c(),
|
||||
new b.c(),
|
||||
new b["c"](),
|
||||
new b["c"](),
|
||||
new function() {
|
||||
console.log(this === a);
|
||||
}();
|
||||
}(),
|
||||
console.log((a, typeof b.c)),
|
||||
console.log((a, typeof b["c"]));
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
"bar",
|
||||
"baz",
|
||||
"true",
|
||||
"foo",
|
||||
"baz",
|
||||
"baz",
|
||||
"baz",
|
||||
"baz",
|
||||
"false",
|
||||
"function",
|
||||
"function",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1069,3 +1136,44 @@ issue_3490_2: {
|
||||
}
|
||||
expect_stdout: "PASS 42"
|
||||
}
|
||||
|
||||
issue_3703: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
sequences: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var a = "FAIL";
|
||||
while ((a = "PASS", 0).foo = 0);
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "FAIL";
|
||||
while (a = "PASS", (0).foo = 0);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4079: {
|
||||
options = {
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
typeof (0, A);
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
A;
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
418
test/compress/side_effects.js
Normal file
418
test/compress/side_effects.js
Normal file
@@ -0,0 +1,418 @@
|
||||
accessor: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
get a() {},
|
||||
set a(v){
|
||||
this.b = 2;
|
||||
},
|
||||
b: 1
|
||||
});
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2233_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
Array.isArray;
|
||||
Boolean;
|
||||
console.log;
|
||||
Date;
|
||||
decodeURI;
|
||||
decodeURIComponent;
|
||||
encodeURI;
|
||||
encodeURIComponent;
|
||||
Error.name;
|
||||
escape;
|
||||
eval;
|
||||
EvalError;
|
||||
Function.length;
|
||||
isFinite;
|
||||
isNaN;
|
||||
JSON;
|
||||
Math.random;
|
||||
Number.isNaN;
|
||||
parseFloat;
|
||||
parseInt;
|
||||
RegExp;
|
||||
Object.defineProperty;
|
||||
String.fromCharCode;
|
||||
RangeError;
|
||||
ReferenceError;
|
||||
SyntaxError;
|
||||
TypeError;
|
||||
unescape;
|
||||
URIError;
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
global_timeout_and_interval_symbols: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
// These global symbols do not exist in the test sandbox
|
||||
// and must be tested separately.
|
||||
clearInterval;
|
||||
clearTimeout;
|
||||
setInterval;
|
||||
setTimeout;
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2233_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var RegExp;
|
||||
Array.isArray;
|
||||
RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Math.sin;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
AnotherUndeclaredGlobal;
|
||||
(void 0).isNaN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2233_3: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var RegExp;
|
||||
Array.isArray;
|
||||
RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Math.sin;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
UndeclaredGlobal;
|
||||
}
|
||||
}
|
||||
|
||||
global_fns: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
Boolean(1, 2);
|
||||
decodeURI(1, 2);
|
||||
decodeURIComponent(1, 2);
|
||||
Date(1, 2);
|
||||
encodeURI(1, 2);
|
||||
encodeURIComponent(1, 2);
|
||||
Error(1, 2);
|
||||
escape(1, 2);
|
||||
EvalError(1, 2);
|
||||
isFinite(1, 2);
|
||||
isNaN(1, 2);
|
||||
Number(1, 2);
|
||||
Object(1, 2);
|
||||
parseFloat(1, 2);
|
||||
parseInt(1, 2);
|
||||
RangeError(1, 2);
|
||||
ReferenceError(1, 2);
|
||||
String(1, 2);
|
||||
SyntaxError(1, 2);
|
||||
TypeError(1, 2);
|
||||
unescape(1, 2);
|
||||
URIError(1, 2);
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect_stdout: [
|
||||
"SyntaxError",
|
||||
"SyntaxError",
|
||||
"RangeError",
|
||||
]
|
||||
}
|
||||
|
||||
unsafe_builtin_1: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
(!w).constructor(x);
|
||||
Math.abs(y);
|
||||
[ 1, 2, z ].valueOf();
|
||||
}
|
||||
expect: {
|
||||
w, x;
|
||||
y;
|
||||
z;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_builtin_2: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
constructor.call(o, 42);
|
||||
__defineGetter__.call(o, "foo", function() {
|
||||
return o.p;
|
||||
});
|
||||
__defineSetter__.call(o, void 0, function(a) {
|
||||
o.p = a;
|
||||
});
|
||||
console.log(typeof o, o.undefined = "PASS", o.foo);
|
||||
}
|
||||
expect: {
|
||||
var o = {};
|
||||
constructor.call(o, 42);
|
||||
__defineGetter__.call(o, "foo", function() {
|
||||
return o.p;
|
||||
});
|
||||
__defineSetter__.call(o, void 0, function(a) {
|
||||
o.p = a;
|
||||
});
|
||||
console.log(typeof o, o.undefined = "PASS", o.foo);
|
||||
}
|
||||
expect_stdout: "object PASS PASS"
|
||||
}
|
||||
|
||||
unsafe_builtin_3: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
if (42 < Math.random())
|
||||
o.p = "FAIL";
|
||||
else
|
||||
o.p = "PASS";
|
||||
for (var k in o)
|
||||
console.log(k, o[k]);
|
||||
}
|
||||
expect: {
|
||||
var o = {};
|
||||
o.p = 42 < Math.random() ? "FAIL" : "PASS";
|
||||
for (var k in o)
|
||||
console.log(k, o[k]);
|
||||
}
|
||||
expect_stdout: "p PASS"
|
||||
}
|
||||
|
||||
unsafe_string_replace: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
"foo".replace("f", function() {
|
||||
console.log("PASS");
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
"foo".replace("f", function() {
|
||||
console.log("PASS");
|
||||
});
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
drop_value: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(1, [2, foo()], 3, {a:1, b:bar()});
|
||||
}
|
||||
expect: {
|
||||
foo(), bar();
|
||||
}
|
||||
}
|
||||
|
||||
operator_in: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
"foo" in true;
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
0 in true;
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3983_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS";
|
||||
function f() {
|
||||
g && g();
|
||||
}
|
||||
f();
|
||||
function g() {
|
||||
0 ? a : 0;
|
||||
}
|
||||
var b = a;
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS";
|
||||
g();
|
||||
function g() {}
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3983_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS";
|
||||
function f() {
|
||||
g && g();
|
||||
}
|
||||
f();
|
||||
function g() {
|
||||
0 ? a : 0;
|
||||
}
|
||||
var b = a;
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4008: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS";
|
||||
function f(b, b) {
|
||||
console.log(b);
|
||||
}
|
||||
f && f(a && a[a]);
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS";
|
||||
function f(b, b) {
|
||||
console.log(b);
|
||||
}
|
||||
f(a[a]);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: [
|
||||
"undefined",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
constant_switch_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
@@ -19,6 +20,7 @@ constant_switch_1: {
|
||||
|
||||
constant_switch_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
@@ -39,6 +41,7 @@ constant_switch_2: {
|
||||
|
||||
constant_switch_3: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
@@ -60,6 +63,7 @@ constant_switch_3: {
|
||||
|
||||
constant_switch_4: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
@@ -86,6 +90,7 @@ constant_switch_4: {
|
||||
|
||||
constant_switch_5: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
@@ -120,6 +125,7 @@ constant_switch_5: {
|
||||
|
||||
constant_switch_6: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
@@ -154,6 +160,7 @@ constant_switch_6: {
|
||||
|
||||
constant_switch_7: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
@@ -197,6 +204,7 @@ constant_switch_7: {
|
||||
|
||||
constant_switch_8: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
@@ -226,6 +234,7 @@ constant_switch_8: {
|
||||
|
||||
constant_switch_9: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
@@ -315,6 +324,7 @@ keep_default: {
|
||||
|
||||
issue_1663: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
@@ -551,6 +561,7 @@ issue_441_2: {
|
||||
|
||||
issue_1674: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
@@ -876,6 +887,7 @@ beautify: {
|
||||
|
||||
issue_1758: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
@@ -898,15 +910,16 @@ issue_1758: {
|
||||
|
||||
issue_2535: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch(w(), 42) {
|
||||
case 13: x();
|
||||
case 42: y();
|
||||
default: z();
|
||||
case 13: x();
|
||||
case 42: y();
|
||||
default: z();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
@@ -919,6 +932,7 @@ issue_2535: {
|
||||
|
||||
issue_1750: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
switches: true,
|
||||
@@ -963,6 +977,7 @@ drop_switch_1: {
|
||||
|
||||
drop_switch_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
@@ -1007,6 +1022,7 @@ drop_switch_3: {
|
||||
|
||||
drop_switch_4: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
@@ -1028,3 +1044,140 @@ drop_switch_4: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
drop_switch_5: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (A) {
|
||||
case B:
|
||||
x();
|
||||
default:
|
||||
}
|
||||
switch (C) {
|
||||
default:
|
||||
y();
|
||||
case D:
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
A === B && x();
|
||||
C !== D && y();
|
||||
}
|
||||
}
|
||||
|
||||
drop_switch_6: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (A) {
|
||||
case B:
|
||||
default:
|
||||
x();
|
||||
}
|
||||
switch (C) {
|
||||
default:
|
||||
case D:
|
||||
y();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
A === B;
|
||||
x();
|
||||
C !== D;
|
||||
y();
|
||||
}
|
||||
}
|
||||
|
||||
drop_switch_7: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (A) {
|
||||
case B:
|
||||
w();
|
||||
default:
|
||||
x();
|
||||
}
|
||||
switch (C) {
|
||||
default:
|
||||
y();
|
||||
case D:
|
||||
z();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
A === B && w();
|
||||
x();
|
||||
C !== D && y();
|
||||
z();
|
||||
}
|
||||
}
|
||||
|
||||
drop_switch_8: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (A) {
|
||||
case B:
|
||||
w();
|
||||
break;
|
||||
default:
|
||||
x();
|
||||
}
|
||||
switch (C) {
|
||||
default:
|
||||
y();
|
||||
break;
|
||||
case D:
|
||||
z();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
(A === B ? w : x)();
|
||||
(C !== D ? y : z)();
|
||||
}
|
||||
}
|
||||
|
||||
issue_4059: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
switches: true,
|
||||
}
|
||||
input: {
|
||||
switch (0) {
|
||||
default:
|
||||
case 1:
|
||||
break;
|
||||
case a:
|
||||
break;
|
||||
var a;
|
||||
}
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
switch (0) {
|
||||
default:
|
||||
break;
|
||||
case a:
|
||||
break;
|
||||
var a;
|
||||
}
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ label_if_break: {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
L: if (true) {
|
||||
@@ -103,6 +104,7 @@ if_return: {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
passes: 2,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
|
||||
@@ -435,3 +435,25 @@ emberjs_global: {
|
||||
}
|
||||
expect_stdout: Error("PASS")
|
||||
}
|
||||
|
||||
issue_3817: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
passes: 2,
|
||||
typeofs: true,
|
||||
}
|
||||
input: {
|
||||
if ("A" == typeof A || !console.log("PASS")) switch (false) {
|
||||
case "undefined" == typeof A:
|
||||
console.log("FAIL");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
if ("A" == typeof A || !console.log("PASS")) switch (false) {
|
||||
case "undefined" == typeof A:
|
||||
console.log("FAIL");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -16,6 +16,81 @@ unicode_parse_variables: {
|
||||
}
|
||||
}
|
||||
|
||||
unicode_escaped_identifier: {
|
||||
input: {
|
||||
var \u0061 = "\ud800\udc00";
|
||||
console.log(a);
|
||||
}
|
||||
expect_exact: 'var a="\ud800\udc00";console.log(a);'
|
||||
expect_stdout: "\ud800\udc00"
|
||||
}
|
||||
|
||||
unicode_identifier_ascii_only: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
var \u0061 = "testing \udbc4\udd11";
|
||||
var bar = "h\u0065llo";
|
||||
console.log(a, \u0062\u0061r);
|
||||
}
|
||||
expect_exact: 'var a="testing \\udbc4\\udd11";var bar="hello";console.log(a,bar);'
|
||||
expect_stdout: "testing \udbc4\udd11 hello"
|
||||
}
|
||||
|
||||
unicode_string_literals: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
var a = "6 length unicode character: \udbc4\udd11";
|
||||
console.log(\u0061);
|
||||
}
|
||||
expect_exact: 'var a="6 length unicode character: \\udbc4\\udd11";console.log(a);'
|
||||
expect_stdout: "6 length unicode character: \udbc4\udd11"
|
||||
}
|
||||
|
||||
check_escape_style: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
var a = "\x01";
|
||||
var \ua0081 = "\x10"; // \u0081 only in ID_Continue
|
||||
var \u0100 = "\u0100";
|
||||
var \u1000 = "\u1000";
|
||||
var \u1000 = "\ud800\udc00";
|
||||
var \u3f80 = "\udbc0\udc00";
|
||||
console.log(\u0061, \ua0081, \u0100, \u1000, \u3f80);
|
||||
}
|
||||
expect_exact: 'var a="\\x01";var \\ua0081="\\x10";var \\u0100="\\u0100";var \\u1000="\\u1000";var \\u1000="\\ud800\\udc00";var \\u3f80="\\udbc0\\udc00";console.log(a,\\ua0081,\\u0100,\\u1000,\\u3f80);'
|
||||
expect_stdout: "\u0001 \u0010 \u0100 \ud800\udc00 \udbc0\udc00"
|
||||
}
|
||||
|
||||
escape_non_escaped_identifier: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
var µþ = "µþ";
|
||||
console.log(\u00b5þ);
|
||||
}
|
||||
expect_exact: 'var \\u00b5\\u00fe="\\xb5\\xfe";console.log(\\u00b5\\u00fe);'
|
||||
expect_stdout: "µþ"
|
||||
}
|
||||
|
||||
non_escape_2_non_escape: {
|
||||
beautify = {
|
||||
ascii_only: false,
|
||||
}
|
||||
input: {
|
||||
var µþ = "µþ";
|
||||
console.log(\u00b5þ);
|
||||
}
|
||||
expect_exact: 'var µþ="µþ";console.log(µþ);'
|
||||
expect_stdout: "µþ"
|
||||
}
|
||||
|
||||
issue_2242_1: {
|
||||
beautify = {
|
||||
ascii_only: false,
|
||||
@@ -24,6 +99,7 @@ issue_2242_1: {
|
||||
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\\ud83d","\\ude00","\ud83d\ude00","\\ud83d@\\ude00");'
|
||||
expect_stdout: "\ud83d \ude00 \ud83d\ude00 \ud83d@\ude00"
|
||||
}
|
||||
|
||||
issue_2242_2: {
|
||||
@@ -34,6 +110,7 @@ issue_2242_2: {
|
||||
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\\ud83d","\\ude00","\\ud83d\\ude00","\\ud83d@\\ude00");'
|
||||
expect_stdout: "\ud83d \ude00 \ud83d\ude00 \ud83d@\ude00"
|
||||
}
|
||||
|
||||
issue_2242_3: {
|
||||
@@ -44,6 +121,7 @@ issue_2242_3: {
|
||||
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\\ud83d"+"\\ude00","\\ud83d"+"@"+"\\ude00");'
|
||||
expect_stdout: "\ud83d\ude00 \ud83d@\ude00"
|
||||
}
|
||||
|
||||
issue_2242_4: {
|
||||
@@ -54,6 +132,7 @@ issue_2242_4: {
|
||||
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\ud83d\ude00","\\ud83d@\\ude00");'
|
||||
expect_stdout: "\ud83d\ude00 \ud83d@\ude00"
|
||||
}
|
||||
|
||||
issue_2569: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
exports["Compressor"] = Compressor;
|
||||
exports["defaults"] = defaults;
|
||||
exports["JS_Parse_Error"] = JS_Parse_Error;
|
||||
exports["List"] = List;
|
||||
exports["mangle_properties"] = mangle_properties;
|
||||
exports["minify"] = minify;
|
||||
exports["OutputStream"] = OutputStream;
|
||||
@@ -12,3 +13,4 @@ exports["to_ascii"] = to_ascii;
|
||||
exports["tokenizer"] = tokenizer;
|
||||
exports["TreeTransformer"] = TreeTransformer;
|
||||
exports["TreeWalker"] = TreeWalker;
|
||||
exports["vlq_decode"] = vlq_decode;
|
||||
|
||||
4
test/input/invalid/switch.js
Normal file
4
test/input/invalid/switch.js
Normal file
@@ -0,0 +1,4 @@
|
||||
switch (0) {
|
||||
default:
|
||||
default:
|
||||
}
|
||||
17
test/input/issue-1482/beautify.js
Normal file
17
test/input/issue-1482/beautify.js
Normal file
@@ -0,0 +1,17 @@
|
||||
if (x) foo();
|
||||
|
||||
if (x) foo(); else baz();
|
||||
|
||||
if (x) foo(); else if (y) bar(); else baz();
|
||||
|
||||
if (x) if (y) foo(); else bar(); else baz();
|
||||
|
||||
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
||||
|
||||
function f() {
|
||||
if (x) foo();
|
||||
if (x) foo(); else baz();
|
||||
if (x) foo(); else if (y) bar(); else baz();
|
||||
if (x) if (y) foo(); else bar(); else baz();
|
||||
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
||||
}
|
||||
@@ -1,17 +1 @@
|
||||
if (x) foo();
|
||||
|
||||
if (x) foo(); else baz();
|
||||
|
||||
if (x) foo(); else if (y) bar(); else baz();
|
||||
|
||||
if (x) if (y) foo(); else bar(); else baz();
|
||||
|
||||
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
||||
|
||||
function f() {
|
||||
if (x) foo();
|
||||
if (x) foo(); else baz();
|
||||
if (x) foo(); else if (y) bar(); else baz();
|
||||
if (x) if (y) foo(); else bar(); else baz();
|
||||
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
||||
}
|
||||
if(x)foo();if(x)foo();else baz();if(x)foo();else if(y)bar();else baz();if(x)if(y)foo();else bar();else baz();if(x)foo();else if(y)bar();else if(z)baz();else moo();function f(){if(x)foo();if(x)foo();else baz();if(x)foo();else if(y)bar();else baz();if(x)if(y)foo();else bar();else baz();if(x)foo();else if(y)bar();else if(z)baz();else moo()}
|
||||
|
||||
@@ -1,2 +1,41 @@
|
||||
function _toConsumableArray(arr){if(Array.isArray(arr)){for(var i=0,arr2=Array(arr.length);i<arr.length;i++){arr2[i]=arr[i]}return arr2}else{return Array.from(arr)}}var _require=require("bar"),foo=_require.foo;var _require2=require("world"),hello=_require2.hello;foo.x.apply(foo,_toConsumableArray(foo.y(hello.z)));
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0Mi5qcyJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiYXJyIl0sIm1hcHBpbmdzIjoiMEpBQWNBLEtBQVFDIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3Qge2Zvb30gPSByZXF1aXJlKFwiYmFyXCIpO1xuY29uc3Qge2hlbGxvfSA9IHJlcXVpcmUoXCJ3b3JsZFwiKTtcblxuZm9vLngoLi4uZm9vLnkoaGVsbG8ueikpO1xuIl19
|
||||
"use strict";
|
||||
|
||||
function _toConsumableArray(arr) {
|
||||
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
|
||||
}
|
||||
|
||||
function _nonIterableSpread() {
|
||||
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
||||
}
|
||||
|
||||
function _unsupportedIterableToArray(o, minLen) {
|
||||
if (!o) return;
|
||||
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
||||
var n = Object.prototype.toString.call(o).slice(8, -1);
|
||||
if (n === "Object" && o.constructor) n = o.constructor.name;
|
||||
if (n === "Map" || n === "Set") return Array.from(n);
|
||||
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
||||
}
|
||||
|
||||
function _iterableToArray(iter) {
|
||||
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
|
||||
}
|
||||
|
||||
function _arrayWithoutHoles(arr) {
|
||||
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
|
||||
}
|
||||
|
||||
function _arrayLikeToArray(arr, len) {
|
||||
if (len == null || len > arr.length) len = arr.length;
|
||||
for (var i = 0, arr2 = new Array(len); i < len; i++) {
|
||||
arr2[i] = arr[i];
|
||||
}
|
||||
return arr2;
|
||||
}
|
||||
|
||||
var _require = require("bar"), foo = _require.foo;
|
||||
|
||||
var _require2 = require("world"), hello = _require2.hello;
|
||||
|
||||
foo.x.apply(foo, _toConsumableArray(foo.y(hello.z)));
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImNvbnN0IHtmb299ID0gcmVxdWlyZShcImJhclwiKTtcbmNvbnN0IHtoZWxsb30gPSByZXF1aXJlKFwid29ybGRcIik7XG5cbmZvby54KC4uLmZvby55KGhlbGxvLnopKTtcbiJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiZm9vIiwiaGVsbG8iLCJ4IiwiYXBwbHkiLCJfdG9Db25zdW1hYmxlQXJyYXkiLCJ5IiwieiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7ZUFBY0EsUUFBUSxRQUFmQyxNLFNBQUFBOztBLGdCQUNTRCxRQUFRLFVBQWpCRSxRLFVBQUFBOztBQUVQRCxJQUFJRSxFQUFKQyxNQUFBSCxLQUFHSSxtQkFBTUosSUFBSUssRUFBRUosTUFBTUsifQ==
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
||||
"use strict";
|
||||
|
||||
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
||||
|
||||
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
||||
|
||||
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
||||
|
||||
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
|
||||
|
||||
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
||||
|
||||
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
||||
|
||||
var _require = require("bar"),
|
||||
foo = _require.foo;
|
||||
|
||||
@@ -1 +1,11 @@
|
||||
{"version":3,"sources":["input2.js"],"names":["require","foo","hello","x","apply","_toConsumableArray","y","z"],"mappings":"kLAAcA,QAAQ,OAAfC,aAAAA,kBACSD,QAAQ,SAAjBE,gBAAAA,MAEPD,IAAIE,EAAJC,MAAAH,IAAAI,mBAASJ,IAAIK,EAAEJ,MAAMK","sourcesContent":["const {foo} = require(\"bar\");\nconst {hello} = require(\"world\");\n\nfoo.x(...foo.y(hello.z));\n"]}
|
||||
{
|
||||
"version": 3,
|
||||
"sources": [
|
||||
"input.js"
|
||||
],
|
||||
"names": [],
|
||||
"mappings": ";;;;;;;;;;;;;;eAAc,OAAO,CAAC,KAAD,C;IAAd,G,YAAA,G;;gBACS,OAAO,CAAC,OAAD,C;IAAhB,K,aAAA,K;;AAEP,GAAG,CAAC,CAAJ,OAAA,GAAG,qBAAM,GAAG,CAAC,CAAJ,CAAM,KAAK,CAAC,CAAZ,CAAN,EAAH",
|
||||
"sourcesContent": [
|
||||
"const {foo} = require(\"bar\");\nconst {hello} = require(\"world\");\n\nfoo.x(...foo.y(hello.z));\n"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
new function(){console.log(3)};
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSJ9
|
||||
|
||||
@@ -2,4 +2,4 @@ function test(a){
|
||||
"aaaaaaaaaaaaaaaa"
|
||||
;a(err,data),a(err,
|
||||
data)}
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7QUFDVjtDQUNBQSxFQUFTQyxJQUFLQyxNQUNkRixFQUFTQztBQUFLQyJ9
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7O0NBRVZBLEVBQVNDLElBQUtDLE1BQ2RGLEVBQVNDO0FBQUtDIn0=
|
||||
@@ -1,2 +1,2 @@
|
||||
new function(){console.log(3)};
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSJ9
|
||||
|
||||
5
test/input/reduce/diff_error.js
Normal file
5
test/input/reduce/diff_error.js
Normal file
@@ -0,0 +1,5 @@
|
||||
(function f(a) {
|
||||
do {
|
||||
console.log(f.length);
|
||||
} while (console.log(f += 0));
|
||||
})();
|
||||
19
test/input/reduce/diff_error.reduced.js
Normal file
19
test/input/reduce/diff_error.reduced.js
Normal file
@@ -0,0 +1,19 @@
|
||||
// (beautified)
|
||||
(function f(a) {
|
||||
do {
|
||||
console.log(f.length);
|
||||
} while (console.log(f += 0));
|
||||
})();
|
||||
// output: 1
|
||||
// function(){}0
|
||||
//
|
||||
// minify: 0
|
||||
// function(){}0
|
||||
//
|
||||
// options: {
|
||||
// "compress": {
|
||||
// "keep_fargs": false,
|
||||
// "unsafe": true
|
||||
// },
|
||||
// "mangle": false
|
||||
// }
|
||||
3
test/input/reduce/label.js
Normal file
3
test/input/reduce/label.js
Normal file
@@ -0,0 +1,3 @@
|
||||
UNUSED: {
|
||||
console.log(0 - .1 - .1 - .1);
|
||||
}
|
||||
12
test/input/reduce/label.reduced.js
Normal file
12
test/input/reduce/label.reduced.js
Normal file
@@ -0,0 +1,12 @@
|
||||
// (beautified)
|
||||
console.log(0 - 1 - .1 - .1);
|
||||
// output: -1.2000000000000002
|
||||
//
|
||||
// minify: -1.2
|
||||
//
|
||||
// options: {
|
||||
// "compress": {
|
||||
// "unsafe_math": true
|
||||
// },
|
||||
// "mangle": false
|
||||
// }
|
||||
8
test/input/reduce/setter.js
Normal file
8
test/input/reduce/setter.js
Normal file
@@ -0,0 +1,8 @@
|
||||
console.log(function f(a) {
|
||||
({
|
||||
set p(v) {
|
||||
f++;
|
||||
}
|
||||
});
|
||||
return f.length;
|
||||
}());
|
||||
20
test/input/reduce/setter.reduced.js
Normal file
20
test/input/reduce/setter.reduced.js
Normal file
@@ -0,0 +1,20 @@
|
||||
// (beautified)
|
||||
console.log(function f(a) {
|
||||
({
|
||||
set p(v) {
|
||||
f++;
|
||||
}
|
||||
});
|
||||
return f.length;
|
||||
}());
|
||||
// output: 1
|
||||
//
|
||||
// minify: 0
|
||||
//
|
||||
// options: {
|
||||
// "compress": {
|
||||
// "keep_fargs": false,
|
||||
// "unsafe": true
|
||||
// },
|
||||
// "mangle": false
|
||||
// }
|
||||
18
test/input/reduce/unsafe_math.js
Normal file
18
test/input/reduce/unsafe_math.js
Normal file
@@ -0,0 +1,18 @@
|
||||
var _calls_ = 10, a = 100, b = 10, c = 0;
|
||||
|
||||
function f0(b_1, a, undefined_2) {
|
||||
a++ + ++b;
|
||||
{
|
||||
var expr2 = (b + 1 - .1 - .1 - .1 || a || 3).toString();
|
||||
L20778: for (var key2 in expr2) {
|
||||
(c = c + 1) + [ --b + b_1, typeof f0 == "function" && --_calls_ >= 0 && f0(--b + typeof (undefined_2 = 1 === 1 ? a : b), --b + {
|
||||
c: (c = c + 1) + null
|
||||
}, a++ + (typeof f0 == "function" && --_calls_ >= 0 && f0(typeof (c = 1 + c, 3 / "a" * ("c" >>> 23..toString()) >= (b_1 && (b_1[(c = c + 1) + a--] = (- -0,
|
||||
true + {})))), 3, 25))), 1 === 1 ? a : b ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var a_1 = f0([ , 0 ].length === 2);
|
||||
|
||||
console.log(null, a, b, c, Infinity, NaN, undefined);
|
||||
20
test/input/reduce/unsafe_math.reduced.js
Normal file
20
test/input/reduce/unsafe_math.reduced.js
Normal file
@@ -0,0 +1,20 @@
|
||||
// (beautified)
|
||||
var b = 0;
|
||||
|
||||
var expr2 = (0 - 1 - .1 - .1).toString();
|
||||
|
||||
for (var key2 in expr2) {
|
||||
--b;
|
||||
}
|
||||
|
||||
console.log(b);
|
||||
// output: -19
|
||||
//
|
||||
// minify: -4
|
||||
//
|
||||
// options: {
|
||||
// "compress": {
|
||||
// "unsafe_math": true
|
||||
// },
|
||||
// "mangle": false
|
||||
// }
|
||||
@@ -1,6 +1,6 @@
|
||||
function f(x) {
|
||||
return g(x);
|
||||
function g(x) {
|
||||
return x;
|
||||
return x + x;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,16 +8,15 @@ if (typeof phantom == "undefined") {
|
||||
require("../tools/exit");
|
||||
var args = process.argv.slice(2);
|
||||
var debug = args.indexOf("--debug");
|
||||
if (debug >= 0) {
|
||||
if (debug < 0) {
|
||||
debug = false;
|
||||
} else {
|
||||
args.splice(debug, 1);
|
||||
debug = true;
|
||||
} else {
|
||||
debug = false;
|
||||
}
|
||||
if (!args.length) {
|
||||
args.push("-mcb", "beautify=false,webkit");
|
||||
}
|
||||
args.push("--timings");
|
||||
if (!args.length) args.push("-mcb", "beautify=false,webkit");
|
||||
args.unshift("bin/uglifyjs");
|
||||
args.push("--validate", "--timings");
|
||||
var child_process = require("child_process");
|
||||
var fetch = require("./fetch");
|
||||
var http = require("http");
|
||||
@@ -39,10 +38,10 @@ if (typeof phantom == "undefined") {
|
||||
});
|
||||
if (/\.js$/.test(url)) {
|
||||
var stderr = "";
|
||||
var uglifyjs = child_process.fork("bin/uglifyjs", args, {
|
||||
var uglifyjs = child_process.spawn(process.argv[0], args, {
|
||||
silent: true
|
||||
}).on("exit", function(code) {
|
||||
console.log("uglifyjs", url.slice(site.length + 1), args.join(" "));
|
||||
console.log("uglifyjs", url.slice(site.length + 1), args.slice(1).join(" "));
|
||||
console.log(stderr);
|
||||
if (code) throw new Error("uglifyjs failed with code " + code);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var fs = require("fs");
|
||||
|
||||
var config = {
|
||||
limit: 5000,
|
||||
limit: 10000,
|
||||
timeout: function(limit) {
|
||||
this.limit = limit;
|
||||
}
|
||||
@@ -55,11 +55,11 @@ process.nextTick(function run() {
|
||||
var elapsed = Date.now();
|
||||
var timer;
|
||||
var done = function() {
|
||||
reset();
|
||||
elapsed = Date.now() - elapsed;
|
||||
if (elapsed > task.limit) {
|
||||
throw new Error("Timed out: " + elapsed + "ms > " + task.limit + "ms");
|
||||
}
|
||||
reset();
|
||||
log_titles(console.log, task.titles, green('\u221A '));
|
||||
process.nextTick(run);
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@ var assert = require("assert");
|
||||
var exec = require("child_process").exec;
|
||||
var fs = require("fs");
|
||||
var run_code = require("../sandbox").run_code;
|
||||
var to_ascii = require("../node").to_ascii;
|
||||
|
||||
function read(path) {
|
||||
return fs.readFileSync(path, "utf8");
|
||||
@@ -48,6 +49,62 @@ describe("bin/uglifyjs", function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --source-map names=true", function(done) {
|
||||
exec([
|
||||
uglifyjscmd,
|
||||
"--beautify",
|
||||
"--source-map", [
|
||||
"names=true",
|
||||
"url=inline",
|
||||
].join(","),
|
||||
].join(" "), function(err, stdout) {
|
||||
if (err) throw err;
|
||||
var expected = [
|
||||
"var obj = {",
|
||||
" p: a,",
|
||||
" q: b",
|
||||
"};",
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,",
|
||||
].join("\n")
|
||||
assert.strictEqual(stdout.slice(0, expected.length), expected);
|
||||
var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim()));
|
||||
assert.deepEqual(map.names, [ "obj", "p", "a", "q", "b" ]);
|
||||
done();
|
||||
}).stdin.end([
|
||||
"var obj = {",
|
||||
" p: a,",
|
||||
" q: b",
|
||||
"};",
|
||||
].join("\n"));
|
||||
});
|
||||
it("Should work with --source-map names=false", function(done) {
|
||||
exec([
|
||||
uglifyjscmd,
|
||||
"--beautify",
|
||||
"--source-map", [
|
||||
"names=false",
|
||||
"url=inline",
|
||||
].join(","),
|
||||
].join(" "), function(err, stdout) {
|
||||
if (err) throw err;
|
||||
var expected = [
|
||||
"var obj = {",
|
||||
" p: a,",
|
||||
" q: b",
|
||||
"};",
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,",
|
||||
].join("\n")
|
||||
assert.strictEqual(stdout.slice(0, expected.length), expected);
|
||||
var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim()));
|
||||
assert.deepEqual(map.names, []);
|
||||
done();
|
||||
}).stdin.end([
|
||||
"var obj = {",
|
||||
" p: a,",
|
||||
" q: b",
|
||||
"};",
|
||||
].join("\n"));
|
||||
});
|
||||
it("Should give sensible error against invalid input source map", function(done) {
|
||||
var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline --verbose";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
@@ -109,9 +166,12 @@ describe("bin/uglifyjs", function() {
|
||||
}
|
||||
var command = [
|
||||
uglifyjscmd,
|
||||
"--source-map", "content=" + mapFile,
|
||||
"--source-map", "includeSources=true",
|
||||
"--source-map", "url=inline",
|
||||
"--beautify",
|
||||
"--source-map", [
|
||||
"content=" + mapFile,
|
||||
"includeSources",
|
||||
"url=inline",
|
||||
].join(","),
|
||||
].join(" ");
|
||||
|
||||
var child = exec(command, function(err, stdout) {
|
||||
@@ -176,7 +236,7 @@ describe("bin/uglifyjs", function() {
|
||||
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b';
|
||||
exec(command, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(stdout, read("test/input/issue-1482/default.js"));
|
||||
assert.strictEqual(stdout, read("test/input/issue-1482/beautify.js"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -188,6 +248,22 @@ describe("bin/uglifyjs", function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with `--output-opts`", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1482/input.js -O ascii_only';
|
||||
exec(command, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(stdout, read("test/input/issue-1482/default.js"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should fail when both --beautify & --output-opts are specified", function(done) {
|
||||
var command = uglifyjscmd + " test/input/issue-520/input.js -bO ascii_only";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stderr, "ERROR: --beautify cannot be used with --output-opts\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should process inline source map", function(done) {
|
||||
var command = [
|
||||
uglifyjscmd,
|
||||
@@ -229,7 +305,7 @@ describe("bin/uglifyjs", function() {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(stdout, [
|
||||
"var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();",
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUFBLE1BQWdCQyxRQUFRQyxJQUFJLEVBQUUsSUFBTyxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUVBLE1BQWNDLFFBQVFDLElBQUksRUFBRSxJQUFPLElBQUlGLElDQW5ELElBQUlHLElBQU0sV0FDTixTQUFTQyxJQUFLRCxLQUNWLE9BQU9BLElBR1gsT0FBT0MsSUFMRCJ9",
|
||||
"",
|
||||
].join("\n"));
|
||||
var stderrLines = stderr.split("\n");
|
||||
@@ -254,7 +330,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should fail with invalid syntax", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/simple.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/simple.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
var lines = stderr.split(/\n/);
|
||||
@@ -266,7 +342,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should fail with correct marking of tabs", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/tab.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/tab.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
var lines = stderr.split(/\n/);
|
||||
@@ -278,7 +354,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should fail with correct marking at start of line", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/eof.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/eof.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
var lines = stderr.split(/\n/);
|
||||
@@ -290,7 +366,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should fail with a missing loop body", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/loop-no-body.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/loop-no-body.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
var lines = stderr.split(/\n/);
|
||||
@@ -302,7 +378,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (5--)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_1.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/assign_1.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -316,7 +392,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (Math.random() /= 2)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_2.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/assign_2.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -330,7 +406,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (++this)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_3.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/assign_3.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -344,7 +420,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (++null)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_4.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/assign_4.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -358,7 +434,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (a.=)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/dot_1.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/dot_1.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -372,7 +448,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (%.a)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/dot_2.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/dot_2.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -386,7 +462,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (a./();)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/dot_3.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/dot_3.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -400,7 +476,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error ({%: 1})", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/object.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/object.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -414,7 +490,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
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";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -428,7 +504,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
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";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -442,7 +518,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
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";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -456,7 +532,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
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";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -470,7 +546,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
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";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -484,7 +560,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
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";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -498,7 +574,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (else)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/else.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/else.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -512,7 +588,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (return)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/return.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/return.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -526,7 +602,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (for-in init)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/for-in_1.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/for-in_1.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -540,7 +616,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (for-in var)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/for-in_2.js';
|
||||
var command = uglifyjscmd + " test/input/invalid/for-in_2.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
@@ -553,6 +629,18 @@ describe("bin/uglifyjs", function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (switch defaults)", function(done) {
|
||||
var command = uglifyjscmd + " test/input/invalid/switch.js";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
var lines = stderr.split(/\n/);
|
||||
assert.strictEqual(lines[0], "Parse error at test/input/invalid/switch.js:3,2");
|
||||
assert.strictEqual(lines[1], " default:");
|
||||
assert.strictEqual(lines[2], " ^");
|
||||
assert.strictEqual(lines[3], "ERROR: More than one default clause in switch statement");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should handle literal string as source map input", function(done) {
|
||||
var command = [
|
||||
uglifyjscmd,
|
||||
@@ -571,7 +659,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
|
||||
function read_map() {
|
||||
var map = JSON.parse(read("./test/input/issue-1236/simple.js.map"));
|
||||
var map = JSON.parse(read("test/input/issue-1236/simple.js.map"));
|
||||
delete map.sourcesContent;
|
||||
return JSON.stringify(map).replace(/"/g, '\\"');
|
||||
}
|
||||
@@ -641,7 +729,7 @@ describe("bin/uglifyjs", function() {
|
||||
var command = uglifyjscmd + " test/input/issue-3315/input.js --config-file test/input/issue-3315/config.json";
|
||||
exec(command, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(stdout, 'function f(){"aaaaaaaaaa";var a={prop:1,a:2};return a.prop+a.a}\n');
|
||||
assert.strictEqual(stdout, 'function f(){"aaaaaaaaaa";var a={prop:1,t:2};return a.prop+a.t}\n');
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -658,7 +746,7 @@ describe("bin/uglifyjs", function() {
|
||||
var command = uglifyjscmd + " test/input/rename/input.js --rename";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(stdout, "function f(a){return b(a);function b(c){return c}}\n");
|
||||
assert.strictEqual(stdout, "function f(a){return b(a);function b(c){return c+c}}\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -666,7 +754,7 @@ describe("bin/uglifyjs", function() {
|
||||
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2 --no-rename";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(stdout, "function f(n){return function(n){return n}(n)}\n");
|
||||
assert.strictEqual(stdout, "function f(n){return function(n){return n+n}(n)}\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -674,7 +762,7 @@ describe("bin/uglifyjs", function() {
|
||||
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(stdout, "function f(n){return n}\n");
|
||||
assert.strictEqual(stdout, "function f(n){return n+n}\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -682,7 +770,7 @@ describe("bin/uglifyjs", function() {
|
||||
var command = uglifyjscmd + " test/input/rename/input.js -c passes=2";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(stdout, "function f(x){return function(x){return x}(x)}\n");
|
||||
assert.strictEqual(stdout, "function f(x){return function(x){return x+x}(x)}\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -69,13 +69,13 @@ describe("Directives", function() {
|
||||
],
|
||||
[
|
||||
'"use \\\nstrict";"use strict";',
|
||||
[],
|
||||
[ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
|
||||
[ "use strict" ],
|
||||
[ "use\nstrict", "use \nstrict", "use asm" ]
|
||||
],
|
||||
[
|
||||
'"\\76";',
|
||||
[],
|
||||
[ ">", "\\76" ]
|
||||
[ "\\76" ],
|
||||
[ ">" ]
|
||||
],
|
||||
[
|
||||
// no ; or newline
|
||||
@@ -106,13 +106,13 @@ describe("Directives", function() {
|
||||
],
|
||||
[
|
||||
'function foo() {"use \\\nstrict";"use strict";',
|
||||
[],
|
||||
[ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
|
||||
[ "use strict" ],
|
||||
[ "use\nstrict", "use \nstrict", "use asm" ]
|
||||
],
|
||||
[
|
||||
'var foo = function() {"\\76";',
|
||||
[],
|
||||
[ ">", "\\76" ]
|
||||
[ "\\76" ],
|
||||
[ ">" ]
|
||||
],
|
||||
[
|
||||
'var foo = function() {"use strict"', // no ; or newline
|
||||
@@ -156,21 +156,24 @@ describe("Directives", function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
it("Should test EXPECT_DIRECTIVE RegExp", function() {
|
||||
it("Should print semicolon to separate strings from directives", function() {
|
||||
[
|
||||
[ "", true ],
|
||||
[ "'test';", true ],
|
||||
[ "'test';;", true ],
|
||||
[ "'tests';\n", true ],
|
||||
[ "'tests'", false ],
|
||||
[ "'tests'; \n\t", true ],
|
||||
[ "'tests';\n\n", true ],
|
||||
[ "\n\n\"use strict\";\n\n", true ],
|
||||
[ "", ';"";' ],
|
||||
[ '"test";', '"test";;"";' ],
|
||||
[ '"test";;', '"test";;"";' ],
|
||||
[ '"tests";\n', '"tests";;"";' ],
|
||||
[ '"tests"', '"tests";;"";' ],
|
||||
[ '"tests"; \n\t', '"tests";;"";' ],
|
||||
[ '"tests";\n\n', '"tests";;"";' ],
|
||||
[ '\n\n"use strict";\n\n', '"use strict";;"";' ],
|
||||
].forEach(function(test) {
|
||||
var ast = UglifyJS.parse(test[0]);
|
||||
ast.body.push(new UglifyJS.AST_SimpleStatement({
|
||||
body: new UglifyJS.AST_String({ value: "" })
|
||||
}));
|
||||
var out = UglifyJS.OutputStream();
|
||||
out.print(test[0]);
|
||||
out.print_string("", null, true);
|
||||
assert.strictEqual(out.get() === test[0] + ';""', test[1], test[0]);
|
||||
ast.print(out);
|
||||
assert.strictEqual(out.get(), test[1], test[0]);
|
||||
});
|
||||
});
|
||||
it("Should only print 2 semicolons spread over 2 lines in beautify mode", function() {
|
||||
@@ -178,8 +181,8 @@ describe("Directives", function() {
|
||||
'"use strict";',
|
||||
"'use strict';",
|
||||
'"use strict";',
|
||||
'"use strict";;',
|
||||
"'use strict';",
|
||||
'"use strict";',
|
||||
";'use strict';",
|
||||
"console.log('use strict');"
|
||||
].join(""), {
|
||||
compress: false,
|
||||
@@ -201,19 +204,23 @@ describe("Directives", function() {
|
||||
it("Should not add double semicolons in non-scoped block statements to avoid strings becoming directives", function() {
|
||||
[
|
||||
[
|
||||
'{"use\x20strict"}',
|
||||
'"use strict";"use\\x20strict";',
|
||||
'"use strict";"use\\x20strict";'
|
||||
],
|
||||
[
|
||||
'{"use\\x20strict"}',
|
||||
'{"use strict"}'
|
||||
],
|
||||
[
|
||||
'function foo(){"use\x20strict";}', // Valid place for directives
|
||||
'function foo(){"use strict"}'
|
||||
'function foo(){"use\\x20strict";}', // Valid place for directives
|
||||
'function foo(){"use\\x20strict"}'
|
||||
],
|
||||
[
|
||||
'try{"use\x20strict"}catch(e){}finally{"use\x20strict"}',
|
||||
'try{"use\\x20strict"}catch(e){}finally{"use\\x20strict"}',
|
||||
'try{"use strict"}catch(e){}finally{"use strict"}'
|
||||
],
|
||||
[
|
||||
'if(1){"use\x20strict"} else {"use strict"}',
|
||||
'if(1){"use\\x20strict"} else {"use strict"}',
|
||||
'if(1){"use strict"}else{"use strict"}'
|
||||
]
|
||||
].forEach(function(test) {
|
||||
@@ -225,16 +232,6 @@ describe("Directives", function() {
|
||||
assert.strictEqual(result.code, test[1], test[0]);
|
||||
});
|
||||
});
|
||||
it("Should add double semicolon when relying on automatic semicolon insertion", function() {
|
||||
var result = UglifyJS.minify('"use strict";"use\\x20strict";', {
|
||||
compress: false,
|
||||
output: {
|
||||
semicolons: false
|
||||
}
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, '"use strict";;"use strict"\n');
|
||||
});
|
||||
it("Should check quote style of directives", function() {
|
||||
[
|
||||
// 0. Prefer double quotes, unless string contains more double quotes than single quotes
|
||||
@@ -249,9 +246,9 @@ describe("Directives", function() {
|
||||
'"use strict";'
|
||||
],
|
||||
[
|
||||
'"\\\'use strict\\\'";', // Not a directive as it contains quotes
|
||||
'"\\\'use strict\\\'";',
|
||||
0,
|
||||
';"\'use strict\'";',
|
||||
'"\\\'use strict\\\'";',
|
||||
],
|
||||
[
|
||||
"'\"use strict\"';",
|
||||
@@ -273,7 +270,7 @@ describe("Directives", function() {
|
||||
'"\'use strict\'";',
|
||||
1,
|
||||
// Intentionally causes directive breakage at cost of less logic, usage should be rare anyway
|
||||
"'\\'use strict\\'';",
|
||||
'"\'use strict\'";',
|
||||
],
|
||||
[
|
||||
"'\\'use strict\\'';", // Not a valid directive
|
||||
@@ -305,7 +302,7 @@ describe("Directives", function() {
|
||||
"'\"use strict\"';",
|
||||
2,
|
||||
// Intentionally causes directive breakage at cost of less logic, usage should be rare anyway
|
||||
'"\\\"use strict\\\"";',
|
||||
"'\"use strict\"';",
|
||||
],
|
||||
[
|
||||
'"\\"use strict\\"";', // Not a valid directive
|
||||
@@ -353,8 +350,7 @@ describe("Directives", function() {
|
||||
[
|
||||
// Nothing gets optimised in the compressor because "use asm" is the first statement
|
||||
'"use asm";"use\\x20strict";1+1;',
|
||||
// Yet, the parser noticed that "use strict" wasn't a directive
|
||||
'"use asm";;"use strict";1+1;',
|
||||
'"use asm";"use\\x20strict";1+1;'
|
||||
],
|
||||
[
|
||||
'function f(){ "use strict" }',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var assert = require("assert");
|
||||
var readFileSync = require("fs").readFileSync;
|
||||
var run_code = require("../sandbox").run_code;
|
||||
var UglifyJS = require("../../");
|
||||
var UglifyJS = require("../..");
|
||||
|
||||
function read(path) {
|
||||
return readFileSync(path, "utf8");
|
||||
@@ -9,18 +9,30 @@ function read(path) {
|
||||
|
||||
describe("minify", function() {
|
||||
it("Should test basic sanity of minify with default options", function() {
|
||||
var js = 'function foo(bar) { if (bar) return 3; else return 7; var u = not_called(); }';
|
||||
var js = "function foo(bar) { if (bar) return 3; else return 7; var u = not_called(); }";
|
||||
var result = UglifyJS.minify(js);
|
||||
assert.strictEqual(result.code, 'function foo(n){return n?3:7}');
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, "function foo(n){return n?3:7}");
|
||||
});
|
||||
|
||||
it("Should not mutate minify `options`", function() {
|
||||
var options = {
|
||||
compress: true,
|
||||
mangle: false,
|
||||
output: {},
|
||||
};
|
||||
var value = JSON.stringify(options);
|
||||
var result = UglifyJS.minify("print(6 * 7);", options);
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, "print(42);");
|
||||
assert.strictEqual(JSON.stringify(options), value);
|
||||
})
|
||||
it("Should skip inherited keys from `files`", function() {
|
||||
var files = Object.create({ skip: this });
|
||||
files[0] = "alert(1 + 1)";
|
||||
var result = UglifyJS.minify(files);
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, "alert(2);");
|
||||
});
|
||||
|
||||
it("Should work with mangle.cache", function() {
|
||||
var cache = {};
|
||||
var original = "";
|
||||
@@ -51,9 +63,8 @@ describe("minify", function() {
|
||||
"var a=n(3),b=r(12);",
|
||||
'c("qux",a,b),o(11);',
|
||||
].join(""));
|
||||
assert.strictEqual(run_code(compressed), run_code(original));
|
||||
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
||||
});
|
||||
|
||||
it("Should work with nameCache", function() {
|
||||
var cache = {};
|
||||
var original = "";
|
||||
@@ -84,9 +95,8 @@ describe("minify", function() {
|
||||
"var a=n(3),b=r(12);",
|
||||
'c("qux",a,b),o(11);',
|
||||
].join(""));
|
||||
assert.strictEqual(run_code(compressed), run_code(original));
|
||||
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
||||
});
|
||||
|
||||
it("Should avoid cached names when mangling top-level variables", function() {
|
||||
var cache = {};
|
||||
var original = "";
|
||||
@@ -113,9 +123,8 @@ describe("minify", function() {
|
||||
'"xxyyy";var y={y:2,a:3},a=4;',
|
||||
'console.log(x.x,y.y,y.a,a);',
|
||||
].join(""));
|
||||
assert.strictEqual(run_code(compressed), run_code(original));
|
||||
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
||||
});
|
||||
|
||||
it("Should avoid cached names when mangling inner-scoped variables", function() {
|
||||
var cache = {};
|
||||
var original = "";
|
||||
@@ -137,9 +146,8 @@ describe("minify", function() {
|
||||
'var o=function(o,n){console.log("extend");o();n()};function n(){console.log("A")}',
|
||||
'var e=function(n){function e(){console.log("B")}o(e,n);return e}(n);',
|
||||
].join(""));
|
||||
assert.strictEqual(run_code(compressed), run_code(original));
|
||||
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
||||
});
|
||||
|
||||
it("Should not parse invalid use of reserved words", function() {
|
||||
assert.strictEqual(UglifyJS.minify("function enum(){}").error, undefined);
|
||||
assert.strictEqual(UglifyJS.minify("function static(){}").error, undefined);
|
||||
@@ -155,7 +163,6 @@ describe("minify", function() {
|
||||
}});
|
||||
assert.strictEqual(result.code, 'var foo={"x":1,y:2,"z":3};');
|
||||
});
|
||||
|
||||
it("Should preserve quote styles when quote_style is 3", function() {
|
||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||
var result = UglifyJS.minify(js, {
|
||||
@@ -165,7 +172,6 @@ describe("minify", function() {
|
||||
}});
|
||||
assert.strictEqual(result.code, 'var foo={"x":1,y:2,\'z\':3};');
|
||||
});
|
||||
|
||||
it("Should not preserve quotes in object literals when disabled", function() {
|
||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||
var result = UglifyJS.minify(js, {
|
||||
|
||||
@@ -486,4 +486,19 @@ describe("operator", function() {
|
||||
assert.strictEqual(UglifyJS.parse(exp[0]).print_to_string(), exp[1] + ";");
|
||||
});
|
||||
});
|
||||
it("Should preserve space between /regex/ and `in`", function() {
|
||||
[
|
||||
"/regex/ in {}",
|
||||
"/regex/g in {}",
|
||||
"0 + /regex/ in {}",
|
||||
"0 + /regex/g in {}",
|
||||
].forEach(function(exp) {
|
||||
var code = UglifyJS.parse(exp).print_to_string();
|
||||
try {
|
||||
assert.strictEqual(UglifyJS.parse(code).print_to_string(), code);
|
||||
} catch (ex) {
|
||||
assert.fail("Failed to reparse: " + exp + "\n" + ex);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
316
test/mocha/reduce.js
Normal file
316
test/mocha/reduce.js
Normal file
@@ -0,0 +1,316 @@
|
||||
var assert = require("assert");
|
||||
var exec = require("child_process").exec;
|
||||
var fs = require("fs");
|
||||
var reduce_test = require("../reduce");
|
||||
var semver = require("semver");
|
||||
|
||||
function read(path) {
|
||||
return fs.readFileSync(path, "utf8");
|
||||
}
|
||||
|
||||
describe("test/reduce.js", function() {
|
||||
this.timeout(60000);
|
||||
it("Should reduce test case", function() {
|
||||
var result = reduce_test(read("test/input/reduce/unsafe_math.js"), {
|
||||
compress: {
|
||||
unsafe_math: true,
|
||||
},
|
||||
mangle: false,
|
||||
}, {
|
||||
verbose: false,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, read("test/input/reduce/unsafe_math.reduced.js"));
|
||||
});
|
||||
it("Should eliminate unreferenced labels", function() {
|
||||
var result = reduce_test(read("test/input/reduce/label.js"), {
|
||||
compress: {
|
||||
unsafe_math: true,
|
||||
},
|
||||
mangle: false,
|
||||
}, {
|
||||
verbose: false,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, read("test/input/reduce/label.reduced.js"));
|
||||
});
|
||||
it("Should retain setter arguments", function() {
|
||||
var result = reduce_test(read("test/input/reduce/setter.js"), {
|
||||
compress: {
|
||||
keep_fargs: false,
|
||||
unsafe: true,
|
||||
},
|
||||
mangle: false,
|
||||
}, {
|
||||
verbose: false,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, read("test/input/reduce/setter.reduced.js"));
|
||||
});
|
||||
it("Should handle test cases with --toplevel", function() {
|
||||
var result = reduce_test([
|
||||
"var Infinity = 42;",
|
||||
"console.log(Infinity);",
|
||||
].join("\n"), {
|
||||
toplevel: true,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"// Can't reproduce test failure",
|
||||
"// minify options: {",
|
||||
'// "toplevel": true',
|
||||
"// }",
|
||||
].join("\n"));
|
||||
});
|
||||
it("Should handle test cases with --compress toplevel", function() {
|
||||
var result = reduce_test([
|
||||
"var NaN = 42;",
|
||||
"console.log(NaN);",
|
||||
].join("\n"), {
|
||||
compress: {
|
||||
toplevel: true,
|
||||
},
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"// Can't reproduce test failure",
|
||||
"// minify options: {",
|
||||
'// "compress": {',
|
||||
'// "toplevel": true',
|
||||
"// }",
|
||||
"// }",
|
||||
].join("\n"));
|
||||
});
|
||||
it("Should handle test cases with --mangle toplevel", function() {
|
||||
var result = reduce_test([
|
||||
"var undefined = 42;",
|
||||
"console.log(undefined);",
|
||||
].join("\n"), {
|
||||
mangle: {
|
||||
toplevel: true,
|
||||
},
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"// Can't reproduce test failure",
|
||||
"// minify options: {",
|
||||
'// "mangle": {',
|
||||
'// "toplevel": true',
|
||||
"// }",
|
||||
"// }",
|
||||
].join("\n"));
|
||||
});
|
||||
it("Should handle test result of NaN", function() {
|
||||
var result = reduce_test("throw 0 / 0;");
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"// Can't reproduce test failure",
|
||||
"// minify options: {}",
|
||||
].join("\n"));
|
||||
});
|
||||
it("Should print correct output for irreducible test case", function() {
|
||||
var result = reduce_test([
|
||||
"console.log(function f(a) {",
|
||||
" return f.length;",
|
||||
"}());",
|
||||
].join("\n"), {
|
||||
compress: {
|
||||
keep_fargs: false,
|
||||
},
|
||||
mangle: false,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"// (beautified)",
|
||||
"console.log(function f(a) {",
|
||||
" return f.length;",
|
||||
"}());",
|
||||
"// output: 1",
|
||||
"// ",
|
||||
"// minify: 0",
|
||||
"// ",
|
||||
"// options: {",
|
||||
'// "compress": {',
|
||||
'// "keep_fargs": false',
|
||||
"// },",
|
||||
'// "mangle": false',
|
||||
"// }",
|
||||
].join("\n"));
|
||||
});
|
||||
it("Should fail when invalid option is supplied", function() {
|
||||
var result = reduce_test("", {
|
||||
compress: {
|
||||
unsafe_regex: true,
|
||||
},
|
||||
});
|
||||
var err = result.error;
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.stack.split(/\n/)[0], "DefaultsError: `unsafe_regex` is not a supported option");
|
||||
});
|
||||
it("Should report on test case with invalid syntax", function() {
|
||||
var result = reduce_test("var 0 = 1;");
|
||||
var err = result.error;
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Name expected");
|
||||
});
|
||||
it("Should format multi-line output correctly", function() {
|
||||
var code = [
|
||||
"var a = 0;",
|
||||
"",
|
||||
"for (var b in [ 1, 2, 3 ]) {",
|
||||
" a = +a + 1 - .2;",
|
||||
" console.log(a);",
|
||||
"}",
|
||||
].join("\n");
|
||||
var result = reduce_test(code, {
|
||||
compress: {
|
||||
unsafe_math: true,
|
||||
},
|
||||
mangle: false,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"// (beautified)",
|
||||
code,
|
||||
"// output: 0.8",
|
||||
"// 1.6",
|
||||
"// 2.4",
|
||||
"// ",
|
||||
"// minify: 0.8",
|
||||
"// 1.6",
|
||||
"// 2.4000000000000004",
|
||||
"// ",
|
||||
"// options: {",
|
||||
'// "compress": {',
|
||||
'// "unsafe_math": true',
|
||||
"// },",
|
||||
'// "mangle": false',
|
||||
"// }",
|
||||
].join("\n"));
|
||||
});
|
||||
it("Should reduce infinite loops with reasonable performance", function() {
|
||||
if (semver.satisfies(process.version, "<=0.10")) return;
|
||||
this.timeout(120000);
|
||||
var result = reduce_test("while (/9/.test(1 - .8));", {
|
||||
compress: {
|
||||
unsafe_math: true,
|
||||
},
|
||||
mangle: false,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code.replace(/ timed out after [0-9]+ms/, " timed out."), [
|
||||
"// (beautified)",
|
||||
"while (/9/.test(1 - .8)) {}",
|
||||
"// output: Error: Script execution timed out.",
|
||||
"// minify: ",
|
||||
"// options: {",
|
||||
'// "compress": {',
|
||||
'// "unsafe_math": true',
|
||||
"// },",
|
||||
'// "mangle": false',
|
||||
"// }",
|
||||
].join("\n"));
|
||||
});
|
||||
it("Should ignore difference in Error.message", function() {
|
||||
var result = reduce_test("null[function() {\n}];");
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, (semver.satisfies(process.version, "<=0.10") ? [
|
||||
"// Can't reproduce test failure",
|
||||
"// minify options: {}",
|
||||
] : [
|
||||
"// No differences except in error message",
|
||||
"// minify options: {}",
|
||||
]).join("\n"));
|
||||
});
|
||||
it("Should report trailing whitespace difference in stringified format", function() {
|
||||
var code = [
|
||||
"for (var a in (1 - .8).toString()) {",
|
||||
" console.log();",
|
||||
"}",
|
||||
].join("\n");
|
||||
var result = reduce_test(code, {
|
||||
compress: {
|
||||
unsafe_math: true,
|
||||
},
|
||||
mangle: false,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"// (beautified)",
|
||||
code,
|
||||
"// (stringified)",
|
||||
'// output: "\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n"',
|
||||
'// minify: "\\n\\n\\n"',
|
||||
"// options: {",
|
||||
'// "compress": {',
|
||||
'// "unsafe_math": true',
|
||||
'// },',
|
||||
'// "mangle": false',
|
||||
"// }",
|
||||
].join("\n"));
|
||||
});
|
||||
it("Should reduce test case which differs only in Error.message", function() {
|
||||
var code = [
|
||||
"var a=0;",
|
||||
"try{",
|
||||
"null[function(){}]",
|
||||
"}catch(e){",
|
||||
"for(var i in e.toString())",
|
||||
"a++,console.log()",
|
||||
"}",
|
||||
"console.log(a);",
|
||||
].join("");
|
||||
var result = reduce_test(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
beautify: true,
|
||||
},
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.deepEqual(result.warnings, []);
|
||||
assert.strictEqual(result.code.replace(/function \(/g, "function("), (semver.satisfies(process.version, "<=0.10") ? [
|
||||
"// Can't reproduce test failure",
|
||||
"// minify options: {",
|
||||
'// "compress": false,',
|
||||
'// "mangle": false,',
|
||||
'// "output": {',
|
||||
'// "beautify": true',
|
||||
"// }",
|
||||
"// }",
|
||||
] : [
|
||||
[
|
||||
"try{",
|
||||
"null[function(){}]",
|
||||
"}catch(e){",
|
||||
"console.log(e)",
|
||||
"}",
|
||||
].join(""),
|
||||
"// output: TypeError: Cannot read property 'function(){}' of null",
|
||||
"// ",
|
||||
"// minify: TypeError: Cannot read property 'function() {}' of null",
|
||||
"// ",
|
||||
"// options: {",
|
||||
'// "compress": false,',
|
||||
'// "mangle": false,',
|
||||
'// "output": {',
|
||||
'// "beautify": true',
|
||||
"// }",
|
||||
"// }",
|
||||
]).join("\n"));
|
||||
});
|
||||
it("Should handle corner cases when intermediate case differs only in Error.message", function() {
|
||||
if (semver.satisfies(process.version, "<=0.10")) return;
|
||||
var result = reduce_test(read("test/input/reduce/diff_error.js"), {
|
||||
compress: {
|
||||
keep_fargs: false,
|
||||
unsafe: true,
|
||||
},
|
||||
mangle: false,
|
||||
}, {
|
||||
verbose: false,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, read("test/input/reduce/diff_error.reduced.js"));
|
||||
});
|
||||
});
|
||||
@@ -1,18 +1,19 @@
|
||||
var assert = require("assert");
|
||||
var readFileSync = require("fs").readFileSync;
|
||||
var SourceMapConsumer = require("source-map").SourceMapConsumer;
|
||||
var fs = require("fs");
|
||||
var UglifyJS = require("../node");
|
||||
|
||||
function read(path) {
|
||||
return readFileSync(path, "utf8");
|
||||
return fs.readFileSync(path, "utf8");
|
||||
}
|
||||
|
||||
function source_map(code) {
|
||||
return JSON.parse(UglifyJS.minify(code, {
|
||||
var result = UglifyJS.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
sourceMap: true,
|
||||
}).map);
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
return JSON.parse(result.map);
|
||||
}
|
||||
|
||||
function get_map() {
|
||||
@@ -44,7 +45,7 @@ function prepare_map(sourceMap) {
|
||||
}
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
return new SourceMapConsumer(result.map);
|
||||
return JSON.parse(result.map);
|
||||
}
|
||||
|
||||
describe("sourcemaps", function() {
|
||||
@@ -66,6 +67,40 @@ describe("sourcemaps", function() {
|
||||
].join("\n"));
|
||||
assert.deepEqual(map.names, [ "enabled", "x" ]);
|
||||
});
|
||||
it("Should work with sourceMap.names=true", function() {
|
||||
var result = UglifyJS.minify([
|
||||
"var obj = {",
|
||||
" p: a,",
|
||||
" q: b",
|
||||
"};",
|
||||
].join("\n"), {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
sourceMap: {
|
||||
names: true,
|
||||
},
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
var map = JSON.parse(result.map);
|
||||
assert.deepEqual(map.names, [ "obj", "p", "a", "q", "b" ]);
|
||||
});
|
||||
it("Should work with sourceMap.names=false", function() {
|
||||
var result = UglifyJS.minify([
|
||||
"var obj = {",
|
||||
" p: a,",
|
||||
" q: b",
|
||||
"};",
|
||||
].join("\n"), {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
sourceMap: {
|
||||
names: false,
|
||||
},
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
var map = JSON.parse(result.map);
|
||||
assert.deepEqual(map.names, []);
|
||||
});
|
||||
it("Should mark array/object literals", function() {
|
||||
var result = UglifyJS.minify([
|
||||
"var obj = {};",
|
||||
@@ -87,14 +122,30 @@ describe("sourcemaps", function() {
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, code);
|
||||
assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["console","log"],"mappings":"AAAAA,QAAQC,IAAI","sourceRoot":"//foo.bar/"}');
|
||||
assert.strictEqual(result.map, '{"version":3,"sourceRoot":"//foo.bar/","sources":["0"],"names":["console","log"],"mappings":"AAAAA,QAAQC,IAAI"}');
|
||||
});
|
||||
it("Should produce same source map with DOS or UNIX line endings", function() {
|
||||
var code = [
|
||||
'console.log("\\',
|
||||
'hello",',
|
||||
'"world");',
|
||||
];
|
||||
var dos = UglifyJS.minify(code.join("\r\n"), {
|
||||
sourceMap: true,
|
||||
});
|
||||
if (dos.error) throw dos.error;
|
||||
var unix = UglifyJS.minify(code.join("\n"), {
|
||||
sourceMap: true,
|
||||
});
|
||||
if (unix.error) throw unix.error;
|
||||
assert.strictEqual(dos.map, unix.map);
|
||||
});
|
||||
|
||||
describe("inSourceMap", function() {
|
||||
it("Should read the given string filename correctly when sourceMapIncludeSources is enabled", function() {
|
||||
var result = UglifyJS.minify(read("./test/input/issue-1236/simple.js"), {
|
||||
var result = UglifyJS.minify(read("test/input/issue-1236/simple.js"), {
|
||||
sourceMap: {
|
||||
content: read("./test/input/issue-1236/simple.js.map"),
|
||||
content: read("test/input/issue-1236/simple.js.map"),
|
||||
filename: "simple.min.js",
|
||||
includeSources: true
|
||||
}
|
||||
@@ -106,7 +157,7 @@ describe("sourcemaps", function() {
|
||||
assert.equal(map.sourcesContent[0], 'let foo = x => "foo " + x;\nconsole.log(foo("bar"));');
|
||||
});
|
||||
it("Should process inline source map", function() {
|
||||
var result = UglifyJS.minify(read("./test/input/issue-520/input.js"), {
|
||||
var result = UglifyJS.minify(read("test/input/issue-520/input.js"), {
|
||||
compress: { toplevel: true },
|
||||
sourceMap: {
|
||||
content: "inline",
|
||||
@@ -115,10 +166,10 @@ describe("sourcemaps", function() {
|
||||
}
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code + "\n", readFileSync("test/input/issue-520/output.js", "utf8"));
|
||||
assert.strictEqual(result.code + "\n", read("test/input/issue-520/output.js"));
|
||||
});
|
||||
it("Should warn for missing inline source map", 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,
|
||||
sourceMap: {
|
||||
content: "inline"
|
||||
@@ -130,8 +181,8 @@ describe("sourcemaps", function() {
|
||||
});
|
||||
it("Should handle multiple input and inline source map", function() {
|
||||
var result = UglifyJS.minify([
|
||||
read("./test/input/issue-520/input.js"),
|
||||
read("./test/input/issue-1323/sample.js"),
|
||||
read("test/input/issue-520/input.js"),
|
||||
read("test/input/issue-1323/sample.js"),
|
||||
], {
|
||||
sourceMap: {
|
||||
content: "inline",
|
||||
@@ -147,7 +198,7 @@ describe("sourcemaps", function() {
|
||||
assert.deepEqual(result.warnings, [ "WARN: inline source map not found: 1" ]);
|
||||
});
|
||||
it("Should drop source contents for includeSources=false", function() {
|
||||
var result = UglifyJS.minify(read("./test/input/issue-520/input.js"), {
|
||||
var result = UglifyJS.minify(read("test/input/issue-520/input.js"), {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
sourceMap: {
|
||||
@@ -170,7 +221,7 @@ describe("sourcemaps", function() {
|
||||
assert.ok(!("sourcesContent" in map));
|
||||
});
|
||||
it("Should parse the correct sourceMappingURL", function() {
|
||||
var result = UglifyJS.minify(read("./test/input/issue-3294/input.js"), {
|
||||
var result = UglifyJS.minify(read("test/input/issue-3294/input.js"), {
|
||||
compress: { toplevel: true },
|
||||
sourceMap: {
|
||||
content: "inline",
|
||||
@@ -179,10 +230,10 @@ describe("sourcemaps", function() {
|
||||
}
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code + "\n", readFileSync("test/input/issue-3294/output.js", "utf8"));
|
||||
assert.strictEqual(result.code + "\n", read("test/input/issue-3294/output.js"));
|
||||
});
|
||||
it("Should work in presence of unrecognised 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,
|
||||
mangle: false,
|
||||
sourceMap: {
|
||||
@@ -214,7 +265,7 @@ describe("sourcemaps", function() {
|
||||
assert.strictEqual(code, "var a=function(n){return n};");
|
||||
});
|
||||
it("Should work with max_line_len", function() {
|
||||
var result = UglifyJS.minify(read("./test/input/issue-505/input.js"), {
|
||||
var result = UglifyJS.minify(read("test/input/issue-505/input.js"), {
|
||||
compress: {
|
||||
directives: false,
|
||||
},
|
||||
@@ -226,7 +277,7 @@ describe("sourcemaps", function() {
|
||||
}
|
||||
});
|
||||
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"));
|
||||
});
|
||||
it("Should work with unicode characters", function() {
|
||||
var code = [
|
||||
@@ -262,32 +313,42 @@ describe("sourcemaps", function() {
|
||||
});
|
||||
|
||||
describe("input sourcemaps", function() {
|
||||
it("Should not modify input source map", function() {
|
||||
var orig = get_map();
|
||||
var original = JSON.stringify(orig);
|
||||
var map = prepare_map(orig);
|
||||
assert.strictEqual(JSON.stringify(orig), original);
|
||||
});
|
||||
it("Should copy over original sourcesContent", function() {
|
||||
var orig = get_map();
|
||||
var map = prepare_map(orig);
|
||||
assert.equal(map.sourceContentFor("index.js"), orig.sourcesContent[0]);
|
||||
assert.strictEqual(map.sources.length, 1);
|
||||
assert.strictEqual(map.sources[0], "index.js");
|
||||
assert.strictEqual(map.sourcesContent.length, 1);
|
||||
assert.equal(map.sourcesContent[0], orig.sourcesContent[0]);
|
||||
});
|
||||
it("Should copy sourcesContent if sources are relative", function() {
|
||||
var relativeMap = get_map();
|
||||
relativeMap.sources = ['./index.js'];
|
||||
var map = prepare_map(relativeMap);
|
||||
assert.notEqual(map.sourcesContent, null);
|
||||
assert.equal(map.sourcesContent.length, 1);
|
||||
assert.equal(map.sourceContentFor("index.js"), relativeMap.sourcesContent[0]);
|
||||
assert.strictEqual(map.sources.length, 1);
|
||||
assert.strictEqual(map.sources[0], "./index.js");
|
||||
assert.strictEqual(map.sourcesContent.length, 1);
|
||||
assert.equal(map.sourcesContent[0], relativeMap.sourcesContent[0]);
|
||||
});
|
||||
it("Should not have invalid mappings from inputSourceMap", function() {
|
||||
var map = prepare_map(get_map());
|
||||
// The original source has only 2 lines, check that mappings don't have more lines
|
||||
var msg = "Mapping should not have higher line number than the original file had";
|
||||
map.eachMapping(function(mapping) {
|
||||
assert.ok(mapping.originalLine <= 2, msg);
|
||||
});
|
||||
map.allGeneratedPositionsFor({
|
||||
source: "index.js",
|
||||
line: 1,
|
||||
column: 1
|
||||
}).forEach(function(pos) {
|
||||
assert.ok(pos.line <= 2, msg);
|
||||
var lines = map.mappings.split(/;/);
|
||||
assert.ok(lines.length <= 2, msg);
|
||||
var indices = [ 0, 0, 1, 0, 0];
|
||||
lines.forEach(function(segments) {
|
||||
indices[0] = 0;
|
||||
segments.split(/,/).forEach(function(segment) {
|
||||
UglifyJS.vlq_decode(indices, segment);
|
||||
assert.ok(indices[2] <= 2, msg);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -59,13 +59,13 @@ describe("String literals", function() {
|
||||
|
||||
it("Should not throw error outside strict mode if string contains escaped octalIntegerLiteral", function() {
|
||||
var tests = [
|
||||
['"\\76";', ';">";'],
|
||||
['"\\0"', '"\\0";'],
|
||||
['"\\08"', '"\\x008";'],
|
||||
['"\\008"', '"\\x008";'],
|
||||
['"\\0008"', '"\\x008";'],
|
||||
['"use strict" === "use strict";\n"\\76";', '"use strict"==="use strict";">";'],
|
||||
['"use\\\n strict";\n"\\07";', ';"use strict";"\07";']
|
||||
[ ';"\\76";', ';">";' ],
|
||||
[ ';"\\0";', ';"\\0";' ],
|
||||
[ ';"\\08"', ';"\\x008";' ],
|
||||
[ ';"\\008"', ';"\\x008";' ],
|
||||
[ ';"\\0008"', ';"\\x008";' ],
|
||||
[ ';"use\\\n strict";\n"\\07";', ';"use strict";"\07";' ],
|
||||
[ '"use strict" === "use strict";\n"\\76";', '"use strict"==="use strict";">";' ],
|
||||
];
|
||||
|
||||
for (var test in tests) {
|
||||
@@ -75,8 +75,8 @@ describe("String literals", function() {
|
||||
});
|
||||
|
||||
it("Should not throw error when digit is 8 or 9", function() {
|
||||
assert.equal(UglifyJS.parse('"use strict";"\\08"').print_to_string(), '"use strict";"\\x008";');
|
||||
assert.equal(UglifyJS.parse('"use strict";"\\09"').print_to_string(), '"use strict";"\\x009";');
|
||||
assert.equal(UglifyJS.parse('"use strict";;"\\08"').print_to_string(), '"use strict";;"\\x008";');
|
||||
assert.equal(UglifyJS.parse('"use strict";;"\\09"').print_to_string(), '"use strict";;"\\x009";');
|
||||
});
|
||||
|
||||
it("Should not unescape unpaired surrogates", function() {
|
||||
@@ -93,7 +93,7 @@ describe("String literals", function() {
|
||||
for (; i <= 0xFFFF; i++) {
|
||||
code.push("\\u" + i.toString(16));
|
||||
}
|
||||
code = '"' + code.join() + '"';
|
||||
code = ';"' + code.join() + '"';
|
||||
var normal = UglifyJS.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
|
||||
@@ -24,11 +24,22 @@ function try_beautify(code) {
|
||||
}
|
||||
}
|
||||
|
||||
function test(original, estree, description) {
|
||||
var transformed = UglifyJS.minify(UglifyJS.AST_Node.from_mozilla_ast(estree), {
|
||||
function validate(ast) {
|
||||
try {
|
||||
ast.walk(new UglifyJS.TreeWalker(function(node) {
|
||||
node.validate();
|
||||
}));
|
||||
} catch (e) {
|
||||
return { error: e };
|
||||
}
|
||||
return UglifyJS.minify(ast, {
|
||||
compress: false,
|
||||
mangle: false
|
||||
mangle: false,
|
||||
});
|
||||
}
|
||||
|
||||
function test(original, estree, description) {
|
||||
var transformed = validate(UglifyJS.AST_Node.from_mozilla_ast(estree));
|
||||
if (transformed.error || original !== transformed.code) {
|
||||
console.log("//=============================================================");
|
||||
console.log("// !!!!!! Failed... round", round);
|
||||
@@ -44,30 +55,37 @@ function test(original, estree, description) {
|
||||
try_beautify(transformed.code);
|
||||
}
|
||||
console.log("!!!!!! Failed... round", round);
|
||||
process.exit(1);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var num_iterations = ufuzz.num_iterations;
|
||||
var minify_options = require("./ufuzz/options.json").map(JSON.stringify);
|
||||
minify_options.unshift(null);
|
||||
for (var round = 1; round <= num_iterations; round++) {
|
||||
process.stdout.write(round + " of " + num_iterations + "\r");
|
||||
var code = ufuzz.createTopLevelCode();
|
||||
var uglified = UglifyJS.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ast: true
|
||||
minify_options.forEach(function(options) {
|
||||
var input = options ? UglifyJS.minify(code, JSON.parse(options)).code : code;
|
||||
var uglified = UglifyJS.minify(input, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ast: true
|
||||
}
|
||||
});
|
||||
var ok = test(uglified.code, uglified.ast.to_mozilla_ast(), "AST_Node.to_mozilla_ast()");
|
||||
try {
|
||||
ok = test(uglified.code, acorn.parse(input), "acorn.parse()") && ok;
|
||||
} catch (e) {
|
||||
console.log("//=============================================================");
|
||||
console.log("// acorn parser failed... round", round);
|
||||
console.log(e);
|
||||
console.log("// original code");
|
||||
console.log(input);
|
||||
}
|
||||
if (!ok) process.exit(1);
|
||||
});
|
||||
test(uglified.code, uglified.ast.to_mozilla_ast(), "AST_Node.to_mozilla_ast()");
|
||||
try {
|
||||
test(uglified.code, acorn.parse(code), "acorn.parse()");
|
||||
} catch (e) {
|
||||
console.log("//=============================================================");
|
||||
console.log("// acorn parser failed... round", round);
|
||||
console.log(e);
|
||||
console.log("// original code");
|
||||
console.log(code);
|
||||
}
|
||||
}
|
||||
console.log();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var fs = require("fs");
|
||||
|
||||
new Function("MOZ_SourceMap", "exports", require("../tools/node").FILES.map(function(file) {
|
||||
new Function("exports", require("../tools/node").FILES.map(function(file) {
|
||||
if (/exports\.js$/.test(file)) file = require.resolve("./exports");
|
||||
return fs.readFileSync(file, "utf8");
|
||||
}).join("\n\n"))(require("source-map"), exports);
|
||||
}).join("\n\n"))(exports);
|
||||
|
||||
690
test/reduce.js
Normal file
690
test/reduce.js
Normal file
@@ -0,0 +1,690 @@
|
||||
var crypto = require("crypto");
|
||||
var U = require("..");
|
||||
var List = U.List;
|
||||
var os = require("os");
|
||||
var sandbox = require("./sandbox");
|
||||
|
||||
// Reduce a test case by iteratively replacing AST nodes with various
|
||||
// permutations. Each AST_Statement in the tree is also speculatively dropped
|
||||
// to determine whether it is needed. If the altered tree and the last known
|
||||
// good tree produce the same output after being run, then the permutation
|
||||
// survives to the next generation and is the basis for subsequent iterations.
|
||||
// The test case is reduced as a consequence of complex expressions being
|
||||
// replaced with simpler ones. Note that a reduced test case will have
|
||||
// different runtime output - it is not functionally equivalent to the
|
||||
// original. The only criteria is that once the generated reduced test case is
|
||||
// run without minification, it will produce different output from the code
|
||||
// minified with `minify_options`. Returns a `minify` result object.
|
||||
|
||||
Error.stackTraceLimit = Infinity;
|
||||
module.exports = function reduce_test(testcase, minify_options, reduce_options) {
|
||||
if (testcase instanceof U.AST_Node) testcase = testcase.print_to_string();
|
||||
minify_options = minify_options || {};
|
||||
reduce_options = reduce_options || {};
|
||||
var max_iterations = reduce_options.max_iterations || 1000;
|
||||
var max_timeout = reduce_options.max_timeout || 10000;
|
||||
var warnings = [];
|
||||
var log = reduce_options.log || function(msg) {
|
||||
warnings.push(msg);
|
||||
};
|
||||
var verbose = reduce_options.verbose;
|
||||
var minify_options_json = JSON.stringify(minify_options, null, 2);
|
||||
var result_cache = Object.create(null);
|
||||
var test_for_diff = compare_run_code;
|
||||
// the initial timeout to assess the viability of the test case must be large
|
||||
var differs = test_for_diff(testcase, minify_options, result_cache, max_timeout);
|
||||
|
||||
if (verbose) {
|
||||
log("// Node.js " + process.version + " on " + os.platform() + " " + os.arch());
|
||||
}
|
||||
if (differs.error && [ "DefaultsError", "SyntaxError" ].indexOf(differs.error.name) < 0) {
|
||||
test_for_diff = test_minify;
|
||||
differs = test_for_diff(testcase, minify_options, result_cache, max_timeout);
|
||||
}
|
||||
if (!differs) {
|
||||
// same stdout result produced when minified
|
||||
return {
|
||||
code: [
|
||||
"// Can't reproduce test failure",
|
||||
"// minify options: " + to_comment(minify_options_json)
|
||||
].join("\n"),
|
||||
warnings: warnings,
|
||||
};
|
||||
} else if (differs.timed_out) {
|
||||
return {
|
||||
code: [
|
||||
"// Can't reproduce test failure within " + max_timeout + "ms",
|
||||
"// minify options: " + to_comment(minify_options_json)
|
||||
].join("\n"),
|
||||
warnings: warnings,
|
||||
};
|
||||
} else if (differs.error) {
|
||||
differs.warnings = warnings;
|
||||
return differs;
|
||||
} else if (is_error(differs.unminified_result)
|
||||
&& is_error(differs.minified_result)
|
||||
&& differs.unminified_result.name == differs.minified_result.name) {
|
||||
return {
|
||||
code: [
|
||||
"// No differences except in error message",
|
||||
"// minify options: " + to_comment(minify_options_json)
|
||||
].join("\n"),
|
||||
warnings: warnings,
|
||||
};
|
||||
} else {
|
||||
max_timeout = Math.min(100 * differs.elapsed, max_timeout);
|
||||
// Replace expressions with constants that will be parsed into
|
||||
// AST_Nodes as required. Each AST_Node has its own permutation count,
|
||||
// so these replacements can't be shared.
|
||||
// Although simpler replacements are generally faster and better,
|
||||
// feel free to experiment with a different replacement set.
|
||||
var REPLACEMENTS = [
|
||||
// "null", "''", "false", "'foo'", "undefined", "9",
|
||||
"1", "0",
|
||||
];
|
||||
|
||||
// There's a relationship between each node's _permute counter and
|
||||
// REPLACEMENTS.length which is why fractional _permutes were needed.
|
||||
// One could scale all _permute operations by a factor of `steps`
|
||||
// to only deal with integer operations, but this works well enough.
|
||||
var steps = 4; // must be a power of 2
|
||||
var step = 1 / steps; // 0.25 is exactly representable in floating point
|
||||
|
||||
var tt = new U.TreeTransformer(function(node, descend, in_list) {
|
||||
if (CHANGED) return;
|
||||
|
||||
// quick ignores
|
||||
if (node instanceof U.AST_Accessor) return;
|
||||
if (node instanceof U.AST_Directive) return;
|
||||
if (!in_list && node instanceof U.AST_EmptyStatement) return;
|
||||
if (node instanceof U.AST_Label) return;
|
||||
if (node instanceof U.AST_LabelRef) return;
|
||||
if (!in_list && node instanceof U.AST_SymbolDeclaration) return;
|
||||
if (node instanceof U.AST_Toplevel) return;
|
||||
var parent = tt.parent();
|
||||
if (node instanceof U.AST_SymbolFunarg && parent instanceof U.AST_Accessor) return;
|
||||
|
||||
// ensure that the _permute prop is a number.
|
||||
// can not use `node.start._permute |= 0;` as it will erase fractional part.
|
||||
if (typeof node.start._permute === "undefined") node.start._permute = 0;
|
||||
|
||||
// if node reached permutation limit - skip over it.
|
||||
// no structural AST changes before this point.
|
||||
if (node.start._permute >= REPLACEMENTS.length) return;
|
||||
|
||||
// ignore lvalues
|
||||
if (parent instanceof U.AST_Assign && parent.left === node) return;
|
||||
if (parent instanceof U.AST_Unary && parent.expression === node) switch (parent.operator) {
|
||||
case "++":
|
||||
case "--":
|
||||
case "delete":
|
||||
return;
|
||||
}
|
||||
// preserve for (var xxx; ...)
|
||||
if (parent instanceof U.AST_For && parent.init === node && node instanceof U.AST_Var) return node;
|
||||
// preserve for (xxx in ...)
|
||||
if (parent instanceof U.AST_ForIn && parent.init === node) return node;
|
||||
|
||||
// node specific permutations with no parent logic
|
||||
|
||||
if (node instanceof U.AST_Array) {
|
||||
var expr = node.elements[0];
|
||||
if (expr && !(expr instanceof U.AST_Hole)) {
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_Binary) {
|
||||
var permute = ((node.start._permute += step) * steps | 0) % 4;
|
||||
var expr = [
|
||||
node.left,
|
||||
node.right,
|
||||
][ permute & 1 ];
|
||||
CHANGED = true;
|
||||
return permute < 2 ? expr : wrap_with_console_log(expr);
|
||||
}
|
||||
else if (node instanceof U.AST_BlockStatement) {
|
||||
if (in_list) {
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return List.splice(node.body);
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_Call) {
|
||||
var expr = [
|
||||
node.expression,
|
||||
node.args[0],
|
||||
null, // intentional
|
||||
][ ((node.start._permute += step) * steps | 0) % 3 ];
|
||||
if (expr) {
|
||||
CHANGED = true;
|
||||
return expr;
|
||||
}
|
||||
if (node.expression instanceof U.AST_Function) {
|
||||
// hoist and return expressions from the IIFE function expression
|
||||
var body = node.expression.body;
|
||||
node.expression.body = [];
|
||||
var seq = [];
|
||||
body.forEach(function(node) {
|
||||
var expr = expr instanceof U.AST_Exit ? node.value : node.body;
|
||||
if (expr instanceof U.AST_Node && !is_statement(expr)) {
|
||||
// collect expressions from each statements' body
|
||||
seq.push(expr);
|
||||
}
|
||||
});
|
||||
CHANGED = true;
|
||||
return to_sequence(seq);
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_Catch) {
|
||||
// drop catch block
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return null;
|
||||
}
|
||||
else if (node instanceof U.AST_Conditional) {
|
||||
CHANGED = true;
|
||||
return [
|
||||
node.condition,
|
||||
node.consequent,
|
||||
node.alternative,
|
||||
][ ((node.start._permute += step) * steps | 0) % 3 ];
|
||||
}
|
||||
else if (node instanceof U.AST_Defun) {
|
||||
switch (((node.start._permute += step) * steps | 0) % 2) {
|
||||
case 0:
|
||||
CHANGED = true;
|
||||
return List.skip;
|
||||
default:
|
||||
if (!has_exit(node)) {
|
||||
// hoist function declaration body
|
||||
var body = node.body;
|
||||
node.body = [];
|
||||
body.push(node); // retain function with empty body to be dropped later
|
||||
CHANGED = true;
|
||||
return List.splice(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_DWLoop) {
|
||||
var expr = [
|
||||
node.condition,
|
||||
node.body,
|
||||
null, // intentional
|
||||
][ (node.start._permute * steps | 0) % 3 ];
|
||||
node.start._permute += step;
|
||||
if (!expr) {
|
||||
if (node.body[0] instanceof U.AST_Break) {
|
||||
if (node instanceof U.AST_Do) {
|
||||
CHANGED = true;
|
||||
return List.skip;
|
||||
}
|
||||
expr = node.condition; // AST_While - fall through
|
||||
}
|
||||
}
|
||||
if (expr && (expr !== node.body || !has_loopcontrol(expr, node, parent))) {
|
||||
CHANGED = true;
|
||||
return to_statement(expr);
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_Finally) {
|
||||
// drop finally block
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return null;
|
||||
}
|
||||
else if (node instanceof U.AST_For) {
|
||||
var expr = [
|
||||
node.init,
|
||||
node.condition,
|
||||
node.step,
|
||||
node.body,
|
||||
][ (node.start._permute * steps | 0) % 4 ];
|
||||
node.start._permute += step;
|
||||
if (expr && (expr !== node.body || !has_loopcontrol(expr, node, parent))) {
|
||||
CHANGED = true;
|
||||
return to_statement(expr);
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_ForIn) {
|
||||
var expr = [
|
||||
node.init,
|
||||
node.object,
|
||||
node.body,
|
||||
][ (node.start._permute * steps | 0) % 3 ];
|
||||
node.start._permute += step;
|
||||
if (expr && (expr !== node.body || !has_loopcontrol(expr, node, parent))) {
|
||||
CHANGED = true;
|
||||
return to_statement(expr);
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_If) {
|
||||
var expr = [
|
||||
node.condition,
|
||||
node.body,
|
||||
node.alternative,
|
||||
][ (node.start._permute * steps | 0) % 3 ];
|
||||
node.start._permute += step;
|
||||
if (expr) {
|
||||
// replace if statement with its condition, then block or else block
|
||||
CHANGED = true;
|
||||
return to_statement(expr);
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_Object) {
|
||||
// first property's value
|
||||
var expr = node.properties[0] instanceof U.AST_ObjectKeyVal && node.properties[0].value;
|
||||
if (expr) {
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_PropAccess) {
|
||||
var expr = [
|
||||
node.expression,
|
||||
node.property instanceof U.AST_Node && node.property,
|
||||
][ node.start._permute++ % 2 ];
|
||||
if (expr) {
|
||||
CHANGED = true;
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_SimpleStatement) {
|
||||
if (node.body instanceof U.AST_Call && node.body.expression instanceof U.AST_Function) {
|
||||
// hoist simple statement IIFE function expression body
|
||||
node.start._permute++;
|
||||
if (!has_exit(node.body.expression)) {
|
||||
var body = node.body.expression.body;
|
||||
node.body.expression.body = [];
|
||||
CHANGED = true;
|
||||
return List.splice(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_Switch) {
|
||||
var expr = [
|
||||
node.expression, // switch expression
|
||||
node.body[0] && node.body[0].expression, // first case expression or undefined
|
||||
node.body[0] && node.body[0], // first case body or undefined
|
||||
][ (node.start._permute * steps | 0) % 4 ];
|
||||
node.start._permute += step;
|
||||
if (expr && (!(expr instanceof U.AST_Statement) || !has_loopcontrol(expr, node, parent))) {
|
||||
CHANGED = true;
|
||||
return expr instanceof U.AST_SwitchBranch ? new U.AST_BlockStatement({
|
||||
body: expr.body.slice(),
|
||||
start: {},
|
||||
}) : to_statement(expr);
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_Try) {
|
||||
var body = [
|
||||
node.body,
|
||||
node.bcatch && node.bcatch.body,
|
||||
node.bfinally && node.bfinally.body,
|
||||
null, // intentional
|
||||
][ (node.start._permute * steps | 0) % 4 ];
|
||||
node.start._permute += step;
|
||||
if (body) {
|
||||
// replace try statement with try block, catch block, or finally block
|
||||
CHANGED = true;
|
||||
return new U.AST_BlockStatement({
|
||||
body: body,
|
||||
start: {},
|
||||
});
|
||||
} else {
|
||||
// replace try with a break or return if first in try statement
|
||||
if (node.body[0] instanceof U.AST_Break
|
||||
|| node.body[0] instanceof U.AST_Return) {
|
||||
CHANGED = true;
|
||||
return node.body[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_Unary) {
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return node.expression;
|
||||
}
|
||||
else if (node instanceof U.AST_Var) {
|
||||
if (node.definitions.length == 1 && node.definitions[0].value) {
|
||||
// first declaration value
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return to_statement(node.definitions[0].value);
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_LabeledStatement) {
|
||||
if (node.body instanceof U.AST_Statement
|
||||
&& !has_loopcontrol(node.body, node.body, node)) {
|
||||
// replace labelled statement with its non-labelled body
|
||||
node.start._permute = REPLACEMENTS.length;
|
||||
CHANGED = true;
|
||||
return node.body;
|
||||
}
|
||||
}
|
||||
|
||||
if (in_list) {
|
||||
// special case to drop object properties and switch branches
|
||||
if (parent instanceof U.AST_Object
|
||||
|| parent instanceof U.AST_Switch && parent.expression != node) {
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return List.skip;
|
||||
}
|
||||
|
||||
// replace or skip statement
|
||||
if (node instanceof U.AST_Statement) {
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return List.skip;
|
||||
}
|
||||
|
||||
// remove this node unless its the sole element of a (transient) sequence
|
||||
if (!(parent instanceof U.AST_Sequence) || parent.expressions.length > 1) {
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return List.skip;
|
||||
}
|
||||
}
|
||||
|
||||
// replace this node
|
||||
var newNode = is_statement(node) ? new U.AST_EmptyStatement({
|
||||
start: {},
|
||||
}) : U.parse(REPLACEMENTS[node.start._permute % REPLACEMENTS.length | 0], {
|
||||
expression: true,
|
||||
});
|
||||
newNode.start._permute = ++node.start._permute;
|
||||
CHANGED = true;
|
||||
return newNode;
|
||||
}, function(node, in_list) {
|
||||
if (node instanceof U.AST_Sequence) {
|
||||
// expand single-element sequence
|
||||
if (node.expressions.length == 1) return node.expressions[0];
|
||||
}
|
||||
else if (node instanceof U.AST_Try) {
|
||||
// expand orphaned try block
|
||||
if (!node.bcatch && !node.bfinally) return new U.AST_BlockStatement({
|
||||
body: node.body,
|
||||
start: {},
|
||||
});
|
||||
}
|
||||
else if (node instanceof U.AST_Var) {
|
||||
// remove empty var statement
|
||||
if (node.definitions.length == 0) return in_list ? List.skip : new U.AST_EmptyStatement({
|
||||
start: {},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var diff_error_message;
|
||||
for (var pass = 1; pass <= 3; ++pass) {
|
||||
var testcase_ast = U.parse(testcase);
|
||||
if (diff_error_message === testcase) {
|
||||
// only difference detected is in error message, so expose that and try again
|
||||
testcase_ast.transform(new U.TreeTransformer(function(node, descend) {
|
||||
if (node.TYPE == "Call" && node.expression.print_to_string() == "console.log") {
|
||||
return to_sequence(node.args);
|
||||
}
|
||||
if (node instanceof U.AST_Catch) {
|
||||
descend(node, this);
|
||||
node.body.unshift(new U.AST_SimpleStatement({
|
||||
body: wrap_with_console_log(new U.AST_SymbolRef(node.argname)),
|
||||
start: {},
|
||||
}));
|
||||
return node;
|
||||
}
|
||||
}));
|
||||
var code = testcase_ast.print_to_string();
|
||||
var diff = test_for_diff(code, minify_options, result_cache, max_timeout);
|
||||
if (diff && !diff.timed_out && !diff.error) {
|
||||
testcase = code;
|
||||
differs = diff;
|
||||
} else {
|
||||
testcase_ast = U.parse(testcase);
|
||||
}
|
||||
}
|
||||
diff_error_message = null;
|
||||
testcase_ast.walk(new U.TreeWalker(function(node) {
|
||||
// unshare start props to retain visit data between iterations
|
||||
node.start = JSON.parse(JSON.stringify(node.start));
|
||||
node.start._permute = 0;
|
||||
}));
|
||||
var before_iterations = testcase;
|
||||
for (var c = 0; c < max_iterations; ++c) {
|
||||
if (verbose && pass == 1 && c % 25 == 0) {
|
||||
log("// reduce test pass " + pass + ", iteration " + c + ": " + testcase.length + " bytes");
|
||||
}
|
||||
var CHANGED = false;
|
||||
var code_ast = testcase_ast.clone(true).transform(tt);
|
||||
if (!CHANGED) break;
|
||||
try {
|
||||
var code = code_ast.print_to_string();
|
||||
} catch (ex) {
|
||||
// AST is not well formed.
|
||||
// no harm done - just log the error, ignore latest change and continue iterating.
|
||||
log("*** Error generating code from AST.");
|
||||
log(ex.stack);
|
||||
log("*** Discarding permutation and continuing.");
|
||||
continue;
|
||||
}
|
||||
var diff = test_for_diff(code, minify_options, result_cache, max_timeout);
|
||||
if (diff) {
|
||||
if (diff.timed_out) {
|
||||
// can't trust the validity of `code_ast` and `code` when timed out.
|
||||
// no harm done - just ignore latest change and continue iterating.
|
||||
} else if (diff.error) {
|
||||
// something went wrong during minify() - could be malformed AST or genuine bug.
|
||||
// no harm done - just log code & error, ignore latest change and continue iterating.
|
||||
log("*** Error during minification.");
|
||||
log(code);
|
||||
log(diff.error.stack);
|
||||
log("*** Discarding permutation and continuing.");
|
||||
} else if (is_error(diff.unminified_result)
|
||||
&& is_error(diff.minified_result)
|
||||
&& diff.unminified_result.name == diff.minified_result.name) {
|
||||
// ignore difference in error messages caused by minification
|
||||
diff_error_message = testcase;
|
||||
} else {
|
||||
// latest permutation is valid, so use it as the basis of new changes
|
||||
testcase_ast = code_ast;
|
||||
testcase = code;
|
||||
differs = diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (before_iterations === testcase) break;
|
||||
if (verbose) {
|
||||
log("// reduce test pass " + pass + ": " + testcase.length + " bytes");
|
||||
}
|
||||
}
|
||||
testcase = try_beautify(testcase, minify_options, differs.unminified_result, result_cache, max_timeout);
|
||||
var lines = [ "" ];
|
||||
if (isNaN(max_timeout)) {
|
||||
lines.push("// minify error: " + to_comment(strip_color_codes(differs.minified_result.stack)));
|
||||
} else {
|
||||
var unminified_result = strip_color_codes(differs.unminified_result);
|
||||
var minified_result = strip_color_codes(differs.minified_result);
|
||||
if (trim_trailing_whitespace(unminified_result) == trim_trailing_whitespace(minified_result)) {
|
||||
lines.push(
|
||||
"// (stringified)",
|
||||
"// output: " + JSON.stringify(unminified_result),
|
||||
"// minify: " + JSON.stringify(minified_result)
|
||||
);
|
||||
} else {
|
||||
lines.push(
|
||||
"// output: " + to_comment(unminified_result),
|
||||
"// minify: " + to_comment(minified_result)
|
||||
);
|
||||
}
|
||||
}
|
||||
lines.push("// options: " + to_comment(minify_options_json));
|
||||
testcase.code += lines.join("\n");
|
||||
testcase.warnings = warnings;
|
||||
return testcase;
|
||||
}
|
||||
};
|
||||
|
||||
function strip_color_codes(value) {
|
||||
return ("" + value).replace(/\u001b\[\d+m/g, "");
|
||||
}
|
||||
|
||||
function to_comment(value) {
|
||||
return ("" + value).replace(/\n/g, "\n// ");
|
||||
}
|
||||
|
||||
function trim_trailing_whitespace(value) {
|
||||
return ("" + value).replace(/\s+$/, "");
|
||||
}
|
||||
|
||||
function try_beautify(testcase, minify_options, expected, result_cache, timeout) {
|
||||
var result = U.minify(testcase, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
beautify: true,
|
||||
braces: true,
|
||||
comments: true,
|
||||
},
|
||||
});
|
||||
if (result.error) return {
|
||||
code: testcase,
|
||||
};
|
||||
var toplevel = sandbox.has_toplevel(minify_options);
|
||||
if (isNaN(timeout)) {
|
||||
if (!U.minify(result.code, minify_options).error) return {
|
||||
code: testcase,
|
||||
};
|
||||
} else {
|
||||
var actual = run_code(result.code, toplevel, result_cache, timeout).result;
|
||||
if (!sandbox.same_stdout(expected, actual)) return {
|
||||
code: testcase,
|
||||
};
|
||||
}
|
||||
result.code = "// (beautified)\n" + result.code;
|
||||
return result;
|
||||
}
|
||||
|
||||
function has_exit(fn) {
|
||||
var found = false;
|
||||
var tw = new U.TreeWalker(function(node) {
|
||||
if (found) return found;
|
||||
if (node instanceof U.AST_Exit) {
|
||||
return found = true;
|
||||
}
|
||||
if (node instanceof U.AST_Scope && node !== fn) {
|
||||
return true; // don't descend into nested functions
|
||||
}
|
||||
});
|
||||
fn.walk(tw);
|
||||
return found;
|
||||
}
|
||||
|
||||
function has_loopcontrol(body, loop, label) {
|
||||
var found = false;
|
||||
var tw = new U.TreeWalker(function(node) {
|
||||
if (found) return true;
|
||||
if (node instanceof U.AST_LoopControl && this.loopcontrol_target(node) === loop) {
|
||||
return found = true;
|
||||
}
|
||||
});
|
||||
if (label instanceof U.AST_LabeledStatement) tw.push(label);
|
||||
tw.push(loop);
|
||||
body.walk(tw);
|
||||
return found;
|
||||
}
|
||||
|
||||
function is_error(result) {
|
||||
return typeof result == "object" && typeof result.name == "string" && typeof result.message == "string";
|
||||
}
|
||||
|
||||
function is_timed_out(result) {
|
||||
return is_error(result) && /timed out/.test(result);
|
||||
}
|
||||
|
||||
function is_statement(node) {
|
||||
return node instanceof U.AST_Statement && !(node instanceof U.AST_Function);
|
||||
}
|
||||
|
||||
function merge_sequence(array, node) {
|
||||
if (node instanceof U.AST_Sequence) {
|
||||
array.push.apply(array, node.expressions);
|
||||
} else {
|
||||
array.push(node);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
function to_sequence(expressions) {
|
||||
if (expressions.length == 0) return new U.AST_Number({value: 0, start: {}});
|
||||
if (expressions.length == 1) return expressions[0];
|
||||
return new U.AST_Sequence({
|
||||
expressions: expressions.reduce(merge_sequence, []),
|
||||
start: {},
|
||||
});
|
||||
}
|
||||
|
||||
function to_statement(node) {
|
||||
return is_statement(node) ? node : new U.AST_SimpleStatement({
|
||||
body: node,
|
||||
start: {},
|
||||
});
|
||||
}
|
||||
|
||||
function wrap_with_console_log(node) {
|
||||
// wrap with console.log()
|
||||
return new U.AST_Call({
|
||||
expression: new U.AST_Dot({
|
||||
expression: new U.AST_SymbolRef({
|
||||
name: "console",
|
||||
start: {},
|
||||
}),
|
||||
property: "log",
|
||||
start: {},
|
||||
}),
|
||||
args: [ node ],
|
||||
start: {},
|
||||
});
|
||||
}
|
||||
|
||||
function run_code(code, toplevel, result_cache, timeout) {
|
||||
var key = crypto.createHash("sha1").update(code).digest("base64");
|
||||
var value = result_cache[key];
|
||||
if (!value) {
|
||||
var start = Date.now();
|
||||
result_cache[key] = value = {
|
||||
result: sandbox.run_code(code, toplevel, timeout),
|
||||
elapsed: Date.now() - start,
|
||||
};
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function compare_run_code(code, minify_options, result_cache, max_timeout) {
|
||||
var minified = U.minify(code, minify_options);
|
||||
if (minified.error) return minified;
|
||||
|
||||
var toplevel = sandbox.has_toplevel(minify_options);
|
||||
var unminified = run_code(code, toplevel, result_cache, max_timeout);
|
||||
var timeout = Math.min(100 * unminified.elapsed, max_timeout);
|
||||
var minified_result = run_code(minified.code, toplevel, result_cache, timeout).result;
|
||||
|
||||
if (sandbox.same_stdout(unminified.result, minified_result)) {
|
||||
return is_timed_out(unminified.result) && is_timed_out(minified_result) && {
|
||||
timed_out: true,
|
||||
};
|
||||
}
|
||||
return {
|
||||
unminified_result: unminified.result,
|
||||
minified_result: minified_result,
|
||||
elapsed: unminified.elapsed,
|
||||
};
|
||||
}
|
||||
|
||||
function test_minify(code, minify_options) {
|
||||
var minified = U.minify(code, minify_options);
|
||||
return minified.error && {
|
||||
minified_result: minified.error,
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,3 @@
|
||||
setInterval(function() {
|
||||
process.stderr.write("\0");
|
||||
}, 8 * 60 * 1000).unref();
|
||||
require("./run")([
|
||||
"-b",
|
||||
"-b braces",
|
||||
@@ -12,6 +9,6 @@ require("./run")([
|
||||
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
|
||||
].map(function(options) {
|
||||
var args = options.split(/ /);
|
||||
args.unshift("test/benchmark.js");
|
||||
args.unshift("test/benchmark.js", "--validate");
|
||||
return args;
|
||||
}));
|
||||
|
||||
@@ -40,7 +40,7 @@ function createContext() {
|
||||
arg.constructor.toString();
|
||||
if (level--) for (var key in arg) {
|
||||
var desc = Object.getOwnPropertyDescriptor(arg, key);
|
||||
if (!desc || !desc.get) arg[key] = safe_log(arg[key], level);
|
||||
if (!desc || !desc.get && !desc.set) arg[key] = safe_log(arg[key], level);
|
||||
}
|
||||
}
|
||||
return arg;
|
||||
@@ -54,14 +54,15 @@ function createContext() {
|
||||
}
|
||||
}
|
||||
|
||||
exports.run_code = function(code, toplevel) {
|
||||
exports.run_code = function(code, toplevel, timeout) {
|
||||
timeout = timeout || 5000;
|
||||
var stdout = "";
|
||||
var original_write = process.stdout.write;
|
||||
process.stdout.write = function(chunk) {
|
||||
stdout += chunk;
|
||||
};
|
||||
try {
|
||||
vm.runInContext(toplevel ? "(function(){" + code + "})()" : code, createContext(), { timeout: 5000 });
|
||||
vm.runInContext(toplevel ? "(function(){" + code + "})()" : code, createContext(), { timeout: timeout });
|
||||
return stdout;
|
||||
} catch (ex) {
|
||||
return ex;
|
||||
@@ -76,8 +77,9 @@ function strip_func_ids(text) {
|
||||
|
||||
exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
|
||||
if (typeof expected != typeof actual) return false;
|
||||
if (typeof expected != "string") {
|
||||
if (expected.name != actual.name) return false;
|
||||
if (typeof expected == "object" && typeof expected.name == "string" && typeof expected.message == "string") {
|
||||
if (expected.name !== actual.name) return false;
|
||||
if (typeof actual.message != "string") return false;
|
||||
expected = expected.message.slice(expected.message.lastIndexOf("\n") + 1);
|
||||
actual = actual.message.slice(actual.message.lastIndexOf("\n") + 1);
|
||||
}
|
||||
@@ -85,3 +87,8 @@ exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expec
|
||||
} : function(expected, actual) {
|
||||
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);
|
||||
};
|
||||
exports.has_toplevel = function(options) {
|
||||
return options.toplevel
|
||||
|| options.mangle && options.mangle.toplevel
|
||||
|| options.compress && options.compress.toplevel;
|
||||
};
|
||||
|
||||
55
test/ufuzz/actions.js
Normal file
55
test/ufuzz/actions.js
Normal file
@@ -0,0 +1,55 @@
|
||||
var get = require("https").get;
|
||||
var parse = require("url").parse;
|
||||
|
||||
var base, token, run_number, eldest = true;
|
||||
exports.init = function(url, auth, num) {
|
||||
base = url;
|
||||
token = auth;
|
||||
run_number = num;
|
||||
};
|
||||
exports.should_stop = function(callback) {
|
||||
read(base + "/actions/runs?per_page=100", function(reply) {
|
||||
if (!reply || !Array.isArray(reply.workflow_runs)) return;
|
||||
var runs = reply.workflow_runs.filter(function(workflow) {
|
||||
return workflow.status != "completed";
|
||||
}).sort(function(a, b) {
|
||||
return b.run_number - a.run_number;
|
||||
});
|
||||
var found = false, remaining = 20;
|
||||
(function next() {
|
||||
if (!runs.length) return;
|
||||
var workflow = runs.pop();
|
||||
if (workflow.event == "schedule" && workflow.run_number == run_number) found = true;
|
||||
read(workflow.jobs_url, function(reply) {
|
||||
if (!reply || !Array.isArray(reply.jobs)) return;
|
||||
if (!reply.jobs.every(function(job) {
|
||||
if (job.status == "completed") return true;
|
||||
remaining--;
|
||||
return found || workflow.event != "schedule";
|
||||
})) return;
|
||||
if (remaining >= 0) {
|
||||
next();
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
})();
|
||||
});
|
||||
};
|
||||
|
||||
function read(url, callback) {
|
||||
var options = parse(url);
|
||||
options.headers = {
|
||||
"Authorization": "Token " + token,
|
||||
"User-Agent": "UglifyJS",
|
||||
};
|
||||
get(options, function(response) {
|
||||
var chunks = [];
|
||||
response.setEncoding("utf8");
|
||||
response.on("data", function(chunk) {
|
||||
chunks.push(chunk);
|
||||
}).on("end", function() {
|
||||
callback(JSON.parse(chunks.join("")));
|
||||
});
|
||||
});
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user