Compare commits
193 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffcce28ce1 | ||
|
|
9c0feb69e5 | ||
|
|
bc6e105174 | ||
|
|
b91a2459c0 | ||
|
|
b7a57fc69d | ||
|
|
2dbe40b01b | ||
|
|
813ac3ba96 | ||
|
|
220dc95c0d | ||
|
|
8f0521d51d | ||
|
|
f9946767c9 | ||
|
|
58ac5b9bd5 | ||
|
|
66140b459e | ||
|
|
1786c69070 | ||
|
|
95ef4d5377 | ||
|
|
04017215cc | ||
|
|
142bd1bd1a | ||
|
|
8cb509d50e | ||
|
|
baf4903aa7 | ||
|
|
35465d590e | ||
|
|
ccd91b9952 | ||
|
|
47a5e6e17a | ||
|
|
090ee895e1 | ||
|
|
1cd1a1e5ee | ||
|
|
1d835ac17d | ||
|
|
9e07ac4102 | ||
|
|
92d1391e5e | ||
|
|
b4ff6d0f2d | ||
|
|
9882a9f4af | ||
|
|
40f36b9e01 | ||
|
|
6e105c5ca6 | ||
|
|
af35cd32f2 | ||
|
|
7de8daa4b1 | ||
|
|
305a4bdcee | ||
|
|
3472cf1a90 | ||
|
|
6d4c0fa6fa | ||
|
|
3cca0d6249 | ||
|
|
12ac49b970 | ||
|
|
8c670cae93 | ||
|
|
0e3da27727 | ||
|
|
13cdc167a2 | ||
|
|
51803cdcb2 | ||
|
|
8fa470c17c | ||
|
|
90410f9fc3 | ||
|
|
ef3831437d | ||
|
|
171c544705 | ||
|
|
3c609e2f4a | ||
|
|
f0ae03ed39 | ||
|
|
31c6b45036 | ||
|
|
3ac533e644 | ||
|
|
38a46c86d7 | ||
|
|
0f0759ec15 | ||
|
|
7f501f9fed | ||
|
|
72844eb5a4 | ||
|
|
09d93cc6c8 | ||
|
|
dd1374aa8a | ||
|
|
fdf2e8c5b0 | ||
|
|
a9d934ab4e | ||
|
|
2a053710bd | ||
|
|
219aac6a84 | ||
|
|
2039185051 | ||
|
|
ad27c14202 | ||
|
|
a62b086184 | ||
|
|
335456cf77 | ||
|
|
d64d0b0bec | ||
|
|
3ac575f2e8 | ||
|
|
d33a3a3253 | ||
|
|
d7456a2dc2 | ||
|
|
d97672613d | ||
|
|
30761eede5 | ||
|
|
fb30aeccaf | ||
|
|
226aa1f76b | ||
|
|
6e235602fb | ||
|
|
980fcbb56b | ||
|
|
375ebe316d | ||
|
|
2500930234 | ||
|
|
2f0da2ff05 | ||
|
|
83a3cbf151 | ||
|
|
da8d154571 | ||
|
|
e33c727e8b | ||
|
|
f886b3fb2b | ||
|
|
b1cc15e85b | ||
|
|
3aa765e429 | ||
|
|
93d084a1d1 | ||
|
|
c7a3e09407 | ||
|
|
09525c7530 | ||
|
|
a7e15fe73c | ||
|
|
a31c27c7cf | ||
|
|
1caf7c7bd2 | ||
|
|
0eb0c9b388 | ||
|
|
7dc61cdc89 | ||
|
|
af1b2f30c9 | ||
|
|
37b4fc7e31 | ||
|
|
da85d102e3 | ||
|
|
35fe1092d3 | ||
|
|
f2d486e771 | ||
|
|
fee677786e | ||
|
|
aa83ecdb3b | ||
|
|
a153176469 | ||
|
|
1c6384b6a5 | ||
|
|
e8db526f51 | ||
|
|
fa13ed4391 | ||
|
|
23f0dca992 | ||
|
|
45ab3b51d8 | ||
|
|
49670d216b | ||
|
|
e2237d8cd2 | ||
|
|
91f078fe35 | ||
|
|
a546cb881d | ||
|
|
84d5dffd9f | ||
|
|
a8e286f7e1 | ||
|
|
9b05494ebc | ||
|
|
30ef20a208 | ||
|
|
a4002ef467 | ||
|
|
9d758a216b | ||
|
|
af13f8dd2c | ||
|
|
88423f2574 | ||
|
|
ee632a5519 | ||
|
|
dfe47bcc42 | ||
|
|
6d3dcaa59e | ||
|
|
1bc0df1569 | ||
|
|
a98ba994bd | ||
|
|
cd671221c5 | ||
|
|
bce3919748 | ||
|
|
61b66e83f1 | ||
|
|
a5db8cd14c | ||
|
|
2021c2fa3e | ||
|
|
484d3fd8c7 | ||
|
|
3bf8699f95 | ||
|
|
58c24f8007 | ||
|
|
e61bc34eb1 | ||
|
|
8b2cfd45fa | ||
|
|
ae9f56be10 | ||
|
|
9aed0e3a73 | ||
|
|
88850a6e05 | ||
|
|
9e881407bd | ||
|
|
3188db7b90 | ||
|
|
a82ca62b66 | ||
|
|
e9465717ab | ||
|
|
e89031f1af | ||
|
|
596fad182e | ||
|
|
ed69adedcd | ||
|
|
1dbf7d4a3a | ||
|
|
2a9d0fc6fb | ||
|
|
45db96679e | ||
|
|
1d15f51238 | ||
|
|
ed7c82fa5e | ||
|
|
3b273cecac | ||
|
|
d764b6cc3b | ||
|
|
08c4729eb4 | ||
|
|
5561d3e7f3 | ||
|
|
491d6ce1d5 | ||
|
|
cd55eeb77c | ||
|
|
3230952d57 | ||
|
|
df3bb8028a | ||
|
|
28b7b15da1 | ||
|
|
aa37b19698 | ||
|
|
02e889e449 | ||
|
|
486ce00b8e | ||
|
|
eb481cee8c | ||
|
|
fbc9d8009b | ||
|
|
04fd3d90f8 | ||
|
|
a489f8cb5e | ||
|
|
e2e4b7fb37 | ||
|
|
c97ad98f92 | ||
|
|
b24eb22c6b | ||
|
|
06ba4e2ce8 | ||
|
|
0eb4577a82 | ||
|
|
43498769f0 | ||
|
|
60c0bc1e6b | ||
|
|
6a5c63e1e3 | ||
|
|
d47ea77811 | ||
|
|
7840746bd9 | ||
|
|
49ea629f3f | ||
|
|
13c72a986c | ||
|
|
08af3eae44 | ||
|
|
27bdcbbd83 | ||
|
|
2c4d7d66ef | ||
|
|
d1cc5270a3 | ||
|
|
75c5b6029b | ||
|
|
fa14a9cfcd | ||
|
|
aeb9ea5ac2 | ||
|
|
798841be82 | ||
|
|
cc6eb4b15f | ||
|
|
14eee81dc6 | ||
|
|
55ebb27878 | ||
|
|
87046410ef | ||
|
|
f9b3198714 | ||
|
|
48b62393a4 | ||
|
|
a00f8dade7 | ||
|
|
9daa2fb6f5 | ||
|
|
8d81d264f4 | ||
|
|
5ef7060098 | ||
|
|
938368ba21 | ||
|
|
fe2f1965d6 |
9
.github/workflows/ci.yml
vendored
9
.github/workflows/ci.yml
vendored
@@ -1,5 +1,8 @@
|
|||||||
name: CI
|
name: CI
|
||||||
on: [ push, pull_request ]
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
strategy:
|
strategy:
|
||||||
@@ -19,7 +22,7 @@ jobs:
|
|||||||
TYPE: ${{ matrix.script }}
|
TYPE: ${{ matrix.script }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/cache@v1
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: tmp
|
path: tmp
|
||||||
key: tmp ${{ matrix.script }}
|
key: tmp ${{ matrix.script }}
|
||||||
@@ -29,7 +32,7 @@ jobs:
|
|||||||
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||||
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add $NODE && nvs use $NODE'; do
|
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add $NODE && nvs use $NODE'; do
|
||||||
cd ~/.nvs
|
cd ~/.nvs
|
||||||
git clean -xdf
|
while !(git clean -xdf); do echo "'git clean' failed - retrying..."; done
|
||||||
cd -
|
cd -
|
||||||
done
|
done
|
||||||
. ~/.nvs/nvs.sh --version
|
. ~/.nvs/nvs.sh --version
|
||||||
|
|||||||
20
.github/workflows/ufuzz.yml
vendored
20
.github/workflows/ufuzz.yml
vendored
@@ -1,7 +1,13 @@
|
|||||||
name: Fuzzing
|
name: Fuzzing
|
||||||
on:
|
on:
|
||||||
|
pull_request:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "*/8 * * * *"
|
- cron: "*/5 * * * *"
|
||||||
|
env:
|
||||||
|
BASE_URL: https://api.github.com/repos/${{ github.repository }}
|
||||||
|
CAUSE: ${{ github.event_name }}
|
||||||
|
RUN_NUM: ${{ github.run_number }}
|
||||||
|
TOKEN: ${{ github.token }}
|
||||||
jobs:
|
jobs:
|
||||||
ufuzz:
|
ufuzz:
|
||||||
strategy:
|
strategy:
|
||||||
@@ -16,13 +22,13 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||||
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add 10 && nvs use 10'; do
|
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add 8 && nvs use 8'; do
|
||||||
cd ~/.nvs
|
cd ~/.nvs
|
||||||
git clean -xdf
|
while !(git clean -xdf); do echo "'git clean' failed - retrying..."; done
|
||||||
cd -
|
cd -
|
||||||
done
|
done
|
||||||
. ~/.nvs/nvs.sh --version
|
. ~/.nvs/nvs.sh --version
|
||||||
nvs use 10
|
nvs use 8
|
||||||
node --version
|
node --version
|
||||||
npm config set audit false
|
npm config set audit false
|
||||||
npm config set optional false
|
npm config set optional false
|
||||||
@@ -31,4 +37,8 @@ jobs:
|
|||||||
npm config set update-notifier false
|
npm config set update-notifier false
|
||||||
npm --version
|
npm --version
|
||||||
while !(npm install); do echo "'npm install' failed - retrying..."; done
|
while !(npm install); do echo "'npm install' failed - retrying..."; done
|
||||||
node test/ufuzz/job 3600000
|
if [[ $CAUSE == "schedule" ]]; then
|
||||||
|
node test/ufuzz/job $BASE_URL $TOKEN $RUN_NUM
|
||||||
|
else
|
||||||
|
node test/ufuzz/job 5000
|
||||||
|
fi
|
||||||
|
|||||||
33
README.md
33
README.md
@@ -212,13 +212,12 @@ Example:
|
|||||||
To enable the mangler you need to pass `--mangle` (`-m`). The following
|
To enable the mangler you need to pass `--mangle` (`-m`). The following
|
||||||
(comma-separated) options are supported:
|
(comma-separated) options are supported:
|
||||||
|
|
||||||
- `toplevel` (default `false`) -- mangle names declared in the top level scope.
|
- `eval` (default `false`) -- mangle names visible in scopes where `eval` or
|
||||||
|
`with` are used.
|
||||||
|
|
||||||
- `eval` (default `false`) -- mangle names visible in scopes where `eval` or `with` are used.
|
- `reserved` (default: `[]`) -- when mangling is enabled but you want to
|
||||||
|
prevent certain names from being mangled, you can declare those names with
|
||||||
When mangling is enabled but you want to prevent certain names from being
|
`--mangle reserved` — pass a comma-separated list of names. For example:
|
||||||
mangled, you can declare those names with `--mangle reserved` — pass a
|
|
||||||
comma-separated list of names. For example:
|
|
||||||
|
|
||||||
uglifyjs ... -m reserved=['$','require','exports']
|
uglifyjs ... -m reserved=['$','require','exports']
|
||||||
|
|
||||||
@@ -657,8 +656,8 @@ to be `false` and all symbol names will be omitted.
|
|||||||
- `hoist_props` (default: `true`) -- hoist properties from constant object and
|
- `hoist_props` (default: `true`) -- hoist properties from constant object and
|
||||||
array literals into regular variables subject to a set of constraints. For example:
|
array literals into regular variables subject to a set of constraints. For example:
|
||||||
`var o={p:1, q:2}; f(o.p, o.q);` is converted to `f(1, 2);`. Note: `hoist_props`
|
`var o={p:1, q:2}; f(o.p, o.q);` is converted to `f(1, 2);`. Note: `hoist_props`
|
||||||
works best with `mangle` enabled, the `compress` option `passes` set to `2` or higher,
|
works best with `toplevel` and `mangle` enabled, alongside with `compress` option
|
||||||
and the `compress` option `toplevel` enabled.
|
`passes` set to `2` or higher.
|
||||||
|
|
||||||
- `hoist_vars` (default: `false`) -- hoist `var` declarations (this is `false`
|
- `hoist_vars` (default: `false`) -- hoist `var` declarations (this is `false`
|
||||||
by default because it seems to increase the size of the output in general)
|
by default because it seems to increase the size of the output in general)
|
||||||
@@ -689,6 +688,8 @@ to be `false` and all symbol names will be omitted.
|
|||||||
- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops
|
- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops
|
||||||
when we can statically determine the condition.
|
when we can statically determine the condition.
|
||||||
|
|
||||||
|
- `merge_vars` (default: `true`) -- combine and reuse variables.
|
||||||
|
|
||||||
- `negate_iife` (default: `true`) -- negate "Immediately-Called Function Expressions"
|
- `negate_iife` (default: `true`) -- negate "Immediately-Called Function Expressions"
|
||||||
where the return value is discarded, to avoid the parens that the
|
where the return value is discarded, to avoid the parens that the
|
||||||
code generator would insert.
|
code generator would insert.
|
||||||
@@ -1157,3 +1158,19 @@ To allow for better optimizations, the compiler makes various assumptions:
|
|||||||
- Object properties can be added, removed and modified (not prevented with
|
- Object properties can be added, removed and modified (not prevented with
|
||||||
`Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
|
`Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
|
||||||
`Object.preventExtensions()` or `Object.seal()`).
|
`Object.preventExtensions()` or `Object.seal()`).
|
||||||
|
- When `toplevel` is enabled, UglifyJS effectively assumes input code is wrapped
|
||||||
|
within `function(){ ... }`, thus forbids aliasing of declared global variables:
|
||||||
|
```js
|
||||||
|
A = "FAIL";
|
||||||
|
var B = "FAIL";
|
||||||
|
// can be `global`, `self`, `window` etc.
|
||||||
|
var top = function() {
|
||||||
|
return this;
|
||||||
|
}();
|
||||||
|
// "PASS"
|
||||||
|
top.A = "PASS";
|
||||||
|
console.log(A);
|
||||||
|
// "FAIL" after compress and/or mangle
|
||||||
|
top.B = "PASS";
|
||||||
|
console.log(B);
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
build: off
|
|
||||||
matrix:
|
|
||||||
fast_finish: true
|
|
||||||
test_script:
|
|
||||||
- echo No longer in use
|
|
||||||
395
bin/uglifyjs
395
bin/uglifyjs
@@ -8,26 +8,58 @@ require("../tools/exit");
|
|||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var info = require("../package.json");
|
var info = require("../package.json");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var program = require("commander");
|
|
||||||
var UglifyJS = require("../tools/node");
|
var UglifyJS = require("../tools/node");
|
||||||
|
|
||||||
var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
|
var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
|
||||||
var files = {};
|
var files = {};
|
||||||
var options = {
|
var options = {};
|
||||||
compress: false,
|
var short_forms = {
|
||||||
mangle: false
|
b: "beautify",
|
||||||
|
c: "compress",
|
||||||
|
d: "define",
|
||||||
|
e: "enclose",
|
||||||
|
h: "help",
|
||||||
|
m: "mangle",
|
||||||
|
o: "output",
|
||||||
|
O: "output-opts",
|
||||||
|
p: "parse",
|
||||||
|
v: "version",
|
||||||
|
V: "version",
|
||||||
};
|
};
|
||||||
program.version(info.name + " " + info.version);
|
var args = process.argv.slice(2);
|
||||||
program.parseArgv = program.parse;
|
var paths = [];
|
||||||
program.parse = undefined;
|
var output, nameCache;
|
||||||
if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
|
var specified = {};
|
||||||
else if (process.argv.indexOf("options") >= 0) program.helpInformation = function() {
|
while (args.length) {
|
||||||
|
var arg = args.shift();
|
||||||
|
if (arg[0] != "-") {
|
||||||
|
paths.push(arg);
|
||||||
|
} else if (arg == "--") {
|
||||||
|
paths = paths.concat(args);
|
||||||
|
break;
|
||||||
|
} else if (arg[1] == "-") {
|
||||||
|
process_option(arg.slice(2));
|
||||||
|
} else [].forEach.call(arg.slice(1), function(letter, index, arg) {
|
||||||
|
if (!(letter in short_forms)) fatal("invalid option -" + letter);
|
||||||
|
process_option(short_forms[letter], index + 1 < arg.length);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function process_option(name, no_value) {
|
||||||
|
specified[name] = true;
|
||||||
|
switch (name) {
|
||||||
|
case "help":
|
||||||
|
switch (read_value()) {
|
||||||
|
case "ast":
|
||||||
|
print(UglifyJS.describe_ast());
|
||||||
|
break;
|
||||||
|
case "options":
|
||||||
var text = [];
|
var text = [];
|
||||||
var toplevels = [];
|
var toplevels = [];
|
||||||
var padding = "";
|
var padding = "";
|
||||||
var options = UglifyJS.default_options();
|
var defaults = UglifyJS.default_options();
|
||||||
for (var name in options) {
|
for (var name in defaults) {
|
||||||
var option = options[name];
|
var option = defaults[name];
|
||||||
if (option && typeof option == "object") {
|
if (option && typeof option == "object") {
|
||||||
text.push("--" + ({
|
text.push("--" + ({
|
||||||
output: "beautify",
|
output: "beautify",
|
||||||
@@ -46,147 +78,182 @@ else if (process.argv.indexOf("options") >= 0) program.helpInformation = functio
|
|||||||
toplevels.forEach(function(tokens) {
|
toplevels.forEach(function(tokens) {
|
||||||
text.push("--" + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
|
text.push("--" + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
|
||||||
});
|
});
|
||||||
return text.join("\n");
|
print(text.join("\n"));
|
||||||
};
|
break;
|
||||||
program.option("-p, --parse <options>", "Specify parser options.", parse_js());
|
default:
|
||||||
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js());
|
print([
|
||||||
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
|
"Usage: uglifyjs [files...] [options]",
|
||||||
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
|
"",
|
||||||
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js());
|
"Options:",
|
||||||
program.option("-O, --output-opts [options]", "Output options (beautify disabled).", parse_js());
|
" -h, --help Print usage information.",
|
||||||
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
" `--help options` for details on available options.",
|
||||||
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
" -v, -V, --version Print version number.",
|
||||||
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
" -p, --parse <options> Specify parser options.",
|
||||||
program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("define"));
|
" -c, --compress [options] Enable compressor/specify compressor options.",
|
||||||
program.option("-e, --enclose [arg[,...][:value[,...]]]", "Embed everything in a big function, with configurable argument(s) & value(s).");
|
" -m, --mangle [options] Mangle names/specify mangler options.",
|
||||||
program.option("--ie8", "Support non-standard Internet Explorer 8.");
|
" --mangle-props [options] Mangle properties/specify mangler options.",
|
||||||
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
|
" -b, --beautify [options] Beautify output/specify output options.",
|
||||||
program.option("--name-cache <file>", "File to hold mangled name mappings.");
|
" -O, --output-opts <options> Output options (beautify disabled).",
|
||||||
program.option("--rename", "Force symbol expansion.");
|
" -o, --output <file> Output file (default STDOUT).",
|
||||||
program.option("--no-rename", "Disable symbol expansion.");
|
" --comments [filter] Preserve copyright comments in the output.",
|
||||||
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
|
" --config-file <file> Read minify() options from JSON file.",
|
||||||
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_js());
|
" -d, --define <expr>[=value] Global definitions.",
|
||||||
program.option("--timings", "Display operations run time on STDERR.");
|
" -e, --enclose [arg[,...][:value[,...]]] Embed everything in a big function, with configurable argument(s) & value(s).",
|
||||||
program.option("--toplevel", "Compress and/or mangle variables in toplevel scope.");
|
" --ie8 Support non-standard Internet Explorer 8.",
|
||||||
program.option("--validate", "Perform validation during AST manipulations.");
|
" --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name.",
|
||||||
program.option("--verbose", "Print diagnostic messages.");
|
" --name-cache <file> File to hold mangled name mappings.",
|
||||||
program.option("--warn", "Print warning messages.");
|
" --rename Force symbol expansion.",
|
||||||
program.option("--wrap <name>", "Embed everything as a function with “exports” corresponding to “name” globally.");
|
" --no-rename Disable symbol expansion.",
|
||||||
program.option("--reduce-test", "Reduce a standalone `console.log` based test case.");
|
" --self Build UglifyJS as a library (implies --wrap UglifyJS)",
|
||||||
program.arguments("[files...]").parseArgv(process.argv);
|
" --source-map [options] Enable source map/specify source map options.",
|
||||||
if (program.configFile) {
|
" --timings Display operations run time on STDERR.",
|
||||||
options = JSON.parse(read_file(program.configFile));
|
" --toplevel Compress and/or mangle variables in toplevel scope.",
|
||||||
if (options.mangle && options.mangle.properties && options.mangle.properties.regex) {
|
" --validate Perform validation during AST manipulations.",
|
||||||
options.mangle.properties.regex = UglifyJS.parse(options.mangle.properties.regex, {
|
" --verbose Print diagnostic messages.",
|
||||||
expression: true
|
" --warn Print warning messages.",
|
||||||
|
" --wrap <name> Embed everything as a function with “exports” corresponding to “name” globally.",
|
||||||
|
" --reduce-test Reduce a standalone test case (assumes cloned repository).",
|
||||||
|
].join("\n"));
|
||||||
|
}
|
||||||
|
process.exit();
|
||||||
|
case "version":
|
||||||
|
print(info.name + " " + info.version);
|
||||||
|
process.exit();
|
||||||
|
case "config-file":
|
||||||
|
var config = JSON.parse(read_file(read_value(true)));
|
||||||
|
if (config.mangle && config.mangle.properties && config.mangle.properties.regex) {
|
||||||
|
config.mangle.properties.regex = UglifyJS.parse(config.mangle.properties.regex, {
|
||||||
|
expression: true,
|
||||||
}).value;
|
}).value;
|
||||||
}
|
}
|
||||||
}
|
for (var key in config) if (!(key in options)) options[key] = config[key];
|
||||||
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
break;
|
||||||
fatal("cannot write source map to STDOUT");
|
case "compress":
|
||||||
}
|
case "mangle":
|
||||||
[
|
options[name] = parse_js(read_value(), options[name]);
|
||||||
"compress",
|
break;
|
||||||
"enclose",
|
case "source-map":
|
||||||
"ie8",
|
options.sourceMap = parse_js(read_value(), options.sourceMap);
|
||||||
"mangle",
|
break;
|
||||||
"sourceMap",
|
case "enclose":
|
||||||
"toplevel",
|
options[name] = read_value();
|
||||||
"validate",
|
break;
|
||||||
"wrap"
|
case "ie8":
|
||||||
].forEach(function(name) {
|
case "timings":
|
||||||
if (name in program) {
|
case "toplevel":
|
||||||
options[name] = program[name];
|
case "validate":
|
||||||
}
|
options[name] = true;
|
||||||
});
|
break;
|
||||||
if (program.verbose) {
|
case "keep-fnames":
|
||||||
|
options.keep_fnames = true;
|
||||||
|
break;
|
||||||
|
case "wrap":
|
||||||
|
options[name] = read_value(true);
|
||||||
|
break;
|
||||||
|
case "verbose":
|
||||||
options.warnings = "verbose";
|
options.warnings = "verbose";
|
||||||
} else if (program.warn) {
|
break;
|
||||||
options.warnings = true;
|
case "warn":
|
||||||
|
if (!options.warnings) options.warnings = true;
|
||||||
|
break;
|
||||||
|
case "beautify":
|
||||||
|
options.output = parse_js(read_value(), options.output);
|
||||||
|
if (!("beautify" in options.output)) options.output.beautify = true;
|
||||||
|
break;
|
||||||
|
case "output-opts":
|
||||||
|
options.output = parse_js(read_value(true), options.output);
|
||||||
|
break;
|
||||||
|
case "comments":
|
||||||
|
if (typeof options.output != "object") options.output = {};
|
||||||
|
options.output.comments = read_value();
|
||||||
|
if (options.output.comments === true) options.output.comments = "some";
|
||||||
|
break;
|
||||||
|
case "define":
|
||||||
|
if (typeof options.compress != "object") options.compress = {};
|
||||||
|
options.compress.global_defs = parse_js(read_value(true), options.compress.global_defs, "define");
|
||||||
|
break;
|
||||||
|
case "mangle-props":
|
||||||
|
if (typeof options.mangle != "object") options.mangle = {};
|
||||||
|
options.mangle.properties = parse_js(read_value(), options.mangle.properties);
|
||||||
|
break;
|
||||||
|
case "name-cache":
|
||||||
|
nameCache = read_value(true);
|
||||||
|
options.nameCache = JSON.parse(read_file(nameCache, "{}"));
|
||||||
|
break;
|
||||||
|
case "output":
|
||||||
|
output = read_value(true);
|
||||||
|
break;
|
||||||
|
case "parse":
|
||||||
|
options.parse = parse_js(read_value(true), options.parse);
|
||||||
|
break;
|
||||||
|
case "rename":
|
||||||
|
options.rename = true;
|
||||||
|
break;
|
||||||
|
case "no-rename":
|
||||||
|
options.rename = false;
|
||||||
|
break;
|
||||||
|
case "reduce-test":
|
||||||
|
case "self":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal("invalid option --" + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function read_value(required) {
|
||||||
|
if (no_value || !args.length || args[0][0] == "-") {
|
||||||
|
if (required) fatal("missing option argument for --" + name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return args.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!output && options.sourceMap && options.sourceMap.url != "inline") fatal("cannot write source map to STDOUT");
|
||||||
|
if (specified["beautify"] && specified["output-opts"]) fatal("--beautify cannot be used with --output-opts");
|
||||||
|
[ "compress", "mangle" ].forEach(function(name) {
|
||||||
|
if (!(name in options)) options[name] = false;
|
||||||
|
});
|
||||||
|
if (options.mangle && options.mangle.properties) {
|
||||||
|
if (options.mangle.properties.domprops) {
|
||||||
|
delete options.mangle.properties.domprops;
|
||||||
|
} else {
|
||||||
|
if (typeof options.mangle.properties != "object") options.mangle.properties = {};
|
||||||
|
if (!Array.isArray(options.mangle.properties.reserved)) options.mangle.properties.reserved = [];
|
||||||
|
require("../tools/domprops").forEach(function(name) {
|
||||||
|
UglifyJS.push_uniq(options.mangle.properties.reserved, name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (output == "ast") options.output = {
|
||||||
|
ast: true,
|
||||||
|
code: false,
|
||||||
|
};
|
||||||
|
if (options.parse && (options.parse.acorn || options.parse.spidermonkey)
|
||||||
|
&& options.sourceMap && options.sourceMap.content == "inline") {
|
||||||
|
fatal("inline source map only works with built-in parser");
|
||||||
}
|
}
|
||||||
if (options.warnings) {
|
if (options.warnings) {
|
||||||
UglifyJS.AST_Node.log_function(print_error, options.warnings == "verbose");
|
UglifyJS.AST_Node.log_function(print_error, options.warnings == "verbose");
|
||||||
delete options.warnings;
|
delete options.warnings;
|
||||||
}
|
}
|
||||||
if (program.beautify) {
|
|
||||||
options.output = typeof program.beautify == "object" ? program.beautify : {};
|
|
||||||
if (!("beautify" in options.output)) {
|
|
||||||
options.output.beautify = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (program.outputOpts) {
|
|
||||||
if (program.beautify) fatal("--beautify cannot be used with --output-opts");
|
|
||||||
options.output = typeof program.outputOpts == "object" ? program.outputOpts : {};
|
|
||||||
}
|
|
||||||
if (program.comments) {
|
|
||||||
if (typeof options.output != "object") options.output = {};
|
|
||||||
options.output.comments = typeof program.comments == "string" ? program.comments : "some";
|
|
||||||
}
|
|
||||||
if (program.define) {
|
|
||||||
if (typeof options.compress != "object") options.compress = {};
|
|
||||||
if (typeof options.compress.global_defs != "object") options.compress.global_defs = {};
|
|
||||||
for (var expr in program.define) {
|
|
||||||
options.compress.global_defs[expr] = program.define[expr];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (program.keepFnames) {
|
|
||||||
options.keep_fnames = true;
|
|
||||||
}
|
|
||||||
if (program.mangleProps) {
|
|
||||||
if (program.mangleProps.domprops) {
|
|
||||||
delete program.mangleProps.domprops;
|
|
||||||
} else {
|
|
||||||
if (typeof program.mangleProps != "object") program.mangleProps = {};
|
|
||||||
if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
|
|
||||||
require("../tools/domprops").forEach(function(name) {
|
|
||||||
UglifyJS.push_uniq(program.mangleProps.reserved, name);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (typeof options.mangle != "object") options.mangle = {};
|
|
||||||
options.mangle.properties = program.mangleProps;
|
|
||||||
}
|
|
||||||
if (program.nameCache) {
|
|
||||||
options.nameCache = JSON.parse(read_file(program.nameCache, "{}"));
|
|
||||||
}
|
|
||||||
if (program.output == "ast") {
|
|
||||||
options.output = {
|
|
||||||
ast: true,
|
|
||||||
code: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (program.parse) {
|
|
||||||
if (!program.parse.acorn && !program.parse.spidermonkey) {
|
|
||||||
options.parse = program.parse;
|
|
||||||
} else if (program.sourceMap && program.sourceMap.content == "inline") {
|
|
||||||
fatal("inline source map only works with built-in parser");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (~program.rawArgs.indexOf("--rename")) {
|
|
||||||
options.rename = true;
|
|
||||||
} else if (!program.rename) {
|
|
||||||
options.rename = false;
|
|
||||||
}
|
|
||||||
var convert_path = function(name) {
|
var convert_path = function(name) {
|
||||||
return name;
|
return name;
|
||||||
};
|
};
|
||||||
if (typeof program.sourceMap == "object" && "base" in program.sourceMap) {
|
if (typeof options.sourceMap == "object" && "base" in options.sourceMap) {
|
||||||
convert_path = function() {
|
convert_path = function() {
|
||||||
var base = program.sourceMap.base;
|
var base = options.sourceMap.base;
|
||||||
delete options.sourceMap.base;
|
delete options.sourceMap.base;
|
||||||
return function(name) {
|
return function(name) {
|
||||||
return path.relative(base, name);
|
return path.relative(base, name);
|
||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
if (program.self) {
|
if (specified["self"]) {
|
||||||
if (program.args.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
|
if (paths.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
|
||||||
if (!options.wrap) options.wrap = "UglifyJS";
|
if (!options.wrap) options.wrap = "UglifyJS";
|
||||||
simple_glob(UglifyJS.FILES).forEach(function(name) {
|
paths = UglifyJS.FILES;
|
||||||
files[convert_path(name)] = read_file(name);
|
}
|
||||||
});
|
if (paths.length) {
|
||||||
run();
|
simple_glob(paths).forEach(function(name) {
|
||||||
} else if (program.args.length) {
|
|
||||||
simple_glob(program.args).forEach(function(name) {
|
|
||||||
files[convert_path(name)] = read_file(name);
|
files[convert_path(name)] = read_file(name);
|
||||||
});
|
});
|
||||||
run();
|
run();
|
||||||
@@ -207,15 +274,14 @@ function convert_ast(fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
var content = program.sourceMap && program.sourceMap.content;
|
var content = options.sourceMap && options.sourceMap.content;
|
||||||
if (content && content != "inline") {
|
if (content && content != "inline") {
|
||||||
UglifyJS.AST_Node.info("Using input source map: " + content);
|
UglifyJS.AST_Node.info("Using input source map: " + content);
|
||||||
options.sourceMap.content = read_file(content, content);
|
options.sourceMap.content = read_file(content, content);
|
||||||
}
|
}
|
||||||
if (program.timings) options.timings = true;
|
|
||||||
try {
|
try {
|
||||||
if (program.parse) {
|
if (options.parse) {
|
||||||
if (program.parse.acorn) {
|
if (options.parse.acorn) {
|
||||||
files = convert_ast(function(toplevel, name) {
|
files = convert_ast(function(toplevel, name) {
|
||||||
return require("acorn").parse(files[name], {
|
return require("acorn").parse(files[name], {
|
||||||
locations: true,
|
locations: true,
|
||||||
@@ -223,7 +289,7 @@ function run() {
|
|||||||
sourceFile: name
|
sourceFile: name
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else if (program.parse.spidermonkey) {
|
} else if (options.parse.spidermonkey) {
|
||||||
files = convert_ast(function(toplevel, name) {
|
files = convert_ast(function(toplevel, name) {
|
||||||
var obj = JSON.parse(files[name]);
|
var obj = JSON.parse(files[name]);
|
||||||
if (!toplevel) return obj;
|
if (!toplevel) return obj;
|
||||||
@@ -235,17 +301,17 @@ function run() {
|
|||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
fatal(ex);
|
fatal(ex);
|
||||||
}
|
}
|
||||||
if (program.reduceTest) {
|
var result;
|
||||||
// load on demand - assumes dev tree checked out
|
if (specified["reduce-test"]) {
|
||||||
|
// load on demand - assumes cloned repository
|
||||||
var reduce_test = require("../test/reduce");
|
var reduce_test = require("../test/reduce");
|
||||||
var testcase = files[0] || files[Object.keys(files)[0]];
|
if (Object.keys(files).length != 1) fatal("can only test on a single file");
|
||||||
var result = reduce_test(testcase, options, {
|
result = reduce_test(files[Object.keys(files)[0]], options, {
|
||||||
log: print_error,
|
log: print_error,
|
||||||
verbose: true,
|
verbose: true,
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
else {
|
result = UglifyJS.minify(files, options);
|
||||||
var result = UglifyJS.minify(files, options);
|
|
||||||
}
|
}
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
var ex = result.error;
|
var ex = result.error;
|
||||||
@@ -275,9 +341,18 @@ function run() {
|
|||||||
print_error(format_object(ex.defs));
|
print_error(format_object(ex.defs));
|
||||||
}
|
}
|
||||||
fatal(ex);
|
fatal(ex);
|
||||||
} else if (program.output == "ast") {
|
} else if (output == "ast") {
|
||||||
if (!options.compress && !options.mangle) {
|
if (!options.compress && !options.mangle) {
|
||||||
result.ast.figure_out_scope({});
|
var toplevel = result.ast;
|
||||||
|
if (!(toplevel instanceof UglifyJS.AST_Toplevel)) {
|
||||||
|
if (!(toplevel instanceof UglifyJS.AST_Statement)) toplevel = new UglifyJS.AST_SimpleStatement({
|
||||||
|
body: toplevel,
|
||||||
|
});
|
||||||
|
toplevel = new UglifyJS.AST_Toplevel({
|
||||||
|
body: [ toplevel ],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
toplevel.figure_out_scope({});
|
||||||
}
|
}
|
||||||
print(JSON.stringify(result.ast, function(key, value) {
|
print(JSON.stringify(result.ast, function(key, value) {
|
||||||
if (value) switch (key) {
|
if (value) switch (key) {
|
||||||
@@ -304,26 +379,22 @@ function run() {
|
|||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}, 2));
|
}, 2));
|
||||||
} else if (program.output == "spidermonkey") {
|
} else if (output == "spidermonkey") {
|
||||||
print(JSON.stringify(UglifyJS.minify(result.code, {
|
print(JSON.stringify(UglifyJS.minify(result.code, {
|
||||||
compress: false,
|
compress: false,
|
||||||
mangle: false,
|
mangle: false,
|
||||||
output: {
|
output: {
|
||||||
ast: true,
|
ast: true,
|
||||||
code: false
|
code: false
|
||||||
}
|
},
|
||||||
}).ast.to_mozilla_ast(), null, 2));
|
}).ast.to_mozilla_ast(), null, 2));
|
||||||
} else if (program.output) {
|
} else if (output) {
|
||||||
fs.writeFileSync(program.output, result.code);
|
fs.writeFileSync(output, result.code);
|
||||||
if (result.map) {
|
if (result.map) fs.writeFileSync(output + ".map", result.map);
|
||||||
fs.writeFileSync(program.output + ".map", result.map);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
print(result.code);
|
print(result.code);
|
||||||
}
|
}
|
||||||
if (program.nameCache) {
|
if (nameCache) fs.writeFileSync(nameCache, JSON.stringify(options.nameCache));
|
||||||
fs.writeFileSync(program.nameCache, JSON.stringify(options.nameCache));
|
|
||||||
}
|
|
||||||
if (result.timings) for (var phase in result.timings) {
|
if (result.timings) for (var phase in result.timings) {
|
||||||
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
|
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
|
||||||
}
|
}
|
||||||
@@ -379,10 +450,9 @@ function read_file(path, default_value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parse_js(flag) {
|
function parse_js(value, options, flag) {
|
||||||
return function(value, options) {
|
if (!options || typeof options != "object") options = {};
|
||||||
options = options || {};
|
if (typeof value == "string") try {
|
||||||
try {
|
|
||||||
UglifyJS.parse(value, {
|
UglifyJS.parse(value, {
|
||||||
expression: true
|
expression: true
|
||||||
}).walk(new UglifyJS.TreeWalker(function(node) {
|
}).walk(new UglifyJS.TreeWalker(function(node) {
|
||||||
@@ -420,7 +490,6 @@ function parse_js(flag) {
|
|||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function skip_key(key) {
|
function skip_key(key) {
|
||||||
return skip_keys.indexOf(key) >= 0;
|
return skip_keys.indexOf(key) >= 0;
|
||||||
|
|||||||
89
lib/ast.js
89
lib/ast.js
@@ -120,6 +120,20 @@ var AST_Node = DEFNODE("Node", "start end", {
|
|||||||
ctor.prototype._validate.call(this);
|
ctor.prototype._validate.call(this);
|
||||||
} while (ctor = ctor.BASE);
|
} while (ctor = ctor.BASE);
|
||||||
},
|
},
|
||||||
|
validate_ast: function() {
|
||||||
|
var marker = {};
|
||||||
|
this.walk(new TreeWalker(function(node) {
|
||||||
|
if (node.validate_visited === marker) {
|
||||||
|
throw new Error(string_template("cannot reuse {type} from [{file}:{line},{col}]", {
|
||||||
|
type: "AST_" + node.TYPE,
|
||||||
|
file: node.start.file,
|
||||||
|
line: node.start.line,
|
||||||
|
col: node.start.col,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
node.validate_visited = marker;
|
||||||
|
}));
|
||||||
|
},
|
||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
(AST_Node.log_function = function(fn, verbose) {
|
(AST_Node.log_function = function(fn, verbose) {
|
||||||
@@ -237,9 +251,38 @@ var AST_Block = DEFNODE("Block", "body", {
|
|||||||
},
|
},
|
||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
|
|
||||||
|
var AST_BlockScope = DEFNODE("BlockScope", "cname enclosed functions make_def parent_scope variables", {
|
||||||
|
$documentation: "Base class for all statements introducing a lexical scope",
|
||||||
|
$propdoc: {
|
||||||
|
cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
|
||||||
|
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
|
||||||
|
functions: "[Object/S] like `variables`, but only lists function declarations",
|
||||||
|
parent_scope: "[AST_Scope?/S] link to the parent scope",
|
||||||
|
variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
|
||||||
|
},
|
||||||
|
clone: function(deep) {
|
||||||
|
var node = this._clone(deep);
|
||||||
|
if (this.enclosed) node.enclosed = this.enclosed.slice();
|
||||||
|
if (this.functions) node.functions = this.functions.clone();
|
||||||
|
if (this.variables) node.variables = this.variables.clone();
|
||||||
|
return node;
|
||||||
|
},
|
||||||
|
pinned: function() {
|
||||||
|
return this.resolve().pinned();
|
||||||
|
},
|
||||||
|
resolve: function() {
|
||||||
|
return this.parent_scope.resolve();
|
||||||
|
},
|
||||||
|
_validate: function() {
|
||||||
|
if (this.parent_scope == null) return;
|
||||||
|
if (!(this.parent_scope instanceof AST_BlockScope)) throw new Error("parent_scope must be AST_BlockScope");
|
||||||
|
if (!(this.resolve() instanceof AST_Scope)) throw new Error("must be contained within AST_Scope");
|
||||||
|
},
|
||||||
|
}, AST_Block);
|
||||||
|
|
||||||
var AST_BlockStatement = DEFNODE("BlockStatement", null, {
|
var AST_BlockStatement = DEFNODE("BlockStatement", null, {
|
||||||
$documentation: "A block statement",
|
$documentation: "A block statement",
|
||||||
}, AST_Block);
|
}, AST_BlockScope);
|
||||||
|
|
||||||
var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
|
var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
|
||||||
$documentation: "The empty statement (empty block or simply a semicolon)"
|
$documentation: "The empty statement (empty block or simply a semicolon)"
|
||||||
@@ -274,10 +317,13 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
|
|||||||
var label = node.label;
|
var label = node.label;
|
||||||
var def = this.label;
|
var def = this.label;
|
||||||
node.walk(new TreeWalker(function(node) {
|
node.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_LoopControl && node.label && node.label.thedef === def) {
|
if (node instanceof AST_LoopControl) {
|
||||||
|
if (!node.label || node.label.thedef !== def) return;
|
||||||
node.label.thedef = label;
|
node.label.thedef = label;
|
||||||
label.references.push(node);
|
label.references.push(node);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
if (node instanceof AST_Scope) return true;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
@@ -395,33 +441,17 @@ var AST_With = DEFNODE("With", "expression", {
|
|||||||
|
|
||||||
/* -----[ scope and functions ]----- */
|
/* -----[ scope and functions ]----- */
|
||||||
|
|
||||||
var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent_scope enclosed cname", {
|
var AST_Scope = DEFNODE("Scope", "uses_eval uses_with", {
|
||||||
$documentation: "Base class for all statements introducing a lexical scope",
|
$documentation: "Base class for all statements introducing a lexical scope",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
|
|
||||||
functions: "[Object/S] like `variables`, but only lists function declarations",
|
|
||||||
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
|
|
||||||
uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
|
uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
|
||||||
parent_scope: "[AST_Scope?/S] link to the parent scope",
|
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
|
||||||
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
|
|
||||||
cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
|
|
||||||
},
|
|
||||||
clone: function(deep) {
|
|
||||||
var node = this._clone(deep);
|
|
||||||
if (this.variables) node.variables = this.variables.clone();
|
|
||||||
if (this.functions) node.functions = this.functions.clone();
|
|
||||||
if (this.enclosed) node.enclosed = this.enclosed.slice();
|
|
||||||
return node;
|
|
||||||
},
|
},
|
||||||
pinned: function() {
|
pinned: function() {
|
||||||
return this.uses_eval || this.uses_with;
|
return this.uses_eval || this.uses_with;
|
||||||
},
|
},
|
||||||
_validate: function() {
|
resolve: return_this,
|
||||||
if (this.parent_scope != null) {
|
}, AST_BlockScope);
|
||||||
if (!(this.parent_scope instanceof AST_Scope)) throw new Error("parent_scope must be AST_Scope");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}, AST_Block);
|
|
||||||
|
|
||||||
var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||||
$documentation: "The toplevel scope",
|
$documentation: "The toplevel scope",
|
||||||
@@ -614,6 +644,9 @@ var AST_Switch = DEFNODE("Switch", "expression", {
|
|||||||
},
|
},
|
||||||
_validate: function() {
|
_validate: function() {
|
||||||
must_be_expression(this, "expression");
|
must_be_expression(this, "expression");
|
||||||
|
this.body.forEach(function(node) {
|
||||||
|
if (!(node instanceof AST_SwitchBranch)) throw new Error("body must be AST_SwitchBranch[]");
|
||||||
|
});
|
||||||
},
|
},
|
||||||
}, AST_Block);
|
}, AST_Block);
|
||||||
|
|
||||||
@@ -666,28 +699,30 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", {
|
|||||||
if (!(this.bfinally instanceof AST_Finally)) throw new Error("bfinally must be AST_Finally");
|
if (!(this.bfinally instanceof AST_Finally)) throw new Error("bfinally must be AST_Finally");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, AST_Block);
|
}, AST_BlockScope);
|
||||||
|
|
||||||
var AST_Catch = DEFNODE("Catch", "argname", {
|
var AST_Catch = DEFNODE("Catch", "argname", {
|
||||||
$documentation: "A `catch` node; only makes sense as part of a `try` statement",
|
$documentation: "A `catch` node; only makes sense as part of a `try` statement",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
argname: "[AST_SymbolCatch] symbol for the exception"
|
argname: "[AST_SymbolCatch?] symbol for the exception, or null if not present",
|
||||||
},
|
},
|
||||||
walk: function(visitor) {
|
walk: function(visitor) {
|
||||||
var node = this;
|
var node = this;
|
||||||
visitor.visit(node, function() {
|
visitor.visit(node, function() {
|
||||||
node.argname.walk(visitor);
|
if (node.argname) node.argname.walk(visitor);
|
||||||
walk_body(node, visitor);
|
walk_body(node, visitor);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
_validate: function() {
|
_validate: function() {
|
||||||
|
if (this.argname != null) {
|
||||||
if (!(this.argname instanceof AST_SymbolCatch)) throw new Error("argname must be AST_SymbolCatch");
|
if (!(this.argname instanceof AST_SymbolCatch)) throw new Error("argname must be AST_SymbolCatch");
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}, AST_Block);
|
}, AST_BlockScope);
|
||||||
|
|
||||||
var AST_Finally = DEFNODE("Finally", null, {
|
var AST_Finally = DEFNODE("Finally", null, {
|
||||||
$documentation: "A `finally` node; only makes sense as part of a `try` statement"
|
$documentation: "A `finally` node; only makes sense as part of a `try` statement"
|
||||||
}, AST_Block);
|
}, AST_BlockScope);
|
||||||
|
|
||||||
/* -----[ VAR ]----- */
|
/* -----[ VAR ]----- */
|
||||||
|
|
||||||
|
|||||||
2005
lib/compress.js
2005
lib/compress.js
File diff suppressed because it is too large
Load Diff
@@ -178,13 +178,17 @@ function minify(files, options) {
|
|||||||
toplevel = toplevel[action](option);
|
toplevel = toplevel[action](option);
|
||||||
files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
|
files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
|
||||||
});
|
});
|
||||||
|
if (options.validate) toplevel.validate_ast();
|
||||||
if (timings) timings.rename = Date.now();
|
if (timings) timings.rename = Date.now();
|
||||||
if (options.rename) {
|
if (options.rename) {
|
||||||
toplevel.figure_out_scope(options.mangle);
|
toplevel.figure_out_scope(options.mangle);
|
||||||
toplevel.expand_names(options.mangle);
|
toplevel.expand_names(options.mangle);
|
||||||
}
|
}
|
||||||
if (timings) timings.compress = Date.now();
|
if (timings) timings.compress = Date.now();
|
||||||
if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
|
if (options.compress) {
|
||||||
|
toplevel = new Compressor(options.compress).compress(toplevel);
|
||||||
|
if (options.validate) toplevel.validate_ast();
|
||||||
|
}
|
||||||
if (timings) timings.scope = Date.now();
|
if (timings) timings.scope = Date.now();
|
||||||
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
||||||
if (timings) timings.mangle = Date.now();
|
if (timings) timings.mangle = Date.now();
|
||||||
@@ -193,9 +197,7 @@ function minify(files, options) {
|
|||||||
toplevel.mangle_names(options.mangle);
|
toplevel.mangle_names(options.mangle);
|
||||||
}
|
}
|
||||||
if (timings) timings.properties = Date.now();
|
if (timings) timings.properties = Date.now();
|
||||||
if (options.mangle && options.mangle.properties) {
|
if (options.mangle && options.mangle.properties) mangle_properties(toplevel, options.mangle.properties);
|
||||||
toplevel = mangle_properties(toplevel, options.mangle.properties);
|
|
||||||
}
|
|
||||||
if (timings) timings.output = Date.now();
|
if (timings) timings.output = Date.now();
|
||||||
var result = {};
|
var result = {};
|
||||||
if (options.output.ast) {
|
if (options.output.ast) {
|
||||||
|
|||||||
372
lib/output.js
372
lib/output.js
@@ -100,7 +100,7 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var indentation = 0;
|
var indentation = options.indent_start;
|
||||||
var current_col = 0;
|
var current_col = 0;
|
||||||
var current_line = 1;
|
var current_line = 1;
|
||||||
var current_pos = 0;
|
var current_pos = 0;
|
||||||
@@ -191,10 +191,6 @@ function OutputStream(options) {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
function make_indent(back) {
|
|
||||||
return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -----[ beautification/minification ]----- */
|
/* -----[ beautification/minification ]----- */
|
||||||
|
|
||||||
var has_parens = false;
|
var has_parens = false;
|
||||||
@@ -305,6 +301,7 @@ function OutputStream(options) {
|
|||||||
|| (ch == "/" && ch == prev)
|
|| (ch == "/" && ch == prev)
|
||||||
|| ((ch == "+" || ch == "-") && ch == last)
|
|| ((ch == "+" || ch == "-") && ch == last)
|
||||||
|| str == "--" && last == "!"
|
|| str == "--" && last == "!"
|
||||||
|
|| str == "in" && prev == "/"
|
||||||
|| last == "--" && ch == ">") {
|
|| last == "--" && ch == ">") {
|
||||||
OUTPUT += " ";
|
OUTPUT += " ";
|
||||||
current_col++;
|
current_col++;
|
||||||
@@ -344,9 +341,7 @@ function OutputStream(options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var indent = options.beautify ? function(half) {
|
var indent = options.beautify ? function(half) {
|
||||||
if (options.beautify) {
|
print(repeat_string(" ", half ? indentation - (options.indent_level >> 1) : indentation));
|
||||||
print(make_indent(half ? 0.5 : 0));
|
|
||||||
}
|
|
||||||
} : noop;
|
} : noop;
|
||||||
|
|
||||||
var with_indent = options.beautify ? function(col, cont) {
|
var with_indent = options.beautify ? function(col, cont) {
|
||||||
@@ -574,9 +569,9 @@ function OutputStream(options) {
|
|||||||
get : get,
|
get : get,
|
||||||
toString : get,
|
toString : get,
|
||||||
indent : indent,
|
indent : indent,
|
||||||
indentation : function() { return indentation },
|
should_break : readonly ? noop : function() {
|
||||||
current_width : function() { return current_col - indentation },
|
return options.width && current_col - indentation >= options.width;
|
||||||
should_break : function() { return options.width && this.current_width() >= options.width },
|
},
|
||||||
has_parens : function() { return has_parens },
|
has_parens : function() { return has_parens },
|
||||||
newline : newline,
|
newline : newline,
|
||||||
print : print,
|
print : print,
|
||||||
@@ -629,13 +624,7 @@ function OutputStream(options) {
|
|||||||
var use_asm = false;
|
var use_asm = false;
|
||||||
|
|
||||||
AST_Node.DEFMETHOD("print", function(stream, force_parens) {
|
AST_Node.DEFMETHOD("print", function(stream, force_parens) {
|
||||||
var self = this, generator = self._codegen;
|
var self = this;
|
||||||
function doit() {
|
|
||||||
stream.prepend_comments(self);
|
|
||||||
self.add_source_map(stream);
|
|
||||||
generator(self, stream);
|
|
||||||
stream.append_comments(self);
|
|
||||||
}
|
|
||||||
stream.push_node(self);
|
stream.push_node(self);
|
||||||
if (force_parens || self.needs_parens(stream)) {
|
if (force_parens || self.needs_parens(stream)) {
|
||||||
stream.with_parens(doit);
|
stream.with_parens(doit);
|
||||||
@@ -643,9 +632,14 @@ function OutputStream(options) {
|
|||||||
doit();
|
doit();
|
||||||
}
|
}
|
||||||
stream.pop_node();
|
stream.pop_node();
|
||||||
});
|
|
||||||
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
|
|
||||||
|
|
||||||
|
function doit() {
|
||||||
|
stream.prepend_comments(self);
|
||||||
|
self.add_source_map(stream);
|
||||||
|
self._codegen(stream);
|
||||||
|
stream.append_comments(self);
|
||||||
|
}
|
||||||
|
});
|
||||||
AST_Node.DEFMETHOD("print_to_string", function(options) {
|
AST_Node.DEFMETHOD("print_to_string", function(options) {
|
||||||
var s = OutputStream(options);
|
var s = OutputStream(options);
|
||||||
this.print(s);
|
this.print(s);
|
||||||
@@ -688,78 +682,66 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
PARENS(AST_Unary, function(output) {
|
PARENS(AST_Unary, function(output) {
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
return p instanceof AST_PropAccess && p.expression === this
|
return (p instanceof AST_Call || p instanceof AST_PropAccess) && p.expression === this;
|
||||||
|| p instanceof AST_Call && p.expression === this;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS(AST_Sequence, function(output) {
|
PARENS(AST_Sequence, function(output) {
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
// (foo, bar)() or foo(1, (2, 3), 4)
|
// [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
|
||||||
return p instanceof AST_Call
|
return p instanceof AST_Array
|
||||||
// !(foo, bar, baz)
|
|
||||||
|| p instanceof AST_Unary
|
|
||||||
// 1 + (2, 3) + 4 ==> 8
|
// 1 + (2, 3) + 4 ==> 8
|
||||||
|| p instanceof AST_Binary
|
|| p instanceof AST_Binary
|
||||||
// var a = (1, 2), b = a + a; ==> b == 4
|
// new (foo, bar) or foo(1, (2, 3), 4)
|
||||||
|| p instanceof AST_VarDef
|
|| p instanceof AST_Call
|
||||||
// (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
|
|
||||||
|| p instanceof AST_PropAccess && p.expression === this
|
|
||||||
// [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
|
|
||||||
|| p instanceof AST_Array
|
|
||||||
// { foo: (1, 2) }.foo ==> 2
|
|
||||||
|| p instanceof AST_ObjectProperty
|
|
||||||
// (false, true) ? (a = 10, b = 20) : (c = 30)
|
// (false, true) ? (a = 10, b = 20) : (c = 30)
|
||||||
// ==> 20 (side effect, set a := 10 and b := 20)
|
// ==> 20 (side effect, set a := 10 and b := 20)
|
||||||
|| p instanceof AST_Conditional;
|
|| p instanceof AST_Conditional
|
||||||
|
// { foo: (1, 2) }.foo ==> 2
|
||||||
|
|| p instanceof AST_ObjectProperty
|
||||||
|
// (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
|
||||||
|
|| p instanceof AST_PropAccess && p.expression === this
|
||||||
|
// !(foo, bar, baz)
|
||||||
|
|| p instanceof AST_Unary
|
||||||
|
// var a = (1, 2), b = a + a; ==> b == 4
|
||||||
|
|| p instanceof AST_VarDef;
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS(AST_Binary, function(output) {
|
PARENS(AST_Binary, function(output) {
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
// (foo && bar)()
|
|
||||||
if (p instanceof AST_Call && p.expression === this)
|
|
||||||
return true;
|
|
||||||
// typeof (foo && bar)
|
|
||||||
if (p instanceof AST_Unary)
|
|
||||||
return true;
|
|
||||||
// (foo && bar)["prop"], (foo && bar).prop
|
|
||||||
if (p instanceof AST_PropAccess && p.expression === this)
|
|
||||||
return true;
|
|
||||||
// this deals with precedence: 3 * (2 + 1)
|
// this deals with precedence: 3 * (2 + 1)
|
||||||
if (p instanceof AST_Binary) {
|
if (p instanceof AST_Binary) {
|
||||||
var po = p.operator, pp = PRECEDENCE[po];
|
var po = p.operator, pp = PRECEDENCE[po];
|
||||||
var so = this.operator, sp = PRECEDENCE[so];
|
var so = this.operator, sp = PRECEDENCE[so];
|
||||||
if (pp > sp
|
return pp > sp || (pp == sp && this === p.right);
|
||||||
|| (pp == sp
|
|
||||||
&& this === p.right)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// (foo && bar)()
|
||||||
|
if (p instanceof AST_Call) return p.expression === this;
|
||||||
|
// (foo && bar)["prop"], (foo && bar).prop
|
||||||
|
if (p instanceof AST_PropAccess) return p.expression === this;
|
||||||
|
// typeof (foo && bar)
|
||||||
|
if (p instanceof AST_Unary) return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS(AST_PropAccess, function(output) {
|
PARENS(AST_PropAccess, function(output) {
|
||||||
|
var node = this;
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
if (p instanceof AST_New && p.expression === this) {
|
if (p instanceof AST_New && p.expression === node) {
|
||||||
// i.e. new (foo.bar().baz)
|
// i.e. new (foo().bar)
|
||||||
//
|
//
|
||||||
// if there's one call into this subtree, then we need
|
// if there's one call into this subtree, then we need
|
||||||
// parens around it too, otherwise the call will be
|
// parens around it too, otherwise the call will be
|
||||||
// interpreted as passing the arguments to the upper New
|
// interpreted as passing the arguments to the upper New
|
||||||
// expression.
|
// expression.
|
||||||
var parens = false;
|
do {
|
||||||
this.walk(new TreeWalker(function(node) {
|
node = node.expression;
|
||||||
if (parens || node instanceof AST_Scope) return true;
|
} while (node instanceof AST_PropAccess);
|
||||||
if (node instanceof AST_Call) {
|
return node.TYPE == "Call";
|
||||||
parens = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
return parens;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS(AST_Call, function(output) {
|
PARENS(AST_Call, function(output) {
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
if (p instanceof AST_New && p.expression === this) return true;
|
if (p instanceof AST_New) return p.expression === this;
|
||||||
// https://bugs.webkit.org/show_bug.cgi?id=123506
|
// https://bugs.webkit.org/show_bug.cgi?id=123506
|
||||||
if (output.option('webkit')) {
|
if (output.option('webkit')) {
|
||||||
var g = output.parent(1);
|
var g = output.parent(1);
|
||||||
@@ -772,11 +754,12 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
PARENS(AST_New, function(output) {
|
PARENS(AST_New, function(output) {
|
||||||
|
if (need_constructor_parens(this, output)) return false;
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
if (!need_constructor_parens(this, output)
|
// (new foo)(bar)
|
||||||
&& (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]()
|
if (p instanceof AST_Call) return p.expression === this;
|
||||||
|| p instanceof AST_Call && p.expression === this)) // (new foo)(bar)
|
// (new Date).getTime(), (new Date)["getTime"]()
|
||||||
return true;
|
return p instanceof AST_PropAccess;
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS(AST_Number, function(output) {
|
PARENS(AST_Number, function(output) {
|
||||||
@@ -785,36 +768,29 @@ function OutputStream(options) {
|
|||||||
var value = this.value;
|
var value = this.value;
|
||||||
// https://github.com/mishoo/UglifyJS/issues/115
|
// https://github.com/mishoo/UglifyJS/issues/115
|
||||||
// https://github.com/mishoo/UglifyJS/pull/1009
|
// https://github.com/mishoo/UglifyJS/pull/1009
|
||||||
if (value < 0 || /^0/.test(make_num(value))) {
|
return value < 0 || /^0/.test(make_num(value));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS([ AST_Assign, AST_Conditional ], function(output) {
|
PARENS([ AST_Assign, AST_Conditional ], function(output) {
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
// !(a = false) → true
|
|
||||||
if (p instanceof AST_Unary)
|
|
||||||
return true;
|
|
||||||
// 1 + (a = 2) + 3 → 6, side effect setting a = 2
|
// 1 + (a = 2) + 3 → 6, side effect setting a = 2
|
||||||
if (p instanceof AST_Binary && !(p instanceof AST_Assign))
|
if (p instanceof AST_Binary) return !(p instanceof AST_Assign);
|
||||||
return true;
|
|
||||||
// (a = func)() —or— new (a = Object)()
|
// (a = func)() —or— new (a = Object)()
|
||||||
if (p instanceof AST_Call && p.expression === this)
|
if (p instanceof AST_Call) return p.expression === this;
|
||||||
return true;
|
|
||||||
// (a = foo) ? bar : baz
|
// (a = foo) ? bar : baz
|
||||||
if (p instanceof AST_Conditional && p.condition === this)
|
if (p instanceof AST_Conditional) return p.condition === this;
|
||||||
return true;
|
|
||||||
// (a = foo)["prop"] —or— (a = foo).prop
|
// (a = foo)["prop"] —or— (a = foo).prop
|
||||||
if (p instanceof AST_PropAccess && p.expression === this)
|
if (p instanceof AST_PropAccess) return p.expression === this;
|
||||||
return true;
|
// !(a = false) → true
|
||||||
|
if (p instanceof AST_Unary) return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ PRINTERS ]----- */
|
/* -----[ PRINTERS ]----- */
|
||||||
|
|
||||||
DEFPRINT(AST_Directive, function(self, output) {
|
DEFPRINT(AST_Directive, function(output) {
|
||||||
var quote = self.quote;
|
var quote = this.quote;
|
||||||
var value = self.value;
|
var value = this.value;
|
||||||
switch (output.option("quote_style")) {
|
switch (output.option("quote_style")) {
|
||||||
case 0:
|
case 0:
|
||||||
case 2:
|
case 2:
|
||||||
@@ -827,7 +803,7 @@ function OutputStream(options) {
|
|||||||
output.print(quote + value + quote);
|
output.print(quote + value + quote);
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Debugger, function(self, output) {
|
DEFPRINT(AST_Debugger, function(output) {
|
||||||
output.print("debugger");
|
output.print("debugger");
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
@@ -863,21 +839,21 @@ function OutputStream(options) {
|
|||||||
force_statement(this.body, output);
|
force_statement(this.body, output);
|
||||||
});
|
});
|
||||||
|
|
||||||
DEFPRINT(AST_Statement, function(self, output) {
|
DEFPRINT(AST_Statement, function(output) {
|
||||||
self.body.print(output);
|
this.body.print(output);
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Toplevel, function(self, output) {
|
DEFPRINT(AST_Toplevel, function(output) {
|
||||||
display_body(self.body, true, output, true);
|
display_body(this.body, true, output, true);
|
||||||
output.print("");
|
output.print("");
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_LabeledStatement, function(self, output) {
|
DEFPRINT(AST_LabeledStatement, function(output) {
|
||||||
self.label.print(output);
|
this.label.print(output);
|
||||||
output.colon();
|
output.colon();
|
||||||
self.body.print(output);
|
this.body.print(output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_SimpleStatement, function(self, output) {
|
DEFPRINT(AST_SimpleStatement, function(output) {
|
||||||
self.body.print(output);
|
this.body.print(output);
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
function print_braced_empty(self, output) {
|
function print_braced_empty(self, output) {
|
||||||
@@ -894,13 +870,14 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
} else print_braced_empty(self, output);
|
} else print_braced_empty(self, output);
|
||||||
}
|
}
|
||||||
DEFPRINT(AST_BlockStatement, function(self, output) {
|
DEFPRINT(AST_BlockStatement, function(output) {
|
||||||
print_braced(self, output);
|
print_braced(this, output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_EmptyStatement, function(self, output) {
|
DEFPRINT(AST_EmptyStatement, function(output) {
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Do, function(self, output) {
|
DEFPRINT(AST_Do, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("do");
|
output.print("do");
|
||||||
output.space();
|
output.space();
|
||||||
make_block(self.body, output);
|
make_block(self.body, output);
|
||||||
@@ -912,7 +889,8 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_While, function(self, output) {
|
DEFPRINT(AST_While, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("while");
|
output.print("while");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
@@ -921,7 +899,8 @@ function OutputStream(options) {
|
|||||||
output.space();
|
output.space();
|
||||||
self._do_print_body(output);
|
self._do_print_body(output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_For, function(self, output) {
|
DEFPRINT(AST_For, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("for");
|
output.print("for");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
@@ -950,7 +929,8 @@ function OutputStream(options) {
|
|||||||
output.space();
|
output.space();
|
||||||
self._do_print_body(output);
|
self._do_print_body(output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_ForIn, function(self, output) {
|
DEFPRINT(AST_ForIn, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("for");
|
output.print("for");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
@@ -963,7 +943,8 @@ function OutputStream(options) {
|
|||||||
output.space();
|
output.space();
|
||||||
self._do_print_body(output);
|
self._do_print_body(output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_With, function(self, output) {
|
DEFPRINT(AST_With, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("with");
|
output.print("with");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
@@ -974,7 +955,7 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ functions ]----- */
|
/* -----[ functions ]----- */
|
||||||
AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword) {
|
DEFPRINT(AST_Lambda, function(output, nokeyword) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (!nokeyword) {
|
if (!nokeyword) {
|
||||||
output.print("function");
|
output.print("function");
|
||||||
@@ -992,32 +973,23 @@ function OutputStream(options) {
|
|||||||
output.space();
|
output.space();
|
||||||
print_braced(self, output, true);
|
print_braced(self, output, true);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Lambda, function(self, output) {
|
|
||||||
self._do_print(output);
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -----[ jumps ]----- */
|
/* -----[ jumps ]----- */
|
||||||
function print_jump(output, kind, target) {
|
function print_jump(kind, prop) {
|
||||||
|
return function(output) {
|
||||||
output.print(kind);
|
output.print(kind);
|
||||||
|
var target = this[prop];
|
||||||
if (target) {
|
if (target) {
|
||||||
output.space();
|
output.space();
|
||||||
target.print(output);
|
target.print(output);
|
||||||
}
|
}
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
DEFPRINT(AST_Return, print_jump("return", "value"));
|
||||||
DEFPRINT(AST_Return, function(self, output) {
|
DEFPRINT(AST_Throw, print_jump("throw", "value"));
|
||||||
print_jump(output, "return", self.value);
|
DEFPRINT(AST_Break, print_jump("break", "label"));
|
||||||
});
|
DEFPRINT(AST_Continue, print_jump("continue", "label"));
|
||||||
DEFPRINT(AST_Throw, function(self, output) {
|
|
||||||
print_jump(output, "throw", self.value);
|
|
||||||
});
|
|
||||||
DEFPRINT(AST_Break, function(self, output) {
|
|
||||||
print_jump(output, "break", self.label);
|
|
||||||
});
|
|
||||||
DEFPRINT(AST_Continue, function(self, output) {
|
|
||||||
print_jump(output, "continue", self.label);
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -----[ if ]----- */
|
/* -----[ if ]----- */
|
||||||
function make_then(self, output) {
|
function make_then(self, output) {
|
||||||
@@ -1046,7 +1018,8 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
force_statement(self.body, output);
|
force_statement(self.body, output);
|
||||||
}
|
}
|
||||||
DEFPRINT(AST_If, function(self, output) {
|
DEFPRINT(AST_If, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("if");
|
output.print("if");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
@@ -1068,7 +1041,8 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ switch ]----- */
|
/* -----[ switch ]----- */
|
||||||
DEFPRINT(AST_Switch, function(self, output) {
|
DEFPRINT(AST_Switch, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("switch");
|
output.print("switch");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
@@ -1086,28 +1060,30 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output) {
|
function print_branch_body(self, output) {
|
||||||
output.newline();
|
output.newline();
|
||||||
this.body.forEach(function(stmt) {
|
self.body.forEach(function(stmt) {
|
||||||
output.indent();
|
output.indent();
|
||||||
stmt.print(output);
|
stmt.print(output);
|
||||||
output.newline();
|
output.newline();
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
DEFPRINT(AST_Default, function(self, output) {
|
DEFPRINT(AST_Default, function(output) {
|
||||||
output.print("default:");
|
output.print("default:");
|
||||||
self._do_print_body(output);
|
print_branch_body(this, output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Case, function(self, output) {
|
DEFPRINT(AST_Case, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("case");
|
output.print("case");
|
||||||
output.space();
|
output.space();
|
||||||
self.expression.print(output);
|
self.expression.print(output);
|
||||||
output.print(":");
|
output.print(":");
|
||||||
self._do_print_body(output);
|
print_branch_body(self, output);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ exceptions ]----- */
|
/* -----[ exceptions ]----- */
|
||||||
DEFPRINT(AST_Try, function(self, output) {
|
DEFPRINT(AST_Try, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("try");
|
output.print("try");
|
||||||
output.space();
|
output.space();
|
||||||
print_braced(self, output);
|
print_braced(self, output);
|
||||||
@@ -1120,22 +1096,26 @@ function OutputStream(options) {
|
|||||||
self.bfinally.print(output);
|
self.bfinally.print(output);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Catch, function(self, output) {
|
DEFPRINT(AST_Catch, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("catch");
|
output.print("catch");
|
||||||
|
if (self.argname) {
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function() {
|
output.with_parens(function() {
|
||||||
self.argname.print(output);
|
self.argname.print(output);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
output.space();
|
output.space();
|
||||||
print_braced(self, output);
|
print_braced(self, output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Finally, function(self, output) {
|
DEFPRINT(AST_Finally, function(output) {
|
||||||
output.print("finally");
|
output.print("finally");
|
||||||
output.space();
|
output.space();
|
||||||
print_braced(self, output);
|
print_braced(this, output);
|
||||||
});
|
});
|
||||||
|
|
||||||
DEFPRINT(AST_Var, function(self, output) {
|
DEFPRINT(AST_Var, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("var");
|
output.print("var");
|
||||||
output.space();
|
output.space();
|
||||||
self.definitions.forEach(function(def, i) {
|
self.definitions.forEach(function(def, i) {
|
||||||
@@ -1160,7 +1140,8 @@ function OutputStream(options) {
|
|||||||
node.print(output, parens);
|
node.print(output, parens);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFPRINT(AST_VarDef, function(self, output) {
|
DEFPRINT(AST_VarDef, function(output) {
|
||||||
|
var self = this;
|
||||||
self.name.print(output);
|
self.name.print(output);
|
||||||
if (self.value) {
|
if (self.value) {
|
||||||
output.space();
|
output.space();
|
||||||
@@ -1173,10 +1154,7 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ other expressions ]----- */
|
/* -----[ other expressions ]----- */
|
||||||
DEFPRINT(AST_Call, function(self, output) {
|
function print_call_args(self, output) {
|
||||||
self.expression.print(output);
|
|
||||||
if (self instanceof AST_New && !need_constructor_parens(self, output))
|
|
||||||
return;
|
|
||||||
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
|
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
|
||||||
output.add_mapping(self.start);
|
output.add_mapping(self.start);
|
||||||
}
|
}
|
||||||
@@ -1186,14 +1164,20 @@ function OutputStream(options) {
|
|||||||
expr.print(output);
|
expr.print(output);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
DEFPRINT(AST_Call, function(output) {
|
||||||
|
this.expression.print(output);
|
||||||
|
print_call_args(this, output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_New, function(self, output) {
|
DEFPRINT(AST_New, function(output) {
|
||||||
|
var self = this;
|
||||||
output.print("new");
|
output.print("new");
|
||||||
output.space();
|
output.space();
|
||||||
AST_Call.prototype._codegen(self, output);
|
self.expression.print(output);
|
||||||
|
if (need_constructor_parens(self, output)) print_call_args(self, output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Sequence, function(self, output) {
|
DEFPRINT(AST_Sequence, function(output) {
|
||||||
self.expressions.forEach(function(node, index) {
|
this.expressions.forEach(function(node, index) {
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
output.comma();
|
output.comma();
|
||||||
if (output.should_break()) {
|
if (output.should_break()) {
|
||||||
@@ -1204,7 +1188,8 @@ function OutputStream(options) {
|
|||||||
node.print(output);
|
node.print(output);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Dot, function(self, output) {
|
DEFPRINT(AST_Dot, function(output) {
|
||||||
|
var self = this;
|
||||||
var expr = self.expression;
|
var expr = self.expression;
|
||||||
expr.print(output);
|
expr.print(output);
|
||||||
var prop = self.property;
|
var prop = self.property;
|
||||||
@@ -1225,35 +1210,38 @@ function OutputStream(options) {
|
|||||||
output.print_name(prop);
|
output.print_name(prop);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Sub, function(self, output) {
|
DEFPRINT(AST_Sub, function(output) {
|
||||||
self.expression.print(output);
|
this.expression.print(output);
|
||||||
output.print("[");
|
output.print("[");
|
||||||
self.property.print(output);
|
this.property.print(output);
|
||||||
output.print("]");
|
output.print("]");
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_UnaryPrefix, function(self, output) {
|
DEFPRINT(AST_UnaryPrefix, function(output) {
|
||||||
var op = self.operator;
|
var op = this.operator;
|
||||||
|
var exp = this.expression;
|
||||||
output.print(op);
|
output.print(op);
|
||||||
if (/^[a-z]/i.test(op)
|
if (/^[a-z]/i.test(op)
|
||||||
|| (/[+-]$/.test(op)
|
|| (/[+-]$/.test(op)
|
||||||
&& self.expression instanceof AST_UnaryPrefix
|
&& exp instanceof AST_UnaryPrefix
|
||||||
&& /^[+-]/.test(self.expression.operator))) {
|
&& /^[+-]/.test(exp.operator))) {
|
||||||
output.space();
|
output.space();
|
||||||
}
|
}
|
||||||
self.expression.print(output);
|
exp.print(output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_UnaryPostfix, function(self, output) {
|
DEFPRINT(AST_UnaryPostfix, function(output) {
|
||||||
self.expression.print(output);
|
this.expression.print(output);
|
||||||
output.print(self.operator);
|
output.print(this.operator);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Binary, function(self, output) {
|
DEFPRINT(AST_Binary, function(output) {
|
||||||
|
var self = this;
|
||||||
self.left.print(output);
|
self.left.print(output);
|
||||||
output.space();
|
output.space();
|
||||||
output.print(self.operator);
|
output.print(self.operator);
|
||||||
output.space();
|
output.space();
|
||||||
self.right.print(output);
|
self.right.print(output);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Conditional, function(self, output) {
|
DEFPRINT(AST_Conditional, function(output) {
|
||||||
|
var self = this;
|
||||||
self.condition.print(output);
|
self.condition.print(output);
|
||||||
output.space();
|
output.space();
|
||||||
output.print("?");
|
output.print("?");
|
||||||
@@ -1265,10 +1253,10 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ literals ]----- */
|
/* -----[ literals ]----- */
|
||||||
DEFPRINT(AST_Array, function(self, output) {
|
DEFPRINT(AST_Array, function(output) {
|
||||||
output.with_square(function() {
|
var a = this.elements, len = a.length;
|
||||||
var a = self.elements, len = a.length;
|
output.with_square(len > 0 ? function() {
|
||||||
if (len > 0) output.space();
|
output.space();
|
||||||
a.forEach(function(exp, i) {
|
a.forEach(function(exp, i) {
|
||||||
if (i) output.comma();
|
if (i) output.comma();
|
||||||
exp.print(output);
|
exp.print(output);
|
||||||
@@ -1278,12 +1266,13 @@ function OutputStream(options) {
|
|||||||
if (i === len - 1 && exp instanceof AST_Hole)
|
if (i === len - 1 && exp instanceof AST_Hole)
|
||||||
output.comma();
|
output.comma();
|
||||||
});
|
});
|
||||||
if (len > 0) output.space();
|
output.space();
|
||||||
|
} : noop);
|
||||||
});
|
});
|
||||||
});
|
DEFPRINT(AST_Object, function(output) {
|
||||||
DEFPRINT(AST_Object, function(self, output) {
|
var props = this.properties;
|
||||||
if (self.properties.length > 0) output.with_block(function() {
|
if (props.length > 0) output.with_block(function() {
|
||||||
self.properties.forEach(function(prop, i) {
|
props.forEach(function(prop, i) {
|
||||||
if (i) {
|
if (i) {
|
||||||
output.print(",");
|
output.print(",");
|
||||||
output.newline();
|
output.newline();
|
||||||
@@ -1293,7 +1282,7 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
output.newline();
|
output.newline();
|
||||||
});
|
});
|
||||||
else print_braced_empty(self, output);
|
else print_braced_empty(this, output);
|
||||||
});
|
});
|
||||||
|
|
||||||
function print_property_name(key, quote, output) {
|
function print_property_name(key, quote, output) {
|
||||||
@@ -1312,47 +1301,48 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFPRINT(AST_ObjectKeyVal, function(self, output) {
|
DEFPRINT(AST_ObjectKeyVal, function(output) {
|
||||||
|
var self = this;
|
||||||
print_property_name(self.key, self.quote, output);
|
print_property_name(self.key, self.quote, output);
|
||||||
output.colon();
|
output.colon();
|
||||||
self.value.print(output);
|
self.value.print(output);
|
||||||
});
|
});
|
||||||
AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, output) {
|
function print_accessor(type) {
|
||||||
|
return function(output) {
|
||||||
|
var self = this;
|
||||||
output.print(type);
|
output.print(type);
|
||||||
output.space();
|
output.space();
|
||||||
print_property_name(this.key.name, this.quote, output);
|
print_property_name(self.key.name, self.quote, output);
|
||||||
this.value._do_print(output, true);
|
self.value._codegen(output, true);
|
||||||
});
|
};
|
||||||
DEFPRINT(AST_ObjectSetter, function(self, output) {
|
}
|
||||||
self._print_getter_setter("set", output);
|
DEFPRINT(AST_ObjectGetter, print_accessor("get"));
|
||||||
});
|
DEFPRINT(AST_ObjectSetter, print_accessor("set"));
|
||||||
DEFPRINT(AST_ObjectGetter, function(self, output) {
|
DEFPRINT(AST_Symbol, function(output) {
|
||||||
self._print_getter_setter("get", output);
|
var def = this.definition();
|
||||||
});
|
output.print_name(def && def.mangled_name || this.name);
|
||||||
DEFPRINT(AST_Symbol, function(self, output) {
|
|
||||||
var def = self.definition();
|
|
||||||
output.print_name(def && def.mangled_name || self.name);
|
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Hole, noop);
|
DEFPRINT(AST_Hole, noop);
|
||||||
DEFPRINT(AST_This, function(self, output) {
|
DEFPRINT(AST_This, function(output) {
|
||||||
output.print("this");
|
output.print("this");
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Constant, function(self, output) {
|
DEFPRINT(AST_Constant, function(output) {
|
||||||
output.print(self.value);
|
output.print(this.value);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_String, function(self, output) {
|
DEFPRINT(AST_String, function(output) {
|
||||||
output.print_string(self.value, self.quote);
|
output.print_string(this.value, this.quote);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Number, function(self, output) {
|
DEFPRINT(AST_Number, function(output) {
|
||||||
if (use_asm && self.start && self.start.raw != null) {
|
var start = this.start;
|
||||||
output.print(self.start.raw);
|
if (use_asm && start && start.raw != null) {
|
||||||
|
output.print(start.raw);
|
||||||
} else {
|
} else {
|
||||||
output.print(make_num(self.value));
|
output.print(make_num(this.value));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
DEFPRINT(AST_RegExp, function(self, output) {
|
DEFPRINT(AST_RegExp, function(output) {
|
||||||
var regexp = self.value;
|
var regexp = this.value;
|
||||||
var str = regexp.toString();
|
var str = regexp.toString();
|
||||||
var end = str.lastIndexOf("/");
|
var end = str.lastIndexOf("/");
|
||||||
if (regexp.raw_source) {
|
if (regexp.raw_source) {
|
||||||
@@ -1386,7 +1376,7 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
|
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === this)
|
||||||
output.print(" ");
|
output.print(" ");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
53
lib/parse.js
53
lib/parse.js
@@ -44,11 +44,14 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with';
|
var KEYWORDS = "break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with";
|
||||||
var KEYWORDS_ATOM = 'false null true';
|
var KEYWORDS_ATOM = "false null true";
|
||||||
var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface let long native package private protected public short static super synchronized this throws transient volatile yield'
|
var RESERVED_WORDS = [
|
||||||
+ " " + KEYWORDS_ATOM + " " + KEYWORDS;
|
"abstract boolean byte char class double enum export extends final float goto implements import int interface let long native package private protected public short static super synchronized this throws transient volatile yield",
|
||||||
var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case';
|
KEYWORDS_ATOM,
|
||||||
|
KEYWORDS,
|
||||||
|
].join(" ");
|
||||||
|
var KEYWORDS_BEFORE_EXPRESSION = "return new delete throw else case";
|
||||||
|
|
||||||
KEYWORDS = makePredicate(KEYWORDS);
|
KEYWORDS = makePredicate(KEYWORDS);
|
||||||
RESERVED_WORDS = makePredicate(RESERVED_WORDS);
|
RESERVED_WORDS = makePredicate(RESERVED_WORDS);
|
||||||
@@ -57,8 +60,9 @@ KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);
|
|||||||
|
|
||||||
var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
|
var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
|
||||||
|
|
||||||
var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
|
var RE_BIN_NUMBER = /^0b([01]+)$/i;
|
||||||
var RE_OCT_NUMBER = /^0[0-7]+$/;
|
var RE_HEX_NUMBER = /^0x([0-9a-f]+)$/i;
|
||||||
|
var RE_OCT_NUMBER = /^0o?([0-7]+)$/i;
|
||||||
|
|
||||||
var OPERATORS = makePredicate([
|
var OPERATORS = makePredicate([
|
||||||
"in",
|
"in",
|
||||||
@@ -144,10 +148,6 @@ function is_digit(code) {
|
|||||||
return code >= 48 && code <= 57;
|
return code >= 48 && code <= 57;
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_alphanumeric_char(code) {
|
|
||||||
return is_digit(code) || is_letter(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_unicode_digit(code) {
|
function is_unicode_digit(code) {
|
||||||
return UNICODE.digit.test(String.fromCharCode(code));
|
return UNICODE.digit.test(String.fromCharCode(code));
|
||||||
}
|
}
|
||||||
@@ -181,15 +181,13 @@ function is_identifier_string(str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parse_js_number(num) {
|
function parse_js_number(num) {
|
||||||
if (RE_HEX_NUMBER.test(num)) {
|
var match;
|
||||||
return parseInt(num.substr(2), 16);
|
if (match = RE_BIN_NUMBER.exec(num)) return parseInt(match[1], 2);
|
||||||
} else if (RE_OCT_NUMBER.test(num)) {
|
if (match = RE_HEX_NUMBER.exec(num)) return parseInt(match[1], 16);
|
||||||
return parseInt(num.substr(1), 8);
|
if (match = RE_OCT_NUMBER.exec(num)) return parseInt(match[1], 8);
|
||||||
} else {
|
|
||||||
var val = parseFloat(num);
|
var val = parseFloat(num);
|
||||||
if (val == num) return val;
|
if (val == num) return val;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function JS_Parse_Error(message, filename, line, col, pos) {
|
function JS_Parse_Error(message, filename, line, col, pos) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
@@ -344,11 +342,13 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
case (after_e = false, 46): // .
|
case (after_e = false, 46): // .
|
||||||
return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false;
|
return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false;
|
||||||
}
|
}
|
||||||
return is_alphanumeric_char(code);
|
return is_digit(code) || is_letter(code) || ch == "_";
|
||||||
});
|
});
|
||||||
if (prefix) num = prefix + num;
|
if (prefix) num = prefix + num;
|
||||||
if (RE_OCT_NUMBER.test(num) && next_token.has_directive("use strict")) {
|
if (/^0[0-7_]+$/.test(num)) {
|
||||||
parse_error("Legacy octal literals are not allowed in strict mode");
|
if (next_token.has_directive("use strict")) parse_error("Legacy octal literals are not allowed in strict mode");
|
||||||
|
} else {
|
||||||
|
num = num.replace(has_x ? /([1-9a-f]|.0)_(?=[0-9a-f])/gi : /([1-9]|.0)_(?=[0-9])/gi, "$1");
|
||||||
}
|
}
|
||||||
var valid = parse_js_number(num);
|
var valid = parse_js_number(num);
|
||||||
if (!isNaN(valid)) return token("num", valid);
|
if (!isNaN(valid)) return token("num", valid);
|
||||||
@@ -438,7 +438,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function() {
|
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function() {
|
||||||
var regex_allowed = S.regex_allowed;
|
var regex_allowed = S.regex_allowed;
|
||||||
var i = find("*/", true);
|
var i = find("*/", true);
|
||||||
var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, '\n');
|
var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, "\n");
|
||||||
// update stream position
|
// update stream position
|
||||||
forward(text.length /* doesn't count \r\n as 2 char while S.pos - i does */ + 2);
|
forward(text.length /* doesn't count \r\n as 2 char while S.pos - i does */ + 2);
|
||||||
S.comments_before.push(token("comment2", text, true));
|
S.comments_before.push(token("comment2", text, true));
|
||||||
@@ -1092,7 +1092,7 @@ function parse($TEXT, options) {
|
|||||||
|
|
||||||
function switch_body_() {
|
function switch_body_() {
|
||||||
expect("{");
|
expect("{");
|
||||||
var a = [], cur = null, branch = null, tmp;
|
var a = [], branch, cur, default_branch, tmp;
|
||||||
while (!is("punc", "}")) {
|
while (!is("punc", "}")) {
|
||||||
if (is("eof")) expect_token("punc", "}");
|
if (is("eof")) expect_token("punc", "}");
|
||||||
if (is("keyword", "case")) {
|
if (is("keyword", "case")) {
|
||||||
@@ -1107,12 +1107,14 @@ function parse($TEXT, options) {
|
|||||||
expect(":");
|
expect(":");
|
||||||
} else if (is("keyword", "default")) {
|
} else if (is("keyword", "default")) {
|
||||||
if (branch) branch.end = prev();
|
if (branch) branch.end = prev();
|
||||||
|
if (default_branch) croak("More than one default clause in switch statement");
|
||||||
cur = [];
|
cur = [];
|
||||||
branch = new AST_Default({
|
branch = new AST_Default({
|
||||||
start : (tmp = S.token, next(), expect(":"), tmp),
|
start : (tmp = S.token, next(), expect(":"), tmp),
|
||||||
body : cur
|
body : cur
|
||||||
});
|
});
|
||||||
a.push(branch);
|
a.push(branch);
|
||||||
|
default_branch = branch;
|
||||||
} else {
|
} else {
|
||||||
if (!cur) unexpected();
|
if (!cur) unexpected();
|
||||||
cur.push(statement());
|
cur.push(statement());
|
||||||
@@ -1128,9 +1130,12 @@ function parse($TEXT, options) {
|
|||||||
if (is("keyword", "catch")) {
|
if (is("keyword", "catch")) {
|
||||||
var start = S.token;
|
var start = S.token;
|
||||||
next();
|
next();
|
||||||
expect("(");
|
var name = null;
|
||||||
var name = as_symbol(AST_SymbolCatch);
|
if (is("punc", "(")) {
|
||||||
|
next();
|
||||||
|
name = as_symbol(AST_SymbolCatch);
|
||||||
expect(")");
|
expect(")");
|
||||||
|
}
|
||||||
bcatch = new AST_Catch({
|
bcatch = new AST_Catch({
|
||||||
start : start,
|
start : start,
|
||||||
argname : name,
|
argname : name,
|
||||||
|
|||||||
@@ -43,7 +43,8 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function find_builtins(reserved) {
|
var builtins = function() {
|
||||||
|
var names = [];
|
||||||
// NaN will be included due to Number.NaN
|
// NaN will be included due to Number.NaN
|
||||||
[
|
[
|
||||||
"null",
|
"null",
|
||||||
@@ -67,19 +68,21 @@ function find_builtins(reserved) {
|
|||||||
].forEach(function(ctor) {
|
].forEach(function(ctor) {
|
||||||
Object.getOwnPropertyNames(ctor).map(add);
|
Object.getOwnPropertyNames(ctor).map(add);
|
||||||
if (ctor.prototype) {
|
if (ctor.prototype) {
|
||||||
|
Object.getOwnPropertyNames(new ctor()).map(add);
|
||||||
Object.getOwnPropertyNames(ctor.prototype).map(add);
|
Object.getOwnPropertyNames(ctor.prototype).map(add);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return makePredicate(names);
|
||||||
|
|
||||||
function add(name) {
|
function add(name) {
|
||||||
push_uniq(reserved, name);
|
names.push(name);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
function reserve_quoted_keys(ast, reserved) {
|
function reserve_quoted_keys(ast, reserved) {
|
||||||
ast.walk(new TreeWalker(function(node) {
|
ast.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_ObjectKeyVal && node.quote) {
|
if (node instanceof AST_ObjectKeyVal) {
|
||||||
add(node.key);
|
if (node.quote) add(node.key);
|
||||||
} else if (node instanceof AST_Sub) {
|
} else if (node instanceof AST_Sub) {
|
||||||
addStrings(node.property, add);
|
addStrings(node.property, add);
|
||||||
}
|
}
|
||||||
@@ -91,17 +94,14 @@ function reserve_quoted_keys(ast, reserved) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addStrings(node, add) {
|
function addStrings(node, add) {
|
||||||
node.walk(new TreeWalker(function(node) {
|
if (node instanceof AST_Conditional) {
|
||||||
if (node instanceof AST_Sequence) {
|
addStrings(node.consequent, add);
|
||||||
|
addStrings(node.alternative, add);
|
||||||
|
} else if (node instanceof AST_Sequence) {
|
||||||
addStrings(node.tail_node(), add);
|
addStrings(node.tail_node(), add);
|
||||||
} else if (node instanceof AST_String) {
|
} else if (node instanceof AST_String) {
|
||||||
add(node.value);
|
add(node.value);
|
||||||
} else if (node instanceof AST_Conditional) {
|
|
||||||
addStrings(node.consequent, add);
|
|
||||||
addStrings(node.alternative, add);
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mangle_properties(ast, options) {
|
function mangle_properties(ast, options) {
|
||||||
@@ -110,21 +110,21 @@ function mangle_properties(ast, options) {
|
|||||||
cache: null,
|
cache: null,
|
||||||
debug: false,
|
debug: false,
|
||||||
keep_quoted: false,
|
keep_quoted: false,
|
||||||
only_cache: false,
|
|
||||||
regex: null,
|
regex: null,
|
||||||
reserved: null,
|
reserved: null,
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
var reserved = options.reserved;
|
var reserved = Object.create(options.builtins ? null : builtins);
|
||||||
if (!Array.isArray(reserved)) reserved = [];
|
if (Array.isArray(options.reserved)) options.reserved.forEach(function(name) {
|
||||||
if (!options.builtins) find_builtins(reserved);
|
reserved[name] = true;
|
||||||
|
});
|
||||||
|
|
||||||
var cname = -1;
|
var cname = -1;
|
||||||
var cache;
|
var cache;
|
||||||
if (options.cache) {
|
if (options.cache) {
|
||||||
cache = options.cache.props;
|
cache = options.cache.props;
|
||||||
cache.each(function(mangled_name) {
|
cache.each(function(name) {
|
||||||
push_uniq(reserved, mangled_name);
|
reserved[name] = true;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
cache = new Dictionary();
|
cache = new Dictionary();
|
||||||
@@ -139,62 +139,92 @@ function mangle_properties(ast, options) {
|
|||||||
var debug_suffix;
|
var debug_suffix;
|
||||||
if (debug) debug_suffix = options.debug === true ? "" : options.debug;
|
if (debug) debug_suffix = options.debug === true ? "" : options.debug;
|
||||||
|
|
||||||
var names_to_mangle = [];
|
var names_to_mangle = Object.create(null);
|
||||||
var unmangleable = [];
|
var unmangleable = Object.create(reserved);
|
||||||
|
|
||||||
// step 1: find candidates to mangle
|
// step 1: find candidates to mangle
|
||||||
ast.walk(new TreeWalker(function(node) {
|
ast.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_ObjectKeyVal) {
|
if (node instanceof AST_Binary) {
|
||||||
|
if (node.operator == "in") addStrings(node.left, add);
|
||||||
|
} else if (node.TYPE == "Call") {
|
||||||
|
var exp = node.expression;
|
||||||
|
if (exp instanceof AST_Dot) switch (exp.property) {
|
||||||
|
case "defineProperty":
|
||||||
|
case "getOwnPropertyDescriptor":
|
||||||
|
if (node.args.length < 2) break;
|
||||||
|
exp = exp.expression;
|
||||||
|
if (!(exp instanceof AST_SymbolRef)) break;
|
||||||
|
if (exp.name != "Object") break;
|
||||||
|
if (!exp.definition().undeclared) break;
|
||||||
|
addStrings(node.args[1], add);
|
||||||
|
break;
|
||||||
|
case "hasOwnProperty":
|
||||||
|
if (node.args.length < 1) break;
|
||||||
|
addStrings(node.args[0], add);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (node instanceof AST_Dot) {
|
||||||
|
add(node.property);
|
||||||
|
} else if (node instanceof AST_ObjectKeyVal) {
|
||||||
add(node.key);
|
add(node.key);
|
||||||
} else if (node instanceof AST_ObjectProperty) {
|
} else if (node instanceof AST_ObjectProperty) {
|
||||||
// setter or getter, since KeyVal is handled above
|
// setter or getter, since KeyVal is handled above
|
||||||
add(node.key.name);
|
add(node.key.name);
|
||||||
} else if (node instanceof AST_Dot) {
|
|
||||||
add(node.property);
|
|
||||||
} else if (node instanceof AST_Sub) {
|
} else if (node instanceof AST_Sub) {
|
||||||
addStrings(node.property, add);
|
addStrings(node.property, add);
|
||||||
} else if (node instanceof AST_Call
|
|
||||||
&& node.expression.print_to_string() == "Object.defineProperty") {
|
|
||||||
addStrings(node.args[1], add);
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// step 2: transform the tree, renaming properties
|
// step 2: renaming properties
|
||||||
return ast.transform(new TreeTransformer(function(node) {
|
ast.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_ObjectKeyVal) {
|
if (node instanceof AST_Binary) {
|
||||||
|
if (node.operator == "in") mangleStrings(node.left);
|
||||||
|
} else if (node.TYPE == "Call") {
|
||||||
|
var exp = node.expression;
|
||||||
|
if (exp instanceof AST_Dot) switch (exp.property) {
|
||||||
|
case "defineProperty":
|
||||||
|
case "getOwnPropertyDescriptor":
|
||||||
|
if (node.args.length < 2) break;
|
||||||
|
exp = exp.expression;
|
||||||
|
if (!(exp instanceof AST_SymbolRef)) break;
|
||||||
|
if (exp.name != "Object") break;
|
||||||
|
if (!exp.definition().undeclared) break;
|
||||||
|
mangleStrings(node.args[1]);
|
||||||
|
break;
|
||||||
|
case "hasOwnProperty":
|
||||||
|
if (node.args.length < 1) break;
|
||||||
|
mangleStrings(node.args[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (node instanceof AST_Dot) {
|
||||||
|
node.property = mangle(node.property);
|
||||||
|
} else if (node instanceof AST_ObjectKeyVal) {
|
||||||
node.key = mangle(node.key);
|
node.key = mangle(node.key);
|
||||||
} else if (node instanceof AST_ObjectProperty) {
|
} else if (node instanceof AST_ObjectProperty) {
|
||||||
// setter or getter
|
// setter or getter
|
||||||
node.key.name = mangle(node.key.name);
|
node.key.name = mangle(node.key.name);
|
||||||
} else if (node instanceof AST_Dot) {
|
} else if (node instanceof AST_Sub) {
|
||||||
node.property = mangle(node.property);
|
if (!options.keep_quoted) mangleStrings(node.property);
|
||||||
} else if (!options.keep_quoted && node instanceof AST_Sub) {
|
|
||||||
node.property = mangleStrings(node.property);
|
|
||||||
} else if (node instanceof AST_Call
|
|
||||||
&& node.expression.print_to_string() == "Object.defineProperty") {
|
|
||||||
node.args[1] = mangleStrings(node.args[1]);
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// only function declarations after this line
|
// only function declarations after this line
|
||||||
|
|
||||||
function can_mangle(name) {
|
function can_mangle(name) {
|
||||||
if (unmangleable.indexOf(name) >= 0) return false;
|
if (unmangleable[name]) return false;
|
||||||
if (reserved.indexOf(name) >= 0) return false;
|
|
||||||
if (options.only_cache) return cache.has(name);
|
|
||||||
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
|
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function should_mangle(name) {
|
function should_mangle(name) {
|
||||||
|
if (reserved[name]) return false;
|
||||||
if (regex && !regex.test(name)) return false;
|
if (regex && !regex.test(name)) return false;
|
||||||
if (reserved.indexOf(name) >= 0) return false;
|
return cache.has(name) || names_to_mangle[name];
|
||||||
return cache.has(name) || names_to_mangle.indexOf(name) >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function add(name) {
|
function add(name) {
|
||||||
if (can_mangle(name)) push_uniq(names_to_mangle, name);
|
if (can_mangle(name)) names_to_mangle[name] = true;
|
||||||
if (!should_mangle(name)) push_uniq(unmangleable, name);
|
if (!should_mangle(name)) unmangleable[name] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mangle(name) {
|
function mangle(name) {
|
||||||
@@ -218,17 +248,13 @@ function mangle_properties(ast, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mangleStrings(node) {
|
function mangleStrings(node) {
|
||||||
return node.transform(new TreeTransformer(function(node) {
|
|
||||||
if (node instanceof AST_Sequence) {
|
if (node instanceof AST_Sequence) {
|
||||||
var last = node.expressions.length - 1;
|
mangleStrings(node.expressions.tail_node());
|
||||||
node.expressions[last] = mangleStrings(node.expressions[last]);
|
|
||||||
} else if (node instanceof AST_String) {
|
} else if (node instanceof AST_String) {
|
||||||
node.value = mangle(node.value);
|
node.value = mangle(node.value);
|
||||||
} else if (node instanceof AST_Conditional) {
|
} else if (node instanceof AST_Conditional) {
|
||||||
node.consequent = mangleStrings(node.consequent);
|
mangleStrings(node.consequent);
|
||||||
node.alternative = mangleStrings(node.alternative);
|
mangleStrings(node.alternative);
|
||||||
}
|
}
|
||||||
return node;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
236
lib/scope.js
236
lib/scope.js
@@ -59,13 +59,9 @@ function SymbolDef(id, scope, orig, init) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SymbolDef.prototype = {
|
SymbolDef.prototype = {
|
||||||
unmangleable: function(options) {
|
forEach: function(fn) {
|
||||||
return this.global && !options.toplevel
|
this.orig.forEach(fn);
|
||||||
|| this.undeclared
|
this.references.forEach(fn);
|
||||||
|| !options.eval && this.scope.pinned()
|
|
||||||
|| options.keep_fnames
|
|
||||||
&& (this.orig[0] instanceof AST_SymbolLambda
|
|
||||||
|| this.orig[0] instanceof AST_SymbolDefun);
|
|
||||||
},
|
},
|
||||||
mangle: function(options) {
|
mangle: function(options) {
|
||||||
var cache = options.cache && options.cache.props;
|
var cache = options.cache && options.cache.props;
|
||||||
@@ -85,7 +81,15 @@ SymbolDef.prototype = {
|
|||||||
},
|
},
|
||||||
redefined: function() {
|
redefined: function() {
|
||||||
return this.defun && this.defun.variables.get(this.name);
|
return this.defun && this.defun.variables.get(this.name);
|
||||||
}
|
},
|
||||||
|
unmangleable: function(options) {
|
||||||
|
return this.global && !options.toplevel
|
||||||
|
|| this.undeclared
|
||||||
|
|| !options.eval && this.scope.pinned()
|
||||||
|
|| options.keep_fnames
|
||||||
|
&& (this.orig[0] instanceof AST_SymbolLambda
|
||||||
|
|| this.orig[0] instanceof AST_SymbolDefun);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||||
@@ -96,29 +100,39 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
|
|
||||||
// pass 1: setup scope chaining and handle definitions
|
// pass 1: setup scope chaining and handle definitions
|
||||||
var self = this;
|
var self = this;
|
||||||
var scope = self.parent_scope = null;
|
|
||||||
var defun = null;
|
var defun = null;
|
||||||
|
var next_def_id = 0;
|
||||||
|
var scope = self.parent_scope = null;
|
||||||
var tw = new TreeWalker(function(node, descend) {
|
var tw = new TreeWalker(function(node, descend) {
|
||||||
if (node instanceof AST_Catch) {
|
if (node instanceof AST_Defun) {
|
||||||
var save_scope = scope;
|
node.name.walk(tw);
|
||||||
scope = new AST_Scope(node);
|
walk_scope(function() {
|
||||||
scope.init_scope_vars(save_scope);
|
node.argnames.forEach(function(argname) {
|
||||||
descend();
|
argname.walk(tw);
|
||||||
scope = save_scope;
|
});
|
||||||
|
walk_body(node, tw);
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Scope) {
|
if (node instanceof AST_Try) {
|
||||||
node.init_scope_vars(scope);
|
walk_scope(function() {
|
||||||
var save_scope = scope;
|
walk_body(node, tw);
|
||||||
var save_defun = defun;
|
});
|
||||||
defun = scope = node;
|
if (node.bcatch) node.bcatch.walk(tw);
|
||||||
descend();
|
if (node.bfinally) node.bfinally.walk(tw);
|
||||||
scope = save_scope;
|
return true;
|
||||||
defun = save_defun;
|
}
|
||||||
|
if (node instanceof AST_BlockScope) {
|
||||||
|
walk_scope(descend);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_With) {
|
if (node instanceof AST_With) {
|
||||||
for (var s = scope; s; s = s.parent_scope) s.uses_with = true;
|
var s = scope;
|
||||||
|
do {
|
||||||
|
s = s.resolve();
|
||||||
|
if (s.uses_with) break;
|
||||||
|
s.uses_with = true;
|
||||||
|
} while (s = s.parent_scope);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Symbol) {
|
if (node instanceof AST_Symbol) {
|
||||||
@@ -128,28 +142,46 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
node.thedef = node;
|
node.thedef = node;
|
||||||
node.references = [];
|
node.references = [];
|
||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolDefun) {
|
if (node instanceof AST_SymbolCatch) {
|
||||||
// This should be defined in the parent scope, as we encounter the
|
scope.def_variable(node).defun = defun;
|
||||||
// AST_Defun node before getting to its AST_Symbol.
|
} else if (node instanceof AST_SymbolDefun) {
|
||||||
(node.scope = defun.parent_scope.resolve()).def_function(node, defun);
|
defun.def_function(node, tw.parent());
|
||||||
|
entangle(defun, scope);
|
||||||
|
} else if (node instanceof AST_SymbolFunarg) {
|
||||||
|
defun.def_variable(node);
|
||||||
|
entangle(defun, scope);
|
||||||
} else if (node instanceof AST_SymbolLambda) {
|
} else if (node instanceof AST_SymbolLambda) {
|
||||||
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
|
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
|
||||||
if (options.ie8) def.defun = defun.parent_scope.resolve();
|
if (options.ie8) def.defun = defun.parent_scope.resolve();
|
||||||
} else if (node instanceof AST_SymbolVar) {
|
} else if (node instanceof AST_SymbolVar) {
|
||||||
defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
|
defun.def_variable(node, null);
|
||||||
if (defun !== scope) {
|
entangle(defun, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
function walk_scope(descend) {
|
||||||
|
node.init_vars(scope);
|
||||||
|
var save_defun = defun;
|
||||||
|
var save_scope = scope;
|
||||||
|
if (node instanceof AST_Scope) defun = node;
|
||||||
|
scope = node;
|
||||||
|
descend();
|
||||||
|
scope = save_scope;
|
||||||
|
defun = save_defun;
|
||||||
|
}
|
||||||
|
|
||||||
|
function entangle(defun, scope) {
|
||||||
|
if (defun === scope) return;
|
||||||
node.mark_enclosed(options);
|
node.mark_enclosed(options);
|
||||||
var def = scope.find_variable(node);
|
var def = scope.find_variable(node);
|
||||||
if (node.thedef !== def) {
|
if (node.thedef === def) return;
|
||||||
node.thedef = def;
|
node.thedef = def;
|
||||||
}
|
def.orig.push(node);
|
||||||
node.reference(options);
|
node.mark_enclosed(options);
|
||||||
}
|
|
||||||
} else if (node instanceof AST_SymbolCatch) {
|
|
||||||
scope.def_variable(node).defun = defun;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.next_def_id = 0;
|
self.make_def = function(orig, init) {
|
||||||
|
return new SymbolDef(++next_def_id, this, orig, init);
|
||||||
|
};
|
||||||
self.walk(tw);
|
self.walk(tw);
|
||||||
|
|
||||||
// pass 2: find back references and eval
|
// pass 2: find back references and eval
|
||||||
@@ -164,15 +196,18 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
var sym = node.scope.find_variable(name);
|
var sym = node.scope.find_variable(name);
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
sym = self.def_global(node);
|
sym = self.def_global(node);
|
||||||
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
|
} else if (name == "arguments" && sym.scope instanceof AST_Lambda) {
|
||||||
sym.scope.uses_arguments = true;
|
sym.scope.uses_arguments = true;
|
||||||
}
|
}
|
||||||
if (name == "eval") {
|
if (name == "eval") {
|
||||||
var parent = tw.parent();
|
var parent = tw.parent();
|
||||||
if (parent.TYPE == "Call" && parent.expression === node) {
|
if (parent.TYPE == "Call" && parent.expression === node) {
|
||||||
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
|
var s = node.scope;
|
||||||
|
do {
|
||||||
|
s = s.resolve();
|
||||||
|
if (s.uses_eval) break;
|
||||||
s.uses_eval = true;
|
s.uses_eval = true;
|
||||||
}
|
} while (s = s.parent_scope);
|
||||||
} else if (sym.undeclared) {
|
} else if (sym.undeclared) {
|
||||||
self.uses_eval = true;
|
self.uses_eval = true;
|
||||||
}
|
}
|
||||||
@@ -230,7 +265,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
} else {
|
} else {
|
||||||
new_def = scope.def_variable(node);
|
new_def = scope.def_variable(node);
|
||||||
}
|
}
|
||||||
old_def.orig.concat(old_def.references).forEach(function(node) {
|
old_def.defun = new_def.scope;
|
||||||
|
old_def.forEach(function(node) {
|
||||||
|
node.redef = true;
|
||||||
node.thedef = new_def;
|
node.thedef = new_def;
|
||||||
node.reference(options);
|
node.reference(options);
|
||||||
});
|
});
|
||||||
@@ -239,12 +276,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
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)) {
|
||||||
@@ -258,24 +289,36 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
|
function init_block_vars(scope, parent) {
|
||||||
this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
scope.cname = -1; // the current index for mangling functions/variables
|
||||||
this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
|
scope.enclosed = []; // variables from this or outer scope(s) that are referenced from this or inner scopes
|
||||||
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
scope.parent_scope = parent; // the parent scope (null if this is the top level)
|
||||||
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
|
scope.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
|
||||||
this.parent_scope = parent_scope; // the parent scope
|
scope.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
||||||
this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
|
if (parent) scope.make_def = parent.make_def; // top-level tracking of SymbolDef instances
|
||||||
this.cname = -1; // the current index for mangling functions/variables
|
}
|
||||||
});
|
|
||||||
|
|
||||||
AST_Lambda.DEFMETHOD("init_scope_vars", function() {
|
function init_scope_vars(scope, parent) {
|
||||||
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
|
init_block_vars(scope, parent);
|
||||||
|
scope.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
|
||||||
|
scope.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
||||||
|
}
|
||||||
|
|
||||||
|
AST_BlockScope.DEFMETHOD("init_vars", function(parent_scope) {
|
||||||
|
init_block_vars(this, parent_scope);
|
||||||
|
});
|
||||||
|
AST_Scope.DEFMETHOD("init_vars", function(parent_scope) {
|
||||||
|
init_scope_vars(this, parent_scope);
|
||||||
|
});
|
||||||
|
AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) {
|
||||||
|
init_scope_vars(this, parent_scope);
|
||||||
this.uses_arguments = false;
|
this.uses_arguments = false;
|
||||||
this.def_variable(new AST_SymbolFunarg({
|
this.def_variable(new AST_SymbolFunarg({
|
||||||
name: "arguments",
|
name: "arguments",
|
||||||
start: this.start,
|
start: this.start,
|
||||||
end: this.end
|
end: this.end,
|
||||||
}));
|
}));
|
||||||
|
return this;
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
|
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
|
||||||
@@ -296,20 +339,20 @@ AST_Symbol.DEFMETHOD("reference", function(options) {
|
|||||||
this.mark_enclosed(options);
|
this.mark_enclosed(options);
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("find_variable", function(name) {
|
AST_BlockScope.DEFMETHOD("find_variable", function(name) {
|
||||||
if (name instanceof AST_Symbol) name = name.name;
|
if (name instanceof AST_Symbol) name = name.name;
|
||||||
return this.variables.get(name)
|
return this.variables.get(name)
|
||||||
|| (this.parent_scope && this.parent_scope.find_variable(name));
|
|| (this.parent_scope && this.parent_scope.find_variable(name));
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("def_function", function(symbol, init) {
|
AST_BlockScope.DEFMETHOD("def_function", function(symbol, init) {
|
||||||
var def = this.def_variable(symbol, init);
|
var def = this.def_variable(symbol, init);
|
||||||
if (!def.init || def.init instanceof AST_Defun) def.init = init;
|
if (!def.init || def.init instanceof AST_Defun) def.init = init;
|
||||||
this.functions.set(symbol.name, def);
|
this.functions.set(symbol.name, def);
|
||||||
return def;
|
return def;
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
|
AST_BlockScope.DEFMETHOD("def_variable", function(symbol, init) {
|
||||||
var def = this.variables.get(symbol.name);
|
var def = this.variables.get(symbol.name);
|
||||||
if (def) {
|
if (def) {
|
||||||
def.orig.push(symbol);
|
def.orig.push(symbol);
|
||||||
@@ -322,16 +365,10 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
|
|||||||
return symbol.thedef = def;
|
return symbol.thedef = def;
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Lambda.DEFMETHOD("resolve", return_this);
|
|
||||||
AST_Scope.DEFMETHOD("resolve", function() {
|
|
||||||
return this.parent_scope.resolve();
|
|
||||||
});
|
|
||||||
AST_Toplevel.DEFMETHOD("resolve", return_this);
|
|
||||||
|
|
||||||
function names_in_use(scope, options) {
|
function names_in_use(scope, options) {
|
||||||
var names = scope.names_in_use;
|
var names = scope.names_in_use;
|
||||||
if (!names) {
|
if (!names) {
|
||||||
scope.names_in_use = names = Object.create(scope.mangled_names || null);
|
scope.names_in_use = names = Object.create(null);
|
||||||
scope.cname_holes = [];
|
scope.cname_holes = [];
|
||||||
var cache = options.cache && options.cache.props;
|
var cache = options.cache && options.cache.props;
|
||||||
scope.enclosed.forEach(function(def) {
|
scope.enclosed.forEach(function(def) {
|
||||||
@@ -349,7 +386,7 @@ function next_mangled_name(scope, options, def) {
|
|||||||
var holes = scope.cname_holes;
|
var holes = scope.cname_holes;
|
||||||
var names = Object.create(null);
|
var names = Object.create(null);
|
||||||
var scopes = [ scope ];
|
var scopes = [ scope ];
|
||||||
def.references.forEach(function(sym) {
|
def.forEach(function(sym) {
|
||||||
var scope = sym.scope;
|
var scope = sym.scope;
|
||||||
do {
|
do {
|
||||||
if (scopes.indexOf(scope) < 0) {
|
if (scopes.indexOf(scope) < 0) {
|
||||||
@@ -365,7 +402,7 @@ function next_mangled_name(scope, options, def) {
|
|||||||
name = base54(holes[i]);
|
name = base54(holes[i]);
|
||||||
if (names[name]) continue;
|
if (names[name]) continue;
|
||||||
holes.splice(i, 1);
|
holes.splice(i, 1);
|
||||||
scope.names_in_use[name] = true;
|
in_use[name] = true;
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -374,7 +411,7 @@ function next_mangled_name(scope, options, def) {
|
|||||||
if (!names[name]) break;
|
if (!names[name]) break;
|
||||||
holes.push(scope.cname);
|
holes.push(scope.cname);
|
||||||
}
|
}
|
||||||
scope.names_in_use[name] = true;
|
in_use[name] = true;
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,18 +423,10 @@ AST_Symbol.DEFMETHOD("unmangleable", function(options) {
|
|||||||
// labels are always mangleable
|
// labels are always mangleable
|
||||||
AST_Label.DEFMETHOD("unmangleable", return_false);
|
AST_Label.DEFMETHOD("unmangleable", return_false);
|
||||||
|
|
||||||
AST_Symbol.DEFMETHOD("unreferenced", function() {
|
|
||||||
return !this.definition().references.length && !this.scope.pinned();
|
|
||||||
});
|
|
||||||
|
|
||||||
AST_Symbol.DEFMETHOD("definition", function() {
|
AST_Symbol.DEFMETHOD("definition", function() {
|
||||||
return this.thedef;
|
return this.thedef;
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Symbol.DEFMETHOD("global", function() {
|
|
||||||
return this.definition().global;
|
|
||||||
});
|
|
||||||
|
|
||||||
function _default_mangler_options(options) {
|
function _default_mangler_options(options) {
|
||||||
options = defaults(options, {
|
options = defaults(options, {
|
||||||
eval : false,
|
eval : false,
|
||||||
@@ -423,7 +452,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
var lname = -1;
|
var lname = -1;
|
||||||
|
|
||||||
if (options.cache && options.cache.props) {
|
if (options.cache && options.cache.props) {
|
||||||
var mangled_names = this.mangled_names = Object.create(null);
|
var mangled_names = names_in_use(this, options);
|
||||||
options.cache.props.each(function(mangled_name) {
|
options.cache.props.each(function(mangled_name) {
|
||||||
mangled_names[mangled_name] = true;
|
mangled_names[mangled_name] = true;
|
||||||
});
|
});
|
||||||
@@ -461,7 +490,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
node.mangled_name = name;
|
node.mangled_name = name;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!options.ie8 && node instanceof AST_Catch) {
|
if (!options.ie8 && node instanceof AST_Catch && node.argname) {
|
||||||
var def = node.argname.definition();
|
var def = node.argname.definition();
|
||||||
var redef = defer_redef(def, node.argname);
|
var redef = defer_redef(def, node.argname);
|
||||||
descend();
|
descend();
|
||||||
@@ -495,12 +524,11 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
|
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
|
||||||
var cache = options.cache && options.cache.props;
|
var cache = options.cache && options.cache.props;
|
||||||
var avoid = Object.create(null);
|
var avoid = Object.create(RESERVED_WORDS);
|
||||||
options.reserved.forEach(to_avoid);
|
options.reserved.forEach(to_avoid);
|
||||||
this.globals.each(add_def);
|
this.globals.each(add_def);
|
||||||
this.walk(new TreeWalker(function(node) {
|
this.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_Scope) node.variables.each(add_def);
|
if (node instanceof AST_BlockScope) node.variables.each(add_def);
|
||||||
if (node instanceof AST_SymbolCatch) add_def(node.definition());
|
|
||||||
}));
|
}));
|
||||||
return avoid;
|
return avoid;
|
||||||
|
|
||||||
@@ -524,15 +552,14 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
|||||||
var cname = 0;
|
var cname = 0;
|
||||||
this.globals.each(rename);
|
this.globals.each(rename);
|
||||||
this.walk(new TreeWalker(function(node) {
|
this.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_Scope) node.variables.each(rename);
|
if (node instanceof AST_BlockScope) node.variables.each(rename);
|
||||||
if (node instanceof AST_SymbolCatch) rename(node.definition());
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function next_name() {
|
function next_name() {
|
||||||
var name;
|
var name;
|
||||||
do {
|
do {
|
||||||
name = base54(cname++);
|
name = base54(cname++);
|
||||||
} while (avoid[name] || RESERVED_WORDS[name]);
|
} while (avoid[name]);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -543,11 +570,8 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
|||||||
var redef = def.redefined();
|
var redef = def.redefined();
|
||||||
var name = redef ? redef.rename || redef.name : next_name();
|
var name = redef ? redef.rename || redef.name : next_name();
|
||||||
def.rename = name;
|
def.rename = name;
|
||||||
def.orig.forEach(function(sym) {
|
def.forEach(function(sym) {
|
||||||
sym.name = name;
|
if (sym.definition() === def) sym.name = name;
|
||||||
});
|
|
||||||
def.references.forEach(function(sym) {
|
|
||||||
sym.name = name;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -560,22 +584,24 @@ AST_Sequence.DEFMETHOD("tail_node", function() {
|
|||||||
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
|
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
|
||||||
options = _default_mangler_options(options);
|
options = _default_mangler_options(options);
|
||||||
base54.reset();
|
base54.reset();
|
||||||
|
var fn = AST_Symbol.prototype.add_source_map;
|
||||||
try {
|
try {
|
||||||
AST_Node.prototype.print = function(stream, force_parens) {
|
AST_Symbol.prototype.add_source_map = function() {
|
||||||
this._print(stream, force_parens);
|
if (!this.unmangleable(options)) base54.consider(this.name, -1);
|
||||||
if (this instanceof AST_Symbol && !this.unmangleable(options)) {
|
|
||||||
base54.consider(this.name, -1);
|
|
||||||
} else if (options.properties) {
|
|
||||||
if (this instanceof AST_Dot) {
|
|
||||||
base54.consider(this.property, -1);
|
|
||||||
} else if (this instanceof AST_Sub) {
|
|
||||||
skip_string(this.property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
if (options.properties) {
|
||||||
|
AST_Dot.prototype.add_source_map = function() {
|
||||||
|
base54.consider(this.property, -1);
|
||||||
|
};
|
||||||
|
AST_Sub.prototype.add_source_map = function() {
|
||||||
|
skip_string(this.property);
|
||||||
|
};
|
||||||
|
}
|
||||||
base54.consider(this.print_to_string(), 1);
|
base54.consider(this.print_to_string(), 1);
|
||||||
} finally {
|
} finally {
|
||||||
AST_Node.prototype.print = AST_Node.prototype._print;
|
AST_Symbol.prototype.add_source_map = fn;
|
||||||
|
delete AST_Dot.prototype.add_source_map;
|
||||||
|
delete AST_Sub.prototype.add_source_map;
|
||||||
}
|
}
|
||||||
base54.sort();
|
base54.sort();
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ TreeTransformer.prototype = new TreeWalker;
|
|||||||
if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
|
if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
|
||||||
});
|
});
|
||||||
DEF(AST_Catch, function(self, tw) {
|
DEF(AST_Catch, function(self, tw) {
|
||||||
self.argname = self.argname.transform(tw);
|
if (self.argname) self.argname = self.argname.transform(tw);
|
||||||
self.body = do_list(self.body, tw);
|
self.body = do_list(self.body, tw);
|
||||||
});
|
});
|
||||||
DEF(AST_Definitions, function(self, tw) {
|
DEF(AST_Definitions, function(self, tw) {
|
||||||
|
|||||||
48
lib/utils.js
48
lib/utils.js
@@ -112,51 +112,29 @@ function return_this() { return this; }
|
|||||||
function return_null() { return null; }
|
function return_null() { return null; }
|
||||||
|
|
||||||
var List = (function() {
|
var List = (function() {
|
||||||
function List(a, f, backwards) {
|
function List(a, f) {
|
||||||
var ret = [], top = [], i;
|
var ret = [];
|
||||||
function doit() {
|
for (var i = 0; i < a.length; i++) {
|
||||||
var val = f(a[i], i);
|
var val = f(a[i], i);
|
||||||
var is_last = val instanceof Last;
|
if (val === skip) continue;
|
||||||
if (is_last) val = val.v;
|
|
||||||
if (val instanceof AtTop) {
|
|
||||||
val = val.v;
|
|
||||||
if (val instanceof Splice) {
|
if (val instanceof Splice) {
|
||||||
top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
|
ret.push.apply(ret, val.v);
|
||||||
} else {
|
|
||||||
top.push(val);
|
|
||||||
}
|
|
||||||
} else if (val !== skip) {
|
|
||||||
if (val instanceof Splice) {
|
|
||||||
ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
|
|
||||||
} else {
|
} else {
|
||||||
ret.push(val);
|
ret.push(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return is_last;
|
return ret;
|
||||||
}
|
|
||||||
if (Array.isArray(a)) {
|
|
||||||
if (backwards) {
|
|
||||||
for (i = a.length; --i >= 0;) if (doit()) break;
|
|
||||||
ret.reverse();
|
|
||||||
top.reverse();
|
|
||||||
} else {
|
|
||||||
for (i = 0; i < a.length; ++i) if (doit()) break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (i in a) if (HOP(a, i)) if (doit()) break;
|
|
||||||
}
|
|
||||||
return top.concat(ret);
|
|
||||||
}
|
}
|
||||||
List.is_op = function(val) {
|
List.is_op = function(val) {
|
||||||
return val === skip || val instanceof AtTop || val instanceof Last || val instanceof Splice;
|
return val === skip || val instanceof Splice;
|
||||||
|
};
|
||||||
|
List.splice = function(val) {
|
||||||
|
return new Splice(val);
|
||||||
};
|
};
|
||||||
List.at_top = function(val) { return new AtTop(val); };
|
|
||||||
List.splice = function(val) { return new Splice(val); };
|
|
||||||
List.last = function(val) { return new Last(val); };
|
|
||||||
var skip = List.skip = {};
|
var skip = List.skip = {};
|
||||||
function AtTop(val) { this.v = val; }
|
function Splice(val) {
|
||||||
function Splice(val) { this.v = val; }
|
this.v = val;
|
||||||
function Last(val) { this.v = val; }
|
}
|
||||||
return List;
|
return List;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|||||||
@@ -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.9.3",
|
"version": "3.11.2",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
@@ -22,9 +22,6 @@
|
|||||||
"tools",
|
"tools",
|
||||||
"LICENSE"
|
"LICENSE"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
|
||||||
"commander": "~2.20.3"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"acorn": "~7.1.0",
|
"acorn": "~7.1.0",
|
||||||
"semver": "~6.3.0"
|
"semver": "~6.3.0"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ var zlib = require("zlib");
|
|||||||
var args = process.argv.slice(2);
|
var args = process.argv.slice(2);
|
||||||
if (!args.length) args.push("-mc");
|
if (!args.length) args.push("-mc");
|
||||||
args.unshift("bin/uglifyjs");
|
args.unshift("bin/uglifyjs");
|
||||||
args.push("--validate", "--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",
|
||||||
"https://code.angularjs.org/1.7.8/angular.js",
|
"https://code.angularjs.org/1.7.8/angular.js",
|
||||||
|
|||||||
@@ -269,6 +269,7 @@ function test_case(test) {
|
|||||||
quote_style: 3,
|
quote_style: 3,
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
|
input.validate_ast();
|
||||||
U.parse(input_code);
|
U.parse(input_code);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
log([
|
log([
|
||||||
@@ -311,12 +312,10 @@ function test_case(test) {
|
|||||||
if (test.mangle) {
|
if (test.mangle) {
|
||||||
output.compute_char_frequency(test.mangle);
|
output.compute_char_frequency(test.mangle);
|
||||||
output.mangle_names(test.mangle);
|
output.mangle_names(test.mangle);
|
||||||
if (test.mangle.properties) {
|
if (test.mangle.properties) U.mangle_properties(output, test.mangle.properties);
|
||||||
output = U.mangle_properties(output, test.mangle.properties);
|
|
||||||
}
|
}
|
||||||
}
|
var output_code = make_code(output, output_options);
|
||||||
output = make_code(output, output_options);
|
if (expect != output_code) {
|
||||||
if (expect != output) {
|
|
||||||
log([
|
log([
|
||||||
"!!! failed",
|
"!!! failed",
|
||||||
"---INPUT---",
|
"---INPUT---",
|
||||||
@@ -329,14 +328,15 @@ function test_case(test) {
|
|||||||
"",
|
"",
|
||||||
].join("\n"), {
|
].join("\n"), {
|
||||||
input: input_formatted,
|
input: input_formatted,
|
||||||
output: output,
|
output: output_code,
|
||||||
expected: expect
|
expected: expect
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// expect == output
|
// expect == output
|
||||||
try {
|
try {
|
||||||
U.parse(output);
|
output.validate_ast();
|
||||||
|
U.parse(output_code);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
log([
|
log([
|
||||||
"!!! Test matched expected result but cannot parse output",
|
"!!! Test matched expected result but cannot parse output",
|
||||||
@@ -350,7 +350,7 @@ function test_case(test) {
|
|||||||
"",
|
"",
|
||||||
].join("\n"), {
|
].join("\n"), {
|
||||||
input: input_formatted,
|
input: input_formatted,
|
||||||
output: output,
|
output: output_code,
|
||||||
error: ex,
|
error: ex,
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
@@ -409,7 +409,7 @@ function test_case(test) {
|
|||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
actual = run_code(output, toplevel);
|
actual = run_code(output_code, toplevel);
|
||||||
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
|
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
|
||||||
log([
|
log([
|
||||||
"!!! failed",
|
"!!! failed",
|
||||||
|
|||||||
@@ -243,20 +243,18 @@ issue_3273: {
|
|||||||
arguments: true,
|
arguments: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(a, a);
|
console.log(a, a);
|
||||||
a++;
|
a++;
|
||||||
console.log(a, a);
|
console.log(a, a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"0 0",
|
"0 0",
|
||||||
@@ -264,26 +262,43 @@ issue_3273: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3273_no_call_arg: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
arguments[0] = "FAIL";
|
||||||
|
console.log(a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
arguments[0] = "FAIL";
|
||||||
|
console.log(a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
issue_3273_reduce_vars: {
|
issue_3273_reduce_vars: {
|
||||||
options = {
|
options = {
|
||||||
arguments: true,
|
arguments: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(a, a);
|
console.log(a, a);
|
||||||
a++;
|
a++;
|
||||||
console.log(a, a);
|
console.log(a, a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"0 0",
|
"0 0",
|
||||||
@@ -296,22 +311,20 @@ issue_3273_local_strict: {
|
|||||||
arguments: true,
|
arguments: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
"use strict";
|
"use strict";
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
"use strict";
|
"use strict";
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"0 0",
|
"0 0",
|
||||||
@@ -325,22 +338,20 @@ issue_3273_local_strict_reduce_vars: {
|
|||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
"use strict";
|
"use strict";
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(a) {
|
(function(a) {
|
||||||
"use strict";
|
"use strict";
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"0 0",
|
"0 0",
|
||||||
@@ -354,21 +365,19 @@ issue_3273_global_strict: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
"use strict";
|
"use strict";
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
"use strict";
|
"use strict";
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"0 0",
|
"0 0",
|
||||||
@@ -383,21 +392,19 @@ issue_3273_global_strict_reduce_vars: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
"use strict";
|
"use strict";
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
"use strict";
|
"use strict";
|
||||||
function f(a) {
|
(function(a) {
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
arguments[0]++;
|
arguments[0]++;
|
||||||
console.log(arguments[0], a);
|
console.log(arguments[0], a);
|
||||||
}
|
})(0);
|
||||||
f(0);
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"0 0",
|
"0 0",
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ asm_mixed: {
|
|||||||
return +sum;
|
return +sum;
|
||||||
}
|
}
|
||||||
function geometricMean(start, end) {
|
function geometricMean(start, end) {
|
||||||
return start |= 0, end |= 0, +exp(logSum(start, end) / (end - start | 0));
|
return start |= 0, end |= 0, +exp(+logSum(start, end) / (end - start | 0));
|
||||||
}
|
}
|
||||||
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
|
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
|
||||||
return { geometricMean: geometricMean };
|
return { geometricMean: geometricMean };
|
||||||
|
|||||||
@@ -407,3 +407,57 @@ issue_3429_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3949_1: {
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 42;
|
||||||
|
function f() {
|
||||||
|
var b = a;
|
||||||
|
b = b >> 2;
|
||||||
|
return 100 + b;
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 42;
|
||||||
|
function f() {
|
||||||
|
var b = a;
|
||||||
|
b >>= 2;
|
||||||
|
return 100 + b;
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect_stdout: "110"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3949_2: {
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 42;
|
||||||
|
function f() {
|
||||||
|
var b = a;
|
||||||
|
b = 5 & b;
|
||||||
|
return 100 + b;
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 42;
|
||||||
|
function f() {
|
||||||
|
var b = a;
|
||||||
|
b &= 5;
|
||||||
|
return 100 + b;
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect_stdout: "100"
|
||||||
|
}
|
||||||
@@ -62,25 +62,26 @@ collapse_vars_side_effects_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
function f1() {
|
function f1() {
|
||||||
var s = "abcdef", i = 2;
|
var s = "abcdef", i = 2;
|
||||||
console.log.bind(console)(s.charAt(i++), s.charAt(i++), s.charAt(i++), 7);
|
console.log.bind(console)(s.charAt(i++), s.charAt(+i), s.charAt(4), 7);
|
||||||
}
|
}
|
||||||
function f2() {
|
function f2() {
|
||||||
var s = "abcdef", i = 2;
|
var s = "abcdef", i = 2;
|
||||||
console.log.bind(console)(s.charAt(i++), 5, s.charAt(i++), s.charAt(i++), 7);
|
console.log.bind(console)(s.charAt(i++), 5, s.charAt(i++), s.charAt(+i), 7);
|
||||||
}
|
}
|
||||||
function f3() {
|
function f3() {
|
||||||
var s = "abcdef",
|
var s = "abcdef",
|
||||||
i = 2,
|
i = 2,
|
||||||
log = console.log.bind(console),
|
log = console.log.bind(console),
|
||||||
x = s.charAt(i++),
|
x = s.charAt(i++),
|
||||||
y = s.charAt(i++);
|
y = s.charAt(+i);
|
||||||
log(x, s.charAt(i++), y, 7);
|
log(x, s.charAt(4), y, 7);
|
||||||
}
|
}
|
||||||
function f4() {
|
function f4() {
|
||||||
var i = 10,
|
var i = 10;
|
||||||
x = i += 2,
|
i += 2,
|
||||||
y = i += 3;
|
i += 3,
|
||||||
console.log.bind(console)(x, i += 4, y, 19);
|
i += 4;
|
||||||
|
console.log.bind(console)(12, 19, 15, 19);
|
||||||
}
|
}
|
||||||
f1(), f2(), f3(), f4();
|
f1(), f2(), f3(), f4();
|
||||||
}
|
}
|
||||||
@@ -916,7 +917,7 @@ collapse_vars_lvalues_drop_assign: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse_vars_misc1: {
|
collapse_vars_misc: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -970,8 +971,8 @@ collapse_vars_misc1: {
|
|||||||
function f7() { var b = window.a * window.z; return b + b }
|
function f7() { var b = window.a * window.z; return b + b }
|
||||||
function f8() { var b = window.a * window.z; return b + (5 + b) }
|
function f8() { var b = window.a * window.z; return b + (5 + b) }
|
||||||
function f9() { var b = window.a * window.z; return bar() || b }
|
function f9() { var b = window.a * window.z; return bar() || b }
|
||||||
function f10(x) { var a = 5; return a += 3; }
|
function f10(x) { return 8; }
|
||||||
function f11(x) { var a = 5; return a += 2; }
|
function f11(x) { return 7; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1598,7 +1599,7 @@ collapse_vars_constants: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse_vars_arguments: {
|
collapse_vars_arguments_1: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -1635,6 +1636,78 @@ collapse_vars_arguments: {
|
|||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
collapse_vars_arguments_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function log(a, b) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
function f(c) {
|
||||||
|
var d = arguments[0];
|
||||||
|
c = "FAIL";
|
||||||
|
log(c, d);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
f("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function log(a, b) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
function f(c) {
|
||||||
|
var d = arguments[0];
|
||||||
|
log(c = "FAIL", d);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
f("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
collapse_vars_arguments_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function log(a, b) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
function f(c) {
|
||||||
|
var args = arguments;
|
||||||
|
console.log(c);
|
||||||
|
var d = args[0];
|
||||||
|
c = "FAIL";
|
||||||
|
log(c, d);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
f("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function log(a, b) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
function f(c) {
|
||||||
|
var args = arguments;
|
||||||
|
console.log(c);
|
||||||
|
var d = args[0];
|
||||||
|
log(c = "FAIL", d);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
f("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined",
|
||||||
|
"undefined",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
collapse_vars_short_circuit: {
|
collapse_vars_short_circuit: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
@@ -3000,8 +3073,6 @@ issue_2298: {
|
|||||||
expect: {
|
expect: {
|
||||||
!function() {
|
!function() {
|
||||||
(function() {
|
(function() {
|
||||||
var a = undefined;
|
|
||||||
var undefined = a++;
|
|
||||||
try {
|
try {
|
||||||
!function(b) {
|
!function(b) {
|
||||||
(void 0)[1] = "foo";
|
(void 0)[1] = "foo";
|
||||||
@@ -3835,20 +3906,19 @@ issue_2436_3: {
|
|||||||
}(o));
|
}(o));
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var o = {
|
|
||||||
a: 1,
|
|
||||||
b: 2,
|
|
||||||
};
|
|
||||||
console.log(function(c) {
|
console.log(function(c) {
|
||||||
o = {
|
({
|
||||||
a: 3,
|
a: 3,
|
||||||
b: 4,
|
b: 4,
|
||||||
};
|
});
|
||||||
return {
|
return {
|
||||||
x: c.a,
|
x: c.a,
|
||||||
y: c.b,
|
y: c.b,
|
||||||
};
|
};
|
||||||
}(o));
|
}({
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
@@ -4070,16 +4140,15 @@ issue_2436_10: {
|
|||||||
}(o).join(" "));
|
}(o).join(" "));
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var o = {
|
|
||||||
a: 1,
|
|
||||||
b: 2,
|
|
||||||
};
|
|
||||||
function f(n) {
|
function f(n) {
|
||||||
o = { b: 3 };
|
({ b: 3 });
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
console.log([
|
console.log([
|
||||||
(c = o).a,
|
(c = {
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
}).a,
|
||||||
f(c.b),
|
f(c.b),
|
||||||
c.b,
|
c.b,
|
||||||
].join(" "));
|
].join(" "));
|
||||||
@@ -6890,6 +6959,30 @@ sequence_in_iife_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = "foo", b = 42;
|
var a = "foo", b = 42;
|
||||||
|
b = a;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "foo foo"
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence_in_iife_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "foo", b = 42;
|
||||||
|
(function() {
|
||||||
|
var c = (b = a, b);
|
||||||
|
})();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "foo";
|
||||||
console.log(a, a);
|
console.log(a, a);
|
||||||
}
|
}
|
||||||
expect_stdout: "foo foo"
|
expect_stdout: "foo foo"
|
||||||
@@ -7955,7 +8048,7 @@ mangleable_var: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3884: {
|
issue_3884_1: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -7973,9 +8066,33 @@ issue_3884: {
|
|||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = 100;
|
var a = 100, b = 1;
|
||||||
++a;
|
b <<= ++a;
|
||||||
console.log(a, 32);
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "101 32"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3884_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
passes: 3,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 100, b = 1;
|
||||||
|
{
|
||||||
|
a++ + a || a;
|
||||||
|
b <<= a;
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(101, 32);
|
||||||
}
|
}
|
||||||
expect_stdout: "101 32"
|
expect_stdout: "101 32"
|
||||||
}
|
}
|
||||||
@@ -8015,3 +8132,430 @@ issue_3891: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "function"
|
expect_stdout: "function"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3894: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function log(msg) {
|
||||||
|
console.log(msg ? "FAIL" : "PASS");
|
||||||
|
}
|
||||||
|
var a, c;
|
||||||
|
(function(b) {
|
||||||
|
a = c = 0,
|
||||||
|
log(b);
|
||||||
|
})(-0);
|
||||||
|
log(a);
|
||||||
|
log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function log(msg) {
|
||||||
|
console.log(msg ? "FAIL" : "PASS");
|
||||||
|
}
|
||||||
|
var a, c;
|
||||||
|
void log(-(a = c = 0));
|
||||||
|
log(a);
|
||||||
|
log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3897: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
(function() {
|
||||||
|
function f(b) {
|
||||||
|
b = a = 1 + a;
|
||||||
|
a = 1 + a;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
(function() {
|
||||||
|
function f(b) {
|
||||||
|
b = a = 1 + a;
|
||||||
|
a = 1 + a;
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3908: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if (console) {
|
||||||
|
var o = {
|
||||||
|
p: !1
|
||||||
|
}, a = o;
|
||||||
|
}
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console && 0;
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3927: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
console.log(function(b) {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
if (a + (b = "PASS", true)) return;
|
||||||
|
b.p;
|
||||||
|
} finally {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
console.log(function(b) {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
if (a + (b = "PASS", true)) return;
|
||||||
|
b.p;
|
||||||
|
} finally {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
operator_in: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function log(msg) {
|
||||||
|
console.log(msg);
|
||||||
|
}
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
a = "PASS";
|
||||||
|
0 in null;
|
||||||
|
log("FAIL", a);
|
||||||
|
} catch (e) {}
|
||||||
|
log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function log(msg) {
|
||||||
|
console.log(msg);
|
||||||
|
}
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
a = "PASS";
|
||||||
|
0 in null;
|
||||||
|
log("FAIL", a);
|
||||||
|
} catch (e) {}
|
||||||
|
log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3971: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0 == typeof f, b = 0;
|
||||||
|
{
|
||||||
|
var a = void (a++ + (b |= a));
|
||||||
|
}
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0 == typeof f, b = 0;
|
||||||
|
var a = void (b |= ++a);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3976: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
console.log("FAIL");
|
||||||
|
}
|
||||||
|
(function(a) {
|
||||||
|
function g() {
|
||||||
|
if ((a = 0) || f(0)) {
|
||||||
|
f();
|
||||||
|
} else {
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
if (h(a = 0));
|
||||||
|
}
|
||||||
|
function h() {
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
console.log("FAIL");
|
||||||
|
}
|
||||||
|
void 0;
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4012: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (b) {
|
||||||
|
a = "PASS";
|
||||||
|
if (--b)
|
||||||
|
return;
|
||||||
|
if (3);
|
||||||
|
} finally {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (b) {
|
||||||
|
a = "PASS";
|
||||||
|
if (--b)
|
||||||
|
return;
|
||||||
|
if (3);
|
||||||
|
} finally {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
global_assign: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
this.A = "FAIL";
|
||||||
|
A = "PASS";
|
||||||
|
B = "FAIL";
|
||||||
|
console.log(A);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
this.A = "FAIL";
|
||||||
|
A = "PASS";
|
||||||
|
B = "FAIL";
|
||||||
|
console.log(A);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
global_read: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
a = this.A;
|
||||||
|
A = 1;
|
||||||
|
a ? console.log("FAIL") : console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
a = this.A;
|
||||||
|
A = 1;
|
||||||
|
a ? console.log("FAIL") : console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4038: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
a = this;
|
||||||
|
a = a.A;
|
||||||
|
A = 1;
|
||||||
|
a ? console.log("FAIL") : console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
a = (a = this).A;
|
||||||
|
A = 1;
|
||||||
|
a ? console.log("FAIL") : console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4040: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = console.log("PASS") && a.p;
|
||||||
|
delete NaN;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = console.log("PASS") && a.p;
|
||||||
|
delete NaN;
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4047_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 1;
|
||||||
|
console.log(+function(a) {
|
||||||
|
b = a;
|
||||||
|
(a >>= 0) && console.log("PASS");
|
||||||
|
}(--b + (0 !== typeof A)));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 1;
|
||||||
|
var a;
|
||||||
|
console.log((a = --b + ((a = 0) !== typeof A), +void ((a >>= 0) && console.log("PASS"))));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"NaN",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4047_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 1;
|
||||||
|
console.log(+function(a) {
|
||||||
|
b = a;
|
||||||
|
(a >>= 0) && console.log("PASS");
|
||||||
|
}(--b + (0 !== typeof A)));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
console.log((a = +(0 !== typeof A), +void ((a >>= 0) && console.log("PASS"))));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"NaN",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4051: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
var a = (b = b.p, "FAIL"), b = b;
|
||||||
|
} catch (e) {}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
var a = (b = b.p, "FAIL"), b = b;
|
||||||
|
} catch (e) {}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4070: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function f() {
|
||||||
|
function g() {}
|
||||||
|
g.p++;
|
||||||
|
return f.p = g.p;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function f() {
|
||||||
|
function g() {}
|
||||||
|
return f.p = ++g.p;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|||||||
@@ -123,6 +123,29 @@ self_comparison_3: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self_comparison_4: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
comparisons: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
console.log(o == o, o != o);
|
||||||
|
console.log(o === o, o !== o);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!0, !1);
|
||||||
|
console.log(!0, !1);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"true false",
|
||||||
|
"true false",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
issue_2857_1: {
|
issue_2857_1: {
|
||||||
options = {
|
options = {
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
|
|||||||
@@ -238,6 +238,41 @@ concat_8: {
|
|||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
concat_9: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
strings: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "foo";
|
||||||
|
console.log(
|
||||||
|
12 + (34 + a),
|
||||||
|
null + (34 + a),
|
||||||
|
12 + (null + a),
|
||||||
|
false + (34 + a),
|
||||||
|
12 + (false + a),
|
||||||
|
"bar" + (34 + a),
|
||||||
|
12 + ("bar" + a)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "foo";
|
||||||
|
console.log(
|
||||||
|
"1234" + a,
|
||||||
|
"null34" + a,
|
||||||
|
"12null" + a,
|
||||||
|
!1 + (34 + a),
|
||||||
|
12 + (!1 + a),
|
||||||
|
"bar34" + a,
|
||||||
|
"12bar" + a
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
issue_3689: {
|
issue_3689: {
|
||||||
options = {
|
options = {
|
||||||
strings: true,
|
strings: true,
|
||||||
|
|||||||
@@ -783,6 +783,28 @@ cond_12: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cond_13: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
x ? y(a) : z(a);
|
||||||
|
x ? y.f(a) : z.f(a);
|
||||||
|
x ? y.f(a) : z.g(a);
|
||||||
|
x ? y.f()(a) : z.g()(a);
|
||||||
|
x ? y.f.u(a) : z.g.u(a);
|
||||||
|
x ? y.f().u(a) : z.g().u(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(x ? y : z)(a);
|
||||||
|
(x ? y : z).f(a);
|
||||||
|
x ? y.f(a) : z.g(a);
|
||||||
|
(x ? y.f() : z.g())(a);
|
||||||
|
(x ? y.f : z.g).u(a);
|
||||||
|
(x ? y.f() : z.g()).u(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ternary_boolean_consequent: {
|
ternary_boolean_consequent: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
@@ -1137,7 +1159,7 @@ issue_1645_2: {
|
|||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
condition_symbol_matches_consequent: {
|
condition_matches_consequent: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
}
|
}
|
||||||
@@ -1166,6 +1188,35 @@ condition_symbol_matches_consequent: {
|
|||||||
expect_stdout: "3 7 true 4"
|
expect_stdout: "3 7 true 4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
condition_matches_alternative: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo(x, y) {
|
||||||
|
return x.p ? y[0] : x.p;
|
||||||
|
}
|
||||||
|
function bar() {
|
||||||
|
return g ? h : g;
|
||||||
|
}
|
||||||
|
var g = 4;
|
||||||
|
var h = 5;
|
||||||
|
console.log(foo({ p: 3 }, [ null ]), foo({ p: 0 }, [ 7 ]), foo({ p: true } , [ false ]), bar());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo(x, y) {
|
||||||
|
return x.p && y[0];
|
||||||
|
}
|
||||||
|
function bar() {
|
||||||
|
return g && h;
|
||||||
|
}
|
||||||
|
var g = 4;
|
||||||
|
var h = 5;
|
||||||
|
console.log(foo({ p: 3 }, [ null ]), foo({ p: 0 }, [ 7 ]), foo({ p: true } , [ false ]), bar());
|
||||||
|
}
|
||||||
|
expect_stdout: "null 0 false 5"
|
||||||
|
}
|
||||||
|
|
||||||
delete_conditional_1: {
|
delete_conditional_1: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ collapse_vars_lvalues_drop_assign: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse_vars_misc1: {
|
collapse_vars_misc: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
@@ -1168,3 +1168,197 @@ redundant_assignments: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS PASS"
|
expect_stdout: "PASS PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self_assignments_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
a = a;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "PASS";
|
||||||
|
a;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
self_assignments_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "q", o = {
|
||||||
|
p: "PASS",
|
||||||
|
};
|
||||||
|
o.p = o.p;
|
||||||
|
o[a] = o[a];
|
||||||
|
console.log(o.p, o[a]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "q", o = {
|
||||||
|
p: "PASS",
|
||||||
|
};
|
||||||
|
console.log(o.p, o[a]);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
self_assignments_3: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "q", o = {
|
||||||
|
p: "FAIL",
|
||||||
|
get q() {
|
||||||
|
return "PASS";
|
||||||
|
},
|
||||||
|
set q(v) {
|
||||||
|
this.p = v;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
o.p = o.p;
|
||||||
|
o[a] = o[a];
|
||||||
|
console.log(o.p, o[a]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "q", o = {
|
||||||
|
p: "FAIL",
|
||||||
|
get q() {
|
||||||
|
return "PASS";
|
||||||
|
},
|
||||||
|
set q(v) {
|
||||||
|
this.p = v;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
o.p = o.p;
|
||||||
|
o[a] = o[a];
|
||||||
|
console.log(o.p, o[a]);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
self_assignments_4: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var i = 0, l = [ "PASS" ];
|
||||||
|
l[0] = l[0];
|
||||||
|
l[i] = l[i];
|
||||||
|
console.log(l[0], i);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var i = 0, l = [ "PASS" ];
|
||||||
|
console.log(l[0], i);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS 0"
|
||||||
|
}
|
||||||
|
|
||||||
|
self_assignments_5: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
passes: 3,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var i = 0, l = [ "FAIL", "PASS" ];
|
||||||
|
l[0] = l[0];
|
||||||
|
l[i] = l[i];
|
||||||
|
l[i++] = l[i++];
|
||||||
|
console.log(l[0], i);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var i = 0, l = [ "FAIL", "PASS" ];
|
||||||
|
l[0];
|
||||||
|
l[0];
|
||||||
|
l[0] = l[1];
|
||||||
|
console.log(l[0], 2);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS 2"
|
||||||
|
}
|
||||||
|
|
||||||
|
self_assignments_6: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {
|
||||||
|
p: "PASS",
|
||||||
|
};
|
||||||
|
console.log(o.p = o.p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
p: "PASS",
|
||||||
|
};
|
||||||
|
console.log(o.p);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3967: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
a = 0 in (a = "PASS");
|
||||||
|
} catch (e) {}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
a = 0 in (a = "PASS");
|
||||||
|
} catch (e) {}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4051: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
delete (A = A);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
delete (A = A);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1730,7 +1730,7 @@ chained_3: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(function(a, b) {
|
console.log(function(a, b) {
|
||||||
var c = b;
|
var c = b;
|
||||||
b++;
|
+b;
|
||||||
return c;
|
return c;
|
||||||
}(0, 2));
|
}(0, 2));
|
||||||
}
|
}
|
||||||
@@ -1997,7 +1997,7 @@ issue_3146_4: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3192: {
|
issue_3192_1: {
|
||||||
options = {
|
options = {
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2025,6 +2025,26 @@ issue_3192: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3192_2: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: "strict",
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
(function(a) {
|
||||||
|
console.log(a = "foo", arguments[0]);
|
||||||
|
})("bar");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
(function() {
|
||||||
|
console.log("foo", arguments[0]);
|
||||||
|
})("bar");
|
||||||
|
}
|
||||||
|
expect_stdout: "foo bar"
|
||||||
|
}
|
||||||
|
|
||||||
issue_3233: {
|
issue_3233: {
|
||||||
options = {
|
options = {
|
||||||
pure_getters: "strict",
|
pure_getters: "strict",
|
||||||
@@ -2161,8 +2181,7 @@ issue_3515_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
var c = 0;
|
var c = 0;
|
||||||
(function() {
|
(function() {
|
||||||
this[c++] = 0;
|
for (var key20 in !(this[c++] = 0));
|
||||||
for (var key20 in !0);
|
|
||||||
})();
|
})();
|
||||||
console.log(c);
|
console.log(c);
|
||||||
}
|
}
|
||||||
@@ -2285,7 +2304,7 @@ issue_3598: {
|
|||||||
try {
|
try {
|
||||||
(function() {
|
(function() {
|
||||||
a = "PASS";
|
a = "PASS";
|
||||||
var c = (void (c.p = 0))[!1];
|
(void ((void 0).p = 0))[!1];
|
||||||
})();
|
})();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
console.log(a);
|
console.log(a);
|
||||||
@@ -2527,8 +2546,542 @@ issue_3802_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
0;
|
0;
|
||||||
function a() {};
|
var a = function() {};
|
||||||
console.log(typeof a);
|
console.log(typeof a);
|
||||||
}
|
}
|
||||||
expect_stdout: "function"
|
expect_stdout: "function"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3899: {
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
evaluate: true,
|
||||||
|
functions: true,
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
a = a + 1;
|
||||||
|
var a = function f(b) {
|
||||||
|
return function() {
|
||||||
|
return b;
|
||||||
|
};
|
||||||
|
}(2);
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function a() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
}
|
||||||
|
|
||||||
|
cross_scope_assign_chain: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b = 0;
|
||||||
|
(function() {
|
||||||
|
a = b;
|
||||||
|
a++;
|
||||||
|
while (b++);
|
||||||
|
})();
|
||||||
|
console.log(a ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b = 0;
|
||||||
|
(function() {
|
||||||
|
a = b;
|
||||||
|
a++;
|
||||||
|
while (b++);
|
||||||
|
})();
|
||||||
|
console.log(a ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
assign_if_assign_read: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
var b;
|
||||||
|
do {
|
||||||
|
b = "FAIL";
|
||||||
|
if (Array.isArray(a)) {
|
||||||
|
b = a[0];
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
} while (!console);
|
||||||
|
})([ "PASS" ]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
var b;
|
||||||
|
do {
|
||||||
|
"FAIL";
|
||||||
|
if (Array.isArray(a)) {
|
||||||
|
b = a[0];
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
} while (!console);
|
||||||
|
})([ "PASS" ]);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3951: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = console.log("PASS");
|
||||||
|
console.log(a);
|
||||||
|
a = "0";
|
||||||
|
console.log(a.p = 0);
|
||||||
|
a && a;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = console.log("PASS");
|
||||||
|
console.log(a);
|
||||||
|
a = "0";
|
||||||
|
console.log(a.p = 0);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"undefined",
|
||||||
|
"0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3956: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
function f(b) {
|
||||||
|
console.log(b);
|
||||||
|
a = 1;
|
||||||
|
}
|
||||||
|
var c = f(c += 0);
|
||||||
|
(function(d) {
|
||||||
|
console.log(d);
|
||||||
|
})(console.log(a) ^ 1, c);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c, d;
|
||||||
|
c += 0,
|
||||||
|
console.log(NaN),
|
||||||
|
d = 1 ^ console.log(1),
|
||||||
|
console.log(d);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"NaN",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3962_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
function f(b, c) {
|
||||||
|
do {
|
||||||
|
var d = console + e, e = 0..toString() === b;
|
||||||
|
} while (0);
|
||||||
|
if (c) console.log("PASS");
|
||||||
|
}
|
||||||
|
var a = f(a--, 1);
|
||||||
|
a;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
a = (function(c) {
|
||||||
|
do {
|
||||||
|
console;
|
||||||
|
0..toString();
|
||||||
|
} while (0);
|
||||||
|
if (c) console.log("PASS");
|
||||||
|
}(1), 0);
|
||||||
|
void 0;
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3962_2: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
function f(b, c) {
|
||||||
|
do {
|
||||||
|
var d = console + e, e = 0..toString() === b;
|
||||||
|
} while (0);
|
||||||
|
if (c) console.log("PASS");
|
||||||
|
}
|
||||||
|
var a = f(a--, 1);
|
||||||
|
a;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
a = (function(c) {
|
||||||
|
do {
|
||||||
|
console;
|
||||||
|
0..toString();
|
||||||
|
} while (0);
|
||||||
|
if (c) console.log("PASS");
|
||||||
|
}(1), 0);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3986: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b = 0;
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
throw 42;
|
||||||
|
} catch (e) {
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
b = b && 0;
|
||||||
|
})(b *= a);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0, b = 0;
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
throw 42;
|
||||||
|
} catch (e) {
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
b = b && 0;
|
||||||
|
})(b *= a);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4017: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
console.log(function f() {
|
||||||
|
var b = c &= 0;
|
||||||
|
var c = a++ + (A = a);
|
||||||
|
var d = c && c[f];
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
console.log(function() {
|
||||||
|
c &= 0;
|
||||||
|
var c = (a++, A = a, 0);
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4025: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b = 0, c = 0, d = a++;
|
||||||
|
try {
|
||||||
|
var e = console.log(c), f = b;
|
||||||
|
} finally {
|
||||||
|
var d = b = 1, d = c + 1;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
console.log(a, b, d);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
try {
|
||||||
|
console.log(c);
|
||||||
|
} finally {
|
||||||
|
var d = c + 1;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
console.log(1, 1, d);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"1 1 1",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
forin_var_1: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var k;
|
||||||
|
for (k in [ 1, 2 ])
|
||||||
|
console.log(k);
|
||||||
|
for (k in { PASS: 3 })
|
||||||
|
console.log(k);
|
||||||
|
console.log(k);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var k in [ 1, 2 ])
|
||||||
|
console.log(k);
|
||||||
|
for (k in { PASS: 3 })
|
||||||
|
console.log(k);
|
||||||
|
console.log(k);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
forin_var_2: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
switch (0) {
|
||||||
|
case function() {
|
||||||
|
for (a in 0);
|
||||||
|
}:
|
||||||
|
var b = 0;
|
||||||
|
}
|
||||||
|
for (var c = 0; a;);
|
||||||
|
var a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
switch (0) {
|
||||||
|
case function() {
|
||||||
|
for (a in 0);
|
||||||
|
}:
|
||||||
|
}
|
||||||
|
for (; a;);
|
||||||
|
var a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4133: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
merge_vars: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
var b = [ a-- ], c = b && b[c];
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 1;
|
||||||
|
console.log(0);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4144: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a, b) {
|
||||||
|
var b = console, c = ++b;
|
||||||
|
})(console.log("PASS"), 0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(b) {
|
||||||
|
b = console,
|
||||||
|
++b;
|
||||||
|
})(console.log("PASS"));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4146: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
function g() {}
|
||||||
|
var a = g;
|
||||||
|
var c = b;
|
||||||
|
c.p;
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
f("FAIL", 42);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a, b) {
|
||||||
|
a = function () {};
|
||||||
|
var c = b;
|
||||||
|
c.p;
|
||||||
|
console.log(typeof a);
|
||||||
|
})(0, 42);
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
}
|
||||||
|
|
||||||
|
var_catch_redefined: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
throw "PASS";
|
||||||
|
} catch (a) {
|
||||||
|
function f() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
throw "PASS";
|
||||||
|
} catch (a) {
|
||||||
|
function f() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
single_use_catch_redefined: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(g());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(g());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4184: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a = function() {}, b = [ a, 1 && b, a = {} ];
|
||||||
|
try {
|
||||||
|
throw 42;
|
||||||
|
} catch (a) {
|
||||||
|
{
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
var b = [ function() {}, 1 && b, {} ];
|
||||||
|
try {
|
||||||
|
throw 42;
|
||||||
|
} catch (a) {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|||||||
@@ -558,34 +558,51 @@ unsafe_array: {
|
|||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
var a = "PASS";
|
||||||
[1, , 3][1],
|
Array.prototype[1] = a;
|
||||||
[1, 2, 3, a] + 1,
|
console.log([, ].length);
|
||||||
[1, 2, 3, 4] + 1,
|
console.log("" + [, , ]);
|
||||||
[1, 2, 3, a][0] + 1,
|
console.log([1, , 3][1]);
|
||||||
[1, 2, 3, 4][0] + 1,
|
console.log([1, 2, 3, a] + 1);
|
||||||
[1, 2, 3, 4][6 - 5] + 1,
|
console.log([1, 2, 3, 4] + 1);
|
||||||
[1, , 3, 4][6 - 5] + 1,
|
console.log([1, 2, 3, a][0] + 1);
|
||||||
[[1, 2], [3, 4]][0] + 1,
|
console.log([1, 2, 3, 4][0] + 1);
|
||||||
[[1, 2], [3, 4]][6 - 5][1] + 1,
|
console.log([1, 2, 3, 4][6 - 5] + 1);
|
||||||
[[1, 2], , [3, 4]][6 - 5][1] + 1
|
console.log([1, , 3, 4][6 - 5] + 1);
|
||||||
);
|
console.log([[1, 2], [3, 4]][0] + 1);
|
||||||
|
console.log([[1, 2], [3, 4]][6 - 5][1] + 1);
|
||||||
|
console.log([[1, 2], , [3, 4]][6 - 5][1] + 1);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(
|
var a = "PASS";
|
||||||
void 0,
|
Array.prototype[1] = a;
|
||||||
[1, 2, 3, a] + 1,
|
console.log([, ].length);
|
||||||
"1,2,3,41",
|
console.log("" + [, , ]);
|
||||||
[1, 2, 3, a][0] + 1,
|
console.log([1, , 3][1]);
|
||||||
2,
|
console.log([1, 2, 3, a] + 1);
|
||||||
3,
|
console.log("1,2,3,41");
|
||||||
NaN,
|
console.log([1, 2, 3, a][0] + 1);
|
||||||
"1,21",
|
console.log(2);
|
||||||
5,
|
console.log(3);
|
||||||
(void 0)[1] + 1
|
console.log([1, , 3, 4][1] + 1);
|
||||||
);
|
console.log("1,21");
|
||||||
|
console.log(5);
|
||||||
|
console.log([[1, 2], , [3, 4]][1][1] + 1);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: [
|
||||||
|
"1",
|
||||||
|
",PASS",
|
||||||
|
"PASS",
|
||||||
|
"1,2,3,PASS1",
|
||||||
|
"1,2,3,41",
|
||||||
|
"2",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"PASS1",
|
||||||
|
"1,21",
|
||||||
|
"5",
|
||||||
|
"A1",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_string: {
|
unsafe_string: {
|
||||||
@@ -1579,9 +1596,9 @@ issue_2968_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
var c = "FAIL";
|
var c = "FAIL";
|
||||||
(function() {
|
(function() {
|
||||||
b = -(a = 42),
|
a = 42,
|
||||||
void ((a <<= 0) && (a[(c = "PASS", 0 >>> (b += 1))] = 0));
|
void ((a <<= 0) && (a[(c = "PASS", 0)] = 0));
|
||||||
var a, b;
|
var a;
|
||||||
})();
|
})();
|
||||||
console.log(c);
|
console.log(c);
|
||||||
}
|
}
|
||||||
@@ -2341,10 +2358,7 @@ issue_3878_1: {
|
|||||||
console.log(b ? "PASS" : "FAIL");
|
console.log(b ? "PASS" : "FAIL");
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var b = function(a) {
|
console.log(true ? "PASS" : "FAIL");
|
||||||
return (a = 0) == (a && this > (a += 0));
|
|
||||||
}();
|
|
||||||
console.log(b ? "PASS" : "FAIL");
|
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
@@ -2412,9 +2426,591 @@ issue_3887: {
|
|||||||
expect: {
|
expect: {
|
||||||
(function(b) {
|
(function(b) {
|
||||||
try {
|
try {
|
||||||
b-- && console.log("PASS");
|
1, console.log("PASS");
|
||||||
} catch (a_2) {}
|
} catch (a_2) {}
|
||||||
})(1);
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3903: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
function f(b, c) {
|
||||||
|
return console, c;
|
||||||
|
}
|
||||||
|
var d = f(f(), a = a);
|
||||||
|
console.log(d);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(b, c) {
|
||||||
|
return console, c;
|
||||||
|
}
|
||||||
|
f(f(), "PASS");
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3905: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
passes: 2,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a, a) {
|
||||||
|
return console.log(a = 0), a && console.log("FAIL");
|
||||||
|
})("foo", 42);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a, a) {
|
||||||
|
return console.log(a = 0), a && console.log("FAIL");
|
||||||
|
})("foo", 42);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3920: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = function(b) {
|
||||||
|
return (b[b = 0] = 0) >= (b ? 0 : 1);
|
||||||
|
}("foo");
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(b) {
|
||||||
|
"foo"[0] = 0;
|
||||||
|
})();
|
||||||
|
console.log(false);
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
}
|
||||||
|
|
||||||
|
inlined_increment_prefix: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
(function() {
|
||||||
|
++a;
|
||||||
|
})();
|
||||||
|
console.log(a += 0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
void ++a;
|
||||||
|
console.log(1);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
inlined_increment_postfix: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
(function() {
|
||||||
|
a++;
|
||||||
|
})();
|
||||||
|
console.log(a += 0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
void a++;
|
||||||
|
console.log(1);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
compound_assignment_to_property: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
1 + (0..p >>= 0) && console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
1 + (0..p >>= 0),
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2208_assign: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a = 42;
|
||||||
|
console.log({
|
||||||
|
p: function() {
|
||||||
|
return function() {
|
||||||
|
return this.a;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}.p());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = 42;
|
||||||
|
console.log({
|
||||||
|
p: function() {
|
||||||
|
return function() {
|
||||||
|
return this.a;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}.p());
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2208_postfix: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a = 41;
|
||||||
|
a++;
|
||||||
|
console.log({
|
||||||
|
p: function() {
|
||||||
|
return function() {
|
||||||
|
return this.a;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}.p());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = 41;
|
||||||
|
a++;
|
||||||
|
console.log({
|
||||||
|
p: function() {
|
||||||
|
return function() {
|
||||||
|
return this.a;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}.p());
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2208_prefix: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a = 43;
|
||||||
|
--a;
|
||||||
|
console.log({
|
||||||
|
p: function() {
|
||||||
|
return function() {
|
||||||
|
return this.a;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}.p());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = 43;
|
||||||
|
--a;
|
||||||
|
console.log({
|
||||||
|
p: function() {
|
||||||
|
return function() {
|
||||||
|
return this.a;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}.p());
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3933: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a, b) {
|
||||||
|
a && (b ^= 1) && console.log("PASS");
|
||||||
|
})(1);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a, b) {
|
||||||
|
1, 1, console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3935: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function f(a) {
|
||||||
|
return a++;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(NaN);
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3937: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 123;
|
||||||
|
(a++ + (b = a))[b] ? 0 ? a : b : 0 ? a : b;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 123;
|
||||||
|
(a++ + (b = a))[b], 0, b;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "124 124"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3944: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
while (function() {
|
||||||
|
var a = 0 == (b && b.p), b = console.log(a);
|
||||||
|
}());
|
||||||
|
f;
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
void function f() {
|
||||||
|
while (a = 0 == (a = void 0), console.log(a), void 0);
|
||||||
|
var a;
|
||||||
|
f;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3953: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
(a += 0 * (a = 0)) && console.log("PASS");
|
||||||
|
}
|
||||||
|
f(1);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
(a += 0 * (a = 0)) && console.log("PASS");
|
||||||
|
}
|
||||||
|
f(1);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3988: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(b) {
|
||||||
|
return ("" + (b &= 0))[b && this];
|
||||||
|
}
|
||||||
|
var a = f();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = function(b) {
|
||||||
|
return ("" + (b &= 0))[b && this];
|
||||||
|
}();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
operator_in: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
Object.prototype.PASS = 0;
|
||||||
|
console.log(0 in [ 1 ]);
|
||||||
|
console.log(0 in [ , ]);
|
||||||
|
console.log(0 / 0 in { NaN: 2 });
|
||||||
|
console.log("PASS" in { });
|
||||||
|
console.log("FAIL" in { });
|
||||||
|
console.log("toString" in { });
|
||||||
|
console.log("toString" in { toString: 3 });
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
Object.prototype.PASS = 0;
|
||||||
|
console.log(true);
|
||||||
|
console.log(0 in [ , ]);
|
||||||
|
console.log(true);
|
||||||
|
console.log("PASS" in { });
|
||||||
|
console.log("FAIL" in { });
|
||||||
|
console.log("toString" in { });
|
||||||
|
console.log(true);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"true",
|
||||||
|
"false",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"false",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3997: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = function f(b) {
|
||||||
|
return b[b += this] = b;
|
||||||
|
}(0);
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = function f(b) {
|
||||||
|
return b[b += this] = b;
|
||||||
|
}(0);
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
expect_stdout: "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4035: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
(function() {
|
||||||
|
var b = --a;
|
||||||
|
console.log(delete (0 + b));
|
||||||
|
console.log(delete (1 * b));
|
||||||
|
console.log(delete (b + 0));
|
||||||
|
console.log(delete (b - 0));
|
||||||
|
console.log(delete (b / 1));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
(function() {
|
||||||
|
var b = --a;
|
||||||
|
console.log((0 + b, true));
|
||||||
|
console.log((1 * b, true));
|
||||||
|
console.log((0 + b, true));
|
||||||
|
console.log((b - 0, true));
|
||||||
|
console.log((b / 1, true));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4067: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
(function(b) {
|
||||||
|
b[0] += 0;
|
||||||
|
console.log(+a);
|
||||||
|
})(a);
|
||||||
|
})([]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
(function(b) {
|
||||||
|
b[0] += 0;
|
||||||
|
console.log(+a);
|
||||||
|
})(a);
|
||||||
|
})([]);
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4077: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log((a = []) - (a[0]++, 1) || "PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log((a = []) - (a[0]++, 1) || "PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4119_1: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b;
|
||||||
|
b = a = [];
|
||||||
|
a[0] += 0;
|
||||||
|
if (+b + 1) {
|
||||||
|
console.log("FAIL");
|
||||||
|
} else {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b;
|
||||||
|
b = a = [];
|
||||||
|
a[0] += 0;
|
||||||
|
+b + 1 ? console.log("FAIL") : console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4119_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
(function(b) {
|
||||||
|
a[0] += 0;
|
||||||
|
console.log(+b + 1 ? "FAIL" : "PASS");
|
||||||
|
})(a = []);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
(function(b) {
|
||||||
|
a[0] += 0;
|
||||||
|
console.log(+b + 1 ? "FAIL" : "PASS");
|
||||||
|
})(a = []);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4119_3: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b;
|
||||||
|
b = a = {
|
||||||
|
p: 42,
|
||||||
|
};
|
||||||
|
delete a.p;
|
||||||
|
console.log(b.p ? "FAIL" : "PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b;
|
||||||
|
b = a = {
|
||||||
|
p: 42,
|
||||||
|
};
|
||||||
|
delete a.p;
|
||||||
|
console.log(b.p ? "FAIL" : "PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4119_4: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b;
|
||||||
|
b = a = {
|
||||||
|
p: 42,
|
||||||
|
};
|
||||||
|
delete a.p;
|
||||||
|
console.log(!b ? "FAIL" : "PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b;
|
||||||
|
b = a = {
|
||||||
|
p: 42,
|
||||||
|
};
|
||||||
|
delete a.p;
|
||||||
|
console.log((b, 0, "PASS"));
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1483,8 +1483,7 @@ issue_2663_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function() {
|
(function() {
|
||||||
var i;
|
for (var i in { a: 1, b: 2, c: 3 })
|
||||||
for (i in { a: 1, b: 2, c: 3 })
|
|
||||||
j = i, console.log(j);
|
j = i, console.log(j);
|
||||||
var j;
|
var j;
|
||||||
})();
|
})();
|
||||||
@@ -2336,6 +2335,7 @@ issue_3274: {
|
|||||||
inline: true,
|
inline: true,
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
loops: true,
|
loops: true,
|
||||||
|
passes: 2,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2676,7 +2676,7 @@ cross_references_3: {
|
|||||||
};
|
};
|
||||||
return Math.square(n) + Math.cube(n);
|
return Math.square(n) + Math.cube(n);
|
||||||
};
|
};
|
||||||
}(Math)(2));
|
}()(2));
|
||||||
console.log(Math.square(3), Math.cube(3));
|
console.log(Math.square(3), Math.cube(3));
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
@@ -4680,3 +4680,399 @@ issue_3852: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3911: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
return function() {
|
||||||
|
if (a) (a++, b += a);
|
||||||
|
f();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var a = f, b;
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3929: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var abc = function f() {
|
||||||
|
(function() {
|
||||||
|
switch (f) {
|
||||||
|
default:
|
||||||
|
var abc = 0;
|
||||||
|
case 0:
|
||||||
|
abc.p;
|
||||||
|
}
|
||||||
|
console.log(typeof f);
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
typeof abc && abc();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
var abc = function f() {
|
||||||
|
(function() {
|
||||||
|
switch (f) {
|
||||||
|
default:
|
||||||
|
var abc = 0;
|
||||||
|
case 0:
|
||||||
|
abc.p;
|
||||||
|
}
|
||||||
|
console.log(typeof f);
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
typeof abc && abc();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4006: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
(function() {
|
||||||
|
(function(b, c) {
|
||||||
|
for (var k in console.log(c), 0)
|
||||||
|
return b += 0;
|
||||||
|
})(0, --a);
|
||||||
|
return a ? 0 : --a;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
(function(c) {
|
||||||
|
for (var k in console.log(c), 0)
|
||||||
|
return;
|
||||||
|
})(--a), a || --a;
|
||||||
|
}
|
||||||
|
expect_stdout: "-1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4155: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
inline: true,
|
||||||
|
merge_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a;
|
||||||
|
(function() {
|
||||||
|
console.log(a);
|
||||||
|
})(a);
|
||||||
|
var b = function() {};
|
||||||
|
b && console.log(typeof b);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
void console.log(b);
|
||||||
|
var b = function() {};
|
||||||
|
b && console.log(typeof b);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined",
|
||||||
|
"function",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4159: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 42, c = function(b) {
|
||||||
|
(b = a) && console.log(a++, b);
|
||||||
|
}(c = a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 42;
|
||||||
|
(b = a) && console.log(a++, b);
|
||||||
|
var b;
|
||||||
|
}
|
||||||
|
expect_stdout: "42 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
direct_inline: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
function g(c) {
|
||||||
|
return c >> 1;
|
||||||
|
}
|
||||||
|
return g(a) + g(b);
|
||||||
|
}
|
||||||
|
console.log(f(13, 31));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
return (a >> 1) + (b >> 1);
|
||||||
|
}
|
||||||
|
console.log(f(13, 31));
|
||||||
|
}
|
||||||
|
expect_stdout: "21"
|
||||||
|
}
|
||||||
|
|
||||||
|
direct_inline_catch_redefined: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
function f() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(a, f(), g());
|
||||||
|
}
|
||||||
|
console.log(a, f(), g());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
function f() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(a, f(), g());
|
||||||
|
}
|
||||||
|
console.log(a, a, g());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4171_1: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
try {
|
||||||
|
while (a)
|
||||||
|
var e = function() {};
|
||||||
|
} catch (e) {
|
||||||
|
return function() {
|
||||||
|
return e;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}(!console));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
try {
|
||||||
|
while (a)
|
||||||
|
var e = function() {};
|
||||||
|
} catch (e) {
|
||||||
|
return function() {
|
||||||
|
return e;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}(!console));
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4171_2: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
try {
|
||||||
|
while (a);
|
||||||
|
} catch (e) {
|
||||||
|
return function() {
|
||||||
|
return e;
|
||||||
|
};
|
||||||
|
} finally {
|
||||||
|
var e = function() {};
|
||||||
|
}
|
||||||
|
}(!console));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
try {
|
||||||
|
while (a);
|
||||||
|
} catch (e) {
|
||||||
|
return function() {
|
||||||
|
return e;
|
||||||
|
};
|
||||||
|
} finally {
|
||||||
|
function e() {}
|
||||||
|
}
|
||||||
|
}(!console));
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
catch_defun: {
|
||||||
|
mangle = {
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
throw 42;
|
||||||
|
} catch (a) {
|
||||||
|
function f() {
|
||||||
|
return typeof a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
throw 42;
|
||||||
|
} catch (o) {
|
||||||
|
function t() {
|
||||||
|
return typeof o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(t());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
catch_no_argname: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
function f() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
throw a;
|
||||||
|
} catch {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(a, f(), g());
|
||||||
|
}
|
||||||
|
console.log(a, f(), g());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "PASS";
|
||||||
|
try {
|
||||||
|
throw a;
|
||||||
|
} catch {
|
||||||
|
console.log(a, a, a);
|
||||||
|
}
|
||||||
|
console.log(a, a, a);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS PASS PASS",
|
||||||
|
"PASS PASS PASS",
|
||||||
|
]
|
||||||
|
node_version: ">=10"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4186: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
return function() {
|
||||||
|
function f() {
|
||||||
|
if (1)
|
||||||
|
g();
|
||||||
|
else
|
||||||
|
(function() {
|
||||||
|
return f;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
function g() {
|
||||||
|
if (1) {
|
||||||
|
if (0)
|
||||||
|
h;
|
||||||
|
else
|
||||||
|
h();
|
||||||
|
var key = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function h() {
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}()());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
return function f() {
|
||||||
|
1 ? void (1 && (0 ? h : h(), 0)) : function() {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
function h() {
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,20 @@ must_replace: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
repeated_nodes: {
|
||||||
|
options = {
|
||||||
|
global_defs: {
|
||||||
|
"@N": "rand()",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(N, N);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(rand(), rand());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
keyword: {
|
keyword: {
|
||||||
options = {
|
options = {
|
||||||
global_defs: {
|
global_defs: {
|
||||||
|
|||||||
@@ -972,3 +972,72 @@ issue_3871: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3945_1: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
o.p;
|
||||||
|
var o = {
|
||||||
|
q: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
o.p;
|
||||||
|
var o = {
|
||||||
|
q: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3945_2: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(typeof o);
|
||||||
|
var o = {
|
||||||
|
p: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(typeof o);
|
||||||
|
var o = {
|
||||||
|
p: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4023: {
|
||||||
|
options = {
|
||||||
|
comparisons: true,
|
||||||
|
hoist_props: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
typeofs: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a = function() {
|
||||||
|
return { p: 0 };
|
||||||
|
}();
|
||||||
|
return console.log("undefined" != typeof a);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(void 0 !== {});
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|||||||
@@ -2223,13 +2223,13 @@ issue_3523_rename_ie8: {
|
|||||||
expect: {
|
expect: {
|
||||||
var a = 0, b, c = "FAIL";
|
var a = 0, b, c = "FAIL";
|
||||||
(function() {
|
(function() {
|
||||||
var c, n, t, o, a, r, f, i, u, e, h, l, v, y;
|
var c, n, t, o, a, r, e, f, i, u, h, l, v, y;
|
||||||
})();
|
})();
|
||||||
try {
|
try {
|
||||||
throw 0;
|
throw 0;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
(function() {
|
(function() {
|
||||||
(function n() {
|
(function e() {
|
||||||
c = "PASS";
|
c = "PASS";
|
||||||
})();
|
})();
|
||||||
})();
|
})();
|
||||||
@@ -2489,3 +2489,373 @@ issue_3889: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3918: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
ie8: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if (console.log("PASS")) {
|
||||||
|
var a = function f() {
|
||||||
|
f.p;
|
||||||
|
try {
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {}
|
||||||
|
}, b = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
console.log("PASS") && (a = function f() {
|
||||||
|
f.p;
|
||||||
|
try {
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (o) {}
|
||||||
|
}, a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3999: {
|
||||||
|
rename = true
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
(function f() {
|
||||||
|
for (var i = 0; i < 2; i++)
|
||||||
|
try {
|
||||||
|
f[0];
|
||||||
|
} catch (f) {
|
||||||
|
var f = 0;
|
||||||
|
console.log(i);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
})(typeof f);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function f() {
|
||||||
|
for (var o = 0; o < 2; o++)
|
||||||
|
try {
|
||||||
|
f[0];
|
||||||
|
} catch (f) {
|
||||||
|
var f = 0;
|
||||||
|
console.log(o);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
})(typeof f);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4001: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
ie8: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
function f() {
|
||||||
|
return a;
|
||||||
|
var b;
|
||||||
|
}
|
||||||
|
var c = f();
|
||||||
|
(function g() {
|
||||||
|
c[42];
|
||||||
|
f;
|
||||||
|
})();
|
||||||
|
(function a() {});
|
||||||
|
}(42));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
var a;
|
||||||
|
console.log((a = 42, void f()[42], void function a() {}));
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4015: {
|
||||||
|
rename = true
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var n, a = 0, b;
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (b) {
|
||||||
|
(function g() {
|
||||||
|
(function b() {
|
||||||
|
a++;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var n, o = 0, c;
|
||||||
|
function t() {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (c) {
|
||||||
|
(function n() {
|
||||||
|
(function c() {
|
||||||
|
o++;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t();
|
||||||
|
console.log(o);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4019: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = function() {
|
||||||
|
try {
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (b) {}
|
||||||
|
}, a = (console.log(a.length), ++a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = function() {
|
||||||
|
try {
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (o) {}
|
||||||
|
}, o = (console.log(o.length), ++o);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4028: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function a() {
|
||||||
|
try {
|
||||||
|
A;
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
var b = a += a;
|
||||||
|
console.log(typeof b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function a() {
|
||||||
|
try {
|
||||||
|
A;
|
||||||
|
} catch (a) {}
|
||||||
|
}
|
||||||
|
var b = a += a;
|
||||||
|
console.log(typeof b);
|
||||||
|
}
|
||||||
|
expect_stdout: "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2737: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
a();
|
||||||
|
})(function f() {
|
||||||
|
console.log(typeof f);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
a();
|
||||||
|
})(function f() {
|
||||||
|
console.log(typeof f);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
}
|
||||||
|
|
||||||
|
single_use_catch_redefined: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(g());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(g());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
single_use_inline_catch_redefined: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(g());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(g());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
direct_inline_catch_redefined: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
function f() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(a, f(), g());
|
||||||
|
}
|
||||||
|
console.log(a, f(), g());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
function f() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (a) {
|
||||||
|
function g() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(a, f(), g());
|
||||||
|
}
|
||||||
|
console.log(a, a, g());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4186: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
ie8: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
(function NaN() {
|
||||||
|
var a = 1;
|
||||||
|
while (a--)
|
||||||
|
try {} finally {
|
||||||
|
console.log(0/0);
|
||||||
|
var b;
|
||||||
|
}
|
||||||
|
})(f);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
NaN;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function NaN() {
|
||||||
|
var n = 1;
|
||||||
|
while (n--)
|
||||||
|
console.log(0/0);
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
NaN;
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|||||||
@@ -594,3 +594,157 @@ iife_if_return_simple: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nested_if_break: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
L1: if ("number" == typeof i) {
|
||||||
|
if (0 === i) break L1;
|
||||||
|
console.log(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
L1: if ("number" == typeof i)
|
||||||
|
if (0 !== i) console.log(i);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
nested_if_continue: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
join_vars: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(n) {
|
||||||
|
var i = 0;
|
||||||
|
do {
|
||||||
|
if ("number" == typeof n) {
|
||||||
|
if (0 === n) {
|
||||||
|
console.log("even", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (1 === n) {
|
||||||
|
console.log("odd", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
} while (0 <= (n -= 2));
|
||||||
|
}
|
||||||
|
f(37);
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(n) {
|
||||||
|
for (var i = 0;
|
||||||
|
"number" == typeof n
|
||||||
|
&& (0 !== n
|
||||||
|
? 1 !== n
|
||||||
|
? i++
|
||||||
|
: console.log("odd", i)
|
||||||
|
: console.log("even", i)),
|
||||||
|
0 <= (n -= 2););
|
||||||
|
}
|
||||||
|
f(37);
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"odd 18",
|
||||||
|
"even 21",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
nested_if_return: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
if (A) {
|
||||||
|
if (B)
|
||||||
|
return B;
|
||||||
|
if (C)
|
||||||
|
return D;
|
||||||
|
if (E)
|
||||||
|
return F;
|
||||||
|
if (G)
|
||||||
|
return H;
|
||||||
|
if (I) {
|
||||||
|
if (J)
|
||||||
|
return K;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (L) {
|
||||||
|
if (M)
|
||||||
|
return;
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
if (A)
|
||||||
|
return B || (C ? D : E ? F : G ? H : I ? J ? K : void 0 : L && !M ? N : void 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_866_1: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
sequences: false,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
if (a)
|
||||||
|
return "";
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
if (a)
|
||||||
|
return "";
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_866_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
if (a)
|
||||||
|
if (b)
|
||||||
|
c;
|
||||||
|
else
|
||||||
|
return d;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
if (a) {
|
||||||
|
if (!b)
|
||||||
|
return d;
|
||||||
|
c;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ multiple_functions: {
|
|||||||
( function() {
|
( function() {
|
||||||
// NOTE: other compression steps will reduce this
|
// NOTE: other compression steps will reduce this
|
||||||
// down to just `window`.
|
// down to just `window`.
|
||||||
if ( window );
|
if ( !window );
|
||||||
function f() {}
|
function f() {}
|
||||||
function g() {}
|
function g() {}
|
||||||
} )();
|
} )();
|
||||||
@@ -38,7 +38,7 @@ single_function: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
( function() {
|
( function() {
|
||||||
if ( window );
|
if ( !window );
|
||||||
function f() {}
|
function f() {}
|
||||||
} )();
|
} )();
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ deeply_nested: {
|
|||||||
// NOTE: other compression steps will reduce this
|
// NOTE: other compression steps will reduce this
|
||||||
// down to just `window`.
|
// down to just `window`.
|
||||||
if ( window )
|
if ( window )
|
||||||
if (document);
|
if ( !document );
|
||||||
function f() {}
|
function f() {}
|
||||||
function g() {}
|
function g() {}
|
||||||
function h() {}
|
function h() {}
|
||||||
|
|||||||
@@ -151,15 +151,18 @@ Infinity_not_in_with_scope: {
|
|||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var o = { Infinity: 'oInfinity' };
|
var o = { Infinity: "FAIL" };
|
||||||
var vInfinity = "Infinity";
|
var vInfinity = "Infinity";
|
||||||
vInfinity = Infinity;
|
vInfinity = Infinity;
|
||||||
|
console.log(vInfinity);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var o = { Infinity: 'oInfinity' }
|
var o = { Infinity: "FAIL" };
|
||||||
var vInfinity = "Infinity"
|
var vInfinity = "Infinity";
|
||||||
vInfinity = 1/0
|
vInfinity = 1/0;
|
||||||
|
console.log(vInfinity);
|
||||||
}
|
}
|
||||||
|
expect_stdout: "Infinity"
|
||||||
}
|
}
|
||||||
|
|
||||||
Infinity_in_with_scope: {
|
Infinity_in_with_scope: {
|
||||||
@@ -167,15 +170,18 @@ Infinity_in_with_scope: {
|
|||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var o = { Infinity: 'oInfinity' };
|
var o = { Infinity: "PASS" };
|
||||||
var vInfinity = "Infinity";
|
var vInfinity = "Infinity";
|
||||||
with (o) { vInfinity = Infinity; }
|
with (o) { vInfinity = Infinity; }
|
||||||
|
console.log(vInfinity);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var o = { Infinity: 'oInfinity' }
|
var o = { Infinity: "PASS" };
|
||||||
var vInfinity = "Infinity"
|
var vInfinity = "Infinity";
|
||||||
with (o) vInfinity = Infinity
|
with (o) vInfinity = Infinity;
|
||||||
|
console.log(vInfinity);
|
||||||
}
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
assorted_Infinity_NaN_undefined_in_with_scope: {
|
assorted_Infinity_NaN_undefined_in_with_scope: {
|
||||||
|
|||||||
@@ -277,8 +277,8 @@ join_object_assignments_forin: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function() {
|
console.log(function() {
|
||||||
var o = { a: "PASS" };
|
var o = { a: "PASS" }, a;
|
||||||
for (var a in o)
|
for (a in o)
|
||||||
return o[a];
|
return o[a];
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
@@ -808,9 +808,9 @@ issue_3795: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = "FAIL", d = function() {
|
var a = "FAIL", d = function() {
|
||||||
if (a = 42, d) return -1;
|
if (void 0) return -1;
|
||||||
a = "PASS";
|
a = "PASS";
|
||||||
}();
|
}(a = 42);
|
||||||
console.log(a, d);
|
console.log(a, d);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS undefined"
|
expect_stdout: "PASS undefined"
|
||||||
@@ -1023,3 +1023,35 @@ issue_3856: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3916: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
o.p = "PASS";
|
||||||
|
o.__proto__ = 42;
|
||||||
|
o.q = "FAIL";
|
||||||
|
o.__proto__ = {
|
||||||
|
p: "FAIL",
|
||||||
|
q: "PASS",
|
||||||
|
};
|
||||||
|
o.__proto__ = "foo";
|
||||||
|
console.log(typeof o.__proto__, o.p, delete o.q, o.q);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
p: "PASS",
|
||||||
|
__proto__: 42,
|
||||||
|
q: "FAIL",
|
||||||
|
};
|
||||||
|
o.__proto__ = {
|
||||||
|
p: "FAIL",
|
||||||
|
q: "PASS",
|
||||||
|
};
|
||||||
|
o.__proto__ = "foo";
|
||||||
|
console.log(typeof o.__proto__, o.p, delete o.q, o.q);
|
||||||
|
}
|
||||||
|
expect_stdout: "object PASS true PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -306,8 +306,6 @@ issue_2298: {
|
|||||||
expect: {
|
expect: {
|
||||||
!function() {
|
!function() {
|
||||||
(function() {
|
(function() {
|
||||||
var a = undefined;
|
|
||||||
var undefined = a++;
|
|
||||||
try {
|
try {
|
||||||
!function() {
|
!function() {
|
||||||
(void 0)[1] = "foo";
|
(void 0)[1] = "foo";
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ evaluate: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1532: {
|
issue_1532_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
loops: true,
|
loops: true,
|
||||||
@@ -210,18 +210,56 @@ issue_1532: {
|
|||||||
function f(x, y) {
|
function f(x, y) {
|
||||||
do {
|
do {
|
||||||
if (x) break;
|
if (x) break;
|
||||||
foo();
|
console.log(y);
|
||||||
} while (false);
|
} while (false);
|
||||||
}
|
}
|
||||||
|
f(null, "PASS");
|
||||||
|
f(42, "FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(x, y) {
|
||||||
|
for (; !x && (console.log(y), false););
|
||||||
|
}
|
||||||
|
f(null, "PASS");
|
||||||
|
f(42, "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1532_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x, y) {
|
||||||
|
do {
|
||||||
|
if (x) {
|
||||||
|
console.log(x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
console.log(y);
|
||||||
|
} while (false);
|
||||||
|
}
|
||||||
|
f(null, "PASS");
|
||||||
|
f(42, "FAIL");
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(x, y) {
|
function f(x, y) {
|
||||||
do {
|
do {
|
||||||
if (x) break;
|
if (x) {
|
||||||
foo();
|
console.log(x);
|
||||||
} while (false);
|
break;
|
||||||
}
|
}
|
||||||
|
} while (console.log(y), false);
|
||||||
}
|
}
|
||||||
|
f(null, "PASS");
|
||||||
|
f(42, "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"42",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_186: {
|
issue_186: {
|
||||||
@@ -756,7 +794,37 @@ empty_for_in_side_effects: {
|
|||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
"WARN: Dropping unused variable b [test/compress/loops.js:4,16]",
|
"WARN: Dropping unused variable b [test/compress/loops.js:4,16]",
|
||||||
"INFO: Dropping unused loop variable a [test/compress/loops.js:1,17]",
|
"INFO: Dropping unused loop variable a [test/compress/loops.js:1,17]",
|
||||||
"WARN: Side effects in object of for-in loop [test/compress/loops.js:1,17]",
|
"WARN: Side effects in object of for-in loop [test/compress/loops.js:2,17]",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
empty_for_in_prop_init: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function f() {
|
||||||
|
var a = "bar";
|
||||||
|
for ((a, f)[a] in console.log("foo"));
|
||||||
|
return a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var a = "bar";
|
||||||
|
console.log("foo");
|
||||||
|
return a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
expect_warnings: [
|
||||||
|
"INFO: Dropping unused loop variable f [test/compress/loops.js:3,21]",
|
||||||
|
"WARN: Side effects in object of for-in loop [test/compress/loops.js:3,30]",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -933,3 +1001,199 @@ issue_3634_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4075: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function() {
|
||||||
|
for (a in { PASS: 0 });
|
||||||
|
})()
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function() {
|
||||||
|
for (a in { PASS: 0 });
|
||||||
|
})()
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4082: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: "strict",
|
||||||
|
loops: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
(function(a) {
|
||||||
|
for (a in "foo")
|
||||||
|
var b;
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "PASS";
|
||||||
|
(function(a) {
|
||||||
|
for (a in "foo");
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4084: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: "strict",
|
||||||
|
loops: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
function f(a) {
|
||||||
|
var b = a++;
|
||||||
|
for (a in "foo");
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
return typeof a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
(function() {
|
||||||
|
0;
|
||||||
|
})();
|
||||||
|
return typeof a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4091_1: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (e) {
|
||||||
|
for (var e in 42);
|
||||||
|
}
|
||||||
|
console.log(e && e);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (e) {
|
||||||
|
var e;
|
||||||
|
}
|
||||||
|
console.log(e && e);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4091_2: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (e) {
|
||||||
|
for (e in 42);
|
||||||
|
var e;
|
||||||
|
}
|
||||||
|
console.log(e && e);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (e) {
|
||||||
|
var e;
|
||||||
|
}
|
||||||
|
console.log(e && e);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4182_1: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
console.log("FAIL");
|
||||||
|
} while (0);
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
console.log("FAIL");
|
||||||
|
} while (0);
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4182_2: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
L: do {
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
continue L;
|
||||||
|
}
|
||||||
|
console.log("FAIL");
|
||||||
|
} while (0);
|
||||||
|
console.log("FAIL");
|
||||||
|
} while (0);
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
L: do {
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
continue L;
|
||||||
|
}
|
||||||
|
} while (console.log("FAIL"), 0);
|
||||||
|
console.log("FAIL");
|
||||||
|
} while (0);
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
3013
test/compress/merge_vars.js
Normal file
3013
test/compress/merge_vars.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -91,7 +91,7 @@ evaluate_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(
|
console.log(
|
||||||
x + 1 + 2,
|
x + 1 + 2,
|
||||||
2 * x,
|
2 * +x,
|
||||||
+x + 1 + 2,
|
+x + 1 + 2,
|
||||||
1 + x + 2 + 3,
|
1 + x + 2 + 3,
|
||||||
3 | x,
|
3 | x,
|
||||||
@@ -130,7 +130,7 @@ evaluate_1_unsafe_math: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(
|
console.log(
|
||||||
x + 1 + 2,
|
x + 1 + 2,
|
||||||
2 * x,
|
2 * +x,
|
||||||
+x + 3,
|
+x + 3,
|
||||||
1 + x + 2 + 3,
|
1 + x + 2 + 3,
|
||||||
3 | x,
|
3 | x,
|
||||||
@@ -148,10 +148,12 @@ evaluate_1_unsafe_math: {
|
|||||||
evaluate_2: {
|
evaluate_2: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
unsafe_math: false,
|
unsafe_math: false,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = "42", y = null;
|
function f(num) {
|
||||||
|
var x = "" + num, y = null;
|
||||||
[
|
[
|
||||||
x + 1 + 2,
|
x + 1 + 2,
|
||||||
x * 1 * 2,
|
x * 1 * 2,
|
||||||
@@ -169,25 +171,30 @@ evaluate_2: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x = "42", y = null;
|
function f(num) {
|
||||||
|
var x = "" + num, y = null;
|
||||||
[
|
[
|
||||||
x + 1 + 2,
|
x + "12",
|
||||||
2 * x,
|
2 * x,
|
||||||
+x + 1 + 2,
|
+x + 1 + 2,
|
||||||
1 + x + 2 + 3,
|
1 + x + "23",
|
||||||
3 | x,
|
3 | x,
|
||||||
1 + x-- + 2 + 3,
|
1 + x-- + 2 + 3,
|
||||||
x*y + 2 + 1 + 3,
|
x*y + 2 + 1 + 3,
|
||||||
1 + (2 + x + 3),
|
2 + x + 3 + 1,
|
||||||
2 + ~x + 3 + 1,
|
2 + ~x + 3 + 1,
|
||||||
2 + ~x + 3 - y,
|
2 + ~x + 3,
|
||||||
0 & x,
|
0 & x,
|
||||||
2 + (x |= 0) + 3 + 1,
|
2 + (x |= 0) + 3 + 1,
|
||||||
].forEach(function(n) {
|
].forEach(function(n) {
|
||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"string 4212",
|
"string 4212",
|
||||||
"number 84",
|
"number 84",
|
||||||
@@ -207,10 +214,12 @@ evaluate_2: {
|
|||||||
evaluate_2_unsafe_math: {
|
evaluate_2_unsafe_math: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
unsafe_math: true,
|
unsafe_math: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = "42", y = null;
|
function f(num) {
|
||||||
|
var x = "" + num, y = null;
|
||||||
[
|
[
|
||||||
x + 1 + 2,
|
x + 1 + 2,
|
||||||
x * 1 * 2,
|
x * 1 * 2,
|
||||||
@@ -228,25 +237,30 @@ evaluate_2_unsafe_math: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x = "42", y = null;
|
function f(num) {
|
||||||
|
var x = "" + num, y = null;
|
||||||
[
|
[
|
||||||
x + 1 + 2,
|
x + "12",
|
||||||
2 * x,
|
2 * x,
|
||||||
+x + 3,
|
+x + 3,
|
||||||
1 + x + 2 + 3,
|
1 + x + "23",
|
||||||
3 | x,
|
3 | x,
|
||||||
6 + x--,
|
6 + x--,
|
||||||
x*y + 6,
|
x*y + 6,
|
||||||
1 + (2 + x + 3),
|
6 + x,
|
||||||
6 + ~x,
|
6 + ~x,
|
||||||
5 + ~x - y,
|
5 + ~x,
|
||||||
0 & x,
|
0 & x,
|
||||||
6 + (x |= 0),
|
6 + (x |= 0),
|
||||||
].forEach(function(n) {
|
].forEach(function(n) {
|
||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"string 4212",
|
"string 4212",
|
||||||
"number 84",
|
"number 84",
|
||||||
@@ -310,10 +324,12 @@ evaluate_4: {
|
|||||||
evaluate_5: {
|
evaluate_5: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
unsafe_math: false,
|
unsafe_math: false,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var a = "1";
|
function f(num) {
|
||||||
|
var a = "" + num;
|
||||||
[
|
[
|
||||||
+a + 2 + 3,
|
+a + 2 + 3,
|
||||||
+a + 2 - 3,
|
+a + 2 - 3,
|
||||||
@@ -331,8 +347,11 @@ evaluate_5: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(1);
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = "1";
|
function f(num) {
|
||||||
|
var a = "" + num;
|
||||||
[
|
[
|
||||||
+a + 2 + 3,
|
+a + 2 + 3,
|
||||||
+a + 2 - 3,
|
+a + 2 - 3,
|
||||||
@@ -350,6 +369,8 @@ evaluate_5: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(1);
|
||||||
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"number 6",
|
"number 6",
|
||||||
"number 0",
|
"number 0",
|
||||||
@@ -369,10 +390,12 @@ evaluate_5: {
|
|||||||
evaluate_5_unsafe_math: {
|
evaluate_5_unsafe_math: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
unsafe_math: true,
|
unsafe_math: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var a = "1";
|
function f(num) {
|
||||||
|
var a = "" + num;
|
||||||
[
|
[
|
||||||
+a + 2 + 3,
|
+a + 2 + 3,
|
||||||
+a + 2 - 3,
|
+a + 2 - 3,
|
||||||
@@ -390,8 +413,11 @@ evaluate_5_unsafe_math: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(1);
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = "1";
|
function f(num) {
|
||||||
|
var a = "" + num;
|
||||||
[
|
[
|
||||||
+a + 5,
|
+a + 5,
|
||||||
+a + -1,
|
+a + -1,
|
||||||
@@ -409,6 +435,8 @@ evaluate_5_unsafe_math: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(1);
|
||||||
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"number 6",
|
"number 6",
|
||||||
"number 0",
|
"number 0",
|
||||||
@@ -546,10 +574,12 @@ evaluate_6_unsafe_math: {
|
|||||||
evaluate_7: {
|
evaluate_7: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
unsafe_math: false,
|
unsafe_math: false,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = "42", y;
|
function f(num, y) {
|
||||||
|
var x = "" + num;
|
||||||
[
|
[
|
||||||
+x + 2 + (3 + !y),
|
+x + 2 + (3 + !y),
|
||||||
+x + 2 + (3 - !y),
|
+x + 2 + (3 - !y),
|
||||||
@@ -563,8 +593,11 @@ evaluate_7: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x = "42", y;
|
function f(num, y) {
|
||||||
|
var x = "" + num;
|
||||||
[
|
[
|
||||||
+x + 2 + (3 + !y),
|
+x + 2 + (3 + !y),
|
||||||
+x + 2 + (3 - !y),
|
+x + 2 + (3 - !y),
|
||||||
@@ -578,6 +611,8 @@ evaluate_7: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"number 48",
|
"number 48",
|
||||||
"number 46",
|
"number 46",
|
||||||
@@ -593,10 +628,12 @@ evaluate_7: {
|
|||||||
evaluate_7_unsafe_math: {
|
evaluate_7_unsafe_math: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
unsafe_math: true,
|
unsafe_math: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = "42", y;
|
function f(num, y) {
|
||||||
|
var x = "" + num;
|
||||||
[
|
[
|
||||||
+x + 2 + (3 + !y),
|
+x + 2 + (3 + !y),
|
||||||
+x + 2 + (3 - !y),
|
+x + 2 + (3 - !y),
|
||||||
@@ -610,8 +647,11 @@ evaluate_7_unsafe_math: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x = "42", y;
|
function f(num, y) {
|
||||||
|
var x = "" + num;
|
||||||
[
|
[
|
||||||
+x + 5 + !y,
|
+x + 5 + !y,
|
||||||
+x + 5 - !y,
|
+x + 5 - !y,
|
||||||
@@ -625,6 +665,8 @@ evaluate_7_unsafe_math: {
|
|||||||
console.log(typeof n, n);
|
console.log(typeof n, n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"number 48",
|
"number 48",
|
||||||
"number 46",
|
"number 46",
|
||||||
@@ -637,6 +679,22 @@ evaluate_7_unsafe_math: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
evaluate_8_unsafe_math: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = [ "42" ];
|
||||||
|
console.log(a * (1 / 7));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = [ "42" ];
|
||||||
|
console.log(+a / 7);
|
||||||
|
}
|
||||||
|
expect_stdout: "6"
|
||||||
|
}
|
||||||
|
|
||||||
NaN_redefined: {
|
NaN_redefined: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -1251,3 +1309,29 @@ issue_3695: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "NaN"
|
expect_stdout: "NaN"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4137: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(+(A = []) * (A[0] = 1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(+(A = []) * (A[0] = 1));
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4142: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log("" + +(0 === console));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("" + +(0 === console));
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ evaluate_string_length: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_properties: {
|
mangle_properties_1: {
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
keep_quoted: false,
|
keep_quoted: false,
|
||||||
@@ -152,6 +152,53 @@ mangle_properties: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mangle_properties_2: {
|
||||||
|
mangle = {
|
||||||
|
properties: {
|
||||||
|
reserved: [
|
||||||
|
"value",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {
|
||||||
|
prop1: 1,
|
||||||
|
};
|
||||||
|
Object.defineProperty(o, "prop2", {
|
||||||
|
value: 2,
|
||||||
|
});
|
||||||
|
Object.defineProperties(o, {
|
||||||
|
prop3: {
|
||||||
|
value: 3,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log("prop1", o.prop1, "prop1" in o);
|
||||||
|
console.log("prop2", o.prop2, o.hasOwnProperty("prop2"));
|
||||||
|
console.log("prop3", o.prop3, Object.getOwnPropertyDescriptor(o, "prop3").value);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
o: 1,
|
||||||
|
};
|
||||||
|
Object.defineProperty(o, "p", {
|
||||||
|
value: 2,
|
||||||
|
});
|
||||||
|
Object.defineProperties(o, {
|
||||||
|
r: {
|
||||||
|
value: 3,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log("prop1", o.o, "o" in o);
|
||||||
|
console.log("prop2", o.p, o.hasOwnProperty("p"));
|
||||||
|
console.log("prop3", o.r, Object.getOwnPropertyDescriptor(o, "r").value);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"prop1 1 true",
|
||||||
|
"prop2 2 true",
|
||||||
|
"prop3 3 3",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
mangle_unquoted_properties: {
|
mangle_unquoted_properties: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -1046,16 +1093,22 @@ array_hole: {
|
|||||||
side_effects: true,
|
side_effects: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(
|
Array.prototype[2] = "PASS";
|
||||||
[ 1, 2, , 3][1],
|
console.log([ 1, 2, , 3 ][1]);
|
||||||
[ 1, 2, , 3][2],
|
console.log([ 1, 2, , 3 ][2]);
|
||||||
[ 1, 2, , 3][3]
|
console.log([ 1, 2, , 3 ][3]);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(2, void 0, 3);
|
Array.prototype[2] = "PASS";
|
||||||
|
console.log(2);
|
||||||
|
console.log([ , , , ][2]);
|
||||||
|
console.log(3);
|
||||||
}
|
}
|
||||||
expect_stdout: "2 undefined 3"
|
expect_stdout: [
|
||||||
|
"2",
|
||||||
|
"PASS",
|
||||||
|
"3",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
new_this: {
|
new_this: {
|
||||||
@@ -1070,11 +1123,7 @@ new_this: {
|
|||||||
}
|
}
|
||||||
}.f(42);
|
}.f(42);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {}
|
||||||
new function(a) {
|
|
||||||
this.a = a;
|
|
||||||
}(42);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2513: {
|
issue_2513: {
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ relational: {
|
|||||||
side_effects :true,
|
side_effects :true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
foo() in foo();
|
foo() in new foo();
|
||||||
foo() instanceof bar();
|
foo() instanceof bar();
|
||||||
foo() < "bar";
|
foo() < "bar";
|
||||||
bar() > foo();
|
bar() > foo();
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ modified: {
|
|||||||
expect: {
|
expect: {
|
||||||
function f0() {
|
function f0() {
|
||||||
var b = 2;
|
var b = 2;
|
||||||
b++;
|
+b;
|
||||||
console.log(2);
|
console.log(2);
|
||||||
console.log(4);
|
console.log(4);
|
||||||
}
|
}
|
||||||
@@ -905,7 +905,7 @@ use_before_var: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(){
|
function f(){
|
||||||
console.log(t);
|
console.log(void 0);
|
||||||
var t = 1;
|
var t = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -981,12 +981,12 @@ inner_var_for_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
function f() {
|
function f() {
|
||||||
var a = 1;
|
var a = 1;
|
||||||
x(1, b, d);
|
x(1, void 0, d);
|
||||||
for (var b = 2, c = 3; x(1, b, 3, d); x(1, b, 3, d)) {
|
for (var b = 2, c = 3; x(1, 2, 3, d); x(1, 2, 3, d)) {
|
||||||
var d = 4, e = 5;
|
var d = 4, e = 5;
|
||||||
x(1, b, 3, d, e);
|
x(1, 2, 3, d, e);
|
||||||
}
|
}
|
||||||
x(1, b, 3, d, e);
|
x(1, 2, 3, d, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1520,10 +1520,7 @@ func_inline: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f() {
|
function f() {
|
||||||
console.log(1 + h());
|
console.log(1 + (void 0)());
|
||||||
var h = function() {
|
|
||||||
return 2;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1627,7 +1624,7 @@ defun_label: {
|
|||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
double_reference: {
|
double_reference_1: {
|
||||||
options = {
|
options = {
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
@@ -1641,6 +1638,32 @@ double_reference: {
|
|||||||
g();
|
g();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
var g = function g() {
|
||||||
|
g();
|
||||||
|
};
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double_reference_2: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var g = function g() {
|
||||||
|
g();
|
||||||
|
};
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f() {
|
function f() {
|
||||||
(function g() {
|
(function g() {
|
||||||
@@ -1650,6 +1673,60 @@ double_reference: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double_reference_3: {
|
||||||
|
options = {
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = function f() {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
function g() {
|
||||||
|
return x();
|
||||||
|
}
|
||||||
|
console.log(g() === g());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x = function f() {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
function g() {
|
||||||
|
return x();
|
||||||
|
}
|
||||||
|
console.log(g() === g());
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
double_reference_4: {
|
||||||
|
options = {
|
||||||
|
comparisons: true,
|
||||||
|
functions: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = function f() {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
function g() {
|
||||||
|
return x();
|
||||||
|
}
|
||||||
|
console.log(g() === g());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(true);
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
iife_arguments_1: {
|
iife_arguments_1: {
|
||||||
options = {
|
options = {
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
@@ -1689,8 +1766,35 @@ iife_arguments_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function() {
|
(function() {
|
||||||
console.log(function f() {
|
var x = function f() {
|
||||||
return f;
|
return f;
|
||||||
|
};
|
||||||
|
console.log(x() === arguments[0]);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
iife_arguments_3: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var x = function f() {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
console.log(x() === arguments[0]);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
console.log(function x() {
|
||||||
|
return x;
|
||||||
}() === arguments[0]);
|
}() === arguments[0]);
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
@@ -2034,6 +2138,7 @@ issue_1670_4: {
|
|||||||
|
|
||||||
issue_1670_5: {
|
issue_1670_5: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
@@ -2065,11 +2170,13 @@ issue_1670_5: {
|
|||||||
|
|
||||||
issue_1670_6: {
|
issue_1670_6: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -2087,10 +2194,9 @@ issue_1670_6: {
|
|||||||
})(1);
|
})(1);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function(a) {
|
(function() {
|
||||||
a = 1;
|
console.log(1);
|
||||||
console.log(a);
|
})();
|
||||||
})(1);
|
|
||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
@@ -2309,7 +2415,7 @@ redefine_farg_2: {
|
|||||||
console.log(typeof [], "number",function(a, b) {
|
console.log(typeof [], "number",function(a, b) {
|
||||||
a = b;
|
a = b;
|
||||||
return typeof a;
|
return typeof a;
|
||||||
}([]));
|
}());
|
||||||
}
|
}
|
||||||
expect_stdout: "object number undefined"
|
expect_stdout: "object number undefined"
|
||||||
}
|
}
|
||||||
@@ -2372,8 +2478,7 @@ delay_def: {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
function g() {
|
function g() {
|
||||||
return a;
|
return;
|
||||||
var a = 1;
|
|
||||||
}
|
}
|
||||||
console.log(f(), g());
|
console.log(f(), g());
|
||||||
}
|
}
|
||||||
@@ -2395,7 +2500,7 @@ delay_def_lhs: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(function() {
|
console.log(function() {
|
||||||
long_name++;
|
long_name++;
|
||||||
return long_name;
|
return NaN;
|
||||||
var long_name;
|
var long_name;
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
@@ -2651,11 +2756,9 @@ var_assign_5: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function() {
|
!function() {
|
||||||
var a;
|
|
||||||
!function(b) {
|
!function(b) {
|
||||||
a = 2,
|
console.log(2, void 0);
|
||||||
console.log(a, b);
|
}();
|
||||||
}(a);
|
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
expect_stdout: "2 undefined"
|
expect_stdout: "2 undefined"
|
||||||
@@ -2676,8 +2779,8 @@ var_assign_6: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function() {
|
!function() {
|
||||||
var a = function(){}(a = 1);
|
(function(){}());
|
||||||
console.log(a);
|
console.log(void 0);
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
@@ -2724,8 +2827,8 @@ issue_1814_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
!function() {
|
!function() {
|
||||||
!function(a) {
|
!function(a) {
|
||||||
console.log(a++, 42);
|
console.log(0, 42);
|
||||||
}(0);
|
}();
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
expect_stdout: "0 42"
|
expect_stdout: "0 42"
|
||||||
@@ -2751,8 +2854,8 @@ issue_1814_2: {
|
|||||||
expect: {
|
expect: {
|
||||||
!function() {
|
!function() {
|
||||||
!function(a) {
|
!function(a) {
|
||||||
console.log("321", a++);
|
console.log("321", 0);
|
||||||
}(0);
|
}();
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
expect_stdout: "321 0"
|
expect_stdout: "321 0"
|
||||||
@@ -4725,7 +4828,7 @@ escape_conditional: {
|
|||||||
function bar() {}
|
function bar() {}
|
||||||
(function() {
|
(function() {
|
||||||
var thing = baz();
|
var thing = baz();
|
||||||
if (thing !== (thing = baz()))
|
if (thing !== baz())
|
||||||
console.log("FAIL");
|
console.log("FAIL");
|
||||||
else
|
else
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
@@ -4763,7 +4866,7 @@ escape_sequence: {
|
|||||||
function bar() {}
|
function bar() {}
|
||||||
(function() {
|
(function() {
|
||||||
var thing = baz();
|
var thing = baz();
|
||||||
if (thing !== (thing = baz()))
|
if (thing !== baz())
|
||||||
console.log("FAIL");
|
console.log("FAIL");
|
||||||
else
|
else
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
@@ -4808,7 +4911,7 @@ escape_throw: {
|
|||||||
function foo() {}
|
function foo() {}
|
||||||
(function() {
|
(function() {
|
||||||
var thing = baz();
|
var thing = baz();
|
||||||
if (thing !== (thing = baz()))
|
if (thing !== baz())
|
||||||
console.log("FAIL");
|
console.log("FAIL");
|
||||||
else
|
else
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
@@ -4845,7 +4948,7 @@ escape_local_conditional: {
|
|||||||
}
|
}
|
||||||
(function() {
|
(function() {
|
||||||
var thing = baz();
|
var thing = baz();
|
||||||
if (thing !== (thing = baz()))
|
if (thing !== baz())
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
else
|
else
|
||||||
console.log("FAIL");
|
console.log("FAIL");
|
||||||
@@ -4882,7 +4985,7 @@ escape_local_sequence: {
|
|||||||
}
|
}
|
||||||
(function() {
|
(function() {
|
||||||
var thing = baz();
|
var thing = baz();
|
||||||
if (thing !== (thing = baz()))
|
if (thing !== baz())
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
else
|
else
|
||||||
console.log("FAIL");
|
console.log("FAIL");
|
||||||
@@ -4926,7 +5029,7 @@ escape_local_throw: {
|
|||||||
}
|
}
|
||||||
(function() {
|
(function() {
|
||||||
var thing = baz();
|
var thing = baz();
|
||||||
if (thing !== (thing = baz()))
|
if (thing !== baz())
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
else
|
else
|
||||||
console.log("FAIL");
|
console.log("FAIL");
|
||||||
@@ -4980,11 +5083,7 @@ inverted_var: {
|
|||||||
console.log(1, 2, 3, 4, 5, function c() {
|
console.log(1, 2, 3, 4, 5, function c() {
|
||||||
c = 6;
|
c = 6;
|
||||||
return c;
|
return c;
|
||||||
}(), 7, function() {
|
}(), 7, 8);
|
||||||
c = 8;
|
|
||||||
return c;
|
|
||||||
var c = "foo";
|
|
||||||
}());
|
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
@@ -5180,9 +5279,7 @@ defun_var_3: {
|
|||||||
var a = 42, b;
|
var a = 42, b;
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function a() {}
|
console.log("function", "function");
|
||||||
console.log(typeof a, "function");
|
|
||||||
var a = 42;
|
|
||||||
}
|
}
|
||||||
expect_stdout: "function function"
|
expect_stdout: "function function"
|
||||||
}
|
}
|
||||||
@@ -5277,11 +5374,11 @@ defun_catch_4: {
|
|||||||
try {
|
try {
|
||||||
throw 42;
|
throw 42;
|
||||||
} catch (a) {
|
} catch (a) {
|
||||||
|
function a() {}
|
||||||
console.log(a);
|
console.log(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_stdout: "42"
|
expect_stdout: true
|
||||||
node_version: "<=4"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defun_catch_5: {
|
defun_catch_5: {
|
||||||
@@ -5303,10 +5400,10 @@ defun_catch_5: {
|
|||||||
throw 42;
|
throw 42;
|
||||||
} catch (a) {
|
} catch (a) {
|
||||||
console.log(a);
|
console.log(a);
|
||||||
|
function a() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_stdout: "42"
|
expect_stdout: true
|
||||||
node_version: "<=4"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defun_catch_6: {
|
defun_catch_6: {
|
||||||
@@ -5493,7 +5590,7 @@ lvalues_def_1: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var b = 1;
|
var b = 1;
|
||||||
var a = b++, b = NaN;
|
var a = +b, b = NaN;
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect_stdout: "1 NaN"
|
expect_stdout: "1 NaN"
|
||||||
@@ -7068,3 +7165,439 @@ issue_3880: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3894: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function log(msg) {
|
||||||
|
console.log(msg ? "FAIL" : "PASS");
|
||||||
|
}
|
||||||
|
var a;
|
||||||
|
(function(b) {
|
||||||
|
a = 0,
|
||||||
|
log(b);
|
||||||
|
})(-0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function log(msg) {
|
||||||
|
console.log(msg ? "FAIL" : "PASS");
|
||||||
|
}
|
||||||
|
var a;
|
||||||
|
void log(-(a = 0));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3922: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
var b;
|
||||||
|
b && b[c];
|
||||||
|
a |= this;
|
||||||
|
console.log("PASS");
|
||||||
|
var c = a.undefined;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
0;
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3949_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function f(a) {
|
||||||
|
var a = void (a = 0, g);
|
||||||
|
function g() {
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function f(a) {
|
||||||
|
var a = void (a = 0, g);
|
||||||
|
function g() {
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3949_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function f(a) {
|
||||||
|
var a = void (a = 0, g);
|
||||||
|
function g() {
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
a = void (a = 0, g);
|
||||||
|
function g() {
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3949_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {}
|
||||||
|
for (var a, i = 3; 0 <= --i; ) {
|
||||||
|
a = f;
|
||||||
|
console.log(a === b);
|
||||||
|
var b = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {}
|
||||||
|
for (var a, i = 3; 0 <= --i; ) {
|
||||||
|
a = f;
|
||||||
|
console.log(a === b);
|
||||||
|
var b = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"false",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3949_4: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {}
|
||||||
|
for (var a, i = 3; 0 <= --i; ) {
|
||||||
|
a = f;
|
||||||
|
console.log(a === b);
|
||||||
|
var b = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {}
|
||||||
|
for (var a, i = 3; 0 <= --i; ) {
|
||||||
|
a = f;
|
||||||
|
console.log(a === b);
|
||||||
|
var b = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"false",
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
local_assignment_lambda: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
function f() {
|
||||||
|
a = "PASS";
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
f(),
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
local_assignment_loop: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
do {
|
||||||
|
a = "PASS";
|
||||||
|
console.log(a);
|
||||||
|
} while (!console);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
do {
|
||||||
|
console.log("PASS");
|
||||||
|
} while (!console);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3957_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
while (a += console.log(a = 0))
|
||||||
|
a = 0;
|
||||||
|
}
|
||||||
|
f("FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
while (a += console.log(a = 0))
|
||||||
|
a = 0;
|
||||||
|
}
|
||||||
|
f("FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3957_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
while (a += console.log(a = 0))
|
||||||
|
a = 0;
|
||||||
|
}
|
||||||
|
f("FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
while (a += console.log(a = 0))
|
||||||
|
a = 0;
|
||||||
|
}
|
||||||
|
f("FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3958: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
(function(b) {
|
||||||
|
(function(c) {
|
||||||
|
console.log(c[0] = 1);
|
||||||
|
})(a = b);
|
||||||
|
--a;
|
||||||
|
})([]);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
(function(b) {
|
||||||
|
(function(c) {
|
||||||
|
console.log(c[0] = 1);
|
||||||
|
})(a = []);
|
||||||
|
--a;
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"1",
|
||||||
|
"0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3974: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
var a = 0 in 0;
|
||||||
|
0 && a;
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
var a = 0 in 0;
|
||||||
|
0 && a;
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4030: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
{
|
||||||
|
delete (a = "PASS");
|
||||||
|
A = "PASS";
|
||||||
|
}
|
||||||
|
console.log(A);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
A = "PASS";
|
||||||
|
console.log(A);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
global_assign: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
A = "FAIL";
|
||||||
|
this.A = "PASS";
|
||||||
|
console.log(A);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
A = "FAIL";
|
||||||
|
this.A = "PASS";
|
||||||
|
console.log(A);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4188_1: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
while (A)
|
||||||
|
var a = function() {}, b = a;
|
||||||
|
} catch (a) {
|
||||||
|
console.log(function() {
|
||||||
|
return typeof a;
|
||||||
|
}(), typeof b);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
while (A)
|
||||||
|
var a = function() {}, b = a;
|
||||||
|
} catch (a) {
|
||||||
|
console.log(function() {
|
||||||
|
return typeof a;
|
||||||
|
}(), typeof b);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "object undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4188_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
throw 42;
|
||||||
|
} catch (a) {
|
||||||
|
console.log(function() {
|
||||||
|
return typeof a;
|
||||||
|
}(), typeof b);
|
||||||
|
}
|
||||||
|
while (!console)
|
||||||
|
var a = function() {}, b = a;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
throw 42;
|
||||||
|
} catch (a) {
|
||||||
|
console.log(function() {
|
||||||
|
return typeof a;
|
||||||
|
}(), typeof b);
|
||||||
|
}
|
||||||
|
while (!console)
|
||||||
|
var a = function() {}, b = a;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "number undefined"
|
||||||
|
}
|
||||||
|
|||||||
@@ -80,3 +80,21 @@ log_global: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "[object global]"
|
expect_stdout: "[object global]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4054: {
|
||||||
|
input: {
|
||||||
|
console.log({
|
||||||
|
set p(v) {
|
||||||
|
throw "FAIL";
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log({
|
||||||
|
set p(v) {
|
||||||
|
throw "FAIL";
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "{ p: [Setter] }"
|
||||||
|
}
|
||||||
|
|||||||
@@ -877,7 +877,7 @@ for_init_var: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
forin: {
|
forin_1: {
|
||||||
options = {
|
options = {
|
||||||
sequences: true,
|
sequences: true,
|
||||||
}
|
}
|
||||||
@@ -895,6 +895,49 @@ forin: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
forin_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {
|
||||||
|
p: 1,
|
||||||
|
q: 2,
|
||||||
|
};
|
||||||
|
var k = "k";
|
||||||
|
for ((console.log("exp"), o)[function() {
|
||||||
|
console.log("prop");
|
||||||
|
return k;
|
||||||
|
}()] in function() {
|
||||||
|
console.log("obj");
|
||||||
|
return o;
|
||||||
|
}())
|
||||||
|
console.log(o.k, o[o.k]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
p: 1,
|
||||||
|
q: 2,
|
||||||
|
};
|
||||||
|
for ((console.log("exp"), o)[console.log("prop"), "k"] in console.log("obj"), o)
|
||||||
|
console.log(o.k, o[o.k]);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"obj",
|
||||||
|
"exp",
|
||||||
|
"prop",
|
||||||
|
"p 1",
|
||||||
|
"exp",
|
||||||
|
"prop",
|
||||||
|
"q 2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
call: {
|
call: {
|
||||||
options = {
|
options = {
|
||||||
sequences: true,
|
sequences: true,
|
||||||
@@ -1112,3 +1155,25 @@ issue_3703: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4079: {
|
||||||
|
options = {
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
typeof (0, A);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
A;
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -97,9 +97,8 @@ issue_2233_2: {
|
|||||||
var RegExp;
|
var RegExp;
|
||||||
UndeclaredGlobal;
|
UndeclaredGlobal;
|
||||||
function foo() {
|
function foo() {
|
||||||
var Number;
|
|
||||||
AnotherUndeclaredGlobal;
|
AnotherUndeclaredGlobal;
|
||||||
Number.isNaN;
|
(void 0).isNaN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,6 +245,31 @@ unsafe_builtin_2: {
|
|||||||
expect_stdout: "object PASS PASS"
|
expect_stdout: "object PASS PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe_builtin_3: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
if (42 < Math.random())
|
||||||
|
o.p = "FAIL";
|
||||||
|
else
|
||||||
|
o.p = "PASS";
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {};
|
||||||
|
o.p = 42 < Math.random() ? "FAIL" : "PASS";
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect_stdout: "p PASS"
|
||||||
|
}
|
||||||
|
|
||||||
unsafe_string_replace: {
|
unsafe_string_replace: {
|
||||||
options = {
|
options = {
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -275,3 +299,137 @@ drop_value: {
|
|||||||
foo(), bar();
|
foo(), bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator_in: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
"foo" in true;
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
0 in true;
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3983_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
function f() {
|
||||||
|
g && g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
function g() {
|
||||||
|
0 ? a : 0;
|
||||||
|
}
|
||||||
|
var b = a;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "PASS";
|
||||||
|
g();
|
||||||
|
function g() {}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3983_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
function f() {
|
||||||
|
g && g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
function g() {
|
||||||
|
0 ? a : 0;
|
||||||
|
}
|
||||||
|
var b = a;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4008: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
function f(b, b) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
f && f(a && a[a]);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "PASS";
|
||||||
|
function f(b, b) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
f(a[a]);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
trim_new: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
new function(a) {
|
||||||
|
console.log(a);
|
||||||
|
}("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
console.log(a);
|
||||||
|
})("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
constant_switch_1: {
|
constant_switch_1: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -19,6 +20,7 @@ constant_switch_1: {
|
|||||||
|
|
||||||
constant_switch_2: {
|
constant_switch_2: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -39,6 +41,7 @@ constant_switch_2: {
|
|||||||
|
|
||||||
constant_switch_3: {
|
constant_switch_3: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -60,6 +63,7 @@ constant_switch_3: {
|
|||||||
|
|
||||||
constant_switch_4: {
|
constant_switch_4: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -86,6 +90,7 @@ constant_switch_4: {
|
|||||||
|
|
||||||
constant_switch_5: {
|
constant_switch_5: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -120,6 +125,7 @@ constant_switch_5: {
|
|||||||
|
|
||||||
constant_switch_6: {
|
constant_switch_6: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -154,6 +160,7 @@ constant_switch_6: {
|
|||||||
|
|
||||||
constant_switch_7: {
|
constant_switch_7: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -197,6 +204,7 @@ constant_switch_7: {
|
|||||||
|
|
||||||
constant_switch_8: {
|
constant_switch_8: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -226,6 +234,7 @@ constant_switch_8: {
|
|||||||
|
|
||||||
constant_switch_9: {
|
constant_switch_9: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -315,6 +324,7 @@ keep_default: {
|
|||||||
|
|
||||||
issue_1663: {
|
issue_1663: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -551,6 +561,7 @@ issue_441_2: {
|
|||||||
|
|
||||||
issue_1674: {
|
issue_1674: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -876,6 +887,7 @@ beautify: {
|
|||||||
|
|
||||||
issue_1758: {
|
issue_1758: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
}
|
}
|
||||||
@@ -898,6 +910,7 @@ issue_1758: {
|
|||||||
|
|
||||||
issue_2535: {
|
issue_2535: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
@@ -919,6 +932,7 @@ issue_2535: {
|
|||||||
|
|
||||||
issue_1750: {
|
issue_1750: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
@@ -963,6 +977,7 @@ drop_switch_1: {
|
|||||||
|
|
||||||
drop_switch_2: {
|
drop_switch_2: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
}
|
}
|
||||||
@@ -1007,6 +1022,7 @@ drop_switch_3: {
|
|||||||
|
|
||||||
drop_switch_4: {
|
drop_switch_4: {
|
||||||
options = {
|
options = {
|
||||||
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
}
|
}
|
||||||
@@ -1028,3 +1044,140 @@ drop_switch_4: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drop_switch_5: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (A) {
|
||||||
|
case B:
|
||||||
|
x();
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
switch (C) {
|
||||||
|
default:
|
||||||
|
y();
|
||||||
|
case D:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
A === B && x();
|
||||||
|
C !== D && y();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_switch_6: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (A) {
|
||||||
|
case B:
|
||||||
|
default:
|
||||||
|
x();
|
||||||
|
}
|
||||||
|
switch (C) {
|
||||||
|
default:
|
||||||
|
case D:
|
||||||
|
y();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
A === B;
|
||||||
|
x();
|
||||||
|
C !== D;
|
||||||
|
y();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_switch_7: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (A) {
|
||||||
|
case B:
|
||||||
|
w();
|
||||||
|
default:
|
||||||
|
x();
|
||||||
|
}
|
||||||
|
switch (C) {
|
||||||
|
default:
|
||||||
|
y();
|
||||||
|
case D:
|
||||||
|
z();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
A === B && w();
|
||||||
|
x();
|
||||||
|
C !== D && y();
|
||||||
|
z();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_switch_8: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (A) {
|
||||||
|
case B:
|
||||||
|
w();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
x();
|
||||||
|
}
|
||||||
|
switch (C) {
|
||||||
|
default:
|
||||||
|
y();
|
||||||
|
break;
|
||||||
|
case D:
|
||||||
|
z();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(A === B ? w : x)();
|
||||||
|
(C !== D ? y : z)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4059: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (0) {
|
||||||
|
default:
|
||||||
|
case 1:
|
||||||
|
break;
|
||||||
|
case a:
|
||||||
|
break;
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch (0) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case a:
|
||||||
|
break;
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
4
test/input/invalid/switch.js
Normal file
4
test/input/invalid/switch.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
switch (0) {
|
||||||
|
default:
|
||||||
|
default:
|
||||||
|
}
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
new function(){console.log(3)};
|
console.log(3);
|
||||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSJ9
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUEwQkEsUUFBUUMsSUFBSSJ9
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
new function(){console.log(3)};
|
console.log(3);
|
||||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSJ9
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUEwQkEsUUFBUUMsSUFBSSJ9
|
||||||
|
|||||||
5
test/input/reduce/diff_error.js
Normal file
5
test/input/reduce/diff_error.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
(function f(a) {
|
||||||
|
do {
|
||||||
|
console.log(f.length);
|
||||||
|
} while (console.log(f += 0));
|
||||||
|
})();
|
||||||
19
test/input/reduce/diff_error.reduced.js
Normal file
19
test/input/reduce/diff_error.reduced.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// (beautified)
|
||||||
|
(function f(a) {
|
||||||
|
do {
|
||||||
|
console.log(f.length);
|
||||||
|
} while (console.log(f += 0));
|
||||||
|
})();
|
||||||
|
// output: 1
|
||||||
|
// function(){}0
|
||||||
|
//
|
||||||
|
// minify: 0
|
||||||
|
// function(){}0
|
||||||
|
//
|
||||||
|
// options: {
|
||||||
|
// "compress": {
|
||||||
|
// "keep_fargs": false,
|
||||||
|
// "unsafe": true
|
||||||
|
// },
|
||||||
|
// "mangle": false
|
||||||
|
// }
|
||||||
@@ -1,9 +1,3 @@
|
|||||||
var o = this;
|
UNUSED: {
|
||||||
|
console.log(0 - .1 - .1 - .1);
|
||||||
for (var k in o) L17060: {
|
|
||||||
a++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var a;
|
|
||||||
|
|
||||||
console.log(k);
|
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
// (beautified)
|
// (beautified)
|
||||||
var o = this;
|
console.log(0 - 1 - .1 - .1);
|
||||||
|
// output: -1.2000000000000002
|
||||||
for (var k in o) {}
|
|
||||||
|
|
||||||
var a;
|
|
||||||
|
|
||||||
console.log(k);
|
|
||||||
// output: a
|
|
||||||
//
|
//
|
||||||
// minify: k
|
// minify: -1.2
|
||||||
//
|
//
|
||||||
// options: {
|
// options: {
|
||||||
|
// "compress": {
|
||||||
|
// "unsafe_math": true
|
||||||
|
// },
|
||||||
// "mangle": false
|
// "mangle": false
|
||||||
// }
|
// }
|
||||||
@@ -249,7 +249,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should work with `--output-opts`", function(done) {
|
it("Should work with `--output-opts`", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/issue-1482/input.js -O';
|
var command = uglifyjscmd + ' test/input/issue-1482/input.js -O ascii_only';
|
||||||
exec(command, function(err, stdout) {
|
exec(command, function(err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, read("test/input/issue-1482/default.js"));
|
assert.strictEqual(stdout, read("test/input/issue-1482/default.js"));
|
||||||
@@ -257,7 +257,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should fail when both --beautify & --output-opts are specified", function(done) {
|
it("Should fail when both --beautify & --output-opts are specified", function(done) {
|
||||||
var command = uglifyjscmd + " test/input/issue-520/input.js -bO";
|
var command = uglifyjscmd + " test/input/issue-520/input.js -bO ascii_only";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stderr, "ERROR: --beautify cannot be used with --output-opts\n");
|
assert.strictEqual(stderr, "ERROR: --beautify cannot be used with --output-opts\n");
|
||||||
@@ -330,7 +330,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should fail with invalid syntax", function(done) {
|
it("Should fail with invalid syntax", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/simple.js';
|
var command = uglifyjscmd + " test/input/invalid/simple.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
var lines = stderr.split(/\n/);
|
var lines = stderr.split(/\n/);
|
||||||
@@ -342,7 +342,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should fail with correct marking of tabs", function(done) {
|
it("Should fail with correct marking of tabs", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/tab.js';
|
var command = uglifyjscmd + " test/input/invalid/tab.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
var lines = stderr.split(/\n/);
|
var lines = stderr.split(/\n/);
|
||||||
@@ -354,7 +354,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should fail with correct marking at start of line", function(done) {
|
it("Should fail with correct marking at start of line", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/eof.js';
|
var command = uglifyjscmd + " test/input/invalid/eof.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
var lines = stderr.split(/\n/);
|
var lines = stderr.split(/\n/);
|
||||||
@@ -366,7 +366,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should fail with a missing loop body", function(done) {
|
it("Should fail with a missing loop body", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/loop-no-body.js';
|
var command = uglifyjscmd + " test/input/invalid/loop-no-body.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
var lines = stderr.split(/\n/);
|
var lines = stderr.split(/\n/);
|
||||||
@@ -378,7 +378,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (5--)", function(done) {
|
it("Should throw syntax error (5--)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/assign_1.js';
|
var command = uglifyjscmd + " test/input/invalid/assign_1.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -392,7 +392,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (Math.random() /= 2)", function(done) {
|
it("Should throw syntax error (Math.random() /= 2)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/assign_2.js';
|
var command = uglifyjscmd + " test/input/invalid/assign_2.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -406,7 +406,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (++this)", function(done) {
|
it("Should throw syntax error (++this)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/assign_3.js';
|
var command = uglifyjscmd + " test/input/invalid/assign_3.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -420,7 +420,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (++null)", function(done) {
|
it("Should throw syntax error (++null)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/assign_4.js';
|
var command = uglifyjscmd + " test/input/invalid/assign_4.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -434,7 +434,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (a.=)", function(done) {
|
it("Should throw syntax error (a.=)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/dot_1.js';
|
var command = uglifyjscmd + " test/input/invalid/dot_1.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -448,7 +448,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (%.a)", function(done) {
|
it("Should throw syntax error (%.a)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/dot_2.js';
|
var command = uglifyjscmd + " test/input/invalid/dot_2.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -462,7 +462,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (a./();)", function(done) {
|
it("Should throw syntax error (a./();)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/dot_3.js';
|
var command = uglifyjscmd + " test/input/invalid/dot_3.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -476,7 +476,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error ({%: 1})", function(done) {
|
it("Should throw syntax error ({%: 1})", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/object.js';
|
var command = uglifyjscmd + " test/input/invalid/object.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -490,7 +490,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (delete x)", function(done) {
|
it("Should throw syntax error (delete x)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/delete.js';
|
var command = uglifyjscmd + " test/input/invalid/delete.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -504,7 +504,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (function g(arguments))", function(done) {
|
it("Should throw syntax error (function g(arguments))", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/function_1.js';
|
var command = uglifyjscmd + " test/input/invalid/function_1.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -518,7 +518,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (function eval())", function(done) {
|
it("Should throw syntax error (function eval())", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/function_2.js';
|
var command = uglifyjscmd + " test/input/invalid/function_2.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -532,7 +532,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (iife arguments())", function(done) {
|
it("Should throw syntax error (iife arguments())", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/function_3.js';
|
var command = uglifyjscmd + " test/input/invalid/function_3.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -546,7 +546,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (catch (eval))", function(done) {
|
it("Should throw syntax error (catch (eval))", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/try.js';
|
var command = uglifyjscmd + " test/input/invalid/try.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -560,7 +560,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (var eval)", function(done) {
|
it("Should throw syntax error (var eval)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/var.js';
|
var command = uglifyjscmd + " test/input/invalid/var.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -574,7 +574,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (else)", function(done) {
|
it("Should throw syntax error (else)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/else.js';
|
var command = uglifyjscmd + " test/input/invalid/else.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -588,7 +588,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (return)", function(done) {
|
it("Should throw syntax error (return)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/return.js';
|
var command = uglifyjscmd + " test/input/invalid/return.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -602,7 +602,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (for-in init)", function(done) {
|
it("Should throw syntax error (for-in init)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/for-in_1.js';
|
var command = uglifyjscmd + " test/input/invalid/for-in_1.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -616,7 +616,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (for-in var)", function(done) {
|
it("Should throw syntax error (for-in var)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/for-in_2.js';
|
var command = uglifyjscmd + " test/input/invalid/for-in_2.js";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
@@ -629,6 +629,18 @@ describe("bin/uglifyjs", function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should throw syntax error (switch defaults)", function(done) {
|
||||||
|
var command = uglifyjscmd + " test/input/invalid/switch.js";
|
||||||
|
exec(command, function(err, stdout, stderr) {
|
||||||
|
assert.ok(err);
|
||||||
|
var lines = stderr.split(/\n/);
|
||||||
|
assert.strictEqual(lines[0], "Parse error at test/input/invalid/switch.js:3,2");
|
||||||
|
assert.strictEqual(lines[1], " default:");
|
||||||
|
assert.strictEqual(lines[2], " ^");
|
||||||
|
assert.strictEqual(lines[3], "ERROR: More than one default clause in switch statement");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
it("Should handle literal string as source map input", function(done) {
|
it("Should handle literal string as source map input", function(done) {
|
||||||
var command = [
|
var command = [
|
||||||
uglifyjscmd,
|
uglifyjscmd,
|
||||||
@@ -717,7 +729,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
var command = uglifyjscmd + " test/input/issue-3315/input.js --config-file test/input/issue-3315/config.json";
|
var command = uglifyjscmd + " test/input/issue-3315/input.js --config-file test/input/issue-3315/config.json";
|
||||||
exec(command, function(err, stdout) {
|
exec(command, function(err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, 'function f(){"aaaaaaaaaa";var a={prop:1,a:2};return a.prop+a.a}\n');
|
assert.strictEqual(stdout, 'function f(){"aaaaaaaaaa";var a={prop:1,t:2};return a.prop+a.t}\n');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -28,4 +28,65 @@ describe("Number literals", function() {
|
|||||||
assert.throws(test(inputs[i]), error, inputs[i]);
|
assert.throws(test(inputs[i]), error, inputs[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
it("Should parse binary, hexadecimal, octal and underscore correctly", function() {
|
||||||
|
[
|
||||||
|
"42",
|
||||||
|
"4_2",
|
||||||
|
"052",
|
||||||
|
"0o52",
|
||||||
|
"0O52",
|
||||||
|
"0o5_2",
|
||||||
|
"0x2a",
|
||||||
|
"0X2A",
|
||||||
|
"0x2_a",
|
||||||
|
"0b101010",
|
||||||
|
"0B101010",
|
||||||
|
"0b101_010",
|
||||||
|
"0.0000000042e+10",
|
||||||
|
"0.0000000042E+10",
|
||||||
|
"0.0_000000042e+10",
|
||||||
|
"0.0000000042e+1_0",
|
||||||
|
"0.000_000_004_2e+1_0",
|
||||||
|
"0.000_000_004_2e+1_0-0B101_010+0x2_A-0o5_2+4_2",
|
||||||
|
].forEach(function(code) {
|
||||||
|
var result = UglifyJS.minify(code, {
|
||||||
|
compress: {
|
||||||
|
expression: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, "42;");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should reject invalid use of underscore", function() {
|
||||||
|
[
|
||||||
|
"_42",
|
||||||
|
"_+42",
|
||||||
|
"+_42",
|
||||||
|
].forEach(function(code) {
|
||||||
|
var node = UglifyJS.parse(code, {
|
||||||
|
expression: true,
|
||||||
|
});
|
||||||
|
assert.ok(!node.is_constant(), code);
|
||||||
|
assert.ok(!(node instanceof UglifyJS.AST_Statement), code);
|
||||||
|
});
|
||||||
|
[
|
||||||
|
"42_",
|
||||||
|
"4__2",
|
||||||
|
"0_52",
|
||||||
|
"05_2",
|
||||||
|
"0_o52",
|
||||||
|
"0o_52",
|
||||||
|
"0.0000000042_e10",
|
||||||
|
"0.0000000042e_10",
|
||||||
|
"0.0000000042e_+10",
|
||||||
|
"0.0000000042e+_10",
|
||||||
|
].forEach(function(code) {
|
||||||
|
assert.throws(function() {
|
||||||
|
UglifyJS.parse(code);
|
||||||
|
}, function(e) {
|
||||||
|
return e instanceof UglifyJS.JS_Parse_Error;
|
||||||
|
}, code);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -486,4 +486,19 @@ describe("operator", function() {
|
|||||||
assert.strictEqual(UglifyJS.parse(exp[0]).print_to_string(), exp[1] + ";");
|
assert.strictEqual(UglifyJS.parse(exp[0]).print_to_string(), exp[1] + ";");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should preserve space between /regex/ and `in`", function() {
|
||||||
|
[
|
||||||
|
"/regex/ in {}",
|
||||||
|
"/regex/g in {}",
|
||||||
|
"0 + /regex/ in {}",
|
||||||
|
"0 + /regex/g in {}",
|
||||||
|
].forEach(function(exp) {
|
||||||
|
var code = UglifyJS.parse(exp).print_to_string();
|
||||||
|
try {
|
||||||
|
assert.strictEqual(UglifyJS.parse(code).print_to_string(), code);
|
||||||
|
} catch (ex) {
|
||||||
|
assert.fail("Failed to reparse: " + exp + "\n" + ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ describe("test/reduce.js", function() {
|
|||||||
});
|
});
|
||||||
it("Should eliminate unreferenced labels", function() {
|
it("Should eliminate unreferenced labels", function() {
|
||||||
var result = reduce_test(read("test/input/reduce/label.js"), {
|
var result = reduce_test(read("test/input/reduce/label.js"), {
|
||||||
|
compress: {
|
||||||
|
unsafe_math: true,
|
||||||
|
},
|
||||||
mangle: false,
|
mangle: false,
|
||||||
}, {
|
}, {
|
||||||
verbose: false,
|
verbose: false,
|
||||||
@@ -296,4 +299,18 @@ describe("test/reduce.js", function() {
|
|||||||
"// }",
|
"// }",
|
||||||
]).join("\n"));
|
]).join("\n"));
|
||||||
});
|
});
|
||||||
|
it("Should handle corner cases when intermediate case differs only in Error.message", function() {
|
||||||
|
if (semver.satisfies(process.version, "<=0.10")) return;
|
||||||
|
var result = reduce_test(read("test/input/reduce/diff_error.js"), {
|
||||||
|
compress: {
|
||||||
|
keep_fargs: false,
|
||||||
|
unsafe: true,
|
||||||
|
},
|
||||||
|
mangle: false,
|
||||||
|
}, {
|
||||||
|
verbose: false,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, read("test/input/reduce/diff_error.reduced.js"));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ describe("With", function() {
|
|||||||
var ast = UglifyJS.parse("with(e) {f(1, 2)}");
|
var ast = UglifyJS.parse("with(e) {f(1, 2)}");
|
||||||
ast.figure_out_scope();
|
ast.figure_out_scope();
|
||||||
assert.equal(ast.uses_with, true);
|
assert.equal(ast.uses_with, true);
|
||||||
assert.equal(ast.body[0].expression.scope.uses_with, true);
|
assert.equal(ast.body[0].expression.scope.resolve().uses_with, true);
|
||||||
assert.equal(ast.body[0].body.body[0].body.expression.scope.uses_with, true);
|
assert.equal(ast.body[0].body.body[0].body.expression.scope.resolve().uses_with, true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
126
test/reduce.js
126
test/reduce.js
@@ -4,19 +4,17 @@ var List = U.List;
|
|||||||
var os = require("os");
|
var os = require("os");
|
||||||
var sandbox = require("./sandbox");
|
var sandbox = require("./sandbox");
|
||||||
|
|
||||||
// Reduce a ufuzz-style `console.log` based test case by iteratively replacing
|
// Reduce a test case by iteratively replacing AST nodes with various
|
||||||
// AST nodes with various permutations. Each AST_Statement in the tree is also
|
// permutations. Each AST_Statement in the tree is also speculatively dropped
|
||||||
// speculatively dropped to determine whether it is needed. If the altered
|
// to determine whether it is needed. If the altered tree and the last known
|
||||||
// tree and the last known good tree produce the same non-nil error-free output
|
// good tree produce the same output after being run, then the permutation
|
||||||
// after being run, then the permutation survives to the next generation and
|
// survives to the next generation and is the basis for subsequent iterations.
|
||||||
// is the basis for subsequent iterations. The test case is reduced as a
|
// The test case is reduced as a consequence of complex expressions being
|
||||||
// consequence of complex expressions being replaced with simpler ones.
|
// replaced with simpler ones. Note that a reduced test case will have
|
||||||
// This function assumes that the testcase will not result in a parse or
|
// different runtime output - it is not functionally equivalent to the
|
||||||
// runtime Error. Note that a reduced test case will have different runtime
|
// original. The only criteria is that once the generated reduced test case is
|
||||||
// output - it is not functionally equivalent to the original. The only criteria
|
// run without minification, it will produce different output from the code
|
||||||
// is that once the generated reduced test case is run without minification, it
|
// minified with `minify_options`. Returns a `minify` result object.
|
||||||
// will produce different output from the code minified with `minify_options`.
|
|
||||||
// Returns a `minify` result object with an additonal boolean property `reduced`.
|
|
||||||
|
|
||||||
Error.stackTraceLimit = Infinity;
|
Error.stackTraceLimit = Infinity;
|
||||||
module.exports = function reduce_test(testcase, minify_options, reduce_options) {
|
module.exports = function reduce_test(testcase, minify_options, reduce_options) {
|
||||||
@@ -114,19 +112,18 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
// no structural AST changes before this point.
|
// no structural AST changes before this point.
|
||||||
if (node.start._permute >= REPLACEMENTS.length) return;
|
if (node.start._permute >= REPLACEMENTS.length) return;
|
||||||
|
|
||||||
if (parent instanceof U.AST_Assign
|
|
||||||
&& parent.left === node
|
|
||||||
|| parent instanceof U.AST_Unary
|
|
||||||
&& parent.expression === node
|
|
||||||
&& ["++", "--", "delete"].indexOf(parent.operator) >= 0) {
|
|
||||||
// ignore lvalues
|
// ignore lvalues
|
||||||
|
if (parent instanceof U.AST_Assign && parent.left === node) return;
|
||||||
|
if (parent instanceof U.AST_Unary && parent.expression === node) switch (parent.operator) {
|
||||||
|
case "++":
|
||||||
|
case "--":
|
||||||
|
case "delete":
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((parent instanceof U.AST_For || parent instanceof U.AST_ForIn)
|
// preserve for (var xxx; ...)
|
||||||
&& parent.init === node && node instanceof U.AST_Var) {
|
if (parent instanceof U.AST_For && parent.init === node && node instanceof U.AST_Var) return node;
|
||||||
// preserve for (var ...)
|
// preserve for (xxx in ...)
|
||||||
return node;
|
if (parent instanceof U.AST_ForIn && parent.init === node) return node;
|
||||||
}
|
|
||||||
|
|
||||||
// node specific permutations with no parent logic
|
// node specific permutations with no parent logic
|
||||||
|
|
||||||
@@ -430,7 +427,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
if (node.TYPE == "Call" && node.expression.print_to_string() == "console.log") {
|
if (node.TYPE == "Call" && node.expression.print_to_string() == "console.log") {
|
||||||
return to_sequence(node.args);
|
return to_sequence(node.args);
|
||||||
}
|
}
|
||||||
if (node instanceof U.AST_Catch) {
|
if (node instanceof U.AST_Catch && node.argname) {
|
||||||
descend(node, this);
|
descend(node, this);
|
||||||
node.body.unshift(new U.AST_SimpleStatement({
|
node.body.unshift(new U.AST_SimpleStatement({
|
||||||
body: wrap_with_console_log(new U.AST_SymbolRef(node.argname)),
|
body: wrap_with_console_log(new U.AST_SymbolRef(node.argname)),
|
||||||
@@ -440,7 +437,8 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
var code = testcase_ast.print_to_string();
|
var code = testcase_ast.print_to_string();
|
||||||
if (diff = test_for_diff(code, minify_options, result_cache, max_timeout)) {
|
var diff = test_for_diff(code, minify_options, result_cache, max_timeout);
|
||||||
|
if (diff && !diff.timed_out && !diff.error) {
|
||||||
testcase = code;
|
testcase = code;
|
||||||
differs = diff;
|
differs = diff;
|
||||||
} else {
|
} else {
|
||||||
@@ -453,6 +451,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
node.start = JSON.parse(JSON.stringify(node.start));
|
node.start = JSON.parse(JSON.stringify(node.start));
|
||||||
node.start._permute = 0;
|
node.start._permute = 0;
|
||||||
}));
|
}));
|
||||||
|
var before_iterations = testcase;
|
||||||
for (var c = 0; c < max_iterations; ++c) {
|
for (var c = 0; c < max_iterations; ++c) {
|
||||||
if (verbose && pass == 1 && c % 25 == 0) {
|
if (verbose && pass == 1 && c % 25 == 0) {
|
||||||
log("// reduce test pass " + pass + ", iteration " + c + ": " + testcase.length + " bytes");
|
log("// reduce test pass " + pass + ", iteration " + c + ": " + testcase.length + " bytes");
|
||||||
@@ -495,12 +494,31 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c == 0) break;
|
if (before_iterations === testcase) break;
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
log("// reduce test pass " + pass + ": " + testcase.length + " bytes");
|
log("// reduce test pass " + pass + ": " + testcase.length + " bytes");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
testcase = try_beautify(testcase, minify_options, differs.unminified_result, result_cache, max_timeout);
|
var beautified = U.minify(testcase, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
beautify: true,
|
||||||
|
braces: true,
|
||||||
|
comments: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
testcase = {
|
||||||
|
code: testcase,
|
||||||
|
};
|
||||||
|
if (!beautified.error) {
|
||||||
|
diff = test_for_diff(beautified.code, minify_options, result_cache, max_timeout);
|
||||||
|
if (diff && !diff.timed_out && !diff.error) {
|
||||||
|
testcase = beautified;
|
||||||
|
testcase.code = "// (beautified)\n" + testcase.code;
|
||||||
|
differs = diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
var lines = [ "" ];
|
var lines = [ "" ];
|
||||||
if (isNaN(max_timeout)) {
|
if (isNaN(max_timeout)) {
|
||||||
lines.push("// minify error: " + to_comment(strip_color_codes(differs.minified_result.stack)));
|
lines.push("// minify error: " + to_comment(strip_color_codes(differs.minified_result.stack)));
|
||||||
@@ -539,34 +557,6 @@ function trim_trailing_whitespace(value) {
|
|||||||
return ("" + value).replace(/\s+$/, "");
|
return ("" + value).replace(/\s+$/, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
function try_beautify(testcase, minify_options, expected, result_cache, timeout) {
|
|
||||||
var result = U.minify(testcase, {
|
|
||||||
compress: false,
|
|
||||||
mangle: false,
|
|
||||||
output: {
|
|
||||||
beautify: true,
|
|
||||||
braces: true,
|
|
||||||
comments: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (result.error) return {
|
|
||||||
code: testcase,
|
|
||||||
};
|
|
||||||
var toplevel = sandbox.has_toplevel(minify_options);
|
|
||||||
if (isNaN(timeout)) {
|
|
||||||
if (!U.minify(result.code, minify_options).error) return {
|
|
||||||
code: testcase,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
var actual = run_code(result.code, toplevel, result_cache, timeout);
|
|
||||||
if (!sandbox.same_stdout(expected, actual)) return {
|
|
||||||
code: testcase,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
result.code = "// (beautified)\n" + result.code;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function has_exit(fn) {
|
function has_exit(fn) {
|
||||||
var found = false;
|
var found = false;
|
||||||
var tw = new U.TreeWalker(function(node) {
|
var tw = new U.TreeWalker(function(node) {
|
||||||
@@ -651,7 +641,15 @@ function wrap_with_console_log(node) {
|
|||||||
|
|
||||||
function run_code(code, toplevel, result_cache, timeout) {
|
function run_code(code, toplevel, result_cache, timeout) {
|
||||||
var key = crypto.createHash("sha1").update(code).digest("base64");
|
var key = crypto.createHash("sha1").update(code).digest("base64");
|
||||||
return result_cache[key] || (result_cache[key] = sandbox.run_code(code, toplevel, timeout));
|
var value = result_cache[key];
|
||||||
|
if (!value) {
|
||||||
|
var start = Date.now();
|
||||||
|
result_cache[key] = value = {
|
||||||
|
result: sandbox.run_code(code, toplevel, timeout),
|
||||||
|
elapsed: Date.now() - start,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function compare_run_code(code, minify_options, result_cache, max_timeout) {
|
function compare_run_code(code, minify_options, result_cache, max_timeout) {
|
||||||
@@ -659,21 +657,19 @@ function compare_run_code(code, minify_options, result_cache, max_timeout) {
|
|||||||
if (minified.error) return minified;
|
if (minified.error) return minified;
|
||||||
|
|
||||||
var toplevel = sandbox.has_toplevel(minify_options);
|
var toplevel = sandbox.has_toplevel(minify_options);
|
||||||
var elapsed = Date.now();
|
var unminified = run_code(code, toplevel, result_cache, max_timeout);
|
||||||
var unminified_result = run_code(code, toplevel, result_cache, max_timeout);
|
var timeout = Math.min(100 * unminified.elapsed, max_timeout);
|
||||||
elapsed = Date.now() - elapsed;
|
var minified_result = run_code(minified.code, toplevel, result_cache, timeout).result;
|
||||||
var timeout = Math.min(100 * elapsed, max_timeout);
|
|
||||||
var minified_result = run_code(minified.code, toplevel, result_cache, timeout);
|
|
||||||
|
|
||||||
if (sandbox.same_stdout(unminified_result, minified_result)) {
|
if (sandbox.same_stdout(unminified.result, minified_result)) {
|
||||||
return is_timed_out(unminified_result) && is_timed_out(minified_result) && {
|
return is_timed_out(unminified.result) && is_timed_out(minified_result) && {
|
||||||
timed_out: true,
|
timed_out: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
unminified_result: unminified_result,
|
unminified_result: unminified.result,
|
||||||
minified_result: minified_result,
|
minified_result: minified_result,
|
||||||
elapsed: elapsed,
|
elapsed: unminified.elapsed,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ require("./run")([
|
|||||||
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
|
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
|
||||||
].map(function(options) {
|
].map(function(options) {
|
||||||
var args = options.split(/ /);
|
var args = options.split(/ /);
|
||||||
args.unshift("test/benchmark.js");
|
args.unshift("test/benchmark.js", "--validate");
|
||||||
return args;
|
return args;
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ function createContext() {
|
|||||||
arg.constructor.toString();
|
arg.constructor.toString();
|
||||||
if (level--) for (var key in arg) {
|
if (level--) for (var key in arg) {
|
||||||
var desc = Object.getOwnPropertyDescriptor(arg, key);
|
var desc = Object.getOwnPropertyDescriptor(arg, key);
|
||||||
if (!desc || !desc.get) arg[key] = safe_log(arg[key], level);
|
if (!desc || !desc.get && !desc.set) arg[key] = safe_log(arg[key], level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return arg;
|
return arg;
|
||||||
|
|||||||
67
test/ufuzz/actions.js
Normal file
67
test/ufuzz/actions.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
var get = require("https").get;
|
||||||
|
var parse = require("url").parse;
|
||||||
|
|
||||||
|
var base, token, run_number, eldest = true;
|
||||||
|
exports.init = function(url, auth, num) {
|
||||||
|
base = url;
|
||||||
|
token = auth;
|
||||||
|
run_number = num;
|
||||||
|
};
|
||||||
|
exports.should_stop = function(callback) {
|
||||||
|
read(base + "/actions/runs?per_page=100", function(reply) {
|
||||||
|
if (!reply || !Array.isArray(reply.workflow_runs)) return;
|
||||||
|
var runs = reply.workflow_runs.filter(function(workflow) {
|
||||||
|
return workflow.status != "completed";
|
||||||
|
}).sort(function(a, b) {
|
||||||
|
return b.run_number - a.run_number;
|
||||||
|
});
|
||||||
|
var found = false, remaining = 20;
|
||||||
|
(function next() {
|
||||||
|
if (!runs.length) return;
|
||||||
|
var workflow = runs.pop();
|
||||||
|
if (workflow.event == "schedule" && workflow.run_number == run_number) found = true;
|
||||||
|
read(workflow.jobs_url, function(reply) {
|
||||||
|
if (!reply || !Array.isArray(reply.jobs)) return;
|
||||||
|
if (!reply.jobs.every(function(job) {
|
||||||
|
if (job.status == "completed") return true;
|
||||||
|
remaining--;
|
||||||
|
return found || workflow.event != "schedule";
|
||||||
|
})) return;
|
||||||
|
if (remaining >= 0) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function read(url, callback) {
|
||||||
|
var done = function(reply) {
|
||||||
|
done = function() {};
|
||||||
|
callback(reply);
|
||||||
|
};
|
||||||
|
var options = parse(url);
|
||||||
|
options.headers = {
|
||||||
|
"Authorization": "Token " + token,
|
||||||
|
"User-Agent": "UglifyJS",
|
||||||
|
};
|
||||||
|
get(options, function(response) {
|
||||||
|
var chunks = [];
|
||||||
|
response.setEncoding("utf8");
|
||||||
|
response.on("data", function(chunk) {
|
||||||
|
chunks.push(chunk);
|
||||||
|
}).on("end", function() {
|
||||||
|
var reply;
|
||||||
|
try {
|
||||||
|
reply = JSON.parse(chunks.join(""))
|
||||||
|
} catch (e) {}
|
||||||
|
done(reply);
|
||||||
|
}).on("error", function() {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}).on("error", function() {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -168,7 +168,7 @@ var VALUES = [
|
|||||||
"this",
|
"this",
|
||||||
];
|
];
|
||||||
|
|
||||||
var BINARY_OPS_NO_COMMA = [
|
var BINARY_OPS = [
|
||||||
" + ", // spaces needed to disambiguate with ++ cases (could otherwise cause syntax errors)
|
" + ", // spaces needed to disambiguate with ++ cases (could otherwise cause syntax errors)
|
||||||
" - ",
|
" - ",
|
||||||
"/",
|
"/",
|
||||||
@@ -190,9 +190,15 @@ var BINARY_OPS_NO_COMMA = [
|
|||||||
"%",
|
"%",
|
||||||
"&&",
|
"&&",
|
||||||
"||",
|
"||",
|
||||||
"^" ];
|
"^",
|
||||||
|
",",
|
||||||
var BINARY_OPS = [","].concat(BINARY_OPS_NO_COMMA);
|
];
|
||||||
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
|
BINARY_OPS.push(" in ");
|
||||||
|
|
||||||
var ASSIGNMENTS = [
|
var ASSIGNMENTS = [
|
||||||
"=",
|
"=",
|
||||||
@@ -490,11 +496,16 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
var label = createLabel(canBreak, canContinue);
|
var label = createLabel(canBreak, canContinue);
|
||||||
canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);
|
canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);
|
||||||
canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);
|
canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);
|
||||||
var optElementVar = "";
|
var key = rng(10) ? "key" + loop : getVarName();
|
||||||
if (rng(5) > 1) {
|
return [
|
||||||
optElementVar = "c = 1 + c; var " + createVarName(MANDATORY) + " = expr" + loop + "[key" + loop + "]; ";
|
"{var expr" + loop + " = " + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "; ",
|
||||||
}
|
label.target + " for (",
|
||||||
return "{var expr" + loop + " = " + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "; " + label.target + " for (var key" + loop + " in expr" + loop + ") {" + optElementVar + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + "}}";
|
/^key/.test(key) ? "var " : "",
|
||||||
|
key + " in expr" + loop + ") {",
|
||||||
|
rng(5) > 1 ? "c = 1 + c; var " + createVarName(MANDATORY) + " = expr" + loop + "[" + key + "]; " : "",
|
||||||
|
createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),
|
||||||
|
"}}",
|
||||||
|
].join("");
|
||||||
case STMT_SEMI:
|
case STMT_SEMI:
|
||||||
return use_strict && rng(20) === 0 ? '"use strict";' : ";";
|
return use_strict && rng(20) === 0 ? '"use strict";' : ";";
|
||||||
case STMT_EXPR:
|
case STMT_EXPR:
|
||||||
@@ -762,6 +773,10 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
return createArrayLiteral(recurmax, stmtDepth, canThrow) + "." + getDotKey();
|
return createArrayLiteral(recurmax, stmtDepth, canThrow) + "." + getDotKey();
|
||||||
case p++:
|
case p++:
|
||||||
return createObjectLiteral(recurmax, stmtDepth, canThrow) + "." + getDotKey();
|
return createObjectLiteral(recurmax, stmtDepth, canThrow) + "." + getDotKey();
|
||||||
|
case p++:
|
||||||
|
return createValue() + " in " + createArrayLiteral(recurmax, stmtDepth, canThrow);
|
||||||
|
case p++:
|
||||||
|
return createValue() + " in " + createObjectLiteral(recurmax, stmtDepth, canThrow);
|
||||||
case p++:
|
case p++:
|
||||||
var name = getVarName();
|
var name = getVarName();
|
||||||
var s = name + "[" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]";
|
var s = name + "[" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]";
|
||||||
@@ -879,7 +894,7 @@ function createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
}
|
}
|
||||||
function _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
function _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
return "(" + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow)
|
return "(" + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow)
|
||||||
+ createBinaryOp(noComma) + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ")";
|
+ createBinaryOp(noComma, canThrow) + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ")";
|
||||||
}
|
}
|
||||||
function _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
function _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
// intentionally generate more hardcore ops
|
// intentionally generate more hardcore ops
|
||||||
@@ -929,9 +944,12 @@ function createValue() {
|
|||||||
return VALUES[rng(VALUES.length)];
|
return VALUES[rng(VALUES.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
function createBinaryOp(noComma) {
|
function createBinaryOp(noComma, canThrow) {
|
||||||
if (noComma) return BINARY_OPS_NO_COMMA[rng(BINARY_OPS_NO_COMMA.length)];
|
var op;
|
||||||
return BINARY_OPS[rng(BINARY_OPS.length)];
|
do {
|
||||||
|
op = BINARY_OPS[rng(BINARY_OPS.length)];
|
||||||
|
} while (noComma && op == "," || !canThrow && op == " in ");
|
||||||
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAssignment() {
|
function createAssignment() {
|
||||||
@@ -1018,6 +1036,7 @@ function log_suspects(minify_options, component) {
|
|||||||
if (!options) return;
|
if (!options) return;
|
||||||
if (typeof options != "object") options = {};
|
if (typeof options != "object") options = {};
|
||||||
var defs = default_options[component];
|
var defs = default_options[component];
|
||||||
|
var toplevel = sandbox.has_toplevel(minify_options);
|
||||||
var suspects = Object.keys(defs).filter(function(name) {
|
var suspects = Object.keys(defs).filter(function(name) {
|
||||||
var flip = name == "keep_fargs";
|
var flip = name == "keep_fargs";
|
||||||
if (flip !== (name in options ? options : defs)[name]) {
|
if (flip !== (name in options ? options : defs)[name]) {
|
||||||
@@ -1025,12 +1044,15 @@ function log_suspects(minify_options, component) {
|
|||||||
var o = JSON.parse(JSON.stringify(options));
|
var o = JSON.parse(JSON.stringify(options));
|
||||||
o[name] = flip;
|
o[name] = flip;
|
||||||
m[component] = o;
|
m[component] = o;
|
||||||
|
m.validate = true;
|
||||||
var result = UglifyJS.minify(original_code, m);
|
var result = UglifyJS.minify(original_code, m);
|
||||||
if (result.error) {
|
if (typeof uglify_code != "string") {
|
||||||
|
return !sandbox.same_stdout(uglify_code, result.error);
|
||||||
|
} else if (result.error) {
|
||||||
errorln("Error testing options." + component + "." + name);
|
errorln("Error testing options." + component + "." + name);
|
||||||
errorln(result.error);
|
errorln(result.error);
|
||||||
} else {
|
} else {
|
||||||
var r = sandbox.run_code(result.code, sandbox.has_toplevel(m));
|
var r = sandbox.run_code(result.code, toplevel);
|
||||||
return !sandbox.same_stdout(uglify_result, r);
|
return !sandbox.same_stdout(uglify_result, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1044,18 +1066,21 @@ function log_suspects(minify_options, component) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function log_suspects_global(options) {
|
function log_suspects_global(options, toplevel) {
|
||||||
var suspects = Object.keys(default_options).filter(function(component) {
|
var suspects = Object.keys(default_options).filter(function(component) {
|
||||||
return typeof default_options[component] != "object";
|
return typeof default_options[component] != "object";
|
||||||
}).filter(function(component) {
|
}).filter(function(component) {
|
||||||
var m = JSON.parse(options);
|
var m = JSON.parse(options);
|
||||||
m[component] = false;
|
m[component] = false;
|
||||||
|
m.validate = true;
|
||||||
var result = UglifyJS.minify(original_code, m);
|
var result = UglifyJS.minify(original_code, m);
|
||||||
if (result.error) {
|
if (typeof uglify_code != "string") {
|
||||||
|
return !sandbox.same_stdout(uglify_code, result.error);
|
||||||
|
} else if (result.error) {
|
||||||
errorln("Error testing options." + component);
|
errorln("Error testing options." + component);
|
||||||
errorln(result.error);
|
errorln(result.error);
|
||||||
} else {
|
} else {
|
||||||
var r = sandbox.run_code(result.code, sandbox.has_toplevel(m));
|
var r = sandbox.run_code(result.code, toplevel);
|
||||||
return !sandbox.same_stdout(uglify_result, r);
|
return !sandbox.same_stdout(uglify_result, r);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1074,7 +1099,37 @@ function log(options) {
|
|||||||
errorln("//=============================================================");
|
errorln("//=============================================================");
|
||||||
if (!ok) errorln("// !!!!!! Failed... round " + round);
|
if (!ok) errorln("// !!!!!! Failed... round " + round);
|
||||||
errorln("// original code");
|
errorln("// original code");
|
||||||
try_beautify(original_code, toplevel, original_result, errorln);
|
var beautified = UglifyJS.minify(original_code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
beautify: true,
|
||||||
|
braces: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (beautified.error) {
|
||||||
|
errorln("// !!! beautify failed !!!");
|
||||||
|
errorln(beautified.error);
|
||||||
|
errorln("//");
|
||||||
|
errorln(original_code);
|
||||||
|
} else {
|
||||||
|
var uglified = UglifyJS.minify(beautified.code, JSON.parse(options));
|
||||||
|
var expected, actual;
|
||||||
|
if (typeof uglify_code != "string" || uglified.error) {
|
||||||
|
expected = uglify_code;
|
||||||
|
actual = uglified.error;
|
||||||
|
} else {
|
||||||
|
expected = uglify_result;
|
||||||
|
actual = sandbox.run_code(uglified.code, toplevel);
|
||||||
|
}
|
||||||
|
if (sandbox.same_stdout(expected, actual)) {
|
||||||
|
errorln("// (beautified)");
|
||||||
|
errorln(beautified.code);
|
||||||
|
} else {
|
||||||
|
errorln("//");
|
||||||
|
errorln(original_code);
|
||||||
|
}
|
||||||
|
}
|
||||||
errorln();
|
errorln();
|
||||||
errorln();
|
errorln();
|
||||||
errorln("//-------------------------------------------------------------");
|
errorln("//-------------------------------------------------------------");
|
||||||
@@ -1087,18 +1142,6 @@ function log(options) {
|
|||||||
errorln(original_result);
|
errorln(original_result);
|
||||||
errorln("uglified result:");
|
errorln("uglified result:");
|
||||||
errorln(uglify_result);
|
errorln(uglify_result);
|
||||||
errorln("//-------------------------------------------------------------");
|
|
||||||
var reduced = reduce_test(original_code, JSON.parse(options), {
|
|
||||||
verbose: false,
|
|
||||||
}).code;
|
|
||||||
if (reduced) {
|
|
||||||
errorln();
|
|
||||||
errorln("// reduced test case (output will differ)");
|
|
||||||
errorln();
|
|
||||||
errorln(reduced);
|
|
||||||
errorln();
|
|
||||||
errorln("//-------------------------------------------------------------");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
errorln("// !!! uglify failed !!!");
|
errorln("// !!! uglify failed !!!");
|
||||||
errorln(uglify_code);
|
errorln(uglify_code);
|
||||||
@@ -1109,19 +1152,38 @@ function log(options) {
|
|||||||
errorln(original_result);
|
errorln(original_result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
errorln("//-------------------------------------------------------------");
|
||||||
|
var reduce_options = JSON.parse(options);
|
||||||
|
reduce_options.validate = true;
|
||||||
|
var reduced = reduce_test(original_code, reduce_options, {
|
||||||
|
verbose: false,
|
||||||
|
}).code;
|
||||||
|
if (reduced) {
|
||||||
|
errorln();
|
||||||
|
errorln("// reduced test case (output will differ)");
|
||||||
|
errorln();
|
||||||
|
errorln(reduced);
|
||||||
|
errorln();
|
||||||
|
errorln("//-------------------------------------------------------------");
|
||||||
|
}
|
||||||
errorln("minify(options):");
|
errorln("minify(options):");
|
||||||
errorln(JSON.stringify(JSON.parse(options), null, 2));
|
errorln(JSON.stringify(JSON.parse(options), null, 2));
|
||||||
errorln();
|
errorln();
|
||||||
if (!ok && typeof uglify_code == "string") {
|
if (!ok) {
|
||||||
Object.keys(default_options).filter(function(component) {
|
Object.keys(default_options).filter(function(component) {
|
||||||
var defs = default_options[component];
|
var defs = default_options[component];
|
||||||
return defs && typeof defs == "object";
|
return defs && typeof defs == "object";
|
||||||
}).forEach(log_suspects.bind(null, JSON.parse(options)));
|
}).forEach(log_suspects.bind(null, JSON.parse(options)));
|
||||||
log_suspects_global(options);
|
log_suspects_global(options, toplevel);
|
||||||
errorln("!!!!!! Failed... round " + round);
|
errorln("!!!!!! Failed... round " + round);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sort_globals(code) {
|
||||||
|
var globals = sandbox.run_code("throw Object.keys(this).sort();" + code);
|
||||||
|
return globals.length ? "var " + globals.join(",") + ";" + code : code;
|
||||||
|
}
|
||||||
|
|
||||||
function fuzzy_match(original, uglified) {
|
function fuzzy_match(original, uglified) {
|
||||||
uglified = uglified.split(" ");
|
uglified = uglified.split(" ");
|
||||||
var i = uglified.length;
|
var i = uglified.length;
|
||||||
@@ -1136,35 +1198,64 @@ function fuzzy_match(original, uglified) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function skip_infinite_recursion(orig, toplevel) {
|
function patch_try_catch(orig, toplevel) {
|
||||||
var code = orig;
|
var stack = [ {
|
||||||
var tries = [];
|
code: orig,
|
||||||
var offset = 0;
|
index: 0,
|
||||||
var re = /(?:(?:^|[\s{};])try|}\s*catch\s*\(([^)]+)\)|}\s*finally)\s*(?={)/g;
|
offset: 0,
|
||||||
|
tries: [],
|
||||||
|
} ];
|
||||||
|
var re = /(?:(?:^|[\s{}):;])try|}\s*catch\s*\(([^)]+)\)|}\s*finally)\s*(?={)/g;
|
||||||
|
while (stack.length) {
|
||||||
|
var code = stack[0].code;
|
||||||
|
var offset = stack[0].offset;
|
||||||
|
var tries = stack[0].tries;
|
||||||
var match;
|
var match;
|
||||||
|
re.lastIndex = stack.shift().index;
|
||||||
while (match = re.exec(code)) {
|
while (match = re.exec(code)) {
|
||||||
if (/}\s*finally\s*$/.test(match[0])) {
|
|
||||||
tries.shift();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (tries.length && tries[0].catch) tries.shift();
|
|
||||||
var index = match.index + match[0].length + 1;
|
var index = match.index + match[0].length + 1;
|
||||||
if (/(?:^|[\s{};])try\s*$/.test(match[0])) {
|
if (/(?:^|[\s{}):;])try\s*$/.test(match[0])) {
|
||||||
tries.unshift({ try: index - offset });
|
tries.unshift({ try: index - offset });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tries[0].catch = index;
|
var insert;
|
||||||
var insert = "throw " + match[1] + ".ufuzz_skip || (" + match[1] + ".ufuzz_skip = " + tries[0].try + "), " + match[1] + ";";
|
if (/}\s*finally\s*$/.test(match[0])) {
|
||||||
|
tries.shift();
|
||||||
|
insert = 'if (typeof UFUZZ_ERROR == "object") throw UFUZZ_ERROR;';
|
||||||
|
} else {
|
||||||
|
while (tries.length && tries[0].catch) tries.shift();
|
||||||
|
tries[0].catch = index - offset;
|
||||||
|
insert = [
|
||||||
|
"if (!" + match[1] + ".ufuzz_var) {",
|
||||||
|
match[1] + '.ufuzz_var = "' + match[1] + '";',
|
||||||
|
match[1] + ".ufuzz_try = " + tries[0].try + ";",
|
||||||
|
match[1] + ".ufuzz_catch = " + tries[0].catch + ";",
|
||||||
|
"UFUZZ_ERROR = " + match[1] + ";",
|
||||||
|
"}",
|
||||||
|
"throw " + match[1] + ";",
|
||||||
|
].join("\n");
|
||||||
|
}
|
||||||
var new_code = code.slice(0, index) + insert + code.slice(index);
|
var new_code = code.slice(0, index) + insert + code.slice(index);
|
||||||
var result = sandbox.run_code(new_code, toplevel);
|
var result = sandbox.run_code(new_code, toplevel);
|
||||||
if (typeof result != "object" || typeof result.name != "string" || typeof result.message != "string") {
|
if (typeof result != "object" || typeof result.name != "string" || typeof result.message != "string") {
|
||||||
|
if (!stack.filled && match[1]) stack.push({
|
||||||
|
code: code,
|
||||||
|
index: index && index - 1,
|
||||||
|
offset: offset,
|
||||||
|
tries: JSON.parse(JSON.stringify(tries)),
|
||||||
|
});
|
||||||
offset += insert.length;
|
offset += insert.length;
|
||||||
code = new_code;
|
code = new_code;
|
||||||
|
} else if (result.name == "TypeError" && /'in'/.test(result.message)) {
|
||||||
|
index = result.ufuzz_catch;
|
||||||
|
return orig.slice(0, index) + result.ufuzz_var + ' = new Error("invalid `in`");' + orig.slice(index);
|
||||||
} else if (result.name == "RangeError" && result.message == "Maximum call stack size exceeded") {
|
} else if (result.name == "RangeError" && result.message == "Maximum call stack size exceeded") {
|
||||||
index = result.ufuzz_skip;
|
index = result.ufuzz_try;
|
||||||
return orig.slice(0, index) + 'throw new Error("skipping infinite recursion");' + orig.slice(index);
|
return orig.slice(0, index) + 'throw new Error("skipping infinite recursion");' + orig.slice(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stack.filled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var fallback_options = [ JSON.stringify({
|
var fallback_options = [ JSON.stringify({
|
||||||
@@ -1172,14 +1263,6 @@ var fallback_options = [ JSON.stringify({
|
|||||||
mangle: false
|
mangle: false
|
||||||
}) ];
|
}) ];
|
||||||
var minify_options = require("./options.json").map(JSON.stringify);
|
var minify_options = require("./options.json").map(JSON.stringify);
|
||||||
var sort_globals = [
|
|
||||||
"Object.keys(this).sort().forEach(function(name) {",
|
|
||||||
" var value = this[name];",
|
|
||||||
" delete this[name];",
|
|
||||||
" this[name] = value;",
|
|
||||||
"});",
|
|
||||||
"",
|
|
||||||
].join("\n");
|
|
||||||
var original_code, original_result, errored;
|
var original_code, original_result, errored;
|
||||||
var uglify_code, uglify_result, ok;
|
var uglify_code, uglify_result, ok;
|
||||||
for (var round = 1; round <= num_iterations; round++) {
|
for (var round = 1; round <= num_iterations; round++) {
|
||||||
@@ -1201,7 +1284,7 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
ok = sandbox.same_stdout(original_result, uglify_result);
|
ok = sandbox.same_stdout(original_result, uglify_result);
|
||||||
// ignore declaration order of global variables
|
// ignore declaration order of global variables
|
||||||
if (!ok && !toplevel) {
|
if (!ok && !toplevel) {
|
||||||
ok = sandbox.same_stdout(sandbox.run_code(sort_globals + original_code), sandbox.run_code(sort_globals + uglify_code));
|
ok = sandbox.same_stdout(sandbox.run_code(sort_globals(original_code)), sandbox.run_code(sort_globals(uglify_code)));
|
||||||
}
|
}
|
||||||
// ignore numerical imprecision caused by `unsafe_math`
|
// ignore numerical imprecision caused by `unsafe_math`
|
||||||
if (!ok && typeof uglify_result == "string" && o.compress && o.compress.unsafe_math) {
|
if (!ok && typeof uglify_result == "string" && o.compress && o.compress.unsafe_math) {
|
||||||
@@ -1211,10 +1294,11 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
ok = sandbox.same_stdout(fuzzy_result, uglify_result);
|
ok = sandbox.same_stdout(fuzzy_result, uglify_result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ignore difference in error message caused by `in`
|
||||||
// ignore difference in depth of termination caused by infinite recursion
|
// ignore difference in depth of termination caused by infinite recursion
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
var orig_skipped = skip_infinite_recursion(original_code, toplevel);
|
var orig_skipped = patch_try_catch(original_code, toplevel);
|
||||||
var uglify_skipped = skip_infinite_recursion(uglify_code, toplevel);
|
var uglify_skipped = patch_try_catch(uglify_code, toplevel);
|
||||||
if (orig_skipped && uglify_skipped) {
|
if (orig_skipped && uglify_skipped) {
|
||||||
ok = sandbox.same_stdout(sandbox.run_code(orig_skipped, toplevel), sandbox.run_code(uglify_skipped, toplevel));
|
ok = sandbox.same_stdout(sandbox.run_code(orig_skipped, toplevel), sandbox.run_code(uglify_skipped, toplevel));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,69 @@
|
|||||||
|
var actions = require("./actions");
|
||||||
var child_process = require("child_process");
|
var child_process = require("child_process");
|
||||||
|
|
||||||
var ping = 5 * 60 * 1000;
|
var args = [
|
||||||
var period = +process.argv[2];
|
|
||||||
var endTime = Date.now() + period;
|
|
||||||
for (var i = 0; i < 2; i++) spawn(endTime);
|
|
||||||
|
|
||||||
function spawn(endTime) {
|
|
||||||
var child = child_process.spawn("node", [
|
|
||||||
"--max-old-space-size=2048",
|
"--max-old-space-size=2048",
|
||||||
"test/ufuzz"
|
"test/ufuzz",
|
||||||
], {
|
];
|
||||||
|
var iterations;
|
||||||
|
switch (process.argv.length) {
|
||||||
|
case 3:
|
||||||
|
iterations = +process.argv[2];
|
||||||
|
args.push(iterations);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
actions.init(process.argv[2], process.argv[3], +process.argv[4]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("invalid parameters");
|
||||||
|
}
|
||||||
|
var tasks = [ run(), run() ];
|
||||||
|
if (iterations) return;
|
||||||
|
var alive = setInterval(function() {
|
||||||
|
actions.should_stop(function() {
|
||||||
|
clearInterval(alive);
|
||||||
|
tasks.forEach(function(kill) {
|
||||||
|
kill();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 8 * 60 * 1000);
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
var child, stdout, stderr, log;
|
||||||
|
spawn();
|
||||||
|
return function() {
|
||||||
|
clearInterval(log);
|
||||||
|
child.removeListener("exit", respawn);
|
||||||
|
child.kill();
|
||||||
|
};
|
||||||
|
|
||||||
|
function spawn() {
|
||||||
|
child = child_process.spawn("node", args, {
|
||||||
stdio: [ "ignore", "pipe", "pipe" ]
|
stdio: [ "ignore", "pipe", "pipe" ]
|
||||||
}).on("exit", respawn);
|
}).on("exit", respawn);
|
||||||
var stdout = "";
|
stdout = "";
|
||||||
child.stdout.on("data", function(data) {
|
child.stdout.on("data", function(data) {
|
||||||
stdout += data;
|
stdout += data;
|
||||||
});
|
});
|
||||||
var stderr = "";
|
stderr = "";
|
||||||
child.stderr.on("data", trap).pipe(process.stdout);
|
child.stderr.on("data", trap).pipe(process.stdout);
|
||||||
var keepAlive = setInterval(function() {
|
log = setInterval(function() {
|
||||||
var end = stdout.lastIndexOf("\r");
|
var end = stdout.lastIndexOf("\r");
|
||||||
console.log(stdout.slice(stdout.lastIndexOf("\r", end - 1) + 1, end));
|
console.log(stdout.slice(stdout.lastIndexOf("\r", end - 1) + 1, end));
|
||||||
stdout = stdout.slice(end + 1);
|
stdout = stdout.slice(end + 1);
|
||||||
}, ping);
|
}, 5 * 60 * 1000);
|
||||||
var timer = setTimeout(function() {
|
}
|
||||||
clearInterval(keepAlive);
|
|
||||||
child.removeListener("exit", respawn);
|
|
||||||
child.kill();
|
|
||||||
}, endTime - Date.now());
|
|
||||||
|
|
||||||
function respawn() {
|
function respawn() {
|
||||||
console.log(stdout.replace(/[^\r\n]*\r/g, ""));
|
console.log(stdout.replace(/[^\r\n]*\r/g, ""));
|
||||||
clearInterval(keepAlive);
|
clearInterval(log);
|
||||||
clearTimeout(timer);
|
if (!iterations) {
|
||||||
spawn(endTime);
|
spawn();
|
||||||
|
} else if (process.exitCode) {
|
||||||
|
tasks.forEach(function(kill) {
|
||||||
|
kill();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function trap(data) {
|
function trap(data) {
|
||||||
|
|||||||
456
tools/domprops.html
Normal file
456
tools/domprops.html
Normal file
@@ -0,0 +1,456 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
!function(G) {
|
||||||
|
var domprops = [];
|
||||||
|
var objs = [ G ];
|
||||||
|
var tagNames = [
|
||||||
|
"a",
|
||||||
|
"abbr",
|
||||||
|
"acronym",
|
||||||
|
"address",
|
||||||
|
"applet",
|
||||||
|
"area",
|
||||||
|
"article",
|
||||||
|
"aside",
|
||||||
|
"audio",
|
||||||
|
"b",
|
||||||
|
"base",
|
||||||
|
"basefont",
|
||||||
|
"bdi",
|
||||||
|
"bdo",
|
||||||
|
"bgsound",
|
||||||
|
"big",
|
||||||
|
"blink",
|
||||||
|
"blockquote",
|
||||||
|
"body",
|
||||||
|
"br",
|
||||||
|
"button",
|
||||||
|
"canvas",
|
||||||
|
"caption",
|
||||||
|
"center",
|
||||||
|
"checked",
|
||||||
|
"cite",
|
||||||
|
"code",
|
||||||
|
"col",
|
||||||
|
"colgroup",
|
||||||
|
"command",
|
||||||
|
"comment",
|
||||||
|
"compact",
|
||||||
|
"content",
|
||||||
|
"data",
|
||||||
|
"datalist",
|
||||||
|
"dd",
|
||||||
|
"declare",
|
||||||
|
"defer",
|
||||||
|
"del",
|
||||||
|
"details",
|
||||||
|
"dfn",
|
||||||
|
"dialog",
|
||||||
|
"dir",
|
||||||
|
"disabled",
|
||||||
|
"div",
|
||||||
|
"dl",
|
||||||
|
"dt",
|
||||||
|
"element",
|
||||||
|
"em",
|
||||||
|
"embed",
|
||||||
|
"fieldset",
|
||||||
|
"figcaption",
|
||||||
|
"figure",
|
||||||
|
"font",
|
||||||
|
"footer",
|
||||||
|
"form",
|
||||||
|
"frame",
|
||||||
|
"frameset",
|
||||||
|
"h1",
|
||||||
|
"h2",
|
||||||
|
"h3",
|
||||||
|
"h4",
|
||||||
|
"h5",
|
||||||
|
"h6",
|
||||||
|
"head",
|
||||||
|
"header",
|
||||||
|
"hgroup",
|
||||||
|
"hr",
|
||||||
|
"html",
|
||||||
|
"i",
|
||||||
|
"iframe",
|
||||||
|
"image",
|
||||||
|
"img",
|
||||||
|
"input",
|
||||||
|
"ins",
|
||||||
|
"isindex",
|
||||||
|
"ismap",
|
||||||
|
"kbd",
|
||||||
|
"keygen",
|
||||||
|
"label",
|
||||||
|
"legend",
|
||||||
|
"li",
|
||||||
|
"link",
|
||||||
|
"listing",
|
||||||
|
"main",
|
||||||
|
"map",
|
||||||
|
"mark",
|
||||||
|
"marquee",
|
||||||
|
"math",
|
||||||
|
"menu",
|
||||||
|
"menuitem",
|
||||||
|
"meta",
|
||||||
|
"meter",
|
||||||
|
"multicol",
|
||||||
|
"multiple",
|
||||||
|
"nav",
|
||||||
|
"nextid",
|
||||||
|
"nobr",
|
||||||
|
"noembed",
|
||||||
|
"noframes",
|
||||||
|
"nohref",
|
||||||
|
"noresize",
|
||||||
|
"noscript",
|
||||||
|
"noshade",
|
||||||
|
"nowrap",
|
||||||
|
"object",
|
||||||
|
"ol",
|
||||||
|
"optgroup",
|
||||||
|
"option",
|
||||||
|
"output",
|
||||||
|
"p",
|
||||||
|
"param",
|
||||||
|
"picture",
|
||||||
|
"plaintext",
|
||||||
|
"pre",
|
||||||
|
"progress",
|
||||||
|
"q",
|
||||||
|
"rb",
|
||||||
|
"readonly",
|
||||||
|
"rp",
|
||||||
|
"rt",
|
||||||
|
"rtc",
|
||||||
|
"ruby",
|
||||||
|
"s",
|
||||||
|
"samp",
|
||||||
|
"script",
|
||||||
|
"section",
|
||||||
|
"select",
|
||||||
|
"selected",
|
||||||
|
"shadow",
|
||||||
|
"slot",
|
||||||
|
"small",
|
||||||
|
"source",
|
||||||
|
"spacer",
|
||||||
|
"span",
|
||||||
|
"strike",
|
||||||
|
"strong",
|
||||||
|
"style",
|
||||||
|
"sub",
|
||||||
|
"summary",
|
||||||
|
"sup",
|
||||||
|
"svg",
|
||||||
|
"table",
|
||||||
|
"tbody",
|
||||||
|
"td",
|
||||||
|
"template",
|
||||||
|
"textarea",
|
||||||
|
"tfoot",
|
||||||
|
"th",
|
||||||
|
"thead",
|
||||||
|
"time",
|
||||||
|
"title",
|
||||||
|
"tr",
|
||||||
|
"track",
|
||||||
|
"tt",
|
||||||
|
"u",
|
||||||
|
"ul",
|
||||||
|
"var",
|
||||||
|
"video",
|
||||||
|
"wbr",
|
||||||
|
"xmp",
|
||||||
|
"XXX",
|
||||||
|
];
|
||||||
|
for (var n = 0; n < tagNames.length; n++) {
|
||||||
|
add(document.createElement(tagNames[n]));
|
||||||
|
}
|
||||||
|
var nsNames = {
|
||||||
|
"http://www.w3.org/1998/Math/MathML": [
|
||||||
|
"annotation",
|
||||||
|
"annotation-xml",
|
||||||
|
"maction",
|
||||||
|
"maligngroup",
|
||||||
|
"malignmark",
|
||||||
|
"math",
|
||||||
|
"menclose",
|
||||||
|
"merror",
|
||||||
|
"mfenced",
|
||||||
|
"mfrac",
|
||||||
|
"mglyph",
|
||||||
|
"mi",
|
||||||
|
"mlabeledtr",
|
||||||
|
"mlongdiv",
|
||||||
|
"mmultiscripts",
|
||||||
|
"mn",
|
||||||
|
"mo",
|
||||||
|
"mover",
|
||||||
|
"mpadded",
|
||||||
|
"mphantom",
|
||||||
|
"mprescripts",
|
||||||
|
"mroot",
|
||||||
|
"mrow",
|
||||||
|
"ms",
|
||||||
|
"mscarries",
|
||||||
|
"mscarry",
|
||||||
|
"msgroup",
|
||||||
|
"msline",
|
||||||
|
"mspace",
|
||||||
|
"msqrt",
|
||||||
|
"msrow",
|
||||||
|
"mstack",
|
||||||
|
"mstyle",
|
||||||
|
"msub",
|
||||||
|
"msubsup",
|
||||||
|
"msup",
|
||||||
|
"mtable",
|
||||||
|
"mtd",
|
||||||
|
"mtext",
|
||||||
|
"mtr",
|
||||||
|
"munder",
|
||||||
|
"munderover",
|
||||||
|
"none",
|
||||||
|
"semantics",
|
||||||
|
],
|
||||||
|
"http://www.w3.org/2000/svg": [
|
||||||
|
"a",
|
||||||
|
"altGlyph",
|
||||||
|
"altGlyphDef",
|
||||||
|
"altGlyphItem",
|
||||||
|
"animate",
|
||||||
|
"animateColor",
|
||||||
|
"animateMotion",
|
||||||
|
"animateTransform",
|
||||||
|
"circle",
|
||||||
|
"clipPath",
|
||||||
|
"color-profile",
|
||||||
|
"cursor",
|
||||||
|
"defs",
|
||||||
|
"desc",
|
||||||
|
"discard",
|
||||||
|
"ellipse",
|
||||||
|
"feBlend",
|
||||||
|
"feColorMatrix",
|
||||||
|
"feComponentTransfer",
|
||||||
|
"feComposite",
|
||||||
|
"feConvolveMatrix",
|
||||||
|
"feDiffuseLighting",
|
||||||
|
"feDisplacementMap",
|
||||||
|
"feDistantLight",
|
||||||
|
"feDropShadow",
|
||||||
|
"feFlood",
|
||||||
|
"feFuncA",
|
||||||
|
"feFuncB",
|
||||||
|
"feFuncG",
|
||||||
|
"feFuncR",
|
||||||
|
"feGaussianBlur",
|
||||||
|
"feImage",
|
||||||
|
"feMerge",
|
||||||
|
"feMergeNode",
|
||||||
|
"feMorphology",
|
||||||
|
"feOffset",
|
||||||
|
"fePointLight",
|
||||||
|
"feSpecularLighting",
|
||||||
|
"feSpotLight",
|
||||||
|
"feTile",
|
||||||
|
"feTurbulence",
|
||||||
|
"filter",
|
||||||
|
"font",
|
||||||
|
"font-face",
|
||||||
|
"font-face-format",
|
||||||
|
"font-face-name",
|
||||||
|
"font-face-src",
|
||||||
|
"font-face-uri",
|
||||||
|
"foreignObject",
|
||||||
|
"g",
|
||||||
|
"glyph",
|
||||||
|
"glyphRef",
|
||||||
|
"hatch",
|
||||||
|
"hatchpath",
|
||||||
|
"hkern",
|
||||||
|
"image",
|
||||||
|
"line",
|
||||||
|
"linearGradient",
|
||||||
|
"marker",
|
||||||
|
"mask",
|
||||||
|
"mesh",
|
||||||
|
"meshgradient",
|
||||||
|
"meshpatch",
|
||||||
|
"meshrow",
|
||||||
|
"metadata",
|
||||||
|
"missing-glyph",
|
||||||
|
"mpath",
|
||||||
|
"path",
|
||||||
|
"pattern",
|
||||||
|
"polygon",
|
||||||
|
"polyline",
|
||||||
|
"radialGradient",
|
||||||
|
"rect",
|
||||||
|
"script",
|
||||||
|
"set",
|
||||||
|
"solidcolor",
|
||||||
|
"stop",
|
||||||
|
"style",
|
||||||
|
"svg",
|
||||||
|
"switch",
|
||||||
|
"symbol",
|
||||||
|
"text",
|
||||||
|
"textPath",
|
||||||
|
"title",
|
||||||
|
"tref",
|
||||||
|
"tspan",
|
||||||
|
"unknown",
|
||||||
|
"use",
|
||||||
|
"view",
|
||||||
|
"vkern",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
if (document.createElementNS) for (var ns in nsNames) {
|
||||||
|
for (var n = 0; n < nsNames[ns].length; n++) {
|
||||||
|
add(document.createElementNS(ns, nsNames[ns][n]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var skips = [
|
||||||
|
G.alert,
|
||||||
|
G.back,
|
||||||
|
G.blur,
|
||||||
|
G.captureEvents,
|
||||||
|
G.clearImmediate,
|
||||||
|
G.clearInterval,
|
||||||
|
G.clearTimeout,
|
||||||
|
G.close,
|
||||||
|
G.confirm,
|
||||||
|
G.console,
|
||||||
|
G.dump,
|
||||||
|
G.fetch,
|
||||||
|
G.find,
|
||||||
|
G.focus,
|
||||||
|
G.forward,
|
||||||
|
G.getAttention,
|
||||||
|
G.history,
|
||||||
|
G.home,
|
||||||
|
G.location,
|
||||||
|
G.moveBy,
|
||||||
|
G.moveTo,
|
||||||
|
G.navigator,
|
||||||
|
G.open,
|
||||||
|
G.openDialog,
|
||||||
|
G.print,
|
||||||
|
G.process,
|
||||||
|
G.prompt,
|
||||||
|
G.resizeBy,
|
||||||
|
G.resizeTo,
|
||||||
|
G.setImmediate,
|
||||||
|
G.setInterval,
|
||||||
|
G.setTimeout,
|
||||||
|
G.showModalDialog,
|
||||||
|
G.sizeToContent,
|
||||||
|
G.stop,
|
||||||
|
];
|
||||||
|
var types = [];
|
||||||
|
var interfaces = [
|
||||||
|
"beforeunloadevent",
|
||||||
|
"compositionevent",
|
||||||
|
"customevent",
|
||||||
|
"devicemotionevent",
|
||||||
|
"deviceorientationevent",
|
||||||
|
"dragevent",
|
||||||
|
"event",
|
||||||
|
"events",
|
||||||
|
"focusevent",
|
||||||
|
"hashchangeevent",
|
||||||
|
"htmlevents",
|
||||||
|
"keyboardevent",
|
||||||
|
"messageevent",
|
||||||
|
"mouseevent",
|
||||||
|
"mouseevents",
|
||||||
|
"storageevent",
|
||||||
|
"svgevents",
|
||||||
|
"textevent",
|
||||||
|
"touchevent",
|
||||||
|
"uievent",
|
||||||
|
"uievents",
|
||||||
|
];
|
||||||
|
var i = 0, full = false;
|
||||||
|
var addEvent = document.createEvent ? function(type) {
|
||||||
|
if (~indexOf(types, type)) return;
|
||||||
|
types.push(type);
|
||||||
|
for (var j = 0; j < interfaces.length; j++) try {
|
||||||
|
var event = document.createEvent(interfaces[j]);
|
||||||
|
event.initEvent(type, true, true);
|
||||||
|
add(event);
|
||||||
|
} catch (e) {}
|
||||||
|
} : function() {};
|
||||||
|
var scanProperties = Object.getOwnPropertyNames ? function(o, fn) {
|
||||||
|
var names = Object.getOwnPropertyNames(o);
|
||||||
|
names.forEach(fn);
|
||||||
|
for (var k in o) if (!~indexOf(names, k)) fn(k);
|
||||||
|
} : function(o, fn) {
|
||||||
|
for (var k in o) fn(k);
|
||||||
|
};
|
||||||
|
setTimeout(function next() {
|
||||||
|
for (var j = 10; --j >= 0 && i < objs.length; i++) {
|
||||||
|
var o = objs[i];
|
||||||
|
var skip = ~indexOf(skips, o);
|
||||||
|
try {
|
||||||
|
scanProperties(o, function(k) {
|
||||||
|
if (!~indexOf(domprops, k)) domprops.push(k);
|
||||||
|
if (/^on/.test(k)) addEvent(k.slice(2));
|
||||||
|
if (!full) try {
|
||||||
|
add(o[k]);
|
||||||
|
} catch (e) {}
|
||||||
|
});
|
||||||
|
} catch (e) {}
|
||||||
|
if (skip || full) continue;
|
||||||
|
try {
|
||||||
|
add(o.__proto__);
|
||||||
|
} catch (e) {}
|
||||||
|
try {
|
||||||
|
add(o.prototype);
|
||||||
|
} catch (e) {}
|
||||||
|
try {
|
||||||
|
add(new o());
|
||||||
|
} catch (e) {}
|
||||||
|
try {
|
||||||
|
add(o());
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
if (!full && objs.length > 20000) {
|
||||||
|
alert(objs.length);
|
||||||
|
full = true;
|
||||||
|
}
|
||||||
|
if (i < objs.length) {
|
||||||
|
setTimeout(next, 0);
|
||||||
|
} else {
|
||||||
|
document.write('<pre>[\n "' + domprops.sort().join('",\n "').replace(/&/g, "&").replace(/</g, "<") + '"\n]</pre>');
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
function add(o) {
|
||||||
|
if (o) switch (typeof o) {
|
||||||
|
case "function":
|
||||||
|
case "object":
|
||||||
|
if (!~indexOf(objs, o)) objs.push(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function indexOf(list, value) {
|
||||||
|
var j = list.length;
|
||||||
|
while (--j >= 0) {
|
||||||
|
if (list[j] === value) break;
|
||||||
|
}
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}(function() {
|
||||||
|
return this;
|
||||||
|
}());
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1475
tools/domprops.json
1475
tools/domprops.json
File diff suppressed because it is too large
Load Diff
540
tools/props.html
540
tools/props.html
@@ -1,540 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<script>
|
|
||||||
!function() {
|
|
||||||
var names = [];
|
|
||||||
var scanned = [];
|
|
||||||
var to_scan = [];
|
|
||||||
|
|
||||||
function scan(obj) {
|
|
||||||
if (obj && typeof obj == "object" && !~scanned.indexOf(obj)) {
|
|
||||||
scanned.push(obj);
|
|
||||||
to_scan.push(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scan(self);
|
|
||||||
[
|
|
||||||
"a",
|
|
||||||
"abbr",
|
|
||||||
"acronym",
|
|
||||||
"address",
|
|
||||||
"applet",
|
|
||||||
"area",
|
|
||||||
"article",
|
|
||||||
"aside",
|
|
||||||
"audio",
|
|
||||||
"b",
|
|
||||||
"base",
|
|
||||||
"basefont",
|
|
||||||
"bdi",
|
|
||||||
"bdo",
|
|
||||||
"bgsound",
|
|
||||||
"big",
|
|
||||||
"blink",
|
|
||||||
"blockquote",
|
|
||||||
"body",
|
|
||||||
"br",
|
|
||||||
"button",
|
|
||||||
"canvas",
|
|
||||||
"caption",
|
|
||||||
"center",
|
|
||||||
"checked",
|
|
||||||
"cite",
|
|
||||||
"code",
|
|
||||||
"col",
|
|
||||||
"colgroup",
|
|
||||||
"command",
|
|
||||||
"comment",
|
|
||||||
"compact",
|
|
||||||
"content",
|
|
||||||
"data",
|
|
||||||
"datalist",
|
|
||||||
"dd",
|
|
||||||
"declare",
|
|
||||||
"defer",
|
|
||||||
"del",
|
|
||||||
"details",
|
|
||||||
"dfn",
|
|
||||||
"dialog",
|
|
||||||
"dir",
|
|
||||||
"disabled",
|
|
||||||
"div",
|
|
||||||
"dl",
|
|
||||||
"dt",
|
|
||||||
"element",
|
|
||||||
"em",
|
|
||||||
"embed",
|
|
||||||
"fieldset",
|
|
||||||
"figcaption",
|
|
||||||
"figure",
|
|
||||||
"font",
|
|
||||||
"footer",
|
|
||||||
"form",
|
|
||||||
"frame",
|
|
||||||
"frameset",
|
|
||||||
"h1",
|
|
||||||
"h2",
|
|
||||||
"h3",
|
|
||||||
"h4",
|
|
||||||
"h5",
|
|
||||||
"h6",
|
|
||||||
"head",
|
|
||||||
"header",
|
|
||||||
"hgroup",
|
|
||||||
"hr",
|
|
||||||
"html",
|
|
||||||
"i",
|
|
||||||
"iframe",
|
|
||||||
"image",
|
|
||||||
"img",
|
|
||||||
"input",
|
|
||||||
"ins",
|
|
||||||
"isindex",
|
|
||||||
"ismap",
|
|
||||||
"kbd",
|
|
||||||
"keygen",
|
|
||||||
"label",
|
|
||||||
"legend",
|
|
||||||
"li",
|
|
||||||
"link",
|
|
||||||
"listing",
|
|
||||||
"main",
|
|
||||||
"map",
|
|
||||||
"mark",
|
|
||||||
"marquee",
|
|
||||||
"math",
|
|
||||||
"menu",
|
|
||||||
"menuitem",
|
|
||||||
"meta",
|
|
||||||
"meter",
|
|
||||||
"multicol",
|
|
||||||
"multiple",
|
|
||||||
"nav",
|
|
||||||
"nobr",
|
|
||||||
"noembed",
|
|
||||||
"noframes",
|
|
||||||
"nohref",
|
|
||||||
"noresize",
|
|
||||||
"noscript",
|
|
||||||
"noshade",
|
|
||||||
"nowrap",
|
|
||||||
"object",
|
|
||||||
"ol",
|
|
||||||
"optgroup",
|
|
||||||
"option",
|
|
||||||
"output",
|
|
||||||
"p",
|
|
||||||
"param",
|
|
||||||
"picture",
|
|
||||||
"plaintext",
|
|
||||||
"pre",
|
|
||||||
"progress",
|
|
||||||
"q",
|
|
||||||
"rb",
|
|
||||||
"readonly",
|
|
||||||
"rp",
|
|
||||||
"rt",
|
|
||||||
"rtc",
|
|
||||||
"ruby",
|
|
||||||
"s",
|
|
||||||
"samp",
|
|
||||||
"script",
|
|
||||||
"section",
|
|
||||||
"select",
|
|
||||||
"selected",
|
|
||||||
"shadow",
|
|
||||||
"small",
|
|
||||||
"source",
|
|
||||||
"spacer",
|
|
||||||
"span",
|
|
||||||
"strike",
|
|
||||||
"strong",
|
|
||||||
"style",
|
|
||||||
"sub",
|
|
||||||
"summary",
|
|
||||||
"sup",
|
|
||||||
"svg",
|
|
||||||
"table",
|
|
||||||
"tbody",
|
|
||||||
"td",
|
|
||||||
"template",
|
|
||||||
"textarea",
|
|
||||||
"tfoot",
|
|
||||||
"th",
|
|
||||||
"thead",
|
|
||||||
"time",
|
|
||||||
"title",
|
|
||||||
"tr",
|
|
||||||
"track",
|
|
||||||
"tt",
|
|
||||||
"u",
|
|
||||||
"ul",
|
|
||||||
"var",
|
|
||||||
"video",
|
|
||||||
"wbr",
|
|
||||||
"xmp",
|
|
||||||
"XXX",
|
|
||||||
].forEach(function(tag) {
|
|
||||||
scan(document.createElement(tag));
|
|
||||||
});
|
|
||||||
[
|
|
||||||
"abort",
|
|
||||||
"absolutedeviceorientation",
|
|
||||||
"activate",
|
|
||||||
"active",
|
|
||||||
"addsourcebuffer",
|
|
||||||
"addstream",
|
|
||||||
"addtrack",
|
|
||||||
"afterprint",
|
|
||||||
"afterscriptexecute",
|
|
||||||
"afterupdate",
|
|
||||||
"animationcancel",
|
|
||||||
"animationend",
|
|
||||||
"animationiteration",
|
|
||||||
"animationstart",
|
|
||||||
"appinstalled",
|
|
||||||
"audioend",
|
|
||||||
"audioprocess",
|
|
||||||
"audiostart",
|
|
||||||
"autocomplete",
|
|
||||||
"autocompleteerror",
|
|
||||||
"auxclick",
|
|
||||||
"beforeactivate",
|
|
||||||
"beforecopy",
|
|
||||||
"beforecut",
|
|
||||||
"beforedeactivate",
|
|
||||||
"beforeeditfocus",
|
|
||||||
"beforeinstallprompt",
|
|
||||||
"beforepaste",
|
|
||||||
"beforeprint",
|
|
||||||
"beforescriptexecute",
|
|
||||||
"beforeunload",
|
|
||||||
"beforeupdate",
|
|
||||||
"blocked",
|
|
||||||
"blur",
|
|
||||||
"bounce",
|
|
||||||
"boundary",
|
|
||||||
"cached",
|
|
||||||
"cancel",
|
|
||||||
"candidatewindowhide",
|
|
||||||
"candidatewindowshow",
|
|
||||||
"candidatewindowupdate",
|
|
||||||
"canplay",
|
|
||||||
"canplaythrough",
|
|
||||||
"cellchange",
|
|
||||||
"change",
|
|
||||||
"chargingchange",
|
|
||||||
"chargingtimechange",
|
|
||||||
"checking",
|
|
||||||
"click",
|
|
||||||
"close",
|
|
||||||
"compassneedscalibration",
|
|
||||||
"complete",
|
|
||||||
"connect",
|
|
||||||
"connecting",
|
|
||||||
"connectionstatechange",
|
|
||||||
"contextmenu",
|
|
||||||
"controllerchange",
|
|
||||||
"controlselect",
|
|
||||||
"copy",
|
|
||||||
"cuechange",
|
|
||||||
"cut",
|
|
||||||
"dataavailable",
|
|
||||||
"datachannel",
|
|
||||||
"datasetchanged",
|
|
||||||
"datasetcomplete",
|
|
||||||
"dblclick",
|
|
||||||
"deactivate",
|
|
||||||
"devicechange",
|
|
||||||
"devicelight",
|
|
||||||
"devicemotion",
|
|
||||||
"deviceorientation",
|
|
||||||
"deviceorientationabsolute",
|
|
||||||
"deviceproximity",
|
|
||||||
"dischargingtimechange",
|
|
||||||
"disconnect",
|
|
||||||
"display",
|
|
||||||
"downloading",
|
|
||||||
"drag",
|
|
||||||
"dragend",
|
|
||||||
"dragenter",
|
|
||||||
"dragexit",
|
|
||||||
"dragleave",
|
|
||||||
"dragover",
|
|
||||||
"dragstart",
|
|
||||||
"drop",
|
|
||||||
"durationchange",
|
|
||||||
"emptied",
|
|
||||||
"encrypted",
|
|
||||||
"end",
|
|
||||||
"ended",
|
|
||||||
"enter",
|
|
||||||
"enterpictureinpicture",
|
|
||||||
"error",
|
|
||||||
"errorupdate",
|
|
||||||
"exit",
|
|
||||||
"filterchange",
|
|
||||||
"finish",
|
|
||||||
"focus",
|
|
||||||
"focusin",
|
|
||||||
"focusout",
|
|
||||||
"freeze",
|
|
||||||
"fullscreenchange",
|
|
||||||
"fullscreenerror",
|
|
||||||
"gesturechange",
|
|
||||||
"gestureend",
|
|
||||||
"gesturestart",
|
|
||||||
"gotpointercapture",
|
|
||||||
"hashchange",
|
|
||||||
"help",
|
|
||||||
"icecandidate",
|
|
||||||
"iceconnectionstatechange",
|
|
||||||
"icegatheringstatechange",
|
|
||||||
"inactive",
|
|
||||||
"input",
|
|
||||||
"invalid",
|
|
||||||
"keydown",
|
|
||||||
"keypress",
|
|
||||||
"keyup",
|
|
||||||
"languagechange",
|
|
||||||
"layoutcomplete",
|
|
||||||
"leavepictureinpicture",
|
|
||||||
"levelchange",
|
|
||||||
"load",
|
|
||||||
"loadeddata",
|
|
||||||
"loadedmetadata",
|
|
||||||
"loadend",
|
|
||||||
"loading",
|
|
||||||
"loadingdone",
|
|
||||||
"loadingerror",
|
|
||||||
"loadstart",
|
|
||||||
"losecapture",
|
|
||||||
"lostpointercapture",
|
|
||||||
"mark",
|
|
||||||
"message",
|
|
||||||
"messageerror",
|
|
||||||
"mousedown",
|
|
||||||
"mouseenter",
|
|
||||||
"mouseleave",
|
|
||||||
"mousemove",
|
|
||||||
"mouseout",
|
|
||||||
"mouseover",
|
|
||||||
"mouseup",
|
|
||||||
"mousewheel",
|
|
||||||
"move",
|
|
||||||
"moveend",
|
|
||||||
"movestart",
|
|
||||||
"mozfullscreenchange",
|
|
||||||
"mozfullscreenerror",
|
|
||||||
"mozorientationchange",
|
|
||||||
"mozpointerlockchange",
|
|
||||||
"mozpointerlockerror",
|
|
||||||
"mscontentzoom",
|
|
||||||
"msfullscreenchange",
|
|
||||||
"msfullscreenerror",
|
|
||||||
"msgesturechange",
|
|
||||||
"msgesturedoubletap",
|
|
||||||
"msgestureend",
|
|
||||||
"msgesturehold",
|
|
||||||
"msgesturestart",
|
|
||||||
"msgesturetap",
|
|
||||||
"msgotpointercapture",
|
|
||||||
"msinertiastart",
|
|
||||||
"mslostpointercapture",
|
|
||||||
"msmanipulationstatechanged",
|
|
||||||
"msneedkey",
|
|
||||||
"msorientationchange",
|
|
||||||
"mspointercancel",
|
|
||||||
"mspointerdown",
|
|
||||||
"mspointerenter",
|
|
||||||
"mspointerhover",
|
|
||||||
"mspointerleave",
|
|
||||||
"mspointermove",
|
|
||||||
"mspointerout",
|
|
||||||
"mspointerover",
|
|
||||||
"mspointerup",
|
|
||||||
"mssitemodejumplistitemremoved",
|
|
||||||
"msthumbnailclick",
|
|
||||||
"negotiationneeded",
|
|
||||||
"nomatch",
|
|
||||||
"noupdate",
|
|
||||||
"obsolete",
|
|
||||||
"offline",
|
|
||||||
"online",
|
|
||||||
"open",
|
|
||||||
"orientationchange",
|
|
||||||
"pagechange",
|
|
||||||
"pagehide",
|
|
||||||
"pageshow",
|
|
||||||
"paste",
|
|
||||||
"pause",
|
|
||||||
"play",
|
|
||||||
"playing",
|
|
||||||
"pluginstreamstart",
|
|
||||||
"pointercancel",
|
|
||||||
"pointerdown",
|
|
||||||
"pointerenter",
|
|
||||||
"pointerleave",
|
|
||||||
"pointerlockchange",
|
|
||||||
"pointerlockerror",
|
|
||||||
"pointermove",
|
|
||||||
"pointerout",
|
|
||||||
"pointerover",
|
|
||||||
"pointerup",
|
|
||||||
"popstate",
|
|
||||||
"progress",
|
|
||||||
"propertychange",
|
|
||||||
"ratechange",
|
|
||||||
"reading",
|
|
||||||
"readystatechange",
|
|
||||||
"rejectionhandled",
|
|
||||||
"removesourcebuffer",
|
|
||||||
"removestream",
|
|
||||||
"removetrack",
|
|
||||||
"reset",
|
|
||||||
"resize",
|
|
||||||
"resizeend",
|
|
||||||
"resizestart",
|
|
||||||
"resourcetimingbufferfull",
|
|
||||||
"result",
|
|
||||||
"resume",
|
|
||||||
"rowenter",
|
|
||||||
"rowexit",
|
|
||||||
"rowsdelete",
|
|
||||||
"rowsinserted",
|
|
||||||
"scroll",
|
|
||||||
"search",
|
|
||||||
"seeked",
|
|
||||||
"seeking",
|
|
||||||
"select",
|
|
||||||
"selectionchange",
|
|
||||||
"selectstart",
|
|
||||||
"show",
|
|
||||||
"signalingstatechange",
|
|
||||||
"soundend",
|
|
||||||
"soundstart",
|
|
||||||
"sourceclose",
|
|
||||||
"sourceclosed",
|
|
||||||
"sourceended",
|
|
||||||
"sourceopen",
|
|
||||||
"speechend",
|
|
||||||
"speechstart",
|
|
||||||
"stalled",
|
|
||||||
"start",
|
|
||||||
"statechange",
|
|
||||||
"stop",
|
|
||||||
"storage",
|
|
||||||
"storagecommit",
|
|
||||||
"submit",
|
|
||||||
"success",
|
|
||||||
"suspend",
|
|
||||||
"textinput",
|
|
||||||
"timeout",
|
|
||||||
"timeupdate",
|
|
||||||
"toggle",
|
|
||||||
"touchcancel",
|
|
||||||
"touchend",
|
|
||||||
"touchmove",
|
|
||||||
"touchstart",
|
|
||||||
"track",
|
|
||||||
"transitioncancel",
|
|
||||||
"transitionend",
|
|
||||||
"transitionrun",
|
|
||||||
"transitionstart",
|
|
||||||
"unhandledrejection",
|
|
||||||
"unload",
|
|
||||||
"updateready",
|
|
||||||
"upgradeneeded",
|
|
||||||
"userproximity",
|
|
||||||
"versionchange",
|
|
||||||
"visibilitychange",
|
|
||||||
"voiceschanged",
|
|
||||||
"volumechange",
|
|
||||||
"vrdisplayactivate",
|
|
||||||
"vrdisplayconnect",
|
|
||||||
"vrdisplaydeactivate",
|
|
||||||
"vrdisplaydisconnect",
|
|
||||||
"vrdisplaypresentchange",
|
|
||||||
"waiting",
|
|
||||||
"waitingforkey",
|
|
||||||
"warning",
|
|
||||||
"webkitanimationend",
|
|
||||||
"webkitanimationiteration",
|
|
||||||
"webkitanimationstart",
|
|
||||||
"webkitcurrentplaybacktargetiswirelesschanged",
|
|
||||||
"webkitfullscreenchange",
|
|
||||||
"webkitfullscreenerror",
|
|
||||||
"webkitkeyadded",
|
|
||||||
"webkitkeyerror",
|
|
||||||
"webkitkeymessage",
|
|
||||||
"webkitneedkey",
|
|
||||||
"webkitorientationchange",
|
|
||||||
"webkitplaybacktargetavailabilitychanged",
|
|
||||||
"webkitpointerlockchange",
|
|
||||||
"webkitpointerlockerror",
|
|
||||||
"webkitresourcetimingbufferfull",
|
|
||||||
"webkittransitionend",
|
|
||||||
"wheel",
|
|
||||||
"zoom",
|
|
||||||
].forEach(function(type) {
|
|
||||||
[
|
|
||||||
"beforeunloadevent",
|
|
||||||
"compositionevent",
|
|
||||||
"customevent",
|
|
||||||
"devicemotionevent",
|
|
||||||
"deviceorientationevent",
|
|
||||||
"dragevent",
|
|
||||||
"event",
|
|
||||||
"events",
|
|
||||||
"focusevent",
|
|
||||||
"hashchangeevent",
|
|
||||||
"htmlevents",
|
|
||||||
"keyboardevent",
|
|
||||||
"messageevent",
|
|
||||||
"mouseevent",
|
|
||||||
"mouseevents",
|
|
||||||
"storageevent",
|
|
||||||
"svgevents",
|
|
||||||
"textevent",
|
|
||||||
"touchevent",
|
|
||||||
"uievent",
|
|
||||||
"uievents",
|
|
||||||
].forEach(function(interface) {
|
|
||||||
try {
|
|
||||||
var event = document.createEvent(interface);
|
|
||||||
event.initEvent(type, true, true);
|
|
||||||
scan(event);
|
|
||||||
} catch (e) {}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
var obj;
|
|
||||||
while (obj = to_scan.shift()) {
|
|
||||||
var proto = obj;
|
|
||||||
do {
|
|
||||||
Object.getOwnPropertyNames(proto).forEach(function(name) {
|
|
||||||
var visited = ~names.indexOf(name);
|
|
||||||
if (!visited) names.push(name);
|
|
||||||
try {
|
|
||||||
scan(obj[name]);
|
|
||||||
if (visited) return;
|
|
||||||
if (/^create/.test(name)) {
|
|
||||||
scan(obj[name]());
|
|
||||||
}
|
|
||||||
if (/^[A-Z]/.test(name)) {
|
|
||||||
scan(new obj[name]());
|
|
||||||
}
|
|
||||||
} catch (e) {}
|
|
||||||
});
|
|
||||||
} while (proto = Object.getPrototypeOf(proto));
|
|
||||||
}
|
|
||||||
names.sort();
|
|
||||||
document.write('<pre>[\n "');
|
|
||||||
document.write(names.join('",\n "'));
|
|
||||||
document.write('"\n]</pre>');
|
|
||||||
}();
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Reference in New Issue
Block a user