Compare commits
248 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20f9a1d908 | ||
|
|
dcb74f558e | ||
|
|
0794aaa2c2 | ||
|
|
74801de315 | ||
|
|
f80d5b8c9e | ||
|
|
d900006973 | ||
|
|
39f849590b | ||
|
|
818738beec | ||
|
|
bc2a4a3bb8 | ||
|
|
a4a8ccea8c | ||
|
|
36dcfa3e82 | ||
|
|
94f33570e3 | ||
|
|
44d6912a55 | ||
|
|
3a4497a1c3 | ||
|
|
3ee13cae02 | ||
|
|
99cf3a38c5 | ||
|
|
3ae24329eb | ||
|
|
01b13d797c | ||
|
|
306e8e9873 | ||
|
|
9577c8c1b7 | ||
|
|
925a0ca1a0 | ||
|
|
b694bfa351 | ||
|
|
a2fc32c64b | ||
|
|
88504ab869 | ||
|
|
e38754e802 | ||
|
|
eb6f32bfc3 | ||
|
|
f110601fb4 | ||
|
|
2a508c6e5f | ||
|
|
fd6144d95b | ||
|
|
60d4e7b09f | ||
|
|
b38838c6bf | ||
|
|
708973e51d | ||
|
|
dac9e69f9e | ||
|
|
39aa33749b | ||
|
|
da68ec6e19 | ||
|
|
15a3ebd467 | ||
|
|
9110fac9a2 | ||
|
|
83f42ede36 | ||
|
|
0ce71bbec0 | ||
|
|
46d142cbf6 | ||
|
|
38c3bcf9a0 | ||
|
|
6e9afdc94f | ||
|
|
c4d28e3b2a | ||
|
|
77261e1ee0 | ||
|
|
903a5df9a5 | ||
|
|
c810ecd081 | ||
|
|
dce9dfce0e | ||
|
|
3d72663689 | ||
|
|
a2b16e89a4 | ||
|
|
b35f4c5a83 | ||
|
|
41eb4f1725 | ||
|
|
94bc221669 | ||
|
|
822d298a55 | ||
|
|
273c6020ba | ||
|
|
1b07f64057 | ||
|
|
80d9c44b22 | ||
|
|
dc0cd088cf | ||
|
|
c69c026728 | ||
|
|
b5f4e1187f | ||
|
|
827bcec186 | ||
|
|
d105ab9722 | ||
|
|
b39228892d | ||
|
|
ff72eaa3c3 | ||
|
|
0a1c9b34ce | ||
|
|
03e968be62 | ||
|
|
421bb7083a | ||
|
|
bdc8ef2218 | ||
|
|
bca52fcba2 | ||
|
|
d6d31cbb5a | ||
|
|
a051846d22 | ||
|
|
3485472866 | ||
|
|
c8d60d6983 | ||
|
|
6092bf23de | ||
|
|
7052ce5aef | ||
|
|
d13b71297e | ||
|
|
457f958af3 | ||
|
|
53517db3e4 | ||
|
|
c13caf4876 | ||
|
|
fbfa6178a6 | ||
|
|
5315dd95b0 | ||
|
|
31a7bf2a22 | ||
|
|
f0a29902ac | ||
|
|
0d820e4c0a | ||
|
|
f01f580d6c | ||
|
|
c01ff76288 | ||
|
|
83a42716c3 | ||
|
|
2557148bba | ||
|
|
dd22eda888 | ||
|
|
f4c77886e7 | ||
|
|
df547ffd97 | ||
|
|
70551febc8 | ||
|
|
44499a6643 | ||
|
|
470a7d4df1 | ||
|
|
551420132c | ||
|
|
b0040ba654 | ||
|
|
c93ca6ee53 | ||
|
|
df506439b1 | ||
|
|
36b2d35bf3 | ||
|
|
79c60032a5 | ||
|
|
a3754068dd | ||
|
|
2ba5f391e0 | ||
|
|
87119e44a0 | ||
|
|
b499e03f82 | ||
|
|
a478f275e4 | ||
|
|
e9e76dcf04 | ||
|
|
0dcedad2d5 | ||
|
|
36a430cd1e | ||
|
|
41a6eb892a | ||
|
|
91d87ae663 | ||
|
|
5beb7e4797 | ||
|
|
46caaa82ba | ||
|
|
5d258259a4 | ||
|
|
14c35739dd | ||
|
|
f5ceff6e4b | ||
|
|
4d6771b9b1 | ||
|
|
d17191111a | ||
|
|
0ff607cb80 | ||
|
|
1988495d71 | ||
|
|
fdc10086da | ||
|
|
746f5f6c62 | ||
|
|
d83d3d741a | ||
|
|
99ac73a635 | ||
|
|
a2e4c2fd97 | ||
|
|
94785e8e14 | ||
|
|
4dbdac9c31 | ||
|
|
78c8efd851 | ||
|
|
af310ba2d0 | ||
|
|
2f3930d1b9 | ||
|
|
d1a78920d9 | ||
|
|
d9cd3d33c8 | ||
|
|
22b47cdd63 | ||
|
|
4cf612dc9f | ||
|
|
a19d31dd33 | ||
|
|
01d6e0f223 | ||
|
|
ab050e7a94 | ||
|
|
75aa6ef848 | ||
|
|
519a00bd8a | ||
|
|
3ff0feddee | ||
|
|
74396acc86 | ||
|
|
036bca980c | ||
|
|
18c2b1841b | ||
|
|
fe19ab7c57 | ||
|
|
9074f05129 | ||
|
|
04fbb1f949 | ||
|
|
bf7e4ca1a3 | ||
|
|
d68ddc31f9 | ||
|
|
500e31e03b | ||
|
|
bef856addb | ||
|
|
9a6faf365b | ||
|
|
e915832a36 | ||
|
|
0593892d6e | ||
|
|
b866a23671 | ||
|
|
1283d73853 | ||
|
|
1b61a81b5d | ||
|
|
5a88c30d65 | ||
|
|
168ae747ad | ||
|
|
d4b7010678 | ||
|
|
e27493f3c2 | ||
|
|
292d1de363 | ||
|
|
6768e6578f | ||
|
|
48a0f6fe41 | ||
|
|
81caadb709 | ||
|
|
d959e0b86f | ||
|
|
67278e76c8 | ||
|
|
c289ba1139 | ||
|
|
02cc4a0d03 | ||
|
|
4e06e1ca34 | ||
|
|
644f65feca | ||
|
|
8504a4ea0e | ||
|
|
10c1a78772 | ||
|
|
a6a0319f1c | ||
|
|
d1b2ecec27 | ||
|
|
552be61c4d | ||
|
|
dcfc4aca5b | ||
|
|
4027f87717 | ||
|
|
910799ca99 | ||
|
|
4bd36dc8da | ||
|
|
ab15c40770 | ||
|
|
fe65ce9658 | ||
|
|
d6fd18d0b0 | ||
|
|
0d17c5b0fa | ||
|
|
5b20bad4b3 | ||
|
|
765a06340f | ||
|
|
5045e140b1 | ||
|
|
10648c9af6 | ||
|
|
87e67ec299 | ||
|
|
61a0dad9fe | ||
|
|
3e2c51a4da | ||
|
|
0e29ad5eb9 | ||
|
|
0f2687ecfc | ||
|
|
1c0defdc03 | ||
|
|
dcbf2236c7 | ||
|
|
24bb288832 | ||
|
|
6ad8e1081f | ||
|
|
815eff1f7c | ||
|
|
1e9b576ee9 | ||
|
|
3797458365 | ||
|
|
1858c2018c | ||
|
|
ec7f071272 | ||
|
|
f1eb03f2c0 | ||
|
|
0f4cfa877a | ||
|
|
1d5c2becbd | ||
|
|
22a09ea7c5 | ||
|
|
bad664c632 | ||
|
|
8a191c0a84 | ||
|
|
83fb8b4ca1 | ||
|
|
f38e31bd1e | ||
|
|
24e8b47977 | ||
|
|
95618793a4 | ||
|
|
2f3b460212 | ||
|
|
06e135e35f | ||
|
|
ebbf3d4a51 | ||
|
|
a270ba6b59 | ||
|
|
37f35e4ac2 | ||
|
|
50a578c1f6 | ||
|
|
85237b08d4 | ||
|
|
27b159e711 | ||
|
|
82b3eed5ef | ||
|
|
0f7aa41e33 | ||
|
|
370c8e0385 | ||
|
|
4240fba9b8 | ||
|
|
267bc70d33 | ||
|
|
a53ab99378 | ||
|
|
02308a7b56 | ||
|
|
0b3705e82f | ||
|
|
da5a21b240 | ||
|
|
5bd0cf8633 | ||
|
|
9199ab5846 | ||
|
|
ca6dce43fe | ||
|
|
543dd7d3d7 | ||
|
|
6b4886c908 | ||
|
|
0201cb4b52 | ||
|
|
cd072317d0 | ||
|
|
0785a15ace | ||
|
|
b1279a46d9 | ||
|
|
b571619d31 | ||
|
|
7b5350b459 | ||
|
|
1549db70e6 | ||
|
|
8ff9a3c8fb | ||
|
|
91cae51d8f | ||
|
|
8af2f5fbcf | ||
|
|
86a8016323 | ||
|
|
009dcdae01 | ||
|
|
f86f615d83 | ||
|
|
d3d1d11926 | ||
|
|
736019b767 | ||
|
|
a39bdb5840 | ||
|
|
e8ab0a44b2 |
43
.github/workflows/ci.yml
vendored
Normal file
43
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
name: CI
|
||||||
|
on: [ push, pull_request ]
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node: [ "0.8", "0.10", "0.12", "4", "6", "8", "10", "12", latest ]
|
||||||
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
|
script: [ compress, mocha, release/benchmark, release/jetstream ]
|
||||||
|
exclude:
|
||||||
|
- node: "0.8"
|
||||||
|
script: release/jetstream
|
||||||
|
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
NODE: ${{ matrix.node }}
|
||||||
|
TYPE: ${{ matrix.script }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/cache@v1
|
||||||
|
with:
|
||||||
|
path: tmp
|
||||||
|
key: tmp ${{ matrix.script }}
|
||||||
|
- name: Perform tests
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||||
|
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add $NODE && nvs use $NODE'; do
|
||||||
|
cd ~/.nvs
|
||||||
|
git clean -xdf
|
||||||
|
cd -
|
||||||
|
done
|
||||||
|
. ~/.nvs/nvs.sh --version
|
||||||
|
nvs use $NODE
|
||||||
|
node --version
|
||||||
|
npm config set audit false
|
||||||
|
npm config set optional false
|
||||||
|
npm config set save false
|
||||||
|
npm config set strict-ssl false
|
||||||
|
npm config set update-notifier false
|
||||||
|
npm --version
|
||||||
|
while !(npm install); do echo "'npm install' failed - retrying..."; done
|
||||||
|
node test/$TYPE
|
||||||
34
.github/workflows/ufuzz.yml
vendored
Normal file
34
.github/workflows/ufuzz.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
name: Fuzzing
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "*/8 * * * *"
|
||||||
|
jobs:
|
||||||
|
ufuzz:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
|
name: ${{ matrix.os }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Perform fuzzing
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||||
|
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add 10 && nvs use 10'; do
|
||||||
|
cd ~/.nvs
|
||||||
|
git clean -xdf
|
||||||
|
cd -
|
||||||
|
done
|
||||||
|
. ~/.nvs/nvs.sh --version
|
||||||
|
nvs use 10
|
||||||
|
node --version
|
||||||
|
npm config set audit false
|
||||||
|
npm config set optional false
|
||||||
|
npm config set save false
|
||||||
|
npm config set strict-ssl false
|
||||||
|
npm config set update-notifier false
|
||||||
|
npm --version
|
||||||
|
while !(npm install); do echo "'npm install' failed - retrying..."; done
|
||||||
|
node test/ufuzz/job 3600000
|
||||||
46
.travis.yml
46
.travis.yml
@@ -1,46 +0,0 @@
|
|||||||
cache:
|
|
||||||
directories: tmp
|
|
||||||
language: generic
|
|
||||||
matrix:
|
|
||||||
fast_finish: true
|
|
||||||
env:
|
|
||||||
- NODE=0.10 TYPE=compress
|
|
||||||
- NODE=0.10 TYPE=mocha
|
|
||||||
- NODE=0.10 TYPE=release/benchmark
|
|
||||||
- NODE=0.10 TYPE=release/jetstream
|
|
||||||
- NODE=0.12 TYPE=compress
|
|
||||||
- NODE=0.12 TYPE=mocha
|
|
||||||
- NODE=0.12 TYPE=release/benchmark
|
|
||||||
- NODE=0.12 TYPE=release/jetstream
|
|
||||||
- NODE=4 TYPE=compress
|
|
||||||
- NODE=4 TYPE=mocha
|
|
||||||
- NODE=4 TYPE=release/benchmark
|
|
||||||
- NODE=4 TYPE=release/jetstream
|
|
||||||
- NODE=6 TYPE=compress
|
|
||||||
- NODE=6 TYPE=mocha
|
|
||||||
- NODE=6 TYPE=release/benchmark
|
|
||||||
- NODE=6 TYPE=release/jetstream
|
|
||||||
- NODE=8 TYPE=compress
|
|
||||||
- NODE=8 TYPE=mocha
|
|
||||||
- NODE=8 TYPE=release/benchmark
|
|
||||||
- NODE=8 TYPE=release/jetstream
|
|
||||||
- NODE=10 TYPE=compress
|
|
||||||
- NODE=10 TYPE=mocha
|
|
||||||
- NODE=10 TYPE=release/benchmark
|
|
||||||
- NODE=10 TYPE=release/jetstream
|
|
||||||
- NODE=latest TYPE=compress
|
|
||||||
- NODE=latest TYPE=mocha
|
|
||||||
- NODE=latest TYPE=release/benchmark
|
|
||||||
- NODE=latest TYPE=release/jetstream
|
|
||||||
before_install:
|
|
||||||
- git clone --branch v1.5.2 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
|
||||||
- . ~/.nvs/nvs.sh
|
|
||||||
- nvs --version
|
|
||||||
install:
|
|
||||||
- nvs add node/$NODE
|
|
||||||
- nvs use node/$NODE
|
|
||||||
- node --version
|
|
||||||
- npm --version --no-update-notifier
|
|
||||||
- npm install --no-audit --no-optional --no-save --no-update-notifier
|
|
||||||
script:
|
|
||||||
- node test/$TYPE
|
|
||||||
67
README.md
67
README.md
@@ -87,6 +87,7 @@ a double dash to prevent input files being used as option arguments:
|
|||||||
`wrap_iife` Wrap IIFEs in parenthesis. Note: you may
|
`wrap_iife` Wrap IIFEs in parenthesis. Note: you may
|
||||||
want to disable `negate_iife` under
|
want to disable `negate_iife` under
|
||||||
compressor options.
|
compressor options.
|
||||||
|
-O, --output-opts [options] Specify output options (`beautify` disabled by default).
|
||||||
-o, --output <file> Output file path (default STDOUT). Specify `ast` or
|
-o, --output <file> Output file path (default STDOUT). Specify `ast` or
|
||||||
`spidermonkey` to write UglifyJS or SpiderMonkey AST
|
`spidermonkey` to write UglifyJS or SpiderMonkey AST
|
||||||
as JSON to STDOUT respectively.
|
as JSON to STDOUT respectively.
|
||||||
@@ -125,6 +126,7 @@ a double dash to prevent input files being used as option arguments:
|
|||||||
`includeSources` Pass this flag if you want to include
|
`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
|
||||||
@@ -158,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.
|
||||||
@@ -478,42 +483,42 @@ if (result.error) throw result.error;
|
|||||||
|
|
||||||
## Minify options
|
## Minify options
|
||||||
|
|
||||||
- `warnings` (default `false`) — pass `true` to return compressor warnings
|
|
||||||
in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
|
|
||||||
|
|
||||||
- `parse` (default `{}`) — pass an object if you wish to specify some
|
|
||||||
additional [parse options](#parse-options).
|
|
||||||
|
|
||||||
- `compress` (default `{}`) — pass `false` to skip compressing entirely.
|
- `compress` (default `{}`) — pass `false` to skip compressing entirely.
|
||||||
Pass an object to specify custom [compress options](#compress-options).
|
Pass an object to specify custom [compress options](#compress-options).
|
||||||
|
|
||||||
|
- `ie8` (default `false`) -- set to `true` to support IE8.
|
||||||
|
|
||||||
|
- `keep_fnames` (default: `false`) -- pass `true` to prevent discarding or mangling
|
||||||
|
of function names. Useful for code relying on `Function.prototype.name`.
|
||||||
|
|
||||||
- `mangle` (default `true`) — pass `false` to skip mangling names, or pass
|
- `mangle` (default `true`) — pass `false` to skip mangling names, or pass
|
||||||
an object to specify [mangle options](#mangle-options) (see below).
|
an object to specify [mangle options](#mangle-options) (see below).
|
||||||
|
|
||||||
- `mangle.properties` (default `false`) — a subcategory of the mangle option.
|
- `mangle.properties` (default `false`) — a subcategory of the mangle option.
|
||||||
Pass an object to specify custom [mangle property options](#mangle-properties-options).
|
Pass an object to specify custom [mangle property options](#mangle-properties-options).
|
||||||
|
|
||||||
- `output` (default `null`) — pass an object if you wish to specify
|
- `nameCache` (default `null`) -- pass an empty object `{}` or a previously
|
||||||
additional [output options](#output-options). The defaults are optimized
|
|
||||||
for best compression.
|
|
||||||
|
|
||||||
- `sourceMap` (default `false`) - pass an object if you wish to specify
|
|
||||||
[source map options](#source-map-options).
|
|
||||||
|
|
||||||
- `toplevel` (default `false`) - set to `true` if you wish to enable top level
|
|
||||||
variable and function name mangling and to drop unused variables and functions.
|
|
||||||
|
|
||||||
- `nameCache` (default `null`) - pass an empty object `{}` or a previously
|
|
||||||
used `nameCache` object if you wish to cache mangled variable and
|
used `nameCache` object if you wish to cache mangled variable and
|
||||||
property names across multiple invocations of `minify()`. Note: this is
|
property names across multiple invocations of `minify()`. Note: this is
|
||||||
a read/write property. `minify()` will read the name cache state of this
|
a read/write property. `minify()` will read the name cache state of this
|
||||||
object and update it during minification so that it may be
|
object and update it during minification so that it may be
|
||||||
reused or externally persisted by the user.
|
reused or externally persisted by the user.
|
||||||
|
|
||||||
- `ie8` (default `false`) - set to `true` to support IE8.
|
- `output` (default `null`) — pass an object if you wish to specify
|
||||||
|
additional [output options](#output-options). The defaults are optimized
|
||||||
|
for best compression.
|
||||||
|
|
||||||
- `keep_fnames` (default: `false`) - pass `true` to prevent discarding or mangling
|
- `parse` (default `{}`) — pass an object if you wish to specify some
|
||||||
of function names. Useful for code relying on `Function.prototype.name`.
|
additional [parse options](#parse-options).
|
||||||
|
|
||||||
|
- `sourceMap` (default `false`) -- pass an object if you wish to specify
|
||||||
|
[source map options](#source-map-options).
|
||||||
|
|
||||||
|
- `toplevel` (default `false`) -- set to `true` if you wish to enable top level
|
||||||
|
variable and function name mangling and to drop unused variables and functions.
|
||||||
|
|
||||||
|
- `warnings` (default `false`) — pass `true` to return compressor warnings
|
||||||
|
in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
|
||||||
|
|
||||||
## Minify options structure
|
## Minify options structure
|
||||||
|
|
||||||
@@ -592,6 +597,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
|
||||||
@@ -631,7 +639,10 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
|
|
||||||
- `drop_debugger` (default: `true`) -- remove `debugger;` statements
|
- `drop_debugger` (default: `true`) -- remove `debugger;` statements
|
||||||
|
|
||||||
- `evaluate` (default: `true`) -- attempt to evaluate constant expressions
|
- `evaluate` (default: `true`) -- Evaluate expression for shorter constant
|
||||||
|
representation. Pass `"eager"` to always replace function calls whenever
|
||||||
|
possible, or a positive integer to specify an upper bound for each individual
|
||||||
|
evaluation in number of characters.
|
||||||
|
|
||||||
- `expression` (default: `false`) -- Pass `true` to preserve completion values
|
- `expression` (default: `false`) -- Pass `true` to preserve completion values
|
||||||
from terminal statements without `return`, e.g. in bookmarklets.
|
from terminal statements without `return`, e.g. in bookmarklets.
|
||||||
@@ -682,6 +693,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
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.
|
||||||
|
|
||||||
|
- `objects` (default: `true`) -- compact duplicate keys in object literals.
|
||||||
|
|
||||||
- `passes` (default: `1`) -- The maximum number of times to run compress.
|
- `passes` (default: `1`) -- The maximum number of times to run compress.
|
||||||
In some cases more than one pass leads to further compressed code. Keep in
|
In some cases more than one pass leads to further compressed code. Keep in
|
||||||
mind more passes will take more time.
|
mind more passes will take more time.
|
||||||
@@ -730,6 +743,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
|
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
|
||||||
example: `/*@__PURE__*/foo();`
|
example: `/*@__PURE__*/foo();`
|
||||||
|
|
||||||
|
- `strings` (default: `true`) -- compact string concatenations.
|
||||||
|
|
||||||
- `switches` (default: `true`) -- de-duplicate and remove unreachable `switch` branches
|
- `switches` (default: `true`) -- de-duplicate and remove unreachable `switch` branches
|
||||||
|
|
||||||
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or
|
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or
|
||||||
@@ -840,8 +855,14 @@ can pass additional arguments that control the code output:
|
|||||||
statement.
|
statement.
|
||||||
|
|
||||||
- `comments` (default `false`) -- pass `true` or `"all"` to preserve all
|
- `comments` (default `false`) -- pass `true` or `"all"` to preserve all
|
||||||
comments, `"some"` to preserve some comments, a regular expression string
|
comments, `"some"` to preserve multi-line comments that contain `@cc_on`,
|
||||||
(e.g. `/^!/`) or a function.
|
`@license`, or `@preserve` (case-insensitive), a regular expression string
|
||||||
|
(e.g. `/^!/`), or a function which returns `boolean`, e.g.
|
||||||
|
```js
|
||||||
|
function(node, comment) {
|
||||||
|
return comment.value.indexOf("@type " + node.TYPE) >= 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
- `indent_level` (default `4`)
|
- `indent_level` (default `4`)
|
||||||
|
|
||||||
|
|||||||
71
appveyor.yml
71
appveyor.yml
@@ -1,74 +1,5 @@
|
|||||||
build: off
|
build: off
|
||||||
cache:
|
|
||||||
- tmp
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
environment:
|
|
||||||
matrix:
|
|
||||||
- NODE: 0.10
|
|
||||||
TYPE: compress
|
|
||||||
- NODE: 0.10
|
|
||||||
TYPE: mocha
|
|
||||||
- NODE: 0.10
|
|
||||||
TYPE: release/benchmark
|
|
||||||
- NODE: 0.10
|
|
||||||
TYPE: release/jetstream
|
|
||||||
- NODE: 0.12
|
|
||||||
TYPE: compress
|
|
||||||
- NODE: 0.12
|
|
||||||
TYPE: mocha
|
|
||||||
- NODE: 0.12
|
|
||||||
TYPE: release/benchmark
|
|
||||||
- NODE: 0.12
|
|
||||||
TYPE: release/jetstream
|
|
||||||
- NODE: 4
|
|
||||||
TYPE: compress
|
|
||||||
- NODE: 4
|
|
||||||
TYPE: mocha
|
|
||||||
- NODE: 4
|
|
||||||
TYPE: release/benchmark
|
|
||||||
- NODE: 4
|
|
||||||
TYPE: release/jetstream
|
|
||||||
- NODE: 6
|
|
||||||
TYPE: compress
|
|
||||||
- NODE: 6
|
|
||||||
TYPE: mocha
|
|
||||||
- NODE: 6
|
|
||||||
TYPE: release/benchmark
|
|
||||||
- NODE: 6
|
|
||||||
TYPE: release/jetstream
|
|
||||||
- NODE: 8
|
|
||||||
TYPE: compress
|
|
||||||
- NODE: 8
|
|
||||||
TYPE: mocha
|
|
||||||
- NODE: 8
|
|
||||||
TYPE: release/benchmark
|
|
||||||
- NODE: 8
|
|
||||||
TYPE: release/jetstream
|
|
||||||
- NODE: 10
|
|
||||||
TYPE: compress
|
|
||||||
- NODE: 10
|
|
||||||
TYPE: mocha
|
|
||||||
- NODE: 10
|
|
||||||
TYPE: release/benchmark
|
|
||||||
- NODE: 10
|
|
||||||
TYPE: release/jetstream
|
|
||||||
- NODE: latest
|
|
||||||
TYPE: compress
|
|
||||||
- NODE: latest
|
|
||||||
TYPE: mocha
|
|
||||||
- NODE: latest
|
|
||||||
TYPE: release/benchmark
|
|
||||||
- NODE: latest
|
|
||||||
TYPE: release/jetstream
|
|
||||||
install:
|
|
||||||
- git clone --branch v1.5.2 --depth 1 https://github.com/jasongin/nvs.git %LOCALAPPDATA%\nvs
|
|
||||||
- set PATH=%LOCALAPPDATA%\nvs;%PATH%
|
|
||||||
- nvs --version
|
|
||||||
- nvs add node/%NODE%
|
|
||||||
- nvs use node/%NODE%
|
|
||||||
- node --version
|
|
||||||
- npm --version --no-update-notifier
|
|
||||||
- npm install --no-audit --no-optional --no-save --no-update-notifier
|
|
||||||
test_script:
|
test_script:
|
||||||
- node test/%TYPE%
|
- echo No longer in use
|
||||||
|
|||||||
50
bin/uglifyjs
50
bin/uglifyjs
@@ -23,12 +23,29 @@ program.parse = undefined;
|
|||||||
if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
|
if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
|
||||||
else if (process.argv.indexOf("options") >= 0) program.helpInformation = function() {
|
else if (process.argv.indexOf("options") >= 0) program.helpInformation = function() {
|
||||||
var text = [];
|
var text = [];
|
||||||
|
var toplevels = [];
|
||||||
|
var padding = "";
|
||||||
var options = UglifyJS.default_options();
|
var options = UglifyJS.default_options();
|
||||||
for (var option in options) {
|
for (var name in options) {
|
||||||
text.push("--" + (option == "output" ? "beautify" : option == "sourceMap" ? "source-map" : option) + " options:");
|
var option = options[name];
|
||||||
text.push(format_object(options[option]));
|
if (option && typeof option == "object") {
|
||||||
text.push("");
|
text.push("--" + ({
|
||||||
|
output: "beautify",
|
||||||
|
sourceMap: "source-map",
|
||||||
|
}[name] || name) + " options:");
|
||||||
|
text.push(format_object(option));
|
||||||
|
text.push("");
|
||||||
|
} else {
|
||||||
|
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
|
||||||
|
toplevels.push([ {
|
||||||
|
keep_fnames: "keep-fnames",
|
||||||
|
nameCache: "name-cache",
|
||||||
|
}[name] || name, option ]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
toplevels.forEach(function(tokens) {
|
||||||
|
text.push("--" + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
|
||||||
|
});
|
||||||
return text.join("\n");
|
return text.join("\n");
|
||||||
};
|
};
|
||||||
program.option("-p, --parse <options>", "Specify parser options.", parse_js());
|
program.option("-p, --parse <options>", "Specify parser options.", parse_js());
|
||||||
@@ -36,6 +53,7 @@ program.option("-c, --compress [options]", "Enable compressor/specify compressor
|
|||||||
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
|
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
|
||||||
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
|
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
|
||||||
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js());
|
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js());
|
||||||
|
program.option("-O, --output-opts [options]", "Output options (beautify disabled).", parse_js());
|
||||||
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
||||||
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
||||||
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
||||||
@@ -53,13 +71,14 @@ program.option("--toplevel", "Compress and/or mangle variables in toplevel scope
|
|||||||
program.option("--verbose", "Print diagnostic messages.");
|
program.option("--verbose", "Print diagnostic messages.");
|
||||||
program.option("--warn", "Print warning messages.");
|
program.option("--warn", "Print warning messages.");
|
||||||
program.option("--wrap <name>", "Embed everything as a function with “exports” corresponding to “name” globally.");
|
program.option("--wrap <name>", "Embed everything as a function with “exports” corresponding to “name” globally.");
|
||||||
|
program.option("--reduce-test", "Reduce a standalone `console.log` based test case.");
|
||||||
program.arguments("[files...]").parseArgv(process.argv);
|
program.arguments("[files...]").parseArgv(process.argv);
|
||||||
if (program.configFile) {
|
if (program.configFile) {
|
||||||
options = JSON.parse(read_file(program.configFile));
|
options = JSON.parse(read_file(program.configFile));
|
||||||
if (options.mangle && options.mangle.properties && options.mangle.properties.regex) {
|
if (options.mangle && options.mangle.properties && options.mangle.properties.regex) {
|
||||||
options.mangle.properties.regex = UglifyJS.parse(options.mangle.properties.regex, {
|
options.mangle.properties.regex = UglifyJS.parse(options.mangle.properties.regex, {
|
||||||
expression: true
|
expression: true
|
||||||
}).getValue();
|
}).value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
||||||
@@ -93,6 +112,10 @@ if (program.beautify) {
|
|||||||
options.output.beautify = true;
|
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 (program.comments) {
|
||||||
if (typeof options.output != "object") options.output = {};
|
if (typeof options.output != "object") options.output = {};
|
||||||
options.output.comments = typeof program.comments == "string" ? program.comments : "some";
|
options.output.comments = typeof program.comments == "string" ? program.comments : "some";
|
||||||
@@ -210,7 +233,18 @@ function run() {
|
|||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
fatal(ex);
|
fatal(ex);
|
||||||
}
|
}
|
||||||
var result = UglifyJS.minify(files, options);
|
if (program.reduceTest) {
|
||||||
|
// load on demand - assumes dev tree checked out
|
||||||
|
var reduce_test = require("../test/reduce");
|
||||||
|
var testcase = files[0] || files[Object.keys(files)[0]];
|
||||||
|
var result = reduce_test(testcase, options, {
|
||||||
|
log: print_error,
|
||||||
|
verbose: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var result = UglifyJS.minify(files, options);
|
||||||
|
}
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
var ex = result.error;
|
var ex = result.error;
|
||||||
if (ex.name == "SyntaxError") {
|
if (ex.name == "SyntaxError") {
|
||||||
@@ -323,7 +357,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);
|
||||||
@@ -370,7 +404,7 @@ function parse_js(flag) {
|
|||||||
if (!(node instanceof UglifyJS.AST_Sequence)) throw node;
|
if (!(node instanceof UglifyJS.AST_Sequence)) throw node;
|
||||||
|
|
||||||
function to_string(value) {
|
function to_string(value) {
|
||||||
return value instanceof UglifyJS.AST_Constant ? value.getValue() : value.print_to_string({
|
return value instanceof UglifyJS.AST_Constant ? value.value : value.print_to_string({
|
||||||
quote_keys: true
|
quote_keys: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
20
lib/ast.js
20
lib/ast.js
@@ -169,10 +169,7 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
|
|||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
|
|
||||||
function walk_body(node, visitor) {
|
function walk_body(node, visitor) {
|
||||||
var body = node.body;
|
node.body.forEach(function(node) {
|
||||||
if (body instanceof AST_Statement) {
|
|
||||||
body._walk(visitor);
|
|
||||||
} else body.forEach(function(node) {
|
|
||||||
node._walk(visitor);
|
node._walk(visitor);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -351,7 +348,7 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
|||||||
filename: "wrap=" + JSON.stringify(name)
|
filename: "wrap=" + JSON.stringify(name)
|
||||||
}).transform(new TreeTransformer(function(node) {
|
}).transform(new TreeTransformer(function(node) {
|
||||||
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
||||||
return MAP.splice(body);
|
return List.splice(body);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
@@ -370,7 +367,7 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
|||||||
filename: "enclose=" + JSON.stringify(args_values)
|
filename: "enclose=" + JSON.stringify(args_values)
|
||||||
}).transform(new TreeTransformer(function(node) {
|
}).transform(new TreeTransformer(function(node) {
|
||||||
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
||||||
return MAP.splice(body);
|
return List.splice(body);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -618,7 +615,7 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
|
|||||||
getProperty: function() {
|
getProperty: function() {
|
||||||
var p = this.property;
|
var p = this.property;
|
||||||
if (p instanceof AST_Constant) {
|
if (p instanceof AST_Constant) {
|
||||||
return p.getValue();
|
return p.value;
|
||||||
}
|
}
|
||||||
if (p instanceof AST_UnaryPrefix
|
if (p instanceof AST_UnaryPrefix
|
||||||
&& p.operator == "void"
|
&& p.operator == "void"
|
||||||
@@ -824,9 +821,6 @@ var AST_This = DEFNODE("This", null, {
|
|||||||
|
|
||||||
var AST_Constant = DEFNODE("Constant", null, {
|
var AST_Constant = DEFNODE("Constant", null, {
|
||||||
$documentation: "Base class for all constants",
|
$documentation: "Base class for all constants",
|
||||||
getValue: function() {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var AST_String = DEFNODE("String", "value quote", {
|
var AST_String = DEFNODE("String", "value quote", {
|
||||||
@@ -967,11 +961,13 @@ TreeWalker.prototype = {
|
|||||||
in_boolean_context: function() {
|
in_boolean_context: function() {
|
||||||
var self = this.self();
|
var self = this.self();
|
||||||
for (var i = 0, p; p = this.parent(i); i++) {
|
for (var i = 0, p; p = this.parent(i); i++) {
|
||||||
if (p instanceof AST_SimpleStatement
|
if (p instanceof AST_Conditional && p.condition === self
|
||||||
|| p instanceof AST_Conditional && p.condition === self
|
|
||||||
|| p instanceof AST_DWLoop && p.condition === self
|
|| p instanceof AST_DWLoop && p.condition === self
|
||||||
|| p instanceof AST_For && p.condition === self
|
|| p instanceof AST_For && p.condition === self
|
||||||
|| p instanceof AST_If && p.condition === self
|
|| p instanceof AST_If && p.condition === self
|
||||||
|
|| p instanceof AST_Return && p.in_bool
|
||||||
|
|| p instanceof AST_Sequence && p.tail_node() !== self
|
||||||
|
|| p instanceof AST_SimpleStatement
|
||||||
|| p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
|
|| p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
3188
lib/compress.js
3188
lib/compress.js
File diff suppressed because it is too large
Load Diff
@@ -129,6 +129,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 +139,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 +152,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) {
|
options.sourceMap.orig[name] = parse_source_map(inlined_content);
|
||||||
source_maps[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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,19 +201,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;
|
||||||
@@ -252,7 +245,7 @@ function minify(files, options) {
|
|||||||
properties: 1e-3 * (timings.output - timings.properties),
|
properties: 1e-3 * (timings.output - timings.properties),
|
||||||
output: 1e-3 * (timings.end - timings.output),
|
output: 1e-3 * (timings.end - timings.output),
|
||||||
total: 1e-3 * (timings.end - timings.start)
|
total: 1e-3 * (timings.end - timings.start)
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
if (warnings.length) {
|
if (warnings.length) {
|
||||||
result.warnings = warnings;
|
result.warnings = warnings;
|
||||||
|
|||||||
@@ -403,7 +403,7 @@
|
|||||||
var def = M.definition();
|
var def = M.definition();
|
||||||
return {
|
return {
|
||||||
type: "Identifier",
|
type: "Identifier",
|
||||||
name: def ? def.mangled_name || def.name : M.name
|
name: def && def.mangled_name || M.name
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
211
lib/output.js
211
lib/output.js
@@ -43,8 +43,6 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/;
|
|
||||||
|
|
||||||
function is_some_comments(comment) {
|
function is_some_comments(comment) {
|
||||||
// multiline comment
|
// multiline comment
|
||||||
return comment.type == "comment2" && /@preserve|@license|@cc_on/i.test(comment.value);
|
return comment.type == "comment2" && /@preserve|@license|@cc_on/i.test(comment.value);
|
||||||
@@ -91,13 +89,11 @@ function OutputStream(options) {
|
|||||||
comment_filter = function(comment) {
|
comment_filter = function(comment) {
|
||||||
return comment.type != "comment5" && comments.test(comment.value);
|
return comment.type != "comment5" && comments.test(comment.value);
|
||||||
};
|
};
|
||||||
}
|
} else if (typeof comments === "function") {
|
||||||
else if (typeof comments === "function") {
|
|
||||||
comment_filter = function(comment) {
|
comment_filter = function(comment) {
|
||||||
return comment.type != "comment5" && comments(this, comment);
|
return comment.type != "comment5" && comments(this, comment);
|
||||||
};
|
};
|
||||||
}
|
} else if (comments === "some") {
|
||||||
else if (comments === "some") {
|
|
||||||
comment_filter = is_some_comments;
|
comment_filter = is_some_comments;
|
||||||
} else { // NOTE includes "all" option
|
} else { // NOTE includes "all" option
|
||||||
comment_filter = return_true;
|
comment_filter = return_true;
|
||||||
@@ -123,15 +119,20 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
} : function(str) {
|
} : function(str) {
|
||||||
var s = "";
|
var s = "";
|
||||||
for (var i = 0; i < str.length; i++) {
|
for (var i = 0, j = 0; i < str.length; i++) {
|
||||||
if (is_surrogate_pair_head(str[i]) && !is_surrogate_pair_tail(str[i + 1])
|
var code = str.charCodeAt(i);
|
||||||
|| is_surrogate_pair_tail(str[i]) && !is_surrogate_pair_head(str[i - 1])) {
|
if (is_surrogate_pair_head(code)) {
|
||||||
s += "\\u" + str.charCodeAt(i).toString(16);
|
if (is_surrogate_pair_tail(str.charCodeAt(i + 1))) {
|
||||||
} else {
|
i++;
|
||||||
s += str[i];
|
continue;
|
||||||
|
}
|
||||||
|
} else if (!is_surrogate_pair_tail(code)) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
s += str.slice(j, i) + "\\u" + code.toString(16);
|
||||||
|
j = i + 1;
|
||||||
}
|
}
|
||||||
return s;
|
return j == 0 ? str : s + str.slice(j);
|
||||||
};
|
};
|
||||||
|
|
||||||
function make_string(str, quote) {
|
function make_string(str, quote) {
|
||||||
@@ -271,7 +272,7 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
newline_insert = -1;
|
newline_insert = -1;
|
||||||
var prev = last.charAt(last.length - 1);
|
var prev = last.slice(-1);
|
||||||
if (might_need_semicolon) {
|
if (might_need_semicolon) {
|
||||||
might_need_semicolon = false;
|
might_need_semicolon = false;
|
||||||
|
|
||||||
@@ -300,16 +301,16 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (might_need_space) {
|
if (might_need_space) {
|
||||||
if ((is_identifier_char(prev)
|
if (is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\")
|
||||||
&& (is_identifier_char(ch) || ch == "\\"))
|
|
||||||
|| (ch == "/" && ch == prev)
|
|| (ch == "/" && ch == prev)
|
||||||
|| ((ch == "+" || ch == "-") && ch == last))
|
|| ((ch == "+" || ch == "-") && ch == last)
|
||||||
{
|
|| str == "--" && last == "!"
|
||||||
|
|| last == "--" && ch == ">") {
|
||||||
OUTPUT += " ";
|
OUTPUT += " ";
|
||||||
current_col++;
|
current_col++;
|
||||||
current_pos++;
|
current_pos++;
|
||||||
}
|
}
|
||||||
might_need_space = false;
|
if (prev != "<" || str != "!") might_need_space = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapping_token) {
|
if (mapping_token) {
|
||||||
@@ -324,7 +325,7 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OUTPUT += str;
|
OUTPUT += str;
|
||||||
has_parens = str[str.length - 1] == "(";
|
has_parens = str.slice(-1) == "(";
|
||||||
current_pos += str.length;
|
current_pos += str.length;
|
||||||
var a = str.split(/\r?\n/), n = a.length - 1;
|
var a = str.split(/\r?\n/), n = a.length - 1;
|
||||||
current_line += n;
|
current_line += n;
|
||||||
@@ -380,7 +381,7 @@ function OutputStream(options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function force_semicolon() {
|
function force_semicolon() {
|
||||||
might_need_semicolon = false;
|
if (might_need_semicolon) print(";");
|
||||||
print(";");
|
print(";");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,7 +453,7 @@ function OutputStream(options) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
var scan = node instanceof AST_Exit && node.value;
|
var scan = node instanceof AST_Exit && node.value;
|
||||||
var comments = dump(node);
|
var comments = dump(node);
|
||||||
if (!comments) return;
|
if (!comments) comments = [];
|
||||||
|
|
||||||
if (scan) {
|
if (scan) {
|
||||||
var tw = new TreeWalker(function(node) {
|
var tw = new TreeWalker(function(node) {
|
||||||
@@ -587,17 +588,7 @@ function OutputStream(options) {
|
|||||||
force_semicolon : force_semicolon,
|
force_semicolon : force_semicolon,
|
||||||
to_utf8 : to_utf8,
|
to_utf8 : to_utf8,
|
||||||
print_name : function(name) { print(make_name(name)) },
|
print_name : function(name) { print(make_name(name)) },
|
||||||
print_string : function(str, quote, escape_directive) {
|
print_string : function(str, quote) { print(encode_string(str, quote)) },
|
||||||
var encoded = encode_string(str, quote);
|
|
||||||
if (escape_directive === true && encoded.indexOf("\\") === -1) {
|
|
||||||
// Insert semicolons to break directive prologue
|
|
||||||
if (!EXPECT_DIRECTIVE.test(OUTPUT)) {
|
|
||||||
force_semicolon();
|
|
||||||
}
|
|
||||||
force_semicolon();
|
|
||||||
}
|
|
||||||
print(encoded);
|
|
||||||
},
|
|
||||||
next_indent : next_indent,
|
next_indent : next_indent,
|
||||||
with_indent : with_indent,
|
with_indent : with_indent,
|
||||||
with_block : with_block,
|
with_block : with_block,
|
||||||
@@ -635,18 +626,10 @@ function OutputStream(options) {
|
|||||||
nodetype.DEFMETHOD("_codegen", generator);
|
nodetype.DEFMETHOD("_codegen", generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
var in_directive = false;
|
var use_asm = false;
|
||||||
var active_scope = null;
|
|
||||||
var use_asm = null;
|
|
||||||
|
|
||||||
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, generator = self._codegen;
|
||||||
if (self instanceof AST_Scope) {
|
|
||||||
active_scope = self;
|
|
||||||
}
|
|
||||||
else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") {
|
|
||||||
use_asm = active_scope;
|
|
||||||
}
|
|
||||||
function doit() {
|
function doit() {
|
||||||
stream.prepend_comments(self);
|
stream.prepend_comments(self);
|
||||||
self.add_source_map(stream);
|
self.add_source_map(stream);
|
||||||
@@ -660,9 +643,6 @@ function OutputStream(options) {
|
|||||||
doit();
|
doit();
|
||||||
}
|
}
|
||||||
stream.pop_node();
|
stream.pop_node();
|
||||||
if (self === use_asm) {
|
|
||||||
use_asm = null;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
|
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
|
||||||
|
|
||||||
@@ -714,16 +694,23 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
PARENS(AST_Sequence, function(output) {
|
PARENS(AST_Sequence, function(output) {
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
|
// (foo, bar)() or foo(1, (2, 3), 4)
|
||||||
|| p instanceof AST_Unary // !(foo, bar, baz)
|
return p instanceof AST_Call
|
||||||
|| p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
|
// !(foo, bar, baz)
|
||||||
|| p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4
|
|| p instanceof AST_Unary
|
||||||
|| p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
|
// 1 + (2, 3) + 4 ==> 8
|
||||||
|| p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
|
|| p instanceof AST_Binary
|
||||||
|| p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2
|
// var a = (1, 2), b = a + a; ==> b == 4
|
||||||
|| p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
|
|| p instanceof AST_VarDef
|
||||||
* ==> 20 (side effect, set a := 10 and b := 20) */
|
// (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)
|
||||||
|
// ==> 20 (side effect, set a := 10 and b := 20)
|
||||||
|
|| p instanceof AST_Conditional;
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS(AST_Binary, function(output) {
|
PARENS(AST_Binary, function(output) {
|
||||||
@@ -795,7 +782,9 @@ function OutputStream(options) {
|
|||||||
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.getValue();
|
var value = this.value;
|
||||||
|
// https://github.com/mishoo/UglifyJS2/issues/115
|
||||||
|
// https://github.com/mishoo/UglifyJS2/pull/1009
|
||||||
if (value < 0 || /^0/.test(make_num(value))) {
|
if (value < 0 || /^0/.test(make_num(value))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -824,7 +813,18 @@ function OutputStream(options) {
|
|||||||
/* -----[ PRINTERS ]----- */
|
/* -----[ PRINTERS ]----- */
|
||||||
|
|
||||||
DEFPRINT(AST_Directive, function(self, output) {
|
DEFPRINT(AST_Directive, function(self, output) {
|
||||||
output.print_string(self.value, self.quote);
|
var quote = self.quote;
|
||||||
|
var value = self.value;
|
||||||
|
switch (output.option("quote_style")) {
|
||||||
|
case 0:
|
||||||
|
case 2:
|
||||||
|
if (value.indexOf('"') == -1) quote = '"';
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (value.indexOf("'") == -1) quote = "'";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
output.print(quote + value + quote);
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Debugger, function(self, output) {
|
DEFPRINT(AST_Debugger, function(self, output) {
|
||||||
@@ -836,30 +836,27 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
function display_body(body, is_toplevel, output, allow_directives) {
|
function display_body(body, is_toplevel, output, allow_directives) {
|
||||||
var last = body.length - 1;
|
var last = body.length - 1;
|
||||||
in_directive = allow_directives;
|
var in_directive = allow_directives;
|
||||||
|
var was_asm = use_asm;
|
||||||
body.forEach(function(stmt, i) {
|
body.forEach(function(stmt, i) {
|
||||||
if (in_directive === true && !(stmt instanceof AST_Directive ||
|
if (in_directive) {
|
||||||
stmt instanceof AST_EmptyStatement ||
|
if (stmt instanceof AST_Directive) {
|
||||||
(stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String)
|
if (stmt.value == "use asm") use_asm = true;
|
||||||
)) {
|
} else if (!(stmt instanceof AST_EmptyStatement)) {
|
||||||
in_directive = false;
|
if (stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String) {
|
||||||
}
|
output.force_semicolon();
|
||||||
if (!(stmt instanceof AST_EmptyStatement)) {
|
}
|
||||||
output.indent();
|
in_directive = false;
|
||||||
stmt.print(output);
|
|
||||||
if (!(i == last && is_toplevel)) {
|
|
||||||
output.newline();
|
|
||||||
if (is_toplevel) output.newline();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (in_directive === true &&
|
if (stmt instanceof AST_EmptyStatement) return;
|
||||||
stmt instanceof AST_SimpleStatement &&
|
output.indent();
|
||||||
stmt.body instanceof AST_String
|
stmt.print(output);
|
||||||
) {
|
if (i == last && is_toplevel) return;
|
||||||
in_directive = false;
|
output.newline();
|
||||||
}
|
if (is_toplevel) output.newline();
|
||||||
});
|
});
|
||||||
in_directive = false;
|
use_asm = was_asm;
|
||||||
}
|
}
|
||||||
|
|
||||||
AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
|
AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
|
||||||
@@ -1043,11 +1040,9 @@ function OutputStream(options) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
b = b.alternative;
|
b = b.alternative;
|
||||||
}
|
} else if (b instanceof AST_StatementWithBody) {
|
||||||
else if (b instanceof AST_StatementWithBody) {
|
|
||||||
b = b.body;
|
b = b.body;
|
||||||
}
|
} else break;
|
||||||
else break;
|
|
||||||
}
|
}
|
||||||
force_statement(self.body, output);
|
force_statement(self.body, output);
|
||||||
}
|
}
|
||||||
@@ -1219,7 +1214,7 @@ function OutputStream(options) {
|
|||||||
output.print_string(prop);
|
output.print_string(prop);
|
||||||
output.print("]");
|
output.print("]");
|
||||||
} else {
|
} else {
|
||||||
if (expr instanceof AST_Number && expr.getValue() >= 0) {
|
if (expr instanceof AST_Number && expr.value >= 0) {
|
||||||
if (!/[xa-f.)]/i.test(output.last())) {
|
if (!/[xa-f.)]/i.test(output.last())) {
|
||||||
output.print(".");
|
output.print(".");
|
||||||
}
|
}
|
||||||
@@ -1252,29 +1247,10 @@ function OutputStream(options) {
|
|||||||
output.print(self.operator);
|
output.print(self.operator);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Binary, function(self, output) {
|
DEFPRINT(AST_Binary, function(self, output) {
|
||||||
var op = self.operator;
|
|
||||||
self.left.print(output);
|
self.left.print(output);
|
||||||
if (op[0] == ">" /* ">>" ">>>" ">" ">=" */
|
output.space();
|
||||||
&& self.left instanceof AST_UnaryPostfix
|
output.print(self.operator);
|
||||||
&& self.left.operator == "--") {
|
output.space();
|
||||||
// space is mandatory to avoid outputting -->
|
|
||||||
output.print(" ");
|
|
||||||
} else {
|
|
||||||
// the space is optional depending on "beautify"
|
|
||||||
output.space();
|
|
||||||
}
|
|
||||||
output.print(op);
|
|
||||||
if ((op == "<" || op == "<<")
|
|
||||||
&& self.right instanceof AST_UnaryPrefix
|
|
||||||
&& self.right.operator == "!"
|
|
||||||
&& self.right.expression instanceof AST_UnaryPrefix
|
|
||||||
&& self.right.expression.operator == "--") {
|
|
||||||
// space is mandatory to avoid outputting <!--
|
|
||||||
output.print(" ");
|
|
||||||
} else {
|
|
||||||
// the space is optional depending on "beautify"
|
|
||||||
output.space();
|
|
||||||
}
|
|
||||||
self.right.print(output);
|
self.right.print(output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Conditional, function(self, output) {
|
DEFPRINT(AST_Conditional, function(self, output) {
|
||||||
@@ -1355,34 +1331,41 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
DEFPRINT(AST_Symbol, function(self, output) {
|
DEFPRINT(AST_Symbol, function(self, output) {
|
||||||
var def = self.definition();
|
var def = self.definition();
|
||||||
output.print_name(def ? def.mangled_name || def.name : self.name);
|
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(self, output) {
|
||||||
output.print("this");
|
output.print("this");
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Constant, function(self, output) {
|
DEFPRINT(AST_Constant, function(self, output) {
|
||||||
output.print(self.getValue());
|
output.print(self.value);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_String, function(self, output) {
|
DEFPRINT(AST_String, function(self, output) {
|
||||||
output.print_string(self.getValue(), self.quote, in_directive);
|
output.print_string(self.value, self.quote);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Number, function(self, output) {
|
DEFPRINT(AST_Number, function(self, output) {
|
||||||
if (use_asm && self.start && self.start.raw != null) {
|
if (use_asm && self.start && self.start.raw != null) {
|
||||||
output.print(self.start.raw);
|
output.print(self.start.raw);
|
||||||
} else {
|
} else {
|
||||||
output.print(make_num(self.getValue()));
|
output.print(make_num(self.value));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
DEFPRINT(AST_RegExp, function(self, output) {
|
DEFPRINT(AST_RegExp, function(self, output) {
|
||||||
var regexp = self.getValue();
|
var regexp = self.value;
|
||||||
var str = regexp.toString();
|
var str = regexp.toString();
|
||||||
|
var end = str.lastIndexOf("/");
|
||||||
if (regexp.raw_source) {
|
if (regexp.raw_source) {
|
||||||
str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
|
str = "/" + regexp.raw_source + str.slice(end);
|
||||||
|
} else if (end == 1) {
|
||||||
|
str = "/(?:)" + str.slice(end);
|
||||||
|
} else if (str.indexOf("/", 1) < end) {
|
||||||
|
str = "/" + str.slice(1, end).replace(/\\\\|[^/]?\//g, function(match) {
|
||||||
|
return match[0] == "\\" ? match : match.slice(0, -1) + "\\/";
|
||||||
|
}) + str.slice(end);
|
||||||
}
|
}
|
||||||
output.print(output.to_utf8(str).replace(/\\(?:\0(?![0-9])|[^\0])/g, function(seq) {
|
output.print(output.to_utf8(str).replace(/\\(?:\0(?![0-9])|[^\0])/g, function(match) {
|
||||||
switch (seq[1]) {
|
switch (match[1]) {
|
||||||
case "\n": return "\\n";
|
case "\n": return "\\n";
|
||||||
case "\r": return "\\r";
|
case "\r": return "\\r";
|
||||||
case "\t": return "\t";
|
case "\t": return "\t";
|
||||||
@@ -1392,7 +1375,7 @@ function OutputStream(options) {
|
|||||||
case "\x0B": return "\v";
|
case "\x0B": return "\v";
|
||||||
case "\u2028": return "\\u2028";
|
case "\u2028": return "\\u2028";
|
||||||
case "\u2029": return "\\u2029";
|
case "\u2029": return "\\u2029";
|
||||||
default: return seq;
|
default: return match;
|
||||||
}
|
}
|
||||||
}).replace(/[\n\r\u2028\u2029]/g, function(c) {
|
}).replace(/[\n\r\u2028\u2029]/g, function(c) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@@ -1487,7 +1470,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,
|
||||||
@@ -1499,7 +1481,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,
|
||||||
|
|||||||
138
lib/parse.js
138
lib/parse.js
@@ -133,14 +133,10 @@ function is_letter(code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function is_surrogate_pair_head(code) {
|
function is_surrogate_pair_head(code) {
|
||||||
if (typeof code == "string")
|
|
||||||
code = code.charCodeAt(0);
|
|
||||||
return code >= 0xd800 && code <= 0xdbff;
|
return code >= 0xd800 && code <= 0xdbff;
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_surrogate_pair_tail(code) {
|
function is_surrogate_pair_tail(code) {
|
||||||
if (typeof code == "string")
|
|
||||||
code = code.charCodeAt(0);
|
|
||||||
return code >= 0xdc00 && code <= 0xdfff;
|
return code >= 0xdc00 && code <= 0xdfff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,6 +230,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
directives : {},
|
directives : {},
|
||||||
directive_stack : []
|
directive_stack : []
|
||||||
};
|
};
|
||||||
|
var prev_was_dot = false;
|
||||||
|
|
||||||
function peek() {
|
function peek() {
|
||||||
return S.text.charAt(S.pos);
|
return S.text.charAt(S.pos);
|
||||||
@@ -244,16 +241,16 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
if (signal_eof && !ch)
|
if (signal_eof && !ch)
|
||||||
throw EX_EOF;
|
throw EX_EOF;
|
||||||
if (NEWLINE_CHARS[ch]) {
|
if (NEWLINE_CHARS[ch]) {
|
||||||
S.newline_before = S.newline_before || !in_string;
|
|
||||||
++S.line;
|
|
||||||
S.col = 0;
|
S.col = 0;
|
||||||
if (!in_string && ch == "\r" && peek() == "\n") {
|
S.line++;
|
||||||
// treat a \r\n sequence as a single \n
|
if (!in_string) S.newline_before = true;
|
||||||
++S.pos;
|
if (ch == "\r" && peek() == "\n") {
|
||||||
|
// treat `\r\n` as `\n`
|
||||||
|
S.pos++;
|
||||||
ch = "\n";
|
ch = "\n";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
++S.col;
|
S.col++;
|
||||||
}
|
}
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
@@ -286,16 +283,12 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
S.tokpos = S.pos;
|
S.tokpos = S.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
var prev_was_dot = false;
|
|
||||||
function token(type, value, is_comment) {
|
function token(type, value, is_comment) {
|
||||||
S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) ||
|
S.regex_allowed = type == "operator" && !UNARY_POSTFIX[value]
|
||||||
(type == "keyword" && KEYWORDS_BEFORE_EXPRESSION[value]) ||
|
|| type == "keyword" && KEYWORDS_BEFORE_EXPRESSION[value]
|
||||||
(type == "punc" && PUNC_BEFORE_EXPRESSION[value]));
|
|| type == "punc" && PUNC_BEFORE_EXPRESSION[value];
|
||||||
if (type == "punc" && value == ".") {
|
if (type == "punc" && value == ".") prev_was_dot = true;
|
||||||
prev_was_dot = true;
|
else if (!is_comment) prev_was_dot = false;
|
||||||
} else if (!is_comment) {
|
|
||||||
prev_was_dot = false;
|
|
||||||
}
|
|
||||||
var ret = {
|
var ret = {
|
||||||
type : type,
|
type : type,
|
||||||
value : value,
|
value : value,
|
||||||
@@ -358,11 +351,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
parse_error("Legacy octal literals are not allowed in strict mode");
|
parse_error("Legacy octal literals are not allowed in strict mode");
|
||||||
}
|
}
|
||||||
var valid = parse_js_number(num);
|
var valid = parse_js_number(num);
|
||||||
if (!isNaN(valid)) {
|
if (!isNaN(valid)) return token("num", valid);
|
||||||
return token("num", valid);
|
parse_error("Invalid syntax: " + num);
|
||||||
} else {
|
|
||||||
parse_error("Invalid syntax: " + num);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function read_escaped_char(in_string) {
|
function read_escaped_char(in_string) {
|
||||||
@@ -463,8 +453,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
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();
|
||||||
else break;
|
else break;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
|
if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
|
||||||
ch = read_escaped_char();
|
ch = read_escaped_char();
|
||||||
if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
|
if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
|
||||||
@@ -538,9 +527,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
|
|
||||||
function handle_dot() {
|
function handle_dot() {
|
||||||
next();
|
next();
|
||||||
return is_digit(peek().charCodeAt(0))
|
return is_digit(peek().charCodeAt(0)) ? read_num(".") : token("punc", ".");
|
||||||
? read_num(".")
|
|
||||||
: token("punc", ".");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function read_word() {
|
function read_word() {
|
||||||
@@ -592,11 +579,10 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
switch (code) {
|
switch (code) {
|
||||||
case 34: case 39: return read_string(ch);
|
case 34: case 39: return read_string(ch);
|
||||||
case 46: return handle_dot();
|
case 46: return handle_dot();
|
||||||
case 47: {
|
case 47:
|
||||||
var tok = handle_slash();
|
var tok = handle_slash();
|
||||||
if (tok === next_token) continue;
|
if (tok === next_token) continue;
|
||||||
return tok;
|
return tok;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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());
|
||||||
@@ -614,12 +600,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
|
|
||||||
next_token.add_directive = function(directive) {
|
next_token.add_directive = function(directive) {
|
||||||
S.directive_stack[S.directive_stack.length - 1].push(directive);
|
S.directive_stack[S.directive_stack.length - 1].push(directive);
|
||||||
|
if (S.directives[directive]) S.directives[directive]++;
|
||||||
if (S.directives[directive] === undefined) {
|
else S.directives[directive] = 1;
|
||||||
S.directives[directive] = 1;
|
|
||||||
} else {
|
|
||||||
S.directives[directive]++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next_token.push_directives_stack = function() {
|
next_token.push_directives_stack = function() {
|
||||||
@@ -627,13 +609,10 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
next_token.pop_directives_stack = function() {
|
next_token.pop_directives_stack = function() {
|
||||||
var directives = S.directive_stack[S.directive_stack.length - 1];
|
var directives = S.directive_stack.pop();
|
||||||
|
for (var i = directives.length; --i >= 0;) {
|
||||||
for (var i = 0; i < directives.length; i++) {
|
|
||||||
S.directives[directives[i]]--;
|
S.directives[directives[i]]--;
|
||||||
}
|
}
|
||||||
|
|
||||||
S.directive_stack.pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next_token.has_directive = function(directive) {
|
next_token.has_directive = function(directive) {
|
||||||
@@ -645,27 +624,17 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
|
|
||||||
/* -----[ Parser (constants) ]----- */
|
/* -----[ Parser (constants) ]----- */
|
||||||
|
|
||||||
var UNARY_PREFIX = makePredicate([
|
var UNARY_PREFIX = makePredicate("typeof void delete -- ++ ! ~ - +");
|
||||||
"typeof",
|
|
||||||
"void",
|
|
||||||
"delete",
|
|
||||||
"--",
|
|
||||||
"++",
|
|
||||||
"!",
|
|
||||||
"~",
|
|
||||||
"-",
|
|
||||||
"+"
|
|
||||||
]);
|
|
||||||
|
|
||||||
var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
|
var UNARY_POSTFIX = makePredicate("-- ++");
|
||||||
|
|
||||||
var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
|
var ASSIGNMENT = makePredicate("= += -= /= *= %= >>= <<= >>>= |= ^= &=");
|
||||||
|
|
||||||
var PRECEDENCE = function(a, ret) {
|
var PRECEDENCE = function(a, ret) {
|
||||||
for (var i = 0; i < a.length; ++i) {
|
for (var i = 0; i < a.length;) {
|
||||||
var b = a[i];
|
var b = a[i++];
|
||||||
for (var j = 0; j < b.length; ++j) {
|
for (var j = 0; j < b.length; j++) {
|
||||||
ret[b[j]] = i + 1;
|
ret[b[j]] = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -682,7 +651,7 @@ var PRECEDENCE = function(a, ret) {
|
|||||||
["*", "/", "%"]
|
["*", "/", "%"]
|
||||||
], {});
|
], {});
|
||||||
|
|
||||||
var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "string", "regexp", "name" ]);
|
var ATOMIC_START_TOKEN = makePredicate("atom num string regexp name");
|
||||||
|
|
||||||
/* -----[ Parser ]----- */
|
/* -----[ Parser ]----- */
|
||||||
|
|
||||||
@@ -698,10 +667,9 @@ function parse($TEXT, options) {
|
|||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
var S = {
|
var S = {
|
||||||
input : (typeof $TEXT == "string"
|
input : typeof $TEXT == "string"
|
||||||
? tokenizer($TEXT, options.filename,
|
? tokenizer($TEXT, options.filename, options.html5_comments, options.shebang)
|
||||||
options.html5_comments, options.shebang)
|
: $TEXT,
|
||||||
: $TEXT),
|
|
||||||
token : null,
|
token : null,
|
||||||
prev : null,
|
prev : null,
|
||||||
peeked : null,
|
peeked : null,
|
||||||
@@ -757,15 +725,12 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function unexpected(token) {
|
function unexpected(token) {
|
||||||
if (token == null)
|
if (token == null) token = S.token;
|
||||||
token = S.token;
|
|
||||||
token_error(token, "Unexpected token: " + token_to_string(token.type, token.value));
|
token_error(token, "Unexpected token: " + token_to_string(token.type, token.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
function expect_token(type, val) {
|
function expect_token(type, val) {
|
||||||
if (is(type, val)) {
|
if (is(type, val)) return next();
|
||||||
return next();
|
|
||||||
}
|
|
||||||
token_error(S.token, "Unexpected token: " + token_to_string(S.token.type, S.token.value) + ", expected: " + token_to_string(type, val));
|
token_error(S.token, "Unexpected token: " + token_to_string(S.token.type, S.token.value) + ", expected: " + token_to_string(type, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -818,20 +783,19 @@ function parse($TEXT, options) {
|
|||||||
handle_regexp();
|
handle_regexp();
|
||||||
switch (S.token.type) {
|
switch (S.token.type) {
|
||||||
case "string":
|
case "string":
|
||||||
if (S.in_directives) {
|
var dir = S.in_directives;
|
||||||
var token = peek();
|
var body = expression(true);
|
||||||
if (S.token.raw.indexOf("\\") == -1
|
if (dir) {
|
||||||
&& (is_token(token, "punc", ";")
|
if (body instanceof AST_String) {
|
||||||
|| is_token(token, "punc", "}")
|
var value = body.start.raw.slice(1, -1);
|
||||||
|| has_newline_before(token)
|
S.input.add_directive(value);
|
||||||
|| is_token(token, "eof"))) {
|
body.value = value;
|
||||||
S.input.add_directive(S.token.value);
|
|
||||||
} else {
|
} else {
|
||||||
S.in_directives = false;
|
S.in_directives = dir = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var dir = S.in_directives, stat = simple_statement();
|
semicolon();
|
||||||
return dir ? new AST_Directive(stat.body) : stat;
|
return dir ? new AST_Directive(body) : new AST_SimpleStatement({ body: body });
|
||||||
case "num":
|
case "num":
|
||||||
case "regexp":
|
case "regexp":
|
||||||
case "operator":
|
case "operator":
|
||||||
@@ -996,8 +960,10 @@ function parse($TEXT, options) {
|
|||||||
return new AST_LabeledStatement({ body: stat, label: label });
|
return new AST_LabeledStatement({ body: stat, label: label });
|
||||||
}
|
}
|
||||||
|
|
||||||
function simple_statement(tmp) {
|
function simple_statement() {
|
||||||
return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) });
|
var body = expression(true);
|
||||||
|
semicolon();
|
||||||
|
return new AST_SimpleStatement({ body: body });
|
||||||
}
|
}
|
||||||
|
|
||||||
function break_cont(type) {
|
function break_cont(type) {
|
||||||
@@ -1284,6 +1250,7 @@ function parse($TEXT, options) {
|
|||||||
var ex = expression(true);
|
var ex = expression(true);
|
||||||
var len = start.comments_before.length;
|
var len = start.comments_before.length;
|
||||||
[].unshift.apply(ex.start.comments_before, start.comments_before);
|
[].unshift.apply(ex.start.comments_before, start.comments_before);
|
||||||
|
start.comments_before.length = 0;
|
||||||
start.comments_before = ex.start.comments_before;
|
start.comments_before = ex.start.comments_before;
|
||||||
start.comments_before_length = len;
|
start.comments_before_length = len;
|
||||||
if (len == 0 && start.comments_before.length > 0) {
|
if (len == 0 && start.comments_before.length > 0) {
|
||||||
@@ -1299,6 +1266,7 @@ function parse($TEXT, options) {
|
|||||||
var end = prev();
|
var end = prev();
|
||||||
end.comments_before = ex.end.comments_before;
|
end.comments_before = ex.end.comments_before;
|
||||||
[].push.apply(ex.end.comments_after, end.comments_after);
|
[].push.apply(ex.end.comments_after, end.comments_after);
|
||||||
|
end.comments_after.length = 0;
|
||||||
end.comments_after = ex.end.comments_after;
|
end.comments_after = ex.end.comments_after;
|
||||||
ex.end = end;
|
ex.end = end;
|
||||||
if (ex instanceof AST_Call) mark_pure(ex);
|
if (ex instanceof AST_Call) mark_pure(ex);
|
||||||
|
|||||||
122
lib/scope.js
122
lib/scope.js
@@ -43,22 +43,21 @@
|
|||||||
|
|
||||||
"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++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolDef.next_id = 1;
|
|
||||||
|
|
||||||
SymbolDef.prototype = {
|
SymbolDef.prototype = {
|
||||||
unmangleable: function(options) {
|
unmangleable: function(options) {
|
||||||
return this.global && !options.toplevel
|
return this.global && !options.toplevel
|
||||||
@@ -150,6 +149,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
scope.def_variable(node).defun = defun;
|
scope.def_variable(node).defun = defun;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
self.next_def_id = 0;
|
||||||
self.walk(tw);
|
self.walk(tw);
|
||||||
|
|
||||||
// pass 2: find back references and eval
|
// pass 2: find back references and eval
|
||||||
@@ -161,17 +161,22 @@ 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 (sym.scope instanceof AST_Lambda && name == "arguments") {
|
||||||
sym.scope.uses_arguments = true;
|
sym.scope.uses_arguments = true;
|
||||||
}
|
}
|
||||||
|
if (name == "eval") {
|
||||||
|
var parent = tw.parent();
|
||||||
|
if (parent.TYPE == "Call" && parent.expression === node) {
|
||||||
|
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
|
||||||
|
s.uses_eval = true;
|
||||||
|
}
|
||||||
|
} else if (sym.undeclared) {
|
||||||
|
self.uses_eval = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
node.thedef = sym;
|
node.thedef = sym;
|
||||||
node.reference(options);
|
node.reference(options);
|
||||||
return true;
|
return true;
|
||||||
@@ -191,13 +196,21 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
// pass 3: fix up any scoping issue with IE8
|
// pass 3: fix up any scoping issue with IE8
|
||||||
if (options.ie8) self.walk(new TreeWalker(function(node) {
|
if (options.ie8) self.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_SymbolCatch) {
|
if (node instanceof AST_SymbolCatch) {
|
||||||
redefine(node, node.thedef.defun);
|
var scope = node.thedef.defun;
|
||||||
|
if (scope.name instanceof AST_SymbolLambda && scope.name.name == node.name) {
|
||||||
|
scope = scope.parent_scope.resolve();
|
||||||
|
}
|
||||||
|
redefine(node, scope);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolLambda) {
|
if (node instanceof AST_SymbolLambda) {
|
||||||
var def = node.thedef;
|
var def = node.thedef;
|
||||||
redefine(node, node.scope.parent_scope);
|
redefine(node, node.scope.parent_scope.resolve());
|
||||||
node.thedef.init = def.init;
|
if (typeof node.thedef.init !== "undefined") {
|
||||||
|
node.thedef.init = false;
|
||||||
|
} else if (def.init) {
|
||||||
|
node.thedef.init = def.init;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@@ -205,20 +218,39 @@ 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;
|
||||||
var new_def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
|
var new_def = scope.find_variable(name);
|
||||||
|
if (new_def) {
|
||||||
|
var redef;
|
||||||
|
while (redef = new_def.redefined()) new_def = redef;
|
||||||
|
} else {
|
||||||
|
new_def = self.globals.get(name);
|
||||||
|
}
|
||||||
|
if (new_def) {
|
||||||
|
new_def.orig.push(node);
|
||||||
|
} else {
|
||||||
|
new_def = scope.def_variable(node);
|
||||||
|
}
|
||||||
old_def.orig.concat(old_def.references).forEach(function(node) {
|
old_def.orig.concat(old_def.references).forEach(function(node) {
|
||||||
node.thedef = new_def;
|
node.thedef = new_def;
|
||||||
node.reference(options);
|
node.reference(options);
|
||||||
});
|
});
|
||||||
|
if (old_def.lambda) new_def.lambda = true;
|
||||||
|
if (new_def.undeclared) self.variables.set(name, new_def);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AST_Scope.DEFMETHOD("make_def", function(orig, init) {
|
||||||
|
var top = this;
|
||||||
|
while (top.parent_scope) top = top.parent_scope;
|
||||||
|
return new SymbolDef(++top.next_def_id, this, orig, init);
|
||||||
|
});
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("def_global", function(node) {
|
AST_Toplevel.DEFMETHOD("def_global", function(node) {
|
||||||
var globals = this.globals, name = node.name;
|
var globals = this.globals, name = node.name;
|
||||||
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);
|
||||||
@@ -281,11 +313,9 @@ AST_Scope.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 && (def.scope !== symbol.scope || def.init instanceof AST_Function)) {
|
if (def.init instanceof AST_Function) def.init = init;
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -413,7 +443,14 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
if (options.cache && node instanceof AST_Toplevel) {
|
if (options.cache && node instanceof AST_Toplevel) {
|
||||||
node.globals.each(mangle);
|
node.globals.each(mangle);
|
||||||
}
|
}
|
||||||
node.variables.each(mangle);
|
if (node instanceof AST_Defun && tw.has_directive("use asm")) {
|
||||||
|
var sym = new AST_SymbolRef(node.name);
|
||||||
|
sym.scope = node;
|
||||||
|
sym.reference(options);
|
||||||
|
}
|
||||||
|
node.variables.each(function(def) {
|
||||||
|
if (!defer_redef(def)) mangle(def);
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Label) {
|
if (node instanceof AST_Label) {
|
||||||
@@ -426,22 +463,11 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
}
|
}
|
||||||
if (!options.ie8 && node instanceof AST_Catch) {
|
if (!options.ie8 && node instanceof AST_Catch) {
|
||||||
var def = node.argname.definition();
|
var def = node.argname.definition();
|
||||||
var redef = def.redefined();
|
var redef = defer_redef(def, node.argname);
|
||||||
if (redef) {
|
|
||||||
redefined.push(def);
|
|
||||||
reference(node.argname);
|
|
||||||
def.references.forEach(reference);
|
|
||||||
}
|
|
||||||
descend();
|
descend();
|
||||||
if (!redef) mangle(def);
|
if (!redef) mangle(def);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function reference(sym) {
|
|
||||||
sym.thedef = redef;
|
|
||||||
sym.reference(options);
|
|
||||||
sym.thedef = def;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
this.walk(tw);
|
this.walk(tw);
|
||||||
redefined.forEach(mangle);
|
redefined.forEach(mangle);
|
||||||
@@ -450,6 +476,21 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
if (options.reserved.has[def.name]) return;
|
if (options.reserved.has[def.name]) return;
|
||||||
def.mangle(options);
|
def.mangle(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function defer_redef(def, node) {
|
||||||
|
var redef = def.redefined();
|
||||||
|
if (!redef) return false;
|
||||||
|
redefined.push(def);
|
||||||
|
def.references.forEach(reference);
|
||||||
|
if (node) reference(node);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
function reference(sym) {
|
||||||
|
sym.thedef = redef;
|
||||||
|
sym.reference(options);
|
||||||
|
sym.thedef = def;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
|
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
|
||||||
@@ -499,13 +540,14 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
|||||||
if (def.global && options.cache) return;
|
if (def.global && options.cache) return;
|
||||||
if (def.unmangleable(options)) return;
|
if (def.unmangleable(options)) return;
|
||||||
if (options.reserved.has[def.name]) return;
|
if (options.reserved.has[def.name]) return;
|
||||||
var d = def.redefined();
|
var redef = def.redefined();
|
||||||
def.name = d ? d.name : next_name();
|
var name = redef ? redef.rename || redef.name : next_name();
|
||||||
|
def.rename = name;
|
||||||
def.orig.forEach(function(sym) {
|
def.orig.forEach(function(sym) {
|
||||||
sym.name = def.name;
|
sym.name = name;
|
||||||
});
|
});
|
||||||
def.references.forEach(function(sym) {
|
def.references.forEach(function(sym) {
|
||||||
sym.name = def.name;
|
sym.name = name;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
189
lib/sourcemap.js
189
lib/sourcemap.js
@@ -43,62 +43,149 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// a small wrapper around fitzgen's source-map library
|
var vlq_char = characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
|
||||||
function SourceMap(options) {
|
var vlq_bits = vlq_char.reduce(function(map, ch, bits) {
|
||||||
options = defaults(options, {
|
map[ch] = bits;
|
||||||
file: null,
|
return map;
|
||||||
root: null,
|
}, Object.create(null));
|
||||||
orig: null,
|
|
||||||
orig_line_diff: 0,
|
function vlq_decode(indices, str) {
|
||||||
dest_line_diff: 0,
|
var value = 0;
|
||||||
}, true);
|
var shift = 0;
|
||||||
var generator = new MOZ_SourceMap.SourceMapGenerator({
|
for (var i = 0, j = 0; i < str.length; i++) {
|
||||||
file: options.file,
|
var bits = vlq_bits[str[i]];
|
||||||
sourceRoot: options.root
|
value += (bits & 31) << shift;
|
||||||
});
|
if (bits & 32) {
|
||||||
var maps = options.orig && Object.create(null);
|
shift += 5;
|
||||||
if (maps) for (var source in options.orig) {
|
} else {
|
||||||
var map = new MOZ_SourceMap.SourceMapConsumer(options.orig[source]);
|
indices[j++] += value & 1 ? 0x80000000 | -(value >> 1) : value >> 1;
|
||||||
if (Array.isArray(options.orig[source].sources)) {
|
value = shift = 0;
|
||||||
map._sources.toArray().forEach(function(source) {
|
|
||||||
var sourceContent = map.sourceContentFor(source, true);
|
|
||||||
if (sourceContent) generator.setSourceContent(source, sourceContent);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
maps[source] = map;
|
|
||||||
}
|
}
|
||||||
return {
|
return j;
|
||||||
add: function(source, gen_line, gen_col, orig_line, orig_col, name) {
|
}
|
||||||
var map = maps && maps[source];
|
|
||||||
if (map) {
|
function vlq_encode(num) {
|
||||||
var info = map.originalPositionFor({
|
var result = "";
|
||||||
line: orig_line,
|
num = Math.abs(num) << 1 | num >>> 31;
|
||||||
column: orig_col
|
do {
|
||||||
|
var bits = num & 31;
|
||||||
|
if (num >>>= 5) bits |= 32;
|
||||||
|
result += vlq_char[bits];
|
||||||
|
} while (num);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_array_map() {
|
||||||
|
var map = Object.create(null);
|
||||||
|
var array = [];
|
||||||
|
array.index = function(name) {
|
||||||
|
if (!HOP(map, name)) {
|
||||||
|
map[name] = array.length;
|
||||||
|
array.push(name);
|
||||||
|
}
|
||||||
|
return map[name];
|
||||||
|
};
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function SourceMap(options) {
|
||||||
|
var sources = create_array_map();
|
||||||
|
var sources_content = options.includeSources && Object.create(null);
|
||||||
|
var names = create_array_map();
|
||||||
|
var mappings = "";
|
||||||
|
if (options.orig) Object.keys(options.orig).forEach(function(name) {
|
||||||
|
var map = options.orig[name];
|
||||||
|
var indices = [ 0, 0, 1, 0, 0 ];
|
||||||
|
options.orig[name] = {
|
||||||
|
names: map.names,
|
||||||
|
mappings: map.mappings.split(/;/).map(function(line) {
|
||||||
|
indices[0] = 0;
|
||||||
|
return line.split(/,/).map(function(segment) {
|
||||||
|
return indices.slice(0, vlq_decode(indices, segment));
|
||||||
});
|
});
|
||||||
if (info.source === null) return;
|
}),
|
||||||
source = info.source;
|
sources: map.sources,
|
||||||
orig_line = info.line;
|
};
|
||||||
orig_col = info.column;
|
if (!sources_content || !map.sourcesContent) return;
|
||||||
name = info.name || name;
|
for (var i = 0; i < map.sources.length; i++) {
|
||||||
}
|
var content = map.sourcesContent[i];
|
||||||
generator.addMapping({
|
if (content) sources_content[map.sources[i]] = content;
|
||||||
name: name,
|
}
|
||||||
source: source,
|
});
|
||||||
generated: {
|
var prev_source;
|
||||||
line: gen_line + options.dest_line_diff,
|
var generated_line = 1;
|
||||||
column: gen_col
|
var generated_column = 0;
|
||||||
},
|
var source_index = 0;
|
||||||
original: {
|
var original_line = 1;
|
||||||
line: orig_line + options.orig_line_diff,
|
var original_column = 0;
|
||||||
column: orig_col
|
var name_index = 0;
|
||||||
|
return {
|
||||||
|
add: options.orig ? function(source, gen_line, gen_col, orig_line, orig_col, name) {
|
||||||
|
var map = options.orig[source];
|
||||||
|
if (map) {
|
||||||
|
var segments = map.mappings[orig_line - 1];
|
||||||
|
if (!segments) return;
|
||||||
|
var indices;
|
||||||
|
for (var i = 0; i < segments.length; i++) {
|
||||||
|
var col = segments[i][0];
|
||||||
|
if (orig_col >= col) indices = segments[i];
|
||||||
|
if (orig_col <= col) break;
|
||||||
}
|
}
|
||||||
});
|
if (!indices || indices.length < 4) {
|
||||||
},
|
source = null;
|
||||||
get: function() {
|
} else {
|
||||||
return generator;
|
source = map.sources[indices[1]];
|
||||||
},
|
orig_line = indices[2];
|
||||||
|
orig_col = indices[3];
|
||||||
|
if (indices.length > 4) name = map.names[indices[4]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add(source, gen_line, gen_col, orig_line, orig_col, name);
|
||||||
|
} : add,
|
||||||
|
setSourceContent: sources_content ? function(source, content) {
|
||||||
|
sources_content[source] = content;
|
||||||
|
} : noop,
|
||||||
toString: function() {
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ TreeTransformer.prototype = new TreeWalker;
|
|||||||
|
|
||||||
(function(DEF) {
|
(function(DEF) {
|
||||||
function do_list(list, tw) {
|
function do_list(list, tw) {
|
||||||
return MAP(list, function(node) {
|
return List(list, function(node) {
|
||||||
return node.transform(tw, true);
|
return node.transform(tw, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
46
lib/utils.js
46
lib/utils.js
@@ -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) {
|
||||||
@@ -113,8 +111,8 @@ function return_true() { return true; }
|
|||||||
function return_this() { return this; }
|
function return_this() { return this; }
|
||||||
function return_null() { return null; }
|
function return_null() { return null; }
|
||||||
|
|
||||||
var MAP = (function() {
|
var List = (function() {
|
||||||
function MAP(a, f, backwards) {
|
function List(a, f, backwards) {
|
||||||
var ret = [], top = [], i;
|
var ret = [], top = [], i;
|
||||||
function doit() {
|
function doit() {
|
||||||
var val = f(a[i], i);
|
var val = f(a[i], i);
|
||||||
@@ -127,8 +125,7 @@ var MAP = (function() {
|
|||||||
} else {
|
} else {
|
||||||
top.push(val);
|
top.push(val);
|
||||||
}
|
}
|
||||||
}
|
} else if (val !== skip) {
|
||||||
else if (val !== skip) {
|
|
||||||
if (val instanceof Splice) {
|
if (val instanceof Splice) {
|
||||||
ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
|
ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
|
||||||
} else {
|
} else {
|
||||||
@@ -145,20 +142,19 @@ var MAP = (function() {
|
|||||||
} else {
|
} else {
|
||||||
for (i = 0; i < a.length; ++i) if (doit()) break;
|
for (i = 0; i < a.length; ++i) if (doit()) break;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
for (i in a) if (HOP(a, i)) if (doit()) break;
|
for (i in a) if (HOP(a, i)) if (doit()) break;
|
||||||
}
|
}
|
||||||
return top.concat(ret);
|
return top.concat(ret);
|
||||||
}
|
}
|
||||||
MAP.at_top = function(val) { return new AtTop(val) };
|
List.at_top = function(val) { return new AtTop(val); };
|
||||||
MAP.splice = function(val) { return new Splice(val) };
|
List.splice = function(val) { return new Splice(val); };
|
||||||
MAP.last = function(val) { return new Last(val) };
|
List.last = function(val) { return new Last(val); };
|
||||||
var skip = MAP.skip = {};
|
var skip = List.skip = {};
|
||||||
function AtTop(val) { this.v = val }
|
function AtTop(val) { this.v = val; }
|
||||||
function Splice(val) { this.v = val }
|
function Splice(val) { this.v = val; }
|
||||||
function Last(val) { this.v = val }
|
function Last(val) { this.v = val; }
|
||||||
return MAP;
|
return List;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function push_uniq(array, el) {
|
function push_uniq(array, el) {
|
||||||
@@ -187,7 +183,7 @@ function makePredicate(words) {
|
|||||||
|
|
||||||
function all(array, predicate) {
|
function all(array, predicate) {
|
||||||
for (var i = array.length; --i >= 0;)
|
for (var i = array.length; --i >= 0;)
|
||||||
if (!predicate(array[i]))
|
if (!predicate(array[i], i))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -219,6 +215,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.6.2",
|
"version": "3.9.2",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
@@ -23,8 +23,7 @@
|
|||||||
"LICENSE"
|
"LICENSE"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"commander": "2.20.0",
|
"commander": "~2.20.3"
|
||||||
"source-map": "~0.6.1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"acorn": "~7.1.0",
|
"acorn": "~7.1.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) {
|
args.unshift("bin/uglifyjs");
|
||||||
args.push("-mc");
|
if (!args.length) args.push("-mc");
|
||||||
}
|
|
||||||
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");
|
||||||
@@ -94,6 +95,3 @@ urls.forEach(function(url) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
setInterval(function() {
|
|
||||||
process.stderr.write("\0");
|
|
||||||
}, 5 * 60 * 1000).unref();
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
require("../tools/exit");
|
||||||
|
|
||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var child_process = require("child_process");
|
var child_process = require("child_process");
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
@@ -9,7 +13,7 @@ var U = require("./node");
|
|||||||
var file = process.argv[2];
|
var file = process.argv[2];
|
||||||
var dir = path.resolve(path.dirname(module.filename), "compress");
|
var dir = path.resolve(path.dirname(module.filename), "compress");
|
||||||
if (file) {
|
if (file) {
|
||||||
var minify_options = require("./ufuzz.json").map(JSON.stringify);
|
var minify_options = require("./ufuzz/options.json").map(JSON.stringify);
|
||||||
log("--- {file}", { file: file });
|
log("--- {file}", { file: file });
|
||||||
var tests = parse_test(path.resolve(dir, file));
|
var tests = parse_test(path.resolve(dir, file));
|
||||||
process.exit(Object.keys(tests).filter(function(name) {
|
process.exit(Object.keys(tests).filter(function(name) {
|
||||||
@@ -203,8 +207,9 @@ function reminify(orig_options, input_code, input_formatted, stdout) {
|
|||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
var expected = stdout[options.toplevel ? 1 : 0];
|
var toplevel = sandbox.has_toplevel(options);
|
||||||
var actual = run_code(result.code, options.toplevel);
|
var expected = stdout[toplevel ? 1 : 0];
|
||||||
|
var actual = run_code(result.code, toplevel);
|
||||||
if (typeof expected != "string" && typeof actual != "string" && expected.name == actual.name) {
|
if (typeof expected != "string" && typeof actual != "string" && expected.name == actual.name) {
|
||||||
actual = expected;
|
actual = expected;
|
||||||
}
|
}
|
||||||
@@ -374,7 +379,10 @@ function test_case(test) {
|
|||||||
}
|
}
|
||||||
if (test.expect_stdout && (!test.node_version || semver.satisfies(process.version, test.node_version))) {
|
if (test.expect_stdout && (!test.node_version || semver.satisfies(process.version, test.node_version))) {
|
||||||
var stdout = [ run_code(input_code), run_code(input_code, true) ];
|
var stdout = [ run_code(input_code), run_code(input_code, true) ];
|
||||||
var toplevel = test.options.toplevel;
|
var toplevel = sandbox.has_toplevel({
|
||||||
|
compress: test.options,
|
||||||
|
mangle: test.mangle
|
||||||
|
});
|
||||||
var actual = stdout[toplevel ? 1 : 0];
|
var actual = stdout[toplevel ? 1 : 0];
|
||||||
if (test.expect_stdout === true) {
|
if (test.expect_stdout === true) {
|
||||||
test.expect_stdout = actual;
|
test.expect_stdout = actual;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ holes_and_undefined: {
|
|||||||
constant_join: {
|
constant_join: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
strings: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -65,6 +66,7 @@ constant_join: {
|
|||||||
constant_join_2: {
|
constant_join_2: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
strings: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -94,9 +96,11 @@ constant_join_2: {
|
|||||||
constant_join_3: {
|
constant_join_3: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
strings: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
var foo, bar, baz;
|
||||||
var a = [ null ].join();
|
var a = [ null ].join();
|
||||||
var b = [ , ].join();
|
var b = [ , ].join();
|
||||||
var c = [ , 1, , 3 ].join();
|
var c = [ , 1, , 3 ].join();
|
||||||
@@ -111,6 +115,7 @@ constant_join_3: {
|
|||||||
var l = [ foo, bar + "baz" ].join("");
|
var l = [ foo, bar + "baz" ].join("");
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
var foo, bar, baz;
|
||||||
var a = "";
|
var a = "";
|
||||||
var b = "";
|
var b = "";
|
||||||
var c = ",1,,3";
|
var c = ",1,,3";
|
||||||
|
|||||||
@@ -91,12 +91,11 @@ 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) sum += +log(values[p >> 3]);
|
||||||
for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) 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 };
|
||||||
@@ -166,3 +165,69 @@ asm_nested_functions: {
|
|||||||
}
|
}
|
||||||
expect_exact: '0;function a(){"use asm";0.0}0;function b(){0;function c(){"use asm";0.0}0;function d(){0}0}0;'
|
expect_exact: '0;function a(){"use asm";0.0}0;function b(){0;function c(){"use asm";0.0}0;function d(){0}0}0;'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3636_1: {
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
function n(stdlib, foreign, buffer) {
|
||||||
|
"use asm";
|
||||||
|
function add(x, y) {
|
||||||
|
x = x | 0;
|
||||||
|
y = y | 0;
|
||||||
|
return x + y | 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
add: add
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log(new n().add("foo", 42));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function n(o, e, u) {
|
||||||
|
"use asm";
|
||||||
|
function d(n, o) {
|
||||||
|
n = n | 0;
|
||||||
|
o = o | 0;
|
||||||
|
return n + o | 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
add: d
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log(new n().add("foo", 42));
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3636_2: {
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var n = function(stdlib, foreign, buffer) {
|
||||||
|
"use asm";
|
||||||
|
function add(x, y) {
|
||||||
|
x = x | 0;
|
||||||
|
y = y | 0;
|
||||||
|
return x + y | 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
add: add
|
||||||
|
};
|
||||||
|
};
|
||||||
|
console.log(new n().add("foo", 42));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var n = function(n, o, e) {
|
||||||
|
"use asm";
|
||||||
|
function r(n, o) {
|
||||||
|
n = n | 0;
|
||||||
|
o = o | 0;
|
||||||
|
return n + o | 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
add: r
|
||||||
|
};
|
||||||
|
};
|
||||||
|
console.log(new n().add("foo", 42));
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|||||||
@@ -290,26 +290,60 @@ increment_decrement_2: {
|
|||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3375: {
|
issue_3375_1: {
|
||||||
options = {
|
options = {
|
||||||
assignments: true,
|
assignments: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(typeof function(b) {
|
function p(o) {
|
||||||
|
console.log(typeof o, o);
|
||||||
|
}
|
||||||
|
p(function(b) {
|
||||||
var a = b += 1;
|
var a = b += 1;
|
||||||
--b;
|
--b;
|
||||||
return a;
|
return a;
|
||||||
}("object"));
|
}("object"));
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(typeof function(b) {
|
function p(o) {
|
||||||
|
console.log(typeof o, o);
|
||||||
|
}
|
||||||
|
p(function(b) {
|
||||||
var a = b += 1;
|
var a = b += 1;
|
||||||
--b;
|
--b;
|
||||||
return a;
|
return a;
|
||||||
}("object"));
|
}("object"));
|
||||||
}
|
}
|
||||||
expect_stdout: "string"
|
expect_stdout: "string object1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3375_2: {
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function p(o) {
|
||||||
|
console.log(typeof o, o);
|
||||||
|
}
|
||||||
|
p(function(b) {
|
||||||
|
var a = b -= 1;
|
||||||
|
--b;
|
||||||
|
return a;
|
||||||
|
}("object"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function p(o) {
|
||||||
|
console.log(typeof o, o);
|
||||||
|
}
|
||||||
|
p(function(b) {
|
||||||
|
var a = --b;
|
||||||
|
--b;
|
||||||
|
return a;
|
||||||
|
}("object"));
|
||||||
|
}
|
||||||
|
expect_stdout: "number NaN"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3427: {
|
issue_3427: {
|
||||||
|
|||||||
@@ -86,3 +86,70 @@ issue_3465_3: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2737_2: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(bar) {
|
||||||
|
for (;bar();) break;
|
||||||
|
})(function qux() {
|
||||||
|
return console.log("PASS"), qux;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(bar) {
|
||||||
|
for (;bar();) break;
|
||||||
|
})(function() {
|
||||||
|
return console.log("PASS"), 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3658: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function f() {
|
||||||
|
console || f();
|
||||||
|
return "PASS";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function f() {
|
||||||
|
console || f();
|
||||||
|
return "PASS";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3690: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
return function() {
|
||||||
|
return a = [ this ];
|
||||||
|
}() ? "PASS" : "FAIL";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
return function() {
|
||||||
|
return 1;
|
||||||
|
}() ? "PASS" : "FAIL";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -33,10 +33,10 @@ unsafe_comps: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var obj1, obj2;
|
var obj1, obj2;
|
||||||
obj2 < obj1 ? g1() : f1();
|
(obj2 < obj1 ? g1 : f1)();
|
||||||
obj1 < obj2 ? f2() : g2();
|
(obj1 < obj2 ? f2 : g2)();
|
||||||
obj1 < obj2 ? g3() : f3();
|
(obj1 < obj2 ? g3 : f3)();
|
||||||
obj2 < obj1 ? f4() : g4();
|
(obj2 < obj1 ? f4 : g4)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ concat_1: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_2: {
|
concat_2: {
|
||||||
options = {}
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
1 + (2 + 3),
|
1 + (2 + 3),
|
||||||
@@ -55,7 +57,9 @@ concat_2: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_3: {
|
concat_3: {
|
||||||
options = {}
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
1 + 2 + (3 + 4 + 5),
|
1 + 2 + (3 + 4 + 5),
|
||||||
@@ -84,7 +88,9 @@ concat_3: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_4: {
|
concat_4: {
|
||||||
options = {}
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
1 + "2" + (3 + 4 + 5),
|
1 + "2" + (3 + 4 + 5),
|
||||||
@@ -113,7 +119,9 @@ concat_4: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_5: {
|
concat_5: {
|
||||||
options = {}
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
"1" + 2 + (3 + 4 + 5),
|
"1" + 2 + (3 + 4 + 5),
|
||||||
@@ -142,7 +150,9 @@ concat_5: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_6: {
|
concat_6: {
|
||||||
options = {}
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
"1" + "2" + (3 + 4 + 5),
|
"1" + "2" + (3 + 4 + 5),
|
||||||
@@ -171,6 +181,9 @@ concat_6: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_7: {
|
concat_7: {
|
||||||
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
"" + 1,
|
"" + 1,
|
||||||
@@ -197,6 +210,9 @@ concat_7: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat_8: {
|
concat_8: {
|
||||||
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(
|
||||||
1 + "",
|
1 + "",
|
||||||
@@ -221,3 +237,20 @@ concat_8: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3689: {
|
||||||
|
options = {
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
return a + ("" + (a[0] = 0));
|
||||||
|
}([]));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
return a + ("" + (a[0] = 0));
|
||||||
|
}([]));
|
||||||
|
}
|
||||||
|
expect_stdout: "00"
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ ifs_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
foo ? x() : bar ? y() : baz && z();
|
foo ? x() : bar ? y() : baz && z();
|
||||||
foo ? x() : bar ? y() : baz ? z() : t();
|
(foo ? x : bar ? y : baz ? z : t)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,6 +161,24 @@ ifs_6: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ifs_7: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if (A); else;
|
||||||
|
if (A) while (B); else;
|
||||||
|
if (A); else while (C);
|
||||||
|
if (A) while (B); else while (C);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
A;
|
||||||
|
if (A) while (B);
|
||||||
|
if (!A) while (C);
|
||||||
|
if (A) while (B); else while (C);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cond_1: {
|
cond_1: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
@@ -271,11 +289,50 @@ cond_5: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
some_condition() && some_other_condition() ? do_something() : alternate();
|
(some_condition() && some_other_condition() ? do_something : alternate)();
|
||||||
some_condition() && some_other_condition() && do_something();
|
some_condition() && some_other_condition() && do_something();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cond_6: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
x ? a : b;
|
||||||
|
x ? a : a;
|
||||||
|
|
||||||
|
x ? y ? a : b : c;
|
||||||
|
x ? y ? a : a : b;
|
||||||
|
x ? y ? a : b : b;
|
||||||
|
x ? y ? a : b : a;
|
||||||
|
x ? y ? a : a : a;
|
||||||
|
|
||||||
|
x ? a : y ? b : c;
|
||||||
|
x ? a : y ? a : b;
|
||||||
|
x ? a : y ? b : b;
|
||||||
|
x ? a : y ? b : a;
|
||||||
|
x ? a : y ? a : a;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
x ? a : b;
|
||||||
|
x, a;
|
||||||
|
|
||||||
|
x ? y ? a : b : c;
|
||||||
|
x ? (y, a) : b;
|
||||||
|
x && y ? a : b;
|
||||||
|
!x || y ? a : b;
|
||||||
|
x && y, a;
|
||||||
|
|
||||||
|
x ? a : y ? b : c;
|
||||||
|
x || y ? a : b;
|
||||||
|
x ? a : (y, b);
|
||||||
|
!x && y ? b : a;
|
||||||
|
!x && y, a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cond_7: {
|
cond_7: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
@@ -645,6 +702,87 @@ cond_9: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cond_10: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
if (1 == a) return "foo";
|
||||||
|
if (2 == a) return "foo";
|
||||||
|
if (3 == a) return "foo";
|
||||||
|
if (4 == a) return 42;
|
||||||
|
if (5 == a) return "foo";
|
||||||
|
if (6 == a) return "foo";
|
||||||
|
return "bar";
|
||||||
|
}
|
||||||
|
console.log(f(1), f(2), f(3), f(4), f(5), f(6), f(7));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
return 1 == a || 2 == a || 3 == a ? "foo" : 4 == a ? 42 : 5 == a || 6 == a ? "foo" : "bar";
|
||||||
|
}
|
||||||
|
console.log(f(1), f(2), f(3), f(4), f(5), f(6), f(7));
|
||||||
|
}
|
||||||
|
expect_stdout: "foo foo foo 42 foo foo bar"
|
||||||
|
}
|
||||||
|
|
||||||
|
cond_11: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {
|
||||||
|
p: "foo",
|
||||||
|
q: function() {
|
||||||
|
return this.p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function f() {
|
||||||
|
return "bar";
|
||||||
|
}
|
||||||
|
function g(a) {
|
||||||
|
return a ? f() : o.q();
|
||||||
|
}
|
||||||
|
console.log(g(0), g(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
p: "foo",
|
||||||
|
q: function() {
|
||||||
|
return this.p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function f() {
|
||||||
|
return "bar";
|
||||||
|
}
|
||||||
|
function g(a) {
|
||||||
|
return a ? f() : o.q();
|
||||||
|
}
|
||||||
|
console.log(g(0), g(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "foo bar"
|
||||||
|
}
|
||||||
|
|
||||||
|
cond_12: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
x ? y && a : a;
|
||||||
|
x ? y || a : a;
|
||||||
|
x ? a : y && a;
|
||||||
|
x ? a : y || a;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(!x || y) && a;
|
||||||
|
x && y || a;
|
||||||
|
(x || y) && a;
|
||||||
|
!x && y || a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ternary_boolean_consequent: {
|
ternary_boolean_consequent: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
@@ -1102,11 +1240,11 @@ issue_2535_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
y();
|
y();
|
||||||
x() && y();
|
x() && y();
|
||||||
(x(), 1) && y();
|
x(), y();
|
||||||
x() && y();
|
x() && y();
|
||||||
x() && y();
|
x() && y();
|
||||||
x() && y();
|
x() && y();
|
||||||
(x(), 0) && y();
|
x();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1246,7 +1384,7 @@ hoist_decl: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a, b;
|
var a, b;
|
||||||
x() ? y() : z();
|
(x() ? y : z)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1471,3 +1609,187 @@ angularjs_chain: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3576: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function(a) {
|
||||||
|
(a = -1) ? (a && (a.a = 0)) : (a && (a.a = 0));
|
||||||
|
a && a[c = "PASS"]++;
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function(a) {
|
||||||
|
a = -1, a, a.a = 0;
|
||||||
|
a, a[c = "PASS"]++;
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3668: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
var undefined = typeof f;
|
||||||
|
if (!f) return undefined;
|
||||||
|
return;
|
||||||
|
} catch (e) {
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
var undefined = typeof f;
|
||||||
|
return f ? void 0 : undefined;
|
||||||
|
} catch (e) {
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_assignments_1: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b, c, d) {
|
||||||
|
a = b;
|
||||||
|
if (c) a = d;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
function g(a, b, c, d) {
|
||||||
|
a = b;
|
||||||
|
if (c); else a = d;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(f(0, "FAIL", 1, "PASS"), g(0, "PASS", 1, "FAIL"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b, c, d) {
|
||||||
|
return a = c ? d : b, a;
|
||||||
|
}
|
||||||
|
function g(a, b, c, d) {
|
||||||
|
return a = c ? b : d, a;
|
||||||
|
}
|
||||||
|
console.log(f(0, "FAIL", 1, "PASS"), g(0, "PASS", 1, "FAIL"));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_assignments_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f1(b, c, d) {
|
||||||
|
a = b;
|
||||||
|
if (c) a = d;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
function f2(a, c, d) {
|
||||||
|
a = b;
|
||||||
|
if (c) a = d;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
function f3(a, b, d) {
|
||||||
|
a = b;
|
||||||
|
if (c) a = d;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
function f4(a, b, c) {
|
||||||
|
a = b;
|
||||||
|
if (c) a = d;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f1(b, c, d) {
|
||||||
|
return a = c ? d : b, a;
|
||||||
|
}
|
||||||
|
function f2(a, c, d) {
|
||||||
|
return a = b, c && (a = d), a;
|
||||||
|
}
|
||||||
|
function f3(a, b, d) {
|
||||||
|
return a = b, c && (a = d), a;
|
||||||
|
}
|
||||||
|
function f4(a, b, c) {
|
||||||
|
return a = b, c && (a = d), a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_assignments_3: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
a = "PASS";
|
||||||
|
if (b) a = a;
|
||||||
|
return a;
|
||||||
|
}(0, 1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
return a = "PASS", b && (a = a), a;
|
||||||
|
}(0, 1));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3808_1: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
a = "PASS", [] + "" && (a = "FAIL");
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
a = [] + "" ? "FAIL" : "PASS";
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3808_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
console.log((a = "PASS", [] + "" && (a = "FAIL")), a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
console.log((a = "PASS", [] + "" && (a = "FAIL")), a);
|
||||||
|
}
|
||||||
|
expect_stdout: " PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -97,6 +97,66 @@ dead_code_constant_boolean_should_warn_more: {
|
|||||||
node_version: "<=4"
|
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 +190,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",
|
||||||
@@ -141,207 +198,6 @@ try_catch_finally: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
accessor: {
|
|
||||||
options = {
|
|
||||||
side_effects: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
({
|
|
||||||
get a() {},
|
|
||||||
set a(v){
|
|
||||||
this.b = 2;
|
|
||||||
},
|
|
||||||
b: 1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
expect: {}
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_2233_1: {
|
|
||||||
options = {
|
|
||||||
pure_getters: "strict",
|
|
||||||
side_effects: true,
|
|
||||||
unsafe: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
Array.isArray;
|
|
||||||
Boolean;
|
|
||||||
console.log;
|
|
||||||
Date;
|
|
||||||
decodeURI;
|
|
||||||
decodeURIComponent;
|
|
||||||
encodeURI;
|
|
||||||
encodeURIComponent;
|
|
||||||
Error.name;
|
|
||||||
escape;
|
|
||||||
eval;
|
|
||||||
EvalError;
|
|
||||||
Function.length;
|
|
||||||
isFinite;
|
|
||||||
isNaN;
|
|
||||||
JSON;
|
|
||||||
Math.random;
|
|
||||||
Number.isNaN;
|
|
||||||
parseFloat;
|
|
||||||
parseInt;
|
|
||||||
RegExp;
|
|
||||||
Object.defineProperty;
|
|
||||||
String.fromCharCode;
|
|
||||||
RangeError;
|
|
||||||
ReferenceError;
|
|
||||||
SyntaxError;
|
|
||||||
TypeError;
|
|
||||||
unescape;
|
|
||||||
URIError;
|
|
||||||
}
|
|
||||||
expect: {}
|
|
||||||
expect_stdout: true
|
|
||||||
}
|
|
||||||
|
|
||||||
global_timeout_and_interval_symbols: {
|
|
||||||
options = {
|
|
||||||
pure_getters: "strict",
|
|
||||||
side_effects: true,
|
|
||||||
unsafe: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
// These global symbols do not exist in the test sandbox
|
|
||||||
// and must be tested separately.
|
|
||||||
clearInterval;
|
|
||||||
clearTimeout;
|
|
||||||
setInterval;
|
|
||||||
setTimeout;
|
|
||||||
}
|
|
||||||
expect: {}
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_2233_2: {
|
|
||||||
options = {
|
|
||||||
pure_getters: "strict",
|
|
||||||
reduce_funcs: true,
|
|
||||||
reduce_vars: true,
|
|
||||||
side_effects: true,
|
|
||||||
unsafe: true,
|
|
||||||
unused: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var RegExp;
|
|
||||||
Array.isArray;
|
|
||||||
RegExp;
|
|
||||||
UndeclaredGlobal;
|
|
||||||
function foo() {
|
|
||||||
var Number;
|
|
||||||
AnotherUndeclaredGlobal;
|
|
||||||
Math.sin;
|
|
||||||
Number.isNaN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var RegExp;
|
|
||||||
UndeclaredGlobal;
|
|
||||||
function foo() {
|
|
||||||
var Number;
|
|
||||||
AnotherUndeclaredGlobal;
|
|
||||||
Number.isNaN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_2233_3: {
|
|
||||||
options = {
|
|
||||||
pure_getters: "strict",
|
|
||||||
reduce_funcs: true,
|
|
||||||
reduce_vars: true,
|
|
||||||
side_effects: true,
|
|
||||||
toplevel: true,
|
|
||||||
unsafe: true,
|
|
||||||
unused: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
var RegExp;
|
|
||||||
Array.isArray;
|
|
||||||
RegExp;
|
|
||||||
UndeclaredGlobal;
|
|
||||||
function foo() {
|
|
||||||
var Number;
|
|
||||||
AnotherUndeclaredGlobal;
|
|
||||||
Math.sin;
|
|
||||||
Number.isNaN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
UndeclaredGlobal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
global_fns: {
|
|
||||||
options = {
|
|
||||||
side_effects: true,
|
|
||||||
unsafe: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
Boolean(1, 2);
|
|
||||||
decodeURI(1, 2);
|
|
||||||
decodeURIComponent(1, 2);
|
|
||||||
Date(1, 2);
|
|
||||||
encodeURI(1, 2);
|
|
||||||
encodeURIComponent(1, 2);
|
|
||||||
Error(1, 2);
|
|
||||||
escape(1, 2);
|
|
||||||
EvalError(1, 2);
|
|
||||||
isFinite(1, 2);
|
|
||||||
isNaN(1, 2);
|
|
||||||
Number(1, 2);
|
|
||||||
Object(1, 2);
|
|
||||||
parseFloat(1, 2);
|
|
||||||
parseInt(1, 2);
|
|
||||||
RangeError(1, 2);
|
|
||||||
ReferenceError(1, 2);
|
|
||||||
String(1, 2);
|
|
||||||
SyntaxError(1, 2);
|
|
||||||
TypeError(1, 2);
|
|
||||||
unescape(1, 2);
|
|
||||||
URIError(1, 2);
|
|
||||||
try {
|
|
||||||
Function(1, 2);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e.name);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
RegExp(1, 2);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e.name);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Array(NaN);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
try {
|
|
||||||
Function(1, 2);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e.name);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
RegExp(1, 2);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e.name);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Array(NaN);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect_stdout: [
|
|
||||||
"SyntaxError",
|
|
||||||
"SyntaxError",
|
|
||||||
"RangeError",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
collapse_vars_assignment: {
|
collapse_vars_assignment: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -863,23 +719,6 @@ issue_2749: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_builtin: {
|
|
||||||
options = {
|
|
||||||
side_effects: true,
|
|
||||||
unsafe: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
(!w).constructor(x);
|
|
||||||
Math.abs(y);
|
|
||||||
[ 1, 2, z ].valueOf();
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
w, x;
|
|
||||||
y;
|
|
||||||
z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_2860_1: {
|
issue_2860_1: {
|
||||||
options = {
|
options = {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
@@ -892,9 +731,7 @@ issue_2860_1: {
|
|||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function(a) {
|
console.log(1);
|
||||||
return 1 ^ a;
|
|
||||||
}());
|
|
||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
@@ -943,24 +780,6 @@ issue_2929: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_string_replace: {
|
|
||||||
options = {
|
|
||||||
side_effects: true,
|
|
||||||
unsafe: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
"foo".replace("f", function() {
|
|
||||||
console.log("PASS");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
"foo".replace("f", function() {
|
|
||||||
console.log("PASS");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
expect_stdout: "PASS"
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_3402: {
|
issue_3402: {
|
||||||
options = {
|
options = {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
@@ -1013,3 +832,322 @@ issue_3406: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "true"
|
expect_stdout: "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function_assign: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var a = "PASS";
|
||||||
|
function h(c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
h.p = function(b) {
|
||||||
|
return b;
|
||||||
|
}.p = a;
|
||||||
|
return h;
|
||||||
|
}().p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var a = "PASS";
|
||||||
|
function h(c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
h.p = a;
|
||||||
|
return h;
|
||||||
|
}().p);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3552: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
(function() {
|
||||||
|
(1..p += 42) && (a = "FAIL");
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "PASS";
|
||||||
|
(function() {
|
||||||
|
(1..p += 42) && (a = "FAIL");
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable_assign: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
strings: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(A = "P" + (A = "A" + (B = "S" + (A = B = "S"))), A, B);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(A = "P" + "A" + (B = "S" + "S"), A, B);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS PASS SS"
|
||||||
|
}
|
||||||
|
|
||||||
|
catch_return_assign: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (e) {
|
||||||
|
return e = "PASS";
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (e) {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3578: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL", b, c;
|
||||||
|
try {
|
||||||
|
b = c.p = b = 0;
|
||||||
|
} catch (e) {
|
||||||
|
b += 42;
|
||||||
|
b && (a = "PASS");
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL", b, c;
|
||||||
|
try {
|
||||||
|
b = c.p = b = 0;
|
||||||
|
} catch (e) {
|
||||||
|
b += 42;
|
||||||
|
b && (a = "PASS");
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|||||||
131
test/compress/directives.js
Normal file
131
test/compress/directives.js
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
simple_statement_is_not_a_directive: {
|
||||||
|
input: {
|
||||||
|
"use strict"
|
||||||
|
.split(" ")
|
||||||
|
.forEach(function(s) {
|
||||||
|
console.log(s);
|
||||||
|
});
|
||||||
|
console.log(!this); // is strict mode?
|
||||||
|
(function() {
|
||||||
|
"directive"
|
||||||
|
""
|
||||||
|
"use strict"
|
||||||
|
"hello world"
|
||||||
|
.split(" ")
|
||||||
|
.forEach(function(s) {
|
||||||
|
console.log(s);
|
||||||
|
});
|
||||||
|
console.log(!this); // is strict mode?
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict".split(" ").forEach(function(s) {
|
||||||
|
console.log(s);
|
||||||
|
});
|
||||||
|
console.log(!this);
|
||||||
|
(function() {
|
||||||
|
"directive";
|
||||||
|
"";
|
||||||
|
"use strict";
|
||||||
|
"hello world".split(" ").forEach(function(s) {
|
||||||
|
console.log(s);
|
||||||
|
});
|
||||||
|
console.log(!this);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"use",
|
||||||
|
"strict",
|
||||||
|
"false",
|
||||||
|
"hello",
|
||||||
|
"world",
|
||||||
|
"true",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_lone_use_strict: {
|
||||||
|
options = {
|
||||||
|
directives: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f1() {
|
||||||
|
"use strict";
|
||||||
|
}
|
||||||
|
function f2() {
|
||||||
|
"use strict";
|
||||||
|
function f3() {
|
||||||
|
"use strict";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(function f4() {
|
||||||
|
"use strict";
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f1() {
|
||||||
|
}
|
||||||
|
function f2() {
|
||||||
|
}
|
||||||
|
(function() {})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3166: {
|
||||||
|
options = {
|
||||||
|
directives: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"foo";
|
||||||
|
"use strict";
|
||||||
|
function f() {
|
||||||
|
"use strict";
|
||||||
|
"bar";
|
||||||
|
"use asm";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
function f() {
|
||||||
|
"use asm";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_after_invalid_1: {
|
||||||
|
input: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
"use\x20strict";
|
||||||
|
"use strict";
|
||||||
|
return this;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
"use\x20strict";
|
||||||
|
"use strict";
|
||||||
|
return this;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_after_invalid_2: {
|
||||||
|
options = {
|
||||||
|
directives: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
"use\x20strict";
|
||||||
|
"use strict";
|
||||||
|
return this;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
"use strict";
|
||||||
|
return this;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
@@ -699,18 +699,6 @@ iife: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drop_value: {
|
|
||||||
options = {
|
|
||||||
side_effects: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
(1, [2, foo()], 3, {a:1, b:bar()});
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
foo(), bar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_1539: {
|
issue_1539: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -1019,14 +1007,21 @@ delete_assign_1: {
|
|||||||
console.log(delete (a = 0 / 0));
|
console.log(delete (a = 0 / 0));
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log((void 0, !0));
|
console.log(!0);
|
||||||
console.log((void 0, !0));
|
console.log(!0);
|
||||||
console.log((1 / 0, !0));
|
console.log(!0);
|
||||||
console.log((1 / 0, !0));
|
console.log(!0);
|
||||||
console.log((NaN, !0));
|
console.log(!0);
|
||||||
console.log((NaN, !0));
|
console.log(!0);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: [
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_assign_2: {
|
delete_assign_2: {
|
||||||
@@ -1047,14 +1042,21 @@ delete_assign_2: {
|
|||||||
console.log(delete (a = 0 / 0));
|
console.log(delete (a = 0 / 0));
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log((void 0, !0));
|
console.log(!0);
|
||||||
console.log((void 0, !0));
|
console.log(!0);
|
||||||
console.log((Infinity, !0));
|
console.log(!0);
|
||||||
console.log((1 / 0, !0));
|
console.log(!0);
|
||||||
console.log((NaN, !0));
|
console.log(!0);
|
||||||
console.log((NaN, !0));
|
console.log(!0);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: [
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
drop_var: {
|
drop_var: {
|
||||||
@@ -1189,10 +1191,10 @@ issue_2105_1: {
|
|||||||
input: {
|
input: {
|
||||||
!function(factory) {
|
!function(factory) {
|
||||||
factory();
|
factory();
|
||||||
}( function() {
|
}(function() {
|
||||||
return function(fn) {
|
return function(fn) {
|
||||||
fn()().prop();
|
fn()().prop();
|
||||||
}( function() {
|
}(function() {
|
||||||
function bar() {
|
function bar() {
|
||||||
var quux = function() {
|
var quux = function() {
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
@@ -1203,7 +1205,7 @@ issue_2105_1: {
|
|||||||
return { prop: foo };
|
return { prop: foo };
|
||||||
}
|
}
|
||||||
return bar;
|
return bar;
|
||||||
} );
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
@@ -1233,10 +1235,10 @@ issue_2105_2: {
|
|||||||
input: {
|
input: {
|
||||||
!function(factory) {
|
!function(factory) {
|
||||||
factory();
|
factory();
|
||||||
}( function() {
|
}(function() {
|
||||||
return function(fn) {
|
return function(fn) {
|
||||||
fn()().prop();
|
fn()().prop();
|
||||||
}( function() {
|
}(function() {
|
||||||
function bar() {
|
function bar() {
|
||||||
var quux = function() {
|
var quux = function() {
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
@@ -1247,7 +1249,7 @@ issue_2105_2: {
|
|||||||
return { prop: foo };
|
return { prop: foo };
|
||||||
}
|
}
|
||||||
return bar;
|
return bar;
|
||||||
} );
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
@@ -1256,6 +1258,44 @@ issue_2105_2: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2105_3: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function(factory) {
|
||||||
|
factory();
|
||||||
|
}(function() {
|
||||||
|
return function(fn) {
|
||||||
|
fn()().prop();
|
||||||
|
}(function() {
|
||||||
|
function bar() {
|
||||||
|
var quux = function() {
|
||||||
|
console.log("PASS");
|
||||||
|
}, foo = function() {
|
||||||
|
console.log;
|
||||||
|
quux();
|
||||||
|
};
|
||||||
|
return { prop: foo };
|
||||||
|
}
|
||||||
|
return bar;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!void void {
|
||||||
|
prop: function() {
|
||||||
|
console.log;
|
||||||
|
void console.log("PASS");
|
||||||
|
}
|
||||||
|
}.prop();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
issue_2226_1: {
|
issue_2226_1: {
|
||||||
options = {
|
options = {
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -1635,7 +1675,7 @@ double_assign_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (var i = 0; i < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
void 0, a = {}, console.log(a);
|
a = {}, console.log(a);
|
||||||
var a;
|
var a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1716,7 +1756,7 @@ issue_2768: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = "FAIL";
|
var a = "FAIL";
|
||||||
var c = (d = a, 0, void (d && (a = "PASS")));
|
var c = (d = a, void (d && (a = "PASS")));
|
||||||
var d;
|
var d;
|
||||||
console.log(a, typeof c);
|
console.log(a, typeof c);
|
||||||
}
|
}
|
||||||
@@ -2062,3 +2102,411 @@ issue_3427_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3495: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function f() {
|
||||||
|
f = 0;
|
||||||
|
var a = f.p;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(void 0);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3497: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
console.log(function(b) {
|
||||||
|
(b += a).p = 0;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
console.log(function(b) {
|
||||||
|
(b += a).p = 0;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3515_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
(function() {
|
||||||
|
this[c++] = 0;
|
||||||
|
var expr20 = !0;
|
||||||
|
for (var key20 in expr20);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
(function() {
|
||||||
|
this[c++] = 0;
|
||||||
|
for (var key20 in !0);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3515_2: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
function f() {
|
||||||
|
typeof b === "number";
|
||||||
|
delete a;
|
||||||
|
}
|
||||||
|
var b = f(a = "PASS");
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
function f() {
|
||||||
|
delete a;
|
||||||
|
}
|
||||||
|
f(a = "PASS");
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3515_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
c = "PASS";
|
||||||
|
}
|
||||||
|
var a = f();
|
||||||
|
var a = function g(b) {
|
||||||
|
b && (b.p = this);
|
||||||
|
}(a);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
c = "PASS";
|
||||||
|
}
|
||||||
|
(function(b) {
|
||||||
|
b && (b.p = this);
|
||||||
|
})(f());
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
function_assign: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var a = "PASS";
|
||||||
|
function g(b) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
g.p = a;
|
||||||
|
function h(c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
h.p = a;
|
||||||
|
return h;
|
||||||
|
}().p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var a = "PASS";
|
||||||
|
function h(c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
h.p = a;
|
||||||
|
return h;
|
||||||
|
}().p);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3598: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
(function() {
|
||||||
|
var b = void 0;
|
||||||
|
a = "PASS";
|
||||||
|
c.p = 0;
|
||||||
|
var c = b[!1];
|
||||||
|
})();
|
||||||
|
} catch (e) {}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
(function() {
|
||||||
|
a = "PASS";
|
||||||
|
var c = (void (c.p = 0))[!1];
|
||||||
|
})();
|
||||||
|
} catch (e) {}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
self_assign: {
|
||||||
|
options = {
|
||||||
|
passes: 2,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function d(a) {
|
||||||
|
a = a;
|
||||||
|
}
|
||||||
|
function e(a, b) {
|
||||||
|
a = b;
|
||||||
|
b = a;
|
||||||
|
}
|
||||||
|
function f(a, b, c) {
|
||||||
|
a = b;
|
||||||
|
b = c;
|
||||||
|
c = a;
|
||||||
|
}
|
||||||
|
function g(a, b, c) {
|
||||||
|
a = a * b + c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function d(a) {}
|
||||||
|
function e(a, b) {}
|
||||||
|
function f(a, b, c) {}
|
||||||
|
function g(a, b, c) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function_argument_reference: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: false,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1, b = 42;
|
||||||
|
function f(a) {
|
||||||
|
b <<= a;
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1, b = 42;
|
||||||
|
function f(a) {
|
||||||
|
b <<= a;
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "1 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
function_parameter_ie8: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a;
|
||||||
|
function f() {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
f(a = 1 + a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function f() {
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3664: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var a, b = (a = (a = [ b && console.log("FAIL") ]).p = 0, 0);
|
||||||
|
return "PASS";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var b = ([ b && console.log("FAIL") ].p = 0, 0);
|
||||||
|
return "PASS";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3673: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
(a = [ a ]).p = 42;
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
(a = [ a ]).p = 42;
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3746: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
A;
|
||||||
|
} catch (e) {
|
||||||
|
var e;
|
||||||
|
}
|
||||||
|
(function f(a) {
|
||||||
|
e = a;
|
||||||
|
})();
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
A;
|
||||||
|
} catch (e) {
|
||||||
|
var e;
|
||||||
|
}
|
||||||
|
(function(a) {
|
||||||
|
e = a;
|
||||||
|
})();
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_duplicated_side_effects: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
for (var i = 1; i--;)
|
||||||
|
var a = 0, b = ++a;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
for (var i = 1; i--;)
|
||||||
|
a = 0, ++a;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_duplicated_var_catch: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (a) {
|
||||||
|
var a, a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3802: {
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|||||||
@@ -237,22 +237,39 @@ unsafe_constant: {
|
|||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
console.log(true.a, false.a);
|
||||||
true.a,
|
console.log(true.valueOf(), false.valueOf());
|
||||||
false.a,
|
try {
|
||||||
null.a,
|
console.log(null.a);
|
||||||
undefined.a
|
} catch (e) {
|
||||||
);
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
console.log(undefined.a);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(
|
console.log(void 0, void 0);
|
||||||
void 0,
|
console.log(true, false);
|
||||||
false.a,
|
try {
|
||||||
null.a,
|
console.log(null.a);
|
||||||
(void 0).a
|
} catch (e) {
|
||||||
);
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
console.log((void 0).a);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: [
|
||||||
|
"undefined undefined",
|
||||||
|
"true false",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_object: {
|
unsafe_object: {
|
||||||
@@ -1757,3 +1774,419 @@ issue_3387_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "NaN"
|
expect_stdout: "NaN"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simple_function_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function sum(a, b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
console.log(sum(1, 2) * sum(3, 4));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(21);
|
||||||
|
}
|
||||||
|
expect_stdout: "21"
|
||||||
|
}
|
||||||
|
|
||||||
|
simple_function_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var sum = function(a, b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
console.log(sum(1, 2) * sum(3, 4));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(21);
|
||||||
|
}
|
||||||
|
expect_stdout: "21"
|
||||||
|
}
|
||||||
|
|
||||||
|
recursive_function_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function factorial(a) {
|
||||||
|
return a > 0 ? a * factorial(a - 1) : 1;
|
||||||
|
}
|
||||||
|
console.log(factorial(5));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function factorial(a) {
|
||||||
|
return a > 0 ? a * factorial(a - 1) : 1;
|
||||||
|
}(5));
|
||||||
|
}
|
||||||
|
expect_stdout: "120"
|
||||||
|
}
|
||||||
|
|
||||||
|
recursive_function_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var factorial = function(a) {
|
||||||
|
return a > 0 ? a * factorial(a - 1) : 1;
|
||||||
|
}
|
||||||
|
console.log(factorial(5));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var factorial = function(a) {
|
||||||
|
return a > 0 ? a * factorial(a - 1) : 1;
|
||||||
|
}
|
||||||
|
console.log(factorial(5));
|
||||||
|
}
|
||||||
|
expect_stdout: "120"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3558: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
return 1 + --a;
|
||||||
|
}
|
||||||
|
console.log(f(true), f(false));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
return 1 + --a;
|
||||||
|
}
|
||||||
|
console.log(1, 0);
|
||||||
|
}
|
||||||
|
expect_stdout: "1 0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3568: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
function f(b) {
|
||||||
|
return b && b.p;
|
||||||
|
}
|
||||||
|
console.log(f(++a + f()));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
function f(b) {
|
||||||
|
return b && b.p;
|
||||||
|
}
|
||||||
|
console.log(NaN);
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_function: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
return a && "undefined" != typeof A ? A : 42;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
return a && "undefined" != typeof A ? A : 42;
|
||||||
|
}
|
||||||
|
console.log(42, f(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "42 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
best_of_evaluate: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function d(x, y) {
|
||||||
|
return x / y;
|
||||||
|
}
|
||||||
|
console.log(0 / 3, 1 / 64, 4 / 7, 7 / 7);
|
||||||
|
console.log(d(0, 3), d(1, 64), d(4, 7), d(7, 7));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function d(x, y) {
|
||||||
|
return x / y;
|
||||||
|
}
|
||||||
|
console.log(0, 1 / 64, 4 / 7, 1);
|
||||||
|
console.log(0, .015625, d(4, 7), 1);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0 0.015625 0.5714285714285714 1",
|
||||||
|
"0 0.015625 0.5714285714285714 1",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
eager_evaluate: {
|
||||||
|
options = {
|
||||||
|
evaluate: "eager",
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function d(x, y) {
|
||||||
|
return x / y;
|
||||||
|
}
|
||||||
|
console.log(0 / 3, 1 / 64, 4 / 7, 7 / 7);
|
||||||
|
console.log(d(0, 3), d(1, 64), d(4, 7), d(7, 7));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(0, .015625, .5714285714285714, 1);
|
||||||
|
console.log(0, .015625, .5714285714285714, 1);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0 0.015625 0.5714285714285714 1",
|
||||||
|
"0 0.015625 0.5714285714285714 1",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
threshold_evaluate_default: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function b(x) {
|
||||||
|
return x + x + x;
|
||||||
|
}
|
||||||
|
console.log(b("1"), b(2), b(b(b("ABCDEFGHIJK"))));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function b(x) {
|
||||||
|
return x + x + x;
|
||||||
|
}
|
||||||
|
console.log("111", 6, b(b(b("ABCDEFGHIJK"))));
|
||||||
|
}
|
||||||
|
expect_stdout: "111 6 ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK"
|
||||||
|
}
|
||||||
|
|
||||||
|
threshold_evaluate_30: {
|
||||||
|
options = {
|
||||||
|
evaluate: 30,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function b(x) {
|
||||||
|
return x + x + x;
|
||||||
|
}
|
||||||
|
console.log(b("1"), b(2), b(b(b("ABCDEFGHIJK"))));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function b(x) {
|
||||||
|
return x + x + x;
|
||||||
|
}
|
||||||
|
console.log("111", 6, b(b("ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK")));
|
||||||
|
}
|
||||||
|
expect_stdout: "111 6 ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK"
|
||||||
|
}
|
||||||
|
|
||||||
|
threshold_evaluate_100: {
|
||||||
|
options = {
|
||||||
|
evaluate: 100,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function b(x) {
|
||||||
|
return x + x + x;
|
||||||
|
}
|
||||||
|
console.log(b("1"), b(2), b(b(b("ABCDEFGHIJK"))));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function b(x) {
|
||||||
|
return x + x + x;
|
||||||
|
}
|
||||||
|
console.log("111", 6, b("ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK"));
|
||||||
|
}
|
||||||
|
expect_stdout: "111 6 ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK"
|
||||||
|
}
|
||||||
|
|
||||||
|
threshold_evaluate_999: {
|
||||||
|
options = {
|
||||||
|
evaluate: 999,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function b(x) {
|
||||||
|
return x + x + x;
|
||||||
|
}
|
||||||
|
console.log(b("1"), b(2), b(b(b("ABCDEFGHIJK"))));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("111", 6, "ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK");
|
||||||
|
}
|
||||||
|
expect_stdout: "111 6 ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK"
|
||||||
|
}
|
||||||
|
|
||||||
|
collapse_vars_regexp: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
comparisons: true,
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
hoist_funs: true,
|
||||||
|
if_return: true,
|
||||||
|
join_vars: true,
|
||||||
|
keep_fargs: true,
|
||||||
|
loops: false,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe_regexp: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f1() {
|
||||||
|
var k = 9;
|
||||||
|
var rx = /[A-Z]+/;
|
||||||
|
return [rx, k];
|
||||||
|
}
|
||||||
|
function f2() {
|
||||||
|
var rx = /ab*/g;
|
||||||
|
return function(s) {
|
||||||
|
return rx.exec(s);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function f3() {
|
||||||
|
var rx = /ab*/g;
|
||||||
|
return function() {
|
||||||
|
return rx;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(function() {
|
||||||
|
var result;
|
||||||
|
var s = "acdabcdeabbb";
|
||||||
|
var rx = /ab*/g;
|
||||||
|
while (result = rx.exec(s))
|
||||||
|
console.log(result[0]);
|
||||||
|
})();
|
||||||
|
(function() {
|
||||||
|
var result;
|
||||||
|
var s = "acdabcdeabbb";
|
||||||
|
var rx = f2();
|
||||||
|
while (result = rx(s))
|
||||||
|
console.log(result[0]);
|
||||||
|
})();
|
||||||
|
(function() {
|
||||||
|
var result;
|
||||||
|
var s = "acdabcdeabbb";
|
||||||
|
var rx = f3();
|
||||||
|
while (result = rx().exec(s))
|
||||||
|
console.log(result[0]);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f1() {
|
||||||
|
return [/[A-Z]+/, 9];
|
||||||
|
}
|
||||||
|
function f2() {
|
||||||
|
var rx = /ab*/g;
|
||||||
|
return function(s) {
|
||||||
|
return rx.exec(s);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function f3() {
|
||||||
|
var rx = /ab*/g;
|
||||||
|
return function() {
|
||||||
|
return rx;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(function() {
|
||||||
|
var result, rx = /ab*/g;
|
||||||
|
while (result = rx.exec("acdabcdeabbb"))
|
||||||
|
console.log(result[0]);
|
||||||
|
})();
|
||||||
|
(function() {
|
||||||
|
var result, rx = f2();
|
||||||
|
while (result = rx("acdabcdeabbb"))
|
||||||
|
console.log(result[0]);
|
||||||
|
})();
|
||||||
|
(function() {
|
||||||
|
var result, rx = f3();
|
||||||
|
while (result = rx().exec("acdabcdeabbb"))
|
||||||
|
console.log(result[0]);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"a",
|
||||||
|
"ab",
|
||||||
|
"abbb",
|
||||||
|
"a",
|
||||||
|
"ab",
|
||||||
|
"abbb",
|
||||||
|
"a",
|
||||||
|
"ab",
|
||||||
|
"abbb",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3738: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(1 / (0 + ([] - 1) % 1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(1 / (0 + ([] - 1) % 1));
|
||||||
|
}
|
||||||
|
expect_stdout: "Infinity"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3755: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log((/4/.exec(1 + (!0 - 5 / "23")) || 0).p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log((/4/.exec(!0 - 5 / "23" + 1), 0).p);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -664,7 +664,7 @@ issue_2519: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function testFunc() {
|
function testFunc() {
|
||||||
return 1 * ((6 + 5) / 2);
|
return +((6 + 5) / 2);
|
||||||
}
|
}
|
||||||
console.log(testFunc());
|
console.log(testFunc());
|
||||||
}
|
}
|
||||||
@@ -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: {
|
||||||
|
|||||||
@@ -1,55 +1,107 @@
|
|||||||
html_comment_in_expression: {
|
html_comment_in_expression: {
|
||||||
input: {
|
input: {
|
||||||
function f(a, b, x, y) { return a < !--b && x-- > y; }
|
(function(a, b) {
|
||||||
|
console.log(a < !--b && a-- > b, a, b);
|
||||||
|
})(1, 2);
|
||||||
}
|
}
|
||||||
expect_exact: "function f(a,b,x,y){return a< !--b&&x-- >y}";
|
expect_exact: "(function(a,b){console.log(a<! --b&&a-- >b,a,b)})(1,2);"
|
||||||
|
expect_stdout: "false 1 1"
|
||||||
}
|
}
|
||||||
|
|
||||||
html_comment_in_less_than: {
|
html_comment_in_less_than: {
|
||||||
input: {
|
input: {
|
||||||
function f(a, b) { return a < !--b; }
|
(function(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
a < !--b,
|
||||||
|
a < !--b + c,
|
||||||
|
a + b < !--c,
|
||||||
|
a, b, c
|
||||||
|
);
|
||||||
|
})(1, 2, 3);
|
||||||
}
|
}
|
||||||
expect_exact: "function f(a,b){return a< !--b}";
|
expect_exact: "(function(a,b,c){console.log(a<! --b,a<! --b+c,a+b<! --c,a,b,c)})(1,2,3);"
|
||||||
|
expect_stdout: "false true false 1 0 2"
|
||||||
}
|
}
|
||||||
|
|
||||||
html_comment_in_left_shift: {
|
html_comment_in_left_shift: {
|
||||||
input: {
|
input: {
|
||||||
function f(a, b) { return a << !--b; }
|
(function(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
a << !--b,
|
||||||
|
a << !--b + c,
|
||||||
|
a + b << !--c,
|
||||||
|
a, b, c
|
||||||
|
);
|
||||||
|
})(1, 2, 3);
|
||||||
}
|
}
|
||||||
expect_exact: "function f(a,b){return a<< !--b}";
|
expect_exact: "(function(a,b,c){console.log(a<<! --b,a<<! --b+c,a+b<<! --c,a,b,c)})(1,2,3);"
|
||||||
}
|
expect_stdout: "1 16 1 1 0 2"
|
||||||
|
|
||||||
html_comment_in_right_shift: {
|
|
||||||
input: {
|
|
||||||
function f(a, b) { return a-- >> b; }
|
|
||||||
}
|
|
||||||
expect_exact: "function f(a,b){return a-- >>b}";
|
|
||||||
}
|
|
||||||
|
|
||||||
html_comment_in_zero_fill_right_shift: {
|
|
||||||
input: {
|
|
||||||
function f(a, b) { return a-- >>> b; }
|
|
||||||
}
|
|
||||||
expect_exact: "function f(a,b){return a-- >>>b}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
html_comment_in_greater_than: {
|
html_comment_in_greater_than: {
|
||||||
input: {
|
input: {
|
||||||
function f(a, b) { return a-- > b; }
|
(function(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
a-- > b,
|
||||||
|
a-- > b + c,
|
||||||
|
a + b-- > c,
|
||||||
|
a, b, c
|
||||||
|
);
|
||||||
|
})(1, 2, 3);
|
||||||
}
|
}
|
||||||
expect_exact: "function f(a,b){return a-- >b}";
|
expect_exact: "(function(a,b,c){console.log(a-- >b,a-- >b+c,a+b-- >c,a,b,c)})(1,2,3);"
|
||||||
|
expect_stdout: "false false false -1 1 3"
|
||||||
}
|
}
|
||||||
|
|
||||||
html_comment_in_greater_than_or_equal: {
|
html_comment_in_greater_than_or_equal: {
|
||||||
input: {
|
input: {
|
||||||
function f(a, b) { return a-- >= b; }
|
(function(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
a-- >= b,
|
||||||
|
a-- >= b + c,
|
||||||
|
a + b-- >= c,
|
||||||
|
a, b, c
|
||||||
|
);
|
||||||
|
})(1, 2, 3);
|
||||||
}
|
}
|
||||||
expect_exact: "function f(a,b){return a-- >=b}";
|
expect_exact: "(function(a,b,c){console.log(a-- >=b,a-- >=b+c,a+b-- >=c,a,b,c)})(1,2,3);"
|
||||||
|
expect_stdout: "false false false -1 1 3"
|
||||||
|
}
|
||||||
|
|
||||||
|
html_comment_in_right_shift: {
|
||||||
|
input: {
|
||||||
|
(function(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
a-- >> b,
|
||||||
|
a-- >> b + c,
|
||||||
|
a + b-- >> c,
|
||||||
|
a, b, c
|
||||||
|
);
|
||||||
|
})(1, 2, 3);
|
||||||
|
}
|
||||||
|
expect_exact: "(function(a,b,c){console.log(a-- >>b,a-- >>b+c,a+b-- >>c,a,b,c)})(1,2,3);"
|
||||||
|
expect_stdout: "0 0 0 -1 1 3"
|
||||||
|
}
|
||||||
|
|
||||||
|
html_comment_in_zero_fill_right_shift: {
|
||||||
|
input: {
|
||||||
|
(function(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
a-- >>> b,
|
||||||
|
a-- >>> b + c,
|
||||||
|
a + b-- >>> c,
|
||||||
|
a, b, c
|
||||||
|
);
|
||||||
|
})(1, 2, 3);
|
||||||
|
}
|
||||||
|
expect_exact: "(function(a,b,c){console.log(a-- >>>b,a-- >>>b+c,a+b-- >>>c,a,b,c)})(1,2,3);"
|
||||||
|
expect_stdout: "0 0 0 -1 1 3"
|
||||||
}
|
}
|
||||||
|
|
||||||
html_comment_in_string_literal: {
|
html_comment_in_string_literal: {
|
||||||
input: {
|
input: {
|
||||||
function f() { return "<!--HTML-->comment in<!--string literal-->"; }
|
console.log("<!--HTML-->comment in<!--string literal-->".length);
|
||||||
}
|
}
|
||||||
expect_exact: 'function f(){return"\\x3c!--HTML--\\x3ecomment in\\x3c!--string literal--\\x3e"}';
|
expect_exact: 'console.log("\\x3c!--HTML--\\x3ecomment in\\x3c!--string literal--\\x3e".length);'
|
||||||
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|||||||
1531
test/compress/ie8.js
1531
test/compress/ie8.js
File diff suppressed because it is too large
Load Diff
@@ -544,3 +544,32 @@ if_body_return_3: {
|
|||||||
"PASS",
|
"PASS",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3600: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
inline: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
(function() {
|
||||||
|
if ([ ][c++]); else return;
|
||||||
|
return void function() {
|
||||||
|
var b = --b, a = c = 42;
|
||||||
|
return c;
|
||||||
|
}();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
(function() {
|
||||||
|
if ([][c++]) b = --b, c = 42;
|
||||||
|
var b;
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ non_hoisted_function_after_return: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function foo(x) {
|
function foo(x) {
|
||||||
return x ? bar() : baz();
|
return (x ? bar : baz)();
|
||||||
function bar() { return 7 }
|
function bar() { return 7 }
|
||||||
function baz() { return 8 }
|
function baz() { return 8 }
|
||||||
}
|
}
|
||||||
@@ -90,13 +90,13 @@ non_hoisted_function_after_return_2a: {
|
|||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
|
"WARN: 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: 36",
|
||||||
"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: 36, count: 18",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +181,7 @@ non_hoisted_function_after_return_strict: {
|
|||||||
expect: {
|
expect: {
|
||||||
"use strict";
|
"use strict";
|
||||||
function foo(x) {
|
function foo(x) {
|
||||||
return x ? bar() : baz();
|
return (x ? bar : baz)();
|
||||||
function bar() { return 7 }
|
function bar() { return 7 }
|
||||||
function baz() { return 8 }
|
function baz() { return 8 }
|
||||||
}
|
}
|
||||||
@@ -248,13 +248,13 @@ non_hoisted_function_after_return_2a_strict: {
|
|||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,16]",
|
"WARN: 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: 47",
|
||||||
"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: 47, count: 29",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,3 +52,30 @@ chained_evaluation_2: {
|
|||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chained_evaluation_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: 10,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a = "long piece of string";
|
||||||
|
(function() {
|
||||||
|
var b = a, c;
|
||||||
|
c = f(b);
|
||||||
|
c.bar = b;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function() {
|
||||||
|
f("long piece of string").bar = "long piece of string";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ mangle_props: {
|
|||||||
obj[1/0],
|
obj[1/0],
|
||||||
obj["Infinity"],
|
obj["Infinity"],
|
||||||
obj[-1/0],
|
obj[-1/0],
|
||||||
obj[-1/0],
|
obj[-(1/0)],
|
||||||
obj["-Infinity"],
|
obj["-Infinity"],
|
||||||
obj[null],
|
obj[null],
|
||||||
obj["null"]
|
obj["null"]
|
||||||
|
|||||||
@@ -1,98 +1,111 @@
|
|||||||
issue_269_1: {
|
issue_269_1: {
|
||||||
options = {
|
options = {
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
f(
|
var x = {};
|
||||||
String(x),
|
console.log(
|
||||||
Number(x),
|
String(x),
|
||||||
Boolean(x),
|
Number(x),
|
||||||
|
Boolean(x),
|
||||||
|
|
||||||
String(),
|
String(),
|
||||||
Number(),
|
Number(),
|
||||||
Boolean()
|
Boolean()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
f(
|
var x = {};
|
||||||
x + '', +x, !!x,
|
console.log(
|
||||||
'', 0, false
|
x + "", +x, !!x,
|
||||||
);
|
"", 0, false
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_269_dangers: {
|
issue_269_dangers: {
|
||||||
options = {
|
options = {
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
f(
|
var x = {};
|
||||||
String(x, x),
|
console.log(
|
||||||
Number(x, x),
|
String(x, x),
|
||||||
Boolean(x, x)
|
Number(x, x),
|
||||||
);
|
Boolean(x, x)
|
||||||
}
|
);
|
||||||
expect: {
|
}
|
||||||
f(String(x, x), Number(x, x), Boolean(x, x));
|
expect: {
|
||||||
}
|
var x = {};
|
||||||
|
console.log(String(x, x), Number(x, x), Boolean(x, x));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_269_in_scope: {
|
issue_269_in_scope: {
|
||||||
options = {
|
options = {
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var String, Number, Boolean;
|
var String, Number, Boolean;
|
||||||
f(
|
var x = {};
|
||||||
String(x),
|
console.log(
|
||||||
Number(x, x),
|
String(x),
|
||||||
Boolean(x)
|
Number(x, x),
|
||||||
);
|
Boolean(x)
|
||||||
}
|
);
|
||||||
expect: {
|
}
|
||||||
var String, Number, Boolean;
|
expect: {
|
||||||
f(String(x), Number(x, x), Boolean(x));
|
var String, Number, Boolean;
|
||||||
}
|
var x = {};
|
||||||
|
console.log(String(x), Number(x, x), Boolean(x));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
strings_concat: {
|
strings_concat: {
|
||||||
options = {
|
options = {
|
||||||
|
strings: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
f(
|
var x = {};
|
||||||
String(x + 'str'),
|
console.log(
|
||||||
String('str' + x)
|
String(x + "str"),
|
||||||
);
|
String("str" + x)
|
||||||
}
|
);
|
||||||
expect: {
|
}
|
||||||
f(
|
expect: {
|
||||||
x + 'str',
|
var x = {};
|
||||||
'str' + x
|
console.log(
|
||||||
);
|
x + "str",
|
||||||
}
|
"str" + x
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
regexp: {
|
regexp: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
RegExp("foo");
|
RegExp("foo");
|
||||||
RegExp("bar", "ig");
|
RegExp("bar", "ig");
|
||||||
RegExp(foo);
|
RegExp(foo);
|
||||||
RegExp("bar", ig);
|
RegExp("bar", ig);
|
||||||
RegExp("should", "fail");
|
RegExp("should", "fail");
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
/foo/;
|
/foo/;
|
||||||
/bar/ig;
|
/bar/ig;
|
||||||
RegExp(foo);
|
RegExp(foo);
|
||||||
RegExp("bar", ig);
|
RegExp("bar", ig);
|
||||||
RegExp("should", "fail");
|
RegExp("should", "fail");
|
||||||
}
|
}
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
'WARN: Error converting RegExp("should","fail") [test/compress/issue-269.js:5,2]',
|
'WARN: Error converting RegExp("should","fail") [test/compress/issue-269.js:5,8]',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
|
}
|
||||||
@@ -16,7 +16,6 @@ wrongly_optimized: {
|
|||||||
function func() {
|
function func() {
|
||||||
foo();
|
foo();
|
||||||
}
|
}
|
||||||
// TODO: optimize to `func(), bar()`
|
func(), 1, bar();
|
||||||
(func(), 1) && bar();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ cond_5: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
some_condition() && some_other_condition() ? do_something() : alternate();
|
(some_condition() && some_other_condition() ? do_something : alternate)();
|
||||||
if (some_condition() && some_other_condition()) do_something();
|
if (some_condition() && some_other_condition()) do_something();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,6 +84,7 @@ wrongly_optimized: {
|
|||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
expression: true,
|
expression: true,
|
||||||
}
|
}
|
||||||
@@ -99,8 +100,8 @@ wrongly_optimized: {
|
|||||||
function func() {
|
function func() {
|
||||||
foo();
|
foo();
|
||||||
}
|
}
|
||||||
// TODO: optimize to `func(), bar()`
|
func(), 1;
|
||||||
if (func(), 1) bar();
|
bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,20 +53,23 @@ 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: {
|
||||||
"use strict";
|
function f() {
|
||||||
var c = a; c();
|
"use strict";
|
||||||
var d = a.b; d();
|
var c = a; c();
|
||||||
var e = eval; e();
|
var d = a.b; d();
|
||||||
|
var e = eval; e();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
"use strict";
|
function f() {
|
||||||
a();
|
"use strict";
|
||||||
(0, a.b)();
|
a();
|
||||||
(0, eval)();
|
(0, a.b)();
|
||||||
|
(0, eval)();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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";
|
||||||
|
|||||||
991
test/compress/join_vars.js
Normal file
991
test/compress/join_vars.js
Normal file
@@ -0,0 +1,991 @@
|
|||||||
|
join_vars_assign: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var y, x;
|
||||||
|
x = Object("PAS");
|
||||||
|
y = Object("S");
|
||||||
|
console.log(x + y);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x = Object("PAS"), y = Object("S");
|
||||||
|
console.log(x + y);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
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, a = { b: 0 };
|
||||||
|
switch (a.b) {
|
||||||
|
case 0:
|
||||||
|
c = "PASS";
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3786: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
var a = b;
|
||||||
|
b = 0;
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
var a = b;
|
||||||
|
b = 0;
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3788: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
function h() {
|
||||||
|
a = 42;
|
||||||
|
a = "PASS";
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
var b = h();
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b, a = "FAIL";
|
||||||
|
a = 42,
|
||||||
|
a = "PASS",
|
||||||
|
b = "PASS",
|
||||||
|
console.log(b),
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3789_1: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
c;
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
try {} catch (c) {
|
||||||
|
var a;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
c;
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
try {} catch (c) {
|
||||||
|
var a;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3789_2: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
c;
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
try {} catch (c) {
|
||||||
|
try {} catch (c) {
|
||||||
|
var a;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
c;
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
try {} catch (c) {
|
||||||
|
try {} catch (c) {
|
||||||
|
var a;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3791_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
join_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
switch (a) {
|
||||||
|
case console:
|
||||||
|
}
|
||||||
|
var a = a;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
switch (a = "PASS") {
|
||||||
|
case console:
|
||||||
|
}
|
||||||
|
var a = a;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3791_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b;
|
||||||
|
return b = a || g;
|
||||||
|
function g() {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(typeof f()());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
var b;
|
||||||
|
return b = a || g;
|
||||||
|
function g() {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(typeof f()());
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3795: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
loops: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
function f(b) {
|
||||||
|
for (var i = 1; b && i; --i) return 0;
|
||||||
|
a = "PASS";
|
||||||
|
}
|
||||||
|
var c = f(a = "");
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function(b) {
|
||||||
|
a = "";
|
||||||
|
a = "PASS";
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
if_body: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
if (x)
|
||||||
|
var b;
|
||||||
|
else
|
||||||
|
var c;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b, c;
|
||||||
|
if (x);
|
||||||
|
else;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if_switch: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
if (x) switch (y) {
|
||||||
|
case 1:
|
||||||
|
var b;
|
||||||
|
default:
|
||||||
|
var c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b, c;
|
||||||
|
if (x) switch (y) {
|
||||||
|
case 1:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_body_1: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
for (;x;)
|
||||||
|
var b;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var a, b; x;);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_body_2: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var a; x;)
|
||||||
|
var b;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var a, b; x;);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_body_3: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
for (var b; x;)
|
||||||
|
var c;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var a, b, c; x;);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_assignments_1: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
join_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(b, c, d) {
|
||||||
|
var a = b;
|
||||||
|
if (c) a = d;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
function g(b, c, d) {
|
||||||
|
var a = b;
|
||||||
|
if (c); else a = d;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(f("FAIL", 1, "PASS"), g("PASS", 1, "FAIL"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(b, c, d) {
|
||||||
|
var a = c ? d : b;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
function g(b, c, d) {
|
||||||
|
var a = c ? b : d;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(f("FAIL", 1, "PASS"), g("PASS", 1, "FAIL"));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_assignments_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
join_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f1(c, d) {
|
||||||
|
var a = b;
|
||||||
|
if (c) a = d;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
function f2(b, d) {
|
||||||
|
var a = b;
|
||||||
|
if (c) a = d;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
function f3(b, c) {
|
||||||
|
var a = b;
|
||||||
|
if (c) a = d;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f1(c, d) {
|
||||||
|
var a = b;
|
||||||
|
return c && (a = d), a;
|
||||||
|
}
|
||||||
|
function f2(b, d) {
|
||||||
|
var a = b;
|
||||||
|
return c && (a = d), a;
|
||||||
|
}
|
||||||
|
function f3(b, c) {
|
||||||
|
var a = b;
|
||||||
|
return c && (a = d), a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_assignments_3: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(b) {
|
||||||
|
var a = "PASS";
|
||||||
|
if (b) a = a;
|
||||||
|
return a;
|
||||||
|
}(0, 1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(b) {
|
||||||
|
var a = "PASS";
|
||||||
|
return b && (a = a), a;
|
||||||
|
}(0, 1));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
@@ -728,7 +728,7 @@ issue_2630_3: {
|
|||||||
(function() {
|
(function() {
|
||||||
(function f1() {
|
(function f1() {
|
||||||
f2();
|
f2();
|
||||||
--x >= 0 && f1({});
|
--x >= 0 && f1();
|
||||||
})(a++);
|
})(a++);
|
||||||
function f2() {
|
function f2() {
|
||||||
a++;
|
a++;
|
||||||
@@ -873,13 +873,13 @@ iife_func_side_effects: {
|
|||||||
function z() {
|
function z() {
|
||||||
console.log("z");
|
console.log("z");
|
||||||
}
|
}
|
||||||
(function(a, b) {
|
(function(b) {
|
||||||
return function() {
|
return function() {
|
||||||
console.log("FAIL");
|
console.log("FAIL");
|
||||||
} + b();
|
} + b();
|
||||||
})(x(), function() {
|
})((x(), function() {
|
||||||
return y();
|
return y();
|
||||||
}, z());
|
}), z());
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"x",
|
"x",
|
||||||
@@ -1155,3 +1155,302 @@ issue_3423_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
collapse_vars_repeated: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
comparisons: true,
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
hoist_funs: true,
|
||||||
|
if_return: true,
|
||||||
|
join_vars: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
loops: true,
|
||||||
|
properties: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f1() {
|
||||||
|
var dummy = 3, a = 5, unused = 2, a = 1, a = 3;
|
||||||
|
return -a;
|
||||||
|
}
|
||||||
|
function f2(x) {
|
||||||
|
var a = 3, a = x;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
(function(x) {
|
||||||
|
var a = "GOOD" + x, e = "BAD", k = "!", e = a;
|
||||||
|
console.log(e + k);
|
||||||
|
})("!"),
|
||||||
|
(function(x) {
|
||||||
|
var a = "GOOD" + x, e = "BAD" + x, k = "!", e = a;
|
||||||
|
console.log(e + k);
|
||||||
|
})("!");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f1() {
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
function f2(x) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
(function() {
|
||||||
|
console.log("GOOD!!");
|
||||||
|
})(),
|
||||||
|
(function() {
|
||||||
|
console.log("GOOD!!");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
chained_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
var c = a, c = b;
|
||||||
|
b++;
|
||||||
|
return c;
|
||||||
|
}(1, 2));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(b) {
|
||||||
|
var c = 1, c = b;
|
||||||
|
b++;
|
||||||
|
return c;
|
||||||
|
}(2));
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
replace_all_var_scope: {
|
||||||
|
rename = true
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
(function(r, a) {
|
||||||
|
switch (~a) {
|
||||||
|
case (b += a):
|
||||||
|
case a++:
|
||||||
|
}
|
||||||
|
})(--b, a);
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
(function(c) {
|
||||||
|
switch (~a) {
|
||||||
|
case (b += a):
|
||||||
|
case c++:
|
||||||
|
}
|
||||||
|
})((--b, a));
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "100 109"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1583: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: "strict",
|
||||||
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function m(t) {
|
||||||
|
(function(e) {
|
||||||
|
t = e();
|
||||||
|
})(function() {
|
||||||
|
return (function(a) {
|
||||||
|
return a;
|
||||||
|
})(function(a) {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function m(t) {
|
||||||
|
(function() {
|
||||||
|
(function() {
|
||||||
|
return (function() {
|
||||||
|
return function(a) {};
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issues_3267_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(x) {
|
||||||
|
x();
|
||||||
|
})(function() {
|
||||||
|
(function(i) {
|
||||||
|
if (i)
|
||||||
|
return console.log("PASS");
|
||||||
|
throw "FAIL";
|
||||||
|
})(Object());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
if (Object())
|
||||||
|
return console.log("PASS");
|
||||||
|
throw "FAIL";
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
trailing_argument_side_effects: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: "strict",
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
|
console.log(function(a, b) {
|
||||||
|
return b || "PASS";
|
||||||
|
}(f()));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
|
console.log(function(b) {
|
||||||
|
return b || "PASS";
|
||||||
|
}(void f()));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
recursive_iife_1: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function f(a, b) {
|
||||||
|
return b || f("FAIL", "PASS");
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function f(a, b) {
|
||||||
|
return b || f(0, "PASS");
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
recursive_iife_2: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function f(a, b) {
|
||||||
|
return b || f("FAIL", "PASS");
|
||||||
|
}(null, 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function f(a, b) {
|
||||||
|
return b || f(0, "PASS");
|
||||||
|
}(0, 0));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
recursive_iife_3: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: false,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1, c = "PASS";
|
||||||
|
(function() {
|
||||||
|
function f(b, d, e) {
|
||||||
|
a-- && f(null, 42, 0);
|
||||||
|
e && (c = "FAIL");
|
||||||
|
d && d.p;
|
||||||
|
}
|
||||||
|
var a_1 = f();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1, c = "PASS";
|
||||||
|
(function() {
|
||||||
|
(function f(b, d, e) {
|
||||||
|
a-- && f(0, 42, 0);
|
||||||
|
e && (c = "FAIL");
|
||||||
|
d && d.p;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3619: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: false,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1, b = "FAIL";
|
||||||
|
(function f(c, d) {
|
||||||
|
function g() {
|
||||||
|
d && (b = "PASS", 0 <= --a && g());
|
||||||
|
0 <= --a && f(0, "function");
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
})();
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1, b = "FAIL";
|
||||||
|
(function f(c, d) {
|
||||||
|
function g() {
|
||||||
|
d && (b = "PASS", 0 <= --a && g());
|
||||||
|
0 <= --a && f(0, "function");
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
})();
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ labels_1: {
|
|||||||
conditionals: true,
|
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) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ while_becomes_for: {
|
|||||||
while (foo()) bar();
|
while (foo()) bar();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; foo(); ) bar();
|
for (;foo();) bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ drop_if_break_1: {
|
|||||||
if (foo()) break;
|
if (foo()) break;
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; !foo(););
|
for (;!foo(););
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ drop_if_break_2: {
|
|||||||
if (foo()) break;
|
if (foo()) break;
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; bar() && !foo(););
|
for (;bar() && !foo(););
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ drop_if_break_4: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; bar() && (x(), y(), !foo());) z(), k();
|
for (;bar() && (x(), y(), !foo());) z(), k();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ drop_if_else_break_1: {
|
|||||||
for (;;) if (foo()) bar(); else break;
|
for (;;) if (foo()) bar(); else break;
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; foo(); ) bar();
|
for (;foo();) bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ drop_if_else_break_2: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; bar() && foo();) baz();
|
for (;bar() && foo();) baz();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ drop_if_else_break_3: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; bar() && foo();) {
|
for (;bar() && foo();) {
|
||||||
baz();
|
baz();
|
||||||
stuff1();
|
stuff1();
|
||||||
stuff2();
|
stuff2();
|
||||||
@@ -138,7 +138,7 @@ drop_if_else_break_4: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (; bar() && (x(), y(), foo());) baz(), z(), k();
|
for (;bar() && (x(), y(), foo());) baz(), z(), k();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,13 +523,13 @@ issue_2740_1: {
|
|||||||
loops: true,
|
loops: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
for (; ; ) break;
|
for (;;) break;
|
||||||
for (a(); ; ) break;
|
for (a();;) break;
|
||||||
for (; b(); ) break;
|
for (;b();) break;
|
||||||
for (c(); d(); ) break;
|
for (c(); d();) break;
|
||||||
for (; ; e()) break;
|
for (;;e()) break;
|
||||||
for (f(); ; g()) break;
|
for (f();; g()) break;
|
||||||
for (; h(); i()) break;
|
for (;h(); i()) break;
|
||||||
for (j(); k(); l()) break;
|
for (j(); k(); l()) break;
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
@@ -549,6 +549,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 +565,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++) {
|
||||||
@@ -574,9 +576,11 @@ issue_2740_3: {
|
|||||||
console.log(x, y);
|
console.log(x, y);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
L1: for (var x = 0; x < 3; x++)
|
L1: for (var x = 0; x < 3; x++) {
|
||||||
for (var y = 0; y < 2; y++)
|
var y = 0;
|
||||||
|
if (y < 2)
|
||||||
break L1;
|
break L1;
|
||||||
|
}
|
||||||
console.log(x, y);
|
console.log(x, y);
|
||||||
}
|
}
|
||||||
expect_stdout: "0 0"
|
expect_stdout: "0 0"
|
||||||
@@ -587,6 +591,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++) {
|
||||||
@@ -611,6 +616,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++) {
|
||||||
@@ -668,7 +674,7 @@ issue_3371: {
|
|||||||
function a() {
|
function a() {
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
}
|
}
|
||||||
for (; a(); );
|
for (;a(););
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
@@ -689,3 +695,241 @@ step: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
empty_for_in: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var a in [ 1, 2, 3 ]) {
|
||||||
|
var b = a + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: Dropping unused variable b [test/compress/loops.js:2,16]",
|
||||||
|
"INFO: Dropping unused loop variable a [test/compress/loops.js:1,17]",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
empty_for_in_used: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var a in [ 1, 2, 3 ]) {
|
||||||
|
var b = a + 1;
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var a in [ 1, 2, 3 ]);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: Dropping unused variable b [test/compress/loops.js:2,16]",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
empty_for_in_side_effects: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var a in {
|
||||||
|
foo: console.log("PASS")
|
||||||
|
}) {
|
||||||
|
var b = a + "bar";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: Dropping unused variable b [test/compress/loops.js:4,16]",
|
||||||
|
"INFO: Dropping unused loop variable a [test/compress/loops.js:1,17]",
|
||||||
|
"WARN: Side effects in object of for-in loop [test/compress/loops.js:1,17]",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3631_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
L: do {
|
||||||
|
for (;;) continue L;
|
||||||
|
var b = 1;
|
||||||
|
} while (b && c++);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
do {
|
||||||
|
var b;
|
||||||
|
} while (b && c++);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3631_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L: for (var a = 1; a--; console.log(b)) {
|
||||||
|
for (;;) continue L;
|
||||||
|
var b = "FAIL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var a = 1; a--; console.log(b))
|
||||||
|
var b;
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_if_break: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
try {
|
||||||
|
while (a) {
|
||||||
|
if (b) {
|
||||||
|
break;
|
||||||
|
var c = 42;
|
||||||
|
console.log(c);
|
||||||
|
} else {
|
||||||
|
var d = false;
|
||||||
|
throw d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log("E:", e);
|
||||||
|
}
|
||||||
|
console.log(a, b, c, d);
|
||||||
|
}
|
||||||
|
f(0, 0);
|
||||||
|
f(0, 1);
|
||||||
|
f(1, 0);
|
||||||
|
f(1, 1);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
try {
|
||||||
|
for (;a && !b;) {
|
||||||
|
var d = false;
|
||||||
|
throw d;
|
||||||
|
var c;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log("E:", e);
|
||||||
|
}
|
||||||
|
console.log(a, b, c, d);
|
||||||
|
}
|
||||||
|
f(0, 0);
|
||||||
|
f(0, 1);
|
||||||
|
f(1, 0);
|
||||||
|
f(1, 1);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0 0 undefined undefined",
|
||||||
|
"0 1 undefined undefined",
|
||||||
|
"E: false",
|
||||||
|
"1 0 undefined false",
|
||||||
|
"1 1 undefined undefined",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_return: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
while (a) return 42;
|
||||||
|
return "foo";
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
if (a) return 42;
|
||||||
|
return "foo";
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "foo 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3634_1: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 0;
|
||||||
|
L: while (++b < 2)
|
||||||
|
while (1)
|
||||||
|
if (b) break L;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 0;
|
||||||
|
L: for (;++b < 2;)
|
||||||
|
for (;1;)
|
||||||
|
if (b) break L;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3634_2: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 0;
|
||||||
|
L: while (++b < 2)
|
||||||
|
while (1)
|
||||||
|
if (!b)
|
||||||
|
continue L;
|
||||||
|
else
|
||||||
|
break L;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 0;
|
||||||
|
L: for (;++b < 2;)
|
||||||
|
for (;1;)
|
||||||
|
if (!b)
|
||||||
|
continue L;
|
||||||
|
else
|
||||||
|
break L;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
223
test/compress/objects.js
Normal file
223
test/compress/objects.js
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
duplicate_key: {
|
||||||
|
options = {
|
||||||
|
objects: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
a: 3,
|
||||||
|
};
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
a: 3,
|
||||||
|
b: 2,
|
||||||
|
};
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"a 3",
|
||||||
|
"b 2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicate_key_strict: {
|
||||||
|
options = {
|
||||||
|
objects: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var o = {
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
a: 3,
|
||||||
|
};
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var o = {
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
a: 3,
|
||||||
|
};
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicate_key_side_effect: {
|
||||||
|
options = {
|
||||||
|
objects: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {
|
||||||
|
a: 1,
|
||||||
|
b: o = 2,
|
||||||
|
a: 3,
|
||||||
|
};
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
a: 1,
|
||||||
|
b: o = 2,
|
||||||
|
a: 3,
|
||||||
|
};
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"a 3",
|
||||||
|
"b 2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicate_key_with_accessor: {
|
||||||
|
options = {
|
||||||
|
objects: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
[
|
||||||
|
{
|
||||||
|
a: 0,
|
||||||
|
b: 1,
|
||||||
|
a: 2,
|
||||||
|
set b(v) {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a: 3,
|
||||||
|
b: 4,
|
||||||
|
get a() {
|
||||||
|
return 5;
|
||||||
|
},
|
||||||
|
a: 6,
|
||||||
|
b: 7,
|
||||||
|
a: 8,
|
||||||
|
b: 9,
|
||||||
|
},
|
||||||
|
].forEach(function(o) {
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
[
|
||||||
|
{
|
||||||
|
a: 2,
|
||||||
|
b: 1,
|
||||||
|
set b(v) {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a: 3,
|
||||||
|
b: 4,
|
||||||
|
get a() {
|
||||||
|
return 5;
|
||||||
|
},
|
||||||
|
a: 8,
|
||||||
|
b: 9,
|
||||||
|
},
|
||||||
|
].forEach(function(o) {
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object_repeated: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
objects: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = { a: { b: 1 }, a: 1 };
|
||||||
|
console.log(
|
||||||
|
o + 1,
|
||||||
|
o.a + 1,
|
||||||
|
o.b + 1,
|
||||||
|
o.a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = { a: 1 };
|
||||||
|
console.log(
|
||||||
|
o + 1,
|
||||||
|
2,
|
||||||
|
o.b + 1,
|
||||||
|
NaN
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
numeric_literal: {
|
||||||
|
options = {
|
||||||
|
objects: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var obj = {
|
||||||
|
0: 0,
|
||||||
|
"-0": 1,
|
||||||
|
42: 2,
|
||||||
|
"42": 3,
|
||||||
|
0x25: 4,
|
||||||
|
"0x25": 5,
|
||||||
|
1E42: 6,
|
||||||
|
"1E42": 7,
|
||||||
|
"1e+42": 8,
|
||||||
|
};
|
||||||
|
console.log(obj[-0], obj[-""], obj["-0"]);
|
||||||
|
console.log(obj[42], obj["42"]);
|
||||||
|
console.log(obj[0x25], obj["0x25"], obj[37], obj["37"]);
|
||||||
|
console.log(obj[1E42], obj["1E42"], obj["1e+42"]);
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
'var obj = {',
|
||||||
|
' 0: 0,',
|
||||||
|
' "-0": 1,',
|
||||||
|
' 42: 3,',
|
||||||
|
' 37: 4,',
|
||||||
|
' o: 5,',
|
||||||
|
' 1e42: 8,',
|
||||||
|
' b: 7',
|
||||||
|
'};',
|
||||||
|
'',
|
||||||
|
'console.log(obj[-0], obj[-""], obj["-0"]);',
|
||||||
|
'',
|
||||||
|
'console.log(obj[42], obj["42"]);',
|
||||||
|
'',
|
||||||
|
'console.log(obj[37], obj["o"], obj[37], obj["37"]);',
|
||||||
|
'',
|
||||||
|
'console.log(obj[1e42], obj["b"], obj["1e+42"]);',
|
||||||
|
]
|
||||||
|
expect_stdout: [
|
||||||
|
"0 0 1",
|
||||||
|
"3 3",
|
||||||
|
"4 5 4 4",
|
||||||
|
"8 7 8",
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -817,6 +817,29 @@ issue_2208_5: {
|
|||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2208_6: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
properties: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a = 42;
|
||||||
|
console.log(("FAIL", {
|
||||||
|
p: function() {
|
||||||
|
return this.a;
|
||||||
|
}
|
||||||
|
}.p)());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = 42;
|
||||||
|
console.log(function() {
|
||||||
|
return this.a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
issue_2256: {
|
issue_2256: {
|
||||||
options = {
|
options = {
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -1120,558 +1143,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: {
|
||||||
@@ -1833,36 +1304,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,
|
||||||
|
|||||||
@@ -1193,6 +1193,7 @@ issue_3427: {
|
|||||||
assignments: true,
|
assignments: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
pure_getters: "strict",
|
pure_getters: "strict",
|
||||||
sequences: true,
|
sequences: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -1206,4 +1207,5 @@ issue_3427: {
|
|||||||
})(a || (a = {}));
|
})(a || (a = {}));
|
||||||
}
|
}
|
||||||
expect: {}
|
expect: {}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,6 +223,25 @@ unsafe_evaluate: {
|
|||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe_evaluate_defun: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
function f() {}
|
||||||
|
return ++f;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(NaN);
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|
||||||
unsafe_evaluate_side_effect_free_1: {
|
unsafe_evaluate_side_effect_free_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -1427,13 +1446,13 @@ defun_inline_3: {
|
|||||||
|
|
||||||
defun_call: {
|
defun_call: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
evaluate: true,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f() {
|
console.log(function f() {
|
||||||
return g() + h(1) - h(g(), 2, 3);
|
return g() + h(1) - h(g(), 2, 3);
|
||||||
function g() {
|
function g() {
|
||||||
return 4;
|
return 4;
|
||||||
@@ -1441,21 +1460,17 @@ defun_call: {
|
|||||||
function h(a) {
|
function h(a) {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
}
|
}());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f() {
|
console.log(1);
|
||||||
return 4 + h(1) - h(4);
|
|
||||||
function h(a) {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
defun_redefine: {
|
defun_redefine: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
evaluate: true,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -1480,7 +1495,7 @@ defun_redefine: {
|
|||||||
(function() {
|
(function() {
|
||||||
return 3;
|
return 3;
|
||||||
});
|
});
|
||||||
return 3 + 2;
|
return 5;
|
||||||
}
|
}
|
||||||
console.log(f());
|
console.log(f());
|
||||||
}
|
}
|
||||||
@@ -1517,7 +1532,7 @@ func_inline: {
|
|||||||
|
|
||||||
func_modified: {
|
func_modified: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
evaluate: true,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -1550,7 +1565,7 @@ func_modified: {
|
|||||||
(function() {
|
(function() {
|
||||||
return 4;
|
return 4;
|
||||||
});
|
});
|
||||||
return 1 + 2 + 4;
|
return 7;
|
||||||
}
|
}
|
||||||
console.log(f());
|
console.log(f());
|
||||||
}
|
}
|
||||||
@@ -2075,13 +2090,8 @@ issue_1670_6: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function(a) {
|
(function(a) {
|
||||||
switch (1) {
|
a = 1;
|
||||||
case a = 1:
|
console.log(a);
|
||||||
console.log(a);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log(2);
|
|
||||||
}
|
|
||||||
})(1);
|
})(1);
|
||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
@@ -2298,11 +2308,10 @@ redefine_farg_2: {
|
|||||||
console.log(f([]), g([]), h([]));
|
console.log(f([]), g([]), h([]));
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log((a = [], typeof a), "number",function(a, b) {
|
console.log(typeof [], "number",function(a, b) {
|
||||||
a = b;
|
a = b;
|
||||||
return typeof a;
|
return typeof a;
|
||||||
}([]));
|
}([]));
|
||||||
var a;
|
|
||||||
}
|
}
|
||||||
expect_stdout: "object number undefined"
|
expect_stdout: "object number undefined"
|
||||||
}
|
}
|
||||||
@@ -4580,7 +4589,7 @@ perf_8: {
|
|||||||
expect_stdout: "348150"
|
expect_stdout: "348150"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2485: {
|
issue_2485_1: {
|
||||||
options = {
|
options = {
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
@@ -4628,6 +4637,53 @@ issue_2485: {
|
|||||||
expect_stdout: "6"
|
expect_stdout: "6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2485_2: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var foo = function(bar) {
|
||||||
|
var n = function(a, b) {
|
||||||
|
return a + b;
|
||||||
|
};
|
||||||
|
var sumAll = function(arg) {
|
||||||
|
return arg.reduce(n, 0);
|
||||||
|
};
|
||||||
|
var runSumAll = function(arg) {
|
||||||
|
return sumAll(arg);
|
||||||
|
};
|
||||||
|
bar.baz = function(arg) {
|
||||||
|
var n = runSumAll(arg);
|
||||||
|
return (n.get = 1), n;
|
||||||
|
};
|
||||||
|
return bar;
|
||||||
|
};
|
||||||
|
var bar = foo({});
|
||||||
|
console.log(bar.baz([1, 2, 3]));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var foo = function(bar) {
|
||||||
|
var n = function(a, b) {
|
||||||
|
return a + b;
|
||||||
|
};
|
||||||
|
var runSumAll = function(arg) {
|
||||||
|
return arg.reduce(n, 0);
|
||||||
|
};
|
||||||
|
bar.baz = function(arg) {
|
||||||
|
var n = runSumAll(arg);
|
||||||
|
return (n.get = 1), n;
|
||||||
|
};
|
||||||
|
return bar;
|
||||||
|
};
|
||||||
|
var bar = foo({});
|
||||||
|
console.log(bar.baz([1, 2, 3]));
|
||||||
|
}
|
||||||
|
expect_stdout: "6"
|
||||||
|
}
|
||||||
|
|
||||||
issue_2455: {
|
issue_2455: {
|
||||||
options = {
|
options = {
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
@@ -4947,7 +5003,7 @@ defun_single_use_loop: {
|
|||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
for (var x, i = 2; --i >= 0; ) {
|
for (var x, i = 2; --i >= 0;) {
|
||||||
var y = x;
|
var y = x;
|
||||||
x = f;
|
x = f;
|
||||||
console.log(x === y);
|
console.log(x === y);
|
||||||
@@ -4955,7 +5011,7 @@ defun_single_use_loop: {
|
|||||||
function f() {};
|
function f() {};
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (var x, i = 2; --i >= 0; ) {
|
for (var x, i = 2; --i >= 0;) {
|
||||||
var y = x;
|
var y = x;
|
||||||
x = f;
|
x = f;
|
||||||
console.log(x === y);
|
console.log(x === y);
|
||||||
@@ -5444,8 +5500,7 @@ lvalues_def_1: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var b = 1;
|
var b = 1;
|
||||||
var a = b++;
|
var a = b++, b = NaN;
|
||||||
b = NaN;
|
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect_stdout: "1 NaN"
|
expect_stdout: "1 NaN"
|
||||||
@@ -5464,8 +5519,7 @@ lvalues_def_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var b = 1;
|
var b = 1;
|
||||||
var a = b += 1;
|
var a = b += 1, b = NaN;
|
||||||
b = NaN;
|
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect_stdout: "2 NaN"
|
expect_stdout: "2 NaN"
|
||||||
@@ -5516,9 +5570,7 @@ issue_2860_1: {
|
|||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function(a) {
|
console.log(1);
|
||||||
return 1 ^ a;
|
|
||||||
}());
|
|
||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
@@ -6522,17 +6574,17 @@ issue_3240_3: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function() {
|
(function() {
|
||||||
(function f(b) {
|
f();
|
||||||
|
function f(b) {
|
||||||
if (!f.a) f.a = 0;
|
if (!f.a) f.a = 0;
|
||||||
console.log(f.a.toString());
|
console.log(f.a.toString());
|
||||||
var g = function() {
|
(function() {
|
||||||
(b ? function() {} : function() {
|
(b ? function() {} : function() {
|
||||||
f.a++;
|
f.a++;
|
||||||
f(1);
|
f(1);
|
||||||
})();
|
})();
|
||||||
};
|
})();
|
||||||
g();
|
}
|
||||||
})();
|
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
@@ -6566,7 +6618,8 @@ issue_3240_4: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function() {
|
(function() {
|
||||||
(function f(b) {
|
f();
|
||||||
|
function f(b) {
|
||||||
if (!f.a) f.a = 0;
|
if (!f.a) f.a = 0;
|
||||||
console.log(f.a.toString());
|
console.log(f.a.toString());
|
||||||
(function() {
|
(function() {
|
||||||
@@ -6575,7 +6628,7 @@ issue_3240_4: {
|
|||||||
f(1);
|
f(1);
|
||||||
})();
|
})();
|
||||||
})();
|
})();
|
||||||
})();
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
@@ -6609,10 +6662,10 @@ issues_3267_1: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function(i) {
|
!function(i) {
|
||||||
if (i)
|
if (Object())
|
||||||
return console.log("PASS");
|
return console.log("PASS");
|
||||||
throw "FAIL";
|
throw "FAIL";
|
||||||
}(Object());
|
}();
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
@@ -6752,3 +6805,174 @@ issue_3377: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3509: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function a() {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
a();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3622: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "FAIL";
|
||||||
|
!function(b, a) {
|
||||||
|
a && (c = "PASS");
|
||||||
|
}(42, this);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "FAIL";
|
||||||
|
var a;
|
||||||
|
a = this,
|
||||||
|
!void (a && (c = "PASS")),
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3631_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
L: do {
|
||||||
|
for (;;) continue L;
|
||||||
|
var b = 1;
|
||||||
|
} while (b && c++);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
L: do {
|
||||||
|
for (;;) continue L;
|
||||||
|
var b = 1;
|
||||||
|
} while (b && c++);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3631_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L: for (var a = 1; a--; console.log(b)) {
|
||||||
|
for (;;) continue L;
|
||||||
|
var b = "FAIL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
L: for (var a = 1; a--; console.log(b)) {
|
||||||
|
for (;;) continue L;
|
||||||
|
var b = "FAIL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3666: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
var a = "FAIL";
|
||||||
|
} finally {
|
||||||
|
for (;!a;)
|
||||||
|
var c = a++;
|
||||||
|
var a = "PASS", b = c = "PASS";
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
var a = "FAIL";
|
||||||
|
} finally {
|
||||||
|
for (;!a;)
|
||||||
|
a++;
|
||||||
|
a = "PASS";
|
||||||
|
}
|
||||||
|
console.log(a, "PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3774: {
|
||||||
|
options = {
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var f = function() {
|
||||||
|
function g() {
|
||||||
|
if (!g.p) {
|
||||||
|
g.p = 1;
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return function() {
|
||||||
|
g();
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
f();
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var f = function() {
|
||||||
|
function g() {
|
||||||
|
if (!g.p) {
|
||||||
|
g.p = 1;
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return function() {
|
||||||
|
g();
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
f();
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,6 +36,20 @@ regexp_2: {
|
|||||||
expect_stdout: '["PASS","pass"]'
|
expect_stdout: '["PASS","pass"]'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regexp_properties: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(/abc/g.source, /abc/g.global, /abc/g.ignoreCase, /abc/g.lastIndex, /abc/g.multiline);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("abc", true, false, /abc/g.lastIndex, false);
|
||||||
|
}
|
||||||
|
expect_stdout: "abc true false 0 false"
|
||||||
|
}
|
||||||
|
|
||||||
issue_3434_1: {
|
issue_3434_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -172,3 +186,290 @@ issue_3434_3: {
|
|||||||
/\nfo\n[\n]o\bbb/;
|
/\nfo\n[\n]o\bbb/;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3434_4: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
[
|
||||||
|
[ "", RegExp("") ],
|
||||||
|
[ "/", RegExp("/") ],
|
||||||
|
[ "//", RegExp("//") ],
|
||||||
|
[ "\/", RegExp("\\/") ],
|
||||||
|
[ "///", RegExp("///") ],
|
||||||
|
[ "/\/", RegExp("/\\/") ],
|
||||||
|
[ "\//", RegExp("\\//") ],
|
||||||
|
[ "\\/", RegExp("\\\\/") ],
|
||||||
|
[ "////", RegExp("////") ],
|
||||||
|
[ "//\/", RegExp("//\\/") ],
|
||||||
|
[ "/\//", RegExp("/\\//") ],
|
||||||
|
[ "/\\/", RegExp("/\\\\/") ],
|
||||||
|
[ "\///", RegExp("\\///") ],
|
||||||
|
[ "\/\/", RegExp("\\/\\/") ],
|
||||||
|
[ "\\//", RegExp("\\\\//") ],
|
||||||
|
[ "\\\/", RegExp("\\\\\\/") ],
|
||||||
|
].forEach(function(test) {
|
||||||
|
console.log(test[1].test("\\"), test[1].test(test[0]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
[
|
||||||
|
[ "", /(?:)/ ],
|
||||||
|
[ "/", /\// ],
|
||||||
|
[ "//", /\/\// ],
|
||||||
|
[ "/", /\// ],
|
||||||
|
[ "///", /\/\/\// ],
|
||||||
|
[ "//", /\/\// ],
|
||||||
|
[ "//", /\/\// ],
|
||||||
|
[ "\\/", /\\\// ],
|
||||||
|
[ "////", /\/\/\/\// ],
|
||||||
|
[ "///", /\/\/\// ],
|
||||||
|
[ "///", /\/\/\// ],
|
||||||
|
[ "/\\/", /\/\\\// ],
|
||||||
|
[ "///", /\/\/\// ],
|
||||||
|
[ "//", /\/\// ],
|
||||||
|
[ "\\//", /\\\/\// ],
|
||||||
|
[ "\\/", /\\\// ],
|
||||||
|
].forEach(function(test) {
|
||||||
|
console.log(test[1].test("\\"), test[1].test(test[0]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"true true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
"false true",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
exec: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
while (/a/.exec("AAA"))
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (;null;)
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
exec_global: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
while (/a/g.exec("AAA"))
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (;null;)
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
test: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
while (/a/.test("AAA"))
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
while (false)
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_global: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
while (/a/g.test("AAA"))
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
while (false)
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
var_exec: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var r = /a/;
|
||||||
|
while (r.exec("AAA"))
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var r = /a/;
|
||||||
|
for (;null;)
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
var_exec_global: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var r = /a/g;
|
||||||
|
while (r.exec("aaa"))
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var r = /a/g;
|
||||||
|
for (;r.exec("aaa");)
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
var_test: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var r = /a/;
|
||||||
|
while (r.test("AAA"))
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var r = /a/;
|
||||||
|
while (false)
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
var_test_global: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var r = /a/g;
|
||||||
|
while (r.test("aaa"))
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var r = /a/g;
|
||||||
|
while (r.test("aaa"))
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_boolean: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
passes: 2,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
/b/.exec({}) && console.log("PASS");
|
||||||
|
/b/.test({}) && console.log("PASS");
|
||||||
|
/b/g.exec({}) && console.log("PASS");
|
||||||
|
/b/g.test({}) && console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
console.log("PASS");
|
||||||
|
console.log("PASS");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_state_between_evaluate: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
passes: 2,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
for (var a in /[abc4]/g.exec("a"))
|
||||||
|
return "PASS";
|
||||||
|
return "FAIL";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
for (var a in /[abc4]/g.exec("a"))
|
||||||
|
return "PASS";
|
||||||
|
return "FAIL";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -579,7 +579,7 @@ function_do_catch_ie8: {
|
|||||||
console.log(b, c);
|
console.log(b, c);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var t = 1, u = 1, y = 0;
|
var u = 1, y = 1, a = 0;
|
||||||
function c(c) {
|
function c(c) {
|
||||||
var d;
|
var d;
|
||||||
do {
|
do {
|
||||||
@@ -587,7 +587,7 @@ function_do_catch_ie8: {
|
|||||||
try {
|
try {
|
||||||
var e = void 0;
|
var e = void 0;
|
||||||
} catch (i) {
|
} catch (i) {
|
||||||
--t && w("ddddddddeeeeeeegggggggggiiiiilllllllnnnnntuuuuuuuuyyyyyyy");
|
--u && w("ddddddddeeeeeeegggggggggiiiiilllllllnnnnntuuuuuuuuyyyyyyy");
|
||||||
0;
|
0;
|
||||||
0;
|
0;
|
||||||
0;
|
0;
|
||||||
@@ -596,18 +596,146 @@ function_do_catch_ie8: {
|
|||||||
d[1];
|
d[1];
|
||||||
} catch (l) {
|
} catch (l) {
|
||||||
var g;
|
var g;
|
||||||
switch(function x() {
|
switch (function n() {
|
||||||
y++;
|
a++;
|
||||||
}()) {
|
}()) {
|
||||||
case e + --g:
|
case e + --g:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (n) {}
|
} catch (t) {}
|
||||||
} while (--d);
|
} while (--d);
|
||||||
u--;
|
y--;
|
||||||
}
|
}
|
||||||
c();
|
c();
|
||||||
console.log(u, y);
|
console.log(y, a);
|
||||||
}
|
}
|
||||||
expect_stdout: "0 1"
|
expect_stdout: "0 1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3480: {
|
||||||
|
rename = true,
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var d, a, b, c = "FAIL";
|
||||||
|
(function b() {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
c = "PASS";
|
||||||
|
} catch (b) {
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var d, a, b, c = "FAIL";
|
||||||
|
(function n() {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
c = "PASS";
|
||||||
|
} catch (c) {}
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3480_ie8: {
|
||||||
|
rename = true,
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var d, a, b, c = "FAIL";
|
||||||
|
(function b() {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
c = "PASS";
|
||||||
|
} catch (b) {
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var d, a, b, c = "FAIL";
|
||||||
|
(function b() {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
c = "PASS";
|
||||||
|
} catch (b) {}
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3480_toplevel: {
|
||||||
|
rename = true,
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var d, a, b, c = "FAIL";
|
||||||
|
(function b() {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
c = "PASS";
|
||||||
|
} catch (b) {
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c, n, o, t = "FAIL";
|
||||||
|
(function c() {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
t = "PASS";
|
||||||
|
} catch (c) {}
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3480_ie8_toplevel: {
|
||||||
|
rename = true,
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var d, a, b, c = "FAIL";
|
||||||
|
(function b() {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
c = "PASS";
|
||||||
|
} catch (b) {
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c, n, o, t = "FAIL";
|
||||||
|
(function o() {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
t = "PASS";
|
||||||
|
} catch (o) {}
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -910,15 +910,23 @@ call: {
|
|||||||
console.log(this === b ? "bar" : "baz");
|
console.log(this === b ? "bar" : "baz");
|
||||||
};
|
};
|
||||||
(a, b)();
|
(a, b)();
|
||||||
|
(a, b).c();
|
||||||
(a, b.c)();
|
(a, b.c)();
|
||||||
|
(a, b)["c"]();
|
||||||
|
(a, b["c"])();
|
||||||
(a, function() {
|
(a, function() {
|
||||||
console.log(this === a);
|
console.log(this === a);
|
||||||
})();
|
})();
|
||||||
new (a, b)();
|
new (a, b)();
|
||||||
|
new (a, b).c();
|
||||||
new (a, b.c)();
|
new (a, b.c)();
|
||||||
|
new (a, b)["c"]();
|
||||||
|
new (a, b["c"])();
|
||||||
new (a, function() {
|
new (a, function() {
|
||||||
console.log(this === a);
|
console.log(this === a);
|
||||||
})();
|
})();
|
||||||
|
console.log(typeof (a, b).c);
|
||||||
|
console.log(typeof (a, b)["c"]);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = function() {
|
var a = function() {
|
||||||
@@ -931,23 +939,39 @@ call: {
|
|||||||
console.log(this === b ? "bar" : "baz");
|
console.log(this === b ? "bar" : "baz");
|
||||||
},
|
},
|
||||||
b(),
|
b(),
|
||||||
|
b.c(),
|
||||||
(a, b.c)(),
|
(a, b.c)(),
|
||||||
|
b["c"](),
|
||||||
|
(a, b["c"])(),
|
||||||
function() {
|
function() {
|
||||||
console.log(this === a);
|
console.log(this === a);
|
||||||
}(),
|
}(),
|
||||||
new b(),
|
new b(),
|
||||||
new b.c(),
|
new b.c(),
|
||||||
|
new b.c(),
|
||||||
|
new b["c"](),
|
||||||
|
new b["c"](),
|
||||||
new function() {
|
new function() {
|
||||||
console.log(this === a);
|
console.log(this === a);
|
||||||
}();
|
}(),
|
||||||
|
console.log((a, typeof b.c)),
|
||||||
|
console.log((a, typeof b["c"]));
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"foo",
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"baz",
|
||||||
|
"bar",
|
||||||
"baz",
|
"baz",
|
||||||
"true",
|
"true",
|
||||||
"foo",
|
"foo",
|
||||||
"baz",
|
"baz",
|
||||||
|
"baz",
|
||||||
|
"baz",
|
||||||
|
"baz",
|
||||||
"false",
|
"false",
|
||||||
|
"function",
|
||||||
|
"function",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1006,3 +1030,85 @@ angularjs_chain: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3490_1: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
inline: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 42, c = "FAIL";
|
||||||
|
if ({
|
||||||
|
3: function() {
|
||||||
|
var a;
|
||||||
|
return (a && a.p) < this;
|
||||||
|
}(),
|
||||||
|
}) c = "PASS";
|
||||||
|
if (b) while ("" == typeof d);
|
||||||
|
console.log(c, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 42, c = "FAIL";
|
||||||
|
if (function() {
|
||||||
|
var a;
|
||||||
|
a && a.p;
|
||||||
|
}(), c = "PASS", b) while ("" == typeof d);
|
||||||
|
console.log(c, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3490_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 42, c = "FAIL";
|
||||||
|
if ({
|
||||||
|
3: function() {
|
||||||
|
var a;
|
||||||
|
return (a && a.p) < this;
|
||||||
|
}(),
|
||||||
|
}) c = "PASS";
|
||||||
|
if (b) for (; "" == typeof d;);
|
||||||
|
console.log(c, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 42, c = "FAIL";
|
||||||
|
for (function() {
|
||||||
|
var a;
|
||||||
|
}(), c = "PASS", b; "" == typeof d;);
|
||||||
|
console.log(c, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3703: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
sequences: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
while ((a = "PASS", 0).foo = 0);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
while (a = "PASS", (0).foo = 0);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
277
test/compress/side_effects.js
Normal file
277
test/compress/side_effects.js
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
accessor: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({
|
||||||
|
get a() {},
|
||||||
|
set a(v){
|
||||||
|
this.b = 2;
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2233_1: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
Array.isArray;
|
||||||
|
Boolean;
|
||||||
|
console.log;
|
||||||
|
Date;
|
||||||
|
decodeURI;
|
||||||
|
decodeURIComponent;
|
||||||
|
encodeURI;
|
||||||
|
encodeURIComponent;
|
||||||
|
Error.name;
|
||||||
|
escape;
|
||||||
|
eval;
|
||||||
|
EvalError;
|
||||||
|
Function.length;
|
||||||
|
isFinite;
|
||||||
|
isNaN;
|
||||||
|
JSON;
|
||||||
|
Math.random;
|
||||||
|
Number.isNaN;
|
||||||
|
parseFloat;
|
||||||
|
parseInt;
|
||||||
|
RegExp;
|
||||||
|
Object.defineProperty;
|
||||||
|
String.fromCharCode;
|
||||||
|
RangeError;
|
||||||
|
ReferenceError;
|
||||||
|
SyntaxError;
|
||||||
|
TypeError;
|
||||||
|
unescape;
|
||||||
|
URIError;
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
global_timeout_and_interval_symbols: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
// These global symbols do not exist in the test sandbox
|
||||||
|
// and must be tested separately.
|
||||||
|
clearInterval;
|
||||||
|
clearTimeout;
|
||||||
|
setInterval;
|
||||||
|
setTimeout;
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2233_2: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var RegExp;
|
||||||
|
Array.isArray;
|
||||||
|
RegExp;
|
||||||
|
UndeclaredGlobal;
|
||||||
|
function foo() {
|
||||||
|
var Number;
|
||||||
|
AnotherUndeclaredGlobal;
|
||||||
|
Math.sin;
|
||||||
|
Number.isNaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var RegExp;
|
||||||
|
UndeclaredGlobal;
|
||||||
|
function foo() {
|
||||||
|
var Number;
|
||||||
|
AnotherUndeclaredGlobal;
|
||||||
|
Number.isNaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2233_3: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var RegExp;
|
||||||
|
Array.isArray;
|
||||||
|
RegExp;
|
||||||
|
UndeclaredGlobal;
|
||||||
|
function foo() {
|
||||||
|
var Number;
|
||||||
|
AnotherUndeclaredGlobal;
|
||||||
|
Math.sin;
|
||||||
|
Number.isNaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
UndeclaredGlobal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
global_fns: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
Boolean(1, 2);
|
||||||
|
decodeURI(1, 2);
|
||||||
|
decodeURIComponent(1, 2);
|
||||||
|
Date(1, 2);
|
||||||
|
encodeURI(1, 2);
|
||||||
|
encodeURIComponent(1, 2);
|
||||||
|
Error(1, 2);
|
||||||
|
escape(1, 2);
|
||||||
|
EvalError(1, 2);
|
||||||
|
isFinite(1, 2);
|
||||||
|
isNaN(1, 2);
|
||||||
|
Number(1, 2);
|
||||||
|
Object(1, 2);
|
||||||
|
parseFloat(1, 2);
|
||||||
|
parseInt(1, 2);
|
||||||
|
RangeError(1, 2);
|
||||||
|
ReferenceError(1, 2);
|
||||||
|
String(1, 2);
|
||||||
|
SyntaxError(1, 2);
|
||||||
|
TypeError(1, 2);
|
||||||
|
unescape(1, 2);
|
||||||
|
URIError(1, 2);
|
||||||
|
try {
|
||||||
|
Function(1, 2);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.name);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
RegExp(1, 2);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.name);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Array(NaN);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
Function(1, 2);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.name);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
RegExp(1, 2);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.name);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Array(NaN);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"SyntaxError",
|
||||||
|
"SyntaxError",
|
||||||
|
"RangeError",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_builtin_1: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(!w).constructor(x);
|
||||||
|
Math.abs(y);
|
||||||
|
[ 1, 2, z ].valueOf();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
w, x;
|
||||||
|
y;
|
||||||
|
z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_builtin_2: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
constructor.call(o, 42);
|
||||||
|
__defineGetter__.call(o, "foo", function() {
|
||||||
|
return o.p;
|
||||||
|
});
|
||||||
|
__defineSetter__.call(o, void 0, function(a) {
|
||||||
|
o.p = a;
|
||||||
|
});
|
||||||
|
console.log(typeof o, o.undefined = "PASS", o.foo);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {};
|
||||||
|
constructor.call(o, 42);
|
||||||
|
__defineGetter__.call(o, "foo", function() {
|
||||||
|
return o.p;
|
||||||
|
});
|
||||||
|
__defineSetter__.call(o, void 0, function(a) {
|
||||||
|
o.p = a;
|
||||||
|
});
|
||||||
|
console.log(typeof o, o.undefined = "PASS", o.foo);
|
||||||
|
}
|
||||||
|
expect_stdout: "object PASS PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_string_replace: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"foo".replace("f", function() {
|
||||||
|
console.log("PASS");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"foo".replace("f", function() {
|
||||||
|
console.log("PASS");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_value: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(1, [2, foo()], 3, {a:1, b:bar()});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
foo(), bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -261,13 +261,13 @@ drop_default_1: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 'bar': baz();
|
case "bar": baz();
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 'bar': baz();
|
case "bar": baz();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,14 +279,14 @@ drop_default_2: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 'bar': baz(); break;
|
case "bar": baz(); break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 'bar': baz();
|
case "bar": baz();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -298,7 +298,7 @@ keep_default: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 'bar': baz();
|
case "bar": baz();
|
||||||
default:
|
default:
|
||||||
something();
|
something();
|
||||||
break;
|
break;
|
||||||
@@ -306,7 +306,7 @@ keep_default: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 'bar': baz();
|
case "bar": baz();
|
||||||
default:
|
default:
|
||||||
something();
|
something();
|
||||||
}
|
}
|
||||||
@@ -347,25 +347,103 @@ issue_1663: {
|
|||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
drop_case: {
|
drop_case_1: {
|
||||||
options = {
|
options = {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 'bar': baz(); break;
|
case "bar": baz(); break;
|
||||||
case 'moo':
|
case "moo":
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 'bar': baz();
|
case "bar": baz();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drop_case_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (foo) {
|
||||||
|
case "bar":
|
||||||
|
bar();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case "moo":
|
||||||
|
moo();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch (foo) {
|
||||||
|
case "bar":
|
||||||
|
bar();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
moo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_case_3: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "PASS";
|
||||||
|
switch ({}.p) {
|
||||||
|
default:
|
||||||
|
case void 0:
|
||||||
|
break;
|
||||||
|
case c = "FAIL":
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "PASS";
|
||||||
|
switch ({}.p) {
|
||||||
|
default:
|
||||||
|
case void 0:
|
||||||
|
break;
|
||||||
|
case c = "FAIL":
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_case_4: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (0) {
|
||||||
|
case [ a, typeof b ]:
|
||||||
|
default:
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch (0) {
|
||||||
|
case [ a, typeof b ]:
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
keep_case: {
|
keep_case: {
|
||||||
options = {
|
options = {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
@@ -373,14 +451,14 @@ keep_case: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 'bar': baz(); break;
|
case "bar": baz(); break;
|
||||||
case moo:
|
case moo:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 'bar': baz(); break;
|
case "bar": baz(); break;
|
||||||
case moo:
|
case moo:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -539,7 +617,7 @@ issue_1679: {
|
|||||||
f();
|
f();
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: "99 8"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1680_1: {
|
issue_1680_1: {
|
||||||
@@ -864,3 +942,89 @@ issue_1750: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "0 2"
|
expect_stdout: "0 2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drop_switch_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (foo) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case "bar":
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
foo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_switch_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (foo) {
|
||||||
|
default:
|
||||||
|
case "bar":
|
||||||
|
baz();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
foo;
|
||||||
|
baz();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_switch_3: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
switch (0) {
|
||||||
|
default:
|
||||||
|
return "PASS";
|
||||||
|
case 1:
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
switch (0) {
|
||||||
|
default:
|
||||||
|
return "PASS";
|
||||||
|
case 1:
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_switch_4: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
switch (0) {
|
||||||
|
default:
|
||||||
|
case a:
|
||||||
|
var b = a = "PASS";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
0;
|
||||||
|
var b = a = "PASS";
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
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) {
|
||||||
@@ -103,6 +104,7 @@ if_return: {
|
|||||||
booleans: true,
|
booleans: true,
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
|
passes: 2,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,9 +166,7 @@ duplicate_lambda_arg_name: {
|
|||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function long_name(long_name) {
|
console.log("undefined");
|
||||||
return typeof long_name;
|
|
||||||
}());
|
|
||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
}
|
}
|
||||||
@@ -295,3 +293,167 @@ issue_2728_6: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "function undefined"
|
expect_stdout: "function undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typeof_defined_1: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
typeofs: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"undefined" == typeof A && A;
|
||||||
|
"undefined" != typeof A && A;
|
||||||
|
"undefined" == typeof A || A;
|
||||||
|
"undefined" != typeof A || A;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"undefined" == typeof A && A;
|
||||||
|
"undefined" != typeof A || A;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typeof_defined_2: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
typeofs: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"function" == typeof A && A;
|
||||||
|
"function" != typeof A && A;
|
||||||
|
"function" == typeof A || A;
|
||||||
|
"function" != typeof A || A;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"function" != typeof A && A;
|
||||||
|
"function" == typeof A || A;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typeof_defined_3: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
typeofs: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"undefined" == typeof A && "undefined" == typeof B && (A, B);
|
||||||
|
"undefined" == typeof A && "undefined" != typeof B && (A, B);
|
||||||
|
"undefined" != typeof A && "undefined" == typeof B && (A, B);
|
||||||
|
"undefined" != typeof A && "undefined" != typeof B && (A, B);
|
||||||
|
"undefined" == typeof A && "undefined" == typeof B || (A, B);
|
||||||
|
"undefined" == typeof A && "undefined" != typeof B || (A, B);
|
||||||
|
"undefined" != typeof A && "undefined" == typeof B || (A, B);
|
||||||
|
"undefined" != typeof A && "undefined" != typeof B || (A, B);
|
||||||
|
"undefined" == typeof A || "undefined" == typeof B && (A, B);
|
||||||
|
"undefined" == typeof A || "undefined" != typeof B && (A, B);
|
||||||
|
"undefined" != typeof A || "undefined" == typeof B && (A, B);
|
||||||
|
"undefined" != typeof A || "undefined" != typeof B && (A, B);
|
||||||
|
"undefined" == typeof A || "undefined" == typeof B || (A, B);
|
||||||
|
"undefined" == typeof A || "undefined" != typeof B || (A, B);
|
||||||
|
"undefined" != typeof A || "undefined" == typeof B || (A, B);
|
||||||
|
"undefined" != typeof A || "undefined" != typeof B || (A, B);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"undefined" == typeof A && "undefined" == typeof B && (A, B);
|
||||||
|
"undefined" == typeof A && "undefined" != typeof B && A;
|
||||||
|
"undefined" != typeof A && "undefined" == typeof B && B;
|
||||||
|
"undefined" == typeof A && "undefined" == typeof B || (A, B);
|
||||||
|
"undefined" == typeof A && "undefined" != typeof B || (A, B);
|
||||||
|
"undefined" != typeof A && "undefined" == typeof B || (A, B);
|
||||||
|
"undefined" != typeof A && "undefined" != typeof B || (A, B);
|
||||||
|
"undefined" == typeof A || "undefined" == typeof B && B;
|
||||||
|
"undefined" != typeof A || "undefined" == typeof B && (A, B);
|
||||||
|
"undefined" != typeof A || "undefined" != typeof B && A;
|
||||||
|
"undefined" == typeof A || "undefined" != typeof B || B;
|
||||||
|
"undefined" != typeof A || "undefined" == typeof B || A;
|
||||||
|
"undefined" != typeof A || "undefined" != typeof B || (A, B);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typeof_defined_4: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
typeofs: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"object" == typeof A && "object" == typeof B && (A, B);
|
||||||
|
"object" == typeof A && "object" != typeof B && (A, B);
|
||||||
|
"object" != typeof A && "object" == typeof B && (A, B);
|
||||||
|
"object" != typeof A && "object" != typeof B && (A, B);
|
||||||
|
"object" == typeof A && "object" == typeof B || (A, B);
|
||||||
|
"object" == typeof A && "object" != typeof B || (A, B);
|
||||||
|
"object" != typeof A && "object" == typeof B || (A, B);
|
||||||
|
"object" != typeof A && "object" != typeof B || (A, B);
|
||||||
|
"object" == typeof A || "object" == typeof B && (A, B);
|
||||||
|
"object" == typeof A || "object" != typeof B && (A, B);
|
||||||
|
"object" != typeof A || "object" == typeof B && (A, B);
|
||||||
|
"object" != typeof A || "object" != typeof B && (A, B);
|
||||||
|
"object" == typeof A || "object" == typeof B || (A, B);
|
||||||
|
"object" == typeof A || "object" != typeof B || (A, B);
|
||||||
|
"object" != typeof A || "object" == typeof B || (A, B);
|
||||||
|
"object" != typeof A || "object" != typeof B || (A, B);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"object" == typeof A && "object" != typeof B && B;
|
||||||
|
"object" != typeof A && "object" == typeof B && A;
|
||||||
|
"object" != typeof A && "object" != typeof B && (A, B);
|
||||||
|
"object" == typeof A && "object" == typeof B || (A, B);
|
||||||
|
"object" == typeof A && "object" != typeof B || (A, B);
|
||||||
|
"object" != typeof A && "object" == typeof B || (A, B);
|
||||||
|
"object" != typeof A && "object" != typeof B || (A, B);
|
||||||
|
"object" == typeof A || "object" == typeof B && A;
|
||||||
|
"object" == typeof A || "object" != typeof B && (A, B);
|
||||||
|
"object" != typeof A || "object" != typeof B && B;
|
||||||
|
"object" == typeof A || "object" == typeof B || (A, B);
|
||||||
|
"object" == typeof A || "object" != typeof B || A;
|
||||||
|
"object" != typeof A || "object" == typeof B || B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emberjs_global: {
|
||||||
|
options = {
|
||||||
|
comparisons: true,
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
passes: 2,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
typeofs: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
if (typeof A === "object") {
|
||||||
|
a = A;
|
||||||
|
} else if (typeof B === "object") {
|
||||||
|
a = B;
|
||||||
|
} else {
|
||||||
|
throw new Error("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
if ("object" != typeof A && "object" != typeof B)
|
||||||
|
throw new 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"
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,6 +16,81 @@ unicode_parse_variables: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unicode_escaped_identifier: {
|
||||||
|
input: {
|
||||||
|
var \u0061 = "\ud800\udc00";
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="\ud800\udc00";console.log(a);'
|
||||||
|
expect_stdout: "\ud800\udc00"
|
||||||
|
}
|
||||||
|
|
||||||
|
unicode_identifier_ascii_only: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var \u0061 = "testing \udbc4\udd11";
|
||||||
|
var bar = "h\u0065llo";
|
||||||
|
console.log(a, \u0062\u0061r);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="testing \\udbc4\\udd11";var bar="hello";console.log(a,bar);'
|
||||||
|
expect_stdout: "testing \udbc4\udd11 hello"
|
||||||
|
}
|
||||||
|
|
||||||
|
unicode_string_literals: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "6 length unicode character: \udbc4\udd11";
|
||||||
|
console.log(\u0061);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="6 length unicode character: \\udbc4\\udd11";console.log(a);'
|
||||||
|
expect_stdout: "6 length unicode character: \udbc4\udd11"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_escape_style: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "\x01";
|
||||||
|
var \ua0081 = "\x10"; // \u0081 only in ID_Continue
|
||||||
|
var \u0100 = "\u0100";
|
||||||
|
var \u1000 = "\u1000";
|
||||||
|
var \u1000 = "\ud800\udc00";
|
||||||
|
var \u3f80 = "\udbc0\udc00";
|
||||||
|
console.log(\u0061, \ua0081, \u0100, \u1000, \u3f80);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="\\x01";var \\ua0081="\\x10";var \\u0100="\\u0100";var \\u1000="\\u1000";var \\u1000="\\ud800\\udc00";var \\u3f80="\\udbc0\\udc00";console.log(a,\\ua0081,\\u0100,\\u1000,\\u3f80);'
|
||||||
|
expect_stdout: "\u0001 \u0010 \u0100 \ud800\udc00 \udbc0\udc00"
|
||||||
|
}
|
||||||
|
|
||||||
|
escape_non_escaped_identifier: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var µþ = "µþ";
|
||||||
|
console.log(\u00b5þ);
|
||||||
|
}
|
||||||
|
expect_exact: 'var \\u00b5\\u00fe="\\xb5\\xfe";console.log(\\u00b5\\u00fe);'
|
||||||
|
expect_stdout: "µþ"
|
||||||
|
}
|
||||||
|
|
||||||
|
non_escape_2_non_escape: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var µþ = "µþ";
|
||||||
|
console.log(\u00b5þ);
|
||||||
|
}
|
||||||
|
expect_exact: 'var µþ="µþ";console.log(µþ);'
|
||||||
|
expect_stdout: "µþ"
|
||||||
|
}
|
||||||
|
|
||||||
issue_2242_1: {
|
issue_2242_1: {
|
||||||
beautify = {
|
beautify = {
|
||||||
ascii_only: false,
|
ascii_only: false,
|
||||||
@@ -24,6 +99,7 @@ issue_2242_1: {
|
|||||||
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||||
}
|
}
|
||||||
expect_exact: 'console.log("\\ud83d","\\ude00","\ud83d\ude00","\\ud83d@\\ude00");'
|
expect_exact: 'console.log("\\ud83d","\\ude00","\ud83d\ude00","\\ud83d@\\ude00");'
|
||||||
|
expect_stdout: "\ud83d \ude00 \ud83d\ude00 \ud83d@\ude00"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2242_2: {
|
issue_2242_2: {
|
||||||
@@ -34,6 +110,7 @@ issue_2242_2: {
|
|||||||
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||||
}
|
}
|
||||||
expect_exact: 'console.log("\\ud83d","\\ude00","\\ud83d\\ude00","\\ud83d@\\ude00");'
|
expect_exact: 'console.log("\\ud83d","\\ude00","\\ud83d\\ude00","\\ud83d@\\ude00");'
|
||||||
|
expect_stdout: "\ud83d \ude00 \ud83d\ude00 \ud83d@\ude00"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2242_3: {
|
issue_2242_3: {
|
||||||
@@ -44,6 +121,7 @@ issue_2242_3: {
|
|||||||
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||||
}
|
}
|
||||||
expect_exact: 'console.log("\\ud83d"+"\\ude00","\\ud83d"+"@"+"\\ude00");'
|
expect_exact: 'console.log("\\ud83d"+"\\ude00","\\ud83d"+"@"+"\\ude00");'
|
||||||
|
expect_stdout: "\ud83d\ude00 \ud83d@\ude00"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2242_4: {
|
issue_2242_4: {
|
||||||
@@ -54,6 +132,7 @@ issue_2242_4: {
|
|||||||
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||||
}
|
}
|
||||||
expect_exact: 'console.log("\ud83d\ude00","\\ud83d@\\ude00");'
|
expect_exact: 'console.log("\ud83d\ude00","\\ud83d@\\ude00");'
|
||||||
|
expect_stdout: "\ud83d\ude00 \ud83d@\ude00"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2569: {
|
issue_2569: {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
exports["Compressor"] = Compressor;
|
exports["Compressor"] = Compressor;
|
||||||
exports["defaults"] = defaults;
|
exports["defaults"] = defaults;
|
||||||
exports["JS_Parse_Error"] = JS_Parse_Error;
|
exports["JS_Parse_Error"] = JS_Parse_Error;
|
||||||
|
exports["List"] = List;
|
||||||
exports["mangle_properties"] = mangle_properties;
|
exports["mangle_properties"] = mangle_properties;
|
||||||
exports["minify"] = minify;
|
exports["minify"] = minify;
|
||||||
exports["OutputStream"] = OutputStream;
|
exports["OutputStream"] = OutputStream;
|
||||||
@@ -8,6 +9,8 @@ exports["parse"] = parse;
|
|||||||
exports["push_uniq"] = push_uniq;
|
exports["push_uniq"] = push_uniq;
|
||||||
exports["reserve_quoted_keys"] = reserve_quoted_keys;
|
exports["reserve_quoted_keys"] = reserve_quoted_keys;
|
||||||
exports["string_template"] = string_template;
|
exports["string_template"] = string_template;
|
||||||
|
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;
|
||||||
|
|||||||
17
test/input/issue-1482/beautify.js
Normal file
17
test/input/issue-1482/beautify.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
if (x) foo();
|
||||||
|
|
||||||
|
if (x) foo(); else baz();
|
||||||
|
|
||||||
|
if (x) foo(); else if (y) bar(); else baz();
|
||||||
|
|
||||||
|
if (x) if (y) foo(); else bar(); else baz();
|
||||||
|
|
||||||
|
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
||||||
|
|
||||||
|
function f() {
|
||||||
|
if (x) foo();
|
||||||
|
if (x) foo(); else baz();
|
||||||
|
if (x) foo(); else if (y) bar(); else baz();
|
||||||
|
if (x) if (y) foo(); else bar(); else baz();
|
||||||
|
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
||||||
|
}
|
||||||
@@ -1,17 +1 @@
|
|||||||
if (x) foo();
|
if(x)foo();if(x)foo();else baz();if(x)foo();else if(y)bar();else baz();if(x)if(y)foo();else bar();else baz();if(x)foo();else if(y)bar();else if(z)baz();else moo();function f(){if(x)foo();if(x)foo();else baz();if(x)foo();else if(y)bar();else baz();if(x)if(y)foo();else bar();else baz();if(x)foo();else if(y)bar();else if(z)baz();else moo()}
|
||||||
|
|
||||||
if (x) foo(); else baz();
|
|
||||||
|
|
||||||
if (x) foo(); else if (y) bar(); else baz();
|
|
||||||
|
|
||||||
if (x) if (y) foo(); else bar(); else baz();
|
|
||||||
|
|
||||||
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
|
||||||
|
|
||||||
function f() {
|
|
||||||
if (x) foo();
|
|
||||||
if (x) foo(); else baz();
|
|
||||||
if (x) foo(); else if (y) bar(); else baz();
|
|
||||||
if (x) if (y) foo(); else bar(); else baz();
|
|
||||||
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,2 +1,41 @@
|
|||||||
function _toConsumableArray(arr){if(Array.isArray(arr)){for(var i=0,arr2=Array(arr.length);i<arr.length;i++){arr2[i]=arr[i]}return arr2}else{return Array.from(arr)}}var _require=require("bar"),foo=_require.foo;var _require2=require("world"),hello=_require2.hello;foo.x.apply(foo,_toConsumableArray(foo.y(hello.z)));
|
"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)};
|
new function(){console.log(3)};
|
||||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSJ9
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ function test(a){
|
|||||||
"aaaaaaaaaaaaaaaa"
|
"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)};
|
new function(){console.log(3)};
|
||||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSJ9
|
||||||
|
|||||||
9
test/input/reduce/label.js
Normal file
9
test/input/reduce/label.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
var o = this;
|
||||||
|
|
||||||
|
for (var k in o) L17060: {
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var a;
|
||||||
|
|
||||||
|
console.log(k);
|
||||||
15
test/input/reduce/label.reduced.js
Normal file
15
test/input/reduce/label.reduced.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// (beautified)
|
||||||
|
var o = this;
|
||||||
|
|
||||||
|
for (var k in o) {}
|
||||||
|
|
||||||
|
var a;
|
||||||
|
|
||||||
|
console.log(k);
|
||||||
|
// output: a
|
||||||
|
//
|
||||||
|
// minify: k
|
||||||
|
//
|
||||||
|
// options: {
|
||||||
|
// "mangle": false
|
||||||
|
// }
|
||||||
8
test/input/reduce/setter.js
Normal file
8
test/input/reduce/setter.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
console.log(function f(a) {
|
||||||
|
({
|
||||||
|
set p(v) {
|
||||||
|
f++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return f.length;
|
||||||
|
}());
|
||||||
20
test/input/reduce/setter.reduced.js
Normal file
20
test/input/reduce/setter.reduced.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// (beautified)
|
||||||
|
console.log(function f(a) {
|
||||||
|
({
|
||||||
|
set p(v) {
|
||||||
|
f++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return f.length;
|
||||||
|
}());
|
||||||
|
// output: 1
|
||||||
|
//
|
||||||
|
// minify: 0
|
||||||
|
//
|
||||||
|
// options: {
|
||||||
|
// "compress": {
|
||||||
|
// "keep_fargs": false,
|
||||||
|
// "unsafe": true
|
||||||
|
// },
|
||||||
|
// "mangle": false
|
||||||
|
// }
|
||||||
18
test/input/reduce/unsafe_math.js
Normal file
18
test/input/reduce/unsafe_math.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
var _calls_ = 10, a = 100, b = 10, c = 0;
|
||||||
|
|
||||||
|
function f0(b_1, a, undefined_2) {
|
||||||
|
a++ + ++b;
|
||||||
|
{
|
||||||
|
var expr2 = (b + 1 - .1 - .1 - .1 || a || 3).toString();
|
||||||
|
L20778: for (var key2 in expr2) {
|
||||||
|
(c = c + 1) + [ --b + b_1, typeof f0 == "function" && --_calls_ >= 0 && f0(--b + typeof (undefined_2 = 1 === 1 ? a : b), --b + {
|
||||||
|
c: (c = c + 1) + null
|
||||||
|
}, a++ + (typeof f0 == "function" && --_calls_ >= 0 && f0(typeof (c = 1 + c, 3 / "a" * ("c" >>> 23..toString()) >= (b_1 && (b_1[(c = c + 1) + a--] = (- -0,
|
||||||
|
true + {})))), 3, 25))), 1 === 1 ? a : b ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var a_1 = f0([ , 0 ].length === 2);
|
||||||
|
|
||||||
|
console.log(null, a, b, c, Infinity, NaN, undefined);
|
||||||
20
test/input/reduce/unsafe_math.reduced.js
Normal file
20
test/input/reduce/unsafe_math.reduced.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// (beautified)
|
||||||
|
var b = 0;
|
||||||
|
|
||||||
|
var expr2 = (0 - 1 - .1 - .1).toString();
|
||||||
|
|
||||||
|
for (var key2 in expr2) {
|
||||||
|
--b;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(b);
|
||||||
|
// output: -19
|
||||||
|
//
|
||||||
|
// minify: -4
|
||||||
|
//
|
||||||
|
// options: {
|
||||||
|
// "compress": {
|
||||||
|
// "unsafe_math": true
|
||||||
|
// },
|
||||||
|
// "mangle": false
|
||||||
|
// }
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
function f(x) {
|
function f(x) {
|
||||||
return g(x);
|
return g(x);
|
||||||
function g(x) {
|
function g(x) {
|
||||||
return x;
|
return x + x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,15 +8,14 @@ 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) {
|
|
||||||
args.push("-mcb", "beautify=false,webkit");
|
|
||||||
}
|
}
|
||||||
|
args.unshift("bin/uglifyjs");
|
||||||
|
if (!args.length) args.push("-mcb", "beautify=false,webkit");
|
||||||
args.push("--timings");
|
args.push("--timings");
|
||||||
var child_process = require("child_process");
|
var child_process = require("child_process");
|
||||||
var fetch = require("./fetch");
|
var fetch = require("./fetch");
|
||||||
@@ -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);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
|
|
||||||
var config = {
|
var config = {
|
||||||
limit: 5000,
|
limit: 10000,
|
||||||
timeout: function(limit) {
|
timeout: function(limit) {
|
||||||
this.limit = limit;
|
this.limit = limit;
|
||||||
}
|
}
|
||||||
@@ -55,11 +55,11 @@ process.nextTick(function run() {
|
|||||||
var elapsed = Date.now();
|
var elapsed = Date.now();
|
||||||
var timer;
|
var timer;
|
||||||
var done = function() {
|
var done = function() {
|
||||||
reset();
|
|
||||||
elapsed = Date.now() - elapsed;
|
elapsed = Date.now() - elapsed;
|
||||||
if (elapsed > task.limit) {
|
if (elapsed > task.limit) {
|
||||||
throw new Error("Timed out: " + elapsed + "ms > " + task.limit + "ms");
|
throw new Error("Timed out: " + elapsed + "ms > " + task.limit + "ms");
|
||||||
}
|
}
|
||||||
|
reset();
|
||||||
log_titles(console.log, task.titles, green('\u221A '));
|
log_titles(console.log, task.titles, green('\u221A '));
|
||||||
process.nextTick(run);
|
process.nextTick(run);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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");
|
||||||
@@ -12,7 +13,9 @@ describe("bin/uglifyjs", function() {
|
|||||||
it("Should produce a functional build when using --self", function(done) {
|
it("Should produce a functional build when using --self", function(done) {
|
||||||
this.timeout(30000);
|
this.timeout(30000);
|
||||||
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
|
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
|
||||||
exec(command, function(err, stdout) {
|
exec(command, {
|
||||||
|
maxBuffer: 1048576
|
||||||
|
}, function(err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
eval(stdout);
|
eval(stdout);
|
||||||
assert.strictEqual(typeof WrappedUglifyJS, "object");
|
assert.strictEqual(typeof WrappedUglifyJS, "object");
|
||||||
@@ -46,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) {
|
||||||
@@ -107,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) {
|
||||||
@@ -174,7 +236,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b';
|
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b';
|
||||||
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/beautify.js"));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -186,6 +248,22 @@ describe("bin/uglifyjs", function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should work with `--output-opts`", function(done) {
|
||||||
|
var command = uglifyjscmd + ' test/input/issue-1482/input.js -O';
|
||||||
|
exec(command, function(err, stdout) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(stdout, read("test/input/issue-1482/default.js"));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should fail when both --beautify & --output-opts are specified", function(done) {
|
||||||
|
var command = uglifyjscmd + " test/input/issue-520/input.js -bO";
|
||||||
|
exec(command, function(err, stdout, stderr) {
|
||||||
|
assert.ok(err);
|
||||||
|
assert.strictEqual(stderr, "ERROR: --beautify cannot be used with --output-opts\n");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
it("Should process inline source map", function(done) {
|
it("Should process inline source map", function(done) {
|
||||||
var command = [
|
var command = [
|
||||||
uglifyjscmd,
|
uglifyjscmd,
|
||||||
@@ -227,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");
|
||||||
@@ -569,7 +647,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, '\\"');
|
||||||
}
|
}
|
||||||
@@ -656,7 +734,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();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -664,7 +742,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();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -672,7 +750,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();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -680,7 +758,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();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -48,53 +48,84 @@ describe("comments", function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should handle comment within return correctly", function() {
|
describe("comment within return", function() {
|
||||||
var result = UglifyJS.minify([
|
it("Should handle leading return", function() {
|
||||||
"function unequal(x, y) {",
|
var result = UglifyJS.minify([
|
||||||
" return (",
|
"function unequal(x, y) {",
|
||||||
" // Either one",
|
" return (",
|
||||||
" x < y",
|
" // Either one",
|
||||||
" ||",
|
" x < y",
|
||||||
" y < x",
|
" ||",
|
||||||
" );",
|
" y < x",
|
||||||
"}",
|
" );",
|
||||||
].join("\n"), {
|
"}",
|
||||||
compress: false,
|
].join("\n"), {
|
||||||
mangle: false,
|
compress: false,
|
||||||
output: {
|
mangle: false,
|
||||||
beautify: true,
|
output: {
|
||||||
comments: "all",
|
beautify: true,
|
||||||
},
|
comments: "all",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"function unequal(x, y) {",
|
||||||
|
" // Either one",
|
||||||
|
" return x < y || y < x;",
|
||||||
|
"}",
|
||||||
|
].join("\n"));
|
||||||
});
|
});
|
||||||
if (result.error) throw result.error;
|
|
||||||
assert.strictEqual(result.code, [
|
|
||||||
"function unequal(x, y) {",
|
|
||||||
" // Either one",
|
|
||||||
" return x < y || y < x;",
|
|
||||||
"}",
|
|
||||||
].join("\n"));
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Should handle comment folded into return correctly", function() {
|
it("Should handle trailing return", function() {
|
||||||
var result = UglifyJS.minify([
|
var result = UglifyJS.minify([
|
||||||
"function f() {",
|
"function unequal(x) {",
|
||||||
" /* boo */ x();",
|
" var y;",
|
||||||
" return y();",
|
" return (",
|
||||||
"}",
|
" // Either one",
|
||||||
].join("\n"), {
|
" x < y",
|
||||||
mangle: false,
|
" ||",
|
||||||
output: {
|
" y < x",
|
||||||
beautify: true,
|
" );",
|
||||||
comments: "all",
|
"}",
|
||||||
},
|
].join("\n"), {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
beautify: true,
|
||||||
|
comments: "all",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"function unequal(x) {",
|
||||||
|
" var y;",
|
||||||
|
" // Either one",
|
||||||
|
" return x < y || y < x;",
|
||||||
|
"}",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should handle comment folded into return", function() {
|
||||||
|
var result = UglifyJS.minify([
|
||||||
|
"function f() {",
|
||||||
|
" /* boo */ x();",
|
||||||
|
" return y();",
|
||||||
|
"}",
|
||||||
|
].join("\n"), {
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
beautify: true,
|
||||||
|
comments: "all",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"function f() {",
|
||||||
|
" /* boo */",
|
||||||
|
" return x(), y();",
|
||||||
|
"}",
|
||||||
|
].join("\n"));
|
||||||
});
|
});
|
||||||
if (result.error) throw result.error;
|
|
||||||
assert.strictEqual(result.code, [
|
|
||||||
"function f() {",
|
|
||||||
" /* boo */",
|
|
||||||
" return x(), y();",
|
|
||||||
"}",
|
|
||||||
].join("\n"));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should not drop comments after first OutputStream", function() {
|
it("Should not drop comments after first OutputStream", function() {
|
||||||
@@ -228,6 +259,30 @@ describe("comments", function() {
|
|||||||
assert.strictEqual(result.code, code);
|
assert.strictEqual(result.code, code);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should handle comments around parenthesis correctly", function() {
|
||||||
|
var code = [
|
||||||
|
"a();",
|
||||||
|
"/* foo */",
|
||||||
|
"(b())",
|
||||||
|
"/* bar */",
|
||||||
|
"c();",
|
||||||
|
].join("\n");
|
||||||
|
var result = UglifyJS.minify(code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
comments: "all",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"a();",
|
||||||
|
"/* foo */",
|
||||||
|
"b()",
|
||||||
|
"/* bar */;c();",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
|
||||||
it("Should preserve comments around IIFE", function() {
|
it("Should preserve comments around IIFE", function() {
|
||||||
var result = UglifyJS.minify("/*a*/(/*b*/function(){/*c*/}/*d*/)/*e*/();", {
|
var result = UglifyJS.minify("/*a*/(/*b*/function(){/*c*/}/*d*/)/*e*/();", {
|
||||||
compress: false,
|
compress: false,
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ describe("Directives", function() {
|
|||||||
[
|
[
|
||||||
[
|
[
|
||||||
'"use strict"\n',
|
'"use strict"\n',
|
||||||
[ "use strict"],
|
[ "use strict" ],
|
||||||
[ "use asm"]
|
[ "use asm" ]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'"use\\\nstrict";',
|
'"use\\\nstrict";',
|
||||||
@@ -69,19 +69,19 @@ describe("Directives", function() {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'"use \\\nstrict";"use strict";',
|
'"use \\\nstrict";"use strict";',
|
||||||
[],
|
[ "use strict" ],
|
||||||
[ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
|
[ "use\nstrict", "use \nstrict", "use asm" ]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'"\\76";',
|
'"\\76";',
|
||||||
[],
|
[ "\\76" ],
|
||||||
[ ">", "\\76" ]
|
[ ">" ]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
// no ; or newline
|
// no ; or newline
|
||||||
'"use strict"',
|
'"use strict"',
|
||||||
[],
|
[ "use strict" ],
|
||||||
[ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
|
[ "use\nstrict", "use \nstrict", "use asm" ]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
';"use strict"',
|
';"use strict"',
|
||||||
@@ -106,18 +106,18 @@ describe("Directives", function() {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'function foo() {"use \\\nstrict";"use strict";',
|
'function foo() {"use \\\nstrict";"use strict";',
|
||||||
[],
|
[ "use strict" ],
|
||||||
[ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
|
[ "use\nstrict", "use \nstrict", "use asm" ]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'var foo = function() {"\\76";',
|
'var foo = function() {"\\76";',
|
||||||
[],
|
[ "\\76" ],
|
||||||
[ ">", "\\76" ]
|
[ ">" ]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'var foo = function() {"use strict"', // no ; or newline
|
'var foo = function() {"use strict"', // no ; or newline
|
||||||
[],
|
[ "use strict" ],
|
||||||
[ "use strict", "use\nstrict", "use \nstrict", "use asm" ]
|
[ "use\nstrict", "use \nstrict", "use asm" ]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'var foo = function() {;"use strict"',
|
'var foo = function() {;"use strict"',
|
||||||
@@ -156,21 +156,24 @@ describe("Directives", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should test EXPECT_DIRECTIVE RegExp", function() {
|
it("Should print semicolon to separate strings from directives", function() {
|
||||||
[
|
[
|
||||||
[ "", true ],
|
[ "", ';"";' ],
|
||||||
[ "'test';", true ],
|
[ '"test";', '"test";;"";' ],
|
||||||
[ "'test';;", true ],
|
[ '"test";;', '"test";;"";' ],
|
||||||
[ "'tests';\n", true ],
|
[ '"tests";\n', '"tests";;"";' ],
|
||||||
[ "'tests'", false ],
|
[ '"tests"', '"tests";;"";' ],
|
||||||
[ "'tests'; \n\t", true ],
|
[ '"tests"; \n\t', '"tests";;"";' ],
|
||||||
[ "'tests';\n\n", true ],
|
[ '"tests";\n\n', '"tests";;"";' ],
|
||||||
[ "\n\n\"use strict\";\n\n", true ],
|
[ '\n\n"use strict";\n\n', '"use strict";;"";' ],
|
||||||
].forEach(function(test) {
|
].forEach(function(test) {
|
||||||
|
var ast = UglifyJS.parse(test[0]);
|
||||||
|
ast.body.push(new UglifyJS.AST_SimpleStatement({
|
||||||
|
body: new UglifyJS.AST_String({ value: "" })
|
||||||
|
}));
|
||||||
var out = UglifyJS.OutputStream();
|
var out = UglifyJS.OutputStream();
|
||||||
out.print(test[0]);
|
ast.print(out);
|
||||||
out.print_string("", null, true);
|
assert.strictEqual(out.get(), test[1], test[0]);
|
||||||
assert.strictEqual(out.get() === test[0] + ';""', test[1], test[0]);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should only print 2 semicolons spread over 2 lines in beautify mode", function() {
|
it("Should only print 2 semicolons spread over 2 lines in beautify mode", function() {
|
||||||
@@ -178,8 +181,8 @@ describe("Directives", function() {
|
|||||||
'"use strict";',
|
'"use strict";',
|
||||||
"'use strict';",
|
"'use strict';",
|
||||||
'"use strict";',
|
'"use strict";',
|
||||||
'"use strict";;',
|
'"use strict";',
|
||||||
"'use strict';",
|
";'use strict';",
|
||||||
"console.log('use strict');"
|
"console.log('use strict');"
|
||||||
].join(""), {
|
].join(""), {
|
||||||
compress: false,
|
compress: false,
|
||||||
@@ -201,19 +204,23 @@ describe("Directives", function() {
|
|||||||
it("Should not add double semicolons in non-scoped block statements to avoid strings becoming directives", function() {
|
it("Should not add double semicolons in non-scoped block statements to avoid strings becoming directives", function() {
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
'{"use\x20strict"}',
|
'"use strict";"use\\x20strict";',
|
||||||
|
'"use strict";"use\\x20strict";'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'{"use\\x20strict"}',
|
||||||
'{"use strict"}'
|
'{"use strict"}'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'function foo(){"use\x20strict";}', // Valid place for directives
|
'function foo(){"use\\x20strict";}', // Valid place for directives
|
||||||
'function foo(){"use strict"}'
|
'function foo(){"use\\x20strict"}'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'try{"use\x20strict"}catch(e){}finally{"use\x20strict"}',
|
'try{"use\\x20strict"}catch(e){}finally{"use\\x20strict"}',
|
||||||
'try{"use strict"}catch(e){}finally{"use strict"}'
|
'try{"use strict"}catch(e){}finally{"use strict"}'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'if(1){"use\x20strict"} else {"use strict"}',
|
'if(1){"use\\x20strict"} else {"use strict"}',
|
||||||
'if(1){"use strict"}else{"use strict"}'
|
'if(1){"use strict"}else{"use strict"}'
|
||||||
]
|
]
|
||||||
].forEach(function(test) {
|
].forEach(function(test) {
|
||||||
@@ -225,16 +232,6 @@ describe("Directives", function() {
|
|||||||
assert.strictEqual(result.code, test[1], test[0]);
|
assert.strictEqual(result.code, test[1], test[0]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should add double semicolon when relying on automatic semicolon insertion", function() {
|
|
||||||
var result = UglifyJS.minify('"use strict";"use\\x20strict";', {
|
|
||||||
compress: false,
|
|
||||||
output: {
|
|
||||||
semicolons: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (result.error) throw result.error;
|
|
||||||
assert.strictEqual(result.code, '"use strict";;"use strict"\n');
|
|
||||||
});
|
|
||||||
it("Should check quote style of directives", function() {
|
it("Should check quote style of directives", function() {
|
||||||
[
|
[
|
||||||
// 0. Prefer double quotes, unless string contains more double quotes than single quotes
|
// 0. Prefer double quotes, unless string contains more double quotes than single quotes
|
||||||
@@ -249,9 +246,9 @@ describe("Directives", function() {
|
|||||||
'"use strict";'
|
'"use strict";'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'"\\\'use strict\\\'";', // Not a directive as it contains quotes
|
'"\\\'use strict\\\'";',
|
||||||
0,
|
0,
|
||||||
';"\'use strict\'";',
|
'"\\\'use strict\\\'";',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"'\"use strict\"';",
|
"'\"use strict\"';",
|
||||||
@@ -273,7 +270,7 @@ describe("Directives", function() {
|
|||||||
'"\'use strict\'";',
|
'"\'use strict\'";',
|
||||||
1,
|
1,
|
||||||
// Intentionally causes directive breakage at cost of less logic, usage should be rare anyway
|
// Intentionally causes directive breakage at cost of less logic, usage should be rare anyway
|
||||||
"'\\'use strict\\'';",
|
'"\'use strict\'";',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"'\\'use strict\\'';", // Not a valid directive
|
"'\\'use strict\\'';", // Not a valid directive
|
||||||
@@ -305,7 +302,7 @@ describe("Directives", function() {
|
|||||||
"'\"use strict\"';",
|
"'\"use strict\"';",
|
||||||
2,
|
2,
|
||||||
// Intentionally causes directive breakage at cost of less logic, usage should be rare anyway
|
// Intentionally causes directive breakage at cost of less logic, usage should be rare anyway
|
||||||
'"\\\"use strict\\\"";',
|
"'\"use strict\"';",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'"\\"use strict\\"";', // Not a valid directive
|
'"\\"use strict\\"";', // Not a valid directive
|
||||||
@@ -353,8 +350,7 @@ describe("Directives", function() {
|
|||||||
[
|
[
|
||||||
// Nothing gets optimised in the compressor because "use asm" is the first statement
|
// Nothing gets optimised in the compressor because "use asm" is the first statement
|
||||||
'"use asm";"use\\x20strict";1+1;',
|
'"use asm";"use\\x20strict";1+1;',
|
||||||
// Yet, the parser noticed that "use strict" wasn't a directive
|
'"use asm";"use\\x20strict";1+1;'
|
||||||
'"use asm";;"use strict";1+1;',
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'function f(){ "use strict" }',
|
'function f(){ "use strict" }',
|
||||||
|
|||||||
@@ -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 = "";
|
||||||
@@ -51,9 +63,8 @@ describe("minify", function() {
|
|||||||
"var a=n(3),b=r(12);",
|
"var a=n(3),b=r(12);",
|
||||||
'c("qux",a,b),o(11);',
|
'c("qux",a,b),o(11);',
|
||||||
].join(""));
|
].join(""));
|
||||||
assert.strictEqual(run_code(compressed), run_code(original));
|
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should work with nameCache", function() {
|
it("Should work with nameCache", function() {
|
||||||
var cache = {};
|
var cache = {};
|
||||||
var original = "";
|
var original = "";
|
||||||
@@ -84,9 +95,8 @@ describe("minify", function() {
|
|||||||
"var a=n(3),b=r(12);",
|
"var a=n(3),b=r(12);",
|
||||||
'c("qux",a,b),o(11);',
|
'c("qux",a,b),o(11);',
|
||||||
].join(""));
|
].join(""));
|
||||||
assert.strictEqual(run_code(compressed), run_code(original));
|
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should avoid cached names when mangling top-level variables", function() {
|
it("Should avoid cached names when mangling top-level variables", function() {
|
||||||
var cache = {};
|
var cache = {};
|
||||||
var original = "";
|
var original = "";
|
||||||
@@ -113,9 +123,8 @@ describe("minify", function() {
|
|||||||
'"xxyyy";var y={y:2,a:3},a=4;',
|
'"xxyyy";var y={y:2,a:3},a=4;',
|
||||||
'console.log(x.x,y.y,y.a,a);',
|
'console.log(x.x,y.y,y.a,a);',
|
||||||
].join(""));
|
].join(""));
|
||||||
assert.strictEqual(run_code(compressed), run_code(original));
|
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should avoid cached names when mangling inner-scoped variables", function() {
|
it("Should avoid cached names when mangling inner-scoped variables", function() {
|
||||||
var cache = {};
|
var cache = {};
|
||||||
var original = "";
|
var original = "";
|
||||||
@@ -137,9 +146,8 @@ describe("minify", function() {
|
|||||||
'var o=function(o,n){console.log("extend");o();n()};function n(){console.log("A")}',
|
'var o=function(o,n){console.log("extend");o();n()};function n(){console.log("A")}',
|
||||||
'var e=function(n){function e(){console.log("B")}o(e,n);return e}(n);',
|
'var e=function(n){function e(){console.log("B")}o(e,n);return e}(n);',
|
||||||
].join(""));
|
].join(""));
|
||||||
assert.strictEqual(run_code(compressed), run_code(original));
|
assert.strictEqual(run_code(compressed, true), run_code(original, true));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should not parse invalid use of reserved words", function() {
|
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, {
|
||||||
|
|||||||
@@ -2,10 +2,18 @@ var assert = require("assert");
|
|||||||
var UglifyJS = require("../node");
|
var UglifyJS = require("../node");
|
||||||
|
|
||||||
describe("Number literals", function() {
|
describe("Number literals", function() {
|
||||||
|
it("Should allow legacy octal literals in non-strict mode", function() {
|
||||||
|
[
|
||||||
|
"'use strict'\n.slice()\n00",
|
||||||
|
'"use strict"\n.slice()\nvar foo = 00',
|
||||||
|
].forEach(function(input) {
|
||||||
|
UglifyJS.parse(input);
|
||||||
|
});
|
||||||
|
});
|
||||||
it("Should not allow legacy octal literals in strict mode", function() {
|
it("Should not allow legacy octal literals in strict mode", function() {
|
||||||
var inputs = [
|
var inputs = [
|
||||||
'"use strict";00;',
|
'"use strict";00;',
|
||||||
'"use strict"; var foo = 00;'
|
'"use strict"; var foo = 00;',
|
||||||
];
|
];
|
||||||
var test = function(input) {
|
var test = function(input) {
|
||||||
return function() {
|
return function() {
|
||||||
|
|||||||
299
test/mocha/reduce.js
Normal file
299
test/mocha/reduce.js
Normal file
@@ -0,0 +1,299 @@
|
|||||||
|
var assert = require("assert");
|
||||||
|
var exec = require("child_process").exec;
|
||||||
|
var fs = require("fs");
|
||||||
|
var reduce_test = require("../reduce");
|
||||||
|
var semver = require("semver");
|
||||||
|
|
||||||
|
function read(path) {
|
||||||
|
return fs.readFileSync(path, "utf8");
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("test/reduce.js", function() {
|
||||||
|
this.timeout(60000);
|
||||||
|
it("Should reduce test case", function() {
|
||||||
|
var result = reduce_test(read("test/input/reduce/unsafe_math.js"), {
|
||||||
|
compress: {
|
||||||
|
unsafe_math: true,
|
||||||
|
},
|
||||||
|
mangle: false,
|
||||||
|
}, {
|
||||||
|
verbose: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, read("test/input/reduce/unsafe_math.reduced.js"));
|
||||||
|
});
|
||||||
|
it("Should eliminate unreferenced labels", function() {
|
||||||
|
var result = reduce_test(read("test/input/reduce/label.js"), {
|
||||||
|
mangle: false,
|
||||||
|
}, {
|
||||||
|
verbose: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, read("test/input/reduce/label.reduced.js"));
|
||||||
|
});
|
||||||
|
it("Should retain setter arguments", function() {
|
||||||
|
var result = reduce_test(read("test/input/reduce/setter.js"), {
|
||||||
|
compress: {
|
||||||
|
keep_fargs: false,
|
||||||
|
unsafe: true,
|
||||||
|
},
|
||||||
|
mangle: false,
|
||||||
|
}, {
|
||||||
|
verbose: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, read("test/input/reduce/setter.reduced.js"));
|
||||||
|
});
|
||||||
|
it("Should handle test cases with --toplevel", function() {
|
||||||
|
var result = reduce_test([
|
||||||
|
"var Infinity = 42;",
|
||||||
|
"console.log(Infinity);",
|
||||||
|
].join("\n"), {
|
||||||
|
toplevel: true,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"// Can't reproduce test failure",
|
||||||
|
"// minify options: {",
|
||||||
|
'// "toplevel": true',
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
it("Should handle test cases with --compress toplevel", function() {
|
||||||
|
var result = reduce_test([
|
||||||
|
"var NaN = 42;",
|
||||||
|
"console.log(NaN);",
|
||||||
|
].join("\n"), {
|
||||||
|
compress: {
|
||||||
|
toplevel: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"// Can't reproduce test failure",
|
||||||
|
"// minify options: {",
|
||||||
|
'// "compress": {',
|
||||||
|
'// "toplevel": true',
|
||||||
|
"// }",
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
it("Should handle test cases with --mangle toplevel", function() {
|
||||||
|
var result = reduce_test([
|
||||||
|
"var undefined = 42;",
|
||||||
|
"console.log(undefined);",
|
||||||
|
].join("\n"), {
|
||||||
|
mangle: {
|
||||||
|
toplevel: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"// Can't reproduce test failure",
|
||||||
|
"// minify options: {",
|
||||||
|
'// "mangle": {',
|
||||||
|
'// "toplevel": true',
|
||||||
|
"// }",
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
it("Should handle test result of NaN", function() {
|
||||||
|
var result = reduce_test("throw 0 / 0;");
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"// Can't reproduce test failure",
|
||||||
|
"// minify options: {}",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
it("Should print correct output for irreducible test case", function() {
|
||||||
|
var result = reduce_test([
|
||||||
|
"console.log(function f(a) {",
|
||||||
|
" return f.length;",
|
||||||
|
"}());",
|
||||||
|
].join("\n"), {
|
||||||
|
compress: {
|
||||||
|
keep_fargs: false,
|
||||||
|
},
|
||||||
|
mangle: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"// (beautified)",
|
||||||
|
"console.log(function f(a) {",
|
||||||
|
" return f.length;",
|
||||||
|
"}());",
|
||||||
|
"// output: 1",
|
||||||
|
"// ",
|
||||||
|
"// minify: 0",
|
||||||
|
"// ",
|
||||||
|
"// options: {",
|
||||||
|
'// "compress": {',
|
||||||
|
'// "keep_fargs": false',
|
||||||
|
"// },",
|
||||||
|
'// "mangle": false',
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
it("Should fail when invalid option is supplied", function() {
|
||||||
|
var result = reduce_test("", {
|
||||||
|
compress: {
|
||||||
|
unsafe_regex: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
var err = result.error;
|
||||||
|
assert.ok(err instanceof Error);
|
||||||
|
assert.strictEqual(err.stack.split(/\n/)[0], "DefaultsError: `unsafe_regex` is not a supported option");
|
||||||
|
});
|
||||||
|
it("Should report on test case with invalid syntax", function() {
|
||||||
|
var result = reduce_test("var 0 = 1;");
|
||||||
|
var err = result.error;
|
||||||
|
assert.ok(err instanceof Error);
|
||||||
|
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Name expected");
|
||||||
|
});
|
||||||
|
it("Should format multi-line output correctly", function() {
|
||||||
|
var code = [
|
||||||
|
"var a = 0;",
|
||||||
|
"",
|
||||||
|
"for (var b in [ 1, 2, 3 ]) {",
|
||||||
|
" a = +a + 1 - .2;",
|
||||||
|
" console.log(a);",
|
||||||
|
"}",
|
||||||
|
].join("\n");
|
||||||
|
var result = reduce_test(code, {
|
||||||
|
compress: {
|
||||||
|
unsafe_math: true,
|
||||||
|
},
|
||||||
|
mangle: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"// (beautified)",
|
||||||
|
code,
|
||||||
|
"// output: 0.8",
|
||||||
|
"// 1.6",
|
||||||
|
"// 2.4",
|
||||||
|
"// ",
|
||||||
|
"// minify: 0.8",
|
||||||
|
"// 1.6",
|
||||||
|
"// 2.4000000000000004",
|
||||||
|
"// ",
|
||||||
|
"// options: {",
|
||||||
|
'// "compress": {',
|
||||||
|
'// "unsafe_math": true',
|
||||||
|
"// },",
|
||||||
|
'// "mangle": false',
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
it("Should reduce infinite loops with reasonable performance", function() {
|
||||||
|
if (semver.satisfies(process.version, "<=0.10")) return;
|
||||||
|
this.timeout(120000);
|
||||||
|
var result = reduce_test("while (/9/.test(1 - .8));", {
|
||||||
|
compress: {
|
||||||
|
unsafe_math: true,
|
||||||
|
},
|
||||||
|
mangle: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code.replace(/ timed out after [0-9]+ms/, " timed out."), [
|
||||||
|
"// (beautified)",
|
||||||
|
"while (/9/.test(1 - .8)) {}",
|
||||||
|
"// output: Error: Script execution timed out.",
|
||||||
|
"// minify: ",
|
||||||
|
"// options: {",
|
||||||
|
'// "compress": {',
|
||||||
|
'// "unsafe_math": true',
|
||||||
|
"// },",
|
||||||
|
'// "mangle": false',
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
it("Should ignore difference in Error.message", function() {
|
||||||
|
var result = reduce_test("null[function() {\n}];");
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, (semver.satisfies(process.version, "<=0.10") ? [
|
||||||
|
"// Can't reproduce test failure",
|
||||||
|
"// minify options: {}",
|
||||||
|
] : [
|
||||||
|
"// No differences except in error message",
|
||||||
|
"// minify options: {}",
|
||||||
|
]).join("\n"));
|
||||||
|
});
|
||||||
|
it("Should report trailing whitespace difference in stringified format", function() {
|
||||||
|
var code = [
|
||||||
|
"for (var a in (1 - .8).toString()) {",
|
||||||
|
" console.log();",
|
||||||
|
"}",
|
||||||
|
].join("\n");
|
||||||
|
var result = reduce_test(code, {
|
||||||
|
compress: {
|
||||||
|
unsafe_math: true,
|
||||||
|
},
|
||||||
|
mangle: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"// (beautified)",
|
||||||
|
code,
|
||||||
|
"// (stringified)",
|
||||||
|
'// output: "\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n"',
|
||||||
|
'// minify: "\\n\\n\\n"',
|
||||||
|
"// options: {",
|
||||||
|
'// "compress": {',
|
||||||
|
'// "unsafe_math": true',
|
||||||
|
'// },',
|
||||||
|
'// "mangle": false',
|
||||||
|
"// }",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
it("Should reduce test case which differs only in Error.message", function() {
|
||||||
|
var code = [
|
||||||
|
"var a=0;",
|
||||||
|
"try{",
|
||||||
|
"null[function(){}]",
|
||||||
|
"}catch(e){",
|
||||||
|
"for(var i in e.toString())",
|
||||||
|
"a++,console.log()",
|
||||||
|
"}",
|
||||||
|
"console.log(a);",
|
||||||
|
].join("");
|
||||||
|
var result = reduce_test(code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
beautify: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.deepEqual(result.warnings, []);
|
||||||
|
assert.strictEqual(result.code.replace(/function \(/g, "function("), (semver.satisfies(process.version, "<=0.10") ? [
|
||||||
|
"// Can't reproduce test failure",
|
||||||
|
"// minify options: {",
|
||||||
|
'// "compress": false,',
|
||||||
|
'// "mangle": false,',
|
||||||
|
'// "output": {',
|
||||||
|
'// "beautify": true',
|
||||||
|
"// }",
|
||||||
|
"// }",
|
||||||
|
] : [
|
||||||
|
[
|
||||||
|
"try{",
|
||||||
|
"null[function(){}]",
|
||||||
|
"}catch(e){",
|
||||||
|
"console.log(e)",
|
||||||
|
"}",
|
||||||
|
].join(""),
|
||||||
|
"// output: TypeError: Cannot read property 'function(){}' of null",
|
||||||
|
"// ",
|
||||||
|
"// minify: TypeError: Cannot read property 'function() {}' of null",
|
||||||
|
"// ",
|
||||||
|
"// options: {",
|
||||||
|
'// "compress": false,',
|
||||||
|
'// "mangle": false,',
|
||||||
|
'// "output": {',
|
||||||
|
'// "beautify": true',
|
||||||
|
"// }",
|
||||||
|
"// }",
|
||||||
|
]).join("\n"));
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -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("../..");
|
|
||||||
|
|
||||||
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,14 +122,30 @@ 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() {
|
||||||
|
var code = [
|
||||||
|
'console.log("\\',
|
||||||
|
'hello",',
|
||||||
|
'"world");',
|
||||||
|
];
|
||||||
|
var dos = UglifyJS.minify(code.join("\r\n"), {
|
||||||
|
sourceMap: true,
|
||||||
|
});
|
||||||
|
if (dos.error) throw dos.error;
|
||||||
|
var unix = UglifyJS.minify(code.join("\n"), {
|
||||||
|
sourceMap: true,
|
||||||
|
});
|
||||||
|
if (unix.error) throw unix.error;
|
||||||
|
assert.strictEqual(dos.map, unix.map);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("inSourceMap", function() {
|
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
|
||||||
}
|
}
|
||||||
@@ -106,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",
|
||||||
@@ -115,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"
|
||||||
@@ -130,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",
|
||||||
@@ -147,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: {
|
||||||
@@ -170,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",
|
||||||
@@ -179,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: {
|
||||||
@@ -214,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,
|
||||||
},
|
},
|
||||||
@@ -226,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 = [
|
||||||
@@ -244,7 +295,7 @@ describe("sourcemaps", function() {
|
|||||||
assert.strictEqual(map.sourcesContent.length, 1);
|
assert.strictEqual(map.sourcesContent.length, 1);
|
||||||
assert.strictEqual(map.sourcesContent[0], code);
|
assert.strictEqual(map.sourcesContent[0], code);
|
||||||
var encoded = result.code.slice(result.code.lastIndexOf(",") + 1);
|
var encoded = result.code.slice(result.code.lastIndexOf(",") + 1);
|
||||||
map = JSON.parse(new Buffer(encoded, "base64").toString());
|
map = JSON.parse(UglifyJS.to_ascii(encoded));
|
||||||
assert.strictEqual(map.sourcesContent.length, 1);
|
assert.strictEqual(map.sourcesContent.length, 1);
|
||||||
assert.strictEqual(map.sourcesContent[0], code);
|
assert.strictEqual(map.sourcesContent[0], code);
|
||||||
result = UglifyJS.minify(result.code, {
|
result = UglifyJS.minify(result.code, {
|
||||||
@@ -262,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];
|
||||||
map.allGeneratedPositionsFor({
|
lines.forEach(function(segments) {
|
||||||
source: "index.js",
|
indices[0] = 0;
|
||||||
line: 1,
|
segments.split(/,/).forEach(function(segment) {
|
||||||
column: 1
|
UglifyJS.vlq_decode(indices, segment);
|
||||||
}).forEach(function(pos) {
|
assert.ok(indices[2] <= 2, msg);
|
||||||
assert.ok(pos.line <= 2, msg);
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ describe("spidermonkey export/import sanity test", function() {
|
|||||||
var command = uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey | " +
|
var command = uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey | " +
|
||||||
uglifyjs + " -p spidermonkey -cm";
|
uglifyjs + " -p spidermonkey -cm";
|
||||||
|
|
||||||
exec(command, function(err, stdout) {
|
exec(command, {
|
||||||
|
maxBuffer: 1048576
|
||||||
|
}, function(err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
eval(stdout);
|
eval(stdout);
|
||||||
|
|||||||
@@ -59,13 +59,13 @@ describe("String literals", function() {
|
|||||||
|
|
||||||
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 = [
|
var tests = [
|
||||||
['"\\76";', ';">";'],
|
[ ';"\\76";', ';">";' ],
|
||||||
['"\\0"', '"\\0";'],
|
[ ';"\\0";', ';"\\0";' ],
|
||||||
['"\\08"', '"\\x008";'],
|
[ ';"\\08"', ';"\\x008";' ],
|
||||||
['"\\008"', '"\\x008";'],
|
[ ';"\\008"', ';"\\x008";' ],
|
||||||
['"\\0008"', '"\\x008";'],
|
[ ';"\\0008"', ';"\\x008";' ],
|
||||||
['"use strict" === "use strict";\n"\\76";', '"use strict"==="use strict";">";'],
|
[ ';"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";">";' ],
|
||||||
];
|
];
|
||||||
|
|
||||||
for (var test in tests) {
|
for (var test in tests) {
|
||||||
@@ -75,8 +75,8 @@ describe("String literals", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Should not throw error when digit is 8 or 9", function() {
|
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() {
|
||||||
@@ -93,7 +93,7 @@ describe("String literals", function() {
|
|||||||
for (; i <= 0xFFFF; i++) {
|
for (; i <= 0xFFFF; i++) {
|
||||||
code.push("\\u" + i.toString(16));
|
code.push("\\u" + i.toString(16));
|
||||||
}
|
}
|
||||||
code = '"' + code.join() + '"';
|
code = ';"' + code.join() + '"';
|
||||||
var normal = UglifyJS.minify(code, {
|
var normal = UglifyJS.minify(code, {
|
||||||
compress: false,
|
compress: false,
|
||||||
mangle: false,
|
mangle: false,
|
||||||
|
|||||||
@@ -44,30 +44,37 @@ function test(original, estree, description) {
|
|||||||
try_beautify(transformed.code);
|
try_beautify(transformed.code);
|
||||||
}
|
}
|
||||||
console.log("!!!!!! Failed... round", round);
|
console.log("!!!!!! Failed... round", round);
|
||||||
process.exit(1);
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var num_iterations = ufuzz.num_iterations;
|
var num_iterations = ufuzz.num_iterations;
|
||||||
|
var minify_options = require("./ufuzz/options.json").map(JSON.stringify);
|
||||||
|
minify_options.unshift(null);
|
||||||
for (var round = 1; round <= num_iterations; round++) {
|
for (var round = 1; round <= num_iterations; round++) {
|
||||||
process.stdout.write(round + " of " + num_iterations + "\r");
|
process.stdout.write(round + " of " + num_iterations + "\r");
|
||||||
var code = ufuzz.createTopLevelCode();
|
var code = ufuzz.createTopLevelCode();
|
||||||
var uglified = UglifyJS.minify(code, {
|
minify_options.forEach(function(options) {
|
||||||
compress: false,
|
var input = options ? UglifyJS.minify(code, JSON.parse(options)).code : code;
|
||||||
mangle: false,
|
var uglified = UglifyJS.minify(input, {
|
||||||
output: {
|
compress: false,
|
||||||
ast: true
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
ast: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var ok = test(uglified.code, uglified.ast.to_mozilla_ast(), "AST_Node.to_mozilla_ast()");
|
||||||
|
try {
|
||||||
|
ok = test(uglified.code, acorn.parse(input), "acorn.parse()") && ok;
|
||||||
|
} catch (e) {
|
||||||
|
console.log("//=============================================================");
|
||||||
|
console.log("// acorn parser failed... round", round);
|
||||||
|
console.log(e);
|
||||||
|
console.log("// original code");
|
||||||
|
console.log(input);
|
||||||
}
|
}
|
||||||
|
if (!ok) process.exit(1);
|
||||||
});
|
});
|
||||||
test(uglified.code, uglified.ast.to_mozilla_ast(), "AST_Node.to_mozilla_ast()");
|
|
||||||
try {
|
|
||||||
test(uglified.code, acorn.parse(code), "acorn.parse()");
|
|
||||||
} catch (e) {
|
|
||||||
console.log("//=============================================================");
|
|
||||||
console.log("// acorn parser failed... round", round);
|
|
||||||
console.log(e);
|
|
||||||
console.log("// original code");
|
|
||||||
console.log(code);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
console.log();
|
console.log();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
663
test/reduce.js
Normal file
663
test/reduce.js
Normal file
@@ -0,0 +1,663 @@
|
|||||||
|
var crypto = require("crypto");
|
||||||
|
var U = require("..");
|
||||||
|
var List = U.List;
|
||||||
|
var os = require("os");
|
||||||
|
var sandbox = require("./sandbox");
|
||||||
|
|
||||||
|
// Reduce a ufuzz-style `console.log` based test case by iteratively replacing
|
||||||
|
// AST nodes with various permutations. Each AST_Statement in the tree is also
|
||||||
|
// speculatively dropped to determine whether it is needed. If the altered
|
||||||
|
// tree and the last known good tree produce the same non-nil error-free output
|
||||||
|
// after being run, then the permutation survives to the next generation and
|
||||||
|
// is the basis for subsequent iterations. The test case is reduced as a
|
||||||
|
// consequence of complex expressions being replaced with simpler ones.
|
||||||
|
// This function assumes that the testcase will not result in a parse or
|
||||||
|
// runtime Error. Note that a reduced test case will have different runtime
|
||||||
|
// output - it is not functionally equivalent to the original. The only criteria
|
||||||
|
// is that once the generated reduced test case is run without minification, it
|
||||||
|
// will produce different output from the code minified with `minify_options`.
|
||||||
|
// Returns a `minify` result object with an additonal boolean property `reduced`.
|
||||||
|
|
||||||
|
module.exports = function reduce_test(testcase, minify_options, reduce_options) {
|
||||||
|
if (testcase instanceof U.AST_Node) testcase = testcase.print_to_string();
|
||||||
|
minify_options = minify_options || {};
|
||||||
|
reduce_options = reduce_options || {};
|
||||||
|
var max_iterations = reduce_options.max_iterations || 1000;
|
||||||
|
var max_timeout = reduce_options.max_timeout || 10000;
|
||||||
|
var warnings = [];
|
||||||
|
var log = reduce_options.log || function(msg) {
|
||||||
|
warnings.push(msg);
|
||||||
|
};
|
||||||
|
var verbose = reduce_options.verbose;
|
||||||
|
var minify_options_json = JSON.stringify(minify_options, null, 2);
|
||||||
|
var result_cache = Object.create(null);
|
||||||
|
// the initial timeout to assess the viability of the test case must be large
|
||||||
|
var differs = producesDifferentResultWhenMinified(result_cache, testcase, minify_options, max_timeout);
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
log("// Node.js " + process.version + " on " + os.platform() + " " + os.arch());
|
||||||
|
}
|
||||||
|
if (!differs) {
|
||||||
|
// same stdout result produced when minified
|
||||||
|
return {
|
||||||
|
code: [
|
||||||
|
"// Can't reproduce test failure",
|
||||||
|
"// minify options: " + to_comment(minify_options_json)
|
||||||
|
].join("\n"),
|
||||||
|
warnings: warnings,
|
||||||
|
};
|
||||||
|
} else if (differs.timed_out) {
|
||||||
|
return {
|
||||||
|
code: [
|
||||||
|
"// Can't reproduce test failure within " + max_timeout + "ms",
|
||||||
|
"// minify options: " + to_comment(minify_options_json)
|
||||||
|
].join("\n"),
|
||||||
|
warnings: warnings,
|
||||||
|
};
|
||||||
|
} else if (differs.error) {
|
||||||
|
differs.warnings = warnings;
|
||||||
|
return differs;
|
||||||
|
} else if (is_error(differs.unminified_result)
|
||||||
|
&& is_error(differs.minified_result)
|
||||||
|
&& differs.unminified_result.name == differs.minified_result.name) {
|
||||||
|
return {
|
||||||
|
code: [
|
||||||
|
"// No differences except in error message",
|
||||||
|
"// minify options: " + to_comment(minify_options_json)
|
||||||
|
].join("\n"),
|
||||||
|
warnings: warnings,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
max_timeout = Math.min(100 * differs.elapsed, max_timeout);
|
||||||
|
// Replace expressions with constants that will be parsed into
|
||||||
|
// AST_Nodes as required. Each AST_Node has its own permutation count,
|
||||||
|
// so these replacements can't be shared.
|
||||||
|
// Although simpler replacements are generally faster and better,
|
||||||
|
// feel free to experiment with a different replacement set.
|
||||||
|
var REPLACEMENTS = [
|
||||||
|
// "null", "''", "false", "'foo'", "undefined", "9",
|
||||||
|
"1", "0",
|
||||||
|
];
|
||||||
|
|
||||||
|
// There's a relationship between each node's _permute counter and
|
||||||
|
// REPLACEMENTS.length which is why fractional _permutes were needed.
|
||||||
|
// One could scale all _permute operations by a factor of `steps`
|
||||||
|
// to only deal with integer operations, but this works well enough.
|
||||||
|
var steps = 4; // must be a power of 2
|
||||||
|
var step = 1 / steps; // 0.25 is exactly representable in floating point
|
||||||
|
|
||||||
|
var tt = new U.TreeTransformer(function(node, descend, in_list) {
|
||||||
|
if (CHANGED) return;
|
||||||
|
|
||||||
|
// quick ignores
|
||||||
|
if (node instanceof U.AST_Accessor) return;
|
||||||
|
if (node instanceof U.AST_Directive) return;
|
||||||
|
if (!in_list && node instanceof U.AST_EmptyStatement) return;
|
||||||
|
if (node instanceof U.AST_Label) return;
|
||||||
|
if (node instanceof U.AST_LabelRef) return;
|
||||||
|
if (!in_list && node instanceof U.AST_SymbolDeclaration) return;
|
||||||
|
if (node instanceof U.AST_Toplevel) return;
|
||||||
|
var parent = tt.parent();
|
||||||
|
if (node instanceof U.AST_SymbolFunarg && parent instanceof U.AST_Accessor) return;
|
||||||
|
|
||||||
|
// ensure that the _permute prop is a number.
|
||||||
|
// can not use `node.start._permute |= 0;` as it will erase fractional part.
|
||||||
|
if (typeof node.start._permute === "undefined") node.start._permute = 0;
|
||||||
|
|
||||||
|
// if node reached permutation limit - skip over it.
|
||||||
|
// no structural AST changes before this point.
|
||||||
|
if (node.start._permute >= REPLACEMENTS.length) return;
|
||||||
|
|
||||||
|
if (parent instanceof U.AST_Assign
|
||||||
|
&& parent.left === node
|
||||||
|
|| parent instanceof U.AST_Unary
|
||||||
|
&& parent.expression === node
|
||||||
|
&& ["++", "--", "delete"].indexOf(parent.operator) >= 0) {
|
||||||
|
// ignore lvalues
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((parent instanceof U.AST_For || parent instanceof U.AST_ForIn)
|
||||||
|
&& parent.init === node && node instanceof U.AST_Var) {
|
||||||
|
// preserve for (var ...)
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// node specific permutations with no parent logic
|
||||||
|
|
||||||
|
if (node instanceof U.AST_Array) {
|
||||||
|
var expr = node.elements[0];
|
||||||
|
if (expr && !(expr instanceof U.AST_Hole)) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Binary) {
|
||||||
|
var permute = ((node.start._permute += step) * steps | 0) % 4;
|
||||||
|
var expr = [
|
||||||
|
node.left,
|
||||||
|
node.right,
|
||||||
|
][ permute & 1 ];
|
||||||
|
CHANGED = true;
|
||||||
|
return permute < 2 ? expr : wrap_with_console_log(expr);
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_BlockStatement) {
|
||||||
|
if (in_list) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return List.splice(node.body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Call) {
|
||||||
|
var expr = [
|
||||||
|
node.expression,
|
||||||
|
node.args[0],
|
||||||
|
null, // intentional
|
||||||
|
][ ((node.start._permute += step) * steps | 0) % 3 ];
|
||||||
|
if (expr) {
|
||||||
|
CHANGED = true;
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
if (node.expression instanceof U.AST_Function) {
|
||||||
|
// hoist and return expressions from the IIFE function expression
|
||||||
|
var body = node.expression.body;
|
||||||
|
node.expression.body = [];
|
||||||
|
var seq = [];
|
||||||
|
body.forEach(function(node) {
|
||||||
|
var expr = expr instanceof U.AST_Exit ? node.value : node.body;
|
||||||
|
if (expr instanceof U.AST_Node && !is_statement(expr)) {
|
||||||
|
// collect expressions from each statements' body
|
||||||
|
seq.push(expr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
CHANGED = true;
|
||||||
|
return to_sequence(seq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Catch) {
|
||||||
|
// drop catch block
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Conditional) {
|
||||||
|
CHANGED = true;
|
||||||
|
return [
|
||||||
|
node.condition,
|
||||||
|
node.consequent,
|
||||||
|
node.alternative,
|
||||||
|
][ ((node.start._permute += step) * steps | 0) % 3 ];
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Defun) {
|
||||||
|
switch (((node.start._permute += step) * steps | 0) % 2) {
|
||||||
|
case 0:
|
||||||
|
CHANGED = true;
|
||||||
|
return List.skip;
|
||||||
|
default:
|
||||||
|
if (!has_exit(node)) {
|
||||||
|
// hoist function declaration body
|
||||||
|
var body = node.body;
|
||||||
|
node.body = [];
|
||||||
|
body.push(node); // retain function with empty body to be dropped later
|
||||||
|
CHANGED = true;
|
||||||
|
return List.splice(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_DWLoop) {
|
||||||
|
var expr = [
|
||||||
|
node.condition,
|
||||||
|
node.body,
|
||||||
|
null, // intentional
|
||||||
|
][ (node.start._permute * steps | 0) % 3 ];
|
||||||
|
node.start._permute += step;
|
||||||
|
if (!expr) {
|
||||||
|
if (node.body[0] instanceof U.AST_Break) {
|
||||||
|
if (node instanceof U.AST_Do) {
|
||||||
|
CHANGED = true;
|
||||||
|
return List.skip;
|
||||||
|
}
|
||||||
|
expr = node.condition; // AST_While - fall through
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (expr && (expr !== node.body || !has_loopcontrol(expr, node, parent))) {
|
||||||
|
CHANGED = true;
|
||||||
|
return to_statement(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Finally) {
|
||||||
|
// drop finally block
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_For) {
|
||||||
|
var expr = [
|
||||||
|
node.init,
|
||||||
|
node.condition,
|
||||||
|
node.step,
|
||||||
|
node.body,
|
||||||
|
][ (node.start._permute * steps | 0) % 4 ];
|
||||||
|
node.start._permute += step;
|
||||||
|
if (expr && (expr !== node.body || !has_loopcontrol(expr, node, parent))) {
|
||||||
|
CHANGED = true;
|
||||||
|
return to_statement(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_ForIn) {
|
||||||
|
var expr = [
|
||||||
|
node.init,
|
||||||
|
node.object,
|
||||||
|
node.body,
|
||||||
|
][ (node.start._permute * steps | 0) % 3 ];
|
||||||
|
node.start._permute += step;
|
||||||
|
if (expr && (expr !== node.body || !has_loopcontrol(expr, node, parent))) {
|
||||||
|
CHANGED = true;
|
||||||
|
return to_statement(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_If) {
|
||||||
|
var expr = [
|
||||||
|
node.condition,
|
||||||
|
node.body,
|
||||||
|
node.alternative,
|
||||||
|
][ (node.start._permute * steps | 0) % 3 ];
|
||||||
|
node.start._permute += step;
|
||||||
|
if (expr) {
|
||||||
|
// replace if statement with its condition, then block or else block
|
||||||
|
CHANGED = true;
|
||||||
|
return to_statement(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Object) {
|
||||||
|
// first property's value
|
||||||
|
var expr = node.properties[0] instanceof U.AST_ObjectKeyVal && node.properties[0].value;
|
||||||
|
if (expr) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_PropAccess) {
|
||||||
|
var expr = [
|
||||||
|
node.expression,
|
||||||
|
node.property instanceof U.AST_Node && node.property,
|
||||||
|
][ node.start._permute++ % 2 ];
|
||||||
|
if (expr) {
|
||||||
|
CHANGED = true;
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_SimpleStatement) {
|
||||||
|
if (node.body instanceof U.AST_Call && node.body.expression instanceof U.AST_Function) {
|
||||||
|
// hoist simple statement IIFE function expression body
|
||||||
|
node.start._permute++;
|
||||||
|
if (!has_exit(node.body.expression)) {
|
||||||
|
var body = node.body.expression.body;
|
||||||
|
node.body.expression.body = [];
|
||||||
|
CHANGED = true;
|
||||||
|
return List.splice(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Switch) {
|
||||||
|
var expr = [
|
||||||
|
node.expression, // switch expression
|
||||||
|
node.body[0] && node.body[0].expression, // first case expression or undefined
|
||||||
|
node.body[0] && node.body[0], // first case body or undefined
|
||||||
|
][ (node.start._permute * steps | 0) % 4 ];
|
||||||
|
node.start._permute += step;
|
||||||
|
if (expr && (!(expr instanceof U.AST_Statement) || !has_loopcontrol(expr, node, parent))) {
|
||||||
|
CHANGED = true;
|
||||||
|
return expr instanceof U.AST_SwitchBranch ? new U.AST_BlockStatement({
|
||||||
|
body: expr.body.slice(),
|
||||||
|
start: {},
|
||||||
|
}) : to_statement(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Try) {
|
||||||
|
var body = [
|
||||||
|
node.body,
|
||||||
|
node.bcatch && node.bcatch.body,
|
||||||
|
node.bfinally && node.bfinally.body,
|
||||||
|
null, // intentional
|
||||||
|
][ (node.start._permute * steps | 0) % 4 ];
|
||||||
|
node.start._permute += step;
|
||||||
|
if (body) {
|
||||||
|
// replace try statement with try block, catch block, or finally block
|
||||||
|
CHANGED = true;
|
||||||
|
return new U.AST_BlockStatement({
|
||||||
|
body: body,
|
||||||
|
start: {},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// replace try with a break or return if first in try statement
|
||||||
|
if (node.body[0] instanceof U.AST_Break
|
||||||
|
|| node.body[0] instanceof U.AST_Return) {
|
||||||
|
CHANGED = true;
|
||||||
|
return node.body[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Unary) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return node.expression;
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Var) {
|
||||||
|
if (node.definitions.length == 1 && node.definitions[0].value) {
|
||||||
|
// first declaration value
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return to_statement(node.definitions[0].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_LabeledStatement) {
|
||||||
|
if (node.body instanceof U.AST_Statement
|
||||||
|
&& !has_loopcontrol(node.body, node.body, node)) {
|
||||||
|
// replace labelled statement with its non-labelled body
|
||||||
|
node.start._permute = REPLACEMENTS.length;
|
||||||
|
CHANGED = true;
|
||||||
|
return node.body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_list) {
|
||||||
|
// special case to drop object properties and switch branches
|
||||||
|
if (parent instanceof U.AST_Object
|
||||||
|
|| parent instanceof U.AST_Switch && parent.expression != node) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return List.skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace or skip statement
|
||||||
|
if (node instanceof U.AST_Statement) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return List.skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove this node unless its the sole element of a (transient) sequence
|
||||||
|
if (!(parent instanceof U.AST_Sequence) || parent.expressions.length > 1) {
|
||||||
|
node.start._permute++;
|
||||||
|
CHANGED = true;
|
||||||
|
return List.skip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace this node
|
||||||
|
var newNode = is_statement(node) ? new U.AST_EmptyStatement({
|
||||||
|
start: {},
|
||||||
|
}) : U.parse(REPLACEMENTS[node.start._permute % REPLACEMENTS.length | 0], {
|
||||||
|
expression: true,
|
||||||
|
});
|
||||||
|
newNode.start._permute = ++node.start._permute;
|
||||||
|
CHANGED = true;
|
||||||
|
return newNode;
|
||||||
|
}, function(node, in_list) {
|
||||||
|
if (node instanceof U.AST_Sequence) {
|
||||||
|
// expand single-element sequence
|
||||||
|
if (node.expressions.length == 1) return node.expressions[0];
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Try) {
|
||||||
|
// expand orphaned try block
|
||||||
|
if (!node.bcatch && !node.bfinally) return new U.AST_BlockStatement({
|
||||||
|
body: node.body,
|
||||||
|
start: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (node instanceof U.AST_Var) {
|
||||||
|
// remove empty var statement
|
||||||
|
if (node.definitions.length == 0) return in_list ? List.skip : new U.AST_EmptyStatement({
|
||||||
|
start: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var diff_error_message;
|
||||||
|
for (var pass = 1; pass <= 3; ++pass) {
|
||||||
|
var testcase_ast = U.parse(testcase);
|
||||||
|
if (diff_error_message === testcase) {
|
||||||
|
// only difference detected is in error message, so expose that and try again
|
||||||
|
testcase_ast.transform(new U.TreeTransformer(function(node, descend) {
|
||||||
|
if (node.TYPE == "Call" && node.expression.print_to_string() == "console.log") {
|
||||||
|
return to_sequence(node.args);
|
||||||
|
}
|
||||||
|
if (node instanceof U.AST_Catch) {
|
||||||
|
descend(node, this);
|
||||||
|
node.body.unshift(new U.AST_SimpleStatement({
|
||||||
|
body: wrap_with_console_log(new U.AST_SymbolRef(node.argname)),
|
||||||
|
start: {},
|
||||||
|
}));
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
var code = testcase_ast.print_to_string();
|
||||||
|
if (diff = producesDifferentResultWhenMinified(result_cache, code, minify_options, max_timeout)) {
|
||||||
|
testcase = code;
|
||||||
|
differs = diff;
|
||||||
|
} else {
|
||||||
|
testcase_ast = U.parse(testcase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff_error_message = null;
|
||||||
|
testcase_ast.walk(new U.TreeWalker(function(node) {
|
||||||
|
// unshare start props to retain visit data between iterations
|
||||||
|
node.start = JSON.parse(JSON.stringify(node.start));
|
||||||
|
node.start._permute = 0;
|
||||||
|
}));
|
||||||
|
for (var c = 0; c < max_iterations; ++c) {
|
||||||
|
if (verbose && pass == 1 && c % 25 == 0) {
|
||||||
|
log("// reduce test pass " + pass + ", iteration " + c + ": " + testcase.length + " bytes");
|
||||||
|
}
|
||||||
|
var CHANGED = false;
|
||||||
|
var code_ast = testcase_ast.clone(true).transform(tt);
|
||||||
|
if (!CHANGED) break;
|
||||||
|
try {
|
||||||
|
var code = code_ast.print_to_string();
|
||||||
|
} catch (ex) {
|
||||||
|
// AST is not well formed.
|
||||||
|
// no harm done - just log the error, ignore latest change and continue iterating.
|
||||||
|
log("*** Error generating code from AST.");
|
||||||
|
log(ex.stack);
|
||||||
|
log("*** Discarding permutation and continuing.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var diff = producesDifferentResultWhenMinified(result_cache, code, minify_options, max_timeout);
|
||||||
|
if (diff) {
|
||||||
|
if (diff.timed_out) {
|
||||||
|
// can't trust the validity of `code_ast` and `code` when timed out.
|
||||||
|
// no harm done - just ignore latest change and continue iterating.
|
||||||
|
} else if (diff.error) {
|
||||||
|
// something went wrong during minify() - could be malformed AST or genuine bug.
|
||||||
|
// no harm done - just log code & error, ignore latest change and continue iterating.
|
||||||
|
log("*** Error during minification.");
|
||||||
|
log(code);
|
||||||
|
log(diff.error.stack);
|
||||||
|
log("*** Discarding permutation and continuing.");
|
||||||
|
} else if (is_error(diff.unminified_result)
|
||||||
|
&& is_error(diff.minified_result)
|
||||||
|
&& diff.unminified_result.name == diff.minified_result.name) {
|
||||||
|
// ignore difference in error messages caused by minification
|
||||||
|
diff_error_message = testcase;
|
||||||
|
} else {
|
||||||
|
// latest permutation is valid, so use it as the basis of new changes
|
||||||
|
testcase_ast = code_ast;
|
||||||
|
testcase = code;
|
||||||
|
differs = diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c == 0) break;
|
||||||
|
if (verbose) {
|
||||||
|
log("// reduce test pass " + pass + ": " + testcase.length + " bytes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testcase = try_beautify(result_cache, testcase, minify_options, differs.unminified_result, max_timeout);
|
||||||
|
var lines = [ "" ];
|
||||||
|
var unminified_result = strip_color_codes(differs.unminified_result);
|
||||||
|
var minified_result = strip_color_codes(differs.minified_result);
|
||||||
|
if (trim_trailing_whitespace(unminified_result) == trim_trailing_whitespace(minified_result)) {
|
||||||
|
lines.push(
|
||||||
|
"// (stringified)",
|
||||||
|
"// output: " + JSON.stringify(unminified_result),
|
||||||
|
"// minify: " + JSON.stringify(minified_result)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
lines.push(
|
||||||
|
"// output: " + to_comment(unminified_result),
|
||||||
|
"// minify: " + to_comment(minified_result)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
lines.push("// options: " + to_comment(minify_options_json));
|
||||||
|
testcase.code += lines.join("\n");
|
||||||
|
testcase.warnings = warnings;
|
||||||
|
return testcase;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function strip_color_codes(value) {
|
||||||
|
return ("" + value).replace(/\u001b\[\d+m/g, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
function to_comment(value) {
|
||||||
|
return ("" + value).replace(/\n/g, "\n// ");
|
||||||
|
}
|
||||||
|
|
||||||
|
function trim_trailing_whitespace(value) {
|
||||||
|
return ("" + value).replace(/\s+$/, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
function try_beautify(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) {
|
||||||
|
var found = false;
|
||||||
|
var tw = new U.TreeWalker(function(node) {
|
||||||
|
if (found) return found;
|
||||||
|
if (node instanceof U.AST_Exit) {
|
||||||
|
return found = true;
|
||||||
|
}
|
||||||
|
if (node instanceof U.AST_Scope && node !== fn) {
|
||||||
|
return true; // don't descend into nested functions
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fn.walk(tw);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
function has_loopcontrol(body, loop, label) {
|
||||||
|
var found = false;
|
||||||
|
var tw = new U.TreeWalker(function(node) {
|
||||||
|
if (found) return true;
|
||||||
|
if (node instanceof U.AST_LoopControl && this.loopcontrol_target(node) === loop) {
|
||||||
|
return found = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (label instanceof U.AST_LabeledStatement) tw.push(label);
|
||||||
|
tw.push(loop);
|
||||||
|
body.walk(tw);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_error(result) {
|
||||||
|
return typeof result == "object" && typeof result.name == "string" && typeof result.message == "string";
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_timed_out(result) {
|
||||||
|
return is_error(result) && /timed out/.test(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_statement(node) {
|
||||||
|
return node instanceof U.AST_Statement && !(node instanceof U.AST_Function);
|
||||||
|
}
|
||||||
|
|
||||||
|
function merge_sequence(array, node) {
|
||||||
|
if (node instanceof U.AST_Sequence) {
|
||||||
|
array.push.apply(array, node.expressions);
|
||||||
|
} else {
|
||||||
|
array.push(node);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function to_sequence(expressions) {
|
||||||
|
if (expressions.length == 0) return new U.AST_Number({value: 0, start: {}});
|
||||||
|
if (expressions.length == 1) return expressions[0];
|
||||||
|
return new U.AST_Sequence({
|
||||||
|
expressions: expressions.reduce(merge_sequence, []),
|
||||||
|
start: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function to_statement(node) {
|
||||||
|
return is_statement(node) ? node : new U.AST_SimpleStatement({
|
||||||
|
body: node,
|
||||||
|
start: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrap_with_console_log(node) {
|
||||||
|
// wrap with console.log()
|
||||||
|
return new U.AST_Call({
|
||||||
|
expression: new U.AST_Dot({
|
||||||
|
expression: new U.AST_SymbolRef({
|
||||||
|
name: "console",
|
||||||
|
start: {},
|
||||||
|
}),
|
||||||
|
property: "log",
|
||||||
|
start: {},
|
||||||
|
}),
|
||||||
|
args: [ node ],
|
||||||
|
start: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_code(result_cache, code, toplevel, timeout) {
|
||||||
|
var key = crypto.createHash("sha1").update(code).digest("base64");
|
||||||
|
return result_cache[key] || (result_cache[key] = sandbox.run_code(code, toplevel, timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
function producesDifferentResultWhenMinified(result_cache, code, minify_options, max_timeout) {
|
||||||
|
var minified = U.minify(code, minify_options);
|
||||||
|
if (minified.error) return minified;
|
||||||
|
|
||||||
|
var toplevel = sandbox.has_toplevel(minify_options);
|
||||||
|
var elapsed = Date.now();
|
||||||
|
var unminified_result = run_code(result_cache, code, toplevel, max_timeout);
|
||||||
|
elapsed = Date.now() - elapsed;
|
||||||
|
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)) {
|
||||||
|
return is_timed_out(unminified_result) && is_timed_out(minified_result) && {
|
||||||
|
timed_out: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
unminified_result: unminified_result,
|
||||||
|
minified_result: minified_result,
|
||||||
|
elapsed: elapsed,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Error.stackTraceLimit = Infinity;
|
||||||
@@ -54,14 +54,15 @@ function createContext() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.run_code = function(code, toplevel) {
|
exports.run_code = function(code, toplevel, timeout) {
|
||||||
|
timeout = timeout || 5000;
|
||||||
var stdout = "";
|
var stdout = "";
|
||||||
var original_write = process.stdout.write;
|
var original_write = process.stdout.write;
|
||||||
process.stdout.write = function(chunk) {
|
process.stdout.write = function(chunk) {
|
||||||
stdout += chunk;
|
stdout += chunk;
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
vm.runInContext(toplevel ? "(function(){" + code + "})()" : code, createContext(), { timeout: 5000 });
|
vm.runInContext(toplevel ? "(function(){" + code + "})()" : code, createContext(), { timeout: timeout });
|
||||||
return stdout;
|
return stdout;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
return ex;
|
return ex;
|
||||||
@@ -76,8 +77,9 @@ function strip_func_ids(text) {
|
|||||||
|
|
||||||
exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
|
exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
|
||||||
if (typeof expected != typeof actual) return false;
|
if (typeof expected != typeof actual) return false;
|
||||||
if (typeof expected != "string") {
|
if (typeof expected == "object" && typeof expected.name == "string" && typeof expected.message == "string") {
|
||||||
if (expected.name != actual.name) return false;
|
if (expected.name !== actual.name) return false;
|
||||||
|
if (typeof actual.message != "string") return false;
|
||||||
expected = expected.message.slice(expected.message.lastIndexOf("\n") + 1);
|
expected = expected.message.slice(expected.message.lastIndexOf("\n") + 1);
|
||||||
actual = actual.message.slice(actual.message.lastIndexOf("\n") + 1);
|
actual = actual.message.slice(actual.message.lastIndexOf("\n") + 1);
|
||||||
}
|
}
|
||||||
@@ -85,3 +87,8 @@ exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expec
|
|||||||
} : function(expected, actual) {
|
} : function(expected, actual) {
|
||||||
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);
|
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);
|
||||||
};
|
};
|
||||||
|
exports.has_toplevel = function(options) {
|
||||||
|
return options.toplevel
|
||||||
|
|| options.mangle && options.mangle.toplevel
|
||||||
|
|| options.compress && options.compress.toplevel;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
var child_process = require("child_process");
|
|
||||||
var https = require("https");
|
|
||||||
var url = require("url");
|
|
||||||
|
|
||||||
var period = 45 * 60 * 1000;
|
|
||||||
var wait = 2 * 60 * 1000;
|
|
||||||
var ping = 5 * 60 * 1000;
|
|
||||||
if (process.argv[2] == "run") {
|
|
||||||
var endTime = Date.now() + period;
|
|
||||||
for (var i = 0; i < 2; i++) spawn(endTime);
|
|
||||||
} else if (process.argv.length > 2) {
|
|
||||||
var token = process.argv[2];
|
|
||||||
var branch = process.argv[3] || "v" + require("../package.json").version;
|
|
||||||
var repository = encodeURIComponent(process.argv[4] || "mishoo/UglifyJS2");
|
|
||||||
var concurrency = process.argv[5] || 1;
|
|
||||||
var platform = process.argv[6] || "latest";
|
|
||||||
(function request() {
|
|
||||||
setTimeout(request, (period + wait) / concurrency);
|
|
||||||
var options = url.parse("https://api.travis-ci.org/repo/" + repository + "/requests");
|
|
||||||
options.method = "POST";
|
|
||||||
options.headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"Travis-API-Version": 3,
|
|
||||||
"Authorization": "token " + token
|
|
||||||
};
|
|
||||||
https.request(options, function(res) {
|
|
||||||
console.log("HTTP", res.statusCode);
|
|
||||||
console.log(JSON.stringify(res.headers, null, 2));
|
|
||||||
console.log();
|
|
||||||
res.setEncoding("utf8");
|
|
||||||
res.on("data", console.log);
|
|
||||||
}).on("error", console.error).end(JSON.stringify({
|
|
||||||
request: {
|
|
||||||
message: "ufuzz testing",
|
|
||||||
branch: branch,
|
|
||||||
config: {
|
|
||||||
cache: false,
|
|
||||||
env: "NODE=" + platform,
|
|
||||||
script: "node test/travis-ufuzz run"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
})();
|
|
||||||
} else {
|
|
||||||
console.log("Usage: test/travis-ufuzz.js <token> [branch] [repository] [concurrency] [platform]");
|
|
||||||
}
|
|
||||||
|
|
||||||
function spawn(endTime) {
|
|
||||||
var child = child_process.spawn("node", [
|
|
||||||
"--max-old-space-size=2048",
|
|
||||||
"test/ufuzz"
|
|
||||||
], {
|
|
||||||
stdio: [ "ignore", "pipe", "pipe" ]
|
|
||||||
}).on("exit", respawn);
|
|
||||||
var line = "";
|
|
||||||
child.stdout.on("data", function(data) {
|
|
||||||
line += data;
|
|
||||||
});
|
|
||||||
child.stderr.on("data", function() {
|
|
||||||
process.exitCode = 1;
|
|
||||||
}).pipe(process.stdout);
|
|
||||||
var keepAlive = setInterval(function() {
|
|
||||||
var end = line.lastIndexOf("\r");
|
|
||||||
console.log(line.slice(line.lastIndexOf("\r", end - 1) + 1, end));
|
|
||||||
line = line.slice(end + 1);
|
|
||||||
}, ping);
|
|
||||||
var timer = setTimeout(function() {
|
|
||||||
clearInterval(keepAlive);
|
|
||||||
child.removeListener("exit", respawn);
|
|
||||||
child.kill();
|
|
||||||
}, endTime - Date.now());
|
|
||||||
|
|
||||||
function respawn() {
|
|
||||||
console.log(line);
|
|
||||||
clearInterval(keepAlive);
|
|
||||||
clearTimeout(timer);
|
|
||||||
spawn(endTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
46
test/ufuzz/job.js
Normal file
46
test/ufuzz/job.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
var child_process = require("child_process");
|
||||||
|
|
||||||
|
var ping = 5 * 60 * 1000;
|
||||||
|
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",
|
||||||
|
"test/ufuzz"
|
||||||
|
], {
|
||||||
|
stdio: [ "ignore", "pipe", "pipe" ]
|
||||||
|
}).on("exit", respawn);
|
||||||
|
var stdout = "";
|
||||||
|
child.stdout.on("data", function(data) {
|
||||||
|
stdout += data;
|
||||||
|
});
|
||||||
|
var stderr = "";
|
||||||
|
child.stderr.on("data", trap).pipe(process.stdout);
|
||||||
|
var keepAlive = setInterval(function() {
|
||||||
|
var end = stdout.lastIndexOf("\r");
|
||||||
|
console.log(stdout.slice(stdout.lastIndexOf("\r", end - 1) + 1, end));
|
||||||
|
stdout = stdout.slice(end + 1);
|
||||||
|
}, ping);
|
||||||
|
var timer = setTimeout(function() {
|
||||||
|
clearInterval(keepAlive);
|
||||||
|
child.removeListener("exit", respawn);
|
||||||
|
child.kill();
|
||||||
|
}, endTime - Date.now());
|
||||||
|
|
||||||
|
function respawn() {
|
||||||
|
console.log(stdout.replace(/[^\r\n]*\r/g, ""));
|
||||||
|
clearInterval(keepAlive);
|
||||||
|
clearTimeout(timer);
|
||||||
|
spawn(endTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
function trap(data) {
|
||||||
|
stderr += data;
|
||||||
|
if (~stderr.indexOf("\nminify(options):\n")) {
|
||||||
|
process.exitCode = 1;
|
||||||
|
child.stderr.removeListener("data", trap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2702,8 +2702,10 @@
|
|||||||
"attrChange",
|
"attrChange",
|
||||||
"attrName",
|
"attrName",
|
||||||
"attributeChangedCallback",
|
"attributeChangedCallback",
|
||||||
|
"attributeFilter",
|
||||||
"attributeName",
|
"attributeName",
|
||||||
"attributeNamespace",
|
"attributeNamespace",
|
||||||
|
"attributeOldValue",
|
||||||
"attributeStyleMap",
|
"attributeStyleMap",
|
||||||
"attributes",
|
"attributes",
|
||||||
"audioTracks",
|
"audioTracks",
|
||||||
@@ -3025,6 +3027,8 @@
|
|||||||
"charCode",
|
"charCode",
|
||||||
"charCodeAt",
|
"charCodeAt",
|
||||||
"charIndex",
|
"charIndex",
|
||||||
|
"characterData",
|
||||||
|
"characterDataOldValue",
|
||||||
"characterSet",
|
"characterSet",
|
||||||
"charging",
|
"charging",
|
||||||
"chargingTime",
|
"chargingTime",
|
||||||
@@ -3036,6 +3040,7 @@
|
|||||||
"checkValidity",
|
"checkValidity",
|
||||||
"checked",
|
"checked",
|
||||||
"childElementCount",
|
"childElementCount",
|
||||||
|
"childList",
|
||||||
"childNodes",
|
"childNodes",
|
||||||
"children",
|
"children",
|
||||||
"chrome",
|
"chrome",
|
||||||
@@ -6150,6 +6155,7 @@
|
|||||||
"substring",
|
"substring",
|
||||||
"substringData",
|
"substringData",
|
||||||
"subtle",
|
"subtle",
|
||||||
|
"subtree",
|
||||||
"suffix",
|
"suffix",
|
||||||
"suffixes",
|
"suffixes",
|
||||||
"summary",
|
"summary",
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user