Compare commits
320 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2775746a7 | ||
|
|
e478da24c7 | ||
|
|
c5df8355ba | ||
|
|
ff38d2471f | ||
|
|
8e86d05c32 | ||
|
|
9e40abeded | ||
|
|
23ca7d675f | ||
|
|
fd8c0212b8 | ||
|
|
256950c2c0 | ||
|
|
8ecaa40c6e | ||
|
|
96bf7fceab | ||
|
|
6c7226c10e | ||
|
|
dc575919e2 | ||
|
|
4298201938 | ||
|
|
4f833937fe | ||
|
|
3d71e97dd1 | ||
|
|
7f35d9cee0 | ||
|
|
9f8106e1d8 | ||
|
|
b7b8435721 | ||
|
|
c0c04c33bb | ||
|
|
0e234a25c5 | ||
|
|
3096f6fdad | ||
|
|
176c09c6a5 | ||
|
|
9272f662c0 | ||
|
|
4d33cb2f94 | ||
|
|
00d0eda85b | ||
|
|
1cdf810f0b | ||
|
|
b512726cf3 | ||
|
|
9b7a13c8c7 | ||
|
|
74ff6ce261 | ||
|
|
b1b8898e7c | ||
|
|
55451e7b78 | ||
|
|
ffcce28ce1 | ||
|
|
9c0feb69e5 | ||
|
|
bc6e105174 | ||
|
|
b91a2459c0 | ||
|
|
b7a57fc69d | ||
|
|
2dbe40b01b | ||
|
|
813ac3ba96 | ||
|
|
220dc95c0d | ||
|
|
8f0521d51d | ||
|
|
f9946767c9 | ||
|
|
58ac5b9bd5 | ||
|
|
66140b459e | ||
|
|
1786c69070 | ||
|
|
95ef4d5377 | ||
|
|
04017215cc | ||
|
|
142bd1bd1a | ||
|
|
8cb509d50e | ||
|
|
baf4903aa7 | ||
|
|
35465d590e | ||
|
|
ccd91b9952 | ||
|
|
47a5e6e17a | ||
|
|
090ee895e1 | ||
|
|
1cd1a1e5ee | ||
|
|
1d835ac17d | ||
|
|
9e07ac4102 | ||
|
|
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 |
33
.github/workflows/ci.yml
vendored
33
.github/workflows/ci.yml
vendored
@@ -1,31 +1,48 @@
|
|||||||
name: CI
|
name: CI
|
||||||
on: [ push, pull_request ]
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node: [ "0.10", "0.12", 4, 6, 8, 10, latest ]
|
node: [ "0.8", "0.10", "0.12", "4", "6", "8", "10", "12", latest ]
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
script: [ compress, mocha, release/benchmark, release/jetstream ]
|
script: [ compress, mocha, release/benchmark, release/jetstream ]
|
||||||
|
exclude:
|
||||||
|
- node: "0.8"
|
||||||
|
script: release/benchmark
|
||||||
|
- node: "0.8"
|
||||||
|
script: release/jetstream
|
||||||
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
|
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
env:
|
env:
|
||||||
NODE: ${{ matrix.node }}
|
NODE: ${{ matrix.node }}
|
||||||
TYPE: ${{ matrix.script }}
|
TYPE: ${{ matrix.script }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/cache@v1
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: tmp
|
path: tmp
|
||||||
key: tmp ${{ matrix.script }}
|
key: tmp ${{ matrix.script }}
|
||||||
- name: Perform tests
|
- name: Perform tests
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
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/nvs.sh --version
|
||||||
nvs add $NODE
|
|
||||||
nvs use $NODE
|
nvs use $NODE
|
||||||
node --version
|
node --version
|
||||||
npm --version --no-update-notifier
|
npm config set audit false
|
||||||
npm install --no-audit --no-optional --no-save --no-update-notifier
|
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
|
node test/$TYPE
|
||||||
|
|||||||
35
.github/workflows/ufuzz.yml
vendored
35
.github/workflows/ufuzz.yml
vendored
@@ -1,7 +1,13 @@
|
|||||||
name: Fuzzing
|
name: Fuzzing
|
||||||
on:
|
on:
|
||||||
|
pull_request:
|
||||||
schedule:
|
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:
|
jobs:
|
||||||
ufuzz:
|
ufuzz:
|
||||||
strategy:
|
strategy:
|
||||||
@@ -11,15 +17,28 @@ jobs:
|
|||||||
name: ${{ matrix.os }}
|
name: ${{ matrix.os }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Perform fuzzing
|
- name: Perform fuzzing
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
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/nvs.sh --version
|
||||||
nvs add 10
|
nvs use 8
|
||||||
nvs use 10
|
|
||||||
node --version
|
node --version
|
||||||
npm --version --no-update-notifier
|
npm config set audit false
|
||||||
npm install --no-audit --no-optional --no-save --no-update-notifier
|
npm config set optional false
|
||||||
node test/ufuzz/job 3600000
|
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
|
||||||
|
|||||||
55
README.md
55
README.md
@@ -4,8 +4,8 @@ UglifyJS 3
|
|||||||
UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.
|
UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.
|
||||||
|
|
||||||
#### Note:
|
#### 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)**.
|
- **`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/UglifyJS2/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).
|
- `uglify-js` only supports JavaScript (ECMAScript 5).
|
||||||
- To minify ECMAScript 2015 or above, transpile using tools like [Babel](https://babeljs.io/).
|
- To minify ECMAScript 2015 or above, transpile using tools like [Babel](https://babeljs.io/).
|
||||||
|
|
||||||
@@ -126,6 +126,7 @@ a double dash to prevent input files being used as option arguments:
|
|||||||
`includeSources` Pass this flag if you want to include
|
`includeSources` Pass this flag if you want to include
|
||||||
the content of source files in the
|
the content of source files in the
|
||||||
source map as sourcesContent property.
|
source map as sourcesContent property.
|
||||||
|
`names` Include symbol names in the source map.
|
||||||
`root` Path to the original source to be included in
|
`root` Path to the original source to be included in
|
||||||
the source map.
|
the source map.
|
||||||
`url` If specified, path to the source map to append in
|
`url` If specified, path to the source map to append in
|
||||||
@@ -159,6 +160,9 @@ Additional options:
|
|||||||
|
|
||||||
- `--source-map "root='<URL>'"` to pass the URL where the original files can be found.
|
- `--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.
|
- `--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
|
Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
|
||||||
`//# sourceMappingURL=` directive.
|
`//# sourceMappingURL=` directive.
|
||||||
@@ -208,17 +212,16 @@ Example:
|
|||||||
To enable the mangler you need to pass `--mangle` (`-m`). The following
|
To enable the mangler you need to pass `--mangle` (`-m`). The following
|
||||||
(comma-separated) options are supported:
|
(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
|
||||||
When mangling is enabled but you want to prevent certain names from being
|
`--mangle reserved` — pass a comma-separated list of names. For example:
|
||||||
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`)
|
### CLI mangling property names (`--mangle-props`)
|
||||||
|
|
||||||
@@ -593,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'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
|
## Parse options
|
||||||
|
|
||||||
- `bare_returns` (default `false`) -- support top level `return` statements
|
- `bare_returns` (default `false`) -- support top level `return` statements
|
||||||
@@ -650,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
|
- `hoist_props` (default: `true`) -- hoist properties from constant object and
|
||||||
array literals into regular variables subject to a set of constraints. For example:
|
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`
|
`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,
|
works best with `toplevel` and `mangle` enabled, alongside with `compress` option
|
||||||
and the `compress` option `toplevel` enabled.
|
`passes` set to `2` or higher.
|
||||||
|
|
||||||
- `hoist_vars` (default: `false`) -- hoist `var` declarations (this is `false`
|
- `hoist_vars` (default: `false`) -- hoist `var` declarations (this is `false`
|
||||||
by default because it seems to increase the size of the output in general)
|
by default because it seems to increase the size of the output in general)
|
||||||
@@ -682,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
|
- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops
|
||||||
when we can statically determine the condition.
|
when we can statically determine the condition.
|
||||||
|
|
||||||
|
- `merge_vars` (default: `true`) -- combine and reuse variables.
|
||||||
|
|
||||||
- `negate_iife` (default: `true`) -- negate "Immediately-Called Function Expressions"
|
- `negate_iife` (default: `true`) -- negate "Immediately-Called Function Expressions"
|
||||||
where the return value is discarded, to avoid the parens that the
|
where the return value is discarded, to avoid the parens that the
|
||||||
code generator would insert.
|
code generator would insert.
|
||||||
@@ -776,6 +784,9 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple
|
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple
|
||||||
direct variable assignments do not count as references unless set to `"keep_assign"`)
|
direct variable assignments do not count as references unless set to `"keep_assign"`)
|
||||||
|
|
||||||
|
- `varify` (default: `true`) -- convert block-scoped declaractions into `var`
|
||||||
|
whenever safe to do so
|
||||||
|
|
||||||
## Mangle options
|
## Mangle options
|
||||||
|
|
||||||
- `eval` (default `false`) -- Pass `true` to mangle names visible in scopes
|
- `eval` (default `false`) -- Pass `true` to mangle names visible in scopes
|
||||||
@@ -906,7 +917,7 @@ can pass additional arguments that control the code output:
|
|||||||
|
|
||||||
- `wrap_iife` (default `false`) -- pass `true` to wrap immediately invoked
|
- `wrap_iife` (default `false`) -- pass `true` to wrap immediately invoked
|
||||||
function expressions. See
|
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
|
# Miscellaneous
|
||||||
|
|
||||||
@@ -1065,8 +1076,8 @@ var result = UglifyJS.minify(ast, {
|
|||||||
### Working with Uglify AST
|
### Working with Uglify AST
|
||||||
|
|
||||||
Transversal and transformation of the native AST can be performed through
|
Transversal and transformation of the native AST can be performed through
|
||||||
[`TreeWalker`](https://github.com/mishoo/UglifyJS2/blob/master/lib/ast.js) and
|
[`TreeWalker`](https://github.com/mishoo/UglifyJS/blob/master/lib/ast.js) and
|
||||||
[`TreeTransformer`](https://github.com/mishoo/UglifyJS2/blob/master/lib/transform.js)
|
[`TreeTransformer`](https://github.com/mishoo/UglifyJS/blob/master/lib/transform.js)
|
||||||
respectively.
|
respectively.
|
||||||
|
|
||||||
### ESTree / SpiderMonkey AST
|
### ESTree / SpiderMonkey AST
|
||||||
@@ -1150,3 +1161,19 @@ To allow for better optimizations, the compiler makes various assumptions:
|
|||||||
- Object properties can be added, removed and modified (not prevented with
|
- Object properties can be added, removed and modified (not prevented with
|
||||||
`Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
|
`Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
|
||||||
`Object.preventExtensions()` or `Object.seal()`).
|
`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
|
|
||||||
417
bin/uglifyjs
417
bin/uglifyjs
@@ -8,166 +8,252 @@ require("../tools/exit");
|
|||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var info = require("../package.json");
|
var info = require("../package.json");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var program = require("commander");
|
|
||||||
var UglifyJS = require("../tools/node");
|
var UglifyJS = require("../tools/node");
|
||||||
|
|
||||||
var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
|
var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
|
||||||
var files = {};
|
var files = {};
|
||||||
var options = {
|
var options = {};
|
||||||
compress: false,
|
var short_forms = {
|
||||||
mangle: false
|
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);
|
var args = process.argv.slice(2);
|
||||||
program.parseArgv = program.parse;
|
var paths = [];
|
||||||
program.parse = undefined;
|
var output, nameCache;
|
||||||
if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
|
var specified = {};
|
||||||
else if (process.argv.indexOf("options") >= 0) program.helpInformation = function() {
|
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 text = [];
|
||||||
var options = UglifyJS.default_options();
|
var toplevels = [];
|
||||||
for (var option in options) {
|
var padding = "";
|
||||||
text.push("--" + (option == "output" ? "beautify" : option == "sourceMap" ? "source-map" : option) + " options:");
|
var defaults = UglifyJS.default_options();
|
||||||
text.push(format_object(options[option]));
|
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("");
|
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 ]);
|
||||||
}
|
}
|
||||||
return text.join("\n");
|
}
|
||||||
};
|
toplevels.forEach(function(tokens) {
|
||||||
program.option("-p, --parse <options>", "Specify parser options.", parse_js());
|
text.push("--" + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
|
||||||
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js());
|
});
|
||||||
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
|
print(text.join("\n"));
|
||||||
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
|
break;
|
||||||
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js());
|
default:
|
||||||
program.option("-O, --output-opts [options]", "Output options (beautify disabled).", parse_js());
|
print([
|
||||||
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
"Usage: uglifyjs [files...] [options]",
|
||||||
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
"",
|
||||||
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
"Options:",
|
||||||
program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("define"));
|
" -h, --help Print usage information.",
|
||||||
program.option("-e, --enclose [arg[,...][:value[,...]]]", "Embed everything in a big function, with configurable argument(s) & value(s).");
|
" `--help options` for details on available options.",
|
||||||
program.option("--ie8", "Support non-standard Internet Explorer 8.");
|
" -v, -V, --version Print version number.",
|
||||||
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
|
" -p, --parse <options> Specify parser options.",
|
||||||
program.option("--name-cache <file>", "File to hold mangled name mappings.");
|
" -c, --compress [options] Enable compressor/specify compressor options.",
|
||||||
program.option("--rename", "Force symbol expansion.");
|
" -m, --mangle [options] Mangle names/specify mangler options.",
|
||||||
program.option("--no-rename", "Disable symbol expansion.");
|
" --mangle-props [options] Mangle properties/specify mangler options.",
|
||||||
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
|
" -b, --beautify [options] Beautify output/specify output options.",
|
||||||
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_js());
|
" -O, --output-opts <options> Output options (beautify disabled).",
|
||||||
program.option("--timings", "Display operations run time on STDERR.");
|
" -o, --output <file> Output file (default STDOUT).",
|
||||||
program.option("--toplevel", "Compress and/or mangle variables in toplevel scope.");
|
" --comments [filter] Preserve copyright comments in the output.",
|
||||||
program.option("--verbose", "Print diagnostic messages.");
|
" --config-file <file> Read minify() options from JSON file.",
|
||||||
program.option("--warn", "Print warning messages.");
|
" -d, --define <expr>[=value] Global definitions.",
|
||||||
program.option("--wrap <name>", "Embed everything as a function with “exports” corresponding to “name” globally.");
|
" -e, --enclose [arg[,...][:value[,...]]] Embed everything in a big function, with configurable argument(s) & value(s).",
|
||||||
program.option("--reduce-test", "Reduce a standalone `console.log` based test case.");
|
" --ie8 Support non-standard Internet Explorer 8.",
|
||||||
program.arguments("[files...]").parseArgv(process.argv);
|
" --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name.",
|
||||||
if (program.configFile) {
|
" --name-cache <file> File to hold mangled name mappings.",
|
||||||
options = JSON.parse(read_file(program.configFile));
|
" --rename Force symbol expansion.",
|
||||||
if (options.mangle && options.mangle.properties && options.mangle.properties.regex) {
|
" --no-rename Disable symbol expansion.",
|
||||||
options.mangle.properties.regex = UglifyJS.parse(options.mangle.properties.regex, {
|
" --self Build UglifyJS as a library (implies --wrap UglifyJS)",
|
||||||
expression: true
|
" --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;
|
}).value;
|
||||||
}
|
}
|
||||||
}
|
for (var key in config) if (!(key in options)) options[key] = config[key];
|
||||||
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
break;
|
||||||
fatal("cannot write source map to STDOUT");
|
case "compress":
|
||||||
}
|
case "mangle":
|
||||||
[
|
options[name] = parse_js(read_value(), options[name]);
|
||||||
"compress",
|
break;
|
||||||
"enclose",
|
case "source-map":
|
||||||
"ie8",
|
options.sourceMap = parse_js(read_value(), options.sourceMap);
|
||||||
"mangle",
|
break;
|
||||||
"sourceMap",
|
case "enclose":
|
||||||
"toplevel",
|
options[name] = read_value();
|
||||||
"wrap"
|
break;
|
||||||
].forEach(function(name) {
|
case "ie8":
|
||||||
if (name in program) {
|
case "timings":
|
||||||
options[name] = program[name];
|
case "toplevel":
|
||||||
}
|
case "validate":
|
||||||
});
|
options[name] = true;
|
||||||
if (program.verbose) {
|
break;
|
||||||
|
case "keep-fnames":
|
||||||
|
options.keep_fnames = true;
|
||||||
|
break;
|
||||||
|
case "wrap":
|
||||||
|
options[name] = read_value(true);
|
||||||
|
break;
|
||||||
|
case "verbose":
|
||||||
options.warnings = "verbose";
|
options.warnings = "verbose";
|
||||||
} else if (program.warn) {
|
break;
|
||||||
options.warnings = true;
|
case "warn":
|
||||||
|
if (!options.warnings) options.warnings = true;
|
||||||
|
break;
|
||||||
|
case "beautify":
|
||||||
|
options.output = parse_js(read_value(), options.output);
|
||||||
|
if (!("beautify" in options.output)) options.output.beautify = true;
|
||||||
|
break;
|
||||||
|
case "output-opts":
|
||||||
|
options.output = parse_js(read_value(true), options.output);
|
||||||
|
break;
|
||||||
|
case "comments":
|
||||||
|
if (typeof options.output != "object") options.output = {};
|
||||||
|
options.output.comments = read_value();
|
||||||
|
if (options.output.comments === true) options.output.comments = "some";
|
||||||
|
break;
|
||||||
|
case "define":
|
||||||
|
if (typeof options.compress != "object") options.compress = {};
|
||||||
|
options.compress.global_defs = parse_js(read_value(true), options.compress.global_defs, "define");
|
||||||
|
break;
|
||||||
|
case "mangle-props":
|
||||||
|
if (typeof options.mangle != "object") options.mangle = {};
|
||||||
|
options.mangle.properties = parse_js(read_value(), options.mangle.properties);
|
||||||
|
break;
|
||||||
|
case "name-cache":
|
||||||
|
nameCache = read_value(true);
|
||||||
|
options.nameCache = JSON.parse(read_file(nameCache, "{}"));
|
||||||
|
break;
|
||||||
|
case "output":
|
||||||
|
output = read_value(true);
|
||||||
|
break;
|
||||||
|
case "parse":
|
||||||
|
options.parse = parse_js(read_value(true), options.parse);
|
||||||
|
break;
|
||||||
|
case "rename":
|
||||||
|
options.rename = true;
|
||||||
|
break;
|
||||||
|
case "no-rename":
|
||||||
|
options.rename = false;
|
||||||
|
break;
|
||||||
|
case "reduce-test":
|
||||||
|
case "self":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal("invalid option --" + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function read_value(required) {
|
||||||
|
if (no_value || !args.length || args[0][0] == "-") {
|
||||||
|
if (required) fatal("missing option argument for --" + name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return args.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!output && options.sourceMap && options.sourceMap.url != "inline") fatal("cannot write source map to STDOUT");
|
||||||
|
if (specified["beautify"] && specified["output-opts"]) fatal("--beautify cannot be used with --output-opts");
|
||||||
|
[ "compress", "mangle" ].forEach(function(name) {
|
||||||
|
if (!(name in options)) options[name] = false;
|
||||||
|
});
|
||||||
|
if (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) {
|
if (options.warnings) {
|
||||||
UglifyJS.AST_Node.log_function(print_error, options.warnings == "verbose");
|
UglifyJS.AST_Node.log_function(print_error, options.warnings == "verbose");
|
||||||
delete options.warnings;
|
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.outputOpts) {
|
|
||||||
if (program.beautify) fatal("--beautify cannot be used with --output-opts");
|
|
||||||
options.output = typeof program.outputOpts == "object" ? program.outputOpts : {};
|
|
||||||
}
|
|
||||||
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) {
|
var convert_path = function(name) {
|
||||||
return name;
|
return name;
|
||||||
};
|
};
|
||||||
if (typeof program.sourceMap == "object" && "base" in program.sourceMap) {
|
if (typeof options.sourceMap == "object" && "base" in options.sourceMap) {
|
||||||
convert_path = function() {
|
convert_path = function() {
|
||||||
var base = program.sourceMap.base;
|
var base = options.sourceMap.base;
|
||||||
delete options.sourceMap.base;
|
delete options.sourceMap.base;
|
||||||
return function(name) {
|
return function(name) {
|
||||||
return path.relative(base, name);
|
return path.relative(base, name);
|
||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
if (program.self) {
|
if (specified["self"]) {
|
||||||
if (program.args.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
|
if (paths.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
|
||||||
if (!options.wrap) options.wrap = "UglifyJS";
|
if (!options.wrap) options.wrap = "UglifyJS";
|
||||||
simple_glob(UglifyJS.FILES).forEach(function(name) {
|
paths = UglifyJS.FILES;
|
||||||
files[convert_path(name)] = read_file(name);
|
}
|
||||||
});
|
if (paths.length) {
|
||||||
run();
|
simple_glob(paths).forEach(function(name) {
|
||||||
} else if (program.args.length) {
|
|
||||||
simple_glob(program.args).forEach(function(name) {
|
|
||||||
files[convert_path(name)] = read_file(name);
|
files[convert_path(name)] = read_file(name);
|
||||||
});
|
});
|
||||||
run();
|
run();
|
||||||
@@ -188,15 +274,14 @@ function convert_ast(fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
var content = program.sourceMap && program.sourceMap.content;
|
var content = options.sourceMap && options.sourceMap.content;
|
||||||
if (content && content != "inline") {
|
if (content && content != "inline") {
|
||||||
UglifyJS.AST_Node.info("Using input source map: " + content);
|
UglifyJS.AST_Node.info("Using input source map: " + content);
|
||||||
options.sourceMap.content = read_file(content, content);
|
options.sourceMap.content = read_file(content, content);
|
||||||
}
|
}
|
||||||
if (program.timings) options.timings = true;
|
|
||||||
try {
|
try {
|
||||||
if (program.parse) {
|
if (options.parse) {
|
||||||
if (program.parse.acorn) {
|
if (options.parse.acorn) {
|
||||||
files = convert_ast(function(toplevel, name) {
|
files = convert_ast(function(toplevel, name) {
|
||||||
return require("acorn").parse(files[name], {
|
return require("acorn").parse(files[name], {
|
||||||
locations: true,
|
locations: true,
|
||||||
@@ -204,7 +289,7 @@ function run() {
|
|||||||
sourceFile: name
|
sourceFile: name
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else if (program.parse.spidermonkey) {
|
} else if (options.parse.spidermonkey) {
|
||||||
files = convert_ast(function(toplevel, name) {
|
files = convert_ast(function(toplevel, name) {
|
||||||
var obj = JSON.parse(files[name]);
|
var obj = JSON.parse(files[name]);
|
||||||
if (!toplevel) return obj;
|
if (!toplevel) return obj;
|
||||||
@@ -216,14 +301,17 @@ function run() {
|
|||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
fatal(ex);
|
fatal(ex);
|
||||||
}
|
}
|
||||||
if (program.reduceTest) {
|
var result;
|
||||||
// load on demand - assumes dev tree checked out
|
if (specified["reduce-test"]) {
|
||||||
|
// load on demand - assumes cloned repository
|
||||||
var reduce_test = require("../test/reduce");
|
var reduce_test = require("../test/reduce");
|
||||||
var testcase = files[0] || files[Object.keys(files)[0]];
|
if (Object.keys(files).length != 1) fatal("can only test on a single file");
|
||||||
var result = reduce_test(testcase, options, {verbose: true});
|
result = reduce_test(files[Object.keys(files)[0]], options, {
|
||||||
}
|
log: print_error,
|
||||||
else {
|
verbose: true,
|
||||||
var result = UglifyJS.minify(files, options);
|
});
|
||||||
|
} else {
|
||||||
|
result = UglifyJS.minify(files, options);
|
||||||
}
|
}
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
var ex = result.error;
|
var ex = result.error;
|
||||||
@@ -253,9 +341,18 @@ function run() {
|
|||||||
print_error(format_object(ex.defs));
|
print_error(format_object(ex.defs));
|
||||||
}
|
}
|
||||||
fatal(ex);
|
fatal(ex);
|
||||||
} else if (program.output == "ast") {
|
} else if (output == "ast") {
|
||||||
if (!options.compress && !options.mangle) {
|
if (!options.compress && !options.mangle) {
|
||||||
result.ast.figure_out_scope({});
|
var toplevel = result.ast;
|
||||||
|
if (!(toplevel instanceof UglifyJS.AST_Toplevel)) {
|
||||||
|
if (!(toplevel instanceof UglifyJS.AST_Statement)) toplevel = new UglifyJS.AST_SimpleStatement({
|
||||||
|
body: toplevel,
|
||||||
|
});
|
||||||
|
toplevel = new UglifyJS.AST_Toplevel({
|
||||||
|
body: [ toplevel ],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
toplevel.figure_out_scope({});
|
||||||
}
|
}
|
||||||
print(JSON.stringify(result.ast, function(key, value) {
|
print(JSON.stringify(result.ast, function(key, value) {
|
||||||
if (value) switch (key) {
|
if (value) switch (key) {
|
||||||
@@ -282,26 +379,22 @@ function run() {
|
|||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}, 2));
|
}, 2));
|
||||||
} else if (program.output == "spidermonkey") {
|
} else if (output == "spidermonkey") {
|
||||||
print(JSON.stringify(UglifyJS.minify(result.code, {
|
print(JSON.stringify(UglifyJS.minify(result.code, {
|
||||||
compress: false,
|
compress: false,
|
||||||
mangle: false,
|
mangle: false,
|
||||||
output: {
|
output: {
|
||||||
ast: true,
|
ast: true,
|
||||||
code: false
|
code: false
|
||||||
}
|
},
|
||||||
}).ast.to_mozilla_ast(), null, 2));
|
}).ast.to_mozilla_ast(), null, 2));
|
||||||
} else if (program.output) {
|
} else if (output) {
|
||||||
fs.writeFileSync(program.output, result.code);
|
fs.writeFileSync(output, result.code);
|
||||||
if (result.map) {
|
if (result.map) fs.writeFileSync(output + ".map", result.map);
|
||||||
fs.writeFileSync(program.output + ".map", result.map);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
print(result.code);
|
print(result.code);
|
||||||
}
|
}
|
||||||
if (program.nameCache) {
|
if (nameCache) fs.writeFileSync(nameCache, JSON.stringify(options.nameCache));
|
||||||
fs.writeFileSync(program.nameCache, JSON.stringify(options.nameCache));
|
|
||||||
}
|
|
||||||
if (result.timings) for (var phase in result.timings) {
|
if (result.timings) for (var phase in result.timings) {
|
||||||
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
|
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
|
||||||
}
|
}
|
||||||
@@ -337,7 +430,7 @@ function simple_glob(glob) {
|
|||||||
.replace(/\?/g, "[^/\\\\]") + "$";
|
.replace(/\?/g, "[^/\\\\]") + "$";
|
||||||
var mod = process.platform === "win32" ? "i" : "";
|
var mod = process.platform === "win32" ? "i" : "";
|
||||||
var rx = new RegExp(pattern, mod);
|
var rx = new RegExp(pattern, mod);
|
||||||
var results = entries.filter(function(name) {
|
var results = entries.sort().filter(function(name) {
|
||||||
return rx.test(name);
|
return rx.test(name);
|
||||||
}).map(function(name) {
|
}).map(function(name) {
|
||||||
return path.join(dir, name);
|
return path.join(dir, name);
|
||||||
@@ -357,10 +450,9 @@ function read_file(path, default_value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parse_js(flag) {
|
function parse_js(value, options, flag) {
|
||||||
return function(value, options) {
|
if (!options || typeof options != "object") options = {};
|
||||||
options = options || {};
|
if (typeof value == "string") try {
|
||||||
try {
|
|
||||||
UglifyJS.parse(value, {
|
UglifyJS.parse(value, {
|
||||||
expression: true
|
expression: true
|
||||||
}).walk(new UglifyJS.TreeWalker(function(node) {
|
}).walk(new UglifyJS.TreeWalker(function(node) {
|
||||||
@@ -397,7 +489,6 @@ function parse_js(flag) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function skip_key(key) {
|
function skip_key(key) {
|
||||||
|
|||||||
684
lib/ast.js
684
lib/ast.js
File diff suppressed because it is too large
Load Diff
3219
lib/compress.js
3219
lib/compress.js
File diff suppressed because it is too large
Load Diff
@@ -85,9 +85,11 @@ function minify(files, options) {
|
|||||||
sourceMap: false,
|
sourceMap: false,
|
||||||
timings: false,
|
timings: false,
|
||||||
toplevel: false,
|
toplevel: false,
|
||||||
|
validate: false,
|
||||||
warnings: false,
|
warnings: false,
|
||||||
wrap: false,
|
wrap: false,
|
||||||
}, true);
|
}, true);
|
||||||
|
if (options.validate) AST_Node.enable_validation();
|
||||||
var timings = options.timings && {
|
var timings = options.timings && {
|
||||||
start: Date.now()
|
start: Date.now()
|
||||||
};
|
};
|
||||||
@@ -129,6 +131,7 @@ function minify(files, options) {
|
|||||||
content: null,
|
content: null,
|
||||||
filename: null,
|
filename: null,
|
||||||
includeSources: false,
|
includeSources: false,
|
||||||
|
names: true,
|
||||||
root: null,
|
root: null,
|
||||||
url: null,
|
url: null,
|
||||||
}, true);
|
}, true);
|
||||||
@@ -138,7 +141,7 @@ function minify(files, options) {
|
|||||||
warnings.push(warning);
|
warnings.push(warning);
|
||||||
}, options.warnings == "verbose");
|
}, options.warnings == "verbose");
|
||||||
if (timings) timings.parse = Date.now();
|
if (timings) timings.parse = Date.now();
|
||||||
var source_maps, toplevel;
|
var toplevel;
|
||||||
if (files instanceof AST_Toplevel) {
|
if (files instanceof AST_Toplevel) {
|
||||||
toplevel = files;
|
toplevel = files;
|
||||||
} else {
|
} else {
|
||||||
@@ -151,19 +154,17 @@ function minify(files, options) {
|
|||||||
if (typeof source_map_content == "string" && source_map_content != "inline") {
|
if (typeof source_map_content == "string" && source_map_content != "inline") {
|
||||||
source_map_content = parse_source_map(source_map_content);
|
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)) {
|
for (var name in files) if (HOP(files, name)) {
|
||||||
options.parse.filename = name;
|
options.parse.filename = name;
|
||||||
options.parse.toplevel = toplevel = parse(files[name], options.parse);
|
options.parse.toplevel = toplevel = parse(files[name], options.parse);
|
||||||
if (source_maps) {
|
|
||||||
if (source_map_content == "inline") {
|
if (source_map_content == "inline") {
|
||||||
var inlined_content = read_source_map(name, toplevel);
|
var inlined_content = read_source_map(name, toplevel);
|
||||||
if (inlined_content) {
|
if (inlined_content) {
|
||||||
source_maps[name] = parse_source_map(inlined_content);
|
options.sourceMap.orig[name] = parse_source_map(inlined_content);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
source_maps[name] = source_map_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);
|
toplevel = toplevel[action](option);
|
||||||
files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
|
files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
|
||||||
});
|
});
|
||||||
|
if (options.validate) toplevel.validate_ast();
|
||||||
if (timings) timings.rename = Date.now();
|
if (timings) timings.rename = Date.now();
|
||||||
if (options.rename) {
|
if (options.rename) {
|
||||||
toplevel.figure_out_scope(options.mangle);
|
toplevel.figure_out_scope(options.mangle);
|
||||||
toplevel.expand_names(options.mangle);
|
toplevel.expand_names(options.mangle);
|
||||||
}
|
}
|
||||||
if (timings) timings.compress = Date.now();
|
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 (timings) timings.scope = Date.now();
|
||||||
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
||||||
if (timings) timings.mangle = Date.now();
|
if (timings) timings.mangle = Date.now();
|
||||||
@@ -192,9 +197,7 @@ function minify(files, options) {
|
|||||||
toplevel.mangle_names(options.mangle);
|
toplevel.mangle_names(options.mangle);
|
||||||
}
|
}
|
||||||
if (timings) timings.properties = Date.now();
|
if (timings) timings.properties = Date.now();
|
||||||
if (options.mangle && options.mangle.properties) {
|
if (options.mangle && options.mangle.properties) mangle_properties(toplevel, options.mangle.properties);
|
||||||
toplevel = mangle_properties(toplevel, options.mangle.properties);
|
|
||||||
}
|
|
||||||
if (timings) timings.output = Date.now();
|
if (timings) timings.output = Date.now();
|
||||||
var result = {};
|
var result = {};
|
||||||
if (options.output.ast) {
|
if (options.output.ast) {
|
||||||
@@ -202,19 +205,13 @@ function minify(files, options) {
|
|||||||
}
|
}
|
||||||
if (!HOP(options.output, "code") || options.output.code) {
|
if (!HOP(options.output, "code") || options.output.code) {
|
||||||
if (options.sourceMap) {
|
if (options.sourceMap) {
|
||||||
options.output.source_map = SourceMap({
|
options.output.source_map = SourceMap(options.sourceMap);
|
||||||
file: options.sourceMap.filename,
|
|
||||||
orig: source_maps,
|
|
||||||
root: options.sourceMap.root
|
|
||||||
});
|
|
||||||
if (options.sourceMap.includeSources) {
|
if (options.sourceMap.includeSources) {
|
||||||
if (files instanceof AST_Toplevel) {
|
if (files instanceof AST_Toplevel) {
|
||||||
throw new Error("original source content unavailable");
|
throw new Error("original source content unavailable");
|
||||||
} else for (var name in files) if (HOP(files, name)) {
|
} 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;
|
delete options.output.ast;
|
||||||
@@ -260,5 +257,7 @@ function minify(files, options) {
|
|||||||
return result;
|
return result;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
return { error: ex };
|
return { error: ex };
|
||||||
|
} finally {
|
||||||
|
AST_Node.disable_validation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
||||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||||
https://github.com/mishoo/UglifyJS2
|
https://github.com/mishoo/UglifyJS
|
||||||
|
|
||||||
-------------------------------- (C) ---------------------------------
|
-------------------------------- (C) ---------------------------------
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@
|
|||||||
var args = {
|
var args = {
|
||||||
start : my_start_token(key),
|
start : my_start_token(key),
|
||||||
end : my_end_token(M.value),
|
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)
|
value : from_moz(M.value)
|
||||||
};
|
};
|
||||||
if (M.kind == "init") return new AST_ObjectKeyVal(args);
|
if (M.kind == "init") return new AST_ObjectKeyVal(args);
|
||||||
@@ -212,7 +212,14 @@
|
|||||||
end : my_end_token(M),
|
end : my_end_token(M),
|
||||||
name : M.name
|
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 =
|
MOZ_TO_ME.UpdateExpression =
|
||||||
@@ -245,7 +252,6 @@
|
|||||||
map("VariableDeclarator", AST_VarDef, "id>name, init>value");
|
map("VariableDeclarator", AST_VarDef, "id>name, init>value");
|
||||||
map("CatchClause", AST_Catch, "param>argname, body%body");
|
map("CatchClause", AST_Catch, "param>argname, body%body");
|
||||||
|
|
||||||
map("ThisExpression", AST_This);
|
|
||||||
map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
|
map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
|
||||||
map("LogicalExpression", 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");
|
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) {
|
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
|
||||||
var flags = M.value.toString().match(/[gimuy]*$/)[0];
|
var flags = M.value.toString().match(/[gimuy]*$/)[0];
|
||||||
var value = "/" + M.value.raw_source + "/" + flags;
|
var value = "/" + M.value.raw_source + "/" + flags;
|
||||||
|
|||||||
417
lib/output.js
417
lib/output.js
@@ -1,7 +1,7 @@
|
|||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
||||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||||
https://github.com/mishoo/UglifyJS2
|
https://github.com/mishoo/UglifyJS
|
||||||
|
|
||||||
-------------------------------- (C) ---------------------------------
|
-------------------------------- (C) ---------------------------------
|
||||||
|
|
||||||
@@ -100,13 +100,16 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var indentation = 0;
|
var indentation = options.indent_start;
|
||||||
var current_col = 0;
|
var current_col = 0;
|
||||||
var current_line = 1;
|
var current_line = 1;
|
||||||
var current_pos = 0;
|
var current_pos = 0;
|
||||||
var OUTPUT = "";
|
var OUTPUT = "";
|
||||||
|
|
||||||
var to_utf8 = options.ascii_only ? function(str, identifier) {
|
var to_utf8 = options.ascii_only ? function(str, identifier) {
|
||||||
|
if (identifier) str = str.replace(/[\ud800-\udbff][\udc00-\udfff]/g, function(ch) {
|
||||||
|
return "\\u{" + (ch.charCodeAt(0) - 0xd7c0 << 10 | ch.charCodeAt(1) - 0xdc00).toString(16) + "}";
|
||||||
|
});
|
||||||
return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
|
return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
|
||||||
var code = ch.charCodeAt(0).toString(16);
|
var code = ch.charCodeAt(0).toString(16);
|
||||||
if (code.length <= 2 && !identifier) {
|
if (code.length <= 2 && !identifier) {
|
||||||
@@ -191,10 +194,6 @@ function OutputStream(options) {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
function make_indent(back) {
|
|
||||||
return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -----[ beautification/minification ]----- */
|
/* -----[ beautification/minification ]----- */
|
||||||
|
|
||||||
var has_parens = false;
|
var has_parens = false;
|
||||||
@@ -305,6 +304,7 @@ function OutputStream(options) {
|
|||||||
|| (ch == "/" && ch == prev)
|
|| (ch == "/" && ch == prev)
|
||||||
|| ((ch == "+" || ch == "-") && ch == last)
|
|| ((ch == "+" || ch == "-") && ch == last)
|
||||||
|| str == "--" && last == "!"
|
|| str == "--" && last == "!"
|
||||||
|
|| str == "in" && prev == "/"
|
||||||
|| last == "--" && ch == ">") {
|
|| last == "--" && ch == ">") {
|
||||||
OUTPUT += " ";
|
OUTPUT += " ";
|
||||||
current_col++;
|
current_col++;
|
||||||
@@ -344,9 +344,7 @@ function OutputStream(options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var indent = options.beautify ? function(half) {
|
var indent = options.beautify ? function(half) {
|
||||||
if (options.beautify) {
|
print(repeat_string(" ", half ? indentation - (options.indent_level >> 1) : indentation));
|
||||||
print(make_indent(half ? 0.5 : 0));
|
|
||||||
}
|
|
||||||
} : noop;
|
} : noop;
|
||||||
|
|
||||||
var with_indent = options.beautify ? function(col, cont) {
|
var with_indent = options.beautify ? function(col, cont) {
|
||||||
@@ -574,9 +572,9 @@ function OutputStream(options) {
|
|||||||
get : get,
|
get : get,
|
||||||
toString : get,
|
toString : get,
|
||||||
indent : indent,
|
indent : indent,
|
||||||
indentation : function() { return indentation },
|
should_break : readonly ? noop : function() {
|
||||||
current_width : function() { return current_col - indentation },
|
return options.width && current_col - indentation >= options.width;
|
||||||
should_break : function() { return options.width && this.current_width() >= options.width },
|
},
|
||||||
has_parens : function() { return has_parens },
|
has_parens : function() { return has_parens },
|
||||||
newline : newline,
|
newline : newline,
|
||||||
print : print,
|
print : print,
|
||||||
@@ -629,13 +627,7 @@ function OutputStream(options) {
|
|||||||
var use_asm = false;
|
var use_asm = false;
|
||||||
|
|
||||||
AST_Node.DEFMETHOD("print", function(stream, force_parens) {
|
AST_Node.DEFMETHOD("print", function(stream, force_parens) {
|
||||||
var self = this, generator = self._codegen;
|
var self = this;
|
||||||
function doit() {
|
|
||||||
stream.prepend_comments(self);
|
|
||||||
self.add_source_map(stream);
|
|
||||||
generator(self, stream);
|
|
||||||
stream.append_comments(self);
|
|
||||||
}
|
|
||||||
stream.push_node(self);
|
stream.push_node(self);
|
||||||
if (force_parens || self.needs_parens(stream)) {
|
if (force_parens || self.needs_parens(stream)) {
|
||||||
stream.with_parens(doit);
|
stream.with_parens(doit);
|
||||||
@@ -643,9 +635,14 @@ function OutputStream(options) {
|
|||||||
doit();
|
doit();
|
||||||
}
|
}
|
||||||
stream.pop_node();
|
stream.pop_node();
|
||||||
});
|
|
||||||
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
|
|
||||||
|
|
||||||
|
function doit() {
|
||||||
|
stream.prepend_comments(self);
|
||||||
|
self.add_source_map(stream);
|
||||||
|
self._codegen(stream);
|
||||||
|
stream.append_comments(self);
|
||||||
|
}
|
||||||
|
});
|
||||||
AST_Node.DEFMETHOD("print_to_string", function(options) {
|
AST_Node.DEFMETHOD("print_to_string", function(options) {
|
||||||
var s = OutputStream(options);
|
var s = OutputStream(options);
|
||||||
this.print(s);
|
this.print(s);
|
||||||
@@ -688,78 +685,66 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
PARENS(AST_Unary, function(output) {
|
PARENS(AST_Unary, function(output) {
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
return p instanceof AST_PropAccess && p.expression === this
|
return (p instanceof AST_Call || p instanceof AST_PropAccess) && p.expression === this;
|
||||||
|| p instanceof AST_Call && p.expression === this;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS(AST_Sequence, function(output) {
|
PARENS(AST_Sequence, function(output) {
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
// (foo, bar)() or foo(1, (2, 3), 4)
|
// [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
|
||||||
return p instanceof AST_Call
|
return p instanceof AST_Array
|
||||||
// !(foo, bar, baz)
|
|
||||||
|| p instanceof AST_Unary
|
|
||||||
// 1 + (2, 3) + 4 ==> 8
|
// 1 + (2, 3) + 4 ==> 8
|
||||||
|| p instanceof AST_Binary
|
|| p instanceof AST_Binary
|
||||||
// var a = (1, 2), b = a + a; ==> b == 4
|
// new (foo, bar) or foo(1, (2, 3), 4)
|
||||||
|| p instanceof AST_VarDef
|
|| p instanceof AST_Call
|
||||||
// (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
|
|
||||||
// (false, true) ? (a = 10, b = 20) : (c = 30)
|
// (false, true) ? (a = 10, b = 20) : (c = 30)
|
||||||
// ==> 20 (side effect, set a := 10 and b := 20)
|
// ==> 20 (side effect, set a := 10 and b := 20)
|
||||||
|| p instanceof AST_Conditional;
|
|| 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) {
|
PARENS(AST_Binary, function(output) {
|
||||||
var p = output.parent();
|
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)
|
// this deals with precedence: 3 * (2 + 1)
|
||||||
if (p instanceof AST_Binary) {
|
if (p instanceof AST_Binary) {
|
||||||
var po = p.operator, pp = PRECEDENCE[po];
|
var po = p.operator, pp = PRECEDENCE[po];
|
||||||
var so = this.operator, sp = PRECEDENCE[so];
|
var so = this.operator, sp = PRECEDENCE[so];
|
||||||
if (pp > sp
|
return pp > sp || (pp == sp && this === p.right);
|
||||||
|| (pp == sp
|
|
||||||
&& this === p.right)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// (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) {
|
PARENS(AST_PropAccess, function(output) {
|
||||||
|
var node = this;
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
if (p instanceof AST_New && p.expression === this) {
|
if (p instanceof AST_New && p.expression === node) {
|
||||||
// i.e. new (foo.bar().baz)
|
// i.e. new (foo().bar)
|
||||||
//
|
//
|
||||||
// if there's one call into this subtree, then we need
|
// if there's one call into this subtree, then we need
|
||||||
// parens around it too, otherwise the call will be
|
// parens around it too, otherwise the call will be
|
||||||
// interpreted as passing the arguments to the upper New
|
// interpreted as passing the arguments to the upper New
|
||||||
// expression.
|
// expression.
|
||||||
var parens = false;
|
do {
|
||||||
this.walk(new TreeWalker(function(node) {
|
node = node.expression;
|
||||||
if (parens || node instanceof AST_Scope) return true;
|
} while (node instanceof AST_PropAccess);
|
||||||
if (node instanceof AST_Call) {
|
return node.TYPE == "Call";
|
||||||
parens = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
return parens;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS(AST_Call, function(output) {
|
PARENS(AST_Call, function(output) {
|
||||||
var p = output.parent();
|
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
|
// https://bugs.webkit.org/show_bug.cgi?id=123506
|
||||||
if (output.option('webkit')) {
|
if (output.option('webkit')) {
|
||||||
var g = output.parent(1);
|
var g = output.parent(1);
|
||||||
@@ -772,49 +757,43 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
PARENS(AST_New, function(output) {
|
PARENS(AST_New, function(output) {
|
||||||
|
if (need_constructor_parens(this, output)) return false;
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
if (!need_constructor_parens(this, output)
|
// (new foo)(bar)
|
||||||
&& (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]()
|
if (p instanceof AST_Call) return p.expression === this;
|
||||||
|| p instanceof AST_Call && p.expression === this)) // (new foo)(bar)
|
// (new Date).getTime(), (new Date)["getTime"]()
|
||||||
return true;
|
return p instanceof AST_PropAccess;
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS(AST_Number, function(output) {
|
PARENS(AST_Number, function(output) {
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
if (p instanceof AST_PropAccess && p.expression === this) {
|
if (p instanceof AST_PropAccess && p.expression === this) {
|
||||||
var value = this.value;
|
var value = this.value;
|
||||||
// https://github.com/mishoo/UglifyJS2/issues/115
|
// https://github.com/mishoo/UglifyJS/issues/115
|
||||||
// https://github.com/mishoo/UglifyJS2/pull/1009
|
// https://github.com/mishoo/UglifyJS/pull/1009
|
||||||
if (value < 0 || /^0/.test(make_num(value))) {
|
return value < 0 || /^0/.test(make_num(value));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS([ AST_Assign, AST_Conditional ], function(output) {
|
PARENS([ AST_Assign, AST_Conditional ], function(output) {
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
// !(a = false) → true
|
|
||||||
if (p instanceof AST_Unary)
|
|
||||||
return true;
|
|
||||||
// 1 + (a = 2) + 3 → 6, side effect setting a = 2
|
// 1 + (a = 2) + 3 → 6, side effect setting a = 2
|
||||||
if (p instanceof AST_Binary && !(p instanceof AST_Assign))
|
if (p instanceof AST_Binary) return !(p instanceof AST_Assign);
|
||||||
return true;
|
|
||||||
// (a = func)() —or— new (a = Object)()
|
// (a = func)() —or— new (a = Object)()
|
||||||
if (p instanceof AST_Call && p.expression === this)
|
if (p instanceof AST_Call) return p.expression === this;
|
||||||
return true;
|
|
||||||
// (a = foo) ? bar : baz
|
// (a = foo) ? bar : baz
|
||||||
if (p instanceof AST_Conditional && p.condition === this)
|
if (p instanceof AST_Conditional) return p.condition === this;
|
||||||
return true;
|
|
||||||
// (a = foo)["prop"] —or— (a = foo).prop
|
// (a = foo)["prop"] —or— (a = foo).prop
|
||||||
if (p instanceof AST_PropAccess && p.expression === this)
|
if (p instanceof AST_PropAccess) return p.expression === this;
|
||||||
return true;
|
// !(a = false) → true
|
||||||
|
if (p instanceof AST_Unary) return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ PRINTERS ]----- */
|
/* -----[ PRINTERS ]----- */
|
||||||
|
|
||||||
DEFPRINT(AST_Directive, function(self, output) {
|
DEFPRINT(AST_Directive, function(output) {
|
||||||
var quote = self.quote;
|
var quote = this.quote;
|
||||||
var value = self.value;
|
var value = this.value;
|
||||||
switch (output.option("quote_style")) {
|
switch (output.option("quote_style")) {
|
||||||
case 0:
|
case 0:
|
||||||
case 2:
|
case 2:
|
||||||
@@ -827,7 +806,7 @@ function OutputStream(options) {
|
|||||||
output.print(quote + value + quote);
|
output.print(quote + value + quote);
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Debugger, function(self, output) {
|
DEFPRINT(AST_Debugger, function(output) {
|
||||||
output.print("debugger");
|
output.print("debugger");
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
@@ -859,25 +838,21 @@ function OutputStream(options) {
|
|||||||
use_asm = was_asm;
|
use_asm = was_asm;
|
||||||
}
|
}
|
||||||
|
|
||||||
AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
|
DEFPRINT(AST_Statement, function(output) {
|
||||||
force_statement(this.body, output);
|
this.body.print(output);
|
||||||
});
|
|
||||||
|
|
||||||
DEFPRINT(AST_Statement, function(self, output) {
|
|
||||||
self.body.print(output);
|
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Toplevel, function(self, output) {
|
DEFPRINT(AST_Toplevel, function(output) {
|
||||||
display_body(self.body, true, output, true);
|
display_body(this.body, true, output, true);
|
||||||
output.print("");
|
output.print("");
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_LabeledStatement, function(self, output) {
|
DEFPRINT(AST_LabeledStatement, function(output) {
|
||||||
self.label.print(output);
|
this.label.print(output);
|
||||||
output.colon();
|
output.colon();
|
||||||
self.body.print(output);
|
this.body.print(output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_SimpleStatement, function(self, output) {
|
DEFPRINT(AST_SimpleStatement, function(output) {
|
||||||
self.body.print(output);
|
this.body.print(output);
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
function print_braced_empty(self, output) {
|
function print_braced_empty(self, output) {
|
||||||
@@ -894,13 +869,14 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
} else print_braced_empty(self, output);
|
} else print_braced_empty(self, output);
|
||||||
}
|
}
|
||||||
DEFPRINT(AST_BlockStatement, function(self, output) {
|
DEFPRINT(AST_BlockStatement, function(output) {
|
||||||
print_braced(self, output);
|
print_braced(this, output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_EmptyStatement, function(self, output) {
|
DEFPRINT(AST_EmptyStatement, function(output) {
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Do, function(self, output) {
|
DEFPRINT(AST_Do, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("do");
|
output.print("do");
|
||||||
output.space();
|
output.space();
|
||||||
make_block(self.body, output);
|
make_block(self.body, output);
|
||||||
@@ -912,16 +888,18 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_While, function(self, output) {
|
DEFPRINT(AST_While, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("while");
|
output.print("while");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
self.condition.print(output);
|
self.condition.print(output);
|
||||||
});
|
});
|
||||||
output.space();
|
output.space();
|
||||||
self._do_print_body(output);
|
force_statement(self.body, output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_For, function(self, output) {
|
DEFPRINT(AST_For, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("for");
|
output.print("for");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
@@ -948,9 +926,10 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
output.space();
|
output.space();
|
||||||
self._do_print_body(output);
|
force_statement(self.body, output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_ForIn, function(self, output) {
|
DEFPRINT(AST_ForIn, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("for");
|
output.print("for");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
@@ -961,20 +940,21 @@ function OutputStream(options) {
|
|||||||
self.object.print(output);
|
self.object.print(output);
|
||||||
});
|
});
|
||||||
output.space();
|
output.space();
|
||||||
self._do_print_body(output);
|
force_statement(self.body, output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_With, function(self, output) {
|
DEFPRINT(AST_With, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("with");
|
output.print("with");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
self.expression.print(output);
|
self.expression.print(output);
|
||||||
});
|
});
|
||||||
output.space();
|
output.space();
|
||||||
self._do_print_body(output);
|
force_statement(self.body, output);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ functions ]----- */
|
/* -----[ functions ]----- */
|
||||||
AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword) {
|
DEFPRINT(AST_Lambda, function(output, nokeyword) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (!nokeyword) {
|
if (!nokeyword) {
|
||||||
output.print("function");
|
output.print("function");
|
||||||
@@ -992,37 +972,28 @@ function OutputStream(options) {
|
|||||||
output.space();
|
output.space();
|
||||||
print_braced(self, output, true);
|
print_braced(self, output, true);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Lambda, function(self, output) {
|
|
||||||
self._do_print(output);
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -----[ jumps ]----- */
|
/* -----[ jumps ]----- */
|
||||||
function print_jump(output, kind, target) {
|
function print_jump(kind, prop) {
|
||||||
|
return function(output) {
|
||||||
output.print(kind);
|
output.print(kind);
|
||||||
|
var target = this[prop];
|
||||||
if (target) {
|
if (target) {
|
||||||
output.space();
|
output.space();
|
||||||
target.print(output);
|
target.print(output);
|
||||||
}
|
}
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
DEFPRINT(AST_Return, print_jump("return", "value"));
|
||||||
DEFPRINT(AST_Return, function(self, output) {
|
DEFPRINT(AST_Throw, print_jump("throw", "value"));
|
||||||
print_jump(output, "return", self.value);
|
DEFPRINT(AST_Break, print_jump("break", "label"));
|
||||||
});
|
DEFPRINT(AST_Continue, print_jump("continue", "label"));
|
||||||
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -----[ if ]----- */
|
/* -----[ if ]----- */
|
||||||
function make_then(self, output) {
|
function make_then(self, output) {
|
||||||
var b = self.body;
|
var b = self.body;
|
||||||
if (output.option("braces")
|
if (output.option("braces") && !(b instanceof AST_Const || b instanceof AST_Let)
|
||||||
|| output.option("ie8") && b instanceof AST_Do)
|
|| output.option("ie8") && b instanceof AST_Do)
|
||||||
return make_block(b, output);
|
return make_block(b, output);
|
||||||
// The squeezer replaces "block"-s that contain only a single
|
// The squeezer replaces "block"-s that contain only a single
|
||||||
@@ -1046,7 +1017,8 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
force_statement(self.body, output);
|
force_statement(self.body, output);
|
||||||
}
|
}
|
||||||
DEFPRINT(AST_If, function(self, output) {
|
DEFPRINT(AST_If, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("if");
|
output.print("if");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
@@ -1063,12 +1035,13 @@ function OutputStream(options) {
|
|||||||
else
|
else
|
||||||
force_statement(self.alternative, output);
|
force_statement(self.alternative, output);
|
||||||
} else {
|
} else {
|
||||||
self._do_print_body(output);
|
force_statement(self.body, output);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ switch ]----- */
|
/* -----[ switch ]----- */
|
||||||
DEFPRINT(AST_Switch, function(self, output) {
|
DEFPRINT(AST_Switch, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("switch");
|
output.print("switch");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
@@ -1086,28 +1059,30 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output) {
|
function print_branch_body(self, output) {
|
||||||
output.newline();
|
output.newline();
|
||||||
this.body.forEach(function(stmt) {
|
self.body.forEach(function(stmt) {
|
||||||
output.indent();
|
output.indent();
|
||||||
stmt.print(output);
|
stmt.print(output);
|
||||||
output.newline();
|
output.newline();
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
DEFPRINT(AST_Default, function(self, output) {
|
DEFPRINT(AST_Default, function(output) {
|
||||||
output.print("default:");
|
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.print("case");
|
||||||
output.space();
|
output.space();
|
||||||
self.expression.print(output);
|
self.expression.print(output);
|
||||||
output.print(":");
|
output.print(":");
|
||||||
self._do_print_body(output);
|
print_branch_body(self, output);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ exceptions ]----- */
|
/* -----[ exceptions ]----- */
|
||||||
DEFPRINT(AST_Try, function(self, output) {
|
DEFPRINT(AST_Try, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("try");
|
output.print("try");
|
||||||
output.space();
|
output.space();
|
||||||
print_braced(self, output);
|
print_braced(self, output);
|
||||||
@@ -1120,23 +1095,28 @@ function OutputStream(options) {
|
|||||||
self.bfinally.print(output);
|
self.bfinally.print(output);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Catch, function(self, output) {
|
DEFPRINT(AST_Catch, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("catch");
|
output.print("catch");
|
||||||
|
if (self.argname) {
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
self.argname.print(output);
|
self.argname.print(output);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
output.space();
|
output.space();
|
||||||
print_braced(self, output);
|
print_braced(self, output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Finally, function(self, output) {
|
DEFPRINT(AST_Finally, function(output) {
|
||||||
output.print("finally");
|
output.print("finally");
|
||||||
output.space();
|
output.space();
|
||||||
print_braced(self, output);
|
print_braced(this, output);
|
||||||
});
|
});
|
||||||
|
|
||||||
DEFPRINT(AST_Var, function(self, output) {
|
function print_definitinos(type) {
|
||||||
output.print("var");
|
return function(output) {
|
||||||
|
var self = this;
|
||||||
|
output.print(type);
|
||||||
output.space();
|
output.space();
|
||||||
self.definitions.forEach(function(def, i) {
|
self.definitions.forEach(function(def, i) {
|
||||||
if (i) output.comma();
|
if (i) output.comma();
|
||||||
@@ -1144,12 +1124,16 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
if (p && p.init !== self || !(p instanceof AST_For || p instanceof AST_ForIn)) output.semicolon();
|
if (p && p.init !== self || !(p instanceof AST_For || p instanceof AST_ForIn)) output.semicolon();
|
||||||
});
|
};
|
||||||
|
}
|
||||||
|
DEFPRINT(AST_Const, print_definitinos("const"));
|
||||||
|
DEFPRINT(AST_Let, print_definitinos("let"));
|
||||||
|
DEFPRINT(AST_Var, print_definitinos("var"));
|
||||||
|
|
||||||
function parenthesize_for_noin(node, output, noin) {
|
function parenthesize_for_noin(node, output, noin) {
|
||||||
var parens = false;
|
var parens = false;
|
||||||
// need to take some precautions here:
|
// 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 (noin) node.walk(new TreeWalker(function(node) {
|
||||||
if (parens || node instanceof AST_Scope) return true;
|
if (parens || node instanceof AST_Scope) return true;
|
||||||
if (node instanceof AST_Binary && node.operator == "in") {
|
if (node instanceof AST_Binary && node.operator == "in") {
|
||||||
@@ -1160,7 +1144,8 @@ function OutputStream(options) {
|
|||||||
node.print(output, parens);
|
node.print(output, parens);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFPRINT(AST_VarDef, function(self, output) {
|
DEFPRINT(AST_VarDef, function(output) {
|
||||||
|
var self = this;
|
||||||
self.name.print(output);
|
self.name.print(output);
|
||||||
if (self.value) {
|
if (self.value) {
|
||||||
output.space();
|
output.space();
|
||||||
@@ -1173,10 +1158,7 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ other expressions ]----- */
|
/* -----[ other expressions ]----- */
|
||||||
DEFPRINT(AST_Call, function(self, output) {
|
function print_call_args(self, output) {
|
||||||
self.expression.print(output);
|
|
||||||
if (self instanceof AST_New && !need_constructor_parens(self, output))
|
|
||||||
return;
|
|
||||||
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
|
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
|
||||||
output.add_mapping(self.start);
|
output.add_mapping(self.start);
|
||||||
}
|
}
|
||||||
@@ -1186,14 +1168,20 @@ function OutputStream(options) {
|
|||||||
expr.print(output);
|
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.print("new");
|
||||||
output.space();
|
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) {
|
DEFPRINT(AST_Sequence, function(output) {
|
||||||
self.expressions.forEach(function(node, index) {
|
this.expressions.forEach(function(node, index) {
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
output.comma();
|
output.comma();
|
||||||
if (output.should_break()) {
|
if (output.should_break()) {
|
||||||
@@ -1204,7 +1192,8 @@ function OutputStream(options) {
|
|||||||
node.print(output);
|
node.print(output);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Dot, function(self, output) {
|
DEFPRINT(AST_Dot, function(output) {
|
||||||
|
var self = this;
|
||||||
var expr = self.expression;
|
var expr = self.expression;
|
||||||
expr.print(output);
|
expr.print(output);
|
||||||
var prop = self.property;
|
var prop = self.property;
|
||||||
@@ -1225,35 +1214,38 @@ function OutputStream(options) {
|
|||||||
output.print_name(prop);
|
output.print_name(prop);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Sub, function(self, output) {
|
DEFPRINT(AST_Sub, function(output) {
|
||||||
self.expression.print(output);
|
this.expression.print(output);
|
||||||
output.print("[");
|
output.print("[");
|
||||||
self.property.print(output);
|
this.property.print(output);
|
||||||
output.print("]");
|
output.print("]");
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_UnaryPrefix, function(self, output) {
|
DEFPRINT(AST_UnaryPrefix, function(output) {
|
||||||
var op = self.operator;
|
var op = this.operator;
|
||||||
|
var exp = this.expression;
|
||||||
output.print(op);
|
output.print(op);
|
||||||
if (/^[a-z]/i.test(op)
|
if (/^[a-z]/i.test(op)
|
||||||
|| (/[+-]$/.test(op)
|
|| (/[+-]$/.test(op)
|
||||||
&& self.expression instanceof AST_UnaryPrefix
|
&& exp instanceof AST_UnaryPrefix
|
||||||
&& /^[+-]/.test(self.expression.operator))) {
|
&& /^[+-]/.test(exp.operator))) {
|
||||||
output.space();
|
output.space();
|
||||||
}
|
}
|
||||||
self.expression.print(output);
|
exp.print(output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_UnaryPostfix, function(self, output) {
|
DEFPRINT(AST_UnaryPostfix, function(output) {
|
||||||
self.expression.print(output);
|
this.expression.print(output);
|
||||||
output.print(self.operator);
|
output.print(this.operator);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Binary, function(self, output) {
|
DEFPRINT(AST_Binary, function(output) {
|
||||||
|
var self = this;
|
||||||
self.left.print(output);
|
self.left.print(output);
|
||||||
output.space();
|
output.space();
|
||||||
output.print(self.operator);
|
output.print(self.operator);
|
||||||
output.space();
|
output.space();
|
||||||
self.right.print(output);
|
self.right.print(output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Conditional, function(self, output) {
|
DEFPRINT(AST_Conditional, function(output) {
|
||||||
|
var self = this;
|
||||||
self.condition.print(output);
|
self.condition.print(output);
|
||||||
output.space();
|
output.space();
|
||||||
output.print("?");
|
output.print("?");
|
||||||
@@ -1265,10 +1257,10 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ literals ]----- */
|
/* -----[ literals ]----- */
|
||||||
DEFPRINT(AST_Array, function(self, output) {
|
DEFPRINT(AST_Array, function(output) {
|
||||||
output.with_square(function() {
|
var a = this.elements, len = a.length;
|
||||||
var a = self.elements, len = a.length;
|
output.with_square(len > 0 ? function() {
|
||||||
if (len > 0) output.space();
|
output.space();
|
||||||
a.forEach(function(exp, i) {
|
a.forEach(function(exp, i) {
|
||||||
if (i) output.comma();
|
if (i) output.comma();
|
||||||
exp.print(output);
|
exp.print(output);
|
||||||
@@ -1278,12 +1270,13 @@ function OutputStream(options) {
|
|||||||
if (i === len - 1 && exp instanceof AST_Hole)
|
if (i === len - 1 && exp instanceof AST_Hole)
|
||||||
output.comma();
|
output.comma();
|
||||||
});
|
});
|
||||||
if (len > 0) output.space();
|
output.space();
|
||||||
|
} : noop);
|
||||||
});
|
});
|
||||||
});
|
DEFPRINT(AST_Object, function(output) {
|
||||||
DEFPRINT(AST_Object, function(self, output) {
|
var props = this.properties;
|
||||||
if (self.properties.length > 0) output.with_block(function() {
|
if (props.length > 0) output.with_block(function() {
|
||||||
self.properties.forEach(function(prop, i) {
|
props.forEach(function(prop, i) {
|
||||||
if (i) {
|
if (i) {
|
||||||
output.print(",");
|
output.print(",");
|
||||||
output.newline();
|
output.newline();
|
||||||
@@ -1293,7 +1286,7 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
output.newline();
|
output.newline();
|
||||||
});
|
});
|
||||||
else print_braced_empty(self, output);
|
else print_braced_empty(this, output);
|
||||||
});
|
});
|
||||||
|
|
||||||
function print_property_name(key, quote, output) {
|
function print_property_name(key, quote, output) {
|
||||||
@@ -1312,47 +1305,48 @@ 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);
|
print_property_name(self.key, self.quote, output);
|
||||||
output.colon();
|
output.colon();
|
||||||
self.value.print(output);
|
self.value.print(output);
|
||||||
});
|
});
|
||||||
AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, output) {
|
function print_accessor(type) {
|
||||||
|
return function(output) {
|
||||||
|
var self = this;
|
||||||
output.print(type);
|
output.print(type);
|
||||||
output.space();
|
output.space();
|
||||||
print_property_name(this.key.name, this.quote, output);
|
print_property_name(self.key.name, self.quote, output);
|
||||||
this.value._do_print(output, true);
|
self.value._codegen(output, true);
|
||||||
});
|
};
|
||||||
DEFPRINT(AST_ObjectSetter, function(self, output) {
|
}
|
||||||
self._print_getter_setter("set", output);
|
DEFPRINT(AST_ObjectGetter, print_accessor("get"));
|
||||||
});
|
DEFPRINT(AST_ObjectSetter, print_accessor("set"));
|
||||||
DEFPRINT(AST_ObjectGetter, function(self, output) {
|
DEFPRINT(AST_Symbol, function(output) {
|
||||||
self._print_getter_setter("get", output);
|
var def = this.definition();
|
||||||
});
|
output.print_name(def && def.mangled_name || this.name);
|
||||||
DEFPRINT(AST_Symbol, function(self, output) {
|
|
||||||
var def = self.definition();
|
|
||||||
output.print_name(def && def.mangled_name || self.name);
|
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Hole, noop);
|
DEFPRINT(AST_Hole, noop);
|
||||||
DEFPRINT(AST_This, function(self, output) {
|
DEFPRINT(AST_This, function(output) {
|
||||||
output.print("this");
|
output.print("this");
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Constant, function(self, output) {
|
DEFPRINT(AST_Constant, function(output) {
|
||||||
output.print(self.value);
|
output.print(this.value);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_String, function(self, output) {
|
DEFPRINT(AST_String, function(output) {
|
||||||
output.print_string(self.value, self.quote);
|
output.print_string(this.value, this.quote);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Number, function(self, output) {
|
DEFPRINT(AST_Number, function(output) {
|
||||||
if (use_asm && self.start && self.start.raw != null) {
|
var start = this.start;
|
||||||
output.print(self.start.raw);
|
if (use_asm && start && start.raw != null) {
|
||||||
|
output.print(start.raw);
|
||||||
} else {
|
} else {
|
||||||
output.print(make_num(self.value));
|
output.print(make_num(this.value));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
DEFPRINT(AST_RegExp, function(self, output) {
|
DEFPRINT(AST_RegExp, function(output) {
|
||||||
var regexp = self.value;
|
var regexp = this.value;
|
||||||
var str = regexp.toString();
|
var str = regexp.toString();
|
||||||
var end = str.lastIndexOf("/");
|
var end = str.lastIndexOf("/");
|
||||||
if (regexp.raw_source) {
|
if (regexp.raw_source) {
|
||||||
@@ -1386,17 +1380,16 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
var p = output.parent();
|
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(" ");
|
output.print(" ");
|
||||||
});
|
});
|
||||||
|
|
||||||
function force_statement(stat, output) {
|
function force_statement(stat, output) {
|
||||||
if (output.option("braces")) {
|
if (output.option("braces") && !(stat instanceof AST_Const || stat instanceof AST_Let)) {
|
||||||
make_block(stat, output);
|
make_block(stat, output);
|
||||||
} else {
|
} else if (!stat || stat instanceof AST_EmptyStatement) {
|
||||||
if (!stat || stat instanceof AST_EmptyStatement)
|
|
||||||
output.force_semicolon();
|
output.force_semicolon();
|
||||||
else
|
} else {
|
||||||
stat.print(output);
|
stat.print(output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1470,7 +1463,6 @@ function OutputStream(options) {
|
|||||||
AST_Node,
|
AST_Node,
|
||||||
// since the label symbol will mark it
|
// since the label symbol will mark it
|
||||||
AST_LabeledStatement,
|
AST_LabeledStatement,
|
||||||
AST_Toplevel,
|
|
||||||
], noop);
|
], noop);
|
||||||
|
|
||||||
// XXX: I'm not exactly sure if we need it for all of these nodes,
|
// XXX: I'm not exactly sure if we need it for all of these nodes,
|
||||||
@@ -1482,7 +1474,6 @@ function OutputStream(options) {
|
|||||||
AST_Constant,
|
AST_Constant,
|
||||||
AST_Debugger,
|
AST_Debugger,
|
||||||
AST_Definitions,
|
AST_Definitions,
|
||||||
AST_Directive,
|
|
||||||
AST_Finally,
|
AST_Finally,
|
||||||
AST_Jump,
|
AST_Jump,
|
||||||
AST_Lambda,
|
AST_Lambda,
|
||||||
|
|||||||
210
lib/parse.js
210
lib/parse.js
@@ -1,7 +1,7 @@
|
|||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
||||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||||
https://github.com/mishoo/UglifyJS2
|
https://github.com/mishoo/UglifyJS
|
||||||
|
|
||||||
-------------------------------- (C) ---------------------------------
|
-------------------------------- (C) ---------------------------------
|
||||||
|
|
||||||
@@ -44,21 +44,23 @@
|
|||||||
|
|
||||||
"use strict";
|
"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 = "break case catch const continue debugger default delete do else finally for function if in instanceof let new return switch throw try typeof var void while with";
|
||||||
var KEYWORDS_ATOM = 'false null true';
|
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'
|
var RESERVED_WORDS = [
|
||||||
+ " " + KEYWORDS_ATOM + " " + KEYWORDS;
|
"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",
|
||||||
var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case';
|
KEYWORDS_ATOM,
|
||||||
|
KEYWORDS,
|
||||||
|
].join(" ");
|
||||||
|
var KEYWORDS_BEFORE_EXPRESSION = "return new delete throw else case";
|
||||||
|
|
||||||
KEYWORDS = makePredicate(KEYWORDS);
|
KEYWORDS = makePredicate(KEYWORDS);
|
||||||
RESERVED_WORDS = makePredicate(RESERVED_WORDS);
|
RESERVED_WORDS = makePredicate(RESERVED_WORDS);
|
||||||
KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION);
|
KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION);
|
||||||
KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);
|
KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);
|
||||||
|
|
||||||
var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
|
var RE_BIN_NUMBER = /^0b([01]+)$/i;
|
||||||
|
var RE_HEX_NUMBER = /^0x([0-9a-f]+)$/i;
|
||||||
var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
|
var RE_OCT_NUMBER = /^0o?([0-7]+)$/i;
|
||||||
var RE_OCT_NUMBER = /^0[0-7]+$/;
|
|
||||||
|
|
||||||
var OPERATORS = makePredicate([
|
var OPERATORS = makePredicate([
|
||||||
"in",
|
"in",
|
||||||
@@ -107,31 +109,21 @@ var OPERATORS = makePredicate([
|
|||||||
"||"
|
"||"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\uFEFF"));
|
var NEWLINE_CHARS = "\n\r\u2028\u2029";
|
||||||
|
var OPERATOR_CHARS = "+-*&%=<>!?|~^";
|
||||||
|
var PUNC_BEFORE_EXPRESSION = "[{(,;:";
|
||||||
|
var PUNC_CHARS = PUNC_BEFORE_EXPRESSION + ")}]";
|
||||||
|
var WHITESPACE_CHARS = NEWLINE_CHARS + " \u00a0\t\f\u000b\u200b\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\uFEFF";
|
||||||
|
var NON_IDENTIFIER_CHARS = makePredicate(characters("./'\"" + OPERATOR_CHARS + PUNC_CHARS + WHITESPACE_CHARS));
|
||||||
|
|
||||||
var NEWLINE_CHARS = makePredicate(characters("\n\r\u2028\u2029"));
|
NEWLINE_CHARS = makePredicate(characters(NEWLINE_CHARS));
|
||||||
|
OPERATOR_CHARS = makePredicate(characters(OPERATOR_CHARS));
|
||||||
var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,;:"));
|
PUNC_BEFORE_EXPRESSION = makePredicate(characters(PUNC_BEFORE_EXPRESSION));
|
||||||
|
PUNC_CHARS = makePredicate(characters(PUNC_CHARS));
|
||||||
var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
|
WHITESPACE_CHARS = makePredicate(characters(WHITESPACE_CHARS));
|
||||||
|
|
||||||
/* -----[ Tokenizer ]----- */
|
/* -----[ Tokenizer ]----- */
|
||||||
|
|
||||||
// regexps adapted from http://xregexp.com/plugins/#unicode
|
|
||||||
var UNICODE = {
|
|
||||||
letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B2\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),
|
|
||||||
digit: new RegExp("[\\u0030-\\u0039\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0DE6-\\u0DEF\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\u1040-\\u1049\\u1090-\\u1099\\u17E0-\\u17E9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19D9\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\uA620-\\uA629\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uA9F0-\\uA9F9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19]"),
|
|
||||||
non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"),
|
|
||||||
space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"),
|
|
||||||
connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]")
|
|
||||||
};
|
|
||||||
|
|
||||||
function is_letter(code) {
|
|
||||||
return (code >= 97 && code <= 122)
|
|
||||||
|| (code >= 65 && code <= 90)
|
|
||||||
|| (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_surrogate_pair_head(code) {
|
function is_surrogate_pair_head(code) {
|
||||||
return code >= 0xd800 && code <= 0xdbff;
|
return code >= 0xd800 && code <= 0xdbff;
|
||||||
}
|
}
|
||||||
@@ -144,36 +136,8 @@ function is_digit(code) {
|
|||||||
return code >= 48 && code <= 57;
|
return code >= 48 && code <= 57;
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_alphanumeric_char(code) {
|
|
||||||
return is_digit(code) || is_letter(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_unicode_digit(code) {
|
|
||||||
return UNICODE.digit.test(String.fromCharCode(code));
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_unicode_combining_mark(ch) {
|
|
||||||
return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_unicode_connector_punctuation(ch) {
|
|
||||||
return UNICODE.connector_punctuation.test(ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_identifier_start(code) {
|
|
||||||
return code == 36 || code == 95 || is_letter(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_identifier_char(ch) {
|
function is_identifier_char(ch) {
|
||||||
var code = ch.charCodeAt(0);
|
return !NON_IDENTIFIER_CHARS[ch];
|
||||||
return is_identifier_start(code)
|
|
||||||
|| is_digit(code)
|
|
||||||
|| code == 8204 // \u200c: zero-width non-joiner <ZWNJ>
|
|
||||||
|| code == 8205 // \u200d: zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)
|
|
||||||
|| is_unicode_combining_mark(ch)
|
|
||||||
|| is_unicode_connector_punctuation(ch)
|
|
||||||
|| is_unicode_digit(code)
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_identifier_string(str) {
|
function is_identifier_string(str) {
|
||||||
@@ -181,14 +145,12 @@ function is_identifier_string(str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parse_js_number(num) {
|
function parse_js_number(num) {
|
||||||
if (RE_HEX_NUMBER.test(num)) {
|
var match;
|
||||||
return parseInt(num.substr(2), 16);
|
if (match = RE_BIN_NUMBER.exec(num)) return parseInt(match[1], 2);
|
||||||
} else if (RE_OCT_NUMBER.test(num)) {
|
if (match = RE_HEX_NUMBER.exec(num)) return parseInt(match[1], 16);
|
||||||
return parseInt(num.substr(1), 8);
|
if (match = RE_OCT_NUMBER.exec(num)) return parseInt(match[1], 8);
|
||||||
} else {
|
|
||||||
var val = parseFloat(num);
|
var val = parseFloat(num);
|
||||||
if (val == num) return val;
|
if (val == num) return val;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function JS_Parse_Error(message, filename, line, col, pos) {
|
function JS_Parse_Error(message, filename, line, col, pos) {
|
||||||
@@ -344,11 +306,13 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
case (after_e = false, 46): // .
|
case (after_e = false, 46): // .
|
||||||
return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false;
|
return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false;
|
||||||
}
|
}
|
||||||
return is_alphanumeric_char(code);
|
return is_digit(code) || /[_0-9a-fo]/i.test(ch);
|
||||||
});
|
});
|
||||||
if (prefix) num = prefix + num;
|
if (prefix) num = prefix + num;
|
||||||
if (RE_OCT_NUMBER.test(num) && next_token.has_directive("use strict")) {
|
if (/^0[0-7_]+$/.test(num)) {
|
||||||
parse_error("Legacy octal literals are not allowed in strict mode");
|
if (next_token.has_directive("use strict")) parse_error("Legacy octal literals are not allowed in strict mode");
|
||||||
|
} else {
|
||||||
|
num = num.replace(has_x ? /([1-9a-f]|.0)_(?=[0-9a-f])/gi : /([1-9]|.0)_(?=[0-9])/gi, "$1");
|
||||||
}
|
}
|
||||||
var valid = parse_js_number(num);
|
var valid = parse_js_number(num);
|
||||||
if (!isNaN(valid)) return token("num", valid);
|
if (!isNaN(valid)) return token("num", valid);
|
||||||
@@ -358,20 +322,30 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
function read_escaped_char(in_string) {
|
function read_escaped_char(in_string) {
|
||||||
var ch = next(true, in_string);
|
var ch = next(true, in_string);
|
||||||
switch (ch.charCodeAt(0)) {
|
switch (ch.charCodeAt(0)) {
|
||||||
case 110 : return "\n";
|
case 110: return "\n";
|
||||||
case 114 : return "\r";
|
case 114: return "\r";
|
||||||
case 116 : return "\t";
|
case 116: return "\t";
|
||||||
case 98 : return "\b";
|
case 98: return "\b";
|
||||||
case 118 : return "\u000b"; // \v
|
case 118: return "\u000b"; // \v
|
||||||
case 102 : return "\f";
|
case 102: return "\f";
|
||||||
case 120 : return String.fromCharCode(hex_bytes(2)); // \x
|
case 120: return String.fromCharCode(hex_bytes(2)); // \x
|
||||||
case 117 : return String.fromCharCode(hex_bytes(4)); // \u
|
case 117: // \u
|
||||||
case 10 : return ""; // newline
|
if (peek() != "{") return String.fromCharCode(hex_bytes(4));
|
||||||
case 13 : // \r
|
next();
|
||||||
if (peek() == "\n") { // DOS newline
|
var num = 0;
|
||||||
next(true, in_string);
|
do {
|
||||||
return "";
|
var digit = parseInt(next(true), 16);
|
||||||
}
|
if (isNaN(digit)) parse_error("Invalid hex-character pattern in string");
|
||||||
|
num = num * 16 + digit;
|
||||||
|
} while (peek() != "}");
|
||||||
|
next();
|
||||||
|
if (num < 0x10000) return String.fromCharCode(num);
|
||||||
|
if (num > 0x10ffff) parse_error("Invalid character code: " + num);
|
||||||
|
return String.fromCharCode((num >> 10) + 0xd7c0) + String.fromCharCode((num & 0x03ff) + 0xdc00);
|
||||||
|
case 13: // \r
|
||||||
|
// DOS newline
|
||||||
|
if (peek() == "\n") next(true, in_string);
|
||||||
|
case 10: return ""; // \n
|
||||||
}
|
}
|
||||||
if (ch >= "0" && ch <= "7")
|
if (ch >= "0" && ch <= "7")
|
||||||
return read_octal_escape_sequence(ch);
|
return read_octal_escape_sequence(ch);
|
||||||
@@ -438,7 +412,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function() {
|
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function() {
|
||||||
var regex_allowed = S.regex_allowed;
|
var regex_allowed = S.regex_allowed;
|
||||||
var i = find("*/", true);
|
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
|
// update stream position
|
||||||
forward(text.length /* doesn't count \r\n as 2 char while S.pos - i does */ + 2);
|
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));
|
S.comments_before.push(token("comment2", text, true));
|
||||||
@@ -448,7 +422,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
|
|
||||||
function read_name() {
|
function read_name() {
|
||||||
var backslash = false, name = "", ch, escaped = false, hex;
|
var backslash = false, name = "", ch, escaped = false, hex;
|
||||||
while ((ch = peek()) != null) {
|
while (ch = peek()) {
|
||||||
if (!backslash) {
|
if (!backslash) {
|
||||||
if (ch == "\\") escaped = backslash = true, next();
|
if (ch == "\\") escaped = backslash = true, next();
|
||||||
else if (is_identifier_char(ch)) name += next();
|
else if (is_identifier_char(ch)) name += next();
|
||||||
@@ -587,7 +561,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
if (is_digit(code)) return read_num();
|
if (is_digit(code)) return read_num();
|
||||||
if (PUNC_CHARS[ch]) return token("punc", next());
|
if (PUNC_CHARS[ch]) return token("punc", next());
|
||||||
if (OPERATOR_CHARS[ch]) return read_operator();
|
if (OPERATOR_CHARS[ch]) return read_operator();
|
||||||
if (code == 92 || is_identifier_start(code)) return read_word();
|
if (code == 92 || !NON_IDENTIFIER_CHARS[ch]) return read_word();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
parse_error("Unexpected character '" + ch + "'");
|
parse_error("Unexpected character '" + ch + "'");
|
||||||
@@ -832,6 +806,12 @@ function parse($TEXT, options) {
|
|||||||
next();
|
next();
|
||||||
return break_cont(AST_Break);
|
return break_cont(AST_Break);
|
||||||
|
|
||||||
|
case "const":
|
||||||
|
next();
|
||||||
|
var node = const_();
|
||||||
|
semicolon();
|
||||||
|
return node;
|
||||||
|
|
||||||
case "continue":
|
case "continue":
|
||||||
next();
|
next();
|
||||||
return break_cont(AST_Continue);
|
return break_cont(AST_Continue);
|
||||||
@@ -874,6 +854,12 @@ function parse($TEXT, options) {
|
|||||||
next();
|
next();
|
||||||
return if_();
|
return if_();
|
||||||
|
|
||||||
|
case "let":
|
||||||
|
next();
|
||||||
|
var node = let_();
|
||||||
|
semicolon();
|
||||||
|
return node;
|
||||||
|
|
||||||
case "return":
|
case "return":
|
||||||
if (S.in_function == 0 && !options.bare_returns)
|
if (S.in_function == 0 && !options.bare_returns)
|
||||||
croak("'return' outside of function");
|
croak("'return' outside of function");
|
||||||
@@ -948,7 +934,7 @@ function parse($TEXT, options) {
|
|||||||
if (!(stat instanceof AST_IterationStatement)) {
|
if (!(stat instanceof AST_IterationStatement)) {
|
||||||
// check for `continue` that refers to this label.
|
// check for `continue` that refers to this label.
|
||||||
// those should be reported as syntax errors.
|
// 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) {
|
label.references.forEach(function(ref) {
|
||||||
if (ref instanceof AST_Continue) {
|
if (ref instanceof AST_Continue) {
|
||||||
ref = ref.label.start;
|
ref = ref.label.start;
|
||||||
@@ -988,7 +974,9 @@ function parse($TEXT, options) {
|
|||||||
expect("(");
|
expect("(");
|
||||||
var init = null;
|
var init = null;
|
||||||
if (!is("punc", ";")) {
|
if (!is("punc", ";")) {
|
||||||
init = is("keyword", "var")
|
init = is("keyword", "const")
|
||||||
|
? (next(), const_(true))
|
||||||
|
: is("keyword", "var")
|
||||||
? (next(), var_(true))
|
? (next(), var_(true))
|
||||||
: expression(true, true);
|
: expression(true, true);
|
||||||
if (is("operator", "in")) {
|
if (is("operator", "in")) {
|
||||||
@@ -1092,7 +1080,7 @@ function parse($TEXT, options) {
|
|||||||
|
|
||||||
function switch_body_() {
|
function switch_body_() {
|
||||||
expect("{");
|
expect("{");
|
||||||
var a = [], cur = null, branch = null, tmp;
|
var a = [], branch, cur, default_branch, tmp;
|
||||||
while (!is("punc", "}")) {
|
while (!is("punc", "}")) {
|
||||||
if (is("eof")) expect_token("punc", "}");
|
if (is("eof")) expect_token("punc", "}");
|
||||||
if (is("keyword", "case")) {
|
if (is("keyword", "case")) {
|
||||||
@@ -1107,12 +1095,14 @@ function parse($TEXT, options) {
|
|||||||
expect(":");
|
expect(":");
|
||||||
} else if (is("keyword", "default")) {
|
} else if (is("keyword", "default")) {
|
||||||
if (branch) branch.end = prev();
|
if (branch) branch.end = prev();
|
||||||
|
if (default_branch) croak("More than one default clause in switch statement");
|
||||||
cur = [];
|
cur = [];
|
||||||
branch = new AST_Default({
|
branch = new AST_Default({
|
||||||
start : (tmp = S.token, next(), expect(":"), tmp),
|
start : (tmp = S.token, next(), expect(":"), tmp),
|
||||||
body : cur
|
body : cur
|
||||||
});
|
});
|
||||||
a.push(branch);
|
a.push(branch);
|
||||||
|
default_branch = branch;
|
||||||
} else {
|
} else {
|
||||||
if (!cur) unexpected();
|
if (!cur) unexpected();
|
||||||
cur.push(statement());
|
cur.push(statement());
|
||||||
@@ -1128,9 +1118,12 @@ function parse($TEXT, options) {
|
|||||||
if (is("keyword", "catch")) {
|
if (is("keyword", "catch")) {
|
||||||
var start = S.token;
|
var start = S.token;
|
||||||
next();
|
next();
|
||||||
expect("(");
|
var name = null;
|
||||||
var name = as_symbol(AST_SymbolCatch);
|
if (is("punc", "(")) {
|
||||||
|
next();
|
||||||
|
name = as_symbol(AST_SymbolCatch);
|
||||||
expect(")");
|
expect(")");
|
||||||
|
}
|
||||||
bcatch = new AST_Catch({
|
bcatch = new AST_Catch({
|
||||||
start : start,
|
start : start,
|
||||||
argname : name,
|
argname : name,
|
||||||
@@ -1156,13 +1149,22 @@ function parse($TEXT, options) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function vardefs(no_in) {
|
function vardefs(type, no_in, must_init) {
|
||||||
var a = [];
|
var a = [];
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
var start = S.token;
|
||||||
|
var name = as_symbol(type);
|
||||||
|
var value = null;
|
||||||
|
if (is("operator", "=")) {
|
||||||
|
next();
|
||||||
|
value = expression(false, no_in);
|
||||||
|
} else if (must_init) {
|
||||||
|
croak("Missing initializer in declaration");
|
||||||
|
}
|
||||||
a.push(new AST_VarDef({
|
a.push(new AST_VarDef({
|
||||||
start : S.token,
|
start : start,
|
||||||
name : as_symbol(AST_SymbolVar),
|
name : name,
|
||||||
value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
|
value : value,
|
||||||
end : prev()
|
end : prev()
|
||||||
}));
|
}));
|
||||||
if (!is("punc", ","))
|
if (!is("punc", ","))
|
||||||
@@ -1172,10 +1174,26 @@ function parse($TEXT, options) {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var const_ = function(no_in) {
|
||||||
|
return new AST_Const({
|
||||||
|
start : prev(),
|
||||||
|
definitions : vardefs(AST_SymbolConst, no_in, true),
|
||||||
|
end : prev()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var let_ = function(no_in) {
|
||||||
|
return new AST_Let({
|
||||||
|
start : prev(),
|
||||||
|
definitions : vardefs(AST_SymbolLet, no_in),
|
||||||
|
end : prev()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var var_ = function(no_in) {
|
var var_ = function(no_in) {
|
||||||
return new AST_Var({
|
return new AST_Var({
|
||||||
start : prev(),
|
start : prev(),
|
||||||
definitions : vardefs(no_in),
|
definitions : vardefs(AST_SymbolVar, no_in),
|
||||||
end : prev()
|
end : prev()
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
||||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||||
https://github.com/mishoo/UglifyJS2
|
https://github.com/mishoo/UglifyJS
|
||||||
|
|
||||||
-------------------------------- (C) ---------------------------------
|
-------------------------------- (C) ---------------------------------
|
||||||
|
|
||||||
@@ -43,7 +43,8 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function find_builtins(reserved) {
|
var builtins = function() {
|
||||||
|
var names = [];
|
||||||
// NaN will be included due to Number.NaN
|
// NaN will be included due to Number.NaN
|
||||||
[
|
[
|
||||||
"null",
|
"null",
|
||||||
@@ -67,19 +68,21 @@ function find_builtins(reserved) {
|
|||||||
].forEach(function(ctor) {
|
].forEach(function(ctor) {
|
||||||
Object.getOwnPropertyNames(ctor).map(add);
|
Object.getOwnPropertyNames(ctor).map(add);
|
||||||
if (ctor.prototype) {
|
if (ctor.prototype) {
|
||||||
|
Object.getOwnPropertyNames(new ctor()).map(add);
|
||||||
Object.getOwnPropertyNames(ctor.prototype).map(add);
|
Object.getOwnPropertyNames(ctor.prototype).map(add);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return makePredicate(names);
|
||||||
|
|
||||||
function add(name) {
|
function add(name) {
|
||||||
push_uniq(reserved, name);
|
names.push(name);
|
||||||
}
|
}
|
||||||
}
|
}();
|
||||||
|
|
||||||
function reserve_quoted_keys(ast, reserved) {
|
function reserve_quoted_keys(ast, reserved) {
|
||||||
ast.walk(new TreeWalker(function(node) {
|
ast.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_ObjectKeyVal && node.quote) {
|
if (node instanceof AST_ObjectKeyVal) {
|
||||||
add(node.key);
|
if (node.quote) add(node.key);
|
||||||
} else if (node instanceof AST_Sub) {
|
} else if (node instanceof AST_Sub) {
|
||||||
addStrings(node.property, add);
|
addStrings(node.property, add);
|
||||||
}
|
}
|
||||||
@@ -91,17 +94,14 @@ function reserve_quoted_keys(ast, reserved) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addStrings(node, add) {
|
function addStrings(node, add) {
|
||||||
node.walk(new TreeWalker(function(node) {
|
if (node instanceof AST_Conditional) {
|
||||||
if (node instanceof AST_Sequence) {
|
addStrings(node.consequent, add);
|
||||||
|
addStrings(node.alternative, add);
|
||||||
|
} else if (node instanceof AST_Sequence) {
|
||||||
addStrings(node.tail_node(), add);
|
addStrings(node.tail_node(), add);
|
||||||
} else if (node instanceof AST_String) {
|
} else if (node instanceof AST_String) {
|
||||||
add(node.value);
|
add(node.value);
|
||||||
} else if (node instanceof AST_Conditional) {
|
|
||||||
addStrings(node.consequent, add);
|
|
||||||
addStrings(node.alternative, add);
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mangle_properties(ast, options) {
|
function mangle_properties(ast, options) {
|
||||||
@@ -110,21 +110,21 @@ function mangle_properties(ast, options) {
|
|||||||
cache: null,
|
cache: null,
|
||||||
debug: false,
|
debug: false,
|
||||||
keep_quoted: false,
|
keep_quoted: false,
|
||||||
only_cache: false,
|
|
||||||
regex: null,
|
regex: null,
|
||||||
reserved: null,
|
reserved: null,
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
var reserved = options.reserved;
|
var reserved = Object.create(options.builtins ? null : builtins);
|
||||||
if (!Array.isArray(reserved)) reserved = [];
|
if (Array.isArray(options.reserved)) options.reserved.forEach(function(name) {
|
||||||
if (!options.builtins) find_builtins(reserved);
|
reserved[name] = true;
|
||||||
|
});
|
||||||
|
|
||||||
var cname = -1;
|
var cname = -1;
|
||||||
var cache;
|
var cache;
|
||||||
if (options.cache) {
|
if (options.cache) {
|
||||||
cache = options.cache.props;
|
cache = options.cache.props;
|
||||||
cache.each(function(mangled_name) {
|
cache.each(function(name) {
|
||||||
push_uniq(reserved, mangled_name);
|
reserved[name] = true;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
cache = new Dictionary();
|
cache = new Dictionary();
|
||||||
@@ -139,62 +139,92 @@ function mangle_properties(ast, options) {
|
|||||||
var debug_suffix;
|
var debug_suffix;
|
||||||
if (debug) debug_suffix = options.debug === true ? "" : options.debug;
|
if (debug) debug_suffix = options.debug === true ? "" : options.debug;
|
||||||
|
|
||||||
var names_to_mangle = [];
|
var names_to_mangle = Object.create(null);
|
||||||
var unmangleable = [];
|
var unmangleable = Object.create(reserved);
|
||||||
|
|
||||||
// step 1: find candidates to mangle
|
// step 1: find candidates to mangle
|
||||||
ast.walk(new TreeWalker(function(node) {
|
ast.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_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);
|
add(node.key);
|
||||||
} else if (node instanceof AST_ObjectProperty) {
|
} else if (node instanceof AST_ObjectProperty) {
|
||||||
// setter or getter, since KeyVal is handled above
|
// setter or getter, since KeyVal is handled above
|
||||||
add(node.key.name);
|
add(node.key.name);
|
||||||
} else if (node instanceof AST_Dot) {
|
|
||||||
add(node.property);
|
|
||||||
} else if (node instanceof AST_Sub) {
|
} else if (node instanceof AST_Sub) {
|
||||||
addStrings(node.property, add);
|
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
|
// step 2: renaming properties
|
||||||
return ast.transform(new TreeTransformer(function(node) {
|
ast.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_ObjectKeyVal) {
|
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);
|
node.key = mangle(node.key);
|
||||||
} else if (node instanceof AST_ObjectProperty) {
|
} else if (node instanceof AST_ObjectProperty) {
|
||||||
// setter or getter
|
// setter or getter
|
||||||
node.key.name = mangle(node.key.name);
|
node.key.name = mangle(node.key.name);
|
||||||
} else if (node instanceof AST_Dot) {
|
} else if (node instanceof AST_Sub) {
|
||||||
node.property = mangle(node.property);
|
if (!options.keep_quoted) mangleStrings(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]);
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// only function declarations after this line
|
// only function declarations after this line
|
||||||
|
|
||||||
function can_mangle(name) {
|
function can_mangle(name) {
|
||||||
if (unmangleable.indexOf(name) >= 0) return false;
|
if (unmangleable[name]) return false;
|
||||||
if (reserved.indexOf(name) >= 0) return false;
|
|
||||||
if (options.only_cache) return cache.has(name);
|
|
||||||
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
|
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function should_mangle(name) {
|
function should_mangle(name) {
|
||||||
|
if (reserved[name]) return false;
|
||||||
if (regex && !regex.test(name)) return false;
|
if (regex && !regex.test(name)) return false;
|
||||||
if (reserved.indexOf(name) >= 0) return false;
|
return cache.has(name) || names_to_mangle[name];
|
||||||
return cache.has(name) || names_to_mangle.indexOf(name) >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function add(name) {
|
function add(name) {
|
||||||
if (can_mangle(name)) push_uniq(names_to_mangle, name);
|
if (can_mangle(name)) names_to_mangle[name] = true;
|
||||||
if (!should_mangle(name)) push_uniq(unmangleable, name);
|
if (!should_mangle(name)) unmangleable[name] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mangle(name) {
|
function mangle(name) {
|
||||||
@@ -218,17 +248,13 @@ function mangle_properties(ast, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mangleStrings(node) {
|
function mangleStrings(node) {
|
||||||
return node.transform(new TreeTransformer(function(node) {
|
|
||||||
if (node instanceof AST_Sequence) {
|
if (node instanceof AST_Sequence) {
|
||||||
var last = node.expressions.length - 1;
|
mangleStrings(node.expressions.tail_node());
|
||||||
node.expressions[last] = mangleStrings(node.expressions[last]);
|
|
||||||
} else if (node instanceof AST_String) {
|
} else if (node instanceof AST_String) {
|
||||||
node.value = mangle(node.value);
|
node.value = mangle(node.value);
|
||||||
} else if (node instanceof AST_Conditional) {
|
} else if (node instanceof AST_Conditional) {
|
||||||
node.consequent = mangleStrings(node.consequent);
|
mangleStrings(node.consequent);
|
||||||
node.alternative = mangleStrings(node.alternative);
|
mangleStrings(node.alternative);
|
||||||
}
|
}
|
||||||
return node;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
321
lib/scope.js
321
lib/scope.js
@@ -1,7 +1,7 @@
|
|||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
||||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||||
https://github.com/mishoo/UglifyJS2
|
https://github.com/mishoo/UglifyJS
|
||||||
|
|
||||||
-------------------------------- (C) ---------------------------------
|
-------------------------------- (C) ---------------------------------
|
||||||
|
|
||||||
@@ -43,39 +43,33 @@
|
|||||||
|
|
||||||
"use strict";
|
"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.name = orig.name;
|
||||||
this.orig = [ orig ];
|
this.orig = [ orig ];
|
||||||
this.init = init;
|
|
||||||
this.eliminated = 0;
|
|
||||||
this.scope = scope;
|
|
||||||
this.references = [];
|
this.references = [];
|
||||||
this.replaced = 0;
|
this.replaced = 0;
|
||||||
this.global = false;
|
this.scope = scope;
|
||||||
this.mangled_name = null;
|
|
||||||
this.undeclared = false;
|
this.undeclared = false;
|
||||||
this.id = SymbolDef.next_id++;
|
|
||||||
this.lambda = orig instanceof AST_SymbolLambda;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolDef.next_id = 1;
|
|
||||||
|
|
||||||
SymbolDef.prototype = {
|
SymbolDef.prototype = {
|
||||||
unmangleable: function(options) {
|
forEach: function(fn) {
|
||||||
return this.global && !options.toplevel
|
this.orig.forEach(fn);
|
||||||
|| this.undeclared
|
this.references.forEach(fn);
|
||||||
|| !options.eval && this.scope.pinned()
|
|
||||||
|| options.keep_fnames
|
|
||||||
&& (this.orig[0] instanceof AST_SymbolLambda
|
|
||||||
|| this.orig[0] instanceof AST_SymbolDefun);
|
|
||||||
},
|
},
|
||||||
mangle: function(options) {
|
mangle: function(options) {
|
||||||
var cache = options.cache && options.cache.props;
|
var cache = options.cache && options.cache.props;
|
||||||
if (this.global && cache && cache.has(this.name)) {
|
if (this.global && cache && cache.has(this.name)) {
|
||||||
this.mangled_name = cache.get(this.name);
|
this.mangled_name = cache.get(this.name);
|
||||||
} else if (!this.mangled_name && !this.unmangleable(options)) {
|
} else if (!this.mangled_name && !this.unmangleable(options)) {
|
||||||
var def;
|
var def = this.redefined();
|
||||||
if (def = this.redefined()) {
|
if (def) {
|
||||||
this.mangled_name = def.mangled_name || def.name;
|
this.mangled_name = def.mangled_name || def.name;
|
||||||
} else {
|
} else {
|
||||||
this.mangled_name = next_mangled_name(this.scope, options, this);
|
this.mangled_name = next_mangled_name(this.scope, options, this);
|
||||||
@@ -86,8 +80,24 @@ SymbolDef.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
redefined: function() {
|
redefined: function() {
|
||||||
return this.defun && this.defun.variables.get(this.name);
|
var scope = this.defun;
|
||||||
}
|
if (!scope) return;
|
||||||
|
var name = this.name;
|
||||||
|
var def = scope.variables.get(name)
|
||||||
|
|| scope instanceof AST_Toplevel && scope.globals.get(name)
|
||||||
|
|| this.orig[0] instanceof AST_SymbolConst && find_if(function(def) {
|
||||||
|
return def.name == name;
|
||||||
|
}, scope.enclosed);
|
||||||
|
if (def && def !== this) return def.redefined() || def;
|
||||||
|
},
|
||||||
|
unmangleable: function(options) {
|
||||||
|
return this.global && !options.toplevel
|
||||||
|
|| this.undeclared
|
||||||
|
|| !options.eval && this.scope.pinned()
|
||||||
|
|| options.keep_fnames
|
||||||
|
&& (this.orig[0] instanceof AST_SymbolLambda
|
||||||
|
|| this.orig[0] instanceof AST_SymbolDefun);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||||
@@ -98,30 +108,46 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
|
|
||||||
// pass 1: setup scope chaining and handle definitions
|
// pass 1: setup scope chaining and handle definitions
|
||||||
var self = this;
|
var self = this;
|
||||||
var scope = self.parent_scope = null;
|
|
||||||
var defun = null;
|
var defun = null;
|
||||||
|
var next_def_id = 0;
|
||||||
|
var scope = self.parent_scope = null;
|
||||||
var tw = new TreeWalker(function(node, descend) {
|
var tw = new TreeWalker(function(node, descend) {
|
||||||
if (node instanceof AST_Catch) {
|
if (node instanceof AST_Defun) {
|
||||||
var save_scope = scope;
|
node.name.walk(tw);
|
||||||
scope = new AST_Scope(node);
|
walk_scope(function() {
|
||||||
scope.init_scope_vars(save_scope);
|
node.argnames.forEach(function(argname) {
|
||||||
descend();
|
argname.walk(tw);
|
||||||
scope = save_scope;
|
});
|
||||||
|
walk_body(node, tw);
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Scope) {
|
if (node instanceof AST_SwitchBranch) {
|
||||||
node.init_scope_vars(scope);
|
node.init_vars(scope);
|
||||||
var save_scope = scope;
|
|
||||||
var save_defun = defun;
|
|
||||||
defun = scope = node;
|
|
||||||
descend();
|
descend();
|
||||||
scope = save_scope;
|
return true;
|
||||||
defun = save_defun;
|
}
|
||||||
|
if (node instanceof AST_Try) {
|
||||||
|
walk_scope(function() {
|
||||||
|
walk_body(node, tw);
|
||||||
|
});
|
||||||
|
if (node.bcatch) node.bcatch.walk(tw);
|
||||||
|
if (node.bfinally) node.bfinally.walk(tw);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_With) {
|
if (node instanceof AST_With) {
|
||||||
for (var s = scope; s; s = s.parent_scope) s.uses_with = true;
|
var s = scope;
|
||||||
return;
|
do {
|
||||||
|
s = s.resolve();
|
||||||
|
if (s.uses_with) break;
|
||||||
|
s.uses_with = true;
|
||||||
|
} while (s = s.parent_scope);
|
||||||
|
walk_scope(descend);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_BlockScope) {
|
||||||
|
walk_scope(descend);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Symbol) {
|
if (node instanceof AST_Symbol) {
|
||||||
node.scope = scope;
|
node.scope = scope;
|
||||||
@@ -130,27 +156,50 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
node.thedef = node;
|
node.thedef = node;
|
||||||
node.references = [];
|
node.references = [];
|
||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolDefun) {
|
if (node instanceof AST_SymbolCatch) {
|
||||||
// This should be defined in the parent scope, as we encounter the
|
scope.def_variable(node).defun = defun;
|
||||||
// AST_Defun node before getting to its AST_Symbol.
|
} else if (node instanceof AST_SymbolConst) {
|
||||||
(node.scope = defun.parent_scope.resolve()).def_function(node, defun);
|
scope.def_variable(node).defun = defun;
|
||||||
|
} else if (node instanceof AST_SymbolDefun) {
|
||||||
|
defun.def_function(node, tw.parent());
|
||||||
|
entangle(defun, scope);
|
||||||
|
} else if (node instanceof AST_SymbolFunarg) {
|
||||||
|
defun.def_variable(node);
|
||||||
|
entangle(defun, scope);
|
||||||
} else if (node instanceof AST_SymbolLambda) {
|
} else if (node instanceof AST_SymbolLambda) {
|
||||||
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
|
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
|
||||||
if (options.ie8) def.defun = defun.parent_scope.resolve();
|
if (options.ie8) def.defun = defun.parent_scope.resolve();
|
||||||
|
} else if (node instanceof AST_SymbolLet) {
|
||||||
|
scope.def_variable(node);
|
||||||
} else if (node instanceof AST_SymbolVar) {
|
} else if (node instanceof AST_SymbolVar) {
|
||||||
defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
|
defun.def_variable(node, null);
|
||||||
if (defun !== scope) {
|
entangle(defun, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
function walk_scope(descend) {
|
||||||
|
node.init_vars(scope);
|
||||||
|
var save_defun = defun;
|
||||||
|
var save_scope = scope;
|
||||||
|
if (node instanceof AST_Scope) defun = node;
|
||||||
|
scope = node;
|
||||||
|
descend();
|
||||||
|
scope = save_scope;
|
||||||
|
defun = save_defun;
|
||||||
|
}
|
||||||
|
|
||||||
|
function entangle(defun, scope) {
|
||||||
|
if (defun === scope) return;
|
||||||
node.mark_enclosed(options);
|
node.mark_enclosed(options);
|
||||||
var def = scope.find_variable(node);
|
var def = scope.find_variable(node);
|
||||||
if (node.thedef !== def) {
|
if (node.thedef === def) return;
|
||||||
node.thedef = def;
|
node.thedef = def;
|
||||||
}
|
def.orig.push(node);
|
||||||
node.reference(options);
|
node.mark_enclosed(options);
|
||||||
}
|
|
||||||
} else if (node instanceof AST_SymbolCatch) {
|
|
||||||
scope.def_variable(node).defun = defun;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
self.make_def = function(orig, init) {
|
||||||
|
return new SymbolDef(++next_def_id, this, orig, init);
|
||||||
|
};
|
||||||
self.walk(tw);
|
self.walk(tw);
|
||||||
|
|
||||||
// pass 2: find back references and eval
|
// pass 2: find back references and eval
|
||||||
@@ -162,22 +211,30 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
var name = node.name;
|
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);
|
var sym = node.scope.find_variable(name);
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
sym = self.def_global(node);
|
sym = self.def_global(node);
|
||||||
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
|
} else if (name == "arguments" && sym.scope instanceof AST_Lambda) {
|
||||||
sym.scope.uses_arguments = true;
|
sym.scope.uses_arguments = true;
|
||||||
}
|
}
|
||||||
|
if (name == "eval") {
|
||||||
|
var parent = tw.parent();
|
||||||
|
if (parent.TYPE == "Call" && parent.expression === node) {
|
||||||
|
var s = node.scope;
|
||||||
|
do {
|
||||||
|
s = s.resolve();
|
||||||
|
if (s.uses_eval) break;
|
||||||
|
s.uses_eval = true;
|
||||||
|
} while (s = s.parent_scope);
|
||||||
|
} else if (sym.undeclared) {
|
||||||
|
self.uses_eval = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
node.thedef = sym;
|
node.thedef = sym;
|
||||||
node.reference(options);
|
node.reference(options);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// ensure mangling works if catch reuses a scope variable
|
// ensure mangling works if `catch` reuses a scope variable
|
||||||
if (node instanceof AST_SymbolCatch) {
|
if (node instanceof AST_SymbolCatch) {
|
||||||
var def = node.definition().redefined();
|
var def = node.definition().redefined();
|
||||||
if (def) for (var s = node.scope; s; s = s.parent_scope) {
|
if (def) for (var s = node.scope; s; s = s.parent_scope) {
|
||||||
@@ -186,6 +243,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// ensure compression works if `const` reuses a scope variable
|
||||||
|
if (node instanceof AST_SymbolConst) {
|
||||||
|
var redef = node.definition().redefined();
|
||||||
|
if (redef) redef.const_redefs = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
self.walk(tw);
|
self.walk(tw);
|
||||||
|
|
||||||
@@ -214,10 +277,13 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
function redefine(node, scope) {
|
function redefine(node, scope) {
|
||||||
var name = node.name;
|
var name = node.name;
|
||||||
var old_def = node.thedef;
|
var old_def = node.thedef;
|
||||||
|
if (!all(old_def.orig, function(sym) {
|
||||||
|
return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet);
|
||||||
|
})) return;
|
||||||
var new_def = scope.find_variable(name);
|
var new_def = scope.find_variable(name);
|
||||||
if (new_def) {
|
if (new_def) {
|
||||||
var redef;
|
var redef = new_def.redefined();
|
||||||
while (redef = new_def.redefined()) new_def = redef;
|
if (redef) new_def = redef;
|
||||||
} else {
|
} else {
|
||||||
new_def = self.globals.get(name);
|
new_def = self.globals.get(name);
|
||||||
}
|
}
|
||||||
@@ -226,7 +292,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
} else {
|
} else {
|
||||||
new_def = scope.def_variable(node);
|
new_def = scope.def_variable(node);
|
||||||
}
|
}
|
||||||
old_def.orig.concat(old_def.references).forEach(function(node) {
|
old_def.defun = new_def.scope;
|
||||||
|
old_def.forEach(function(node) {
|
||||||
|
node.redef = true;
|
||||||
node.thedef = new_def;
|
node.thedef = new_def;
|
||||||
node.reference(options);
|
node.reference(options);
|
||||||
});
|
});
|
||||||
@@ -240,7 +308,7 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
|
|||||||
if (globals.has(name)) {
|
if (globals.has(name)) {
|
||||||
return globals.get(name);
|
return globals.get(name);
|
||||||
} else {
|
} else {
|
||||||
var g = new SymbolDef(this, node);
|
var g = this.make_def(node);
|
||||||
g.undeclared = true;
|
g.undeclared = true;
|
||||||
g.global = true;
|
g.global = true;
|
||||||
globals.set(name, g);
|
globals.set(name, g);
|
||||||
@@ -248,24 +316,35 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
|
function init_block_vars(scope, parent) {
|
||||||
this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
scope.enclosed = []; // variables from this or outer scope(s) that are referenced from this or inner scopes
|
||||||
this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
|
scope.parent_scope = parent; // the parent scope (null if this is the top level)
|
||||||
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
scope.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
|
||||||
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
|
scope.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
||||||
this.parent_scope = parent_scope; // the parent scope
|
if (parent) scope.make_def = parent.make_def; // top-level tracking of SymbolDef instances
|
||||||
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
|
|
||||||
});
|
|
||||||
|
|
||||||
AST_Lambda.DEFMETHOD("init_scope_vars", function() {
|
function init_scope_vars(scope, parent) {
|
||||||
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
|
init_block_vars(scope, parent);
|
||||||
|
scope.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
|
||||||
|
scope.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
||||||
|
}
|
||||||
|
|
||||||
|
AST_BlockScope.DEFMETHOD("init_vars", function(parent_scope) {
|
||||||
|
init_block_vars(this, parent_scope);
|
||||||
|
});
|
||||||
|
AST_Scope.DEFMETHOD("init_vars", function(parent_scope) {
|
||||||
|
init_scope_vars(this, parent_scope);
|
||||||
|
});
|
||||||
|
AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) {
|
||||||
|
init_scope_vars(this, parent_scope);
|
||||||
this.uses_arguments = false;
|
this.uses_arguments = false;
|
||||||
this.def_variable(new AST_SymbolFunarg({
|
this.def_variable(new AST_SymbolFunarg({
|
||||||
name: "arguments",
|
name: "arguments",
|
||||||
start: this.start,
|
start: this.start,
|
||||||
end: this.end
|
end: this.end,
|
||||||
}));
|
}));
|
||||||
|
return this;
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
|
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
|
||||||
@@ -286,43 +365,38 @@ AST_Symbol.DEFMETHOD("reference", function(options) {
|
|||||||
this.mark_enclosed(options);
|
this.mark_enclosed(options);
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("find_variable", function(name) {
|
AST_BlockScope.DEFMETHOD("find_variable", function(name) {
|
||||||
if (name instanceof AST_Symbol) name = name.name;
|
if (name instanceof AST_Symbol) name = name.name;
|
||||||
return this.variables.get(name)
|
return this.variables.get(name)
|
||||||
|| (this.parent_scope && this.parent_scope.find_variable(name));
|
|| (this.parent_scope && this.parent_scope.find_variable(name));
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("def_function", function(symbol, init) {
|
AST_BlockScope.DEFMETHOD("def_function", function(symbol, init) {
|
||||||
var def = this.def_variable(symbol, init);
|
var def = this.def_variable(symbol, init);
|
||||||
if (!def.init || def.init instanceof AST_Defun) def.init = init;
|
if (!def.init || def.init instanceof AST_Defun) def.init = init;
|
||||||
this.functions.set(symbol.name, def);
|
this.functions.set(symbol.name, def);
|
||||||
return def;
|
return def;
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
|
AST_BlockScope.DEFMETHOD("def_variable", function(symbol, init) {
|
||||||
var def = this.variables.get(symbol.name);
|
var def = this.variables.get(symbol.name);
|
||||||
if (def) {
|
if (def) {
|
||||||
def.orig.push(symbol);
|
def.orig.push(symbol);
|
||||||
if (def.init instanceof AST_Function) def.init = init;
|
if (def.init instanceof AST_Function) def.init = init;
|
||||||
} else {
|
} else {
|
||||||
def = new SymbolDef(this, symbol, init);
|
def = this.make_def(symbol, init);
|
||||||
this.variables.set(symbol.name, def);
|
this.variables.set(symbol.name, def);
|
||||||
def.global = !this.parent_scope;
|
def.global = !this.parent_scope;
|
||||||
}
|
}
|
||||||
return symbol.thedef = def;
|
return symbol.thedef = def;
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Lambda.DEFMETHOD("resolve", return_this);
|
|
||||||
AST_Scope.DEFMETHOD("resolve", function() {
|
|
||||||
return this.parent_scope.resolve();
|
|
||||||
});
|
|
||||||
AST_Toplevel.DEFMETHOD("resolve", return_this);
|
|
||||||
|
|
||||||
function names_in_use(scope, options) {
|
function names_in_use(scope, options) {
|
||||||
var names = scope.names_in_use;
|
var names = scope.names_in_use;
|
||||||
if (!names) {
|
if (!names) {
|
||||||
scope.names_in_use = names = Object.create(scope.mangled_names || null);
|
scope.cname = -1;
|
||||||
scope.cname_holes = [];
|
scope.cname_holes = [];
|
||||||
|
scope.names_in_use = names = Object.create(null);
|
||||||
var cache = options.cache && options.cache.props;
|
var cache = options.cache && options.cache.props;
|
||||||
scope.enclosed.forEach(function(def) {
|
scope.enclosed.forEach(function(def) {
|
||||||
if (def.unmangleable(options)) names[def.name] = true;
|
if (def.unmangleable(options)) names[def.name] = true;
|
||||||
@@ -339,7 +413,7 @@ function next_mangled_name(scope, options, def) {
|
|||||||
var holes = scope.cname_holes;
|
var holes = scope.cname_holes;
|
||||||
var names = Object.create(null);
|
var names = Object.create(null);
|
||||||
var scopes = [ scope ];
|
var scopes = [ scope ];
|
||||||
def.references.forEach(function(sym) {
|
def.forEach(function(sym) {
|
||||||
var scope = sym.scope;
|
var scope = sym.scope;
|
||||||
do {
|
do {
|
||||||
if (scopes.indexOf(scope) < 0) {
|
if (scopes.indexOf(scope) < 0) {
|
||||||
@@ -355,7 +429,7 @@ function next_mangled_name(scope, options, def) {
|
|||||||
name = base54(holes[i]);
|
name = base54(holes[i]);
|
||||||
if (names[name]) continue;
|
if (names[name]) continue;
|
||||||
holes.splice(i, 1);
|
holes.splice(i, 1);
|
||||||
scope.names_in_use[name] = true;
|
in_use[name] = true;
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -364,7 +438,7 @@ function next_mangled_name(scope, options, def) {
|
|||||||
if (!names[name]) break;
|
if (!names[name]) break;
|
||||||
holes.push(scope.cname);
|
holes.push(scope.cname);
|
||||||
}
|
}
|
||||||
scope.names_in_use[name] = true;
|
in_use[name] = true;
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,18 +450,10 @@ AST_Symbol.DEFMETHOD("unmangleable", function(options) {
|
|||||||
// labels are always mangleable
|
// labels are always mangleable
|
||||||
AST_Label.DEFMETHOD("unmangleable", return_false);
|
AST_Label.DEFMETHOD("unmangleable", return_false);
|
||||||
|
|
||||||
AST_Symbol.DEFMETHOD("unreferenced", function() {
|
|
||||||
return !this.definition().references.length && !this.scope.pinned();
|
|
||||||
});
|
|
||||||
|
|
||||||
AST_Symbol.DEFMETHOD("definition", function() {
|
AST_Symbol.DEFMETHOD("definition", function() {
|
||||||
return this.thedef;
|
return this.thedef;
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Symbol.DEFMETHOD("global", function() {
|
|
||||||
return this.definition().global;
|
|
||||||
});
|
|
||||||
|
|
||||||
function _default_mangler_options(options) {
|
function _default_mangler_options(options) {
|
||||||
options = defaults(options, {
|
options = defaults(options, {
|
||||||
eval : false,
|
eval : false,
|
||||||
@@ -413,7 +479,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
var lname = -1;
|
var lname = -1;
|
||||||
|
|
||||||
if (options.cache && options.cache.props) {
|
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) {
|
options.cache.props.each(function(mangled_name) {
|
||||||
mangled_names[mangled_name] = true;
|
mangled_names[mangled_name] = true;
|
||||||
});
|
});
|
||||||
@@ -428,7 +494,11 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
lname = save_nesting;
|
lname = save_nesting;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Scope) {
|
if (node instanceof AST_BlockScope) {
|
||||||
|
var to_mangle = [];
|
||||||
|
node.variables.each(function(def) {
|
||||||
|
if (!defer_redef(def)) to_mangle.push(def);
|
||||||
|
});
|
||||||
descend();
|
descend();
|
||||||
if (options.cache && node instanceof AST_Toplevel) {
|
if (options.cache && node instanceof AST_Toplevel) {
|
||||||
node.globals.each(mangle);
|
node.globals.each(mangle);
|
||||||
@@ -438,9 +508,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
sym.scope = node;
|
sym.scope = node;
|
||||||
sym.reference(options);
|
sym.reference(options);
|
||||||
}
|
}
|
||||||
node.variables.each(function(def) {
|
to_mangle.forEach(mangle);
|
||||||
if (!defer_redef(def)) mangle(def);
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Label) {
|
if (node instanceof AST_Label) {
|
||||||
@@ -451,13 +519,6 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
node.mangled_name = name;
|
node.mangled_name = name;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!options.ie8 && node instanceof AST_Catch) {
|
|
||||||
var def = node.argname.definition();
|
|
||||||
var redef = defer_redef(def, node.argname);
|
|
||||||
descend();
|
|
||||||
if (!redef) mangle(def);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
this.walk(tw);
|
this.walk(tw);
|
||||||
redefined.forEach(mangle);
|
redefined.forEach(mangle);
|
||||||
@@ -472,7 +533,8 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
if (!redef) return false;
|
if (!redef) return false;
|
||||||
redefined.push(def);
|
redefined.push(def);
|
||||||
def.references.forEach(reference);
|
def.references.forEach(reference);
|
||||||
if (node) reference(node);
|
var node = def.orig[0];
|
||||||
|
if (node instanceof AST_SymbolCatch || node instanceof AST_SymbolConst) reference(node);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
function reference(sym) {
|
function reference(sym) {
|
||||||
@@ -485,12 +547,11 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
|
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
|
||||||
var cache = options.cache && options.cache.props;
|
var cache = options.cache && options.cache.props;
|
||||||
var avoid = Object.create(null);
|
var avoid = Object.create(RESERVED_WORDS);
|
||||||
options.reserved.forEach(to_avoid);
|
options.reserved.forEach(to_avoid);
|
||||||
this.globals.each(add_def);
|
this.globals.each(add_def);
|
||||||
this.walk(new TreeWalker(function(node) {
|
this.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_Scope) node.variables.each(add_def);
|
if (node instanceof AST_BlockScope) node.variables.each(add_def);
|
||||||
if (node instanceof AST_SymbolCatch) add_def(node.definition());
|
|
||||||
}));
|
}));
|
||||||
return avoid;
|
return avoid;
|
||||||
|
|
||||||
@@ -514,15 +575,14 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
|||||||
var cname = 0;
|
var cname = 0;
|
||||||
this.globals.each(rename);
|
this.globals.each(rename);
|
||||||
this.walk(new TreeWalker(function(node) {
|
this.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_Scope) node.variables.each(rename);
|
if (node instanceof AST_BlockScope) node.variables.each(rename);
|
||||||
if (node instanceof AST_SymbolCatch) rename(node.definition());
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function next_name() {
|
function next_name() {
|
||||||
var name;
|
var name;
|
||||||
do {
|
do {
|
||||||
name = base54(cname++);
|
name = base54(cname++);
|
||||||
} while (avoid[name] || RESERVED_WORDS[name]);
|
} while (avoid[name]);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,11 +593,8 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
|||||||
var redef = def.redefined();
|
var redef = def.redefined();
|
||||||
var name = redef ? redef.rename || redef.name : next_name();
|
var name = redef ? redef.rename || redef.name : next_name();
|
||||||
def.rename = name;
|
def.rename = name;
|
||||||
def.orig.forEach(function(sym) {
|
def.forEach(function(sym) {
|
||||||
sym.name = name;
|
if (sym.definition() === def) sym.name = name;
|
||||||
});
|
|
||||||
def.references.forEach(function(sym) {
|
|
||||||
sym.name = name;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -550,22 +607,24 @@ AST_Sequence.DEFMETHOD("tail_node", function() {
|
|||||||
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
|
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
|
||||||
options = _default_mangler_options(options);
|
options = _default_mangler_options(options);
|
||||||
base54.reset();
|
base54.reset();
|
||||||
|
var fn = AST_Symbol.prototype.add_source_map;
|
||||||
try {
|
try {
|
||||||
AST_Node.prototype.print = function(stream, force_parens) {
|
AST_Symbol.prototype.add_source_map = function() {
|
||||||
this._print(stream, force_parens);
|
if (!this.unmangleable(options)) base54.consider(this.name, -1);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
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);
|
base54.consider(this.print_to_string(), 1);
|
||||||
} finally {
|
} 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();
|
base54.sort();
|
||||||
|
|
||||||
|
|||||||
185
lib/sourcemap.js
185
lib/sourcemap.js
@@ -1,7 +1,7 @@
|
|||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
||||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||||
https://github.com/mishoo/UglifyJS2
|
https://github.com/mishoo/UglifyJS
|
||||||
|
|
||||||
-------------------------------- (C) ---------------------------------
|
-------------------------------- (C) ---------------------------------
|
||||||
|
|
||||||
@@ -43,62 +43,149 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// a small wrapper around fitzgen's source-map library
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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) {
|
function SourceMap(options) {
|
||||||
options = defaults(options, {
|
var sources = create_array_map();
|
||||||
file: null,
|
var sources_content = options.includeSources && Object.create(null);
|
||||||
root: null,
|
var names = create_array_map();
|
||||||
orig: null,
|
var mappings = "";
|
||||||
orig_line_diff: 0,
|
if (options.orig) Object.keys(options.orig).forEach(function(name) {
|
||||||
dest_line_diff: 0,
|
var map = options.orig[name];
|
||||||
}, true);
|
var indices = [ 0, 0, 1, 0, 0 ];
|
||||||
var generator = new MOZ_SourceMap.SourceMapGenerator({
|
options.orig[name] = {
|
||||||
file: options.file,
|
names: map.names,
|
||||||
sourceRoot: options.root
|
mappings: map.mappings.split(/;/).map(function(line) {
|
||||||
|
indices[0] = 0;
|
||||||
|
return line.split(/,/).map(function(segment) {
|
||||||
|
return indices.slice(0, vlq_decode(indices, segment));
|
||||||
});
|
});
|
||||||
var maps = options.orig && Object.create(null);
|
}),
|
||||||
if (maps) for (var source in options.orig) {
|
sources: map.sources,
|
||||||
var map = new MOZ_SourceMap.SourceMapConsumer(options.orig[source]);
|
};
|
||||||
if (Array.isArray(options.orig[source].sources)) {
|
if (!sources_content || !map.sourcesContent) return;
|
||||||
map._sources.toArray().forEach(function(source) {
|
for (var i = 0; i < map.sources.length; i++) {
|
||||||
var sourceContent = map.sourceContentFor(source, true);
|
var content = map.sourcesContent[i];
|
||||||
if (sourceContent) generator.setSourceContent(source, sourceContent);
|
if (content) sources_content[map.sources[i]] = content;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
var prev_source;
|
||||||
maps[source] = map;
|
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 {
|
return {
|
||||||
add: function(source, gen_line, gen_col, orig_line, orig_col, name) {
|
add: options.orig ? function(source, gen_line, gen_col, orig_line, orig_col, name) {
|
||||||
var map = maps && maps[source];
|
var map = options.orig[source];
|
||||||
if (map) {
|
if (map) {
|
||||||
var info = map.originalPositionFor({
|
var segments = map.mappings[orig_line - 1];
|
||||||
line: orig_line,
|
if (!segments) return;
|
||||||
column: orig_col
|
var indices;
|
||||||
});
|
for (var i = 0; i < segments.length; i++) {
|
||||||
if (info.source === null) return;
|
var col = segments[i][0];
|
||||||
source = info.source;
|
if (orig_col >= col) indices = segments[i];
|
||||||
orig_line = info.line;
|
if (orig_col <= col) break;
|
||||||
orig_col = info.column;
|
|
||||||
name = info.name || name;
|
|
||||||
}
|
}
|
||||||
generator.addMapping({
|
if (!indices || indices.length < 4) {
|
||||||
name: name,
|
source = null;
|
||||||
source: source,
|
} else {
|
||||||
generated: {
|
source = map.sources[indices[1]];
|
||||||
line: gen_line + options.dest_line_diff,
|
orig_line = indices[2];
|
||||||
column: gen_col
|
orig_col = indices[3];
|
||||||
},
|
if (indices.length > 4) name = map.names[indices[4]];
|
||||||
original: {
|
|
||||||
line: orig_line + options.orig_line_diff,
|
|
||||||
column: orig_col
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
},
|
add(source, gen_line, gen_col, orig_line, orig_col, name);
|
||||||
get: function() {
|
} : add,
|
||||||
return generator;
|
setSourceContent: sources_content ? function(source, content) {
|
||||||
},
|
sources_content[source] = content;
|
||||||
|
} : noop,
|
||||||
toString: function() {
|
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.
|
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||||
https://github.com/mishoo/UglifyJS2
|
https://github.com/mishoo/UglifyJS
|
||||||
|
|
||||||
-------------------------------- (C) ---------------------------------
|
-------------------------------- (C) ---------------------------------
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ TreeTransformer.prototype = new TreeWalker;
|
|||||||
if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
|
if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
|
||||||
});
|
});
|
||||||
DEF(AST_Catch, function(self, tw) {
|
DEF(AST_Catch, function(self, tw) {
|
||||||
self.argname = self.argname.transform(tw);
|
if (self.argname) self.argname = self.argname.transform(tw);
|
||||||
self.body = do_list(self.body, tw);
|
self.body = do_list(self.body, tw);
|
||||||
});
|
});
|
||||||
DEF(AST_Definitions, function(self, tw) {
|
DEF(AST_Definitions, function(self, tw) {
|
||||||
|
|||||||
69
lib/utils.js
69
lib/utils.js
@@ -1,7 +1,7 @@
|
|||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
||||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||||
https://github.com/mishoo/UglifyJS2
|
https://github.com/mishoo/UglifyJS
|
||||||
|
|
||||||
-------------------------------- (C) ---------------------------------
|
-------------------------------- (C) ---------------------------------
|
||||||
|
|
||||||
@@ -87,15 +87,13 @@ DefaultsError.prototype.name = "DefaultsError";
|
|||||||
configure_error_stack(DefaultsError);
|
configure_error_stack(DefaultsError);
|
||||||
|
|
||||||
function defaults(args, defs, croak) {
|
function defaults(args, defs, croak) {
|
||||||
if (args === true) args = {};
|
if (croak) for (var i in args) {
|
||||||
var ret = args || {};
|
if (HOP(args, i) && !HOP(defs, i)) throw new DefaultsError("`" + i + "` is not a supported option", defs);
|
||||||
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
|
|
||||||
throw new DefaultsError("`" + i + "` is not a supported option", defs);
|
|
||||||
}
|
}
|
||||||
for (var i in defs) if (HOP(defs, i)) {
|
for (var i in args) {
|
||||||
ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
|
if (HOP(args, i)) defs[i] = args[i];
|
||||||
}
|
}
|
||||||
return ret;
|
return defs;
|
||||||
}
|
}
|
||||||
|
|
||||||
function merge(obj, ext) {
|
function merge(obj, ext) {
|
||||||
@@ -114,48 +112,29 @@ function return_this() { return this; }
|
|||||||
function return_null() { return null; }
|
function return_null() { return null; }
|
||||||
|
|
||||||
var List = (function() {
|
var List = (function() {
|
||||||
function List(a, f, backwards) {
|
function List(a, f) {
|
||||||
var ret = [], top = [], i;
|
var ret = [];
|
||||||
function doit() {
|
for (var i = 0; i < a.length; i++) {
|
||||||
var val = f(a[i], i);
|
var val = f(a[i], i);
|
||||||
var is_last = val instanceof Last;
|
if (val === skip) continue;
|
||||||
if (is_last) val = val.v;
|
|
||||||
if (val instanceof AtTop) {
|
|
||||||
val = val.v;
|
|
||||||
if (val instanceof Splice) {
|
if (val instanceof Splice) {
|
||||||
top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
|
ret.push.apply(ret, 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 {
|
} else {
|
||||||
ret.push(val);
|
ret.push(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return is_last;
|
return ret;
|
||||||
}
|
}
|
||||||
if (Array.isArray(a)) {
|
List.is_op = function(val) {
|
||||||
if (backwards) {
|
return val === skip || val instanceof Splice;
|
||||||
for (i = a.length; --i >= 0;) if (doit()) break;
|
};
|
||||||
ret.reverse();
|
List.splice = function(val) {
|
||||||
top.reverse();
|
return new Splice(val);
|
||||||
} else {
|
};
|
||||||
for (i = 0; i < a.length; ++i) if (doit()) break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (i in a) if (HOP(a, i)) if (doit()) break;
|
|
||||||
}
|
|
||||||
return top.concat(ret);
|
|
||||||
}
|
|
||||||
List.at_top = function(val) { return new AtTop(val); };
|
|
||||||
List.splice = function(val) { return new Splice(val); };
|
|
||||||
List.last = function(val) { return new Last(val); };
|
|
||||||
var skip = List.skip = {};
|
var skip = List.skip = {};
|
||||||
function AtTop(val) { this.v = val; }
|
function Splice(val) {
|
||||||
function Splice(val) { this.v = val; }
|
this.v = val;
|
||||||
function Last(val) { this.v = val; }
|
}
|
||||||
return List;
|
return List;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
@@ -217,6 +196,12 @@ Dictionary.prototype = {
|
|||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
has: function(key) { return ("$" + key) in this._values },
|
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) {
|
each: function(f) {
|
||||||
for (var i in this._values)
|
for (var i in this._values)
|
||||||
f(this._values[i], i.substr(1));
|
f(this._values[i], i.substr(1));
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.8.1",
|
"version": "3.11.4",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
"Alex Lam <alexlamsl@gmail.com>",
|
"Alex Lam <alexlamsl@gmail.com>",
|
||||||
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
|
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
|
||||||
],
|
],
|
||||||
"repository": "mishoo/UglifyJS2",
|
"repository": "mishoo/UglifyJS",
|
||||||
"main": "tools/node.js",
|
"main": "tools/node.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
"uglifyjs": "bin/uglifyjs"
|
"uglifyjs": "bin/uglifyjs"
|
||||||
@@ -22,10 +22,6 @@
|
|||||||
"tools",
|
"tools",
|
||||||
"LICENSE"
|
"LICENSE"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
|
||||||
"commander": "~2.20.3",
|
|
||||||
"source-map": "~0.6.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"acorn": "~7.1.0",
|
"acorn": "~7.1.0",
|
||||||
"semver": "~6.3.0"
|
"semver": "~6.3.0"
|
||||||
|
|||||||
@@ -5,12 +5,11 @@
|
|||||||
|
|
||||||
var createHash = require("crypto").createHash;
|
var createHash = require("crypto").createHash;
|
||||||
var fetch = require("./fetch");
|
var fetch = require("./fetch");
|
||||||
var fork = require("child_process").fork;
|
var spawn = require("child_process").spawn;
|
||||||
var zlib = require("zlib");
|
var zlib = require("zlib");
|
||||||
var args = process.argv.slice(2);
|
var args = process.argv.slice(2);
|
||||||
if (!args.length) {
|
if (!args.length) args.push("-mc");
|
||||||
args.push("-mc");
|
args.unshift("bin/uglifyjs");
|
||||||
}
|
|
||||||
args.push("--timings");
|
args.push("--timings");
|
||||||
var urls = [
|
var urls = [
|
||||||
"https://code.jquery.com/jquery-3.4.1.js",
|
"https://code.jquery.com/jquery-3.4.1.js",
|
||||||
@@ -70,18 +69,20 @@ urls.forEach(function(url) {
|
|||||||
};
|
};
|
||||||
fetch(url, function(err, res) {
|
fetch(url, function(err, res) {
|
||||||
if (err) throw err;
|
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) {
|
res.on("data", function(data) {
|
||||||
results[url].input += data.length;
|
results[url].input += data.length;
|
||||||
}).pipe(uglifyjs.stdin);
|
}).pipe(uglifyjs.stdin);
|
||||||
|
var sha1 = createHash("sha1");
|
||||||
uglifyjs.stdout.on("data", function(data) {
|
uglifyjs.stdout.on("data", function(data) {
|
||||||
results[url].output += data.length;
|
results[url].output += data.length;
|
||||||
}).pipe(zlib.createGzip({
|
}).pipe(zlib.createGzip({
|
||||||
level: zlib.Z_BEST_COMPRESSION
|
level: zlib.Z_BEST_COMPRESSION
|
||||||
})).on("data", function(data) {
|
})).on("data", function(data) {
|
||||||
results[url].gzip += data.length;
|
results[url].gzip += data.length;
|
||||||
}).pipe(createHash("sha1")).on("data", function(data) {
|
sha1.update(data);
|
||||||
results[url].sha1 = data.toString("hex");
|
}).on("end", function() {
|
||||||
|
results[url].sha1 = sha1.digest("hex");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
uglifyjs.stderr.setEncoding("utf8");
|
uglifyjs.stderr.setEncoding("utf8");
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ function make_code(ast, options) {
|
|||||||
|
|
||||||
function parse_test(file) {
|
function parse_test(file) {
|
||||||
var script = fs.readFileSync(file, "utf8");
|
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 {
|
try {
|
||||||
var ast = U.parse(script, {
|
var ast = U.parse(script, {
|
||||||
filename: file
|
filename: file
|
||||||
@@ -188,6 +188,7 @@ function reminify(orig_options, input_code, input_formatted, stdout) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
var options_formatted = JSON.stringify(options, null, 4);
|
var options_formatted = JSON.stringify(options, null, 4);
|
||||||
|
options.validate = true;
|
||||||
var result = U.minify(input_code, options);
|
var result = U.minify(input_code, options);
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
log([
|
log([
|
||||||
@@ -251,6 +252,7 @@ function run_code(code, toplevel) {
|
|||||||
|
|
||||||
function test_case(test) {
|
function test_case(test) {
|
||||||
log(" Running test [{name}]", { name: test.name });
|
log(" Running test [{name}]", { name: test.name });
|
||||||
|
U.AST_Node.enable_validation();
|
||||||
var output_options = test.beautify || {};
|
var output_options = test.beautify || {};
|
||||||
var expect;
|
var expect;
|
||||||
if (test.expect) {
|
if (test.expect) {
|
||||||
@@ -267,6 +269,7 @@ function test_case(test) {
|
|||||||
quote_style: 3,
|
quote_style: 3,
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
|
input.validate_ast();
|
||||||
U.parse(input_code);
|
U.parse(input_code);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
log([
|
log([
|
||||||
@@ -309,12 +312,10 @@ function test_case(test) {
|
|||||||
if (test.mangle) {
|
if (test.mangle) {
|
||||||
output.compute_char_frequency(test.mangle);
|
output.compute_char_frequency(test.mangle);
|
||||||
output.mangle_names(test.mangle);
|
output.mangle_names(test.mangle);
|
||||||
if (test.mangle.properties) {
|
if (test.mangle.properties) U.mangle_properties(output, test.mangle.properties);
|
||||||
output = U.mangle_properties(output, test.mangle.properties);
|
|
||||||
}
|
}
|
||||||
}
|
var output_code = make_code(output, output_options);
|
||||||
output = make_code(output, output_options);
|
if (expect != output_code) {
|
||||||
if (expect != output) {
|
|
||||||
log([
|
log([
|
||||||
"!!! failed",
|
"!!! failed",
|
||||||
"---INPUT---",
|
"---INPUT---",
|
||||||
@@ -327,14 +328,15 @@ function test_case(test) {
|
|||||||
"",
|
"",
|
||||||
].join("\n"), {
|
].join("\n"), {
|
||||||
input: input_formatted,
|
input: input_formatted,
|
||||||
output: output,
|
output: output_code,
|
||||||
expected: expect
|
expected: expect
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// expect == output
|
// expect == output
|
||||||
try {
|
try {
|
||||||
U.parse(output);
|
output.validate_ast();
|
||||||
|
U.parse(output_code);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
log([
|
log([
|
||||||
"!!! Test matched expected result but cannot parse output",
|
"!!! Test matched expected result but cannot parse output",
|
||||||
@@ -348,7 +350,7 @@ function test_case(test) {
|
|||||||
"",
|
"",
|
||||||
].join("\n"), {
|
].join("\n"), {
|
||||||
input: input_formatted,
|
input: input_formatted,
|
||||||
output: output,
|
output: output_code,
|
||||||
error: ex,
|
error: ex,
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
@@ -407,7 +409,7 @@ function test_case(test) {
|
|||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
actual = run_code(output, toplevel);
|
actual = run_code(output_code, toplevel);
|
||||||
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
|
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
|
||||||
log([
|
log([
|
||||||
"!!! failed",
|
"!!! failed",
|
||||||
|
|||||||
@@ -243,20 +243,18 @@ issue_3273: {
|
|||||||
arguments: true,
|
arguments: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(a, a);
|
console.log(a, a);
|
||||||
a++;
|
a++;
|
||||||
console.log(a, a);
|
console.log(a, a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"0 0",
|
"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: {
|
issue_3273_reduce_vars: {
|
||||||
options = {
|
options = {
|
||||||
arguments: true,
|
arguments: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(a, a);
|
console.log(a, a);
|
||||||
a++;
|
a++;
|
||||||
console.log(a, a);
|
console.log(a, a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"0 0",
|
"0 0",
|
||||||
@@ -296,22 +311,20 @@ issue_3273_local_strict: {
|
|||||||
arguments: true,
|
arguments: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
"use strict";
|
"use strict";
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
"use strict";
|
"use strict";
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"0 0",
|
"0 0",
|
||||||
@@ -325,22 +338,20 @@ issue_3273_local_strict_reduce_vars: {
|
|||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
"use strict";
|
"use strict";
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
"use strict";
|
"use strict";
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"0 0",
|
"0 0",
|
||||||
@@ -354,21 +365,19 @@ issue_3273_global_strict: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
"use strict";
|
"use strict";
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
"use strict";
|
"use strict";
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"0 0",
|
"0 0",
|
||||||
@@ -383,21 +392,19 @@ issue_3273_global_strict_reduce_vars: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
"use strict";
|
"use strict";
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
"use strict";
|
"use strict";
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"0 0",
|
"0 0",
|
||||||
@@ -776,3 +783,27 @@ issue_3420_7: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "true"
|
expect_stdout: "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4200: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {
|
||||||
|
get p() {
|
||||||
|
return arguments[0];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
console.log(o.p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
get p() {
|
||||||
|
return arguments[0];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
console.log(o.p);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
ascii_only_true: {
|
|
||||||
options = {}
|
|
||||||
beautify = {
|
|
||||||
ascii_only : true,
|
|
||||||
ie8 : false,
|
|
||||||
beautify : false,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
function f() {
|
|
||||||
return "\x000\x001\x007\x008\x00" +
|
|
||||||
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
|
|
||||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
|
|
||||||
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\0"+"\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\v\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}'
|
|
||||||
}
|
|
||||||
|
|
||||||
ascii_only_false: {
|
|
||||||
options = {}
|
|
||||||
beautify = {
|
|
||||||
ascii_only : false,
|
|
||||||
ie8 : false,
|
|
||||||
beautify : false,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
function f() {
|
|
||||||
return "\x000\x001\x007\x008\x00" +
|
|
||||||
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
|
|
||||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
|
|
||||||
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\0"+"\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
|
|
||||||
}
|
|
||||||
@@ -76,9 +76,8 @@ asm_mixed: {
|
|||||||
start = start | 0;
|
start = start | 0;
|
||||||
end = end | 0;
|
end = end | 0;
|
||||||
var sum = 0.0, p = 0, q = 0;
|
var sum = 0.0, p = 0, q = 0;
|
||||||
for (p = start << 3, q = end << 3; (p | 0) < (q | 0); p = p + 8 | 0) {
|
for (p = start << 3, q = end << 3; (p | 0) < (q | 0); p = p + 8 | 0)
|
||||||
sum = sum + +log(values[p >> 3]);
|
sum = sum + +log(values[p >> 3]);
|
||||||
}
|
|
||||||
return +sum;
|
return +sum;
|
||||||
}
|
}
|
||||||
function geometricMean(start, end) {
|
function geometricMean(start, end) {
|
||||||
@@ -91,12 +90,12 @@ asm_mixed: {
|
|||||||
function no_asm_GeometricMean(stdlib, foreign, buffer) {
|
function no_asm_GeometricMean(stdlib, foreign, buffer) {
|
||||||
function logSum(start, end) {
|
function logSum(start, end) {
|
||||||
start |= 0, end |= 0;
|
start |= 0, end |= 0;
|
||||||
var sum = 0, p = 0, q = 0;
|
for (var sum = 0, p = 0, q = 0, p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0)
|
||||||
for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
|
sum += +log(values[p >> 3]);
|
||||||
return +sum;
|
return +sum;
|
||||||
}
|
}
|
||||||
function geometricMean(start, end) {
|
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);
|
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
|
||||||
return { geometricMean: geometricMean };
|
return { geometricMean: geometricMean };
|
||||||
|
|||||||
@@ -407,3 +407,57 @@ issue_3429_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
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"
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -93,6 +93,59 @@ self_comparison_2: {
|
|||||||
expect_stdout: "false true"
|
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: {
|
issue_2857_1: {
|
||||||
options = {
|
options = {
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
|
|||||||
@@ -238,6 +238,41 @@ concat_8: {
|
|||||||
expect_stdout: true
|
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: {
|
issue_3689: {
|
||||||
options = {
|
options = {
|
||||||
strings: true,
|
strings: true,
|
||||||
|
|||||||
@@ -55,14 +55,15 @@ ifs_3_should_warn: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x, y;
|
var x, y;
|
||||||
if (x && !(x + "1") && y) { // 1
|
// 1
|
||||||
|
if (x && !(x + "1") && y) {
|
||||||
var qq;
|
var qq;
|
||||||
foo();
|
foo();
|
||||||
} else {
|
} else {
|
||||||
bar();
|
bar();
|
||||||
}
|
}
|
||||||
|
// 2
|
||||||
if (x || !!(x + "1") || y) { // 2
|
if (x || !!(x + "1") || y) {
|
||||||
foo();
|
foo();
|
||||||
} else {
|
} else {
|
||||||
var jj;
|
var jj;
|
||||||
@@ -71,9 +72,27 @@ ifs_3_should_warn: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x, y;
|
var x, y;
|
||||||
var qq; bar(); // 1
|
// 1
|
||||||
var jj; foo(); // 2
|
var qq; bar();
|
||||||
|
// 2
|
||||||
|
foo(); var jj;
|
||||||
}
|
}
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: + in boolean context always true [test/compress/conditionals.js:3,18]",
|
||||||
|
"WARN: Boolean && always false [test/compress/conditionals.js:3,12]",
|
||||||
|
"WARN: Condition left of && always false [test/compress/conditionals.js:3,12]",
|
||||||
|
"WARN: Condition always false [test/compress/conditionals.js:3,12]",
|
||||||
|
"WARN: Dropping unreachable code [test/compress/conditionals.js:3,34]",
|
||||||
|
"WARN: Declarations in unreachable code! [test/compress/conditionals.js:4,12]",
|
||||||
|
"WARN: + in boolean context always true [test/compress/conditionals.js:10,19]",
|
||||||
|
"WARN: Boolean || always true [test/compress/conditionals.js:10,12]",
|
||||||
|
"WARN: Condition left of || always true [test/compress/conditionals.js:10,12]",
|
||||||
|
"WARN: Condition always true [test/compress/conditionals.js:10,12]",
|
||||||
|
"WARN: Dropping unreachable code [test/compress/conditionals.js:12,15]",
|
||||||
|
"WARN: Declarations in unreachable code! [test/compress/conditionals.js:13,12]",
|
||||||
|
"WARN: Dropping side-effect-free statement [test/compress/conditionals.js:3,12]",
|
||||||
|
"WARN: Dropping side-effect-free statement [test/compress/conditionals.js:10,12]",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
ifs_4: {
|
ifs_4: {
|
||||||
@@ -783,6 +802,28 @@ cond_12: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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: {
|
ternary_boolean_consequent: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
@@ -1137,7 +1178,7 @@ issue_1645_2: {
|
|||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
condition_symbol_matches_consequent: {
|
condition_matches_consequent: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
}
|
}
|
||||||
@@ -1166,6 +1207,35 @@ condition_symbol_matches_consequent: {
|
|||||||
expect_stdout: "3 7 true 4"
|
expect_stdout: "3 7 true 4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
condition_matches_alternative: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo(x, y) {
|
||||||
|
return x.p ? y[0] : x.p;
|
||||||
|
}
|
||||||
|
function bar() {
|
||||||
|
return g ? h : g;
|
||||||
|
}
|
||||||
|
var g = 4;
|
||||||
|
var h = 5;
|
||||||
|
console.log(foo({ p: 3 }, [ null ]), foo({ p: 0 }, [ 7 ]), foo({ p: true } , [ false ]), bar());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo(x, y) {
|
||||||
|
return x.p && y[0];
|
||||||
|
}
|
||||||
|
function bar() {
|
||||||
|
return g && h;
|
||||||
|
}
|
||||||
|
var g = 4;
|
||||||
|
var h = 5;
|
||||||
|
console.log(foo({ p: 3 }, [ null ]), foo({ p: 0 }, [ 7 ]), foo({ p: true } , [ false ]), bar());
|
||||||
|
}
|
||||||
|
expect_stdout: "null 0 false 5"
|
||||||
|
}
|
||||||
|
|
||||||
delete_conditional_1: {
|
delete_conditional_1: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
@@ -1384,7 +1454,7 @@ hoist_decl: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a, b;
|
var a, b;
|
||||||
x() ? y() : z();
|
(x() ? y : z)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1666,3 +1736,130 @@ issue_3668: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
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"
|
||||||
|
}
|
||||||
|
|||||||
1086
test/compress/const.js
Normal file
1086
test/compress/const.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -59,6 +59,11 @@ dead_code_2_should_warn: {
|
|||||||
f();
|
f();
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: Dropping unreachable code [test/compress/dead-code.js:8,12]",
|
||||||
|
"WARN: Declarations in unreachable code! [test/compress/dead-code.js:10,16]",
|
||||||
|
"WARN: Dropping unreachable code [test/compress/dead-code.js:10,16]",
|
||||||
|
]
|
||||||
node_version: "<=4"
|
node_version: "<=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,14 +94,86 @@ dead_code_constant_boolean_should_warn_more: {
|
|||||||
function bar() {}
|
function bar() {}
|
||||||
// nothing for the while
|
// nothing for the while
|
||||||
// as for the for, it should keep:
|
// as for the for, it should keep:
|
||||||
var moo;
|
|
||||||
var x = 10, y;
|
var x = 10, y;
|
||||||
|
var moo;
|
||||||
bar();
|
bar();
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: + in boolean context always true [test/compress/dead-code.js:1,33]",
|
||||||
|
"WARN: Boolean || always true [test/compress/dead-code.js:1,16]",
|
||||||
|
"WARN: Dropping unreachable code [test/compress/dead-code.js:1,45]",
|
||||||
|
"WARN: Declarations in unreachable code! [test/compress/dead-code.js:3,12]",
|
||||||
|
"WARN: Boolean expression always true [test/compress/dead-code.js:6,47]",
|
||||||
|
"WARN: Boolean && always false [test/compress/dead-code.js:6,28]",
|
||||||
|
"WARN: Dropping unreachable code [test/compress/dead-code.js:6,63]",
|
||||||
|
"WARN: Declarations in unreachable code! [test/compress/dead-code.js:9,12]",
|
||||||
|
"WARN: Dropping side-effect-free statement [test/compress/dead-code.js:1,15]",
|
||||||
|
"WARN: Dropping side-effect-free statement [test/compress/dead-code.js:6,28]",
|
||||||
|
]
|
||||||
node_version: "<=4"
|
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: {
|
try_catch_finally: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
@@ -130,10 +207,7 @@ try_catch_finally: {
|
|||||||
a = 3;
|
a = 3;
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
}();
|
}();
|
||||||
try {
|
|
||||||
console.log(a);
|
console.log(a);
|
||||||
} finally {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"PASS",
|
"PASS",
|
||||||
@@ -179,7 +253,7 @@ collapse_vars_lvalues_drop_assign: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse_vars_misc1: {
|
collapse_vars_misc: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
@@ -892,3 +966,416 @@ issue_3578: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
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: {
|
drop_lone_use_strict: {
|
||||||
options = {
|
options = {
|
||||||
directives: true,
|
directives: true,
|
||||||
side_effects: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f1() {
|
function f1() {
|
||||||
@@ -66,10 +66,8 @@ drop_lone_use_strict: {
|
|||||||
function f1() {
|
function f1() {
|
||||||
}
|
}
|
||||||
function f2() {
|
function f2() {
|
||||||
"use strict";
|
|
||||||
function f3() {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
(function() {})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1730,7 +1730,7 @@ chained_3: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(function(a, b) {
|
console.log(function(a, b) {
|
||||||
var c = b;
|
var c = b;
|
||||||
b++;
|
+b;
|
||||||
return c;
|
return c;
|
||||||
}(0, 2));
|
}(0, 2));
|
||||||
}
|
}
|
||||||
@@ -1997,7 +1997,7 @@ issue_3146_4: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3192: {
|
issue_3192_1: {
|
||||||
options = {
|
options = {
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2025,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: {
|
issue_3233: {
|
||||||
options = {
|
options = {
|
||||||
pure_getters: "strict",
|
pure_getters: "strict",
|
||||||
@@ -2161,8 +2181,7 @@ issue_3515_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
var c = 0;
|
var c = 0;
|
||||||
(function() {
|
(function() {
|
||||||
this[c++] = 0;
|
for (var key20 in !(this[c++] = 0));
|
||||||
for (var key20 in !0);
|
|
||||||
})();
|
})();
|
||||||
console.log(c);
|
console.log(c);
|
||||||
}
|
}
|
||||||
@@ -2285,7 +2304,7 @@ issue_3598: {
|
|||||||
try {
|
try {
|
||||||
(function() {
|
(function() {
|
||||||
a = "PASS";
|
a = "PASS";
|
||||||
var c = (void (c.p = 0))[!1];
|
(void ((void 0).p = 0))[!1];
|
||||||
})();
|
})();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
console.log(a);
|
console.log(a);
|
||||||
@@ -2366,7 +2385,7 @@ function_parameter_ie8: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function() {
|
(function() {
|
||||||
(function f() {
|
(function() {
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
})();
|
})();
|
||||||
})();
|
})();
|
||||||
@@ -2444,3 +2463,652 @@ issue_3746: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "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"
|
||||||
|
}
|
||||||
|
|
||||||
|
var_catch_redefined: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
throw "PASS";
|
||||||
|
} catch (a) {
|
||||||
|
function f() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
throw "PASS";
|
||||||
|
} catch (a) {
|
||||||
|
function f() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
single_use_catch_redefined: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(g());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(g());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4184: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a = function() {}, b = [ a, 1 && b, a = {} ];
|
||||||
|
try {
|
||||||
|
throw 42;
|
||||||
|
} catch (a) {
|
||||||
|
{
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
var b = [ function() {}, 1 && b, {} ];
|
||||||
|
try {
|
||||||
|
throw 42;
|
||||||
|
} catch (a) {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4235: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
{
|
||||||
|
const f = 0;
|
||||||
|
}
|
||||||
|
(function f() {
|
||||||
|
var f = console.log(f);
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
f = console.log(f),
|
||||||
|
void 0;
|
||||||
|
var f;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|||||||
@@ -558,34 +558,51 @@ unsafe_array: {
|
|||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
var a = "PASS";
|
||||||
[1, , 3][1],
|
Array.prototype[1] = a;
|
||||||
[1, 2, 3, a] + 1,
|
console.log([, ].length);
|
||||||
[1, 2, 3, 4] + 1,
|
console.log("" + [, , ]);
|
||||||
[1, 2, 3, a][0] + 1,
|
console.log([1, , 3][1]);
|
||||||
[1, 2, 3, 4][0] + 1,
|
console.log([1, 2, 3, a] + 1);
|
||||||
[1, 2, 3, 4][6 - 5] + 1,
|
console.log([1, 2, 3, 4] + 1);
|
||||||
[1, , 3, 4][6 - 5] + 1,
|
console.log([1, 2, 3, a][0] + 1);
|
||||||
[[1, 2], [3, 4]][0] + 1,
|
console.log([1, 2, 3, 4][0] + 1);
|
||||||
[[1, 2], [3, 4]][6 - 5][1] + 1,
|
console.log([1, 2, 3, 4][6 - 5] + 1);
|
||||||
[[1, 2], , [3, 4]][6 - 5][1] + 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: {
|
expect: {
|
||||||
console.log(
|
var a = "PASS";
|
||||||
void 0,
|
Array.prototype[1] = a;
|
||||||
[1, 2, 3, a] + 1,
|
console.log([, ].length);
|
||||||
"1,2,3,41",
|
console.log("" + [, , ]);
|
||||||
[1, 2, 3, a][0] + 1,
|
console.log([1, , 3][1]);
|
||||||
2,
|
console.log([1, 2, 3, a] + 1);
|
||||||
3,
|
console.log("1,2,3,41");
|
||||||
NaN,
|
console.log([1, 2, 3, a][0] + 1);
|
||||||
"1,21",
|
console.log(2);
|
||||||
5,
|
console.log(3);
|
||||||
(void 0)[1] + 1
|
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: {
|
unsafe_string: {
|
||||||
@@ -1579,9 +1596,9 @@ issue_2968_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
var c = "FAIL";
|
var c = "FAIL";
|
||||||
(function() {
|
(function() {
|
||||||
b = -(a = 42),
|
a = 42,
|
||||||
void ((a <<= 0) && (a[(c = "PASS", 0 >>> (b += 1))] = 0));
|
void ((a <<= 0) && (a[(c = "PASS", 0)] = 0));
|
||||||
var a, b;
|
var a;
|
||||||
})();
|
})();
|
||||||
console.log(c);
|
console.log(c);
|
||||||
}
|
}
|
||||||
@@ -2174,3 +2191,859 @@ issue_3738: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "Infinity"
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4214: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
return function() {
|
||||||
|
try {
|
||||||
|
return a;
|
||||||
|
} finally {
|
||||||
|
var b = 0;
|
||||||
|
}
|
||||||
|
}(a++ && this());
|
||||||
|
}
|
||||||
|
var c = f();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = function(a) {
|
||||||
|
return function() {
|
||||||
|
try {
|
||||||
|
return a;
|
||||||
|
} finally {}
|
||||||
|
}(a++ && this());
|
||||||
|
}();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|||||||
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: {
|
keyword: {
|
||||||
options = {
|
options = {
|
||||||
global_defs: {
|
global_defs: {
|
||||||
|
|||||||
@@ -767,18 +767,17 @@ issue_3071_1: {
|
|||||||
var obj = {};
|
var obj = {};
|
||||||
obj.one = 1;
|
obj.one = 1;
|
||||||
obj.two = 2;
|
obj.two = 2;
|
||||||
console.log(obj.one);
|
console.log(obj.one, obj.two);
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(1);
|
console.log(1, 2);
|
||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1 2"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3071_2: {
|
issue_3071_2: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
|
||||||
hoist_props: true,
|
hoist_props: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
@@ -793,19 +792,18 @@ issue_3071_2: {
|
|||||||
obj = {};
|
obj = {};
|
||||||
obj.one = 1;
|
obj.one = 1;
|
||||||
obj.two = 2;
|
obj.two = 2;
|
||||||
console.log(obj.one);
|
console.log(obj.one, obj.two);
|
||||||
var obj;
|
var obj;
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(1);
|
console.log(1, 2);
|
||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1 2"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3071_2_toplevel: {
|
issue_3071_2_toplevel: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
|
||||||
hoist_props: true,
|
hoist_props: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
@@ -821,14 +819,14 @@ issue_3071_2_toplevel: {
|
|||||||
obj = {};
|
obj = {};
|
||||||
obj.one = 1;
|
obj.one = 1;
|
||||||
obj.two = 2;
|
obj.two = 2;
|
||||||
console.log(obj.one);
|
console.log(obj.one, obj.two);
|
||||||
var obj;
|
var obj;
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(1);
|
console.log(1, 2);
|
||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1 2"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3071_3: {
|
issue_3071_3: {
|
||||||
@@ -914,3 +912,132 @@ issue_3440: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
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"
|
||||||
|
}
|
||||||
|
|||||||
@@ -2223,13 +2223,13 @@ issue_3523_rename_ie8: {
|
|||||||
expect: {
|
expect: {
|
||||||
var a = 0, b, c = "FAIL";
|
var a = 0, b, c = "FAIL";
|
||||||
(function() {
|
(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 {
|
try {
|
||||||
throw 0;
|
throw 0;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
(function() {
|
(function() {
|
||||||
(function n() {
|
(function e() {
|
||||||
c = "PASS";
|
c = "PASS";
|
||||||
})();
|
})();
|
||||||
})();
|
})();
|
||||||
@@ -2389,7 +2389,7 @@ issue_3703: {
|
|||||||
var a = "PASS";
|
var a = "PASS";
|
||||||
(function() {
|
(function() {
|
||||||
var b;
|
var b;
|
||||||
var c = function g() {
|
var c = function() {
|
||||||
a = "FAIL";
|
a = "FAIL";
|
||||||
};
|
};
|
||||||
a ? b |= c : b.p;
|
a ? b |= c : b.p;
|
||||||
@@ -2420,3 +2420,460 @@ issue_3750: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "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"
|
||||||
|
}
|
||||||
|
|
||||||
|
single_use_catch_redefined: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(g());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(g());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
single_use_inline_catch_redefined: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(g());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(g());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
direct_inline_catch_redefined: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
function f() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(a, f(), g());
|
||||||
|
}
|
||||||
|
console.log(a, f(), g());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
function f() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(a, f(), g());
|
||||||
|
}
|
||||||
|
console.log(a, a, g());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4186: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
ie8: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
(function NaN() {
|
||||||
|
var a = 1;
|
||||||
|
while (a--)
|
||||||
|
try {} finally {
|
||||||
|
console.log(0/0);
|
||||||
|
var b;
|
||||||
|
}
|
||||||
|
})(f);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
NaN;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function NaN() {
|
||||||
|
var n = 1;
|
||||||
|
while (n--)
|
||||||
|
console.log(0/0);
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
NaN;
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4235: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {} catch (e) {}
|
||||||
|
console.log(function e() {
|
||||||
|
var e = 0;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {} catch (e) {}
|
||||||
|
console.log(function e() {}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|||||||
@@ -573,3 +573,178 @@ issue_3600: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iife_if_return_simple: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
inline: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
if (console)
|
||||||
|
return console.log("PASS");
|
||||||
|
console.log("FAIL");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console ? console.log("PASS") : console.log("FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
nested_if_break: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
L1: if ("number" == typeof i) {
|
||||||
|
if (0 === i) break L1;
|
||||||
|
console.log(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
L1: if ("number" == typeof i)
|
||||||
|
if (0 !== i) console.log(i);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
nested_if_continue: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
join_vars: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(n) {
|
||||||
|
var i = 0;
|
||||||
|
do {
|
||||||
|
if ("number" == typeof n) {
|
||||||
|
if (0 === n) {
|
||||||
|
console.log("even", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (1 === n) {
|
||||||
|
console.log("odd", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
} while (0 <= (n -= 2));
|
||||||
|
}
|
||||||
|
f(37);
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(n) {
|
||||||
|
for (var i = 0;
|
||||||
|
"number" == typeof n
|
||||||
|
&& (0 !== n
|
||||||
|
? 1 !== n
|
||||||
|
? i++
|
||||||
|
: console.log("odd", i)
|
||||||
|
: console.log("even", i)),
|
||||||
|
0 <= (n -= 2););
|
||||||
|
}
|
||||||
|
f(37);
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"odd 18",
|
||||||
|
"even 21",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
nested_if_return: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
if (A) {
|
||||||
|
if (B)
|
||||||
|
return B;
|
||||||
|
if (C)
|
||||||
|
return D;
|
||||||
|
if (E)
|
||||||
|
return F;
|
||||||
|
if (G)
|
||||||
|
return H;
|
||||||
|
if (I) {
|
||||||
|
if (J)
|
||||||
|
return K;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (L) {
|
||||||
|
if (M)
|
||||||
|
return;
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
if (A)
|
||||||
|
return B || (C ? D : E ? F : G ? H : I ? J ? K : void 0 : L && !M ? N : void 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_866_1: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
sequences: false,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
if (a)
|
||||||
|
return "";
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
if (a)
|
||||||
|
return "";
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_866_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
if (a)
|
||||||
|
if (b)
|
||||||
|
c;
|
||||||
|
else
|
||||||
|
return d;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
if (a) {
|
||||||
|
if (!b)
|
||||||
|
return d;
|
||||||
|
c;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -90,13 +90,13 @@ non_hoisted_function_after_return_2a: {
|
|||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
|
"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 variable a [test/compress/issue-1034.js:4,20]",
|
||||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]",
|
"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: 35",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
|
||||||
"WARN: Declarations in 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]",
|
"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 b [test/compress/issue-1034.js:7,20]",
|
||||||
"INFO: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
|
"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: 35, count: 18",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,13 +248,13 @@ non_hoisted_function_after_return_2a_strict: {
|
|||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,16]",
|
"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 variable a [test/compress/issue-1034.js:5,20]",
|
||||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:12,21]",
|
"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: 46",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
|
||||||
"WARN: Declarations in 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]",
|
"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 b [test/compress/issue-1034.js:8,20]",
|
||||||
"INFO: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
|
"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: 46, count: 29",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ multiple_functions: {
|
|||||||
( function() {
|
( function() {
|
||||||
// NOTE: other compression steps will reduce this
|
// NOTE: other compression steps will reduce this
|
||||||
// down to just `window`.
|
// down to just `window`.
|
||||||
if ( window );
|
if ( !window );
|
||||||
function f() {}
|
function f() {}
|
||||||
function g() {}
|
function g() {}
|
||||||
} )();
|
} )();
|
||||||
@@ -38,7 +38,7 @@ single_function: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
( function() {
|
( function() {
|
||||||
if ( window );
|
if ( !window );
|
||||||
function f() {}
|
function f() {}
|
||||||
} )();
|
} )();
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ deeply_nested: {
|
|||||||
// NOTE: other compression steps will reduce this
|
// NOTE: other compression steps will reduce this
|
||||||
// down to just `window`.
|
// down to just `window`.
|
||||||
if ( window )
|
if ( window )
|
||||||
if (document);
|
if ( !document );
|
||||||
function f() {}
|
function f() {}
|
||||||
function g() {}
|
function g() {}
|
||||||
function h() {}
|
function h() {}
|
||||||
|
|||||||
@@ -151,15 +151,18 @@ Infinity_not_in_with_scope: {
|
|||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var o = { Infinity: 'oInfinity' };
|
var o = { Infinity: "FAIL" };
|
||||||
var vInfinity = "Infinity";
|
var vInfinity = "Infinity";
|
||||||
vInfinity = Infinity;
|
vInfinity = Infinity;
|
||||||
|
console.log(vInfinity);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var o = { Infinity: 'oInfinity' }
|
var o = { Infinity: "FAIL" };
|
||||||
var vInfinity = "Infinity"
|
var vInfinity = "Infinity";
|
||||||
vInfinity = 1/0
|
vInfinity = 1/0;
|
||||||
|
console.log(vInfinity);
|
||||||
}
|
}
|
||||||
|
expect_stdout: "Infinity"
|
||||||
}
|
}
|
||||||
|
|
||||||
Infinity_in_with_scope: {
|
Infinity_in_with_scope: {
|
||||||
@@ -167,15 +170,18 @@ Infinity_in_with_scope: {
|
|||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var o = { Infinity: 'oInfinity' };
|
var o = { Infinity: "PASS" };
|
||||||
var vInfinity = "Infinity";
|
var vInfinity = "Infinity";
|
||||||
with (o) { vInfinity = Infinity; }
|
with (o) { vInfinity = Infinity; }
|
||||||
|
console.log(vInfinity);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var o = { Infinity: 'oInfinity' }
|
var o = { Infinity: "PASS" };
|
||||||
var vInfinity = "Infinity"
|
var vInfinity = "Infinity";
|
||||||
with (o) vInfinity = Infinity
|
with (o) vInfinity = Infinity;
|
||||||
|
console.log(vInfinity);
|
||||||
}
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
assorted_Infinity_NaN_undefined_in_with_scope: {
|
assorted_Infinity_NaN_undefined_in_with_scope: {
|
||||||
|
|||||||
@@ -22,8 +22,9 @@ issue_1639_1: {
|
|||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
|
for (var a = 100, b = 10, L1 = 5, ignore; --L1 > 0;) {
|
||||||
if (--b, 0) var ignore = 0;
|
--b;
|
||||||
|
}
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect_stdout: "100 6"
|
expect_stdout: "100 6"
|
||||||
|
|||||||
@@ -35,11 +35,7 @@ f7: {
|
|||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect_exact: [
|
expect_exact: [
|
||||||
"var b = 10;",
|
"console.log(100, 100);",
|
||||||
"",
|
|
||||||
"!function() {",
|
|
||||||
" b = 100;",
|
|
||||||
"}(), console.log(100, b);",
|
|
||||||
]
|
]
|
||||||
expect_stdout: true
|
expect_stdout: "100 100"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ warn: {
|
|||||||
}().length);
|
}().length);
|
||||||
}
|
}
|
||||||
expect_warnings: [
|
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.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"
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ remove_sequence: {
|
|||||||
(0, 1, _decorators.logThis)();
|
(0, 1, _decorators.logThis)();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
eval();
|
(0, eval)();
|
||||||
logThis();
|
logThis();
|
||||||
(0, _decorators.logThis)();
|
(0, _decorators.logThis)();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,21 +53,24 @@ this_binding_conditionals: {
|
|||||||
this_binding_collapse_vars: {
|
this_binding_collapse_vars: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
toplevel: true,
|
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
function f() {
|
||||||
"use strict";
|
"use strict";
|
||||||
var c = a; c();
|
var c = a; c();
|
||||||
var d = a.b; d();
|
var d = a.b; d();
|
||||||
var e = eval; e();
|
var e = eval; e();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
function f() {
|
||||||
"use strict";
|
"use strict";
|
||||||
a();
|
a();
|
||||||
(0, a.b)();
|
(0, a.b)();
|
||||||
(0, eval)();
|
(0, eval)();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this_binding_side_effects: {
|
this_binding_side_effects: {
|
||||||
@@ -97,7 +100,7 @@ this_binding_side_effects: {
|
|||||||
(function(foo) {
|
(function(foo) {
|
||||||
foo();
|
foo();
|
||||||
(0, foo.bar)();
|
(0, foo.bar)();
|
||||||
eval("console.log(foo);");
|
(0, eval)("console.log(foo);");
|
||||||
}());
|
}());
|
||||||
(function(foo) {
|
(function(foo) {
|
||||||
"use strict";
|
"use strict";
|
||||||
@@ -144,7 +147,7 @@ this_binding_sequences: {
|
|||||||
return eval("this");
|
return eval("this");
|
||||||
}()),
|
}()),
|
||||||
console.log(typeof function() {
|
console.log(typeof function() {
|
||||||
return eval("this");
|
return (0, eval)("this");
|
||||||
}()),
|
}()),
|
||||||
console.log(typeof function() {
|
console.log(typeof function() {
|
||||||
"use strict";
|
"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: {
|
expect: {
|
||||||
!function() {
|
!function() {
|
||||||
(function() {
|
(function() {
|
||||||
var a = undefined;
|
|
||||||
var undefined = a++;
|
|
||||||
try {
|
try {
|
||||||
!function() {
|
!function() {
|
||||||
(void 0)[1] = "foo";
|
(void 0)[1] = "foo";
|
||||||
@@ -1226,8 +1224,7 @@ chained_3: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function(b) {
|
console.log(function(b) {
|
||||||
var c = 1;
|
var c = 1, c = b;
|
||||||
c = b;
|
|
||||||
b++;
|
b++;
|
||||||
return c;
|
return c;
|
||||||
}(2));
|
}(2));
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ labels_1: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
out: {
|
out: {
|
||||||
@@ -21,6 +22,7 @@ labels_2: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
out: {
|
out: {
|
||||||
@@ -61,6 +63,7 @@ labels_4: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
out: for (var i = 0; i < 5; ++i) {
|
out: for (var i = 0; i < 5; ++i) {
|
||||||
@@ -105,6 +108,9 @@ labels_5: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
labels_6: {
|
labels_6: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
out: break out;
|
out: break out;
|
||||||
};
|
};
|
||||||
@@ -159,6 +165,7 @@ labels_9: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
out: while (foo) {
|
out: while (foo) {
|
||||||
|
|||||||
895
test/compress/let.js
Normal file
895
test/compress/let.js
Normal file
@@ -0,0 +1,895 @@
|
|||||||
|
retain_block: {
|
||||||
|
options = {}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = "FAIL";
|
||||||
|
}
|
||||||
|
var a = "PASS";
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = "FAIL";
|
||||||
|
}
|
||||||
|
var a = "PASS";
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
if_dead_branch: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
console.log(function() {
|
||||||
|
if (0) {
|
||||||
|
let a = 0;
|
||||||
|
}
|
||||||
|
return typeof a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
console.log(function() {
|
||||||
|
0;
|
||||||
|
{
|
||||||
|
let a;
|
||||||
|
}
|
||||||
|
return typeof a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
merge_vars_1: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
let a = console;
|
||||||
|
console.log(typeof a);
|
||||||
|
var b = typeof a;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
let a = console;
|
||||||
|
console.log(typeof a);
|
||||||
|
var b = typeof a;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"object",
|
||||||
|
"object",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
merge_vars_2: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
merge_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var a = 0;
|
||||||
|
(function() {
|
||||||
|
var b = function f() {
|
||||||
|
let c = a && f;
|
||||||
|
c.var += 0;
|
||||||
|
}();
|
||||||
|
console.log(b);
|
||||||
|
})(1 && --a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var a = 0;
|
||||||
|
1 && --a,
|
||||||
|
b = function f() {
|
||||||
|
let c = a && f;
|
||||||
|
c.var += 0;
|
||||||
|
}(),
|
||||||
|
void console.log(b);
|
||||||
|
var b;
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
merge_vars_3: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = 0;
|
||||||
|
var b = console;
|
||||||
|
console.log(typeof b);
|
||||||
|
}
|
||||||
|
var a = 1;
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = 0;
|
||||||
|
var b = console;
|
||||||
|
console.log(typeof b);
|
||||||
|
}
|
||||||
|
var a = 1;
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"object",
|
||||||
|
"number",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
use_before_init_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
a = "foo";
|
||||||
|
let a = "bar";
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
a = "foo";
|
||||||
|
let a = "bar";
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
use_before_init_2: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
try {
|
||||||
|
a = "foo";
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
let a = "bar";
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
try {
|
||||||
|
a = "foo";
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
let a = "bar";
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
use_before_init_3: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
try {
|
||||||
|
a;
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
let a = 42;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
try {
|
||||||
|
a;
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
let a = 42;
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
use_before_init_4: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
try {
|
||||||
|
console.log(a);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
let a = "FAIL";
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
try {
|
||||||
|
console.log(a);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
let a = "FAIL";
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
collapse_block: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = typeof console;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = typeof console;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "object"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
reduce_block_1: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = typeof console;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = typeof console;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "object"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
reduce_block_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = typeof console;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = typeof console;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"object",
|
||||||
|
"undefined",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
reduce_block_2_toplevel: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = typeof console;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = typeof console;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"object",
|
||||||
|
"undefined",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
hoist_props: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let o = {
|
||||||
|
p: "PASS",
|
||||||
|
};
|
||||||
|
console.log(o.p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let o = {
|
||||||
|
p: "PASS",
|
||||||
|
};
|
||||||
|
console.log(o.p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_block_1: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
do {
|
||||||
|
let o = console;
|
||||||
|
console.log(typeof o.log);
|
||||||
|
} while (!console);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
do {
|
||||||
|
let o = console;
|
||||||
|
console.log(typeof o.log);
|
||||||
|
} while (!console);
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_block_2: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
do {
|
||||||
|
let o = {};
|
||||||
|
(function() {
|
||||||
|
console.log(typeof this, o.p++);
|
||||||
|
})();
|
||||||
|
} while (!console);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
do {
|
||||||
|
let o = {};
|
||||||
|
(function() {
|
||||||
|
console.log(typeof this, o.p++);
|
||||||
|
})();
|
||||||
|
} while (!console);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined NaN"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_continue: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
try {
|
||||||
|
do {
|
||||||
|
{
|
||||||
|
let a = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} while ([ A ]);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
try {
|
||||||
|
do {
|
||||||
|
let a = 0;
|
||||||
|
continue;
|
||||||
|
} while ([ A ]);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
dead_block_after_return: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
(function(a) {
|
||||||
|
console.log(a);
|
||||||
|
return;
|
||||||
|
{
|
||||||
|
let a = "FAIL";
|
||||||
|
}
|
||||||
|
})("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
(function(a) {
|
||||||
|
console.log(a);
|
||||||
|
return;
|
||||||
|
{
|
||||||
|
let a;
|
||||||
|
}
|
||||||
|
})("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_if_continue_1: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
do {
|
||||||
|
if (console) {
|
||||||
|
console.log("PASS");
|
||||||
|
{
|
||||||
|
let a = 0;
|
||||||
|
var b;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
do {
|
||||||
|
if (!console);
|
||||||
|
else {
|
||||||
|
console.log("PASS");
|
||||||
|
{
|
||||||
|
let a = 0;
|
||||||
|
var b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (b);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_if_continue_2: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
do {
|
||||||
|
if (console) {
|
||||||
|
console.log("FAIL");
|
||||||
|
{
|
||||||
|
let a = 0;
|
||||||
|
A = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (A);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
do {
|
||||||
|
if (!console);
|
||||||
|
else {
|
||||||
|
console.log("FAIL");
|
||||||
|
{
|
||||||
|
let a = 0;
|
||||||
|
A = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (A);
|
||||||
|
}
|
||||||
|
expect_stdout: ReferenceError("A is not defined")
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_unused: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
function f(a) {
|
||||||
|
let b = a, c = b;
|
||||||
|
0 && c.p++;
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
function f(a) {
|
||||||
|
let b = a;
|
||||||
|
b;
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4191: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = function() {};
|
||||||
|
}
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = function() {};
|
||||||
|
}
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4197: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var a = 0;
|
||||||
|
try {
|
||||||
|
let b = function() {
|
||||||
|
a = 1;
|
||||||
|
b[1];
|
||||||
|
}();
|
||||||
|
} catch (e) {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var a = 0;
|
||||||
|
try {
|
||||||
|
let b = function() {
|
||||||
|
a = 1;
|
||||||
|
b[1];
|
||||||
|
}();
|
||||||
|
} catch (e) {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4202: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let o = {};
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
o.p = 42;
|
||||||
|
}
|
||||||
|
f(f);
|
||||||
|
})();
|
||||||
|
console.log(o.p++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let o = {};
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
o.p = 42;
|
||||||
|
}
|
||||||
|
f(f);
|
||||||
|
})();
|
||||||
|
console.log(o.p++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4207: {
|
||||||
|
options = {
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = function() {};
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = function() {};
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4218: {
|
||||||
|
options = {
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var a;
|
||||||
|
{
|
||||||
|
let a = function() {};
|
||||||
|
var b = 0 * a;
|
||||||
|
}
|
||||||
|
console.log(typeof a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var b = 0 * function() {};
|
||||||
|
console.log(typeof void 0, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined NaN"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4210: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var a;
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
throw 42;
|
||||||
|
} catch (e) {
|
||||||
|
let a = typeof e;
|
||||||
|
console.log(a);
|
||||||
|
} finally {
|
||||||
|
return a = "foo";
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var a;
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
throw 42;
|
||||||
|
} catch (e) {
|
||||||
|
let a = typeof e;
|
||||||
|
console.log(a);
|
||||||
|
} finally {
|
||||||
|
return a = "foo";
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"number",
|
||||||
|
"string",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4212_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
console.log({
|
||||||
|
get b() {
|
||||||
|
let a = 0;
|
||||||
|
return a /= 0;
|
||||||
|
}
|
||||||
|
}.b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
console.log({
|
||||||
|
get b() {
|
||||||
|
let a = 0;
|
||||||
|
return a / 0;
|
||||||
|
}
|
||||||
|
}.b);
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4212_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
console.log({
|
||||||
|
get b() {
|
||||||
|
let a = 0;
|
||||||
|
return a /= 0;
|
||||||
|
}
|
||||||
|
}.b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
console.log({
|
||||||
|
get b() {
|
||||||
|
let a = 0;
|
||||||
|
return a /= 0;
|
||||||
|
}
|
||||||
|
}.b);
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_braces: {
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
braces: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
if (console)
|
||||||
|
let a = console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
'"use strict";',
|
||||||
|
"",
|
||||||
|
"if (console) let a = console.log(typeof a);",
|
||||||
|
]
|
||||||
|
expect_stdout: true
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4225: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
let a = void typeof b;
|
||||||
|
let b = 42;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
let a = void b;
|
||||||
|
let b = 42;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4229: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
try {
|
||||||
|
(function f() {
|
||||||
|
f;
|
||||||
|
let f;
|
||||||
|
})();
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
try {
|
||||||
|
(function f() {
|
||||||
|
f;
|
||||||
|
let f;
|
||||||
|
})();
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4231: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
typeof a == 0;
|
||||||
|
console.log(typeof function a() {
|
||||||
|
let a;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
console.log(typeof function a() {
|
||||||
|
let a;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
@@ -201,7 +201,7 @@ evaluate: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1532: {
|
issue_1532_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
loops: true,
|
loops: true,
|
||||||
@@ -210,18 +210,56 @@ issue_1532: {
|
|||||||
function f(x, y) {
|
function f(x, y) {
|
||||||
do {
|
do {
|
||||||
if (x) break;
|
if (x) break;
|
||||||
foo();
|
console.log(y);
|
||||||
} while (false);
|
} while (false);
|
||||||
}
|
}
|
||||||
|
f(null, "PASS");
|
||||||
|
f(42, "FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(x, y) {
|
||||||
|
for (; !x && (console.log(y), false););
|
||||||
|
}
|
||||||
|
f(null, "PASS");
|
||||||
|
f(42, "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1532_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x, y) {
|
||||||
|
do {
|
||||||
|
if (x) {
|
||||||
|
console.log(x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
console.log(y);
|
||||||
|
} while (false);
|
||||||
|
}
|
||||||
|
f(null, "PASS");
|
||||||
|
f(42, "FAIL");
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(x, y) {
|
function f(x, y) {
|
||||||
do {
|
do {
|
||||||
if (x) break;
|
if (x) {
|
||||||
foo();
|
console.log(x);
|
||||||
} while (false);
|
break;
|
||||||
}
|
}
|
||||||
|
} while (console.log(y), false);
|
||||||
}
|
}
|
||||||
|
f(null, "PASS");
|
||||||
|
f(42, "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"42",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_186: {
|
issue_186: {
|
||||||
@@ -509,8 +547,8 @@ dead_code_condition: {
|
|||||||
console.log(a);
|
console.log(a);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var c;
|
|
||||||
var a = 0, b = 5;
|
var a = 0, b = 5;
|
||||||
|
var c;
|
||||||
a += 1, 0,
|
a += 1, 0,
|
||||||
console.log(a);
|
console.log(a);
|
||||||
}
|
}
|
||||||
@@ -549,6 +587,7 @@ issue_2740_2: {
|
|||||||
dead_code: true,
|
dead_code: true,
|
||||||
loops: true,
|
loops: true,
|
||||||
passes: 2,
|
passes: 2,
|
||||||
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
L1: while (x()) {
|
L1: while (x()) {
|
||||||
@@ -564,6 +603,7 @@ issue_2740_3: {
|
|||||||
options = {
|
options = {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
loops: true,
|
loops: true,
|
||||||
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
L1: for (var x = 0; x < 3; x++) {
|
L1: for (var x = 0; x < 3; x++) {
|
||||||
@@ -589,6 +629,7 @@ issue_2740_4: {
|
|||||||
dead_code: true,
|
dead_code: true,
|
||||||
loops: true,
|
loops: true,
|
||||||
passes: 2,
|
passes: 2,
|
||||||
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
L1: for (var x = 0; x < 3; x++) {
|
L1: for (var x = 0; x < 3; x++) {
|
||||||
@@ -613,6 +654,7 @@ issue_2740_5: {
|
|||||||
dead_code: true,
|
dead_code: true,
|
||||||
loops: true,
|
loops: true,
|
||||||
passes: 2,
|
passes: 2,
|
||||||
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
L1: for (var x = 0; x < 3; x++) {
|
L1: for (var x = 0; x < 3; x++) {
|
||||||
@@ -752,7 +794,37 @@ empty_for_in_side_effects: {
|
|||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
"WARN: Dropping unused variable b [test/compress/loops.js:4,16]",
|
"WARN: Dropping unused variable b [test/compress/loops.js:4,16]",
|
||||||
"INFO: Dropping unused loop variable a [test/compress/loops.js:1,17]",
|
"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]",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -763,6 +835,7 @@ issue_3631_1: {
|
|||||||
loops: true,
|
loops: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
toplevel: true,
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var c = 0;
|
var c = 0;
|
||||||
@@ -789,6 +862,7 @@ issue_3631_2: {
|
|||||||
loops: true,
|
loops: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
toplevel: true,
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
L: for (var a = 1; a--; console.log(b)) {
|
L: for (var a = 1; a--; console.log(b)) {
|
||||||
@@ -927,3 +1001,256 @@ issue_3634_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4182_1: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
console.log("FAIL");
|
||||||
|
} while (0);
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
console.log("FAIL");
|
||||||
|
} while (0);
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4182_2: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
L: do {
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
continue L;
|
||||||
|
}
|
||||||
|
console.log("FAIL");
|
||||||
|
} while (0);
|
||||||
|
console.log("FAIL");
|
||||||
|
} while (0);
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
L: do {
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
continue L;
|
||||||
|
}
|
||||||
|
} while (console.log("FAIL"), 0);
|
||||||
|
console.log("FAIL");
|
||||||
|
} while (0);
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_continue: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
do {
|
||||||
|
continue;
|
||||||
|
} while ([ A ]);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
do {
|
||||||
|
continue;
|
||||||
|
} while ([ A ]);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4240: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
function f() {
|
||||||
|
var o = { PASS: 42 };
|
||||||
|
for (a in o);
|
||||||
|
}
|
||||||
|
(function() {
|
||||||
|
if (f());
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
(function() {
|
||||||
|
if (function() {
|
||||||
|
for (a in { PASS: 42 });
|
||||||
|
}());
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
3094
test/compress/merge_vars.js
Normal file
3094
test/compress/merge_vars.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -91,7 +91,7 @@ evaluate_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(
|
console.log(
|
||||||
x + 1 + 2,
|
x + 1 + 2,
|
||||||
2 * x,
|
2 * +x,
|
||||||
+x + 1 + 2,
|
+x + 1 + 2,
|
||||||
1 + x + 2 + 3,
|
1 + x + 2 + 3,
|
||||||
3 | x,
|
3 | x,
|
||||||
@@ -130,7 +130,7 @@ evaluate_1_unsafe_math: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(
|
console.log(
|
||||||
x + 1 + 2,
|
x + 1 + 2,
|
||||||
2 * x,
|
2 * +x,
|
||||||
+x + 3,
|
+x + 3,
|
||||||
1 + x + 2 + 3,
|
1 + x + 2 + 3,
|
||||||
3 | x,
|
3 | x,
|
||||||
@@ -148,10 +148,12 @@ evaluate_1_unsafe_math: {
|
|||||||
evaluate_2: {
|
evaluate_2: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
unsafe_math: false,
|
unsafe_math: false,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = "42", y = null;
|
function f(num) {
|
||||||
|
var x = "" + num, y = null;
|
||||||
[
|
[
|
||||||
x + 1 + 2,
|
x + 1 + 2,
|
||||||
x * 1 * 2,
|
x * 1 * 2,
|
||||||
@@ -169,25 +171,30 @@ evaluate_2: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x = "42", y = null;
|
function f(num) {
|
||||||
|
var x = "" + num, y = null;
|
||||||
[
|
[
|
||||||
x + 1 + 2,
|
x + "12",
|
||||||
2 * x,
|
2 * x,
|
||||||
+x + 1 + 2,
|
+x + 1 + 2,
|
||||||
1 + x + 2 + 3,
|
1 + x + "23",
|
||||||
3 | x,
|
3 | x,
|
||||||
1 + x-- + 2 + 3,
|
1 + x-- + 2 + 3,
|
||||||
x*y + 2 + 1 + 3,
|
x*y + 2 + 1 + 3,
|
||||||
1 + (2 + x + 3),
|
2 + x + 3 + 1,
|
||||||
2 + ~x + 3 + 1,
|
2 + ~x + 3 + 1,
|
||||||
2 + ~x + 3 - y,
|
2 + ~x + 3,
|
||||||
0 & x,
|
0 & x,
|
||||||
2 + (x |= 0) + 3 + 1,
|
2 + (x |= 0) + 3 + 1,
|
||||||
].forEach(function(n) {
|
].forEach(function(n) {
|
||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"string 4212",
|
"string 4212",
|
||||||
"number 84",
|
"number 84",
|
||||||
@@ -207,10 +214,12 @@ evaluate_2: {
|
|||||||
evaluate_2_unsafe_math: {
|
evaluate_2_unsafe_math: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
unsafe_math: true,
|
unsafe_math: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = "42", y = null;
|
function f(num) {
|
||||||
|
var x = "" + num, y = null;
|
||||||
[
|
[
|
||||||
x + 1 + 2,
|
x + 1 + 2,
|
||||||
x * 1 * 2,
|
x * 1 * 2,
|
||||||
@@ -228,25 +237,30 @@ evaluate_2_unsafe_math: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x = "42", y = null;
|
function f(num) {
|
||||||
|
var x = "" + num, y = null;
|
||||||
[
|
[
|
||||||
x + 1 + 2,
|
x + "12",
|
||||||
2 * x,
|
2 * x,
|
||||||
+x + 3,
|
+x + 3,
|
||||||
1 + x + 2 + 3,
|
1 + x + "23",
|
||||||
3 | x,
|
3 | x,
|
||||||
6 + x--,
|
6 + x--,
|
||||||
x*y + 6,
|
x*y + 6,
|
||||||
1 + (2 + x + 3),
|
6 + x,
|
||||||
6 + ~x,
|
6 + ~x,
|
||||||
5 + ~x - y,
|
5 + ~x,
|
||||||
0 & x,
|
0 & x,
|
||||||
6 + (x |= 0),
|
6 + (x |= 0),
|
||||||
].forEach(function(n) {
|
].forEach(function(n) {
|
||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"string 4212",
|
"string 4212",
|
||||||
"number 84",
|
"number 84",
|
||||||
@@ -310,10 +324,12 @@ evaluate_4: {
|
|||||||
evaluate_5: {
|
evaluate_5: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
unsafe_math: false,
|
unsafe_math: false,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var a = "1";
|
function f(num) {
|
||||||
|
var a = "" + num;
|
||||||
[
|
[
|
||||||
+a + 2 + 3,
|
+a + 2 + 3,
|
||||||
+a + 2 - 3,
|
+a + 2 - 3,
|
||||||
@@ -331,8 +347,11 @@ evaluate_5: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(1);
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = "1";
|
function f(num) {
|
||||||
|
var a = "" + num;
|
||||||
[
|
[
|
||||||
+a + 2 + 3,
|
+a + 2 + 3,
|
||||||
+a + 2 - 3,
|
+a + 2 - 3,
|
||||||
@@ -350,6 +369,8 @@ evaluate_5: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(1);
|
||||||
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"number 6",
|
"number 6",
|
||||||
"number 0",
|
"number 0",
|
||||||
@@ -369,10 +390,12 @@ evaluate_5: {
|
|||||||
evaluate_5_unsafe_math: {
|
evaluate_5_unsafe_math: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
unsafe_math: true,
|
unsafe_math: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var a = "1";
|
function f(num) {
|
||||||
|
var a = "" + num;
|
||||||
[
|
[
|
||||||
+a + 2 + 3,
|
+a + 2 + 3,
|
||||||
+a + 2 - 3,
|
+a + 2 - 3,
|
||||||
@@ -390,8 +413,11 @@ evaluate_5_unsafe_math: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(1);
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = "1";
|
function f(num) {
|
||||||
|
var a = "" + num;
|
||||||
[
|
[
|
||||||
+a + 5,
|
+a + 5,
|
||||||
+a + -1,
|
+a + -1,
|
||||||
@@ -409,6 +435,8 @@ evaluate_5_unsafe_math: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(1);
|
||||||
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"number 6",
|
"number 6",
|
||||||
"number 0",
|
"number 0",
|
||||||
@@ -546,10 +574,12 @@ evaluate_6_unsafe_math: {
|
|||||||
evaluate_7: {
|
evaluate_7: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
unsafe_math: false,
|
unsafe_math: false,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = "42", y;
|
function f(num, y) {
|
||||||
|
var x = "" + num;
|
||||||
[
|
[
|
||||||
+x + 2 + (3 + !y),
|
+x + 2 + (3 + !y),
|
||||||
+x + 2 + (3 - !y),
|
+x + 2 + (3 - !y),
|
||||||
@@ -563,8 +593,11 @@ evaluate_7: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x = "42", y;
|
function f(num, y) {
|
||||||
|
var x = "" + num;
|
||||||
[
|
[
|
||||||
+x + 2 + (3 + !y),
|
+x + 2 + (3 + !y),
|
||||||
+x + 2 + (3 - !y),
|
+x + 2 + (3 - !y),
|
||||||
@@ -578,6 +611,8 @@ evaluate_7: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"number 48",
|
"number 48",
|
||||||
"number 46",
|
"number 46",
|
||||||
@@ -593,10 +628,12 @@ evaluate_7: {
|
|||||||
evaluate_7_unsafe_math: {
|
evaluate_7_unsafe_math: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
unsafe_math: true,
|
unsafe_math: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = "42", y;
|
function f(num, y) {
|
||||||
|
var x = "" + num;
|
||||||
[
|
[
|
||||||
+x + 2 + (3 + !y),
|
+x + 2 + (3 + !y),
|
||||||
+x + 2 + (3 - !y),
|
+x + 2 + (3 - !y),
|
||||||
@@ -610,8 +647,11 @@ evaluate_7_unsafe_math: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x = "42", y;
|
function f(num, y) {
|
||||||
|
var x = "" + num;
|
||||||
[
|
[
|
||||||
+x + 5 + !y,
|
+x + 5 + !y,
|
||||||
+x + 5 - !y,
|
+x + 5 - !y,
|
||||||
@@ -625,6 +665,8 @@ evaluate_7_unsafe_math: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"number 48",
|
"number 48",
|
||||||
"number 46",
|
"number 46",
|
||||||
@@ -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: {
|
NaN_redefined: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -1251,3 +1309,29 @@ issue_3695: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "NaN"
|
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 = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
keep_quoted: false,
|
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: {
|
mangle_unquoted_properties: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -1046,16 +1093,22 @@ array_hole: {
|
|||||||
side_effects: true,
|
side_effects: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
Array.prototype[2] = "PASS";
|
||||||
[ 1, 2, , 3][1],
|
console.log([ 1, 2, , 3 ][1]);
|
||||||
[ 1, 2, , 3][2],
|
console.log([ 1, 2, , 3 ][2]);
|
||||||
[ 1, 2, , 3][3]
|
console.log([ 1, 2, , 3 ][3]);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
expect: {
|
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: {
|
new_this: {
|
||||||
@@ -1070,11 +1123,7 @@ new_this: {
|
|||||||
}
|
}
|
||||||
}.f(42);
|
}.f(42);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {}
|
||||||
new function(a) {
|
|
||||||
this.a = a;
|
|
||||||
}(42);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2513: {
|
issue_2513: {
|
||||||
@@ -1143,558 +1192,6 @@ const_prop_assign_pure: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
join_object_assignments_1: {
|
|
||||||
options = {
|
|
||||||
evaluate: true,
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
console.log(function() {
|
|
||||||
var x = {
|
|
||||||
a: 1,
|
|
||||||
c: (console.log("c"), "C"),
|
|
||||||
};
|
|
||||||
x.b = 2;
|
|
||||||
x[3] = function() {
|
|
||||||
console.log(x);
|
|
||||||
},
|
|
||||||
x["a"] = /foo/,
|
|
||||||
x.bar = x;
|
|
||||||
return x;
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
console.log(function() {
|
|
||||||
var x = {
|
|
||||||
a: 1,
|
|
||||||
c: (console.log("c"), "C"),
|
|
||||||
b: 2,
|
|
||||||
3: function() {
|
|
||||||
console.log(x);
|
|
||||||
},
|
|
||||||
a: /foo/,
|
|
||||||
};
|
|
||||||
x.bar = x;
|
|
||||||
return x;
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect_stdout: true
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_2: {
|
|
||||||
options = {
|
|
||||||
evaluate: true,
|
|
||||||
hoist_props: true,
|
|
||||||
join_vars: true,
|
|
||||||
passes: 3,
|
|
||||||
reduce_vars: true,
|
|
||||||
toplevel: true,
|
|
||||||
unused: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o = {
|
|
||||||
foo: 1,
|
|
||||||
};
|
|
||||||
o.bar = 2;
|
|
||||||
o.baz = 3;
|
|
||||||
console.log(o.foo, o.bar + o.bar, o.foo * o.bar * o.baz);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
console.log(1, 4, 6);
|
|
||||||
}
|
|
||||||
expect_stdout: "1 4 6"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_3: {
|
|
||||||
options = {
|
|
||||||
evaluate: true,
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
console.log(function() {
|
|
||||||
var o = {
|
|
||||||
a: "PASS",
|
|
||||||
}, a = o.a;
|
|
||||||
o.a = "FAIL";
|
|
||||||
return a;
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
console.log(function() {
|
|
||||||
var o = {
|
|
||||||
a: "PASS",
|
|
||||||
}, a = o.a;
|
|
||||||
o.a = "FAIL";
|
|
||||||
return a;
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect_stdout: "PASS"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_4: {
|
|
||||||
options = {
|
|
||||||
join_vars: true,
|
|
||||||
sequences: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o;
|
|
||||||
console.log(o);
|
|
||||||
o = {};
|
|
||||||
o.a = "foo";
|
|
||||||
console.log(o.b);
|
|
||||||
o.b = "bar";
|
|
||||||
console.log(o.a);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var o;
|
|
||||||
console.log(o),
|
|
||||||
o = {
|
|
||||||
a: "foo",
|
|
||||||
},
|
|
||||||
console.log(o.b),
|
|
||||||
o.b = "bar",
|
|
||||||
console.log(o.a);
|
|
||||||
}
|
|
||||||
expect_stdout: [
|
|
||||||
"undefined",
|
|
||||||
"undefined",
|
|
||||||
"foo",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_return_1: {
|
|
||||||
options = {
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
console.log(function() {
|
|
||||||
var o = {
|
|
||||||
p: 3
|
|
||||||
};
|
|
||||||
return o.q = "foo";
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
console.log(function() {
|
|
||||||
var o = {
|
|
||||||
p: 3,
|
|
||||||
q: "foo"
|
|
||||||
};
|
|
||||||
return o.q;
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect_stdout: "foo"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_return_2: {
|
|
||||||
options = {
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
console.log(function() {
|
|
||||||
var o = {
|
|
||||||
p: 3
|
|
||||||
};
|
|
||||||
return o.q = /foo/,
|
|
||||||
o.r = "bar";
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
console.log(function() {
|
|
||||||
var o = {
|
|
||||||
p: 3,
|
|
||||||
q: /foo/,
|
|
||||||
r: "bar"
|
|
||||||
};
|
|
||||||
return o.r;
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect_stdout: "bar"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_return_3: {
|
|
||||||
options = {
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
console.log(function() {
|
|
||||||
var o = {
|
|
||||||
p: 3
|
|
||||||
};
|
|
||||||
return o.q = "foo",
|
|
||||||
o.p += "",
|
|
||||||
console.log(o.q),
|
|
||||||
o.p;
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
console.log(function() {
|
|
||||||
var o = {
|
|
||||||
p: 3,
|
|
||||||
q: "foo"
|
|
||||||
};
|
|
||||||
return o.p += "",
|
|
||||||
console.log(o.q),
|
|
||||||
o.p;
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect_stdout: [
|
|
||||||
"foo",
|
|
||||||
"3",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_for: {
|
|
||||||
options = {
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
console.log(function() {
|
|
||||||
var o = {
|
|
||||||
p: 3
|
|
||||||
};
|
|
||||||
for (o.q = "foo"; console.log(o.q););
|
|
||||||
return o.p;
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
console.log(function() {
|
|
||||||
for (var o = {
|
|
||||||
p: 3,
|
|
||||||
q: "foo"
|
|
||||||
}; console.log(o.q););
|
|
||||||
return o.p;
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect_stdout: [
|
|
||||||
"foo",
|
|
||||||
"3",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_if: {
|
|
||||||
options = {
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
console.log(function() {
|
|
||||||
var o = {};
|
|
||||||
if (o.a = "PASS") return o.a;
|
|
||||||
}())
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
console.log(function() {
|
|
||||||
var o = { a: "PASS" };
|
|
||||||
if (o.a) return o.a;
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect_stdout: "PASS"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_forin: {
|
|
||||||
options = {
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
console.log(function() {
|
|
||||||
var o = {};
|
|
||||||
for (var a in o.a = "PASS", o)
|
|
||||||
return o[a];
|
|
||||||
}())
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
console.log(function() {
|
|
||||||
var o = { a: "PASS" };
|
|
||||||
for (var a in o)
|
|
||||||
return o[a];
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect_stdout: "PASS"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_negative: {
|
|
||||||
options = {
|
|
||||||
evaluate: true,
|
|
||||||
join_vars: true,
|
|
||||||
properties: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o = {};
|
|
||||||
o[0] = 0;
|
|
||||||
o[-0] = 1;
|
|
||||||
o[-1] = 2;
|
|
||||||
console.log(o[0], o[-0], o[-1]);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var o = {
|
|
||||||
0: 0,
|
|
||||||
0: 1,
|
|
||||||
"-1": 2
|
|
||||||
};
|
|
||||||
console.log(o[0], o[-0], o[-1]);
|
|
||||||
}
|
|
||||||
expect_stdout: "1 1 2"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_NaN_1: {
|
|
||||||
options = {
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o = {};
|
|
||||||
o[NaN] = 1;
|
|
||||||
o[0/0] = 2;
|
|
||||||
console.log(o[NaN], o[NaN]);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var o = {};
|
|
||||||
o[NaN] = 1;
|
|
||||||
o[0/0] = 2;
|
|
||||||
console.log(o[NaN], o[NaN]);
|
|
||||||
}
|
|
||||||
expect_stdout: "2 2"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_NaN_2: {
|
|
||||||
options = {
|
|
||||||
evaluate: true,
|
|
||||||
join_vars: true,
|
|
||||||
properties: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o = {};
|
|
||||||
o[NaN] = 1;
|
|
||||||
o[0/0] = 2;
|
|
||||||
console.log(o[NaN], o[NaN]);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var o = {
|
|
||||||
NaN: 1,
|
|
||||||
NaN: 2
|
|
||||||
};
|
|
||||||
console.log(o.NaN, o.NaN);
|
|
||||||
}
|
|
||||||
expect_stdout: "2 2"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_null_0: {
|
|
||||||
options = {
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o = {};
|
|
||||||
o[null] = 1;
|
|
||||||
console.log(o[null]);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var o = {};
|
|
||||||
o[null] = 1;
|
|
||||||
console.log(o[null]);
|
|
||||||
}
|
|
||||||
expect_stdout: "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_null_1: {
|
|
||||||
options = {
|
|
||||||
evaluate: true,
|
|
||||||
join_vars: true,
|
|
||||||
properties: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o = {};
|
|
||||||
o[null] = 1;
|
|
||||||
console.log(o[null]);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var o = {
|
|
||||||
null: 1
|
|
||||||
};
|
|
||||||
console.log(o.null);
|
|
||||||
}
|
|
||||||
expect_stdout: "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_void_0: {
|
|
||||||
options = {
|
|
||||||
evaluate: true,
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o = {};
|
|
||||||
o[void 0] = 1;
|
|
||||||
console.log(o[void 0]);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var o = {
|
|
||||||
undefined: 1
|
|
||||||
};
|
|
||||||
console.log(o[void 0]);
|
|
||||||
}
|
|
||||||
expect_stdout: "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_undefined_1: {
|
|
||||||
options = {
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o = {};
|
|
||||||
o[undefined] = 1;
|
|
||||||
console.log(o[undefined]);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var o = {};
|
|
||||||
o[void 0] = 1;
|
|
||||||
console.log(o[void 0]);
|
|
||||||
}
|
|
||||||
expect_stdout: "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_undefined_2: {
|
|
||||||
options = {
|
|
||||||
evaluate: true,
|
|
||||||
join_vars: true,
|
|
||||||
properties: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o = {};
|
|
||||||
o[undefined] = 1;
|
|
||||||
console.log(o[undefined]);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var o = {
|
|
||||||
undefined : 1
|
|
||||||
};
|
|
||||||
console.log(o[void 0]);
|
|
||||||
}
|
|
||||||
expect_stdout: "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_Infinity: {
|
|
||||||
options = {
|
|
||||||
evaluate: true,
|
|
||||||
join_vars: true,
|
|
||||||
properties: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o = {};
|
|
||||||
o[Infinity] = 1;
|
|
||||||
o[1/0] = 2;
|
|
||||||
o[-Infinity] = 3;
|
|
||||||
o[-1/0] = 4;
|
|
||||||
console.log(o[Infinity], o[1/0], o[-Infinity], o[-1/0]);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var o = {
|
|
||||||
Infinity: 1,
|
|
||||||
Infinity: 2,
|
|
||||||
"-Infinity": 3,
|
|
||||||
"-Infinity": 4
|
|
||||||
};
|
|
||||||
console.log(o[1/0], o[1/0], o[-1/0], o[-1/0]);
|
|
||||||
}
|
|
||||||
expect_stdout: "2 2 4 4"
|
|
||||||
}
|
|
||||||
|
|
||||||
join_object_assignments_regex: {
|
|
||||||
options = {
|
|
||||||
evaluate: true,
|
|
||||||
join_vars: true,
|
|
||||||
properties: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o = {};
|
|
||||||
o[/rx/] = 1;
|
|
||||||
console.log(o[/rx/]);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var o = {
|
|
||||||
"/rx/": 1
|
|
||||||
};
|
|
||||||
console.log(o[/rx/]);
|
|
||||||
}
|
|
||||||
expect_stdout: "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_2816: {
|
|
||||||
options = {
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
"use strict";
|
|
||||||
var o = {
|
|
||||||
a: 1
|
|
||||||
};
|
|
||||||
o.b = 2;
|
|
||||||
o.a = 3;
|
|
||||||
o.c = 4;
|
|
||||||
console.log(o.a, o.b, o.c);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
"use strict";
|
|
||||||
var o = {
|
|
||||||
a: 1,
|
|
||||||
b: 2
|
|
||||||
};
|
|
||||||
o.a = 3;
|
|
||||||
o.c = 4;
|
|
||||||
console.log(o.a, o.b, o.c);
|
|
||||||
}
|
|
||||||
expect_stdout: "3 2 4"
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_2893_1: {
|
|
||||||
options = {
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o = {
|
|
||||||
get a() {
|
|
||||||
return "PASS";
|
|
||||||
},
|
|
||||||
};
|
|
||||||
o.a = "FAIL";
|
|
||||||
console.log(o.a);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var o = {
|
|
||||||
get a() {
|
|
||||||
return "PASS";
|
|
||||||
},
|
|
||||||
};
|
|
||||||
o.a = "FAIL";
|
|
||||||
console.log(o.a);
|
|
||||||
}
|
|
||||||
expect_stdout: "PASS"
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_2893_2: {
|
|
||||||
options = {
|
|
||||||
join_vars: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var o = {
|
|
||||||
set a(v) {
|
|
||||||
this.b = v;
|
|
||||||
},
|
|
||||||
b: "FAIL",
|
|
||||||
};
|
|
||||||
o.a = "PASS";
|
|
||||||
console.log(o.b);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var o = {
|
|
||||||
set a(v) {
|
|
||||||
this.b = v;
|
|
||||||
},
|
|
||||||
b: "FAIL",
|
|
||||||
};
|
|
||||||
o.a = "PASS";
|
|
||||||
console.log(o.b);
|
|
||||||
}
|
|
||||||
expect_stdout: "PASS"
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_869_1: {
|
issue_869_1: {
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
@@ -1856,36 +1353,6 @@ issue_3188_3: {
|
|||||||
expect_stdout: "PASS"
|
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: {
|
issue_3389: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ relational: {
|
|||||||
side_effects :true,
|
side_effects :true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
foo() in foo();
|
foo() in new foo();
|
||||||
foo() instanceof bar();
|
foo() instanceof bar();
|
||||||
foo() < "bar";
|
foo() < "bar";
|
||||||
bar() > foo();
|
bar() > foo();
|
||||||
@@ -680,3 +680,130 @@ issue_3325_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
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",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -848,11 +848,10 @@ collapse_vars_1_true: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(a, b) {
|
function f(a, b) {
|
||||||
for (;;) {
|
for (;;)
|
||||||
if (a.g() || b.p) break;
|
if (a.g() || b.p) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse_vars_1_false: {
|
collapse_vars_1_false: {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -80,3 +80,21 @@ log_global: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "[object 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"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
forin: {
|
forin_1: {
|
||||||
options = {
|
options = {
|
||||||
sequences: true,
|
sequences: true,
|
||||||
}
|
}
|
||||||
@@ -895,6 +895,49 @@ forin: {
|
|||||||
expect_stdout: "PASS"
|
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: {
|
call: {
|
||||||
options = {
|
options = {
|
||||||
sequences: true,
|
sequences: true,
|
||||||
@@ -1112,3 +1155,25 @@ issue_3703: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
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"
|
||||||
|
}
|
||||||
|
|||||||
@@ -97,9 +97,8 @@ issue_2233_2: {
|
|||||||
var RegExp;
|
var RegExp;
|
||||||
UndeclaredGlobal;
|
UndeclaredGlobal;
|
||||||
function foo() {
|
function foo() {
|
||||||
var Number;
|
|
||||||
AnotherUndeclaredGlobal;
|
AnotherUndeclaredGlobal;
|
||||||
Number.isNaN;
|
(void 0).isNaN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,6 +245,31 @@ unsafe_builtin_2: {
|
|||||||
expect_stdout: "object PASS PASS"
|
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: {
|
unsafe_string_replace: {
|
||||||
options = {
|
options = {
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -275,3 +299,137 @@ drop_value: {
|
|||||||
foo(), bar();
|
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",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
trim_new: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
new function(a) {
|
||||||
|
console.log(a);
|
||||||
|
}("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
console.log(a);
|
||||||
|
})("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
constant_switch_1: {
|
constant_switch_1: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -19,6 +20,7 @@ constant_switch_1: {
|
|||||||
|
|
||||||
constant_switch_2: {
|
constant_switch_2: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -39,6 +41,7 @@ constant_switch_2: {
|
|||||||
|
|
||||||
constant_switch_3: {
|
constant_switch_3: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -60,6 +63,7 @@ constant_switch_3: {
|
|||||||
|
|
||||||
constant_switch_4: {
|
constant_switch_4: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -86,6 +90,7 @@ constant_switch_4: {
|
|||||||
|
|
||||||
constant_switch_5: {
|
constant_switch_5: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -120,6 +125,7 @@ constant_switch_5: {
|
|||||||
|
|
||||||
constant_switch_6: {
|
constant_switch_6: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -154,6 +160,7 @@ constant_switch_6: {
|
|||||||
|
|
||||||
constant_switch_7: {
|
constant_switch_7: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -197,6 +204,7 @@ constant_switch_7: {
|
|||||||
|
|
||||||
constant_switch_8: {
|
constant_switch_8: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -226,6 +234,7 @@ constant_switch_8: {
|
|||||||
|
|
||||||
constant_switch_9: {
|
constant_switch_9: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -315,6 +324,7 @@ keep_default: {
|
|||||||
|
|
||||||
issue_1663: {
|
issue_1663: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -551,6 +561,7 @@ issue_441_2: {
|
|||||||
|
|
||||||
issue_1674: {
|
issue_1674: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -876,6 +887,7 @@ beautify: {
|
|||||||
|
|
||||||
issue_1758: {
|
issue_1758: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
}
|
}
|
||||||
@@ -898,6 +910,7 @@ issue_1758: {
|
|||||||
|
|
||||||
issue_2535: {
|
issue_2535: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
@@ -919,6 +932,7 @@ issue_2535: {
|
|||||||
|
|
||||||
issue_1750: {
|
issue_1750: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
@@ -963,6 +977,7 @@ drop_switch_1: {
|
|||||||
|
|
||||||
drop_switch_2: {
|
drop_switch_2: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
}
|
}
|
||||||
@@ -1007,6 +1022,7 @@ drop_switch_3: {
|
|||||||
|
|
||||||
drop_switch_4: {
|
drop_switch_4: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
}
|
}
|
||||||
@@ -1028,3 +1044,140 @@ drop_switch_4: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
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,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
L: if (true) {
|
L: if (true) {
|
||||||
|
|||||||
@@ -435,3 +435,25 @@ emberjs_global: {
|
|||||||
}
|
}
|
||||||
expect_stdout: Error("PASS")
|
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"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,37 @@
|
|||||||
|
ascii_only_false: {
|
||||||
|
options = {}
|
||||||
|
beautify = {
|
||||||
|
ascii_only: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"\x000\x001\x007\x008\x00",
|
||||||
|
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
|
||||||
|
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
|
||||||
|
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_exact: 'console.log("\\x000\\x001\\x007\\x008\\0","\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f","\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\');'
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ascii_only_true: {
|
||||||
|
options = {}
|
||||||
|
beautify = {
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"\x000\x001\x007\x008\x00",
|
||||||
|
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
|
||||||
|
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
|
||||||
|
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_exact: 'console.log("\\x000\\x001\\x007\\x008\\0","\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\v\\f\\r\\x0e\\x0f","\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f",\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\');'
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
unicode_parse_variables: {
|
unicode_parse_variables: {
|
||||||
options = {}
|
options = {}
|
||||||
input: {
|
input: {
|
||||||
@@ -141,3 +175,35 @@ issue_2569: {
|
|||||||
}
|
}
|
||||||
expect_exact: 'new RegExp("[\\udc42-\\udcaa\\udd74-\\udd96\\ude45-\\ude4f\\udea3-\\udecc]");'
|
expect_exact: 'new RegExp("[\\udc42-\\udcaa\\udd74-\\udd96\\ude45-\\ude4f\\udea3-\\udecc]");'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
surrogate_pair: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var \u{2f800} = {
|
||||||
|
\u{2f801}: "\u{100000}",
|
||||||
|
};
|
||||||
|
\u{2f800}.\u{2f802} = "\u{100001}";
|
||||||
|
console.log(typeof \u{2f800}, \u{2f800}.\u{2f801}, \u{2f800}["\u{2f802}"]);
|
||||||
|
}
|
||||||
|
expect_exact: 'var \ud87e\udc00={"\ud87e\udc01":"\udbc0\udc00"};\ud87e\udc00.\ud87e\udc02="\udbc0\udc01";console.log(typeof \ud87e\udc00,\ud87e\udc00.\ud87e\udc01,\ud87e\udc00["\ud87e\udc02"]);'
|
||||||
|
expect_stdout: "object \udbc0\udc00 \udbc0\udc01"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
surrogate_pair_ascii: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var \u{2f800} = {
|
||||||
|
\u{2f801}: "\u{100000}",
|
||||||
|
};
|
||||||
|
\u{2f800}.\u{2f802} = "\u{100001}";
|
||||||
|
console.log(typeof \u{2f800}, \u{2f800}.\u{2f801}, \u{2f800}["\u{2f802}"]);
|
||||||
|
}
|
||||||
|
expect_exact: 'var \\u{2f800}={"\\ud87e\\udc01":"\\udbc0\\udc00"};\\u{2f800}.\\u{2f802}="\\udbc0\\udc01";console.log(typeof \\u{2f800},\\u{2f800}.\\u{2f801},\\u{2f800}["\\ud87e\\udc02"]);'
|
||||||
|
expect_stdout: "object \udbc0\udc00 \udbc0\udc01"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
236
test/compress/varify.js
Normal file
236
test/compress/varify.js
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
reduce_merge_const: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
const a = console;
|
||||||
|
console.log(typeof a);
|
||||||
|
var b = typeof a;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = console;
|
||||||
|
console.log(typeof b);
|
||||||
|
b = typeof b;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"object",
|
||||||
|
"object",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
reduce_merge_let: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
let a = console;
|
||||||
|
console.log(typeof a);
|
||||||
|
var b = typeof a;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var b = console;
|
||||||
|
console.log(typeof b);
|
||||||
|
b = typeof b;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"object",
|
||||||
|
"object",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
reduce_block_const: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
{
|
||||||
|
const a = typeof console;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = typeof console;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "object"
|
||||||
|
}
|
||||||
|
|
||||||
|
reduce_block_let: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let a = typeof console;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var a = typeof console;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "object"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
hoist_props_const: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
{
|
||||||
|
const o = {
|
||||||
|
p: "PASS",
|
||||||
|
};
|
||||||
|
console.log(o.p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o_p = "PASS";
|
||||||
|
console.log(o_p);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
hoist_props_let: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
{
|
||||||
|
let o = {
|
||||||
|
p: "PASS",
|
||||||
|
};
|
||||||
|
console.log(o.p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var o_p = "PASS";
|
||||||
|
console.log(o_p);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
scope_adjustment_const: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var k in [ 42 ])
|
||||||
|
console.log(function f() {
|
||||||
|
if (k) {
|
||||||
|
const a = 0;
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var k in [ 42 ])
|
||||||
|
console.log(void (k && 0));
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
scope_adjustment_let: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
for (var k in [ 42 ])
|
||||||
|
console.log(function f() {
|
||||||
|
if (k) {
|
||||||
|
let a = 0;
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
for (var k in [ 42 ])
|
||||||
|
console.log(void (k && 0));
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4191_const: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
const a = function() {};
|
||||||
|
console.log(typeof a, a());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function a() {};
|
||||||
|
console.log(typeof a, a());
|
||||||
|
}
|
||||||
|
expect_stdout: "function undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4191_let: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
let a = function() {};
|
||||||
|
console.log(typeof a, a());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
function a() {};
|
||||||
|
console.log(typeof a, a());
|
||||||
|
}
|
||||||
|
expect_stdout: "function undefined"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
@@ -13,3 +13,4 @@ exports["to_ascii"] = to_ascii;
|
|||||||
exports["tokenizer"] = tokenizer;
|
exports["tokenizer"] = tokenizer;
|
||||||
exports["TreeTransformer"] = TreeTransformer;
|
exports["TreeTransformer"] = TreeTransformer;
|
||||||
exports["TreeWalker"] = TreeWalker;
|
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:
|
||||||
|
}
|
||||||
@@ -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)));
|
"use strict";
|
||||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0Mi5qcyJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiYXJyIl0sIm1hcHBpbmdzIjoiMEpBQWNBLEtBQVFDIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3Qge2Zvb30gPSByZXF1aXJlKFwiYmFyXCIpO1xuY29uc3Qge2hlbGxvfSA9IHJlcXVpcmUoXCJ3b3JsZFwiKTtcblxuZm9vLngoLi4uZm9vLnkoaGVsbG8ueikpO1xuIl19
|
|
||||||
|
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"),
|
var _require = require("bar"),
|
||||||
foo = _require.foo;
|
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)};
|
console.log(3);
|
||||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUEwQkEsUUFBUUMsSUFBSSJ9
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ function test(a){
|
|||||||
"aaaaaaaaaaaaaaaa"
|
"aaaaaaaaaaaaaaaa"
|
||||||
;a(err,data),a(err,
|
;a(err,data),a(err,
|
||||||
data)}
|
data)}
|
||||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7QUFDVjtDQUNBQSxFQUFTQyxJQUFLQyxNQUNkRixFQUFTQztBQUFLQyJ9
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7O0NBRVZBLEVBQVNDLElBQUtDLE1BQ2RGLEVBQVNDO0FBQUtDIn0=
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
new function(){console.log(3)};
|
console.log(3);
|
||||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUEwQkEsUUFBUUMsSUFBSSJ9
|
||||||
|
|||||||
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
|
||||||
|
// }
|
||||||
@@ -1,9 +1,3 @@
|
|||||||
var o = this;
|
UNUSED: {
|
||||||
|
console.log(0 - .1 - .1 - .1);
|
||||||
for (var k in o) L17060: {
|
|
||||||
a++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var a;
|
|
||||||
|
|
||||||
console.log(k);
|
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
// (beautified)
|
// (beautified)
|
||||||
var o = this;
|
console.log(0 - 1 - .1 - .1);
|
||||||
|
// output: -1.2000000000000002
|
||||||
for (var k in o) {}
|
|
||||||
|
|
||||||
var a;
|
|
||||||
|
|
||||||
console.log(k);
|
|
||||||
// output: a
|
|
||||||
//
|
//
|
||||||
// minify: k
|
// minify: -1.2
|
||||||
//
|
//
|
||||||
// options: {
|
// options: {
|
||||||
|
// "compress": {
|
||||||
|
// "unsafe_math": true
|
||||||
|
// },
|
||||||
// "mangle": false
|
// "mangle": false
|
||||||
// }
|
// }
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
function f(x) {
|
function f(x) {
|
||||||
return g(x);
|
return g(x);
|
||||||
function g(x) {
|
function g(x) {
|
||||||
return x;
|
return x + x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,16 +8,15 @@ if (typeof phantom == "undefined") {
|
|||||||
require("../tools/exit");
|
require("../tools/exit");
|
||||||
var args = process.argv.slice(2);
|
var args = process.argv.slice(2);
|
||||||
var debug = args.indexOf("--debug");
|
var debug = args.indexOf("--debug");
|
||||||
if (debug >= 0) {
|
if (debug < 0) {
|
||||||
|
debug = false;
|
||||||
|
} else {
|
||||||
args.splice(debug, 1);
|
args.splice(debug, 1);
|
||||||
debug = true;
|
debug = true;
|
||||||
} else {
|
|
||||||
debug = false;
|
|
||||||
}
|
}
|
||||||
if (!args.length) {
|
if (!args.length) args.push("-mcb", "beautify=false,webkit");
|
||||||
args.push("-mcb", "beautify=false,webkit");
|
args.unshift("bin/uglifyjs");
|
||||||
}
|
args.push("--validate", "--timings");
|
||||||
args.push("--timings");
|
|
||||||
var child_process = require("child_process");
|
var child_process = require("child_process");
|
||||||
var fetch = require("./fetch");
|
var fetch = require("./fetch");
|
||||||
var http = require("http");
|
var http = require("http");
|
||||||
@@ -39,10 +38,10 @@ if (typeof phantom == "undefined") {
|
|||||||
});
|
});
|
||||||
if (/\.js$/.test(url)) {
|
if (/\.js$/.test(url)) {
|
||||||
var stderr = "";
|
var stderr = "";
|
||||||
var uglifyjs = child_process.fork("bin/uglifyjs", args, {
|
var uglifyjs = child_process.spawn(process.argv[0], args, {
|
||||||
silent: true
|
silent: true
|
||||||
}).on("exit", function(code) {
|
}).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);
|
console.log(stderr);
|
||||||
if (code) throw new Error("uglifyjs failed with code " + code);
|
if (code) throw new Error("uglifyjs failed with code " + code);
|
||||||
});
|
});
|
||||||
@@ -61,7 +60,7 @@ if (typeof phantom == "undefined") {
|
|||||||
var port = server.address().port;
|
var port = server.address().port;
|
||||||
if (debug) {
|
if (debug) {
|
||||||
console.log("http://localhost:" + port + "/");
|
console.log("http://localhost:" + port + "/");
|
||||||
} else {
|
} else (function install() {
|
||||||
child_process.spawn(process.platform == "win32" ? "npm.cmd" : "npm", [
|
child_process.spawn(process.platform == "win32" ? "npm.cmd" : "npm", [
|
||||||
"install",
|
"install",
|
||||||
"phantomjs-prebuilt@2.1.14",
|
"phantomjs-prebuilt@2.1.14",
|
||||||
@@ -72,7 +71,10 @@ if (typeof phantom == "undefined") {
|
|||||||
], {
|
], {
|
||||||
stdio: [ "ignore", 1, 2 ]
|
stdio: [ "ignore", 1, 2 ]
|
||||||
}).on("exit", function(code) {
|
}).on("exit", function(code) {
|
||||||
if (code) throw new Error("npm install failed!");
|
if (code) {
|
||||||
|
console.log("npm install failed with code", code);
|
||||||
|
return install();
|
||||||
|
}
|
||||||
var program = require("phantomjs-prebuilt").exec(process.argv[1], port);
|
var program = require("phantomjs-prebuilt").exec(process.argv[1], port);
|
||||||
program.stdout.pipe(process.stdout);
|
program.stdout.pipe(process.stdout);
|
||||||
program.stderr.pipe(process.stderr);
|
program.stderr.pipe(process.stderr);
|
||||||
@@ -83,7 +85,7 @@ if (typeof phantom == "undefined") {
|
|||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
})();
|
||||||
});
|
});
|
||||||
server.timeout = 0;
|
server.timeout = 0;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ var assert = require("assert");
|
|||||||
var exec = require("child_process").exec;
|
var exec = require("child_process").exec;
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var run_code = require("../sandbox").run_code;
|
var run_code = require("../sandbox").run_code;
|
||||||
|
var to_ascii = require("../node").to_ascii;
|
||||||
|
|
||||||
function read(path) {
|
function read(path) {
|
||||||
return fs.readFileSync(path, "utf8");
|
return fs.readFileSync(path, "utf8");
|
||||||
@@ -48,6 +49,62 @@ describe("bin/uglifyjs", function() {
|
|||||||
done();
|
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) {
|
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";
|
var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline --verbose";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
@@ -109,9 +166,12 @@ describe("bin/uglifyjs", function() {
|
|||||||
}
|
}
|
||||||
var command = [
|
var command = [
|
||||||
uglifyjscmd,
|
uglifyjscmd,
|
||||||
"--source-map", "content=" + mapFile,
|
"--beautify",
|
||||||
"--source-map", "includeSources=true",
|
"--source-map", [
|
||||||
"--source-map", "url=inline",
|
"content=" + mapFile,
|
||||||
|
"includeSources",
|
||||||
|
"url=inline",
|
||||||
|
].join(","),
|
||||||
].join(" ");
|
].join(" ");
|
||||||
|
|
||||||
var child = exec(command, function(err, stdout) {
|
var child = exec(command, function(err, stdout) {
|
||||||
@@ -189,7 +249,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should work with `--output-opts`", function(done) {
|
it("Should work with `--output-opts`", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/issue-1482/input.js -O';
|
var command = uglifyjscmd + ' test/input/issue-1482/input.js -O ascii_only';
|
||||||
exec(command, function(err, stdout) {
|
exec(command, function(err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, read("test/input/issue-1482/default.js"));
|
assert.strictEqual(stdout, read("test/input/issue-1482/default.js"));
|
||||||
@@ -197,7 +257,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should fail when both --beautify & --output-opts are specified", function(done) {
|
it("Should fail when both --beautify & --output-opts are specified", function(done) {
|
||||||
var command = uglifyjscmd + " test/input/issue-520/input.js -bO";
|
var command = uglifyjscmd + " test/input/issue-520/input.js -bO ascii_only";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stderr, "ERROR: --beautify cannot be used with --output-opts\n");
|
assert.strictEqual(stderr, "ERROR: --beautify cannot be used with --output-opts\n");
|
||||||
@@ -245,7 +305,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, [
|
assert.strictEqual(stdout, [
|
||||||
"var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();",
|
"var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();",
|
||||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUFBLE1BQWdCQyxRQUFRQyxJQUFJLEVBQUUsSUFBTyxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUVBLE1BQWNDLFFBQVFDLElBQUksRUFBRSxJQUFPLElBQUlGLElDQW5ELElBQUlHLElBQU0sV0FDTixTQUFTQyxJQUFLRCxLQUNWLE9BQU9BLElBR1gsT0FBT0MsSUFMRCJ9",
|
||||||
"",
|
"",
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
var stderrLines = stderr.split("\n");
|
var stderrLines = stderr.split("\n");
|
||||||
@@ -270,7 +330,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should fail with invalid syntax", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
var lines = stderr.split(/\n/);
|
var lines = stderr.split(/\n/);
|
||||||
@@ -282,7 +342,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should fail with correct marking of tabs", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
var lines = stderr.split(/\n/);
|
var lines = stderr.split(/\n/);
|
||||||
@@ -294,7 +354,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should fail with correct marking at start of line", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
var lines = stderr.split(/\n/);
|
var lines = stderr.split(/\n/);
|
||||||
@@ -306,7 +366,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should fail with a missing loop body", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
var lines = stderr.split(/\n/);
|
var lines = stderr.split(/\n/);
|
||||||
@@ -318,7 +378,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (5--)", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -332,7 +392,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (Math.random() /= 2)", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -346,7 +406,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (++this)", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -360,7 +420,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (++null)", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -374,7 +434,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (a.=)", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -388,7 +448,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (%.a)", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -402,7 +462,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (a./();)", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -416,7 +476,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error ({%: 1})", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -430,7 +490,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (delete x)", function(done) {
|
it("Should throw syntax error (delete x)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/delete.js';
|
var command = uglifyjscmd + " test/input/invalid/delete.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -444,7 +504,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (function g(arguments))", function(done) {
|
it("Should throw syntax error (function g(arguments))", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/function_1.js';
|
var command = uglifyjscmd + " test/input/invalid/function_1.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -458,7 +518,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (function eval())", function(done) {
|
it("Should throw syntax error (function eval())", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/function_2.js';
|
var command = uglifyjscmd + " test/input/invalid/function_2.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -472,7 +532,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (iife arguments())", function(done) {
|
it("Should throw syntax error (iife arguments())", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/function_3.js';
|
var command = uglifyjscmd + " test/input/invalid/function_3.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -486,7 +546,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (catch (eval))", function(done) {
|
it("Should throw syntax error (catch (eval))", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/try.js';
|
var command = uglifyjscmd + " test/input/invalid/try.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -500,7 +560,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (var eval)", function(done) {
|
it("Should throw syntax error (var eval)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/var.js';
|
var command = uglifyjscmd + " test/input/invalid/var.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -514,7 +574,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (else)", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -528,7 +588,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (return)", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -542,7 +602,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (for-in init)", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -556,7 +616,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (for-in var)", function(done) {
|
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) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -569,6 +629,18 @@ describe("bin/uglifyjs", function() {
|
|||||||
done();
|
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) {
|
it("Should handle literal string as source map input", function(done) {
|
||||||
var command = [
|
var command = [
|
||||||
uglifyjscmd,
|
uglifyjscmd,
|
||||||
@@ -587,7 +659,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function read_map() {
|
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;
|
delete map.sourcesContent;
|
||||||
return JSON.stringify(map).replace(/"/g, '\\"');
|
return JSON.stringify(map).replace(/"/g, '\\"');
|
||||||
}
|
}
|
||||||
@@ -657,7 +729,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
var command = uglifyjscmd + " test/input/issue-3315/input.js --config-file test/input/issue-3315/config.json";
|
var command = uglifyjscmd + " test/input/issue-3315/input.js --config-file test/input/issue-3315/config.json";
|
||||||
exec(command, function(err, stdout) {
|
exec(command, function(err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, 'function f(){"aaaaaaaaaa";var a={prop:1,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();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -674,7 +746,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
var command = uglifyjscmd + " test/input/rename/input.js --rename";
|
var command = uglifyjscmd + " test/input/rename/input.js --rename";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, "function f(a){return b(a);function b(c){return c}}\n");
|
assert.strictEqual(stdout, "function f(a){return b(a);function b(c){return c+c}}\n");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -682,7 +754,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2 --no-rename";
|
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2 --no-rename";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, "function f(n){return function(n){return n}(n)}\n");
|
assert.strictEqual(stdout, "function f(n){return function(n){return n+n}(n)}\n");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -690,7 +762,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2";
|
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, "function f(n){return n}\n");
|
assert.strictEqual(stdout, "function f(n){return n+n}\n");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -698,7 +770,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
var command = uglifyjscmd + " test/input/rename/input.js -c passes=2";
|
var command = uglifyjscmd + " test/input/rename/input.js -c passes=2";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, "function f(x){return function(x){return x}(x)}\n");
|
assert.strictEqual(stdout, "function f(x){return function(x){return x+x}(x)}\n");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var readFileSync = require("fs").readFileSync;
|
var readFileSync = require("fs").readFileSync;
|
||||||
var run_code = require("../sandbox").run_code;
|
var run_code = require("../sandbox").run_code;
|
||||||
var UglifyJS = require("../../");
|
var UglifyJS = require("../..");
|
||||||
|
|
||||||
function read(path) {
|
function read(path) {
|
||||||
return readFileSync(path, "utf8");
|
return readFileSync(path, "utf8");
|
||||||
@@ -9,18 +9,30 @@ function read(path) {
|
|||||||
|
|
||||||
describe("minify", function() {
|
describe("minify", function() {
|
||||||
it("Should test basic sanity of minify with default options", 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);
|
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() {
|
it("Should skip inherited keys from `files`", function() {
|
||||||
var files = Object.create({ skip: this });
|
var files = Object.create({ skip: this });
|
||||||
files[0] = "alert(1 + 1)";
|
files[0] = "alert(1 + 1)";
|
||||||
var result = UglifyJS.minify(files);
|
var result = UglifyJS.minify(files);
|
||||||
|
if (result.error) throw result.error;
|
||||||
assert.strictEqual(result.code, "alert(2);");
|
assert.strictEqual(result.code, "alert(2);");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should work with mangle.cache", function() {
|
it("Should work with mangle.cache", function() {
|
||||||
var cache = {};
|
var cache = {};
|
||||||
var original = "";
|
var original = "";
|
||||||
@@ -53,7 +65,6 @@ describe("minify", function() {
|
|||||||
].join(""));
|
].join(""));
|
||||||
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should work with nameCache", function() {
|
it("Should work with nameCache", function() {
|
||||||
var cache = {};
|
var cache = {};
|
||||||
var original = "";
|
var original = "";
|
||||||
@@ -86,7 +97,6 @@ describe("minify", function() {
|
|||||||
].join(""));
|
].join(""));
|
||||||
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should avoid cached names when mangling top-level variables", function() {
|
it("Should avoid cached names when mangling top-level variables", function() {
|
||||||
var cache = {};
|
var cache = {};
|
||||||
var original = "";
|
var original = "";
|
||||||
@@ -115,7 +125,6 @@ describe("minify", function() {
|
|||||||
].join(""));
|
].join(""));
|
||||||
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should avoid cached names when mangling inner-scoped variables", function() {
|
it("Should avoid cached names when mangling inner-scoped variables", function() {
|
||||||
var cache = {};
|
var cache = {};
|
||||||
var original = "";
|
var original = "";
|
||||||
@@ -139,7 +148,6 @@ describe("minify", function() {
|
|||||||
].join(""));
|
].join(""));
|
||||||
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should not parse invalid use of reserved words", function() {
|
it("Should not parse invalid use of reserved words", function() {
|
||||||
assert.strictEqual(UglifyJS.minify("function enum(){}").error, undefined);
|
assert.strictEqual(UglifyJS.minify("function enum(){}").error, undefined);
|
||||||
assert.strictEqual(UglifyJS.minify("function static(){}").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};');
|
assert.strictEqual(result.code, 'var foo={"x":1,y:2,"z":3};');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should preserve quote styles when quote_style is 3", function() {
|
it("Should preserve quote styles when quote_style is 3", function() {
|
||||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||||
var result = UglifyJS.minify(js, {
|
var result = UglifyJS.minify(js, {
|
||||||
@@ -165,7 +172,6 @@ describe("minify", function() {
|
|||||||
}});
|
}});
|
||||||
assert.strictEqual(result.code, 'var foo={"x":1,y:2,\'z\':3};');
|
assert.strictEqual(result.code, 'var foo={"x":1,y:2,\'z\':3};');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should not preserve quotes in object literals when disabled", function() {
|
it("Should not preserve quotes in object literals when disabled", function() {
|
||||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||||
var result = UglifyJS.minify(js, {
|
var result = UglifyJS.minify(js, {
|
||||||
|
|||||||
@@ -28,4 +28,65 @@ describe("Number literals", function() {
|
|||||||
assert.throws(test(inputs[i]), error, inputs[i]);
|
assert.throws(test(inputs[i]), error, inputs[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
it("Should parse binary, hexadecimal, octal and underscore correctly", function() {
|
||||||
|
[
|
||||||
|
"42",
|
||||||
|
"4_2",
|
||||||
|
"052",
|
||||||
|
"0o52",
|
||||||
|
"0O52",
|
||||||
|
"0o5_2",
|
||||||
|
"0x2a",
|
||||||
|
"0X2A",
|
||||||
|
"0x2_a",
|
||||||
|
"0b101010",
|
||||||
|
"0B101010",
|
||||||
|
"0b101_010",
|
||||||
|
"0.0000000042e+10",
|
||||||
|
"0.0000000042E+10",
|
||||||
|
"0.0_000000042e+10",
|
||||||
|
"0.0000000042e+1_0",
|
||||||
|
"0.000_000_004_2e+1_0",
|
||||||
|
"0.000_000_004_2e+1_0-0B101_010+0x2_A-0o5_2+4_2",
|
||||||
|
].forEach(function(code) {
|
||||||
|
var result = UglifyJS.minify(code, {
|
||||||
|
compress: {
|
||||||
|
expression: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, "42;");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should reject invalid use of underscore", function() {
|
||||||
|
[
|
||||||
|
"_42",
|
||||||
|
"_+42",
|
||||||
|
"+_42",
|
||||||
|
].forEach(function(code) {
|
||||||
|
var node = UglifyJS.parse(code, {
|
||||||
|
expression: true,
|
||||||
|
});
|
||||||
|
assert.ok(!node.is_constant(), code);
|
||||||
|
assert.ok(!(node instanceof UglifyJS.AST_Statement), code);
|
||||||
|
});
|
||||||
|
[
|
||||||
|
"42_",
|
||||||
|
"4__2",
|
||||||
|
"0_52",
|
||||||
|
"05_2",
|
||||||
|
"0_o52",
|
||||||
|
"0o_52",
|
||||||
|
"0.0000000042_e10",
|
||||||
|
"0.0000000042e_10",
|
||||||
|
"0.0000000042e_+10",
|
||||||
|
"0.0000000042e+_10",
|
||||||
|
].forEach(function(code) {
|
||||||
|
assert.throws(function() {
|
||||||
|
UglifyJS.parse(code);
|
||||||
|
}, function(e) {
|
||||||
|
return e instanceof UglifyJS.JS_Parse_Error;
|
||||||
|
}, code);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -486,4 +486,19 @@ describe("operator", function() {
|
|||||||
assert.strictEqual(UglifyJS.parse(exp[0]).print_to_string(), exp[1] + ";");
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ describe("test/reduce.js", function() {
|
|||||||
});
|
});
|
||||||
it("Should eliminate unreferenced labels", function() {
|
it("Should eliminate unreferenced labels", function() {
|
||||||
var result = reduce_test(read("test/input/reduce/label.js"), {
|
var result = reduce_test(read("test/input/reduce/label.js"), {
|
||||||
|
compress: {
|
||||||
|
unsafe_math: true,
|
||||||
|
},
|
||||||
mangle: false,
|
mangle: false,
|
||||||
}, {
|
}, {
|
||||||
verbose: false,
|
verbose: false,
|
||||||
@@ -186,7 +189,7 @@ describe("test/reduce.js", function() {
|
|||||||
].join("\n"));
|
].join("\n"));
|
||||||
});
|
});
|
||||||
it("Should reduce infinite loops with reasonable performance", function() {
|
it("Should reduce infinite loops with reasonable performance", function() {
|
||||||
if (semver.satisfies(process.version, "0.10")) return;
|
if (semver.satisfies(process.version, "<=0.10")) return;
|
||||||
this.timeout(120000);
|
this.timeout(120000);
|
||||||
var result = reduce_test("while (/9/.test(1 - .8));", {
|
var result = reduce_test("while (/9/.test(1 - .8));", {
|
||||||
compress: {
|
compress: {
|
||||||
@@ -211,7 +214,7 @@ describe("test/reduce.js", function() {
|
|||||||
it("Should ignore difference in Error.message", function() {
|
it("Should ignore difference in Error.message", function() {
|
||||||
var result = reduce_test("null[function() {\n}];");
|
var result = reduce_test("null[function() {\n}];");
|
||||||
if (result.error) throw result.error;
|
if (result.error) throw result.error;
|
||||||
assert.strictEqual(result.code, (semver.satisfies(process.version, "0.10") ? [
|
assert.strictEqual(result.code, (semver.satisfies(process.version, "<=0.10") ? [
|
||||||
"// Can't reproduce test failure",
|
"// Can't reproduce test failure",
|
||||||
"// minify options: {}",
|
"// minify options: {}",
|
||||||
] : [
|
] : [
|
||||||
@@ -246,4 +249,68 @@ describe("test/reduce.js", function() {
|
|||||||
"// }",
|
"// }",
|
||||||
].join("\n"));
|
].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 assert = require("assert");
|
||||||
var readFileSync = require("fs").readFileSync;
|
var fs = require("fs");
|
||||||
var SourceMapConsumer = require("source-map").SourceMapConsumer;
|
|
||||||
var UglifyJS = require("../node");
|
var UglifyJS = require("../node");
|
||||||
|
|
||||||
function read(path) {
|
function read(path) {
|
||||||
return readFileSync(path, "utf8");
|
return fs.readFileSync(path, "utf8");
|
||||||
}
|
}
|
||||||
|
|
||||||
function source_map(code) {
|
function source_map(code) {
|
||||||
return JSON.parse(UglifyJS.minify(code, {
|
var result = UglifyJS.minify(code, {
|
||||||
compress: false,
|
compress: false,
|
||||||
mangle: false,
|
mangle: false,
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
}).map);
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
return JSON.parse(result.map);
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_map() {
|
function get_map() {
|
||||||
@@ -44,7 +45,7 @@ function prepare_map(sourceMap) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (result.error) throw result.error;
|
if (result.error) throw result.error;
|
||||||
return new SourceMapConsumer(result.map);
|
return JSON.parse(result.map);
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("sourcemaps", function() {
|
describe("sourcemaps", function() {
|
||||||
@@ -66,6 +67,40 @@ describe("sourcemaps", function() {
|
|||||||
].join("\n"));
|
].join("\n"));
|
||||||
assert.deepEqual(map.names, [ "enabled", "x" ]);
|
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() {
|
it("Should mark array/object literals", function() {
|
||||||
var result = UglifyJS.minify([
|
var result = UglifyJS.minify([
|
||||||
"var obj = {};",
|
"var obj = {};",
|
||||||
@@ -87,7 +122,7 @@ describe("sourcemaps", function() {
|
|||||||
});
|
});
|
||||||
if (result.error) throw result.error;
|
if (result.error) throw result.error;
|
||||||
assert.strictEqual(result.code, code);
|
assert.strictEqual(result.code, code);
|
||||||
assert.strictEqual(result.map, '{"version":3,"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() {
|
it("Should produce same source map with DOS or UNIX line endings", function() {
|
||||||
var code = [
|
var code = [
|
||||||
@@ -108,9 +143,9 @@ describe("sourcemaps", function() {
|
|||||||
|
|
||||||
describe("inSourceMap", function() {
|
describe("inSourceMap", function() {
|
||||||
it("Should read the given string filename correctly when sourceMapIncludeSources is enabled", 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: {
|
sourceMap: {
|
||||||
content: read("./test/input/issue-1236/simple.js.map"),
|
content: read("test/input/issue-1236/simple.js.map"),
|
||||||
filename: "simple.min.js",
|
filename: "simple.min.js",
|
||||||
includeSources: true
|
includeSources: true
|
||||||
}
|
}
|
||||||
@@ -122,7 +157,7 @@ describe("sourcemaps", function() {
|
|||||||
assert.equal(map.sourcesContent[0], 'let foo = x => "foo " + x;\nconsole.log(foo("bar"));');
|
assert.equal(map.sourcesContent[0], 'let foo = x => "foo " + x;\nconsole.log(foo("bar"));');
|
||||||
});
|
});
|
||||||
it("Should process inline source map", function() {
|
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 },
|
compress: { toplevel: true },
|
||||||
sourceMap: {
|
sourceMap: {
|
||||||
content: "inline",
|
content: "inline",
|
||||||
@@ -131,10 +166,10 @@ describe("sourcemaps", function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (result.error) throw result.error;
|
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() {
|
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,
|
mangle: false,
|
||||||
sourceMap: {
|
sourceMap: {
|
||||||
content: "inline"
|
content: "inline"
|
||||||
@@ -146,8 +181,8 @@ describe("sourcemaps", function() {
|
|||||||
});
|
});
|
||||||
it("Should handle multiple input and inline source map", function() {
|
it("Should handle multiple input and inline source map", function() {
|
||||||
var result = UglifyJS.minify([
|
var result = UglifyJS.minify([
|
||||||
read("./test/input/issue-520/input.js"),
|
read("test/input/issue-520/input.js"),
|
||||||
read("./test/input/issue-1323/sample.js"),
|
read("test/input/issue-1323/sample.js"),
|
||||||
], {
|
], {
|
||||||
sourceMap: {
|
sourceMap: {
|
||||||
content: "inline",
|
content: "inline",
|
||||||
@@ -163,7 +198,7 @@ describe("sourcemaps", function() {
|
|||||||
assert.deepEqual(result.warnings, [ "WARN: inline source map not found: 1" ]);
|
assert.deepEqual(result.warnings, [ "WARN: inline source map not found: 1" ]);
|
||||||
});
|
});
|
||||||
it("Should drop source contents for includeSources=false", function() {
|
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,
|
compress: false,
|
||||||
mangle: false,
|
mangle: false,
|
||||||
sourceMap: {
|
sourceMap: {
|
||||||
@@ -186,7 +221,7 @@ describe("sourcemaps", function() {
|
|||||||
assert.ok(!("sourcesContent" in map));
|
assert.ok(!("sourcesContent" in map));
|
||||||
});
|
});
|
||||||
it("Should parse the correct sourceMappingURL", function() {
|
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 },
|
compress: { toplevel: true },
|
||||||
sourceMap: {
|
sourceMap: {
|
||||||
content: "inline",
|
content: "inline",
|
||||||
@@ -195,10 +230,10 @@ describe("sourcemaps", function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (result.error) throw result.error;
|
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() {
|
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,
|
compress: false,
|
||||||
mangle: false,
|
mangle: false,
|
||||||
sourceMap: {
|
sourceMap: {
|
||||||
@@ -230,7 +265,7 @@ describe("sourcemaps", function() {
|
|||||||
assert.strictEqual(code, "var a=function(n){return n};");
|
assert.strictEqual(code, "var a=function(n){return n};");
|
||||||
});
|
});
|
||||||
it("Should work with max_line_len", function() {
|
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: {
|
compress: {
|
||||||
directives: false,
|
directives: false,
|
||||||
},
|
},
|
||||||
@@ -242,7 +277,7 @@ describe("sourcemaps", function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (result.error) throw result.error;
|
if (result.error) throw result.error;
|
||||||
assert.strictEqual(result.code, read("./test/input/issue-505/output.js"));
|
assert.strictEqual(result.code, read("test/input/issue-505/output.js"));
|
||||||
});
|
});
|
||||||
it("Should work with unicode characters", function() {
|
it("Should work with unicode characters", function() {
|
||||||
var code = [
|
var code = [
|
||||||
@@ -278,32 +313,42 @@ describe("sourcemaps", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("input 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() {
|
it("Should copy over original sourcesContent", function() {
|
||||||
var orig = get_map();
|
var orig = get_map();
|
||||||
var map = prepare_map(orig);
|
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() {
|
it("Should copy sourcesContent if sources are relative", function() {
|
||||||
var relativeMap = get_map();
|
var relativeMap = get_map();
|
||||||
relativeMap.sources = ['./index.js'];
|
relativeMap.sources = ['./index.js'];
|
||||||
var map = prepare_map(relativeMap);
|
var map = prepare_map(relativeMap);
|
||||||
assert.notEqual(map.sourcesContent, null);
|
assert.strictEqual(map.sources.length, 1);
|
||||||
assert.equal(map.sourcesContent.length, 1);
|
assert.strictEqual(map.sources[0], "./index.js");
|
||||||
assert.equal(map.sourceContentFor("index.js"), relativeMap.sourcesContent[0]);
|
assert.strictEqual(map.sourcesContent.length, 1);
|
||||||
|
assert.equal(map.sourcesContent[0], relativeMap.sourcesContent[0]);
|
||||||
});
|
});
|
||||||
it("Should not have invalid mappings from inputSourceMap", function() {
|
it("Should not have invalid mappings from inputSourceMap", function() {
|
||||||
var map = prepare_map(get_map());
|
var map = prepare_map(get_map());
|
||||||
// The original source has only 2 lines, check that mappings don't have more lines
|
// 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";
|
var msg = "Mapping should not have higher line number than the original file had";
|
||||||
map.eachMapping(function(mapping) {
|
var lines = map.mappings.split(/;/);
|
||||||
assert.ok(mapping.originalLine <= 2, msg);
|
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);
|
||||||
});
|
});
|
||||||
map.allGeneratedPositionsFor({
|
|
||||||
source: "index.js",
|
|
||||||
line: 1,
|
|
||||||
column: 1
|
|
||||||
}).forEach(function(pos) {
|
|
||||||
assert.ok(pos.line <= 2, msg);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,64 +1,58 @@
|
|||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
|
var run_code = require("../sandbox").run_code;
|
||||||
var UglifyJS = require("../node");
|
var UglifyJS = require("../node");
|
||||||
|
|
||||||
describe("String literals", function() {
|
describe("String literals", function() {
|
||||||
it("Should throw syntax error if a string literal contains a newline", function() {
|
it("Should throw syntax error if a string literal contains a newline", function() {
|
||||||
var inputs = [
|
[
|
||||||
"'\n'",
|
"'\n'",
|
||||||
"'\r'",
|
"'\r'",
|
||||||
'"\r\n"',
|
'"\r\n"',
|
||||||
"'\u2028'",
|
"'\u2028'",
|
||||||
'"\u2029"'
|
'"\u2029"',
|
||||||
];
|
].forEach(function(input) {
|
||||||
|
assert.throws(function() {
|
||||||
var test = function(input) {
|
|
||||||
return function() {
|
|
||||||
var ast = UglifyJS.parse(input);
|
var ast = UglifyJS.parse(input);
|
||||||
};
|
}, function(e) {
|
||||||
};
|
|
||||||
|
|
||||||
var error = function(e) {
|
|
||||||
return e instanceof UglifyJS.JS_Parse_Error
|
return e instanceof UglifyJS.JS_Parse_Error
|
||||||
&& e.message === "Unterminated string constant";
|
&& e.message === "Unterminated string constant";
|
||||||
};
|
|
||||||
|
|
||||||
for (var input in inputs) {
|
|
||||||
assert.throws(test(inputs[input]), error);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should handle line continuation correctly", function() {
|
||||||
|
[
|
||||||
|
'"\\\r"',
|
||||||
|
'"\\\n"',
|
||||||
|
'"\\\r\n"',
|
||||||
|
].forEach(function(str) {
|
||||||
|
var code = "console.log(" + str + ");";
|
||||||
|
var result = UglifyJS.minify(code);
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(run_code(result.code), run_code(code));
|
||||||
|
});
|
||||||
|
});
|
||||||
it("Should not throw syntax error if a string has a line continuation", function() {
|
it("Should not throw syntax error if a string has a line continuation", function() {
|
||||||
var output = UglifyJS.parse('var a = "a\\\nb";').print_to_string();
|
var ast = UglifyJS.parse('var a = "a\\\nb";');
|
||||||
assert.equal(output, 'var a="ab";');
|
assert.equal(ast.print_to_string(), 'var a="ab";');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should throw error in strict mode if string contains escaped octalIntegerLiteral", function() {
|
it("Should throw error in strict mode if string contains escaped octalIntegerLiteral", function() {
|
||||||
var inputs = [
|
[
|
||||||
'"use strict";\n"\\76";',
|
'"use strict";\n"\\76";',
|
||||||
'"use strict";\nvar foo = "\\76";',
|
'"use strict";\nvar foo = "\\76";',
|
||||||
'"use strict";\n"\\1";',
|
'"use strict";\n"\\1";',
|
||||||
'"use strict";\n"\\07";',
|
'"use strict";\n"\\07";',
|
||||||
'"use strict";\n"\\011"'
|
'"use strict";\n"\\011"',
|
||||||
];
|
].forEach(function(input) {
|
||||||
|
assert.throws(function() {
|
||||||
var test = function(input) {
|
|
||||||
return function() {
|
|
||||||
var output = UglifyJS.parse(input);
|
var output = UglifyJS.parse(input);
|
||||||
}
|
}, function(e) {
|
||||||
};
|
|
||||||
|
|
||||||
var error = function(e) {
|
|
||||||
return e instanceof UglifyJS.JS_Parse_Error
|
return e instanceof UglifyJS.JS_Parse_Error
|
||||||
&& e.message === "Legacy octal escape sequences are not allowed in strict mode";
|
&& e.message === "Legacy octal escape sequences are not allowed in strict mode";
|
||||||
}
|
|
||||||
|
|
||||||
for (var input in inputs) {
|
|
||||||
assert.throws(test(inputs[input]), error);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
it("Should not throw error outside strict mode if string contains escaped octalIntegerLiteral", function() {
|
it("Should not throw error outside strict mode if string contains escaped octalIntegerLiteral", function() {
|
||||||
var tests = [
|
[
|
||||||
[ ';"\\76";', ';">";' ],
|
[ ';"\\76";', ';">";' ],
|
||||||
[ ';"\\0";', ';"\\0";' ],
|
[ ';"\\0";', ';"\\0";' ],
|
||||||
[ ';"\\08"', ';"\\x008";' ],
|
[ ';"\\08"', ';"\\x008";' ],
|
||||||
@@ -66,19 +60,15 @@ describe("String literals", function() {
|
|||||||
[ ';"\\0008"', ';"\\x008";' ],
|
[ ';"\\0008"', ';"\\x008";' ],
|
||||||
[ ';"use\\\n strict";\n"\\07";', ';"use strict";"\07";' ],
|
[ ';"use\\\n strict";\n"\\07";', ';"use strict";"\07";' ],
|
||||||
[ '"use strict" === "use strict";\n"\\76";', '"use strict"==="use strict";">";' ],
|
[ '"use strict" === "use strict";\n"\\76";', '"use strict"==="use strict";">";' ],
|
||||||
];
|
].forEach(function(test) {
|
||||||
|
var ast = UglifyJS.parse(test[0]);
|
||||||
for (var test in tests) {
|
assert.equal(ast.print_to_string(), test[1]);
|
||||||
var output = UglifyJS.parse(tests[test][0]).print_to_string();
|
});
|
||||||
assert.equal(output, tests[test][1]);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should not throw error when digit is 8 or 9", 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";;"\\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";;"\\09"').print_to_string(), '"use strict";;"\\x009";');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should not unescape unpaired surrogates", function() {
|
it("Should not unescape unpaired surrogates", function() {
|
||||||
var code = [];
|
var code = [];
|
||||||
for (var i = 0; i <= 0xF; i++) {
|
for (var i = 0; i <= 0xF; i++) {
|
||||||
@@ -115,4 +105,33 @@ describe("String literals", function() {
|
|||||||
assert.ok(code.length > ascii.code.length);
|
assert.ok(code.length > ascii.code.length);
|
||||||
assert.strictEqual(eval(code), eval(ascii.code));
|
assert.strictEqual(eval(code), eval(ascii.code));
|
||||||
});
|
});
|
||||||
|
it("Should reject invalid Unicode escape sequence", function() {
|
||||||
|
[
|
||||||
|
'var foo = "\\u-111"',
|
||||||
|
'var bar = "\\u{-1}"',
|
||||||
|
'var baz = "\\ugggg"',
|
||||||
|
].forEach(function(test) {
|
||||||
|
assert.throws(function() {
|
||||||
|
UglifyJS.parse(test);
|
||||||
|
}, function(e) {
|
||||||
|
return e instanceof UglifyJS.JS_Parse_Error
|
||||||
|
&& e.message === "Invalid hex-character pattern in string";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should reject invalid code points in Unicode escape sequence", function() {
|
||||||
|
[
|
||||||
|
// A bit over the valid range
|
||||||
|
'"\\u{110000}"',
|
||||||
|
// 32-bit overflow resulting in "a"
|
||||||
|
'"\\u{100000061}"',
|
||||||
|
].forEach(function(test) {
|
||||||
|
assert.throws(function() {
|
||||||
|
UglifyJS.parse(test);
|
||||||
|
}, function(e) {
|
||||||
|
return e instanceof UglifyJS.JS_Parse_Error
|
||||||
|
&& /^Invalid character code: /.test(e.message);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ describe("With", function() {
|
|||||||
var ast = UglifyJS.parse("with(e) {f(1, 2)}");
|
var ast = UglifyJS.parse("with(e) {f(1, 2)}");
|
||||||
ast.figure_out_scope();
|
ast.figure_out_scope();
|
||||||
assert.equal(ast.uses_with, true);
|
assert.equal(ast.uses_with, true);
|
||||||
assert.equal(ast.body[0].expression.scope.uses_with, true);
|
assert.equal(ast.body[0].expression.scope.resolve().uses_with, true);
|
||||||
assert.equal(ast.body[0].body.body[0].body.expression.scope.uses_with, true);
|
assert.equal(ast.body[0].body.body[0].body.expression.scope.resolve().uses_with, true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -24,11 +24,22 @@ function try_beautify(code) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function test(original, estree, description) {
|
function validate(ast) {
|
||||||
var transformed = UglifyJS.minify(UglifyJS.AST_Node.from_mozilla_ast(estree), {
|
try {
|
||||||
|
ast.walk(new UglifyJS.TreeWalker(function(node) {
|
||||||
|
node.validate();
|
||||||
|
}));
|
||||||
|
} catch (e) {
|
||||||
|
return { error: e };
|
||||||
|
}
|
||||||
|
return UglifyJS.minify(ast, {
|
||||||
compress: false,
|
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) {
|
if (transformed.error || original !== transformed.code) {
|
||||||
console.log("//=============================================================");
|
console.log("//=============================================================");
|
||||||
console.log("// !!!!!! Failed... round", round);
|
console.log("// !!!!!! Failed... round", round);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
var fs = require("fs");
|
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");
|
if (/exports\.js$/.test(file)) file = require.resolve("./exports");
|
||||||
return fs.readFileSync(file, "utf8");
|
return fs.readFileSync(file, "utf8");
|
||||||
}).join("\n\n"))(require("source-map"), exports);
|
}).join("\n\n"))(exports);
|
||||||
|
|||||||
301
test/reduce.js
301
test/reduce.js
@@ -1,37 +1,45 @@
|
|||||||
var crypto = require("crypto");
|
var crypto = require("crypto");
|
||||||
var U = require("./node");
|
var U = require("..");
|
||||||
var List = U.List;
|
var List = U.List;
|
||||||
var os = require("os");
|
var os = require("os");
|
||||||
var sandbox = require("./sandbox");
|
var sandbox = require("./sandbox");
|
||||||
|
|
||||||
// Reduce a ufuzz-style `console.log` based test case by iteratively replacing
|
// Reduce a test case by iteratively replacing AST nodes with various
|
||||||
// AST nodes with various permutations. Each AST_Statement in the tree is also
|
// permutations. Each AST_Statement in the tree is also speculatively dropped
|
||||||
// speculatively dropped to determine whether it is needed. If the altered
|
// to determine whether it is needed. If the altered tree and the last known
|
||||||
// tree and the last known good tree produce the same non-nil error-free output
|
// good tree produce the same output after being run, then the permutation
|
||||||
// after being run, then the permutation survives to the next generation and
|
// survives to the next generation and is the basis for subsequent iterations.
|
||||||
// is the basis for subsequent iterations. The test case is reduced as a
|
// The test case is reduced as a consequence of complex expressions being
|
||||||
// consequence of complex expressions being replaced with simpler ones.
|
// replaced with simpler ones. Note that a reduced test case will have
|
||||||
// This function assumes that the testcase will not result in a parse or
|
// different runtime output - it is not functionally equivalent to the
|
||||||
// runtime Error. Note that a reduced test case will have different runtime
|
// original. The only criteria is that once the generated reduced test case is
|
||||||
// output - it is not functionally equivalent to the original. The only criteria
|
// run without minification, it will produce different output from the code
|
||||||
// is that once the generated reduced test case is run without minification, it
|
// minified with `minify_options`. Returns a `minify` result object.
|
||||||
// will produce different output from the code minified with `minify_options`.
|
|
||||||
// Returns a `minify` result object with an additonal boolean property `reduced`.
|
|
||||||
|
|
||||||
|
Error.stackTraceLimit = Infinity;
|
||||||
module.exports = function reduce_test(testcase, minify_options, reduce_options) {
|
module.exports = function reduce_test(testcase, minify_options, reduce_options) {
|
||||||
if (testcase instanceof U.AST_Node) testcase = testcase.print_to_string();
|
if (testcase instanceof U.AST_Node) testcase = testcase.print_to_string();
|
||||||
minify_options = minify_options || {};
|
minify_options = minify_options || {};
|
||||||
reduce_options = reduce_options || {};
|
reduce_options = reduce_options || {};
|
||||||
var max_iterations = reduce_options.max_iterations || 1000;
|
var max_iterations = reduce_options.max_iterations || 1000;
|
||||||
var max_timeout = reduce_options.max_timeout || 10000;
|
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 verbose = reduce_options.verbose;
|
||||||
var minify_options_json = JSON.stringify(minify_options, null, 2);
|
var minify_options_json = JSON.stringify(minify_options, null, 2);
|
||||||
var result_cache = Object.create(null);
|
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
|
// the initial timeout to assess the viability of the test case must be large
|
||||||
var differs = producesDifferentResultWhenMinified(result_cache, testcase, minify_options, max_timeout);
|
var differs = test_for_diff(testcase, minify_options, result_cache, max_timeout);
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
console.error("// Node.js " + process.version + " on " + os.platform() + " " + os.arch());
|
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) {
|
if (!differs) {
|
||||||
// same stdout result produced when minified
|
// same stdout result produced when minified
|
||||||
@@ -39,16 +47,19 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
code: [
|
code: [
|
||||||
"// Can't reproduce test failure",
|
"// Can't reproduce test failure",
|
||||||
"// minify options: " + to_comment(minify_options_json)
|
"// minify options: " + to_comment(minify_options_json)
|
||||||
].join("\n")
|
].join("\n"),
|
||||||
|
warnings: warnings,
|
||||||
};
|
};
|
||||||
} else if (differs.timed_out) {
|
} else if (differs.timed_out) {
|
||||||
return {
|
return {
|
||||||
code: [
|
code: [
|
||||||
"// Can't reproduce test failure within " + max_timeout + "ms",
|
"// Can't reproduce test failure within " + max_timeout + "ms",
|
||||||
"// minify options: " + to_comment(minify_options_json)
|
"// minify options: " + to_comment(minify_options_json)
|
||||||
].join("\n")
|
].join("\n"),
|
||||||
|
warnings: warnings,
|
||||||
};
|
};
|
||||||
} else if (differs.error) {
|
} else if (differs.error) {
|
||||||
|
differs.warnings = warnings;
|
||||||
return differs;
|
return differs;
|
||||||
} else if (is_error(differs.unminified_result)
|
} else if (is_error(differs.unminified_result)
|
||||||
&& is_error(differs.minified_result)
|
&& is_error(differs.minified_result)
|
||||||
@@ -57,7 +68,8 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
code: [
|
code: [
|
||||||
"// No differences except in error message",
|
"// No differences except in error message",
|
||||||
"// minify options: " + to_comment(minify_options_json)
|
"// minify options: " + to_comment(minify_options_json)
|
||||||
].join("\n")
|
].join("\n"),
|
||||||
|
warnings: warnings,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
max_timeout = Math.min(100 * differs.elapsed, max_timeout);
|
max_timeout = Math.min(100 * differs.elapsed, max_timeout);
|
||||||
@@ -100,19 +112,18 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
// no structural AST changes before this point.
|
// no structural AST changes before this point.
|
||||||
if (node.start._permute >= REPLACEMENTS.length) return;
|
if (node.start._permute >= REPLACEMENTS.length) return;
|
||||||
|
|
||||||
if (parent instanceof U.AST_Assign
|
|
||||||
&& parent.left === node
|
|
||||||
|| parent instanceof U.AST_Unary
|
|
||||||
&& parent.expression === node
|
|
||||||
&& ["++", "--", "delete"].indexOf(parent.operator) >= 0) {
|
|
||||||
// ignore lvalues
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
if ((parent instanceof U.AST_For || parent instanceof U.AST_ForIn)
|
// preserve for (var xxx; ...)
|
||||||
&& parent.init === node && node instanceof U.AST_Var) {
|
if (parent instanceof U.AST_For && parent.init === node && node instanceof U.AST_Definitions) return node;
|
||||||
// preserve for (var ...)
|
// preserve for (xxx in ...)
|
||||||
return node;
|
if (parent instanceof U.AST_ForIn && parent.init === node) return node;
|
||||||
}
|
|
||||||
|
|
||||||
// node specific permutations with no parent logic
|
// node specific permutations with no parent logic
|
||||||
|
|
||||||
@@ -125,43 +136,18 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (node instanceof U.AST_Binary) {
|
else if (node instanceof U.AST_Binary) {
|
||||||
CHANGED = true;
|
|
||||||
var permute = ((node.start._permute += step) * steps | 0) % 4;
|
var permute = ((node.start._permute += step) * steps | 0) % 4;
|
||||||
var expr = [
|
var expr = [
|
||||||
node.left,
|
node.left,
|
||||||
node.right,
|
node.right,
|
||||||
][ permute & 1 ];
|
][ permute & 1 ];
|
||||||
if (permute < 2) return expr;
|
|
||||||
// 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: [ expr ],
|
|
||||||
start: {},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (node instanceof U.AST_Catch || node instanceof U.AST_Finally) {
|
|
||||||
// drop catch or finally block
|
|
||||||
node.start._permute++;
|
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
return null;
|
return permute < 2 ? expr : wrap_with_console_log(expr);
|
||||||
}
|
|
||||||
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_BlockStatement) {
|
else if (node instanceof U.AST_BlockStatement) {
|
||||||
if (in_list) {
|
if (in_list && node.body.filter(function(node) {
|
||||||
|
return node instanceof U.AST_Const;
|
||||||
|
}).length == 0) {
|
||||||
node.start._permute++;
|
node.start._permute++;
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
return List.splice(node.body);
|
return List.splice(node.body);
|
||||||
@@ -193,12 +179,26 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
return to_sequence(seq);
|
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) {
|
else if (node instanceof U.AST_Defun) {
|
||||||
switch (((node.start._permute += step) * steps | 0) % 2) {
|
switch (((node.start._permute += step) * steps | 0) % 2) {
|
||||||
case 0:
|
case 0:
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
return List.skip;
|
return List.skip;
|
||||||
case 1:
|
default:
|
||||||
if (!has_exit(node)) {
|
if (!has_exit(node)) {
|
||||||
// hoist function declaration body
|
// hoist function declaration body
|
||||||
var body = node.body;
|
var body = node.body;
|
||||||
@@ -230,15 +230,11 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
return to_statement(expr);
|
return to_statement(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (node instanceof U.AST_PropAccess) {
|
else if (node instanceof U.AST_Finally) {
|
||||||
var expr = [
|
// drop finally block
|
||||||
node.expression,
|
node.start._permute++;
|
||||||
node.property instanceof U.AST_Node && node.property,
|
|
||||||
][ node.start._permute++ % 2 ];
|
|
||||||
if (expr) {
|
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
return expr;
|
return null;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (node instanceof U.AST_For) {
|
else if (node instanceof U.AST_For) {
|
||||||
var expr = [
|
var expr = [
|
||||||
@@ -287,6 +283,16 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
return expr;
|
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) {
|
else if (node instanceof U.AST_SimpleStatement) {
|
||||||
if (node.body instanceof U.AST_Call && node.body.expression instanceof U.AST_Function) {
|
if (node.body instanceof U.AST_Call && node.body.expression instanceof U.AST_Function) {
|
||||||
// hoist simple statement IIFE function expression body
|
// hoist simple statement IIFE function expression body
|
||||||
@@ -406,7 +412,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
start: {},
|
start: {},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (node instanceof U.AST_Var) {
|
else if (node instanceof U.AST_Definitions) {
|
||||||
// remove empty var statement
|
// remove empty var statement
|
||||||
if (node.definitions.length == 0) return in_list ? List.skip : new U.AST_EmptyStatement({
|
if (node.definitions.length == 0) return in_list ? List.skip : new U.AST_EmptyStatement({
|
||||||
start: {},
|
start: {},
|
||||||
@@ -414,19 +420,43 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var diff_error_message;
|
||||||
for (var pass = 1; pass <= 3; ++pass) {
|
for (var pass = 1; pass <= 3; ++pass) {
|
||||||
var testcase_ast = U.parse(testcase);
|
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 && node.argname) {
|
||||||
|
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) {
|
testcase_ast.walk(new U.TreeWalker(function(node) {
|
||||||
// unshare start props to retain visit data between iterations
|
// unshare start props to retain visit data between iterations
|
||||||
node.start = JSON.parse(JSON.stringify(node.start));
|
node.start = JSON.parse(JSON.stringify(node.start));
|
||||||
node.start._permute = 0;
|
node.start._permute = 0;
|
||||||
}));
|
}));
|
||||||
|
var before_iterations = testcase;
|
||||||
for (var c = 0; c < max_iterations; ++c) {
|
for (var c = 0; c < max_iterations; ++c) {
|
||||||
if (verbose) {
|
if (verbose && pass == 1 && c % 25 == 0) {
|
||||||
if (pass == 1 && c % 25 == 0) {
|
log("// reduce test pass " + pass + ", iteration " + c + ": " + testcase.length + " bytes");
|
||||||
console.error("// reduce test pass "
|
|
||||||
+ pass + ", iteration " + c + ": " + testcase.length + " bytes");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var CHANGED = false;
|
var CHANGED = false;
|
||||||
var code_ast = testcase_ast.clone(true).transform(tt);
|
var code_ast = testcase_ast.clone(true).transform(tt);
|
||||||
@@ -436,12 +466,12 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
// AST is not well formed.
|
// AST is not well formed.
|
||||||
// no harm done - just log the error, ignore latest change and continue iterating.
|
// no harm done - just log the error, ignore latest change and continue iterating.
|
||||||
console.error("*** Error generating code from AST.");
|
log("*** Error generating code from AST.");
|
||||||
console.error(ex);
|
log(ex.stack);
|
||||||
console.error("*** Discarding permutation and continuing.");
|
log("*** Discarding permutation and continuing.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var diff = producesDifferentResultWhenMinified(result_cache, code, minify_options, max_timeout);
|
var diff = test_for_diff(code, minify_options, result_cache, max_timeout);
|
||||||
if (diff) {
|
if (diff) {
|
||||||
if (diff.timed_out) {
|
if (diff.timed_out) {
|
||||||
// can't trust the validity of `code_ast` and `code` when timed out.
|
// can't trust the validity of `code_ast` and `code` when timed out.
|
||||||
@@ -449,14 +479,15 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
} else if (diff.error) {
|
} else if (diff.error) {
|
||||||
// something went wrong during minify() - could be malformed AST or genuine bug.
|
// 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.
|
// no harm done - just log code & error, ignore latest change and continue iterating.
|
||||||
console.error("*** Error during minification.");
|
log("*** Error during minification.");
|
||||||
console.error(code);
|
log(code);
|
||||||
console.error(diff.error);
|
log(diff.error.stack);
|
||||||
console.error("*** Discarding permutation and continuing.");
|
log("*** Discarding permutation and continuing.");
|
||||||
} else if (is_error(diff.unminified_result)
|
} else if (is_error(diff.unminified_result)
|
||||||
&& is_error(diff.minified_result)
|
&& is_error(diff.minified_result)
|
||||||
&& diff.unminified_result.name == diff.minified_result.name) {
|
&& diff.unminified_result.name == diff.minified_result.name) {
|
||||||
// ignore difference in error messages caused by minification
|
// ignore difference in error messages caused by minification
|
||||||
|
diff_error_message = testcase;
|
||||||
} else {
|
} else {
|
||||||
// latest permutation is valid, so use it as the basis of new changes
|
// latest permutation is valid, so use it as the basis of new changes
|
||||||
testcase_ast = code_ast;
|
testcase_ast = code_ast;
|
||||||
@@ -465,13 +496,35 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c == 0) break;
|
if (before_iterations === testcase) break;
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
console.error("// reduce test pass " + pass + ": " + testcase.length + " bytes");
|
log("// reduce test pass " + pass + ": " + testcase.length + " bytes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var beautified = U.minify(testcase, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
beautify: true,
|
||||||
|
braces: true,
|
||||||
|
comments: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
testcase = {
|
||||||
|
code: testcase,
|
||||||
|
};
|
||||||
|
if (!beautified.error) {
|
||||||
|
diff = test_for_diff(beautified.code, minify_options, result_cache, max_timeout);
|
||||||
|
if (diff && !diff.timed_out && !diff.error) {
|
||||||
|
testcase = beautified;
|
||||||
|
testcase.code = "// (beautified)\n" + testcase.code;
|
||||||
|
differs = diff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
testcase = try_beautify(result_cache, testcase, minify_options, differs.unminified_result, max_timeout);
|
|
||||||
var lines = [ "" ];
|
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 unminified_result = strip_color_codes(differs.unminified_result);
|
||||||
var minified_result = strip_color_codes(differs.minified_result);
|
var minified_result = strip_color_codes(differs.minified_result);
|
||||||
if (trim_trailing_whitespace(unminified_result) == trim_trailing_whitespace(minified_result)) {
|
if (trim_trailing_whitespace(unminified_result) == trim_trailing_whitespace(minified_result)) {
|
||||||
@@ -486,8 +539,10 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
"// minify: " + to_comment(minified_result)
|
"// minify: " + to_comment(minified_result)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
lines.push("// options: " + to_comment(minify_options_json));
|
lines.push("// options: " + to_comment(minify_options_json));
|
||||||
testcase.code += lines.join("\n");
|
testcase.code += lines.join("\n");
|
||||||
|
testcase.warnings = warnings;
|
||||||
return testcase;
|
return testcase;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -504,28 +559,6 @@ function trim_trailing_whitespace(value) {
|
|||||||
return ("" + value).replace(/\s+$/, "");
|
return ("" + value).replace(/\s+$/, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
function try_beautify(result_cache, testcase, minify_options, expected, 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);
|
|
||||||
var actual = run_code(result_cache, result.code, toplevel, timeout);
|
|
||||||
if (!sandbox.same_stdout(expected, actual)) return {
|
|
||||||
code: testcase,
|
|
||||||
};
|
|
||||||
result.code = "// (beautified)\n" + result.code;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function has_exit(fn) {
|
function has_exit(fn) {
|
||||||
var found = false;
|
var found = false;
|
||||||
var tw = new U.TreeWalker(function(node) {
|
var tw = new U.TreeWalker(function(node) {
|
||||||
@@ -592,31 +625,59 @@ function to_statement(node) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function run_code(result_cache, code, toplevel, timeout) {
|
function wrap_with_console_log(node) {
|
||||||
var key = crypto.createHash("sha1").update(code).digest("base64");
|
// wrap with console.log()
|
||||||
return result_cache[key] || (result_cache[key] = sandbox.run_code(code, toplevel, timeout));
|
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 producesDifferentResultWhenMinified(result_cache, code, minify_options, max_timeout) {
|
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);
|
var minified = U.minify(code, minify_options);
|
||||||
if (minified.error) return minified;
|
if (minified.error) return minified;
|
||||||
|
|
||||||
var toplevel = sandbox.has_toplevel(minify_options);
|
var toplevel = sandbox.has_toplevel(minify_options);
|
||||||
var elapsed = Date.now();
|
var unminified = run_code(code, toplevel, result_cache, max_timeout);
|
||||||
var unminified_result = run_code(result_cache, code, toplevel, max_timeout);
|
var timeout = Math.min(100 * unminified.elapsed, max_timeout);
|
||||||
elapsed = Date.now() - elapsed;
|
var minified_result = run_code(minified.code, toplevel, result_cache, timeout).result;
|
||||||
var timeout = Math.min(100 * elapsed, max_timeout);
|
|
||||||
var minified_result = run_code(result_cache, minified.code, toplevel, timeout);
|
|
||||||
|
|
||||||
if (sandbox.same_stdout(unminified_result, minified_result)) {
|
if (sandbox.same_stdout(unminified.result, minified_result)) {
|
||||||
return is_timed_out(unminified_result) && is_timed_out(minified_result) && {
|
return is_timed_out(unminified.result) && is_timed_out(minified_result) && {
|
||||||
timed_out: true,
|
timed_out: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
unminified_result: unminified_result,
|
unminified_result: unminified.result,
|
||||||
minified_result: minified_result,
|
minified_result: minified_result,
|
||||||
elapsed: elapsed,
|
elapsed: unminified.elapsed,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_minify(code, minify_options) {
|
||||||
|
var minified = U.minify(code, minify_options);
|
||||||
|
return minified.error && {
|
||||||
|
minified_result: minified.error,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Error.stackTraceLimit = Infinity;
|
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
setInterval(function() {
|
|
||||||
process.stderr.write("\0");
|
|
||||||
}, 8 * 60 * 1000).unref();
|
|
||||||
require("./run")([
|
require("./run")([
|
||||||
"-b",
|
"-b",
|
||||||
"-b braces",
|
"-b braces",
|
||||||
@@ -12,6 +9,6 @@ require("./run")([
|
|||||||
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
|
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
|
||||||
].map(function(options) {
|
].map(function(options) {
|
||||||
var args = options.split(/ /);
|
var args = options.split(/ /);
|
||||||
args.unshift("test/benchmark.js");
|
args.unshift("test/benchmark.js", "--validate");
|
||||||
return args;
|
return args;
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ function createContext() {
|
|||||||
arg.constructor.toString();
|
arg.constructor.toString();
|
||||||
if (level--) for (var key in arg) {
|
if (level--) for (var key in arg) {
|
||||||
var desc = Object.getOwnPropertyDescriptor(arg, key);
|
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;
|
return arg;
|
||||||
|
|||||||
67
test/ufuzz/actions.js
Normal file
67
test/ufuzz/actions.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
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 done = function(reply) {
|
||||||
|
done = function() {};
|
||||||
|
callback(reply);
|
||||||
|
};
|
||||||
|
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() {
|
||||||
|
var reply;
|
||||||
|
try {
|
||||||
|
reply = JSON.parse(chunks.join(""))
|
||||||
|
} catch (e) {}
|
||||||
|
done(reply);
|
||||||
|
}).on("error", function() {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}).on("error", function() {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -168,7 +168,7 @@ var VALUES = [
|
|||||||
"this",
|
"this",
|
||||||
];
|
];
|
||||||
|
|
||||||
var BINARY_OPS_NO_COMMA = [
|
var BINARY_OPS = [
|
||||||
" + ", // spaces needed to disambiguate with ++ cases (could otherwise cause syntax errors)
|
" + ", // spaces needed to disambiguate with ++ cases (could otherwise cause syntax errors)
|
||||||
" - ",
|
" - ",
|
||||||
"/",
|
"/",
|
||||||
@@ -190,9 +190,15 @@ var BINARY_OPS_NO_COMMA = [
|
|||||||
"%",
|
"%",
|
||||||
"&&",
|
"&&",
|
||||||
"||",
|
"||",
|
||||||
"^" ];
|
"^",
|
||||||
|
",",
|
||||||
var BINARY_OPS = [","].concat(BINARY_OPS_NO_COMMA);
|
];
|
||||||
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
|
BINARY_OPS.push(" in ");
|
||||||
|
|
||||||
var ASSIGNMENTS = [
|
var ASSIGNMENTS = [
|
||||||
"=",
|
"=",
|
||||||
@@ -269,6 +275,7 @@ var CANNOT_RETURN = true;
|
|||||||
var NO_DEFUN = false;
|
var NO_DEFUN = false;
|
||||||
var DEFUN_OK = true;
|
var DEFUN_OK = true;
|
||||||
var DONT_STORE = true;
|
var DONT_STORE = true;
|
||||||
|
var NO_CONST = true;
|
||||||
|
|
||||||
var VAR_NAMES = [
|
var VAR_NAMES = [
|
||||||
"a",
|
"a",
|
||||||
@@ -306,6 +313,7 @@ var TYPEOF_OUTCOMES = [
|
|||||||
"crap",
|
"crap",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
var block_vars = [];
|
||||||
var unique_vars = [];
|
var unique_vars = [];
|
||||||
var loops = 0;
|
var loops = 0;
|
||||||
var funcs = 0;
|
var funcs = 0;
|
||||||
@@ -323,6 +331,7 @@ function strictMode() {
|
|||||||
|
|
||||||
function createTopLevelCode() {
|
function createTopLevelCode() {
|
||||||
VAR_NAMES.length = INITIAL_NAMES_LEN; // prune any previous names still in the list
|
VAR_NAMES.length = INITIAL_NAMES_LEN; // prune any previous names still in the list
|
||||||
|
block_vars.length = 0;
|
||||||
unique_vars.length = 0;
|
unique_vars.length = 0;
|
||||||
loops = 0;
|
loops = 0;
|
||||||
funcs = 0;
|
funcs = 0;
|
||||||
@@ -368,11 +377,56 @@ function filterDirective(s) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createBlockVariables(recurmax, stmtDepth, canThrow, fn) {
|
||||||
|
var block_len = block_vars.length;
|
||||||
|
var var_len = VAR_NAMES.length;
|
||||||
|
var consts = [];
|
||||||
|
var lets = [];
|
||||||
|
unique_vars.push("a", "b", "c", "undefined", "NaN", "Infinity");
|
||||||
|
while (!rng(block_vars.length > block_len ? 10 : 100)) {
|
||||||
|
var name = createVarName(MANDATORY, DONT_STORE);
|
||||||
|
if (rng(2)) {
|
||||||
|
consts.push(name);
|
||||||
|
} else {
|
||||||
|
lets.push(name);
|
||||||
|
}
|
||||||
|
block_vars.push(name);
|
||||||
|
}
|
||||||
|
unique_vars.length -= 6;
|
||||||
|
fn(function() {
|
||||||
|
if (rng(2)) {
|
||||||
|
return createDefinitions("const", consts) + "\n" + createDefinitions("let", lets) + "\n";
|
||||||
|
} else {
|
||||||
|
return createDefinitions("let", lets) + "\n" + createDefinitions("const", consts) + "\n";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
block_vars.length = block_len;
|
||||||
|
if (consts.length || lets.length) VAR_NAMES.splice(var_len, consts.length + lets.length);
|
||||||
|
|
||||||
|
function createDefinitions(type, names) {
|
||||||
|
if (!names.length) return "";
|
||||||
|
var save = VAR_NAMES;
|
||||||
|
VAR_NAMES = VAR_NAMES.filter(function(name) {
|
||||||
|
return names.indexOf(name) < 0;
|
||||||
|
});
|
||||||
|
var len = VAR_NAMES.length;
|
||||||
|
var s = type + " " + names.map(function(name) {
|
||||||
|
var value = createExpression(recurmax, NO_COMMA, stmtDepth, canThrow);
|
||||||
|
VAR_NAMES.push(name);
|
||||||
|
return name + " = " + value;
|
||||||
|
}).join(", ") + ";";
|
||||||
|
VAR_NAMES = save.concat(VAR_NAMES.slice(len));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function createFunction(recurmax, allowDefun, canThrow, stmtDepth) {
|
function createFunction(recurmax, allowDefun, canThrow, stmtDepth) {
|
||||||
if (--recurmax < 0) { return ";"; }
|
if (--recurmax < 0) { return ";"; }
|
||||||
if (!STMT_COUNT_FROM_GLOBAL) stmtDepth = 0;
|
if (!STMT_COUNT_FROM_GLOBAL) stmtDepth = 0;
|
||||||
var namesLenBefore = VAR_NAMES.length;
|
var s = [];
|
||||||
var name;
|
var name;
|
||||||
|
createBlockVariables(recurmax, stmtDepth, canThrow, function(defns) {
|
||||||
|
var namesLenBefore = VAR_NAMES.length;
|
||||||
if (allowDefun || rng(5) > 0) {
|
if (allowDefun || rng(5) > 0) {
|
||||||
name = "f" + funcs++;
|
name = "f" + funcs++;
|
||||||
} else {
|
} else {
|
||||||
@@ -380,21 +434,20 @@ function createFunction(recurmax, allowDefun, canThrow, stmtDepth) {
|
|||||||
name = createVarName(MANDATORY, !allowDefun);
|
name = createVarName(MANDATORY, !allowDefun);
|
||||||
unique_vars.length -= 3;
|
unique_vars.length -= 3;
|
||||||
}
|
}
|
||||||
var s = [
|
s.push("function " + name + "(" + createParams() + "){", strictMode());
|
||||||
"function " + name + "(" + createParams() + "){",
|
s.push(defns());
|
||||||
strictMode()
|
|
||||||
];
|
|
||||||
if (rng(5) === 0) {
|
if (rng(5) === 0) {
|
||||||
// functions with functions. lower the recursion to prevent a mess.
|
// functions with functions. lower the recursion to prevent a mess.
|
||||||
s.push(createFunctions(rng(5) + 1, Math.ceil(recurmax * 0.7), DEFUN_OK, canThrow, stmtDepth));
|
s.push(createFunctions(rng(5) + 1, Math.ceil(recurmax * 0.7), DEFUN_OK, canThrow, stmtDepth));
|
||||||
} else {
|
} else {
|
||||||
// functions with statements
|
// functions with statements
|
||||||
s.push(createStatements(3, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth));
|
s.push(_createStatements(3, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth));
|
||||||
}
|
}
|
||||||
s.push("}", "");
|
s.push("}", "");
|
||||||
s = filterDirective(s).join("\n");
|
s = filterDirective(s).join("\n");
|
||||||
|
|
||||||
VAR_NAMES.length = namesLenBefore;
|
VAR_NAMES.length = namesLenBefore;
|
||||||
|
});
|
||||||
|
|
||||||
if (!allowDefun) {
|
if (!allowDefun) {
|
||||||
// avoid "function statements" (decl inside statements)
|
// avoid "function statements" (decl inside statements)
|
||||||
@@ -408,7 +461,7 @@ function createFunction(recurmax, allowDefun, canThrow, stmtDepth) {
|
|||||||
return s + ";";
|
return s + ";";
|
||||||
}
|
}
|
||||||
|
|
||||||
function createStatements(n, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {
|
function _createStatements(n, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {
|
||||||
if (--recurmax < 0) { return ";"; }
|
if (--recurmax < 0) { return ";"; }
|
||||||
var s = "";
|
var s = "";
|
||||||
while (--n > 0) {
|
while (--n > 0) {
|
||||||
@@ -417,6 +470,15 @@ function createStatements(n, recurmax, canThrow, canBreak, canContinue, cannotRe
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createStatements(n, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {
|
||||||
|
var s = "";
|
||||||
|
createBlockVariables(recurmax, stmtDepth, canThrow, function(defns) {
|
||||||
|
s += defns() + "\n";
|
||||||
|
s += _createStatements(n, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth);
|
||||||
|
});
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
function enableLoopControl(flag, defaultValue) {
|
function enableLoopControl(flag, defaultValue) {
|
||||||
return Array.isArray(flag) && flag.indexOf("") < 0 ? flag.concat("") : flag || defaultValue;
|
return Array.isArray(flag) && flag.indexOf("") < 0 ? flag.concat("") : flag || defaultValue;
|
||||||
}
|
}
|
||||||
@@ -490,11 +552,16 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
var label = createLabel(canBreak, canContinue);
|
var label = createLabel(canBreak, canContinue);
|
||||||
canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);
|
canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);
|
||||||
canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);
|
canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);
|
||||||
var optElementVar = "";
|
var key = rng(10) ? "key" + loop : getVarName(NO_CONST);
|
||||||
if (rng(5) > 1) {
|
return [
|
||||||
optElementVar = "c = 1 + c; var " + createVarName(MANDATORY) + " = expr" + loop + "[key" + loop + "]; ";
|
"{var expr" + loop + " = " + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "; ",
|
||||||
}
|
label.target + " for (",
|
||||||
return "{var expr" + loop + " = " + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "; " + label.target + " for (var key" + loop + " in expr" + loop + ") {" + optElementVar + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + "}}";
|
/^key/.test(key) ? "var " : "",
|
||||||
|
key + " in expr" + loop + ") {",
|
||||||
|
rng(5) > 1 ? "c = 1 + c; var " + createVarName(MANDATORY) + " = expr" + loop + "[" + key + "]; " : "",
|
||||||
|
createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),
|
||||||
|
"}}",
|
||||||
|
].join("");
|
||||||
case STMT_SEMI:
|
case STMT_SEMI:
|
||||||
return use_strict && rng(20) === 0 ? '"use strict";' : ";";
|
return use_strict && rng(20) === 0 ? '"use strict";' : ";";
|
||||||
case STMT_EXPR:
|
case STMT_EXPR:
|
||||||
@@ -560,13 +627,18 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
// the catch var should only be accessible in the catch clause...
|
// the catch var should only be accessible in the catch clause...
|
||||||
// we have to do go through some trouble here to prevent leaking it
|
// we have to do go through some trouble here to prevent leaking it
|
||||||
var nameLenBefore = VAR_NAMES.length;
|
var nameLenBefore = VAR_NAMES.length;
|
||||||
|
createBlockVariables(recurmax, stmtDepth, canThrow, function(defns) {
|
||||||
var catchName = createVarName(MANDATORY);
|
var catchName = createVarName(MANDATORY);
|
||||||
var freshCatchName = VAR_NAMES.length !== nameLenBefore;
|
var freshCatchName = VAR_NAMES.length !== nameLenBefore;
|
||||||
if (!catch_redef) unique_vars.push(catchName);
|
if (!catch_redef) unique_vars.push(catchName);
|
||||||
s += " catch (" + catchName + ") { " + createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + " }";
|
s += " catch (" + catchName + ") { ";
|
||||||
|
s += defns() + "\n";
|
||||||
|
s += _createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth);
|
||||||
|
s += " }";
|
||||||
// remove catch name
|
// remove catch name
|
||||||
if (!catch_redef) unique_vars.pop();
|
if (!catch_redef) unique_vars.pop();
|
||||||
if (freshCatchName) VAR_NAMES.splice(nameLenBefore, 1);
|
if (freshCatchName) VAR_NAMES.splice(nameLenBefore, 1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (n !== 0) s += " finally { " + createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + " }";
|
if (n !== 0) s += " finally { " + createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + " }";
|
||||||
return s;
|
return s;
|
||||||
@@ -586,7 +658,7 @@ function createSwitchParts(recurmax, n, canThrow, canBreak, canContinue, cannotR
|
|||||||
if (hadDefault || rng(5) > 0) {
|
if (hadDefault || rng(5) > 0) {
|
||||||
s.push(
|
s.push(
|
||||||
"case " + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ":",
|
"case " + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ":",
|
||||||
createStatements(rng(3) + 1, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),
|
_createStatements(rng(3) + 1, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),
|
||||||
rng(10) > 0 ? " break;" : "/* fall-through */",
|
rng(10) > 0 ? " break;" : "/* fall-through */",
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
@@ -594,7 +666,7 @@ function createSwitchParts(recurmax, n, canThrow, canBreak, canContinue, cannotR
|
|||||||
hadDefault = true;
|
hadDefault = true;
|
||||||
s.push(
|
s.push(
|
||||||
"default:",
|
"default:",
|
||||||
createStatements(rng(3) + 1, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),
|
_createStatements(rng(3) + 1, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -642,7 +714,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
case p++:
|
case p++:
|
||||||
return getVarName();
|
return getVarName();
|
||||||
case p++:
|
case p++:
|
||||||
return getVarName() + createAssignment() + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);
|
return getVarName(NO_CONST) + createAssignment() + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);
|
||||||
case p++:
|
case p++:
|
||||||
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);
|
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);
|
||||||
case p++:
|
case p++:
|
||||||
@@ -688,19 +760,22 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
createBlockVariables(recurmax, stmtDepth, canThrow, function(defns) {
|
||||||
var instantiate = rng(4) ? "new " : "";
|
var instantiate = rng(4) ? "new " : "";
|
||||||
s.push(
|
s.push(
|
||||||
instantiate + "function " + name + "(){",
|
instantiate + "function " + name + "(){",
|
||||||
strictMode()
|
strictMode(),
|
||||||
|
defns()
|
||||||
);
|
);
|
||||||
if (instantiate) for (var i = rng(4); --i >= 0;) {
|
if (instantiate) for (var i = rng(4); --i >= 0;) {
|
||||||
if (rng(2)) s.push("this." + getDotKey(true) + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ";");
|
if (rng(2)) s.push("this." + getDotKey(true) + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ";");
|
||||||
else s.push("this[" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]" + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ";");
|
else s.push("this[" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]" + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ";");
|
||||||
}
|
}
|
||||||
s.push(
|
s.push(
|
||||||
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
_createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
||||||
rng(2) == 0 ? "}" : "}()"
|
rng(2) == 0 ? "}" : "}()"
|
||||||
);
|
);
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
VAR_NAMES.length = nameLenBefore;
|
VAR_NAMES.length = nameLenBefore;
|
||||||
@@ -763,11 +838,23 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
case p++:
|
case p++:
|
||||||
return createObjectLiteral(recurmax, stmtDepth, canThrow) + "." + getDotKey();
|
return createObjectLiteral(recurmax, stmtDepth, canThrow) + "." + getDotKey();
|
||||||
case p++:
|
case p++:
|
||||||
var name = getVarName();
|
return createValue() + " in " + createArrayLiteral(recurmax, stmtDepth, canThrow);
|
||||||
return name + " && " + name + "[" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]";
|
case p++:
|
||||||
|
return createValue() + " in " + createObjectLiteral(recurmax, stmtDepth, canThrow);
|
||||||
case p++:
|
case p++:
|
||||||
var name = getVarName();
|
var name = getVarName();
|
||||||
return name + " && " + name + "." + getDotKey();
|
var s = name + "[" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]";
|
||||||
|
return canThrow && rng(8) == 0 ? s : name + " && " + s;
|
||||||
|
case p++:
|
||||||
|
var name = getVarName();
|
||||||
|
var s = name + "." + getDotKey();
|
||||||
|
return canThrow && rng(8) == 0 ? s : name + " && " + s;
|
||||||
|
case p++:
|
||||||
|
case p++:
|
||||||
|
var name = getVarName();
|
||||||
|
var s = name + "." + getDotKey();
|
||||||
|
s = "typeof " + s + ' == "function" && --_calls_ >= 0 && ' + s + "(" + createArgs(recurmax, stmtDepth, canThrow) + ")";
|
||||||
|
return canThrow && rng(8) == 0 ? s : name + " && " + s;
|
||||||
case p++:
|
case p++:
|
||||||
case p++:
|
case p++:
|
||||||
case p++:
|
case p++:
|
||||||
@@ -824,12 +911,14 @@ function getDotKey(assign) {
|
|||||||
function createAccessor(recurmax, stmtDepth, canThrow) {
|
function createAccessor(recurmax, stmtDepth, canThrow) {
|
||||||
var namesLenBefore = VAR_NAMES.length;
|
var namesLenBefore = VAR_NAMES.length;
|
||||||
var s;
|
var s;
|
||||||
|
createBlockVariables(recurmax, stmtDepth, canThrow, function(defns) {
|
||||||
var prop1 = getDotKey();
|
var prop1 = getDotKey();
|
||||||
if (rng(2) == 0) {
|
if (rng(2) == 0) {
|
||||||
s = [
|
s = [
|
||||||
"get " + prop1 + "(){",
|
"get " + prop1 + "(){",
|
||||||
strictMode(),
|
strictMode(),
|
||||||
createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
defns(),
|
||||||
|
_createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
||||||
createStatement(recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth, STMT_RETURN_ETC),
|
createStatement(recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth, STMT_RETURN_ETC),
|
||||||
"},"
|
"},"
|
||||||
];
|
];
|
||||||
@@ -841,11 +930,13 @@ function createAccessor(recurmax, stmtDepth, canThrow) {
|
|||||||
s = [
|
s = [
|
||||||
"set " + prop1 + "(" + createVarName(MANDATORY) + "){",
|
"set " + prop1 + "(" + createVarName(MANDATORY) + "){",
|
||||||
strictMode(),
|
strictMode(),
|
||||||
createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
defns(),
|
||||||
|
_createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
|
||||||
"this." + prop2 + createAssignment() + _createBinaryExpr(recurmax, COMMA_OK, stmtDepth, canThrow) + ";",
|
"this." + prop2 + createAssignment() + _createBinaryExpr(recurmax, COMMA_OK, stmtDepth, canThrow) + ";",
|
||||||
"},"
|
"},"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
});
|
||||||
VAR_NAMES.length = namesLenBefore;
|
VAR_NAMES.length = namesLenBefore;
|
||||||
return filterDirective(s).join("\n");
|
return filterDirective(s).join("\n");
|
||||||
}
|
}
|
||||||
@@ -871,7 +962,7 @@ function createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
}
|
}
|
||||||
function _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
function _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
return "(" + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow)
|
return "(" + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow)
|
||||||
+ createBinaryOp(noComma) + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ")";
|
+ createBinaryOp(noComma, canThrow) + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ")";
|
||||||
}
|
}
|
||||||
function _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
function _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
// intentionally generate more hardcore ops
|
// intentionally generate more hardcore ops
|
||||||
@@ -883,7 +974,7 @@ function _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
case 1:
|
case 1:
|
||||||
return "(" + createUnarySafePrefix() + "(" + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + "))";
|
return "(" + createUnarySafePrefix() + "(" + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + "))";
|
||||||
case 2:
|
case 2:
|
||||||
assignee = getVarName();
|
assignee = getVarName(NO_CONST);
|
||||||
return "(" + assignee + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ")";
|
return "(" + assignee + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ")";
|
||||||
case 3:
|
case 3:
|
||||||
assignee = getVarName();
|
assignee = getVarName();
|
||||||
@@ -921,9 +1012,12 @@ function createValue() {
|
|||||||
return VALUES[rng(VALUES.length)];
|
return VALUES[rng(VALUES.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
function createBinaryOp(noComma) {
|
function createBinaryOp(noComma, canThrow) {
|
||||||
if (noComma) return BINARY_OPS_NO_COMMA[rng(BINARY_OPS_NO_COMMA.length)];
|
var op;
|
||||||
return BINARY_OPS[rng(BINARY_OPS.length)];
|
do {
|
||||||
|
op = BINARY_OPS[rng(BINARY_OPS.length)];
|
||||||
|
} while (noComma && op == "," || !canThrow && op == " in ");
|
||||||
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAssignment() {
|
function createAssignment() {
|
||||||
@@ -942,9 +1036,10 @@ function createUnaryPostfix() {
|
|||||||
return UNARY_POSTFIX[rng(UNARY_POSTFIX.length)];
|
return UNARY_POSTFIX[rng(UNARY_POSTFIX.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVarName() {
|
function getVarName(noConst) {
|
||||||
// try to get a generated name reachable from current scope. default to just `a`
|
// try to get a generated name reachable from current scope. default to just `a`
|
||||||
return VAR_NAMES[INITIAL_NAMES_LEN + rng(VAR_NAMES.length - INITIAL_NAMES_LEN)] || "a";
|
var name = VAR_NAMES[INITIAL_NAMES_LEN + rng(VAR_NAMES.length - INITIAL_NAMES_LEN)];
|
||||||
|
return !name || noConst && block_vars.indexOf(name) >= 0 ? "a" : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createVarName(maybe, dontStore) {
|
function createVarName(maybe, dontStore) {
|
||||||
@@ -954,7 +1049,7 @@ function createVarName(maybe, dontStore) {
|
|||||||
do {
|
do {
|
||||||
name = VAR_NAMES[rng(VAR_NAMES.length)];
|
name = VAR_NAMES[rng(VAR_NAMES.length)];
|
||||||
if (suffix) name += "_" + suffix;
|
if (suffix) name += "_" + suffix;
|
||||||
} while (unique_vars.indexOf(name) >= 0);
|
} while (unique_vars.indexOf(name) >= 0 || block_vars.indexOf(name) >= 0);
|
||||||
if (suffix && !dontStore) VAR_NAMES.push(name);
|
if (suffix && !dontStore) VAR_NAMES.push(name);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@@ -1010,20 +1105,24 @@ function log_suspects(minify_options, component) {
|
|||||||
if (!options) return;
|
if (!options) return;
|
||||||
if (typeof options != "object") options = {};
|
if (typeof options != "object") options = {};
|
||||||
var defs = default_options[component];
|
var defs = default_options[component];
|
||||||
|
var toplevel = sandbox.has_toplevel(minify_options);
|
||||||
var suspects = Object.keys(defs).filter(function(name) {
|
var suspects = Object.keys(defs).filter(function(name) {
|
||||||
var flip = name == "keep_fargs";
|
var flip = name == "keep_fargs";
|
||||||
if (flip === !(name in options ? options : defs)[name]) {
|
if (flip !== (name in options ? options : defs)[name]) {
|
||||||
var m = JSON.parse(JSON.stringify(minify_options));
|
var m = JSON.parse(JSON.stringify(minify_options));
|
||||||
var o = JSON.parse(JSON.stringify(options));
|
var o = JSON.parse(JSON.stringify(options));
|
||||||
o[name] = flip;
|
o[name] = flip;
|
||||||
m[component] = o;
|
m[component] = o;
|
||||||
|
m.validate = true;
|
||||||
var result = UglifyJS.minify(original_code, m);
|
var result = UglifyJS.minify(original_code, m);
|
||||||
if (result.error) {
|
if (typeof uglify_code != "string") {
|
||||||
|
return !sandbox.same_stdout(uglify_code, result.error);
|
||||||
|
} else if (result.error) {
|
||||||
errorln("Error testing options." + component + "." + name);
|
errorln("Error testing options." + component + "." + name);
|
||||||
errorln(result.error);
|
errorln(result.error);
|
||||||
} else {
|
} else {
|
||||||
var r = sandbox.run_code(result.code, sandbox.has_toplevel(m));
|
var r = sandbox.run_code(result.code, toplevel);
|
||||||
return sandbox.same_stdout(original_result, r);
|
return !sandbox.same_stdout(uglify_result, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1036,21 +1135,22 @@ function log_suspects(minify_options, component) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function log_suspects_global(options) {
|
function log_suspects_global(options, toplevel) {
|
||||||
var o = {};
|
var suspects = Object.keys(default_options).filter(function(component) {
|
||||||
UglifyJS.minify("", o);
|
return typeof default_options[component] != "object";
|
||||||
var suspects = Object.keys(o).filter(function(component) {
|
|
||||||
return typeof o[component] != "object";
|
|
||||||
}).filter(function(component) {
|
}).filter(function(component) {
|
||||||
var m = JSON.parse(options);
|
var m = JSON.parse(options);
|
||||||
m[component] = false;
|
m[component] = false;
|
||||||
|
m.validate = true;
|
||||||
var result = UglifyJS.minify(original_code, m);
|
var result = UglifyJS.minify(original_code, m);
|
||||||
if (result.error) {
|
if (typeof uglify_code != "string") {
|
||||||
|
return !sandbox.same_stdout(uglify_code, result.error);
|
||||||
|
} else if (result.error) {
|
||||||
errorln("Error testing options." + component);
|
errorln("Error testing options." + component);
|
||||||
errorln(result.error);
|
errorln(result.error);
|
||||||
} else {
|
} else {
|
||||||
var r = sandbox.run_code(result.code, sandbox.has_toplevel(m));
|
var r = sandbox.run_code(result.code, toplevel);
|
||||||
return sandbox.same_stdout(original_result, r);
|
return !sandbox.same_stdout(uglify_result, r);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (suspects.length > 0) {
|
if (suspects.length > 0) {
|
||||||
@@ -1068,7 +1168,37 @@ function log(options) {
|
|||||||
errorln("//=============================================================");
|
errorln("//=============================================================");
|
||||||
if (!ok) errorln("// !!!!!! Failed... round " + round);
|
if (!ok) errorln("// !!!!!! Failed... round " + round);
|
||||||
errorln("// original code");
|
errorln("// original code");
|
||||||
try_beautify(original_code, toplevel, original_result, errorln);
|
var beautified = UglifyJS.minify(original_code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
beautify: true,
|
||||||
|
braces: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (beautified.error) {
|
||||||
|
errorln("// !!! beautify failed !!!");
|
||||||
|
errorln(beautified.error);
|
||||||
|
errorln("//");
|
||||||
|
errorln(original_code);
|
||||||
|
} else {
|
||||||
|
var uglified = UglifyJS.minify(beautified.code, JSON.parse(options));
|
||||||
|
var expected, actual;
|
||||||
|
if (typeof uglify_code != "string" || uglified.error) {
|
||||||
|
expected = uglify_code;
|
||||||
|
actual = uglified.error;
|
||||||
|
} else {
|
||||||
|
expected = uglify_result;
|
||||||
|
actual = sandbox.run_code(uglified.code, toplevel);
|
||||||
|
}
|
||||||
|
if (sandbox.same_stdout(expected, actual)) {
|
||||||
|
errorln("// (beautified)");
|
||||||
|
errorln(beautified.code);
|
||||||
|
} else {
|
||||||
|
errorln("//");
|
||||||
|
errorln(original_code);
|
||||||
|
}
|
||||||
|
}
|
||||||
errorln();
|
errorln();
|
||||||
errorln();
|
errorln();
|
||||||
errorln("//-------------------------------------------------------------");
|
errorln("//-------------------------------------------------------------");
|
||||||
@@ -1081,18 +1211,6 @@ function log(options) {
|
|||||||
errorln(original_result);
|
errorln(original_result);
|
||||||
errorln("uglified result:");
|
errorln("uglified result:");
|
||||||
errorln(uglify_result);
|
errorln(uglify_result);
|
||||||
errorln("//-------------------------------------------------------------");
|
|
||||||
var reduced = reduce_test(original_code, JSON.parse(options), {
|
|
||||||
verbose: false,
|
|
||||||
}).code;
|
|
||||||
if (reduced) {
|
|
||||||
errorln();
|
|
||||||
errorln("// reduced test case (output will differ)");
|
|
||||||
errorln();
|
|
||||||
errorln(reduced);
|
|
||||||
errorln();
|
|
||||||
errorln("//-------------------------------------------------------------");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
errorln("// !!! uglify failed !!!");
|
errorln("// !!! uglify failed !!!");
|
||||||
errorln(uglify_code);
|
errorln(uglify_code);
|
||||||
@@ -1103,16 +1221,38 @@ function log(options) {
|
|||||||
errorln(original_result);
|
errorln(original_result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
errorln("//-------------------------------------------------------------");
|
||||||
|
var reduce_options = JSON.parse(options);
|
||||||
|
reduce_options.validate = true;
|
||||||
|
var reduced = reduce_test(original_code, reduce_options, {
|
||||||
|
verbose: false,
|
||||||
|
}).code;
|
||||||
|
if (reduced) {
|
||||||
|
errorln();
|
||||||
|
errorln("// reduced test case (output will differ)");
|
||||||
|
errorln();
|
||||||
|
errorln(reduced);
|
||||||
|
errorln();
|
||||||
|
errorln("//-------------------------------------------------------------");
|
||||||
|
}
|
||||||
errorln("minify(options):");
|
errorln("minify(options):");
|
||||||
errorln(JSON.stringify(JSON.parse(options), null, 2));
|
errorln(JSON.stringify(JSON.parse(options), null, 2));
|
||||||
errorln();
|
errorln();
|
||||||
if (!ok && typeof uglify_code == "string") {
|
if (!ok) {
|
||||||
Object.keys(default_options).forEach(log_suspects.bind(null, JSON.parse(options)));
|
Object.keys(default_options).filter(function(component) {
|
||||||
log_suspects_global(options);
|
var defs = default_options[component];
|
||||||
|
return defs && typeof defs == "object";
|
||||||
|
}).forEach(log_suspects.bind(null, JSON.parse(options)));
|
||||||
|
log_suspects_global(options, toplevel);
|
||||||
errorln("!!!!!! Failed... round " + round);
|
errorln("!!!!!! Failed... round " + round);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sort_globals(code) {
|
||||||
|
var globals = sandbox.run_code("throw Object.keys(this).sort();" + code);
|
||||||
|
return globals.length ? "var " + globals.join(",") + ";" + code : code;
|
||||||
|
}
|
||||||
|
|
||||||
function fuzzy_match(original, uglified) {
|
function fuzzy_match(original, uglified) {
|
||||||
uglified = uglified.split(" ");
|
uglified = uglified.split(" ");
|
||||||
var i = uglified.length;
|
var i = uglified.length;
|
||||||
@@ -1127,10 +1267,66 @@ function fuzzy_match(original, uglified) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fallback_options = [ JSON.stringify({
|
function patch_try_catch(orig, toplevel) {
|
||||||
compress: false,
|
var stack = [ {
|
||||||
mangle: false
|
code: orig,
|
||||||
}) ];
|
index: 0,
|
||||||
|
offset: 0,
|
||||||
|
tries: [],
|
||||||
|
} ];
|
||||||
|
var re = /(?:(?:^|[\s{}):;])try|}\s*catch\s*\(([^)]+)\)|}\s*finally)\s*(?={)/g;
|
||||||
|
while (stack.length) {
|
||||||
|
var code = stack[0].code;
|
||||||
|
var offset = stack[0].offset;
|
||||||
|
var tries = stack[0].tries;
|
||||||
|
var match;
|
||||||
|
re.lastIndex = stack.shift().index;
|
||||||
|
while (match = re.exec(code)) {
|
||||||
|
var index = match.index + match[0].length + 1;
|
||||||
|
if (/(?:^|[\s{}):;])try\s*$/.test(match[0])) {
|
||||||
|
tries.unshift({ try: index - offset });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var insert;
|
||||||
|
if (/}\s*finally\s*$/.test(match[0])) {
|
||||||
|
tries.shift();
|
||||||
|
insert = 'if (typeof UFUZZ_ERROR == "object") throw UFUZZ_ERROR;';
|
||||||
|
} else {
|
||||||
|
while (tries.length && tries[0].catch) tries.shift();
|
||||||
|
tries[0].catch = index - offset;
|
||||||
|
insert = [
|
||||||
|
"if (!" + match[1] + ".ufuzz_var) {",
|
||||||
|
match[1] + '.ufuzz_var = "' + match[1] + '";',
|
||||||
|
match[1] + ".ufuzz_try = " + tries[0].try + ";",
|
||||||
|
match[1] + ".ufuzz_catch = " + tries[0].catch + ";",
|
||||||
|
"UFUZZ_ERROR = " + match[1] + ";",
|
||||||
|
"}",
|
||||||
|
"throw " + match[1] + ";",
|
||||||
|
].join("\n");
|
||||||
|
}
|
||||||
|
var new_code = code.slice(0, index) + insert + code.slice(index);
|
||||||
|
var result = sandbox.run_code(new_code, toplevel);
|
||||||
|
if (typeof result != "object" || typeof result.name != "string" || typeof result.message != "string") {
|
||||||
|
if (!stack.filled && match[1]) stack.push({
|
||||||
|
code: code,
|
||||||
|
index: index && index - 1,
|
||||||
|
offset: offset,
|
||||||
|
tries: JSON.parse(JSON.stringify(tries)),
|
||||||
|
});
|
||||||
|
offset += insert.length;
|
||||||
|
code = new_code;
|
||||||
|
} else if (result.name == "TypeError" && /'in'/.test(result.message)) {
|
||||||
|
index = result.ufuzz_catch;
|
||||||
|
return orig.slice(0, index) + result.ufuzz_var + ' = new Error("invalid `in`");' + orig.slice(index);
|
||||||
|
} else if (result.name == "RangeError" && result.message == "Maximum call stack size exceeded") {
|
||||||
|
index = result.ufuzz_try;
|
||||||
|
return orig.slice(0, index) + 'throw new Error("skipping infinite recursion");' + orig.slice(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stack.filled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var minify_options = require("./options.json").map(JSON.stringify);
|
var minify_options = require("./options.json").map(JSON.stringify);
|
||||||
var original_code, original_result, errored;
|
var original_code, original_result, errored;
|
||||||
var uglify_code, uglify_result, ok;
|
var uglify_code, uglify_result, ok;
|
||||||
@@ -1138,42 +1334,56 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
process.stdout.write(round + " of " + num_iterations + "\r");
|
process.stdout.write(round + " of " + num_iterations + "\r");
|
||||||
|
|
||||||
original_code = createTopLevelCode();
|
original_code = createTopLevelCode();
|
||||||
var orig_result = [ sandbox.run_code(original_code) ];
|
var orig_result = [ sandbox.run_code(original_code), sandbox.run_code(original_code, true) ];
|
||||||
errored = typeof orig_result[0] != "string";
|
errored = typeof orig_result[0] != "string";
|
||||||
if (!errored) orig_result.push(sandbox.run_code(original_code, true));
|
if (errored) {
|
||||||
(errored ? fallback_options : minify_options).forEach(function(options) {
|
println("//=============================================================");
|
||||||
|
println("// original code");
|
||||||
|
try_beautify(original_code, false, orig_result[0], println);
|
||||||
|
println();
|
||||||
|
println();
|
||||||
|
println("original result:");
|
||||||
|
println(orig_result[0]);
|
||||||
|
println();
|
||||||
|
}
|
||||||
|
minify_options.forEach(function(options) {
|
||||||
var o = JSON.parse(options);
|
var o = JSON.parse(options);
|
||||||
var toplevel = sandbox.has_toplevel(o);
|
var toplevel = sandbox.has_toplevel(o);
|
||||||
|
o.validate = true;
|
||||||
uglify_code = UglifyJS.minify(original_code, o);
|
uglify_code = UglifyJS.minify(original_code, o);
|
||||||
original_result = orig_result[toplevel ? 1 : 0];
|
original_result = orig_result[toplevel ? 1 : 0];
|
||||||
if (!uglify_code.error) {
|
if (!uglify_code.error) {
|
||||||
uglify_code = uglify_code.code;
|
uglify_code = uglify_code.code;
|
||||||
uglify_result = sandbox.run_code(uglify_code, toplevel);
|
uglify_result = sandbox.run_code(uglify_code, toplevel);
|
||||||
ok = sandbox.same_stdout(original_result, uglify_result);
|
ok = sandbox.same_stdout(original_result, uglify_result);
|
||||||
if (!ok && typeof uglify_result == "string" && o.compress.unsafe_math) {
|
// ignore declaration order of global variables
|
||||||
|
if (!ok && !toplevel) {
|
||||||
|
ok = sandbox.same_stdout(sandbox.run_code(sort_globals(original_code)), sandbox.run_code(sort_globals(uglify_code)));
|
||||||
|
}
|
||||||
|
// ignore numerical imprecision caused by `unsafe_math`
|
||||||
|
if (!ok && o.compress && o.compress.unsafe_math && typeof original_result == "string" && typeof uglify_result == "string") {
|
||||||
ok = fuzzy_match(original_result, uglify_result);
|
ok = fuzzy_match(original_result, uglify_result);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
var fuzzy_result = sandbox.run_code(original_code.replace(/( - 0\.1){3}/g, " - 0.3"), toplevel);
|
var fuzzy_result = sandbox.run_code(original_code.replace(/( - 0\.1){3}/g, " - 0.3"), toplevel);
|
||||||
ok = sandbox.same_stdout(fuzzy_result, uglify_result);
|
ok = sandbox.same_stdout(fuzzy_result, uglify_result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ignore difference in error message caused by Temporal Dead Zone
|
||||||
|
if (!ok && errored) ok = uglify_result.name == "ReferenceError" && original_result.name == "ReferenceError";
|
||||||
|
// ignore difference in error message caused by `in`
|
||||||
|
// ignore difference in depth of termination caused by infinite recursion
|
||||||
|
if (!ok) {
|
||||||
|
var orig_skipped = patch_try_catch(original_code, toplevel);
|
||||||
|
var uglify_skipped = patch_try_catch(uglify_code, toplevel);
|
||||||
|
if (orig_skipped && uglify_skipped) {
|
||||||
|
ok = sandbox.same_stdout(sandbox.run_code(orig_skipped, toplevel), sandbox.run_code(uglify_skipped, toplevel));
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
uglify_code = uglify_code.error;
|
uglify_code = uglify_code.error;
|
||||||
if (errored) {
|
ok = errored && uglify_code.name == original_result.name;
|
||||||
ok = uglify_code.name == original_result.name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options);
|
if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options);
|
||||||
else if (errored) {
|
|
||||||
println("//=============================================================");
|
|
||||||
println("// original code");
|
|
||||||
try_beautify(original_code, toplevel, original_result, println);
|
|
||||||
println();
|
|
||||||
println();
|
|
||||||
println("original result:");
|
|
||||||
println(original_result);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
if (!ok && isFinite(num_iterations)) {
|
if (!ok && isFinite(num_iterations)) {
|
||||||
println();
|
println();
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
@@ -1,39 +1,71 @@
|
|||||||
|
var actions = require("./actions");
|
||||||
var child_process = require("child_process");
|
var child_process = require("child_process");
|
||||||
|
|
||||||
var ping = 5 * 60 * 1000;
|
var args = [
|
||||||
var period = +process.argv[2];
|
|
||||||
var endTime = Date.now() + period;
|
|
||||||
for (var i = 0; i < 2; i++) spawn(endTime);
|
|
||||||
|
|
||||||
function spawn(endTime) {
|
|
||||||
var child = child_process.spawn("node", [
|
|
||||||
"--max-old-space-size=2048",
|
"--max-old-space-size=2048",
|
||||||
"test/ufuzz"
|
"test/ufuzz",
|
||||||
], {
|
];
|
||||||
|
var iterations;
|
||||||
|
switch (process.argv.length) {
|
||||||
|
case 3:
|
||||||
|
iterations = +process.argv[2];
|
||||||
|
args.push(iterations);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
actions.init(process.argv[2], process.argv[3], +process.argv[4]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("invalid parameters");
|
||||||
|
}
|
||||||
|
var tasks = [ run(), run() ];
|
||||||
|
if (iterations) return;
|
||||||
|
var alive = setInterval(function() {
|
||||||
|
actions.should_stop(function() {
|
||||||
|
clearInterval(alive);
|
||||||
|
tasks.forEach(function(kill) {
|
||||||
|
kill();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 8 * 60 * 1000);
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
var child, stdout, stderr, log;
|
||||||
|
spawn();
|
||||||
|
return function() {
|
||||||
|
clearInterval(log);
|
||||||
|
child.removeListener("exit", respawn);
|
||||||
|
child.kill();
|
||||||
|
};
|
||||||
|
|
||||||
|
function spawn() {
|
||||||
|
child = child_process.spawn("node", args, {
|
||||||
stdio: [ "ignore", "pipe", "pipe" ]
|
stdio: [ "ignore", "pipe", "pipe" ]
|
||||||
}).on("exit", respawn);
|
}).on("exit", respawn);
|
||||||
var stdout = "";
|
stdout = "";
|
||||||
child.stdout.on("data", function(data) {
|
child.stdout.on("data", function(data) {
|
||||||
stdout += data;
|
stdout += data;
|
||||||
});
|
});
|
||||||
var stderr = "";
|
stderr = "";
|
||||||
child.stderr.on("data", trap).pipe(process.stdout);
|
child.stderr.on("data", trap).pipe(process.stdout);
|
||||||
var keepAlive = setInterval(function() {
|
log = setInterval(function() {
|
||||||
|
stdout = stdout.replace(/[^\r\n]+\r(?=[^\r\n]+\r)/g, "");
|
||||||
var end = stdout.lastIndexOf("\r");
|
var end = stdout.lastIndexOf("\r");
|
||||||
console.log(stdout.slice(stdout.lastIndexOf("\r", end - 1) + 1, end));
|
if (end < 0) return;
|
||||||
|
console.log(stdout.slice(0, end));
|
||||||
stdout = stdout.slice(end + 1);
|
stdout = stdout.slice(end + 1);
|
||||||
}, ping);
|
}, 5 * 60 * 1000);
|
||||||
var timer = setTimeout(function() {
|
}
|
||||||
clearInterval(keepAlive);
|
|
||||||
child.removeListener("exit", respawn);
|
|
||||||
child.kill();
|
|
||||||
}, endTime - Date.now());
|
|
||||||
|
|
||||||
function respawn() {
|
function respawn() {
|
||||||
console.log(stdout.replace(/[^\r\n]*\r/g, ""));
|
console.log(stdout.replace(/[^\r\n]*\r/g, ""));
|
||||||
clearInterval(keepAlive);
|
clearInterval(log);
|
||||||
clearTimeout(timer);
|
if (!iterations) {
|
||||||
spawn(endTime);
|
spawn();
|
||||||
|
} else if (process.exitCode) {
|
||||||
|
tasks.forEach(function(kill) {
|
||||||
|
kill();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function trap(data) {
|
function trap(data) {
|
||||||
|
|||||||
456
tools/domprops.html
Normal file
456
tools/domprops.html
Normal file
@@ -0,0 +1,456 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
!function(G) {
|
||||||
|
var domprops = [];
|
||||||
|
var objs = [ G ];
|
||||||
|
var tagNames = [
|
||||||
|
"a",
|
||||||
|
"abbr",
|
||||||
|
"acronym",
|
||||||
|
"address",
|
||||||
|
"applet",
|
||||||
|
"area",
|
||||||
|
"article",
|
||||||
|
"aside",
|
||||||
|
"audio",
|
||||||
|
"b",
|
||||||
|
"base",
|
||||||
|
"basefont",
|
||||||
|
"bdi",
|
||||||
|
"bdo",
|
||||||
|
"bgsound",
|
||||||
|
"big",
|
||||||
|
"blink",
|
||||||
|
"blockquote",
|
||||||
|
"body",
|
||||||
|
"br",
|
||||||
|
"button",
|
||||||
|
"canvas",
|
||||||
|
"caption",
|
||||||
|
"center",
|
||||||
|
"checked",
|
||||||
|
"cite",
|
||||||
|
"code",
|
||||||
|
"col",
|
||||||
|
"colgroup",
|
||||||
|
"command",
|
||||||
|
"comment",
|
||||||
|
"compact",
|
||||||
|
"content",
|
||||||
|
"data",
|
||||||
|
"datalist",
|
||||||
|
"dd",
|
||||||
|
"declare",
|
||||||
|
"defer",
|
||||||
|
"del",
|
||||||
|
"details",
|
||||||
|
"dfn",
|
||||||
|
"dialog",
|
||||||
|
"dir",
|
||||||
|
"disabled",
|
||||||
|
"div",
|
||||||
|
"dl",
|
||||||
|
"dt",
|
||||||
|
"element",
|
||||||
|
"em",
|
||||||
|
"embed",
|
||||||
|
"fieldset",
|
||||||
|
"figcaption",
|
||||||
|
"figure",
|
||||||
|
"font",
|
||||||
|
"footer",
|
||||||
|
"form",
|
||||||
|
"frame",
|
||||||
|
"frameset",
|
||||||
|
"h1",
|
||||||
|
"h2",
|
||||||
|
"h3",
|
||||||
|
"h4",
|
||||||
|
"h5",
|
||||||
|
"h6",
|
||||||
|
"head",
|
||||||
|
"header",
|
||||||
|
"hgroup",
|
||||||
|
"hr",
|
||||||
|
"html",
|
||||||
|
"i",
|
||||||
|
"iframe",
|
||||||
|
"image",
|
||||||
|
"img",
|
||||||
|
"input",
|
||||||
|
"ins",
|
||||||
|
"isindex",
|
||||||
|
"ismap",
|
||||||
|
"kbd",
|
||||||
|
"keygen",
|
||||||
|
"label",
|
||||||
|
"legend",
|
||||||
|
"li",
|
||||||
|
"link",
|
||||||
|
"listing",
|
||||||
|
"main",
|
||||||
|
"map",
|
||||||
|
"mark",
|
||||||
|
"marquee",
|
||||||
|
"math",
|
||||||
|
"menu",
|
||||||
|
"menuitem",
|
||||||
|
"meta",
|
||||||
|
"meter",
|
||||||
|
"multicol",
|
||||||
|
"multiple",
|
||||||
|
"nav",
|
||||||
|
"nextid",
|
||||||
|
"nobr",
|
||||||
|
"noembed",
|
||||||
|
"noframes",
|
||||||
|
"nohref",
|
||||||
|
"noresize",
|
||||||
|
"noscript",
|
||||||
|
"noshade",
|
||||||
|
"nowrap",
|
||||||
|
"object",
|
||||||
|
"ol",
|
||||||
|
"optgroup",
|
||||||
|
"option",
|
||||||
|
"output",
|
||||||
|
"p",
|
||||||
|
"param",
|
||||||
|
"picture",
|
||||||
|
"plaintext",
|
||||||
|
"pre",
|
||||||
|
"progress",
|
||||||
|
"q",
|
||||||
|
"rb",
|
||||||
|
"readonly",
|
||||||
|
"rp",
|
||||||
|
"rt",
|
||||||
|
"rtc",
|
||||||
|
"ruby",
|
||||||
|
"s",
|
||||||
|
"samp",
|
||||||
|
"script",
|
||||||
|
"section",
|
||||||
|
"select",
|
||||||
|
"selected",
|
||||||
|
"shadow",
|
||||||
|
"slot",
|
||||||
|
"small",
|
||||||
|
"source",
|
||||||
|
"spacer",
|
||||||
|
"span",
|
||||||
|
"strike",
|
||||||
|
"strong",
|
||||||
|
"style",
|
||||||
|
"sub",
|
||||||
|
"summary",
|
||||||
|
"sup",
|
||||||
|
"svg",
|
||||||
|
"table",
|
||||||
|
"tbody",
|
||||||
|
"td",
|
||||||
|
"template",
|
||||||
|
"textarea",
|
||||||
|
"tfoot",
|
||||||
|
"th",
|
||||||
|
"thead",
|
||||||
|
"time",
|
||||||
|
"title",
|
||||||
|
"tr",
|
||||||
|
"track",
|
||||||
|
"tt",
|
||||||
|
"u",
|
||||||
|
"ul",
|
||||||
|
"var",
|
||||||
|
"video",
|
||||||
|
"wbr",
|
||||||
|
"xmp",
|
||||||
|
"XXX",
|
||||||
|
];
|
||||||
|
for (var n = 0; n < tagNames.length; n++) {
|
||||||
|
add(document.createElement(tagNames[n]));
|
||||||
|
}
|
||||||
|
var nsNames = {
|
||||||
|
"http://www.w3.org/1998/Math/MathML": [
|
||||||
|
"annotation",
|
||||||
|
"annotation-xml",
|
||||||
|
"maction",
|
||||||
|
"maligngroup",
|
||||||
|
"malignmark",
|
||||||
|
"math",
|
||||||
|
"menclose",
|
||||||
|
"merror",
|
||||||
|
"mfenced",
|
||||||
|
"mfrac",
|
||||||
|
"mglyph",
|
||||||
|
"mi",
|
||||||
|
"mlabeledtr",
|
||||||
|
"mlongdiv",
|
||||||
|
"mmultiscripts",
|
||||||
|
"mn",
|
||||||
|
"mo",
|
||||||
|
"mover",
|
||||||
|
"mpadded",
|
||||||
|
"mphantom",
|
||||||
|
"mprescripts",
|
||||||
|
"mroot",
|
||||||
|
"mrow",
|
||||||
|
"ms",
|
||||||
|
"mscarries",
|
||||||
|
"mscarry",
|
||||||
|
"msgroup",
|
||||||
|
"msline",
|
||||||
|
"mspace",
|
||||||
|
"msqrt",
|
||||||
|
"msrow",
|
||||||
|
"mstack",
|
||||||
|
"mstyle",
|
||||||
|
"msub",
|
||||||
|
"msubsup",
|
||||||
|
"msup",
|
||||||
|
"mtable",
|
||||||
|
"mtd",
|
||||||
|
"mtext",
|
||||||
|
"mtr",
|
||||||
|
"munder",
|
||||||
|
"munderover",
|
||||||
|
"none",
|
||||||
|
"semantics",
|
||||||
|
],
|
||||||
|
"http://www.w3.org/2000/svg": [
|
||||||
|
"a",
|
||||||
|
"altGlyph",
|
||||||
|
"altGlyphDef",
|
||||||
|
"altGlyphItem",
|
||||||
|
"animate",
|
||||||
|
"animateColor",
|
||||||
|
"animateMotion",
|
||||||
|
"animateTransform",
|
||||||
|
"circle",
|
||||||
|
"clipPath",
|
||||||
|
"color-profile",
|
||||||
|
"cursor",
|
||||||
|
"defs",
|
||||||
|
"desc",
|
||||||
|
"discard",
|
||||||
|
"ellipse",
|
||||||
|
"feBlend",
|
||||||
|
"feColorMatrix",
|
||||||
|
"feComponentTransfer",
|
||||||
|
"feComposite",
|
||||||
|
"feConvolveMatrix",
|
||||||
|
"feDiffuseLighting",
|
||||||
|
"feDisplacementMap",
|
||||||
|
"feDistantLight",
|
||||||
|
"feDropShadow",
|
||||||
|
"feFlood",
|
||||||
|
"feFuncA",
|
||||||
|
"feFuncB",
|
||||||
|
"feFuncG",
|
||||||
|
"feFuncR",
|
||||||
|
"feGaussianBlur",
|
||||||
|
"feImage",
|
||||||
|
"feMerge",
|
||||||
|
"feMergeNode",
|
||||||
|
"feMorphology",
|
||||||
|
"feOffset",
|
||||||
|
"fePointLight",
|
||||||
|
"feSpecularLighting",
|
||||||
|
"feSpotLight",
|
||||||
|
"feTile",
|
||||||
|
"feTurbulence",
|
||||||
|
"filter",
|
||||||
|
"font",
|
||||||
|
"font-face",
|
||||||
|
"font-face-format",
|
||||||
|
"font-face-name",
|
||||||
|
"font-face-src",
|
||||||
|
"font-face-uri",
|
||||||
|
"foreignObject",
|
||||||
|
"g",
|
||||||
|
"glyph",
|
||||||
|
"glyphRef",
|
||||||
|
"hatch",
|
||||||
|
"hatchpath",
|
||||||
|
"hkern",
|
||||||
|
"image",
|
||||||
|
"line",
|
||||||
|
"linearGradient",
|
||||||
|
"marker",
|
||||||
|
"mask",
|
||||||
|
"mesh",
|
||||||
|
"meshgradient",
|
||||||
|
"meshpatch",
|
||||||
|
"meshrow",
|
||||||
|
"metadata",
|
||||||
|
"missing-glyph",
|
||||||
|
"mpath",
|
||||||
|
"path",
|
||||||
|
"pattern",
|
||||||
|
"polygon",
|
||||||
|
"polyline",
|
||||||
|
"radialGradient",
|
||||||
|
"rect",
|
||||||
|
"script",
|
||||||
|
"set",
|
||||||
|
"solidcolor",
|
||||||
|
"stop",
|
||||||
|
"style",
|
||||||
|
"svg",
|
||||||
|
"switch",
|
||||||
|
"symbol",
|
||||||
|
"text",
|
||||||
|
"textPath",
|
||||||
|
"title",
|
||||||
|
"tref",
|
||||||
|
"tspan",
|
||||||
|
"unknown",
|
||||||
|
"use",
|
||||||
|
"view",
|
||||||
|
"vkern",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
if (document.createElementNS) for (var ns in nsNames) {
|
||||||
|
for (var n = 0; n < nsNames[ns].length; n++) {
|
||||||
|
add(document.createElementNS(ns, nsNames[ns][n]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var skips = [
|
||||||
|
G.alert,
|
||||||
|
G.back,
|
||||||
|
G.blur,
|
||||||
|
G.captureEvents,
|
||||||
|
G.clearImmediate,
|
||||||
|
G.clearInterval,
|
||||||
|
G.clearTimeout,
|
||||||
|
G.close,
|
||||||
|
G.confirm,
|
||||||
|
G.console,
|
||||||
|
G.dump,
|
||||||
|
G.fetch,
|
||||||
|
G.find,
|
||||||
|
G.focus,
|
||||||
|
G.forward,
|
||||||
|
G.getAttention,
|
||||||
|
G.history,
|
||||||
|
G.home,
|
||||||
|
G.location,
|
||||||
|
G.moveBy,
|
||||||
|
G.moveTo,
|
||||||
|
G.navigator,
|
||||||
|
G.open,
|
||||||
|
G.openDialog,
|
||||||
|
G.print,
|
||||||
|
G.process,
|
||||||
|
G.prompt,
|
||||||
|
G.resizeBy,
|
||||||
|
G.resizeTo,
|
||||||
|
G.setImmediate,
|
||||||
|
G.setInterval,
|
||||||
|
G.setTimeout,
|
||||||
|
G.showModalDialog,
|
||||||
|
G.sizeToContent,
|
||||||
|
G.stop,
|
||||||
|
];
|
||||||
|
var types = [];
|
||||||
|
var interfaces = [
|
||||||
|
"beforeunloadevent",
|
||||||
|
"compositionevent",
|
||||||
|
"customevent",
|
||||||
|
"devicemotionevent",
|
||||||
|
"deviceorientationevent",
|
||||||
|
"dragevent",
|
||||||
|
"event",
|
||||||
|
"events",
|
||||||
|
"focusevent",
|
||||||
|
"hashchangeevent",
|
||||||
|
"htmlevents",
|
||||||
|
"keyboardevent",
|
||||||
|
"messageevent",
|
||||||
|
"mouseevent",
|
||||||
|
"mouseevents",
|
||||||
|
"storageevent",
|
||||||
|
"svgevents",
|
||||||
|
"textevent",
|
||||||
|
"touchevent",
|
||||||
|
"uievent",
|
||||||
|
"uievents",
|
||||||
|
];
|
||||||
|
var i = 0, full = false;
|
||||||
|
var addEvent = document.createEvent ? function(type) {
|
||||||
|
if (~indexOf(types, type)) return;
|
||||||
|
types.push(type);
|
||||||
|
for (var j = 0; j < interfaces.length; j++) try {
|
||||||
|
var event = document.createEvent(interfaces[j]);
|
||||||
|
event.initEvent(type, true, true);
|
||||||
|
add(event);
|
||||||
|
} catch (e) {}
|
||||||
|
} : function() {};
|
||||||
|
var scanProperties = Object.getOwnPropertyNames ? function(o, fn) {
|
||||||
|
var names = Object.getOwnPropertyNames(o);
|
||||||
|
names.forEach(fn);
|
||||||
|
for (var k in o) if (!~indexOf(names, k)) fn(k);
|
||||||
|
} : function(o, fn) {
|
||||||
|
for (var k in o) fn(k);
|
||||||
|
};
|
||||||
|
setTimeout(function next() {
|
||||||
|
for (var j = 10; --j >= 0 && i < objs.length; i++) {
|
||||||
|
var o = objs[i];
|
||||||
|
var skip = ~indexOf(skips, o);
|
||||||
|
try {
|
||||||
|
scanProperties(o, function(k) {
|
||||||
|
if (!~indexOf(domprops, k)) domprops.push(k);
|
||||||
|
if (/^on/.test(k)) addEvent(k.slice(2));
|
||||||
|
if (!full) try {
|
||||||
|
add(o[k]);
|
||||||
|
} catch (e) {}
|
||||||
|
});
|
||||||
|
} catch (e) {}
|
||||||
|
if (skip || full) continue;
|
||||||
|
try {
|
||||||
|
add(o.__proto__);
|
||||||
|
} catch (e) {}
|
||||||
|
try {
|
||||||
|
add(o.prototype);
|
||||||
|
} catch (e) {}
|
||||||
|
try {
|
||||||
|
add(new o());
|
||||||
|
} catch (e) {}
|
||||||
|
try {
|
||||||
|
add(o());
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
if (!full && objs.length > 20000) {
|
||||||
|
alert(objs.length);
|
||||||
|
full = true;
|
||||||
|
}
|
||||||
|
if (i < objs.length) {
|
||||||
|
setTimeout(next, 0);
|
||||||
|
} else {
|
||||||
|
document.write('<pre>[\n "' + domprops.sort().join('",\n "').replace(/&/g, "&").replace(/</g, "<") + '"\n]</pre>');
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
function add(o) {
|
||||||
|
if (o) switch (typeof o) {
|
||||||
|
case "function":
|
||||||
|
case "object":
|
||||||
|
if (!~indexOf(objs, o)) objs.push(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function indexOf(list, value) {
|
||||||
|
var j = list.length;
|
||||||
|
while (--j >= 0) {
|
||||||
|
if (list[j] === value) break;
|
||||||
|
}
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}(function() {
|
||||||
|
return this;
|
||||||
|
}());
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1475
tools/domprops.json
1475
tools/domprops.json
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@ process.exit = function() {
|
|||||||
process.once("uncaughtException", function() {
|
process.once("uncaughtException", function() {
|
||||||
(function callback() {
|
(function callback() {
|
||||||
if (process.stdout.bufferSize || process.stderr.bufferSize) {
|
if (process.stdout.bufferSize || process.stderr.bufferSize) {
|
||||||
setImmediate(callback);
|
setTimeout(callback, 1);
|
||||||
} else {
|
} else {
|
||||||
exit.apply(process, args);
|
exit.apply(process, args);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ exports.FILES = [
|
|||||||
require.resolve("./exports.js"),
|
require.resolve("./exports.js"),
|
||||||
];
|
];
|
||||||
|
|
||||||
new Function("MOZ_SourceMap", "exports", function() {
|
new Function("exports", function() {
|
||||||
var code = exports.FILES.map(function(file) {
|
var code = exports.FILES.map(function(file) {
|
||||||
return fs.readFileSync(file, "utf8");
|
return fs.readFileSync(file, "utf8");
|
||||||
});
|
});
|
||||||
code.push("exports.describe_ast = " + describe_ast.toString());
|
code.push("exports.describe_ast = " + describe_ast.toString());
|
||||||
return code.join("\n\n");
|
return code.join("\n\n");
|
||||||
}())(require("source-map"), exports);
|
}())(exports);
|
||||||
|
|
||||||
function describe_ast() {
|
function describe_ast() {
|
||||||
var out = OutputStream({ beautify: true });
|
var out = OutputStream({ beautify: true });
|
||||||
@@ -66,8 +66,8 @@ function infer_options(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
exports.default_options = function() {
|
exports.default_options = function() {
|
||||||
var defs = {};
|
var defs = infer_options({ 0: 0 });
|
||||||
Object.keys(infer_options({ 0: 0 })).forEach(function(component) {
|
Object.keys(defs).forEach(function(component) {
|
||||||
var options = {};
|
var options = {};
|
||||||
options[component] = { 0: 0 };
|
options[component] = { 0: 0 };
|
||||||
if (options = infer_options(options)) {
|
if (options = infer_options(options)) {
|
||||||
|
|||||||
540
tools/props.html
540
tools/props.html
@@ -1,540 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<script>
|
|
||||||
!function() {
|
|
||||||
var names = [];
|
|
||||||
var scanned = [];
|
|
||||||
var to_scan = [];
|
|
||||||
|
|
||||||
function scan(obj) {
|
|
||||||
if (obj && typeof obj == "object" && !~scanned.indexOf(obj)) {
|
|
||||||
scanned.push(obj);
|
|
||||||
to_scan.push(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scan(self);
|
|
||||||
[
|
|
||||||
"a",
|
|
||||||
"abbr",
|
|
||||||
"acronym",
|
|
||||||
"address",
|
|
||||||
"applet",
|
|
||||||
"area",
|
|
||||||
"article",
|
|
||||||
"aside",
|
|
||||||
"audio",
|
|
||||||
"b",
|
|
||||||
"base",
|
|
||||||
"basefont",
|
|
||||||
"bdi",
|
|
||||||
"bdo",
|
|
||||||
"bgsound",
|
|
||||||
"big",
|
|
||||||
"blink",
|
|
||||||
"blockquote",
|
|
||||||
"body",
|
|
||||||
"br",
|
|
||||||
"button",
|
|
||||||
"canvas",
|
|
||||||
"caption",
|
|
||||||
"center",
|
|
||||||
"checked",
|
|
||||||
"cite",
|
|
||||||
"code",
|
|
||||||
"col",
|
|
||||||
"colgroup",
|
|
||||||
"command",
|
|
||||||
"comment",
|
|
||||||
"compact",
|
|
||||||
"content",
|
|
||||||
"data",
|
|
||||||
"datalist",
|
|
||||||
"dd",
|
|
||||||
"declare",
|
|
||||||
"defer",
|
|
||||||
"del",
|
|
||||||
"details",
|
|
||||||
"dfn",
|
|
||||||
"dialog",
|
|
||||||
"dir",
|
|
||||||
"disabled",
|
|
||||||
"div",
|
|
||||||
"dl",
|
|
||||||
"dt",
|
|
||||||
"element",
|
|
||||||
"em",
|
|
||||||
"embed",
|
|
||||||
"fieldset",
|
|
||||||
"figcaption",
|
|
||||||
"figure",
|
|
||||||
"font",
|
|
||||||
"footer",
|
|
||||||
"form",
|
|
||||||
"frame",
|
|
||||||
"frameset",
|
|
||||||
"h1",
|
|
||||||
"h2",
|
|
||||||
"h3",
|
|
||||||
"h4",
|
|
||||||
"h5",
|
|
||||||
"h6",
|
|
||||||
"head",
|
|
||||||
"header",
|
|
||||||
"hgroup",
|
|
||||||
"hr",
|
|
||||||
"html",
|
|
||||||
"i",
|
|
||||||
"iframe",
|
|
||||||
"image",
|
|
||||||
"img",
|
|
||||||
"input",
|
|
||||||
"ins",
|
|
||||||
"isindex",
|
|
||||||
"ismap",
|
|
||||||
"kbd",
|
|
||||||
"keygen",
|
|
||||||
"label",
|
|
||||||
"legend",
|
|
||||||
"li",
|
|
||||||
"link",
|
|
||||||
"listing",
|
|
||||||
"main",
|
|
||||||
"map",
|
|
||||||
"mark",
|
|
||||||
"marquee",
|
|
||||||
"math",
|
|
||||||
"menu",
|
|
||||||
"menuitem",
|
|
||||||
"meta",
|
|
||||||
"meter",
|
|
||||||
"multicol",
|
|
||||||
"multiple",
|
|
||||||
"nav",
|
|
||||||
"nobr",
|
|
||||||
"noembed",
|
|
||||||
"noframes",
|
|
||||||
"nohref",
|
|
||||||
"noresize",
|
|
||||||
"noscript",
|
|
||||||
"noshade",
|
|
||||||
"nowrap",
|
|
||||||
"object",
|
|
||||||
"ol",
|
|
||||||
"optgroup",
|
|
||||||
"option",
|
|
||||||
"output",
|
|
||||||
"p",
|
|
||||||
"param",
|
|
||||||
"picture",
|
|
||||||
"plaintext",
|
|
||||||
"pre",
|
|
||||||
"progress",
|
|
||||||
"q",
|
|
||||||
"rb",
|
|
||||||
"readonly",
|
|
||||||
"rp",
|
|
||||||
"rt",
|
|
||||||
"rtc",
|
|
||||||
"ruby",
|
|
||||||
"s",
|
|
||||||
"samp",
|
|
||||||
"script",
|
|
||||||
"section",
|
|
||||||
"select",
|
|
||||||
"selected",
|
|
||||||
"shadow",
|
|
||||||
"small",
|
|
||||||
"source",
|
|
||||||
"spacer",
|
|
||||||
"span",
|
|
||||||
"strike",
|
|
||||||
"strong",
|
|
||||||
"style",
|
|
||||||
"sub",
|
|
||||||
"summary",
|
|
||||||
"sup",
|
|
||||||
"svg",
|
|
||||||
"table",
|
|
||||||
"tbody",
|
|
||||||
"td",
|
|
||||||
"template",
|
|
||||||
"textarea",
|
|
||||||
"tfoot",
|
|
||||||
"th",
|
|
||||||
"thead",
|
|
||||||
"time",
|
|
||||||
"title",
|
|
||||||
"tr",
|
|
||||||
"track",
|
|
||||||
"tt",
|
|
||||||
"u",
|
|
||||||
"ul",
|
|
||||||
"var",
|
|
||||||
"video",
|
|
||||||
"wbr",
|
|
||||||
"xmp",
|
|
||||||
"XXX",
|
|
||||||
].forEach(function(tag) {
|
|
||||||
scan(document.createElement(tag));
|
|
||||||
});
|
|
||||||
[
|
|
||||||
"abort",
|
|
||||||
"absolutedeviceorientation",
|
|
||||||
"activate",
|
|
||||||
"active",
|
|
||||||
"addsourcebuffer",
|
|
||||||
"addstream",
|
|
||||||
"addtrack",
|
|
||||||
"afterprint",
|
|
||||||
"afterscriptexecute",
|
|
||||||
"afterupdate",
|
|
||||||
"animationcancel",
|
|
||||||
"animationend",
|
|
||||||
"animationiteration",
|
|
||||||
"animationstart",
|
|
||||||
"appinstalled",
|
|
||||||
"audioend",
|
|
||||||
"audioprocess",
|
|
||||||
"audiostart",
|
|
||||||
"autocomplete",
|
|
||||||
"autocompleteerror",
|
|
||||||
"auxclick",
|
|
||||||
"beforeactivate",
|
|
||||||
"beforecopy",
|
|
||||||
"beforecut",
|
|
||||||
"beforedeactivate",
|
|
||||||
"beforeeditfocus",
|
|
||||||
"beforeinstallprompt",
|
|
||||||
"beforepaste",
|
|
||||||
"beforeprint",
|
|
||||||
"beforescriptexecute",
|
|
||||||
"beforeunload",
|
|
||||||
"beforeupdate",
|
|
||||||
"blocked",
|
|
||||||
"blur",
|
|
||||||
"bounce",
|
|
||||||
"boundary",
|
|
||||||
"cached",
|
|
||||||
"cancel",
|
|
||||||
"candidatewindowhide",
|
|
||||||
"candidatewindowshow",
|
|
||||||
"candidatewindowupdate",
|
|
||||||
"canplay",
|
|
||||||
"canplaythrough",
|
|
||||||
"cellchange",
|
|
||||||
"change",
|
|
||||||
"chargingchange",
|
|
||||||
"chargingtimechange",
|
|
||||||
"checking",
|
|
||||||
"click",
|
|
||||||
"close",
|
|
||||||
"compassneedscalibration",
|
|
||||||
"complete",
|
|
||||||
"connect",
|
|
||||||
"connecting",
|
|
||||||
"connectionstatechange",
|
|
||||||
"contextmenu",
|
|
||||||
"controllerchange",
|
|
||||||
"controlselect",
|
|
||||||
"copy",
|
|
||||||
"cuechange",
|
|
||||||
"cut",
|
|
||||||
"dataavailable",
|
|
||||||
"datachannel",
|
|
||||||
"datasetchanged",
|
|
||||||
"datasetcomplete",
|
|
||||||
"dblclick",
|
|
||||||
"deactivate",
|
|
||||||
"devicechange",
|
|
||||||
"devicelight",
|
|
||||||
"devicemotion",
|
|
||||||
"deviceorientation",
|
|
||||||
"deviceorientationabsolute",
|
|
||||||
"deviceproximity",
|
|
||||||
"dischargingtimechange",
|
|
||||||
"disconnect",
|
|
||||||
"display",
|
|
||||||
"downloading",
|
|
||||||
"drag",
|
|
||||||
"dragend",
|
|
||||||
"dragenter",
|
|
||||||
"dragexit",
|
|
||||||
"dragleave",
|
|
||||||
"dragover",
|
|
||||||
"dragstart",
|
|
||||||
"drop",
|
|
||||||
"durationchange",
|
|
||||||
"emptied",
|
|
||||||
"encrypted",
|
|
||||||
"end",
|
|
||||||
"ended",
|
|
||||||
"enter",
|
|
||||||
"enterpictureinpicture",
|
|
||||||
"error",
|
|
||||||
"errorupdate",
|
|
||||||
"exit",
|
|
||||||
"filterchange",
|
|
||||||
"finish",
|
|
||||||
"focus",
|
|
||||||
"focusin",
|
|
||||||
"focusout",
|
|
||||||
"freeze",
|
|
||||||
"fullscreenchange",
|
|
||||||
"fullscreenerror",
|
|
||||||
"gesturechange",
|
|
||||||
"gestureend",
|
|
||||||
"gesturestart",
|
|
||||||
"gotpointercapture",
|
|
||||||
"hashchange",
|
|
||||||
"help",
|
|
||||||
"icecandidate",
|
|
||||||
"iceconnectionstatechange",
|
|
||||||
"icegatheringstatechange",
|
|
||||||
"inactive",
|
|
||||||
"input",
|
|
||||||
"invalid",
|
|
||||||
"keydown",
|
|
||||||
"keypress",
|
|
||||||
"keyup",
|
|
||||||
"languagechange",
|
|
||||||
"layoutcomplete",
|
|
||||||
"leavepictureinpicture",
|
|
||||||
"levelchange",
|
|
||||||
"load",
|
|
||||||
"loadeddata",
|
|
||||||
"loadedmetadata",
|
|
||||||
"loadend",
|
|
||||||
"loading",
|
|
||||||
"loadingdone",
|
|
||||||
"loadingerror",
|
|
||||||
"loadstart",
|
|
||||||
"losecapture",
|
|
||||||
"lostpointercapture",
|
|
||||||
"mark",
|
|
||||||
"message",
|
|
||||||
"messageerror",
|
|
||||||
"mousedown",
|
|
||||||
"mouseenter",
|
|
||||||
"mouseleave",
|
|
||||||
"mousemove",
|
|
||||||
"mouseout",
|
|
||||||
"mouseover",
|
|
||||||
"mouseup",
|
|
||||||
"mousewheel",
|
|
||||||
"move",
|
|
||||||
"moveend",
|
|
||||||
"movestart",
|
|
||||||
"mozfullscreenchange",
|
|
||||||
"mozfullscreenerror",
|
|
||||||
"mozorientationchange",
|
|
||||||
"mozpointerlockchange",
|
|
||||||
"mozpointerlockerror",
|
|
||||||
"mscontentzoom",
|
|
||||||
"msfullscreenchange",
|
|
||||||
"msfullscreenerror",
|
|
||||||
"msgesturechange",
|
|
||||||
"msgesturedoubletap",
|
|
||||||
"msgestureend",
|
|
||||||
"msgesturehold",
|
|
||||||
"msgesturestart",
|
|
||||||
"msgesturetap",
|
|
||||||
"msgotpointercapture",
|
|
||||||
"msinertiastart",
|
|
||||||
"mslostpointercapture",
|
|
||||||
"msmanipulationstatechanged",
|
|
||||||
"msneedkey",
|
|
||||||
"msorientationchange",
|
|
||||||
"mspointercancel",
|
|
||||||
"mspointerdown",
|
|
||||||
"mspointerenter",
|
|
||||||
"mspointerhover",
|
|
||||||
"mspointerleave",
|
|
||||||
"mspointermove",
|
|
||||||
"mspointerout",
|
|
||||||
"mspointerover",
|
|
||||||
"mspointerup",
|
|
||||||
"mssitemodejumplistitemremoved",
|
|
||||||
"msthumbnailclick",
|
|
||||||
"negotiationneeded",
|
|
||||||
"nomatch",
|
|
||||||
"noupdate",
|
|
||||||
"obsolete",
|
|
||||||
"offline",
|
|
||||||
"online",
|
|
||||||
"open",
|
|
||||||
"orientationchange",
|
|
||||||
"pagechange",
|
|
||||||
"pagehide",
|
|
||||||
"pageshow",
|
|
||||||
"paste",
|
|
||||||
"pause",
|
|
||||||
"play",
|
|
||||||
"playing",
|
|
||||||
"pluginstreamstart",
|
|
||||||
"pointercancel",
|
|
||||||
"pointerdown",
|
|
||||||
"pointerenter",
|
|
||||||
"pointerleave",
|
|
||||||
"pointerlockchange",
|
|
||||||
"pointerlockerror",
|
|
||||||
"pointermove",
|
|
||||||
"pointerout",
|
|
||||||
"pointerover",
|
|
||||||
"pointerup",
|
|
||||||
"popstate",
|
|
||||||
"progress",
|
|
||||||
"propertychange",
|
|
||||||
"ratechange",
|
|
||||||
"reading",
|
|
||||||
"readystatechange",
|
|
||||||
"rejectionhandled",
|
|
||||||
"removesourcebuffer",
|
|
||||||
"removestream",
|
|
||||||
"removetrack",
|
|
||||||
"reset",
|
|
||||||
"resize",
|
|
||||||
"resizeend",
|
|
||||||
"resizestart",
|
|
||||||
"resourcetimingbufferfull",
|
|
||||||
"result",
|
|
||||||
"resume",
|
|
||||||
"rowenter",
|
|
||||||
"rowexit",
|
|
||||||
"rowsdelete",
|
|
||||||
"rowsinserted",
|
|
||||||
"scroll",
|
|
||||||
"search",
|
|
||||||
"seeked",
|
|
||||||
"seeking",
|
|
||||||
"select",
|
|
||||||
"selectionchange",
|
|
||||||
"selectstart",
|
|
||||||
"show",
|
|
||||||
"signalingstatechange",
|
|
||||||
"soundend",
|
|
||||||
"soundstart",
|
|
||||||
"sourceclose",
|
|
||||||
"sourceclosed",
|
|
||||||
"sourceended",
|
|
||||||
"sourceopen",
|
|
||||||
"speechend",
|
|
||||||
"speechstart",
|
|
||||||
"stalled",
|
|
||||||
"start",
|
|
||||||
"statechange",
|
|
||||||
"stop",
|
|
||||||
"storage",
|
|
||||||
"storagecommit",
|
|
||||||
"submit",
|
|
||||||
"success",
|
|
||||||
"suspend",
|
|
||||||
"textinput",
|
|
||||||
"timeout",
|
|
||||||
"timeupdate",
|
|
||||||
"toggle",
|
|
||||||
"touchcancel",
|
|
||||||
"touchend",
|
|
||||||
"touchmove",
|
|
||||||
"touchstart",
|
|
||||||
"track",
|
|
||||||
"transitioncancel",
|
|
||||||
"transitionend",
|
|
||||||
"transitionrun",
|
|
||||||
"transitionstart",
|
|
||||||
"unhandledrejection",
|
|
||||||
"unload",
|
|
||||||
"updateready",
|
|
||||||
"upgradeneeded",
|
|
||||||
"userproximity",
|
|
||||||
"versionchange",
|
|
||||||
"visibilitychange",
|
|
||||||
"voiceschanged",
|
|
||||||
"volumechange",
|
|
||||||
"vrdisplayactivate",
|
|
||||||
"vrdisplayconnect",
|
|
||||||
"vrdisplaydeactivate",
|
|
||||||
"vrdisplaydisconnect",
|
|
||||||
"vrdisplaypresentchange",
|
|
||||||
"waiting",
|
|
||||||
"waitingforkey",
|
|
||||||
"warning",
|
|
||||||
"webkitanimationend",
|
|
||||||
"webkitanimationiteration",
|
|
||||||
"webkitanimationstart",
|
|
||||||
"webkitcurrentplaybacktargetiswirelesschanged",
|
|
||||||
"webkitfullscreenchange",
|
|
||||||
"webkitfullscreenerror",
|
|
||||||
"webkitkeyadded",
|
|
||||||
"webkitkeyerror",
|
|
||||||
"webkitkeymessage",
|
|
||||||
"webkitneedkey",
|
|
||||||
"webkitorientationchange",
|
|
||||||
"webkitplaybacktargetavailabilitychanged",
|
|
||||||
"webkitpointerlockchange",
|
|
||||||
"webkitpointerlockerror",
|
|
||||||
"webkitresourcetimingbufferfull",
|
|
||||||
"webkittransitionend",
|
|
||||||
"wheel",
|
|
||||||
"zoom",
|
|
||||||
].forEach(function(type) {
|
|
||||||
[
|
|
||||||
"beforeunloadevent",
|
|
||||||
"compositionevent",
|
|
||||||
"customevent",
|
|
||||||
"devicemotionevent",
|
|
||||||
"deviceorientationevent",
|
|
||||||
"dragevent",
|
|
||||||
"event",
|
|
||||||
"events",
|
|
||||||
"focusevent",
|
|
||||||
"hashchangeevent",
|
|
||||||
"htmlevents",
|
|
||||||
"keyboardevent",
|
|
||||||
"messageevent",
|
|
||||||
"mouseevent",
|
|
||||||
"mouseevents",
|
|
||||||
"storageevent",
|
|
||||||
"svgevents",
|
|
||||||
"textevent",
|
|
||||||
"touchevent",
|
|
||||||
"uievent",
|
|
||||||
"uievents",
|
|
||||||
].forEach(function(interface) {
|
|
||||||
try {
|
|
||||||
var event = document.createEvent(interface);
|
|
||||||
event.initEvent(type, true, true);
|
|
||||||
scan(event);
|
|
||||||
} catch (e) {}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
var obj;
|
|
||||||
while (obj = to_scan.shift()) {
|
|
||||||
var proto = obj;
|
|
||||||
do {
|
|
||||||
Object.getOwnPropertyNames(proto).forEach(function(name) {
|
|
||||||
var visited = ~names.indexOf(name);
|
|
||||||
if (!visited) names.push(name);
|
|
||||||
try {
|
|
||||||
scan(obj[name]);
|
|
||||||
if (visited) return;
|
|
||||||
if (/^create/.test(name)) {
|
|
||||||
scan(obj[name]());
|
|
||||||
}
|
|
||||||
if (/^[A-Z]/.test(name)) {
|
|
||||||
scan(new obj[name]());
|
|
||||||
}
|
|
||||||
} catch (e) {}
|
|
||||||
});
|
|
||||||
} while (proto = Object.getPrototypeOf(proto));
|
|
||||||
}
|
|
||||||
names.sort();
|
|
||||||
document.write('<pre>[\n "');
|
|
||||||
document.write(names.join('",\n "'));
|
|
||||||
document.write('"\n]</pre>');
|
|
||||||
}();
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Reference in New Issue
Block a user