Compare commits
95 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4f5ba1d29 | ||
|
|
b9053c7a25 | ||
|
|
d357a7aabc | ||
|
|
ae77ebe5a5 | ||
|
|
04439edcec | ||
|
|
a246195412 | ||
|
|
8939a36bc7 | ||
|
|
a21c348d93 | ||
|
|
1f0def10eb | ||
|
|
f87caac9d8 | ||
|
|
d538a73250 | ||
|
|
2e4fbdeb08 | ||
|
|
3bc7cc82bb | ||
|
|
45fbdbc2dc | ||
|
|
54cb678055 | ||
|
|
e88c439eac | ||
|
|
9fc8cd4076 | ||
|
|
5476cb8f05 | ||
|
|
6a30e1d6be | ||
|
|
e4881245d9 | ||
|
|
354fec8a9c | ||
|
|
11cdab745d | ||
|
|
a89d424a0b | ||
|
|
429d2b56b7 | ||
|
|
2ea96549c5 | ||
|
|
fba008e298 | ||
|
|
c37a8e927e | ||
|
|
413bbe0480 | ||
|
|
34075fc4c4 | ||
|
|
e5436ca566 | ||
|
|
cfde686eab | ||
|
|
a206964c0a | ||
|
|
c56d89f804 | ||
|
|
c215706350 | ||
|
|
d3b93ec682 | ||
|
|
6fe20dbe33 | ||
|
|
7ccdf3337b | ||
|
|
dafed54764 | ||
|
|
a84beafd1b | ||
|
|
f01cc1e413 | ||
|
|
338dd144b8 | ||
|
|
c719552317 | ||
|
|
855964a87a | ||
|
|
a438e2fca9 | ||
|
|
00833e893a | ||
|
|
f1a77e4fc0 | ||
|
|
b55a2fd531 | ||
|
|
e8a2c0b5bf | ||
|
|
21cd7e3f57 | ||
|
|
5172ba5f2a | ||
|
|
a57b069409 | ||
|
|
4454656c3b | ||
|
|
fa43768ce0 | ||
|
|
a74e600fa0 | ||
|
|
4b21526310 | ||
|
|
a7a7b1daed | ||
|
|
7436977aa5 | ||
|
|
e3c565b46f | ||
|
|
54b0b49b68 | ||
|
|
65648d84a5 | ||
|
|
fd788590f6 | ||
|
|
143f9054da | ||
|
|
f2286c33f1 | ||
|
|
b9615f7a62 | ||
|
|
c520e99eda | ||
|
|
615ae37ca3 | ||
|
|
7aa7f21872 | ||
|
|
4430a436eb | ||
|
|
9707ccdc9f | ||
|
|
cb8f3a2a31 | ||
|
|
8b3259e0c2 | ||
|
|
b66f47b8dd | ||
|
|
8d2e6f333e | ||
|
|
b3ef5e514d | ||
|
|
627f5fb41e | ||
|
|
d90777b724 | ||
|
|
e49297e5eb | ||
|
|
ebd82b3fb6 | ||
|
|
d074aa6e27 | ||
|
|
b052f62710 | ||
|
|
d4ac84b255 | ||
|
|
e250396d7e | ||
|
|
c6fa39b482 | ||
|
|
9aae4f2424 | ||
|
|
008c236137 | ||
|
|
b1c0664066 | ||
|
|
ea999b0e92 | ||
|
|
ce7e220de4 | ||
|
|
2bdaca10ae | ||
|
|
aa0029204e | ||
|
|
f352bcec3a | ||
|
|
08514030f4 | ||
|
|
694ca5d045 | ||
|
|
57fb58b263 | ||
|
|
18c1c9b38a |
54
.travis.yml
54
.travis.yml
@@ -1,34 +1,46 @@
|
|||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
packages:
|
|
||||||
- libstdc++-4.9-dev
|
|
||||||
cache:
|
cache:
|
||||||
directories: tmp
|
directories: tmp
|
||||||
language: generic
|
language: generic
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
sudo: false
|
|
||||||
env:
|
env:
|
||||||
global:
|
- NODE=0.10 TYPE=compress
|
||||||
- UGLIFYJS_TEST_ALL=1
|
- NODE=0.10 TYPE=mocha
|
||||||
matrix:
|
- NODE=0.10 TYPE=release/benchmark
|
||||||
- NODEJS_VER=node/0.10
|
- NODE=0.10 TYPE=release/jetstream
|
||||||
- NODEJS_VER=node/0.12
|
- NODE=0.12 TYPE=compress
|
||||||
- NODEJS_VER=node/4
|
- NODE=0.12 TYPE=mocha
|
||||||
- NODEJS_VER=node/6
|
- NODE=0.12 TYPE=release/benchmark
|
||||||
- NODEJS_VER=node/8
|
- NODE=0.12 TYPE=release/jetstream
|
||||||
- NODEJS_VER=node/latest
|
- NODE=4 TYPE=compress
|
||||||
|
- NODE=4 TYPE=mocha
|
||||||
|
- NODE=4 TYPE=release/benchmark
|
||||||
|
- NODE=4 TYPE=release/jetstream
|
||||||
|
- NODE=6 TYPE=compress
|
||||||
|
- NODE=6 TYPE=mocha
|
||||||
|
- NODE=6 TYPE=release/benchmark
|
||||||
|
- NODE=6 TYPE=release/jetstream
|
||||||
|
- NODE=8 TYPE=compress
|
||||||
|
- NODE=8 TYPE=mocha
|
||||||
|
- NODE=8 TYPE=release/benchmark
|
||||||
|
- NODE=8 TYPE=release/jetstream
|
||||||
|
- NODE=10 TYPE=compress
|
||||||
|
- NODE=10 TYPE=mocha
|
||||||
|
- NODE=10 TYPE=release/benchmark
|
||||||
|
- NODE=10 TYPE=release/jetstream
|
||||||
|
- NODE=latest TYPE=compress
|
||||||
|
- NODE=latest TYPE=mocha
|
||||||
|
- NODE=latest TYPE=release/benchmark
|
||||||
|
- NODE=latest TYPE=release/jetstream
|
||||||
before_install:
|
before_install:
|
||||||
- git clone --branch v1.4.2 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
- git clone --branch v1.5.2 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||||
- . ~/.nvs/nvs.sh
|
- . ~/.nvs/nvs.sh
|
||||||
- nvs --version
|
- nvs --version
|
||||||
install:
|
install:
|
||||||
- nvs add $NODEJS_VER
|
- nvs add node/$NODE
|
||||||
- nvs use $NODEJS_VER
|
- nvs use node/$NODE
|
||||||
- node --version
|
- node --version
|
||||||
- npm --version --no-update-notifier
|
- npm --version --no-update-notifier
|
||||||
- npm install --no-optional --no-save --no-update-notifier
|
- npm install --no-audit --no-optional --no-save --no-update-notifier
|
||||||
script:
|
script:
|
||||||
- npm test --no-update-notifier
|
- node test/$TYPE
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
|||||||
UglifyJS is released under the BSD license:
|
UglifyJS is released under the BSD license:
|
||||||
|
|
||||||
Copyright 2012-2018 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
Copyright 2012-2019 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions
|
modification, are permitted provided that the following conditions
|
||||||
|
|||||||
15
README.md
15
README.md
@@ -605,6 +605,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
- `arguments` (default: `true`) -- replace `arguments[index]` with function
|
- `arguments` (default: `true`) -- replace `arguments[index]` with function
|
||||||
parameter name whenever possible.
|
parameter name whenever possible.
|
||||||
|
|
||||||
|
- `assignments` (default: `true`) -- apply optimizations to assignment expressions.
|
||||||
|
|
||||||
- `booleans` (default: `true`) -- various optimizations for boolean context,
|
- `booleans` (default: `true`) -- various optimizations for boolean context,
|
||||||
for example `!!a ? b : c → a ? b : c`
|
for example `!!a ? b : c → a ? b : c`
|
||||||
|
|
||||||
@@ -634,6 +636,9 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
- `expression` (default: `false`) -- Pass `true` to preserve completion values
|
- `expression` (default: `false`) -- Pass `true` to preserve completion values
|
||||||
from terminal statements without `return`, e.g. in bookmarklets.
|
from terminal statements without `return`, e.g. in bookmarklets.
|
||||||
|
|
||||||
|
- `functions` (default: `true`) -- convert declarations from `var`to `function`
|
||||||
|
whenever possible.
|
||||||
|
|
||||||
- `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation)
|
- `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation)
|
||||||
|
|
||||||
- `hoist_funs` (default: `false`) -- hoist function declarations
|
- `hoist_funs` (default: `false`) -- hoist function declarations
|
||||||
@@ -659,12 +664,13 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
|
|
||||||
- `join_vars` (default: `true`) -- join consecutive `var` statements
|
- `join_vars` (default: `true`) -- join consecutive `var` statements
|
||||||
|
|
||||||
- `keep_fargs` (default: `true`) -- Prevents the compressor from discarding unused
|
- `keep_fargs` (default: `strict`) -- Discard unused function arguments. Code
|
||||||
function arguments. You need this for code which relies on `Function.length`.
|
which relies on `Function.length` will break if this is done indiscriminately,
|
||||||
|
i.e. when passing `true`. Pass `false` to always retain function arguments.
|
||||||
|
|
||||||
- `keep_fnames` (default: `false`) -- Pass `true` to prevent the
|
- `keep_fnames` (default: `false`) -- Pass `true` to prevent the
|
||||||
compressor from discarding function names. Useful for code relying on
|
compressor from discarding function names. Useful for code relying on
|
||||||
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
|
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle-options).
|
||||||
|
|
||||||
- `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from
|
- `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from
|
||||||
being compressed into `1/0`, which may cause performance issues on Chrome.
|
being compressed into `1/0`, which may cause performance issues on Chrome.
|
||||||
@@ -762,9 +768,6 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple
|
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple
|
||||||
direct variable assignments do not count as references unless set to `"keep_assign"`)
|
direct variable assignments do not count as references unless set to `"keep_assign"`)
|
||||||
|
|
||||||
- `warnings` (default: `false`) -- display warnings when dropping unreachable
|
|
||||||
code or unused declarations etc.
|
|
||||||
|
|
||||||
## Mangle options
|
## Mangle options
|
||||||
|
|
||||||
- `eval` (default `false`) -- Pass `true` to mangle names visible in scopes
|
- `eval` (default `false`) -- Pass `true` to mangle names visible in scopes
|
||||||
|
|||||||
87
appveyor.yml
87
appveyor.yml
@@ -1,25 +1,74 @@
|
|||||||
environment:
|
|
||||||
UGLIFYJS_TEST_ALL: 1
|
|
||||||
matrix:
|
|
||||||
- NODEJS_VER: node/0.10
|
|
||||||
- NODEJS_VER: node/0.12
|
|
||||||
- NODEJS_VER: node/4
|
|
||||||
- NODEJS_VER: node/6
|
|
||||||
- NODEJS_VER: node/8
|
|
||||||
- NODEJS_VER: node/latest
|
|
||||||
install:
|
|
||||||
- git clone --branch v1.4.2 --depth 1 https://github.com/jasongin/nvs.git %LOCALAPPDATA%\nvs
|
|
||||||
- set PATH=%LOCALAPPDATA%\nvs;%PATH%
|
|
||||||
- nvs --version
|
|
||||||
- nvs add %NODEJS_VER%
|
|
||||||
- nvs use %NODEJS_VER%
|
|
||||||
- node --version
|
|
||||||
- npm --version --no-update-notifier
|
|
||||||
- npm install --no-optional --no-save --no-update-notifier
|
|
||||||
build: off
|
build: off
|
||||||
cache:
|
cache:
|
||||||
- tmp
|
- tmp
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- NODE: 0.10
|
||||||
|
TYPE: compress
|
||||||
|
- NODE: 0.10
|
||||||
|
TYPE: mocha
|
||||||
|
- NODE: 0.10
|
||||||
|
TYPE: release/benchmark
|
||||||
|
- NODE: 0.10
|
||||||
|
TYPE: release/jetstream
|
||||||
|
- NODE: 0.12
|
||||||
|
TYPE: compress
|
||||||
|
- NODE: 0.12
|
||||||
|
TYPE: mocha
|
||||||
|
- NODE: 0.12
|
||||||
|
TYPE: release/benchmark
|
||||||
|
- NODE: 0.12
|
||||||
|
TYPE: release/jetstream
|
||||||
|
- NODE: 4
|
||||||
|
TYPE: compress
|
||||||
|
- NODE: 4
|
||||||
|
TYPE: mocha
|
||||||
|
- NODE: 4
|
||||||
|
TYPE: release/benchmark
|
||||||
|
- NODE: 4
|
||||||
|
TYPE: release/jetstream
|
||||||
|
- NODE: 6
|
||||||
|
TYPE: compress
|
||||||
|
- NODE: 6
|
||||||
|
TYPE: mocha
|
||||||
|
- NODE: 6
|
||||||
|
TYPE: release/benchmark
|
||||||
|
- NODE: 6
|
||||||
|
TYPE: release/jetstream
|
||||||
|
- NODE: 8
|
||||||
|
TYPE: compress
|
||||||
|
- NODE: 8
|
||||||
|
TYPE: mocha
|
||||||
|
- NODE: 8
|
||||||
|
TYPE: release/benchmark
|
||||||
|
- NODE: 8
|
||||||
|
TYPE: release/jetstream
|
||||||
|
- NODE: 10
|
||||||
|
TYPE: compress
|
||||||
|
- NODE: 10
|
||||||
|
TYPE: mocha
|
||||||
|
- NODE: 10
|
||||||
|
TYPE: release/benchmark
|
||||||
|
- NODE: 10
|
||||||
|
TYPE: release/jetstream
|
||||||
|
- NODE: latest
|
||||||
|
TYPE: compress
|
||||||
|
- NODE: latest
|
||||||
|
TYPE: mocha
|
||||||
|
- NODE: latest
|
||||||
|
TYPE: release/benchmark
|
||||||
|
- NODE: latest
|
||||||
|
TYPE: release/jetstream
|
||||||
|
install:
|
||||||
|
- git clone --branch v1.5.2 --depth 1 https://github.com/jasongin/nvs.git %LOCALAPPDATA%\nvs
|
||||||
|
- set PATH=%LOCALAPPDATA%\nvs;%PATH%
|
||||||
|
- nvs --version
|
||||||
|
- nvs add node/%NODE%
|
||||||
|
- nvs use node/%NODE%
|
||||||
|
- node --version
|
||||||
|
- npm --version --no-update-notifier
|
||||||
|
- npm install --no-audit --no-optional --no-save --no-update-notifier
|
||||||
test_script:
|
test_script:
|
||||||
- npm test --no-update-notifier
|
- node test/%TYPE%
|
||||||
|
|||||||
90
bin/uglifyjs
90
bin/uglifyjs
@@ -56,9 +56,14 @@ program.option("--wrap <name>", "Embed everything as a function with “exports
|
|||||||
program.arguments("[files...]").parseArgv(process.argv);
|
program.arguments("[files...]").parseArgv(process.argv);
|
||||||
if (program.configFile) {
|
if (program.configFile) {
|
||||||
options = JSON.parse(read_file(program.configFile));
|
options = JSON.parse(read_file(program.configFile));
|
||||||
|
if (options.mangle && options.mangle.properties && options.mangle.properties.regex) {
|
||||||
|
options.mangle.properties.regex = UglifyJS.parse(options.mangle.properties.regex, {
|
||||||
|
expression: true
|
||||||
|
}).getValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
||||||
fatal("ERROR: cannot write source map to STDOUT");
|
fatal("cannot write source map to STDOUT");
|
||||||
}
|
}
|
||||||
[
|
[
|
||||||
"compress",
|
"compress",
|
||||||
@@ -73,6 +78,15 @@ if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
|||||||
options[name] = program[name];
|
options[name] = program[name];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (program.verbose) {
|
||||||
|
options.warnings = "verbose";
|
||||||
|
} else if (program.warn) {
|
||||||
|
options.warnings = true;
|
||||||
|
}
|
||||||
|
if (options.warnings) {
|
||||||
|
UglifyJS.AST_Node.log_function(print_error, options.warnings == "verbose");
|
||||||
|
delete options.warnings;
|
||||||
|
}
|
||||||
if (program.beautify) {
|
if (program.beautify) {
|
||||||
options.output = typeof program.beautify == "object" ? program.beautify : {};
|
options.output = typeof program.beautify == "object" ? program.beautify : {};
|
||||||
if (!("beautify" in options.output)) {
|
if (!("beautify" in options.output)) {
|
||||||
@@ -119,7 +133,7 @@ if (program.parse) {
|
|||||||
if (!program.parse.acorn && !program.parse.spidermonkey) {
|
if (!program.parse.acorn && !program.parse.spidermonkey) {
|
||||||
options.parse = program.parse;
|
options.parse = program.parse;
|
||||||
} else if (program.sourceMap && program.sourceMap.content == "inline") {
|
} else if (program.sourceMap && program.sourceMap.content == "inline") {
|
||||||
fatal("ERROR: inline source map only works with built-in parser");
|
fatal("inline source map only works with built-in parser");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (~program.rawArgs.indexOf("--rename")) {
|
if (~program.rawArgs.indexOf("--rename")) {
|
||||||
@@ -139,15 +153,8 @@ if (typeof program.sourceMap == "object" && "base" in program.sourceMap) {
|
|||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
if (program.verbose) {
|
|
||||||
options.warnings = "verbose";
|
|
||||||
} else if (program.warn) {
|
|
||||||
options.warnings = true;
|
|
||||||
}
|
|
||||||
if (program.self) {
|
if (program.self) {
|
||||||
if (program.args.length) {
|
if (program.args.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
|
||||||
print_error("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) {
|
simple_glob(UglifyJS.FILES).forEach(function(name) {
|
||||||
files[convert_path(name)] = read_file(name);
|
files[convert_path(name)] = read_file(name);
|
||||||
@@ -175,12 +182,9 @@ function convert_ast(fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
UglifyJS.AST_Node.warn_function = function(msg) {
|
|
||||||
print_error("WARN: " + msg);
|
|
||||||
};
|
|
||||||
var content = program.sourceMap && program.sourceMap.content;
|
var content = program.sourceMap && program.sourceMap.content;
|
||||||
if (content && content != "inline") {
|
if (content && content != "inline") {
|
||||||
print_error("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;
|
if (program.timings) options.timings = true;
|
||||||
@@ -211,24 +215,26 @@ function run() {
|
|||||||
var ex = result.error;
|
var ex = result.error;
|
||||||
if (ex.name == "SyntaxError") {
|
if (ex.name == "SyntaxError") {
|
||||||
print_error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
|
print_error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
|
||||||
var col = ex.col;
|
var file = files[ex.filename];
|
||||||
var lines = files[ex.filename].split(/\r?\n/);
|
if (file) {
|
||||||
var line = lines[ex.line - 1];
|
var col = ex.col;
|
||||||
if (!line && !col) {
|
var lines = file.split(/\r?\n/);
|
||||||
line = lines[ex.line - 2];
|
var line = lines[ex.line - 1];
|
||||||
col = line.length;
|
if (!line && !col) {
|
||||||
}
|
line = lines[ex.line - 2];
|
||||||
if (line) {
|
col = line.length;
|
||||||
var limit = 70;
|
}
|
||||||
if (col > limit) {
|
if (line) {
|
||||||
line = line.slice(col - limit);
|
var limit = 70;
|
||||||
col = limit;
|
if (col > limit) {
|
||||||
|
line = line.slice(col - limit);
|
||||||
|
col = limit;
|
||||||
|
}
|
||||||
|
print_error(line.slice(0, 80));
|
||||||
|
print_error(line.slice(0, col).replace(/\S/g, " ") + "^");
|
||||||
}
|
}
|
||||||
print_error(line.slice(0, 80));
|
|
||||||
print_error(line.slice(0, col).replace(/\S/g, " ") + "^");
|
|
||||||
}
|
}
|
||||||
}
|
} else if (ex.defs) {
|
||||||
if (ex.defs) {
|
|
||||||
print_error("Supported options:");
|
print_error("Supported options:");
|
||||||
print_error(format_object(ex.defs));
|
print_error(format_object(ex.defs));
|
||||||
}
|
}
|
||||||
@@ -288,7 +294,11 @@ function run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fatal(message) {
|
function fatal(message) {
|
||||||
if (message instanceof Error) message = message.stack.replace(/^\S*?Error:/, "ERROR:")
|
if (message instanceof Error) {
|
||||||
|
message = message.stack.replace(/^\S*?Error:/, "ERROR:")
|
||||||
|
} else {
|
||||||
|
message = "ERROR: " + message;
|
||||||
|
}
|
||||||
print_error(message);
|
print_error(message);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -337,17 +347,9 @@ function parse_js(flag) {
|
|||||||
return function(value, options) {
|
return function(value, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
try {
|
try {
|
||||||
UglifyJS.minify(value, {
|
UglifyJS.parse(value, {
|
||||||
parse: {
|
expression: true
|
||||||
expression: true
|
}).walk(new UglifyJS.TreeWalker(function(node) {
|
||||||
},
|
|
||||||
compress: false,
|
|
||||||
mangle: false,
|
|
||||||
output: {
|
|
||||||
ast: true,
|
|
||||||
code: false
|
|
||||||
}
|
|
||||||
}).ast.walk(new UglifyJS.TreeWalker(function(node) {
|
|
||||||
if (node instanceof UglifyJS.AST_Assign) {
|
if (node instanceof UglifyJS.AST_Assign) {
|
||||||
var name = node.left.print_to_string();
|
var name = node.left.print_to_string();
|
||||||
var value = node.right;
|
var value = node.right;
|
||||||
@@ -373,9 +375,9 @@ function parse_js(flag) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
} catch(ex) {
|
} catch (ex) {
|
||||||
if (flag) {
|
if (flag) {
|
||||||
fatal("Error parsing arguments for '" + flag + "': " + value);
|
fatal("cannot parse arguments for '" + flag + "': " + value);
|
||||||
} else {
|
} else {
|
||||||
options[value] = null;
|
options[value] = null;
|
||||||
}
|
}
|
||||||
|
|||||||
61
lib/ast.js
61
lib/ast.js
@@ -118,9 +118,25 @@ var AST_Node = DEFNODE("Node", "start end", {
|
|||||||
}
|
}
|
||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
AST_Node.warn = function(txt, props) {
|
(AST_Node.log_function = function(fn, verbose) {
|
||||||
if (AST_Node.warn_function) AST_Node.warn_function(string_template(txt, props));
|
var printed = Object.create(null);
|
||||||
};
|
if (fn) {
|
||||||
|
AST_Node.info = verbose ? function(text, props) {
|
||||||
|
log("INFO: " + string_template(text, props));
|
||||||
|
} : noop;
|
||||||
|
AST_Node.warn = function(text, props) {
|
||||||
|
log("WARN: " + string_template(text, props));
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
AST_Node.info = AST_Node.warn = noop;
|
||||||
|
}
|
||||||
|
|
||||||
|
function log(msg) {
|
||||||
|
if (printed[msg]) return;
|
||||||
|
printed[msg] = true;
|
||||||
|
fn(msg);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
/* -----[ statements ]----- */
|
/* -----[ statements ]----- */
|
||||||
|
|
||||||
@@ -321,18 +337,25 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
|||||||
$propdoc: {
|
$propdoc: {
|
||||||
globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
|
globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
|
||||||
},
|
},
|
||||||
wrap_commonjs: function(name) {
|
wrap: function(name) {
|
||||||
var body = this.body;
|
var body = this.body;
|
||||||
var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
|
return parse([
|
||||||
wrapped_tl = parse(wrapped_tl);
|
"(function(exports){'$ORIG';})(typeof ",
|
||||||
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function(node) {
|
name,
|
||||||
|
"=='undefined'?(",
|
||||||
|
name,
|
||||||
|
"={}):",
|
||||||
|
name,
|
||||||
|
");"
|
||||||
|
].join(""), {
|
||||||
|
filename: "wrap=" + JSON.stringify(name)
|
||||||
|
}).transform(new TreeTransformer(function(node) {
|
||||||
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
||||||
return MAP.splice(body);
|
return MAP.splice(body);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
return wrapped_tl;
|
|
||||||
},
|
},
|
||||||
wrap_enclose: function(args_values) {
|
enclose: function(args_values) {
|
||||||
if (typeof args_values != "string") args_values = "";
|
if (typeof args_values != "string") args_values = "";
|
||||||
var index = args_values.indexOf(":");
|
var index = args_values.indexOf(":");
|
||||||
if (index < 0) index = args_values.length;
|
if (index < 0) index = args_values.length;
|
||||||
@@ -343,7 +366,9 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
|||||||
'){"$ORIG"})(',
|
'){"$ORIG"})(',
|
||||||
args_values.slice(index + 1),
|
args_values.slice(index + 1),
|
||||||
")"
|
")"
|
||||||
].join("")).transform(new TreeTransformer(function(node) {
|
].join(""), {
|
||||||
|
filename: "enclose=" + JSON.stringify(args_values)
|
||||||
|
}).transform(new TreeTransformer(function(node) {
|
||||||
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
||||||
return MAP.splice(body);
|
return MAP.splice(body);
|
||||||
}
|
}
|
||||||
@@ -351,7 +376,7 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
|||||||
}
|
}
|
||||||
}, AST_Scope);
|
}, AST_Scope);
|
||||||
|
|
||||||
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
|
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments length_read", {
|
||||||
$documentation: "Base class for functions",
|
$documentation: "Base class for functions",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
name: "[AST_SymbolDeclaration?] the name of this function",
|
name: "[AST_SymbolDeclaration?] the name of this function",
|
||||||
@@ -589,6 +614,18 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
|
|||||||
$propdoc: {
|
$propdoc: {
|
||||||
expression: "[AST_Node] the “container” expression",
|
expression: "[AST_Node] the “container” expression",
|
||||||
property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node"
|
property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node"
|
||||||
|
},
|
||||||
|
getProperty: function() {
|
||||||
|
var p = this.property;
|
||||||
|
if (p instanceof AST_Constant) {
|
||||||
|
return p.getValue();
|
||||||
|
}
|
||||||
|
if (p instanceof AST_UnaryPrefix
|
||||||
|
&& p.operator == "void"
|
||||||
|
&& p.expression instanceof AST_Constant) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -773,7 +810,7 @@ var AST_Label = DEFNODE("Label", "references", {
|
|||||||
}
|
}
|
||||||
}, AST_Symbol);
|
}, AST_Symbol);
|
||||||
|
|
||||||
var AST_SymbolRef = DEFNODE("SymbolRef", null, {
|
var AST_SymbolRef = DEFNODE("SymbolRef", "fixed", {
|
||||||
$documentation: "Reference to some symbol (not definition/declaration)",
|
$documentation: "Reference to some symbol (not definition/declaration)",
|
||||||
}, AST_Symbol);
|
}, AST_Symbol);
|
||||||
|
|
||||||
|
|||||||
1356
lib/compress.js
1356
lib/compress.js
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ var to_base64 = typeof btoa == "undefined" ? function(str) {
|
|||||||
} : btoa;
|
} : btoa;
|
||||||
|
|
||||||
function read_source_map(name, code) {
|
function read_source_map(name, code) {
|
||||||
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
|
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(\S+)\s*$/.exec(code);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
AST_Node.warn("inline source map not found: " + name);
|
AST_Node.warn("inline source map not found: " + name);
|
||||||
return null;
|
return null;
|
||||||
@@ -51,7 +51,6 @@ function to_json(cache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function minify(files, options) {
|
function minify(files, options) {
|
||||||
var warn_function = AST_Node.warn_function;
|
|
||||||
try {
|
try {
|
||||||
options = defaults(options, {
|
options = defaults(options, {
|
||||||
compress: {},
|
compress: {},
|
||||||
@@ -78,7 +77,6 @@ function minify(files, options) {
|
|||||||
set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
|
set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
|
||||||
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
||||||
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
||||||
set_shorthand("warnings", options, [ "compress" ]);
|
|
||||||
var quoted_props;
|
var quoted_props;
|
||||||
if (options.mangle) {
|
if (options.mangle) {
|
||||||
options.mangle = defaults(options.mangle, {
|
options.mangle = defaults(options.mangle, {
|
||||||
@@ -116,11 +114,9 @@ function minify(files, options) {
|
|||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
var warnings = [];
|
var warnings = [];
|
||||||
if (options.warnings && !AST_Node.warn_function) {
|
if (options.warnings) AST_Node.log_function(function(warning) {
|
||||||
AST_Node.warn_function = function(warning) {
|
warnings.push(warning);
|
||||||
warnings.push(warning);
|
}, options.warnings == "verbose");
|
||||||
};
|
|
||||||
}
|
|
||||||
if (timings) timings.parse = Date.now();
|
if (timings) timings.parse = Date.now();
|
||||||
var source_maps, toplevel;
|
var source_maps, toplevel;
|
||||||
if (files instanceof AST_Toplevel) {
|
if (files instanceof AST_Toplevel) {
|
||||||
@@ -155,12 +151,13 @@ function minify(files, options) {
|
|||||||
if (quoted_props) {
|
if (quoted_props) {
|
||||||
reserve_quoted_keys(toplevel, quoted_props);
|
reserve_quoted_keys(toplevel, quoted_props);
|
||||||
}
|
}
|
||||||
if (options.wrap) {
|
[ "enclose", "wrap" ].forEach(function(action) {
|
||||||
toplevel = toplevel.wrap_commonjs(options.wrap);
|
var option = options[action];
|
||||||
}
|
if (!option) return;
|
||||||
if (options.enclose) {
|
var orig = toplevel.print_to_string().slice(0, -1);
|
||||||
toplevel = toplevel.wrap_enclose(options.enclose);
|
toplevel = toplevel[action](option);
|
||||||
}
|
files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
|
||||||
|
});
|
||||||
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);
|
||||||
@@ -208,10 +205,14 @@ function minify(files, options) {
|
|||||||
result.code = stream.get();
|
result.code = stream.get();
|
||||||
if (options.sourceMap) {
|
if (options.sourceMap) {
|
||||||
result.map = options.output.source_map.toString();
|
result.map = options.output.source_map.toString();
|
||||||
if (options.sourceMap.url == "inline") {
|
var url = options.sourceMap.url;
|
||||||
result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(result.map);
|
if (url) {
|
||||||
} else if (options.sourceMap.url) {
|
result.code = result.code.replace(/\n\/\/# sourceMappingURL=\S+\s*$/, "");
|
||||||
result.code += "\n//# sourceMappingURL=" + options.sourceMap.url;
|
if (url == "inline") {
|
||||||
|
result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(result.map);
|
||||||
|
} else {
|
||||||
|
result.code += "\n//# sourceMappingURL=" + url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,7 +241,5 @@ function minify(files, options) {
|
|||||||
return result;
|
return result;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
return { error: ex };
|
return { error: ex };
|
||||||
} finally {
|
|
||||||
AST_Node.warn_function = warn_function;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
} : function(str) {
|
} : function(str) {
|
||||||
var s = "";
|
var s = "";
|
||||||
for (var i = 0, len = str.length; i < len; i++) {
|
for (var i = 0; i < str.length; i++) {
|
||||||
if (is_surrogate_pair_head(str[i]) && !is_surrogate_pair_tail(str[i + 1])
|
if (is_surrogate_pair_head(str[i]) && !is_surrogate_pair_tail(str[i + 1])
|
||||||
|| is_surrogate_pair_tail(str[i]) && !is_surrogate_pair_head(str[i - 1])) {
|
|| is_surrogate_pair_tail(str[i]) && !is_surrogate_pair_head(str[i - 1])) {
|
||||||
s += "\\u" + str.charCodeAt(i).toString(16);
|
s += "\\u" + str.charCodeAt(i).toString(16);
|
||||||
@@ -217,23 +217,12 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
var flush_mappings = mappings ? function() {
|
var flush_mappings = mappings ? function() {
|
||||||
mappings.forEach(function(mapping) {
|
mappings.forEach(function(mapping) {
|
||||||
try {
|
options.source_map.add(
|
||||||
options.source_map.add(
|
mapping.token.file,
|
||||||
mapping.token.file,
|
mapping.line, mapping.col,
|
||||||
mapping.line, mapping.col,
|
mapping.token.line, mapping.token.col,
|
||||||
mapping.token.line, mapping.token.col,
|
!mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name
|
||||||
!mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name
|
);
|
||||||
);
|
|
||||||
} catch(ex) {
|
|
||||||
AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
|
|
||||||
file: mapping.token.file,
|
|
||||||
line: mapping.token.line,
|
|
||||||
col: mapping.token.col,
|
|
||||||
cline: mapping.line,
|
|
||||||
ccol: mapping.col,
|
|
||||||
name: mapping.name || ""
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
mappings = [];
|
mappings = [];
|
||||||
} : noop;
|
} : noop;
|
||||||
@@ -462,16 +451,11 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
function prepend_comments(node) {
|
function prepend_comments(node) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var start = node.start;
|
var scan = node instanceof AST_Exit && node.value;
|
||||||
if (!start) return;
|
var comments = dump(node);
|
||||||
if (start.comments_before && start.comments_before._dumped === self) return;
|
if (!comments) return;
|
||||||
var comments = start.comments_before;
|
|
||||||
if (!comments) {
|
|
||||||
comments = start.comments_before = [];
|
|
||||||
}
|
|
||||||
comments._dumped = self;
|
|
||||||
|
|
||||||
if (node instanceof AST_Exit && node.value) {
|
if (scan) {
|
||||||
var tw = new TreeWalker(function(node) {
|
var tw = new TreeWalker(function(node) {
|
||||||
var parent = tw.parent();
|
var parent = tw.parent();
|
||||||
if (parent instanceof AST_Exit
|
if (parent instanceof AST_Exit
|
||||||
@@ -482,11 +466,8 @@ function OutputStream(options) {
|
|||||||
|| parent instanceof AST_Sequence && parent.expressions[0] === node
|
|| parent instanceof AST_Sequence && parent.expressions[0] === node
|
||||||
|| parent instanceof AST_Sub && parent.expression === node
|
|| parent instanceof AST_Sub && parent.expression === node
|
||||||
|| parent instanceof AST_UnaryPostfix) {
|
|| parent instanceof AST_UnaryPostfix) {
|
||||||
var text = node.start.comments_before;
|
var before = dump(node);
|
||||||
if (text && text._dumped !== self) {
|
if (before) comments = comments.concat(before);
|
||||||
text._dumped = self;
|
|
||||||
comments = comments.concat(text);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -529,13 +510,29 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!last_nlb) {
|
if (!last_nlb) {
|
||||||
if (start.nlb) {
|
if (node.start.nlb) {
|
||||||
print("\n");
|
print("\n");
|
||||||
indent();
|
indent();
|
||||||
} else {
|
} else {
|
||||||
space();
|
space();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function dump(node) {
|
||||||
|
var token = node.start;
|
||||||
|
if (!token) {
|
||||||
|
if (!scan) return;
|
||||||
|
node.start = token = new AST_Token();
|
||||||
|
}
|
||||||
|
var comments = token.comments_before;
|
||||||
|
if (!comments) {
|
||||||
|
if (!scan) return;
|
||||||
|
token.comments_before = comments = [];
|
||||||
|
}
|
||||||
|
if (comments._dumped === self) return;
|
||||||
|
comments._dumped = self;
|
||||||
|
return comments;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function append_comments(node, tail) {
|
function append_comments(node, tail) {
|
||||||
|
|||||||
43
lib/parse.js
43
lib/parse.js
@@ -164,10 +164,6 @@ function is_unicode_connector_punctuation(ch) {
|
|||||||
return UNICODE.connector_punctuation.test(ch);
|
return UNICODE.connector_punctuation.test(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_identifier(name) {
|
|
||||||
return !RESERVED_WORDS[name] && /^[a-z_$][a-z0-9_$]*$/i.test(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_identifier_start(code) {
|
function is_identifier_start(code) {
|
||||||
return code == 36 || code == 95 || is_letter(code);
|
return code == 36 || code == 95 || is_letter(code);
|
||||||
}
|
}
|
||||||
@@ -272,10 +268,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
|
|
||||||
function find_eol() {
|
function find_eol() {
|
||||||
var text = S.text;
|
var text = S.text;
|
||||||
for (var i = S.pos, n = S.text.length; i < n; ++i) {
|
for (var i = S.pos; i < S.text.length; ++i) {
|
||||||
var ch = text[i];
|
if (NEWLINE_CHARS[text[i]]) return i;
|
||||||
if (NEWLINE_CHARS[ch])
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -510,7 +504,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
var regexp = new RegExp(source, mods);
|
var regexp = new RegExp(source, mods);
|
||||||
regexp.raw_source = source;
|
regexp.raw_source = source;
|
||||||
return token("regexp", regexp);
|
return token("regexp", regexp);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
parse_error(e.message);
|
parse_error(e.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -562,7 +556,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
return function(x) {
|
return function(x) {
|
||||||
try {
|
try {
|
||||||
return cont(x);
|
return cont(x);
|
||||||
} catch(ex) {
|
} catch (ex) {
|
||||||
if (ex === EX_EOF) parse_error(eof_error);
|
if (ex === EX_EOF) parse_error(eof_error);
|
||||||
else throw ex;
|
else throw ex;
|
||||||
}
|
}
|
||||||
@@ -758,17 +752,21 @@ function parse($TEXT, options) {
|
|||||||
croak(msg, token.line, token.col);
|
croak(msg, token.line, token.col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function token_to_string(type, value) {
|
||||||
|
return type + (value === undefined ? "" : " «" + value + "»");
|
||||||
|
}
|
||||||
|
|
||||||
function unexpected(token) {
|
function unexpected(token) {
|
||||||
if (token == null)
|
if (token == null)
|
||||||
token = S.token;
|
token = S.token;
|
||||||
token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
|
token_error(token, "Unexpected token: " + token_to_string(token.type, token.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
function expect_token(type, val) {
|
function expect_token(type, val) {
|
||||||
if (is(type, val)) {
|
if (is(type, val)) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
|
token_error(S.token, "Unexpected token: " + token_to_string(S.token.type, S.token.value) + ", expected: " + token_to_string(type, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
function expect(punc) {
|
function expect(punc) {
|
||||||
@@ -788,7 +786,7 @@ function parse($TEXT, options) {
|
|||||||
|
|
||||||
function semicolon(optional) {
|
function semicolon(optional) {
|
||||||
if (is("punc", ";")) next();
|
if (is("punc", ";")) next();
|
||||||
else if (!optional && !can_insert_semicolon()) unexpected();
|
else if (!optional && !can_insert_semicolon()) expect_token("punc", ";");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parenthesised() {
|
function parenthesised() {
|
||||||
@@ -1069,7 +1067,7 @@ function parse($TEXT, options) {
|
|||||||
var in_statement = ctor === AST_Defun;
|
var in_statement = ctor === AST_Defun;
|
||||||
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
|
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
|
||||||
if (in_statement && !name)
|
if (in_statement && !name)
|
||||||
unexpected();
|
expect_token("name");
|
||||||
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
|
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
|
||||||
unexpected(prev());
|
unexpected(prev());
|
||||||
expect("(");
|
expect("(");
|
||||||
@@ -1119,7 +1117,7 @@ function parse($TEXT, options) {
|
|||||||
expect("{");
|
expect("{");
|
||||||
var a = [];
|
var a = [];
|
||||||
while (!is("punc", "}")) {
|
while (!is("punc", "}")) {
|
||||||
if (is("eof")) unexpected();
|
if (is("eof")) expect_token("punc", "}");
|
||||||
a.push(statement(strict_defun));
|
a.push(statement(strict_defun));
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
@@ -1130,7 +1128,7 @@ function parse($TEXT, options) {
|
|||||||
expect("{");
|
expect("{");
|
||||||
var a = [], cur = null, branch = null, tmp;
|
var a = [], cur = null, branch = null, tmp;
|
||||||
while (!is("punc", "}")) {
|
while (!is("punc", "}")) {
|
||||||
if (is("eof")) unexpected();
|
if (is("eof")) expect_token("punc", "}");
|
||||||
if (is("keyword", "case")) {
|
if (is("keyword", "case")) {
|
||||||
if (branch) branch.end = prev();
|
if (branch) branch.end = prev();
|
||||||
cur = [];
|
cur = [];
|
||||||
@@ -1141,8 +1139,7 @@ function parse($TEXT, options) {
|
|||||||
});
|
});
|
||||||
a.push(branch);
|
a.push(branch);
|
||||||
expect(":");
|
expect(":");
|
||||||
}
|
} else if (is("keyword", "default")) {
|
||||||
else if (is("keyword", "default")) {
|
|
||||||
if (branch) branch.end = prev();
|
if (branch) branch.end = prev();
|
||||||
cur = [];
|
cur = [];
|
||||||
branch = new AST_Default({
|
branch = new AST_Default({
|
||||||
@@ -1150,8 +1147,7 @@ function parse($TEXT, options) {
|
|||||||
body : cur
|
body : cur
|
||||||
});
|
});
|
||||||
a.push(branch);
|
a.push(branch);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (!cur) unexpected();
|
if (!cur) unexpected();
|
||||||
cur.push(statement());
|
cur.push(statement());
|
||||||
}
|
}
|
||||||
@@ -1420,10 +1416,10 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function as_name() {
|
function as_name() {
|
||||||
var tmp = S.token;
|
if (!is("name")) expect_token("name");
|
||||||
if (tmp.type != "name") unexpected();
|
var name = S.token.value;
|
||||||
next();
|
next();
|
||||||
return tmp.value;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _make_symbol(type) {
|
function _make_symbol(type) {
|
||||||
@@ -1625,6 +1621,7 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.expression) {
|
if (options.expression) {
|
||||||
|
handle_regexp();
|
||||||
return expression(true);
|
return expression(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
36
lib/scope.js
36
lib/scope.js
@@ -61,8 +61,6 @@ SymbolDef.next_id = 1;
|
|||||||
|
|
||||||
SymbolDef.prototype = {
|
SymbolDef.prototype = {
|
||||||
unmangleable: function(options) {
|
unmangleable: function(options) {
|
||||||
if (!options) options = {};
|
|
||||||
|
|
||||||
return this.global && !options.toplevel
|
return this.global && !options.toplevel
|
||||||
|| this.undeclared
|
|| this.undeclared
|
||||||
|| !options.eval && this.scope.pinned()
|
|| !options.eval && this.scope.pinned()
|
||||||
@@ -198,24 +196,20 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolLambda) {
|
if (node instanceof AST_SymbolLambda) {
|
||||||
var def = node.thedef;
|
var def = node.thedef;
|
||||||
if (def.orig.length == 1) {
|
redefine(node, node.scope.parent_scope);
|
||||||
redefine(node, node.scope.parent_scope);
|
node.thedef.init = def.init;
|
||||||
node.thedef.init = def.init;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function redefine(node, scope) {
|
function redefine(node, scope) {
|
||||||
var name = node.name;
|
var name = node.name;
|
||||||
var refs = node.thedef.references;
|
var old_def = node.thedef;
|
||||||
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
|
var new_def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
|
||||||
refs.forEach(function(ref) {
|
old_def.orig.concat(old_def.references).forEach(function(node) {
|
||||||
ref.thedef = def;
|
node.thedef = new_def;
|
||||||
ref.reference(options);
|
node.reference(options);
|
||||||
});
|
});
|
||||||
node.thedef = def;
|
|
||||||
node.reference(options);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -300,7 +294,7 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
|
|||||||
|
|
||||||
AST_Lambda.DEFMETHOD("resolve", return_this);
|
AST_Lambda.DEFMETHOD("resolve", return_this);
|
||||||
AST_Scope.DEFMETHOD("resolve", function() {
|
AST_Scope.DEFMETHOD("resolve", function() {
|
||||||
return this.parent_scope;
|
return this.parent_scope.resolve();
|
||||||
});
|
});
|
||||||
AST_Toplevel.DEFMETHOD("resolve", return_this);
|
AST_Toplevel.DEFMETHOD("resolve", return_this);
|
||||||
|
|
||||||
@@ -309,8 +303,12 @@ function names_in_use(scope, options) {
|
|||||||
if (!names) {
|
if (!names) {
|
||||||
scope.names_in_use = names = Object.create(scope.mangled_names || null);
|
scope.names_in_use = names = Object.create(scope.mangled_names || null);
|
||||||
scope.cname_holes = [];
|
scope.cname_holes = [];
|
||||||
|
var cache = options.cache && options.cache.props;
|
||||||
scope.enclosed.forEach(function(def) {
|
scope.enclosed.forEach(function(def) {
|
||||||
if (def.unmangleable(options)) names[def.name] = true;
|
if (def.unmangleable(options)) names[def.name] = true;
|
||||||
|
if (def.global && cache && cache.has(def.name)) {
|
||||||
|
names[cache.get(def.name)] = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return names;
|
return names;
|
||||||
@@ -333,7 +331,7 @@ function next_mangled_name(scope, options, def) {
|
|||||||
} while (scope = scope.parent_scope);
|
} while (scope = scope.parent_scope);
|
||||||
});
|
});
|
||||||
var name;
|
var name;
|
||||||
for (var i = 0, len = holes.length; i < len; i++) {
|
for (var i = 0; i < holes.length; i++) {
|
||||||
name = base54(holes[i]);
|
name = base54(holes[i]);
|
||||||
if (names[name]) continue;
|
if (names[name]) continue;
|
||||||
holes.splice(i, 1);
|
holes.splice(i, 1);
|
||||||
@@ -342,7 +340,7 @@ function next_mangled_name(scope, options, def) {
|
|||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
name = base54(++scope.cname);
|
name = base54(++scope.cname);
|
||||||
if (in_use[name] || !is_identifier(name) || options.reserved.has[name]) continue;
|
if (in_use[name] || RESERVED_WORDS[name] || options.reserved.has[name]) continue;
|
||||||
if (!names[name]) break;
|
if (!names[name]) break;
|
||||||
holes.push(scope.cname);
|
holes.push(scope.cname);
|
||||||
}
|
}
|
||||||
@@ -422,7 +420,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
|||||||
var name;
|
var name;
|
||||||
do {
|
do {
|
||||||
name = base54(++lname);
|
name = base54(++lname);
|
||||||
} while (!is_identifier(name));
|
} while (RESERVED_WORDS[name]);
|
||||||
node.mangled_name = name;
|
node.mangled_name = name;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -493,7 +491,7 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
|||||||
var name;
|
var name;
|
||||||
do {
|
do {
|
||||||
name = base54(cname++);
|
name = base54(cname++);
|
||||||
} while (avoid[name] || !is_identifier(name));
|
} while (avoid[name] || RESERVED_WORDS[name]);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,7 +553,7 @@ var base54 = (function() {
|
|||||||
var freq = Object.create(null);
|
var freq = Object.create(null);
|
||||||
function init(chars) {
|
function init(chars) {
|
||||||
var array = [];
|
var array = [];
|
||||||
for (var i = 0, len = chars.length; i < len; i++) {
|
for (var i = 0; i < chars.length; i++) {
|
||||||
var ch = chars[i];
|
var ch = chars[i];
|
||||||
array.push(ch);
|
array.push(ch);
|
||||||
freq[ch] = -1e-2 * i;
|
freq[ch] = -1e-2 * i;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ function configure_error_stack(fn) {
|
|||||||
err.name = this.name;
|
err.name = this.name;
|
||||||
try {
|
try {
|
||||||
throw err;
|
throw err;
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
return e.stack;
|
return e.stack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
package.json
10
package.json
@@ -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.4.7",
|
"version": "3.5.15",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
@@ -23,15 +23,15 @@
|
|||||||
"LICENSE"
|
"LICENSE"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"commander": "~2.16.0",
|
"commander": "~2.20.0",
|
||||||
"source-map": "~0.6.1"
|
"source-map": "~0.6.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"acorn": "~5.7.1",
|
"acorn": "~6.1.1",
|
||||||
"semver": "~5.5.0"
|
"semver": "~6.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node test/run-tests.js"
|
"test": "node test/compress.js && node test/mocha.js"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"cli",
|
"cli",
|
||||||
|
|||||||
450
test/compress.js
Normal file
450
test/compress.js
Normal file
@@ -0,0 +1,450 @@
|
|||||||
|
var assert = require("assert");
|
||||||
|
var child_process = require("child_process");
|
||||||
|
var fs = require("fs");
|
||||||
|
var path = require("path");
|
||||||
|
var sandbox = require("./sandbox");
|
||||||
|
var semver = require("semver");
|
||||||
|
var U = require("./node");
|
||||||
|
|
||||||
|
var file = process.argv[2];
|
||||||
|
var dir = path.resolve(path.dirname(module.filename), "compress");
|
||||||
|
if (file) {
|
||||||
|
var minify_options = require("./ufuzz.json").map(JSON.stringify);
|
||||||
|
log("--- {file}", { file: file });
|
||||||
|
var tests = parse_test(path.resolve(dir, file));
|
||||||
|
process.exit(Object.keys(tests).filter(function(name) {
|
||||||
|
return !test_case(tests[name]);
|
||||||
|
}).length);
|
||||||
|
} else {
|
||||||
|
var files = fs.readdirSync(dir).filter(function(name) {
|
||||||
|
return /\.js$/i.test(name);
|
||||||
|
});
|
||||||
|
var failures = 0;
|
||||||
|
var failed_files = Object.create(null);
|
||||||
|
(function next() {
|
||||||
|
var file = files.shift();
|
||||||
|
if (file) {
|
||||||
|
child_process.spawn(process.argv[0], [ process.argv[1], file ], {
|
||||||
|
stdio: [ "ignore", 1, 2 ]
|
||||||
|
}).on("exit", function(code) {
|
||||||
|
if (code) {
|
||||||
|
failures += code;
|
||||||
|
failed_files[file] = code;
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
} else if (failures) {
|
||||||
|
console.error();
|
||||||
|
console.error("!!! Failed " + failures + " test case(s).");
|
||||||
|
console.error("!!! " + Object.keys(failed_files).join(", "));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
function evaluate(code) {
|
||||||
|
if (code instanceof U.AST_Node) code = make_code(code, { beautify: true });
|
||||||
|
return new Function("return(" + code + ")")();
|
||||||
|
}
|
||||||
|
|
||||||
|
function log() {
|
||||||
|
console.log("%s", tmpl.apply(null, arguments));
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_code(ast, options) {
|
||||||
|
var stream = U.OutputStream(options);
|
||||||
|
ast.print(stream);
|
||||||
|
return stream.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_test(file) {
|
||||||
|
var script = fs.readFileSync(file, "utf8");
|
||||||
|
// TODO try/catch can be removed after fixing https://github.com/mishoo/UglifyJS2/issues/348
|
||||||
|
try {
|
||||||
|
var ast = U.parse(script, {
|
||||||
|
filename: file
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Caught error while parsing tests in " + file);
|
||||||
|
console.error(e);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
var tests = Object.create(null);
|
||||||
|
var tw = new U.TreeWalker(function(node, descend) {
|
||||||
|
if (node instanceof U.AST_LabeledStatement
|
||||||
|
&& tw.parent() instanceof U.AST_Toplevel) {
|
||||||
|
var name = node.label.name;
|
||||||
|
if (name in tests) {
|
||||||
|
throw new Error('Duplicated test name "' + name + '" in ' + file);
|
||||||
|
}
|
||||||
|
tests[name] = get_one_test(name, node.body);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(node instanceof U.AST_Toplevel)) croak(node);
|
||||||
|
});
|
||||||
|
ast.walk(tw);
|
||||||
|
return tests;
|
||||||
|
|
||||||
|
function croak(node) {
|
||||||
|
throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", {
|
||||||
|
file: file,
|
||||||
|
line: node.start.line,
|
||||||
|
col: node.start.col,
|
||||||
|
code: make_code(node, { beautify: false })
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function read_string(stat) {
|
||||||
|
if (stat.TYPE == "SimpleStatement") {
|
||||||
|
var body = stat.body;
|
||||||
|
switch(body.TYPE) {
|
||||||
|
case "String":
|
||||||
|
return body.value;
|
||||||
|
case "Array":
|
||||||
|
return body.elements.map(function(element) {
|
||||||
|
if (element.TYPE !== "String")
|
||||||
|
throw new Error("Should be array of strings");
|
||||||
|
return element.value;
|
||||||
|
}).join("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error("Should be string or array of strings");
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_one_test(name, block) {
|
||||||
|
var test = { name: name, options: {} };
|
||||||
|
var tw = new U.TreeWalker(function(node, descend) {
|
||||||
|
if (node instanceof U.AST_Assign) {
|
||||||
|
if (!(node.left instanceof U.AST_SymbolRef)) {
|
||||||
|
croak(node);
|
||||||
|
}
|
||||||
|
var name = node.left.name;
|
||||||
|
test[name] = evaluate(node.right);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof U.AST_LabeledStatement) {
|
||||||
|
var label = node.label;
|
||||||
|
assert.ok([
|
||||||
|
"input",
|
||||||
|
"expect",
|
||||||
|
"expect_exact",
|
||||||
|
"expect_warnings",
|
||||||
|
"expect_stdout",
|
||||||
|
"node_version",
|
||||||
|
].indexOf(label.name) >= 0, tmpl("Unsupported label {name} [{line},{col}]", {
|
||||||
|
name: label.name,
|
||||||
|
line: label.start.line,
|
||||||
|
col: label.start.col
|
||||||
|
}));
|
||||||
|
var stat = node.body;
|
||||||
|
if (label.name == "expect_exact" || label.name == "node_version") {
|
||||||
|
test[label.name] = read_string(stat);
|
||||||
|
} else if (label.name == "expect_stdout") {
|
||||||
|
var body = stat.body;
|
||||||
|
if (body instanceof U.AST_Boolean) {
|
||||||
|
test[label.name] = body.value;
|
||||||
|
} else if (body instanceof U.AST_Call) {
|
||||||
|
var ctor = global[body.expression.name];
|
||||||
|
assert.ok(ctor === Error || ctor.prototype instanceof Error, tmpl("Unsupported expect_stdout format [{line},{col}]", {
|
||||||
|
line: label.start.line,
|
||||||
|
col: label.start.col
|
||||||
|
}));
|
||||||
|
test[label.name] = ctor.apply(null, body.args.map(function(node) {
|
||||||
|
assert.ok(node instanceof U.AST_Constant, tmpl("Unsupported expect_stdout format [{line},{col}]", {
|
||||||
|
line: label.start.line,
|
||||||
|
col: label.start.col
|
||||||
|
}));
|
||||||
|
return node.value;
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
test[label.name] = read_string(stat) + "\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
test[label.name] = stat;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
block.walk(tw);
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to reminify original input with standard options
|
||||||
|
// to see if it matches expect_stdout.
|
||||||
|
function reminify(orig_options, input_code, input_formatted, stdout) {
|
||||||
|
for (var i = 0; i < minify_options.length; i++) {
|
||||||
|
var options = JSON.parse(minify_options[i]);
|
||||||
|
if (options.compress) [
|
||||||
|
"keep_fargs",
|
||||||
|
"keep_fnames",
|
||||||
|
].forEach(function(name) {
|
||||||
|
if (name in orig_options) {
|
||||||
|
options.compress[name] = orig_options[name];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var options_formatted = JSON.stringify(options, null, 4);
|
||||||
|
var result = U.minify(input_code, options);
|
||||||
|
if (result.error) {
|
||||||
|
log([
|
||||||
|
"!!! failed input reminify",
|
||||||
|
"---INPUT---",
|
||||||
|
"{input}",
|
||||||
|
"---OPTIONS---",
|
||||||
|
"{options}",
|
||||||
|
"--ERROR---",
|
||||||
|
"{error}",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
].join("\n"), {
|
||||||
|
input: input_formatted,
|
||||||
|
options: options_formatted,
|
||||||
|
error: result.error,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
var expected = stdout[options.toplevel ? 1 : 0];
|
||||||
|
var actual = run_code(result.code, options.toplevel);
|
||||||
|
if (typeof expected != "string" && typeof actual != "string" && expected.name == actual.name) {
|
||||||
|
actual = expected;
|
||||||
|
}
|
||||||
|
if (!sandbox.same_stdout(expected, actual)) {
|
||||||
|
log([
|
||||||
|
"!!! failed running reminified input",
|
||||||
|
"---INPUT---",
|
||||||
|
"{input}",
|
||||||
|
"---OPTIONS---",
|
||||||
|
"{options}",
|
||||||
|
"---OUTPUT---",
|
||||||
|
"{output}",
|
||||||
|
"---EXPECTED {expected_type}---",
|
||||||
|
"{expected}",
|
||||||
|
"---ACTUAL {actual_type}---",
|
||||||
|
"{actual}",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
].join("\n"), {
|
||||||
|
input: input_formatted,
|
||||||
|
options: options_formatted,
|
||||||
|
output: result.code,
|
||||||
|
expected_type: typeof expected == "string" ? "STDOUT" : "ERROR",
|
||||||
|
expected: expected,
|
||||||
|
actual_type: typeof actual == "string" ? "STDOUT" : "ERROR",
|
||||||
|
actual: actual,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_code(code, toplevel) {
|
||||||
|
var result = sandbox.run_code(code, toplevel);
|
||||||
|
return typeof result == "string" ? result.replace(/\u001b\[\d+m/g, "") : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_case(test) {
|
||||||
|
log(" Running test [{name}]", { name: test.name });
|
||||||
|
var output_options = test.beautify || {};
|
||||||
|
var expect;
|
||||||
|
if (test.expect) {
|
||||||
|
expect = make_code(to_toplevel(test.expect, test.mangle), output_options);
|
||||||
|
} else {
|
||||||
|
expect = test.expect_exact;
|
||||||
|
}
|
||||||
|
var input = to_toplevel(test.input, test.mangle);
|
||||||
|
var input_code = make_code(input);
|
||||||
|
var input_formatted = make_code(test.input, {
|
||||||
|
beautify: true,
|
||||||
|
comments: "all",
|
||||||
|
keep_quoted_props: true,
|
||||||
|
quote_style: 3,
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
U.parse(input_code);
|
||||||
|
} catch (ex) {
|
||||||
|
log([
|
||||||
|
"!!! Cannot parse input",
|
||||||
|
"---INPUT---",
|
||||||
|
"{input}",
|
||||||
|
"--PARSE ERROR--",
|
||||||
|
"{error}",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
].join("\n"), {
|
||||||
|
input: input_formatted,
|
||||||
|
error: ex,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var warnings_emitted = [];
|
||||||
|
if (test.expect_warnings) {
|
||||||
|
var expected_warnings = make_code(test.expect_warnings, {
|
||||||
|
beautify: false,
|
||||||
|
quote_style: 2, // force double quote to match JSON
|
||||||
|
});
|
||||||
|
U.AST_Node.log_function(function(text) {
|
||||||
|
warnings_emitted.push(text);
|
||||||
|
}, /"INFO: /.test(expected_warnings));
|
||||||
|
}
|
||||||
|
if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) {
|
||||||
|
var quoted_props = test.mangle.properties.reserved;
|
||||||
|
if (!Array.isArray(quoted_props)) quoted_props = [];
|
||||||
|
test.mangle.properties.reserved = quoted_props;
|
||||||
|
U.reserve_quoted_keys(input, quoted_props);
|
||||||
|
}
|
||||||
|
if (test.rename) {
|
||||||
|
input.figure_out_scope(test.mangle);
|
||||||
|
input.expand_names(test.mangle);
|
||||||
|
}
|
||||||
|
var cmp = new U.Compressor(test.options, true);
|
||||||
|
var output = cmp.compress(input);
|
||||||
|
output.figure_out_scope(test.mangle);
|
||||||
|
if (test.mangle) {
|
||||||
|
output.compute_char_frequency(test.mangle);
|
||||||
|
output.mangle_names(test.mangle);
|
||||||
|
if (test.mangle.properties) {
|
||||||
|
output = U.mangle_properties(output, test.mangle.properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output = make_code(output, output_options);
|
||||||
|
if (expect != output) {
|
||||||
|
log([
|
||||||
|
"!!! failed",
|
||||||
|
"---INPUT---",
|
||||||
|
"{input}",
|
||||||
|
"---OUTPUT---",
|
||||||
|
"{output}",
|
||||||
|
"---EXPECTED---",
|
||||||
|
"{expected}",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
].join("\n"), {
|
||||||
|
input: input_formatted,
|
||||||
|
output: output,
|
||||||
|
expected: expect
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// expect == output
|
||||||
|
try {
|
||||||
|
U.parse(output);
|
||||||
|
} catch (ex) {
|
||||||
|
log([
|
||||||
|
"!!! Test matched expected result but cannot parse output",
|
||||||
|
"---INPUT---",
|
||||||
|
"{input}",
|
||||||
|
"---OUTPUT---",
|
||||||
|
"{output}",
|
||||||
|
"--REPARSE ERROR--",
|
||||||
|
"{error}",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
].join("\n"), {
|
||||||
|
input: input_formatted,
|
||||||
|
output: output,
|
||||||
|
error: ex,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (test.expect_warnings) {
|
||||||
|
warnings_emitted = warnings_emitted.map(function(input) {
|
||||||
|
return input.split(process.cwd() + path.sep).join("").split(path.sep).join("/");
|
||||||
|
});
|
||||||
|
var actual_warnings = JSON.stringify(warnings_emitted);
|
||||||
|
if (expected_warnings != actual_warnings) {
|
||||||
|
log([
|
||||||
|
"!!! failed",
|
||||||
|
"---INPUT---",
|
||||||
|
"{input}",
|
||||||
|
"---EXPECTED WARNINGS---",
|
||||||
|
"{expected_warnings}",
|
||||||
|
"---ACTUAL WARNINGS---",
|
||||||
|
"{actual_warnings}",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
].join("\n"), {
|
||||||
|
input: input_formatted,
|
||||||
|
expected_warnings: expected_warnings,
|
||||||
|
actual_warnings: actual_warnings,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (test.expect_stdout && (!test.node_version || semver.satisfies(process.version, test.node_version))) {
|
||||||
|
var stdout = [ run_code(input_code), run_code(input_code, true) ];
|
||||||
|
var toplevel = test.options.toplevel;
|
||||||
|
var actual = stdout[toplevel ? 1 : 0];
|
||||||
|
if (test.expect_stdout === true) {
|
||||||
|
test.expect_stdout = actual;
|
||||||
|
}
|
||||||
|
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
|
||||||
|
log([
|
||||||
|
"!!! Invalid input or expected stdout",
|
||||||
|
"---INPUT---",
|
||||||
|
"{input}",
|
||||||
|
"---EXPECTED {expected_type}---",
|
||||||
|
"{expected}",
|
||||||
|
"---ACTUAL {actual_type}---",
|
||||||
|
"{actual}",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
].join("\n"), {
|
||||||
|
input: input_formatted,
|
||||||
|
expected_type: typeof test.expect_stdout == "string" ? "STDOUT" : "ERROR",
|
||||||
|
expected: test.expect_stdout,
|
||||||
|
actual_type: typeof actual == "string" ? "STDOUT" : "ERROR",
|
||||||
|
actual: actual,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
actual = run_code(output, toplevel);
|
||||||
|
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
|
||||||
|
log([
|
||||||
|
"!!! failed",
|
||||||
|
"---INPUT---",
|
||||||
|
"{input}",
|
||||||
|
"---EXPECTED {expected_type}---",
|
||||||
|
"{expected}",
|
||||||
|
"---ACTUAL {actual_type}---",
|
||||||
|
"{actual}",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
].join("\n"), {
|
||||||
|
input: input_formatted,
|
||||||
|
expected_type: typeof test.expect_stdout == "string" ? "STDOUT" : "ERROR",
|
||||||
|
expected: test.expect_stdout,
|
||||||
|
actual_type: typeof actual == "string" ? "STDOUT" : "ERROR",
|
||||||
|
actual: actual,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!reminify(test.options, input_code, input_formatted, stdout)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tmpl() {
|
||||||
|
return U.string_template.apply(null, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
function to_toplevel(input, mangle_options) {
|
||||||
|
if (!(input instanceof U.AST_BlockStatement)) throw new Error("Unsupported input syntax");
|
||||||
|
var directive = true;
|
||||||
|
var offset = input.start.line;
|
||||||
|
var tokens = [];
|
||||||
|
var toplevel = new U.AST_Toplevel(input.transform(new U.TreeTransformer(function(node) {
|
||||||
|
if (U.push_uniq(tokens, node.start)) node.start.line -= offset;
|
||||||
|
if (!directive || node === input) return;
|
||||||
|
if (node instanceof U.AST_SimpleStatement && node.body instanceof U.AST_String) {
|
||||||
|
return new U.AST_Directive(node.body);
|
||||||
|
} else {
|
||||||
|
directive = false;
|
||||||
|
}
|
||||||
|
})));
|
||||||
|
toplevel.figure_out_scope(mangle_options);
|
||||||
|
return toplevel;
|
||||||
|
}
|
||||||
@@ -237,3 +237,542 @@ duplicate_argname: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "bar 42 foo 42 bar"
|
expect_stdout: "bar 42 foo 42 bar"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3273: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
arguments[0]++;
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
console.log(a, a);
|
||||||
|
a++;
|
||||||
|
console.log(a, a);
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0 0",
|
||||||
|
"1 1",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3273_reduce_vars: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
arguments[0]++;
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
console.log(a, a);
|
||||||
|
a++;
|
||||||
|
console.log(a, a);
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0 0",
|
||||||
|
"1 1",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3273_local_strict: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
"use strict";
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
arguments[0]++;
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
"use strict";
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
arguments[0]++;
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0 0",
|
||||||
|
"1 0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3273_local_strict_reduce_vars: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
"use strict";
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
arguments[0]++;
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
"use strict";
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
arguments[0]++;
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0 0",
|
||||||
|
"1 0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3273_global_strict: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
function f(a) {
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
arguments[0]++;
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
function f(a) {
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
arguments[0]++;
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0 0",
|
||||||
|
"1 0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3273_global_strict_reduce_vars: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
function f(a) {
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
arguments[0]++;
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
function f(a) {
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
arguments[0]++;
|
||||||
|
console.log(arguments[0], a);
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0 0",
|
||||||
|
"1 0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3273_keep_fargs_false: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
"use strict";
|
||||||
|
arguments[0]++;
|
||||||
|
console.log(arguments[0]);
|
||||||
|
})(0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(argument_0) {
|
||||||
|
"use strict";
|
||||||
|
argument_0++;
|
||||||
|
console.log(argument_0);
|
||||||
|
})(0);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3273_keep_fargs_strict: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
"use strict";
|
||||||
|
arguments[0]++;
|
||||||
|
console.log(arguments[0]);
|
||||||
|
})(0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(argument_0) {
|
||||||
|
"use strict";
|
||||||
|
argument_0++;
|
||||||
|
console.log(argument_0);
|
||||||
|
})(0);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3282_1: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(t) {
|
||||||
|
return function() {
|
||||||
|
t();
|
||||||
|
};
|
||||||
|
})(function() {
|
||||||
|
'use strict';
|
||||||
|
function e() {
|
||||||
|
return arguments[0];
|
||||||
|
}
|
||||||
|
e();
|
||||||
|
e();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
return function() {
|
||||||
|
(function() {
|
||||||
|
"use strict";
|
||||||
|
function e() {
|
||||||
|
return arguments[0];
|
||||||
|
}
|
||||||
|
e();
|
||||||
|
e();
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
})()();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3282_1_passes: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(t) {
|
||||||
|
return function() {
|
||||||
|
t();
|
||||||
|
};
|
||||||
|
})(function() {
|
||||||
|
'use strict';
|
||||||
|
function e() {
|
||||||
|
return arguments[0];
|
||||||
|
}
|
||||||
|
e();
|
||||||
|
e();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
return function() {
|
||||||
|
(function() {
|
||||||
|
"use strict";
|
||||||
|
function e(argument_0) {
|
||||||
|
return argument_0;
|
||||||
|
}
|
||||||
|
e();
|
||||||
|
e();
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
})()();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3282_2: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(f) {
|
||||||
|
f();
|
||||||
|
})(function() {
|
||||||
|
return (function(t) {
|
||||||
|
return function() {
|
||||||
|
t();
|
||||||
|
};
|
||||||
|
})(function() {
|
||||||
|
'use strict';
|
||||||
|
function e() {
|
||||||
|
return arguments[0];
|
||||||
|
}
|
||||||
|
e();
|
||||||
|
e();
|
||||||
|
})();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function() {
|
||||||
|
return function(t) {
|
||||||
|
return function() {
|
||||||
|
t();
|
||||||
|
};
|
||||||
|
}(function() {
|
||||||
|
"use strict";
|
||||||
|
function e() {
|
||||||
|
return arguments[0];
|
||||||
|
}
|
||||||
|
e();
|
||||||
|
e();
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3282_2_passes: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(f) {
|
||||||
|
f();
|
||||||
|
})(function() {
|
||||||
|
return (function(t) {
|
||||||
|
return function() {
|
||||||
|
t();
|
||||||
|
};
|
||||||
|
})(function() {
|
||||||
|
'use strict';
|
||||||
|
function e() {
|
||||||
|
return arguments[0];
|
||||||
|
}
|
||||||
|
e();
|
||||||
|
e();
|
||||||
|
})();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function() {
|
||||||
|
return function(t) {
|
||||||
|
return function() {
|
||||||
|
t();
|
||||||
|
};
|
||||||
|
}(function() {
|
||||||
|
"use strict";
|
||||||
|
function e(argument_0) {
|
||||||
|
return argument_0;
|
||||||
|
}
|
||||||
|
e();
|
||||||
|
e();
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3420_1: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
return function() {
|
||||||
|
return arguments[0];
|
||||||
|
};
|
||||||
|
}().length);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
return function() {
|
||||||
|
return arguments[0];
|
||||||
|
};
|
||||||
|
}().length);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3420_2: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var foo = function() {
|
||||||
|
delete arguments[0];
|
||||||
|
};
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var foo = function() {
|
||||||
|
delete arguments[0];
|
||||||
|
};
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3420_3: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var foo = function() {
|
||||||
|
delete arguments[0];
|
||||||
|
};
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var foo = function() {
|
||||||
|
delete arguments[0];
|
||||||
|
};
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3420_4: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function() {
|
||||||
|
console.log(arguments[0]);
|
||||||
|
delete arguments[0];
|
||||||
|
console.log(arguments[0]);
|
||||||
|
}(42);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function(argument_0) {
|
||||||
|
console.log(argument_0);
|
||||||
|
delete arguments[0];
|
||||||
|
console.log(arguments[0]);
|
||||||
|
}(42);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"42",
|
||||||
|
"undefined",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3420_5: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
!function() {
|
||||||
|
console.log(arguments[0]);
|
||||||
|
delete arguments[0];
|
||||||
|
console.log(arguments[0]);
|
||||||
|
}(42);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
!function(argument_0) {
|
||||||
|
console.log(argument_0);
|
||||||
|
delete arguments[0];
|
||||||
|
console.log(arguments[0]);
|
||||||
|
}(42);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"42",
|
||||||
|
"undefined",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3420_6: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
return delete arguments[0];
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
return delete arguments[0];
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3420_7: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
console.log(function() {
|
||||||
|
return delete arguments[0];
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
console.log(function() {
|
||||||
|
return delete arguments[0];
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|||||||
@@ -239,3 +239,113 @@ index_length: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1 2"
|
expect_stdout: "1 2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor_bad: {
|
||||||
|
options = {
|
||||||
|
unsafe: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
Array(NaN);
|
||||||
|
console.log("FAIL1");
|
||||||
|
} catch (ex) {
|
||||||
|
try {
|
||||||
|
new Array(NaN);
|
||||||
|
console.log("FAIL2");
|
||||||
|
} catch (ex) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Array(3.14);
|
||||||
|
console.log("FAIL1");
|
||||||
|
} catch (ex) {
|
||||||
|
try {
|
||||||
|
new Array(3.14);
|
||||||
|
console.log("FAIL2");
|
||||||
|
} catch (ex) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
Array(NaN);
|
||||||
|
console.log("FAIL1");
|
||||||
|
} catch (ex) {
|
||||||
|
try {
|
||||||
|
Array(NaN);
|
||||||
|
console.log("FAIL2");
|
||||||
|
} catch (ex) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Array(3.14);
|
||||||
|
console.log("FAIL1");
|
||||||
|
} catch (ex) {
|
||||||
|
try {
|
||||||
|
Array(3.14);
|
||||||
|
console.log("FAIL2");
|
||||||
|
} catch (ex) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: Invalid array length: 3.14 [test/compress/arrays.js:13,12]",
|
||||||
|
"WARN: Invalid array length: 3.14 [test/compress/arrays.js:17,16]",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor_good: {
|
||||||
|
options = {
|
||||||
|
unsafe: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(Array());
|
||||||
|
console.log(Array(0));
|
||||||
|
console.log(Array(1));
|
||||||
|
console.log(Array(6));
|
||||||
|
console.log(Array(7));
|
||||||
|
console.log(Array(1, 2));
|
||||||
|
console.log(Array(false));
|
||||||
|
console.log(Array("foo"));
|
||||||
|
console.log(Array(Array));
|
||||||
|
console.log(new Array());
|
||||||
|
console.log(new Array(0));
|
||||||
|
console.log(new Array(1));
|
||||||
|
console.log(new Array(6));
|
||||||
|
console.log(new Array(7));
|
||||||
|
console.log(new Array(1, 2));
|
||||||
|
console.log(new Array(false));
|
||||||
|
console.log(new Array("foo"));
|
||||||
|
console.log(new Array(Array));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log([]);
|
||||||
|
console.log([]);
|
||||||
|
console.log([,]);
|
||||||
|
console.log([,,,,,,]);
|
||||||
|
console.log(Array(7));
|
||||||
|
console.log([ 1, 2 ]);
|
||||||
|
console.log([ false ]);
|
||||||
|
console.log([ "foo" ]);
|
||||||
|
console.log(Array(Array));
|
||||||
|
console.log([]);
|
||||||
|
console.log([]);
|
||||||
|
console.log([,]);
|
||||||
|
console.log([,,,,,,]);
|
||||||
|
console.log(Array(7));
|
||||||
|
console.log([ 1, 2 ]);
|
||||||
|
console.log([ false ]);
|
||||||
|
console.log([ "foo" ]);
|
||||||
|
console.log(Array(Array));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
expect_warnings: []
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
asm_mixed: {
|
asm_mixed: {
|
||||||
options = {
|
options = {
|
||||||
|
assignments: true,
|
||||||
booleans: true,
|
booleans: true,
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
op_equals_left_local_var: {
|
op_equals_left_local_var: {
|
||||||
options = {
|
options = {
|
||||||
|
assignments: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -60,6 +61,7 @@ op_equals_left_local_var: {
|
|||||||
|
|
||||||
op_equals_right_local_var: {
|
op_equals_right_local_var: {
|
||||||
options = {
|
options = {
|
||||||
|
assignments: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -123,6 +125,7 @@ op_equals_right_local_var: {
|
|||||||
}
|
}
|
||||||
op_equals_left_global_var: {
|
op_equals_left_global_var: {
|
||||||
options = {
|
options = {
|
||||||
|
assignments: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -179,6 +182,7 @@ op_equals_left_global_var: {
|
|||||||
|
|
||||||
op_equals_right_global_var: {
|
op_equals_right_global_var: {
|
||||||
options = {
|
options = {
|
||||||
|
assignments: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -236,3 +240,74 @@ op_equals_right_global_var: {
|
|||||||
x = g() & x;
|
x = g() & x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
increment_decrement_1: {
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
a += 1;
|
||||||
|
a -= 1;
|
||||||
|
return a;
|
||||||
|
}(42));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a){
|
||||||
|
++a;
|
||||||
|
--a;
|
||||||
|
return a;
|
||||||
|
}(42));
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
increment_decrement_2: {
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
a = a + 1;
|
||||||
|
a = a - 1;
|
||||||
|
a += 1;
|
||||||
|
a -= 1;
|
||||||
|
return a;
|
||||||
|
}(42));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a){
|
||||||
|
++a;
|
||||||
|
--a;
|
||||||
|
++a;
|
||||||
|
--a;
|
||||||
|
return a;
|
||||||
|
}(42));
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3375: {
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(typeof function(b) {
|
||||||
|
var a = b += 1;
|
||||||
|
--b;
|
||||||
|
return a;
|
||||||
|
}("object"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(typeof function(b) {
|
||||||
|
var a = b += 1;
|
||||||
|
--b;
|
||||||
|
return a;
|
||||||
|
}("object"));
|
||||||
|
}
|
||||||
|
expect_stdout: "string"
|
||||||
|
}
|
||||||
|
|||||||
@@ -944,10 +944,10 @@ collapse_vars_misc1: {
|
|||||||
function f5(x) { var z = foo(); return (5 - window.x) / z }
|
function f5(x) { var z = foo(); return (5 - window.x) / z }
|
||||||
function f6() { return window.a * window.z && zap() }
|
function f6() { return window.a * window.z && zap() }
|
||||||
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 + (b + 5) }
|
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) { var a = 5; return a += 3; }
|
||||||
function f11(x) { var a = 5, b = 3; return a += --b; }
|
function f11(x) { var a = 5; return a += 2; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3497,10 +3497,10 @@ issue_2437_1: {
|
|||||||
return Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
|
return Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
|
||||||
result;
|
result;
|
||||||
}
|
}
|
||||||
var req, detectFunc = function(){};
|
var req = new XMLHttpRequest(), detectFunc = function(){};
|
||||||
(req = new XMLHttpRequest()).onreadystatechange = detectFunc;
|
return req.onreadystatechange = detectFunc,
|
||||||
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
|
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc,
|
||||||
return req.onreadystatechange = null, result;
|
req.onreadystatechange = null, result;
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3545,8 +3545,8 @@ issue_2437_2: {
|
|||||||
if (xhrDesc)
|
if (xhrDesc)
|
||||||
return (req = new XMLHttpRequest()).onreadystatechange,
|
return (req = new XMLHttpRequest()).onreadystatechange,
|
||||||
Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {});
|
Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {});
|
||||||
var req;
|
var req = new XMLHttpRequest();
|
||||||
(req = new XMLHttpRequest).onreadystatechange = function(){},
|
req.onreadystatechange = function(){},
|
||||||
req[SYMBOL_FAKE_ONREADYSTATECHANGE_1],
|
req[SYMBOL_FAKE_ONREADYSTATECHANGE_1],
|
||||||
req.onreadystatechange = null;
|
req.onreadystatechange = null;
|
||||||
}();
|
}();
|
||||||
@@ -3895,11 +3895,11 @@ issue_2436_10: {
|
|||||||
o = { b: 3 };
|
o = { b: 3 };
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
console.log((c = o, [
|
console.log([
|
||||||
c.a,
|
(c = o).a,
|
||||||
f(c.b),
|
f(c.b),
|
||||||
c.b,
|
c.b,
|
||||||
]).join(" "));
|
].join(" "));
|
||||||
var c;
|
var c;
|
||||||
}
|
}
|
||||||
expect_stdout: "1 2 2"
|
expect_stdout: "1 2 2"
|
||||||
@@ -4194,7 +4194,7 @@ may_throw_2: {
|
|||||||
var a = x();
|
var a = x();
|
||||||
++b;
|
++b;
|
||||||
return b(a);
|
return b(a);
|
||||||
} catch(e) {}
|
} catch (e) {}
|
||||||
console.log(b);
|
console.log(b);
|
||||||
}
|
}
|
||||||
f(0);
|
f(0);
|
||||||
@@ -4204,7 +4204,7 @@ may_throw_2: {
|
|||||||
try {
|
try {
|
||||||
var a = x();
|
var a = x();
|
||||||
return (++b)(a);
|
return (++b)(a);
|
||||||
} catch(e) {}
|
} catch (e) {}
|
||||||
console.log(b);
|
console.log(b);
|
||||||
}
|
}
|
||||||
f(0);
|
f(0);
|
||||||
@@ -5827,3 +5827,373 @@ issue_3215_4: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "number"
|
expect_stdout: "number"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3238_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b, c;
|
||||||
|
if (a) {
|
||||||
|
b = Object.create(null);
|
||||||
|
c = Object.create(null);
|
||||||
|
}
|
||||||
|
return b === c;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
var b, c;
|
||||||
|
if (a) {
|
||||||
|
b = Object.create(null);
|
||||||
|
c = Object.create(null);
|
||||||
|
}
|
||||||
|
return b === c;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "true false"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3238_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b, c;
|
||||||
|
if (a) {
|
||||||
|
b = Error();
|
||||||
|
c = Error();
|
||||||
|
}
|
||||||
|
return b === c;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
var b, c;
|
||||||
|
if (a) {
|
||||||
|
b = Error();
|
||||||
|
c = Error();
|
||||||
|
}
|
||||||
|
return b === c;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "true false"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3238_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b, c;
|
||||||
|
if (a) {
|
||||||
|
b = new Date();
|
||||||
|
c = new Date();
|
||||||
|
}
|
||||||
|
return b === c;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
var b, c;
|
||||||
|
if (a) {
|
||||||
|
b = new Date();
|
||||||
|
c = new Date();
|
||||||
|
}
|
||||||
|
return b === c;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "true false"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3238_4: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b, c;
|
||||||
|
if (a) {
|
||||||
|
b = a && {};
|
||||||
|
c = a && {};
|
||||||
|
}
|
||||||
|
return b === c;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
var b, c;
|
||||||
|
if (a) {
|
||||||
|
b = a && {};
|
||||||
|
c = a && {};
|
||||||
|
}
|
||||||
|
return b === c;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "true false"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3238_5: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b, c;
|
||||||
|
if (a) {
|
||||||
|
b = a ? [] : 42;
|
||||||
|
c = a ? [] : 42;
|
||||||
|
}
|
||||||
|
return b === c;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
var b, c;
|
||||||
|
if (a) {
|
||||||
|
b = a ? [] : 42;
|
||||||
|
c = a ? [] : 42;
|
||||||
|
}
|
||||||
|
return b === c;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "true false"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3238_6: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b, c;
|
||||||
|
if (a) {
|
||||||
|
b = a && 0 || [];
|
||||||
|
c = a && 0 || [];
|
||||||
|
}
|
||||||
|
return b === c;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
var b, c;
|
||||||
|
if (a) {
|
||||||
|
b = a && 0 || [];
|
||||||
|
c = a && 0 || [];
|
||||||
|
}
|
||||||
|
return b === c;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "true false"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3247: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(o) {
|
||||||
|
console.log(o.p);
|
||||||
|
}
|
||||||
|
var a;
|
||||||
|
a = Object({ p: "PASS" });
|
||||||
|
a.q = true;
|
||||||
|
f(a, true);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(o) {
|
||||||
|
console.log(o.p);
|
||||||
|
}
|
||||||
|
var a;
|
||||||
|
(a = Object({ p: "PASS" })).q = true;
|
||||||
|
f(a, true);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3305: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function calc(a) {
|
||||||
|
var x, w;
|
||||||
|
if (a) {
|
||||||
|
x = a;
|
||||||
|
w = 1;
|
||||||
|
} else {
|
||||||
|
x = 1;
|
||||||
|
w = 0;
|
||||||
|
}
|
||||||
|
return add(x, w);
|
||||||
|
}
|
||||||
|
function add(x, w) {
|
||||||
|
return x + w;
|
||||||
|
}
|
||||||
|
console.log(calc(41));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function calc(a) {
|
||||||
|
var x, w;
|
||||||
|
return w = a ? (x = a, 1) : (x = 1, 0), add(x, w);
|
||||||
|
}
|
||||||
|
function add(x, w) {
|
||||||
|
return x + w;
|
||||||
|
}
|
||||||
|
console.log(calc(41));
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3314: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function test(a, b) {
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
var a = "FAIL", b;
|
||||||
|
b = a = "PASS";
|
||||||
|
test(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function test(a, b) {
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
var a = "FAIL", b;
|
||||||
|
b = a = "PASS";
|
||||||
|
test(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3327: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b, l = ["PASS", 42];
|
||||||
|
if (l.length === 1) {
|
||||||
|
a = l[0].a;
|
||||||
|
b = l[0].b;
|
||||||
|
} else {
|
||||||
|
a = l[0];
|
||||||
|
b = l[1];
|
||||||
|
}
|
||||||
|
function echo(a, b) {
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
echo(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b, l = ["PASS", 42];
|
||||||
|
function echo(a, b) {
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
b = 1 === l.length ? (a = l[0].a, l[0].b) : (a = l[0], l[1]),
|
||||||
|
echo(a,b);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
assign_left: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
(b = a, b.p).q = "PASS";
|
||||||
|
return a.p.q;
|
||||||
|
}({p: {}}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
(b = a).p.q = "PASS";
|
||||||
|
return a.p.q;
|
||||||
|
}({p: {}}));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
sub_property: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
return a[(b = a, b.length - 1)];
|
||||||
|
}([ "FAIL", "PASS" ]));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
return a[(b = a).length - 1];
|
||||||
|
}([ "FAIL", "PASS" ]));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
assign_undeclared: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var A = (console.log(42), function() {});
|
||||||
|
B = new A();
|
||||||
|
console.log(typeof B);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
B = new (console.log(42), function() {})();
|
||||||
|
console.log(typeof B);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"42",
|
||||||
|
"object",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Infinity_assignment: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var Infinity;
|
||||||
|
Infinity = 42;
|
||||||
|
console.log(Infinity);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var Infinity;
|
||||||
|
Infinity = 42;
|
||||||
|
console.log(Infinity);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|||||||
@@ -323,3 +323,120 @@ is_number_unsafe: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "true"
|
expect_stdout: "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_boolean_var: {
|
||||||
|
options = {
|
||||||
|
comparisons: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
for (var i = 0, c = !b; i < a.length; i++)
|
||||||
|
if (!a[i] === c)
|
||||||
|
return i;
|
||||||
|
}([ false, true ], 42));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
for (var i = 0, c = !b; i < a.length; i++)
|
||||||
|
if (!a[i] == c)
|
||||||
|
return i;
|
||||||
|
}([ false, true ], 42));
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_defined: {
|
||||||
|
options = {
|
||||||
|
comparisons: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function a() {
|
||||||
|
return void 0 === a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function a() {
|
||||||
|
return a, false;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: Expression always defined [test/compress/comparisons.js:2,19]",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_indexOf: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
comparisons: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = Object.keys({ foo: 42 });
|
||||||
|
if (a.indexOf("bar") < 0) console.log("PASS");
|
||||||
|
if (0 > a.indexOf("bar")) console.log("PASS");
|
||||||
|
if (a.indexOf("foo") >= 0) console.log("PASS");
|
||||||
|
if (0 <= a.indexOf("foo")) console.log("PASS");
|
||||||
|
if (a.indexOf("foo") > -1) console.log("PASS");
|
||||||
|
if (-1 < a.indexOf("foo")) console.log("PASS");
|
||||||
|
if (a.indexOf("bar") == -1) console.log("PASS");
|
||||||
|
if (-1 == a.indexOf("bar")) console.log("PASS");
|
||||||
|
if (a.indexOf("bar") === -1) console.log("PASS");
|
||||||
|
if (-1 === a.indexOf("bar")) console.log("PASS");
|
||||||
|
if (a.indexOf("foo") != -1) console.log("PASS");
|
||||||
|
if (-1 != a.indexOf("foo")) console.log("PASS");
|
||||||
|
if (a.indexOf("foo") !== -1) console.log("PASS");
|
||||||
|
if (-1 !== a.indexOf("foo")) console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = Object.keys({ foo: 42 });
|
||||||
|
if (!~a.indexOf("bar")) console.log("PASS");
|
||||||
|
if (!~a.indexOf("bar")) console.log("PASS");
|
||||||
|
if (~a.indexOf("foo")) console.log("PASS");
|
||||||
|
if (~a.indexOf("foo")) console.log("PASS");
|
||||||
|
if (~a.indexOf("foo")) console.log("PASS");
|
||||||
|
if (~a.indexOf("foo")) console.log("PASS");
|
||||||
|
if (!~a.indexOf("bar")) console.log("PASS");
|
||||||
|
if (!~a.indexOf("bar")) console.log("PASS");
|
||||||
|
if (!~a.indexOf("bar")) console.log("PASS");
|
||||||
|
if (!~a.indexOf("bar")) console.log("PASS");
|
||||||
|
if (~a.indexOf("foo")) console.log("PASS");
|
||||||
|
if (~a.indexOf("foo")) console.log("PASS");
|
||||||
|
if (~a.indexOf("foo")) console.log("PASS");
|
||||||
|
if (~a.indexOf("foo")) console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3413: {
|
||||||
|
options = {
|
||||||
|
comparisons: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b;
|
||||||
|
void 0 !== ("" < b || void 0) || console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b;
|
||||||
|
void 0 !== ("" < b || void 0) || console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
@@ -1292,3 +1292,182 @@ to_and_or: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cond_seq_assign_1: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var t;
|
||||||
|
if (a) {
|
||||||
|
t = "foo";
|
||||||
|
t = "bar";
|
||||||
|
} else {
|
||||||
|
console.log(t);
|
||||||
|
t = 42;
|
||||||
|
}
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
f(f);
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
var t;
|
||||||
|
t = a ? (t = "foo", "bar") : (console.log(t), 42),
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
f(f),
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"bar",
|
||||||
|
"undefined",
|
||||||
|
"42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
cond_seq_assign_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var t;
|
||||||
|
if (a) {
|
||||||
|
t = "foo";
|
||||||
|
a = "bar";
|
||||||
|
} else {
|
||||||
|
console.log(t);
|
||||||
|
t = 42;
|
||||||
|
}
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
f(f);
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
var t;
|
||||||
|
a ? (t = "foo", a = "bar") : (console.log(t), t = 42),
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
f(f),
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"undefined",
|
||||||
|
"42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
cond_seq_assign_3: {
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
if (this)
|
||||||
|
c = 1 + c, c = c + 1;
|
||||||
|
else
|
||||||
|
c = 1 + c, c = c + 1;
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
this, c = 1 + c, c += 1;
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3271: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var i = 0, b = [];
|
||||||
|
if (a) {
|
||||||
|
b[i++] = 4,
|
||||||
|
b[i++] = 1;
|
||||||
|
} else {
|
||||||
|
b[i++] = 3,
|
||||||
|
b[i++] = 2,
|
||||||
|
b[i++] = 1;
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
console.log(f(0).pop(), f(1).pop());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
var i = 0, b = [];
|
||||||
|
a ? b[i++] = 4 : (b[i++] = 3, b[i++] = 2),
|
||||||
|
b[i++] = 1;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
console.log(f(0).pop(), f(1).pop());
|
||||||
|
}
|
||||||
|
expect_stdout: "1 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
iife_condition: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if (function() {
|
||||||
|
return console;
|
||||||
|
}())
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
return console;
|
||||||
|
}() || console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
angularjs_chain: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
passes: 2,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function nonComputedMember(left, right, context, create) {
|
||||||
|
var lhs = left();
|
||||||
|
if (create && create !== 1) {
|
||||||
|
if (lhs && lhs[right] == null) {
|
||||||
|
lhs[right] = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var value = lhs != null ? lhs[right] : undefined;
|
||||||
|
if (context) {
|
||||||
|
return { context: lhs, name: right, value: value };
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function nonComputedMember(left, right, context, create) {
|
||||||
|
var lhs = left();
|
||||||
|
create && 1 !== create && lhs && null == lhs[right] && (lhs[right] = {});
|
||||||
|
var value = null != lhs ? lhs[right] : void 0;
|
||||||
|
return context ? {
|
||||||
|
context: lhs,
|
||||||
|
name: right,
|
||||||
|
value: value
|
||||||
|
} : value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -942,3 +942,74 @@ issue_2929: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe_string_replace: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"foo".replace("f", function() {
|
||||||
|
console.log("PASS");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"foo".replace("f", function() {
|
||||||
|
console.log("PASS");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3402: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
functions: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
typeofs: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var f = function f() {
|
||||||
|
f = 42;
|
||||||
|
console.log(typeof f);
|
||||||
|
};
|
||||||
|
"function" == typeof f && f();
|
||||||
|
"function" == typeof f && f();
|
||||||
|
console.log(typeof f);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
console.log(typeof f);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
f();
|
||||||
|
console.log(typeof f);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"function",
|
||||||
|
"function",
|
||||||
|
"function",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3406: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function f(a) {
|
||||||
|
return delete (f = a);
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function f(a) {
|
||||||
|
return delete (0, a);
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ unused_var_in_catch: {
|
|||||||
function foo() {
|
function foo() {
|
||||||
try {
|
try {
|
||||||
foo();
|
foo();
|
||||||
} catch(ex) {
|
} catch (ex) {
|
||||||
var x = 10;
|
var x = 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ unused_var_in_catch: {
|
|||||||
function foo() {
|
function foo() {
|
||||||
try {
|
try {
|
||||||
foo();
|
foo();
|
||||||
} catch(ex) {}
|
} catch (ex) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,7 +166,7 @@ used_var_in_catch: {
|
|||||||
function foo() {
|
function foo() {
|
||||||
try {
|
try {
|
||||||
foo();
|
foo();
|
||||||
} catch(ex) {
|
} catch (ex) {
|
||||||
var x = 10;
|
var x = 10;
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
@@ -176,7 +176,7 @@ used_var_in_catch: {
|
|||||||
function foo() {
|
function foo() {
|
||||||
try {
|
try {
|
||||||
foo();
|
foo();
|
||||||
} catch(ex) {
|
} catch (ex) {
|
||||||
var x = 10;
|
var x = 10;
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
@@ -797,6 +797,7 @@ assign_chain: {
|
|||||||
issue_1583: {
|
issue_1583: {
|
||||||
options = {
|
options = {
|
||||||
keep_fargs: true,
|
keep_fargs: true,
|
||||||
|
passes: 2,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -1004,7 +1005,7 @@ issue_1715_4: {
|
|||||||
delete_assign_1: {
|
delete_assign_1: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
side_effects: true,
|
evaluate: true,
|
||||||
toplevel: true,
|
toplevel: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -1023,7 +1024,7 @@ delete_assign_1: {
|
|||||||
console.log((1 / 0, !0));
|
console.log((1 / 0, !0));
|
||||||
console.log((1 / 0, !0));
|
console.log((1 / 0, !0));
|
||||||
console.log((NaN, !0));
|
console.log((NaN, !0));
|
||||||
console.log((0 / 0, !0));
|
console.log((NaN, !0));
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
@@ -1031,8 +1032,8 @@ delete_assign_1: {
|
|||||||
delete_assign_2: {
|
delete_assign_2: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
keep_infinity: true,
|
keep_infinity: true,
|
||||||
side_effects: true,
|
|
||||||
toplevel: true,
|
toplevel: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -1051,7 +1052,7 @@ delete_assign_2: {
|
|||||||
console.log((Infinity, !0));
|
console.log((Infinity, !0));
|
||||||
console.log((1 / 0, !0));
|
console.log((1 / 0, !0));
|
||||||
console.log((NaN, !0));
|
console.log((NaN, !0));
|
||||||
console.log((0 / 0, !0));
|
console.log((NaN, !0));
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
@@ -1144,6 +1145,7 @@ var_catch_toplevel: {
|
|||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
negate_iife: true,
|
negate_iife: true,
|
||||||
|
passes: 2,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -1156,7 +1158,7 @@ var_catch_toplevel: {
|
|||||||
try {
|
try {
|
||||||
a++;
|
a++;
|
||||||
x();
|
x();
|
||||||
} catch(a) {
|
} catch (a) {
|
||||||
if (a) var a;
|
if (a) var a;
|
||||||
var a = 10;
|
var a = 10;
|
||||||
}
|
}
|
||||||
@@ -1167,7 +1169,7 @@ var_catch_toplevel: {
|
|||||||
!function() {
|
!function() {
|
||||||
try {
|
try {
|
||||||
x();
|
x();
|
||||||
} catch(a) {
|
} catch (a) {
|
||||||
var a;
|
var a;
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
@@ -1982,3 +1984,47 @@ issue_3192: {
|
|||||||
"foo bar",
|
"foo bar",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3233: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = function b() {
|
||||||
|
b.c = "PASS";
|
||||||
|
};
|
||||||
|
a();
|
||||||
|
console.log(a.c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = function b() {
|
||||||
|
b.c = "PASS";
|
||||||
|
};
|
||||||
|
a();
|
||||||
|
console.log(a.c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3375: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 1;
|
||||||
|
var a = c = [], c = --b + ("function" == typeof f && f());
|
||||||
|
var a = c && c[a];
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 1;
|
||||||
|
var a = [], c = --b + ("function" == typeof f && f());
|
||||||
|
a = c && c[a];
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "0 0"
|
||||||
|
}
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ unsafe_constant: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(
|
console.log(
|
||||||
true.a,
|
void 0,
|
||||||
false.a,
|
false.a,
|
||||||
null.a,
|
null.a,
|
||||||
(void 0).a
|
(void 0).a
|
||||||
@@ -278,7 +278,7 @@ unsafe_object: {
|
|||||||
o + 1,
|
o + 1,
|
||||||
2,
|
2,
|
||||||
o.b + 1,
|
o.b + 1,
|
||||||
1..b + 1
|
NaN
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
@@ -365,7 +365,7 @@ unsafe_object_repeated: {
|
|||||||
o + 1,
|
o + 1,
|
||||||
2,
|
2,
|
||||||
o.b + 1,
|
o.b + 1,
|
||||||
1..b + 1
|
NaN
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
@@ -444,8 +444,8 @@ unsafe_integer_key: {
|
|||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
({0:1})[1] + 1,
|
({0:1})[1] + 1,
|
||||||
1[1] + 1,
|
NaN,
|
||||||
1["1"] + 1
|
NaN
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
@@ -500,8 +500,8 @@ unsafe_float_key: {
|
|||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
({2.72:1})[3.14] + 1,
|
({2.72:1})[3.14] + 1,
|
||||||
1[3.14] + 1,
|
NaN,
|
||||||
1["3.14"] + 1
|
NaN
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
@@ -635,12 +635,12 @@ unsafe_string_bad_index: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(
|
console.log(
|
||||||
"1234".a + 1,
|
NaN,
|
||||||
"1234"["a"] + 1,
|
NaN,
|
||||||
"1234"[3.14] + 1
|
NaN
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: "NaN NaN NaN"
|
||||||
}
|
}
|
||||||
|
|
||||||
prototype_function: {
|
prototype_function: {
|
||||||
@@ -820,8 +820,8 @@ unsafe_charAt_noop: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(
|
console.log(
|
||||||
s.charAt(0),
|
s[0],
|
||||||
"string".charAt(x),
|
"string"[0 | x],
|
||||||
(typeof x)[0]
|
(typeof x)[0]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1124,14 +1124,14 @@ issue_2207_1: {
|
|||||||
console.log(Math.max(3, 6, 2, 7, 3, 4));
|
console.log(Math.max(3, 6, 2, 7, 3, 4));
|
||||||
console.log(Math.cos(1.2345));
|
console.log(Math.cos(1.2345));
|
||||||
console.log(Math.cos(1.2345) - Math.sin(4.321));
|
console.log(Math.cos(1.2345) - Math.sin(4.321));
|
||||||
console.log(Math.pow(Math.PI, Math.E - Math.LN10));
|
console.log(Math.pow(Math.PI, Math.E - Math.LN10).toFixed(15));
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log("A");
|
console.log("A");
|
||||||
console.log(7);
|
console.log(7);
|
||||||
console.log(Math.cos(1.2345));
|
console.log(Math.cos(1.2345));
|
||||||
console.log(1.2543732512566947);
|
console.log(1.2543732512566947);
|
||||||
console.log(1.6093984514472044);
|
console.log("1.609398451447204");
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
@@ -1245,12 +1245,12 @@ self_comparison_1: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var o = { n: NaN };
|
var o = { n: NaN };
|
||||||
console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n);
|
console.log(typeof o.n, o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(false, false, true, true, "number");
|
console.log("number", false, false, true, true);
|
||||||
}
|
}
|
||||||
expect_stdout: "false false true true 'number'"
|
expect_stdout: "number false false true true"
|
||||||
}
|
}
|
||||||
|
|
||||||
self_comparison_2: {
|
self_comparison_2: {
|
||||||
@@ -1265,12 +1265,12 @@ self_comparison_2: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var o = { n: NaN };
|
var o = { n: NaN };
|
||||||
console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n);
|
console.log(typeof o.n, o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(false, false, true, true, "number");
|
console.log("number", false, false, true, true);
|
||||||
}
|
}
|
||||||
expect_stdout: "false false true true 'number'"
|
expect_stdout: "number false false true true"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2535_1: {
|
issue_2535_1: {
|
||||||
@@ -1540,7 +1540,7 @@ issue_2926_2: {
|
|||||||
expect_stdout: "function"
|
expect_stdout: "function"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2968: {
|
issue_2968_1: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -1571,6 +1571,39 @@ issue_2968: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2968_2: {
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
(function(a, b) {
|
||||||
|
a <<= 0;
|
||||||
|
a && (a[(c = "PASS", 0 >>> (b += 1))] = 0);
|
||||||
|
})(42, -42);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
a = 42,
|
||||||
|
((a <<= 0) && (a[(c = "PASS", 0)] = 0));
|
||||||
|
var a;
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
truthy_conditionals: {
|
truthy_conditionals: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
@@ -1610,3 +1643,117 @@ truthy_loops: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if_increment: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
if (console)
|
||||||
|
return ++a;
|
||||||
|
}(0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
if (console)
|
||||||
|
return 1;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
try_increment: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
try {
|
||||||
|
return ++a;
|
||||||
|
} catch (e) {}
|
||||||
|
}(0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
try {
|
||||||
|
return 1;
|
||||||
|
} catch (e) {}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_escaped: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 3,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
console.log(function(index) {
|
||||||
|
return a[index];
|
||||||
|
}(function(term) {
|
||||||
|
return a.indexOf(term);
|
||||||
|
}("PASS")));
|
||||||
|
})([ "PASS" ]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_string_replace: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"foo".replace("f", function() {
|
||||||
|
console.log("PASS");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"foo".replace("f", function() {
|
||||||
|
console.log("PASS");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3387_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(1 + (2 + "3"[4]));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(1 + (2 + "3"[4]));
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3387_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(1 + (2 + "3"[4]));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(NaN);
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|||||||
@@ -358,6 +358,7 @@ inner_ref: {
|
|||||||
|
|
||||||
issue_2107: {
|
issue_2107: {
|
||||||
options = {
|
options = {
|
||||||
|
assignments: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
passes: 3,
|
passes: 3,
|
||||||
@@ -387,6 +388,7 @@ issue_2107: {
|
|||||||
|
|
||||||
issue_2114_1: {
|
issue_2114_1: {
|
||||||
options = {
|
options = {
|
||||||
|
assignments: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
@@ -419,6 +421,7 @@ issue_2114_1: {
|
|||||||
|
|
||||||
issue_2114_2: {
|
issue_2114_2: {
|
||||||
options = {
|
options = {
|
||||||
|
assignments: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
@@ -1223,6 +1226,7 @@ issue_2630_1: {
|
|||||||
|
|
||||||
issue_2630_2: {
|
issue_2630_2: {
|
||||||
options = {
|
options = {
|
||||||
|
assignments: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
passes: 2,
|
passes: 2,
|
||||||
@@ -1320,6 +1324,7 @@ issue_2630_4: {
|
|||||||
|
|
||||||
issue_2630_5: {
|
issue_2630_5: {
|
||||||
options = {
|
options = {
|
||||||
|
assignments: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
@@ -1398,6 +1403,8 @@ recursive_inline_2: {
|
|||||||
issue_2657: {
|
issue_2657: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -2315,3 +2322,829 @@ issue_3125: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3274: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
loops: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var g = function(a) {
|
||||||
|
var c = a.p, b = c;
|
||||||
|
return b != c;
|
||||||
|
};
|
||||||
|
while (g(1))
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
for (var c; void 0, (c = 1..p) != c;)
|
||||||
|
console.log("FAIL");
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3297_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
function function1() {
|
||||||
|
var r = {
|
||||||
|
function2: function2
|
||||||
|
};
|
||||||
|
function function2() {
|
||||||
|
alert(1234);
|
||||||
|
function function3() {
|
||||||
|
function2();
|
||||||
|
};
|
||||||
|
function3();
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function function1() {
|
||||||
|
return {
|
||||||
|
function2: function n() {
|
||||||
|
alert(1234);
|
||||||
|
function t() {
|
||||||
|
n();
|
||||||
|
}
|
||||||
|
t();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3297_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
function function1(session) {
|
||||||
|
var public = {
|
||||||
|
processBulk: processBulk
|
||||||
|
};
|
||||||
|
return public;
|
||||||
|
function processBulk(bulk) {
|
||||||
|
var subparam1 = session();
|
||||||
|
function processOne(param1) {
|
||||||
|
var param2 = {
|
||||||
|
subparam1: subparam1
|
||||||
|
};
|
||||||
|
doProcessOne({
|
||||||
|
param1: param1,
|
||||||
|
param2: param2,
|
||||||
|
}, function () {
|
||||||
|
processBulk(bulk);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
if (bulk && bulk.length > 0)
|
||||||
|
processOne(bulk.shift());
|
||||||
|
}
|
||||||
|
function doProcessOne(config, callback) {
|
||||||
|
console.log(JSON.stringify(config));
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function1(function session() {
|
||||||
|
return 42;
|
||||||
|
}).processBulk([1, 2, 3]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function function1(o) {
|
||||||
|
return {
|
||||||
|
processBulk: function t(u) {
|
||||||
|
var r = o();
|
||||||
|
function n(n) {
|
||||||
|
var o = {
|
||||||
|
subparam1: r
|
||||||
|
};
|
||||||
|
c({
|
||||||
|
param1: n,
|
||||||
|
param2: o
|
||||||
|
}, function() {
|
||||||
|
t(u);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
u && u.length > 0 && n(u.shift());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function c(n, o) {
|
||||||
|
console.log(JSON.stringify(n));
|
||||||
|
o();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function1(function() {
|
||||||
|
return 42;
|
||||||
|
}).processBulk([ 1, 2, 3 ]);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
'{"param1":1,"param2":{"subparam1":42}}',
|
||||||
|
'{"param1":2,"param2":{"subparam1":42}}',
|
||||||
|
'{"param1":3,"param2":{"subparam1":42}}',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3297_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
comparisons: true,
|
||||||
|
conditionals: true,
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
passes: 3,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
function function1(session) {
|
||||||
|
var public = {
|
||||||
|
processBulk: processBulk
|
||||||
|
};
|
||||||
|
return public;
|
||||||
|
function processBulk(bulk) {
|
||||||
|
var subparam1 = session();
|
||||||
|
function processOne(param1) {
|
||||||
|
var param2 = {
|
||||||
|
subparam1: subparam1
|
||||||
|
};
|
||||||
|
doProcessOne({
|
||||||
|
param1: param1,
|
||||||
|
param2: param2,
|
||||||
|
}, function () {
|
||||||
|
processBulk(bulk);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
if (bulk && bulk.length > 0)
|
||||||
|
processOne(bulk.shift());
|
||||||
|
}
|
||||||
|
function doProcessOne(config, callback) {
|
||||||
|
console.log(JSON.stringify(config));
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function1(function session() {
|
||||||
|
return 42;
|
||||||
|
}).processBulk([1, 2, 3]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function function1(u) {
|
||||||
|
return {
|
||||||
|
processBulk: function n(r) {
|
||||||
|
var o, t = u();
|
||||||
|
r && 0 < r.length && (o = {
|
||||||
|
param1: r.shift(),
|
||||||
|
param2: {
|
||||||
|
subparam1: t
|
||||||
|
}
|
||||||
|
},
|
||||||
|
console.log(JSON.stringify(o)),
|
||||||
|
n(r));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function1(function() {
|
||||||
|
return 42;
|
||||||
|
}).processBulk([ 1, 2, 3 ]);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
'{"param1":1,"param2":{"subparam1":42}}',
|
||||||
|
'{"param1":2,"param2":{"subparam1":42}}',
|
||||||
|
'{"param1":3,"param2":{"subparam1":42}}',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
cross_references_1: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var Math = {
|
||||||
|
square: function(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log((function(factory) {
|
||||||
|
return factory();
|
||||||
|
})(function() {
|
||||||
|
return function(Math) {
|
||||||
|
return function(n) {
|
||||||
|
return Math.square(n);
|
||||||
|
};
|
||||||
|
}(Math);
|
||||||
|
})(3));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var Math = {
|
||||||
|
square: function(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log(function(Math) {
|
||||||
|
return function(n) {
|
||||||
|
return Math.square(n);
|
||||||
|
};
|
||||||
|
}(Math)(3));
|
||||||
|
}
|
||||||
|
expect_stdout: "9"
|
||||||
|
}
|
||||||
|
|
||||||
|
cross_references_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
hoist_props: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 4,
|
||||||
|
pure_getters: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var Math = {
|
||||||
|
square: function(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log((function(factory) {
|
||||||
|
return factory();
|
||||||
|
})(function() {
|
||||||
|
return function(Math) {
|
||||||
|
return function(n) {
|
||||||
|
return Math.square(n);
|
||||||
|
};
|
||||||
|
}(Math);
|
||||||
|
})(3));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(9);
|
||||||
|
}
|
||||||
|
expect_stdout: "9"
|
||||||
|
}
|
||||||
|
|
||||||
|
cross_references_3: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var Math = {
|
||||||
|
square: function(n) {
|
||||||
|
return n * n;
|
||||||
|
},
|
||||||
|
cube: function(n) {
|
||||||
|
return n * n * n;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log(function(factory) {
|
||||||
|
return factory();
|
||||||
|
}(function() {
|
||||||
|
return function(Math) {
|
||||||
|
return function(n) {
|
||||||
|
Math = {
|
||||||
|
square: function(x) {
|
||||||
|
return "(SQUARE" + x + ")";
|
||||||
|
},
|
||||||
|
cube: function(x) {
|
||||||
|
return "(CUBE" + x + ")";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Math.square(n) + Math.cube(n);
|
||||||
|
};
|
||||||
|
}(Math);
|
||||||
|
})(2));
|
||||||
|
console.log(Math.square(3), Math.cube(3));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var Math = {
|
||||||
|
square: function(n) {
|
||||||
|
return n * n;
|
||||||
|
},
|
||||||
|
cube: function(n) {
|
||||||
|
return n * n * n;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log(function(Math) {
|
||||||
|
return function(n) {
|
||||||
|
Math = {
|
||||||
|
square: function(x) {
|
||||||
|
return "(SQUARE" + x + ")";
|
||||||
|
},
|
||||||
|
cube: function(x) {
|
||||||
|
return "(CUBE" + x + ")";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Math.square(n) + Math.cube(n);
|
||||||
|
};
|
||||||
|
}(Math)(2));
|
||||||
|
console.log(Math.square(3), Math.cube(3));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"(SQUARE2)(CUBE2)",
|
||||||
|
"9 27",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_inline: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(o) {
|
||||||
|
function g(p) {
|
||||||
|
return o[p];
|
||||||
|
}
|
||||||
|
function h(q) {
|
||||||
|
while (g(q));
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}([ 1, "foo", 0 ])(2));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(o) {
|
||||||
|
return function(q) {
|
||||||
|
while (p = q, o[p]);
|
||||||
|
var p;
|
||||||
|
};
|
||||||
|
}([ 1, "foo", 0 ])(2));
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
functions: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function() {
|
||||||
|
var a = function a() {
|
||||||
|
return a && "a";
|
||||||
|
};
|
||||||
|
var b = function x() {
|
||||||
|
return !!x;
|
||||||
|
};
|
||||||
|
var c = function(c) {
|
||||||
|
return c;
|
||||||
|
};
|
||||||
|
if (c(b(a()))) {
|
||||||
|
var d = function() {};
|
||||||
|
var e = function y() {
|
||||||
|
return typeof y;
|
||||||
|
};
|
||||||
|
var f = function(f) {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
function a() {
|
||||||
|
return a && "a";
|
||||||
|
}
|
||||||
|
function b() {
|
||||||
|
return !!b;
|
||||||
|
}
|
||||||
|
var c = function(c) {
|
||||||
|
return c;
|
||||||
|
};
|
||||||
|
if (c(b(a()))) {
|
||||||
|
function d() {}
|
||||||
|
function e() {
|
||||||
|
return typeof e;
|
||||||
|
}
|
||||||
|
var f = function(f) {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "a true 42 function function function"
|
||||||
|
}
|
||||||
|
|
||||||
|
functions_use_strict: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
!function() {
|
||||||
|
var a = function a() {
|
||||||
|
return a && "a";
|
||||||
|
};
|
||||||
|
var b = function x() {
|
||||||
|
return !!x;
|
||||||
|
};
|
||||||
|
var c = function(c) {
|
||||||
|
return c;
|
||||||
|
};
|
||||||
|
if (c(b(a()))) {
|
||||||
|
var d = function() {};
|
||||||
|
var e = function y() {
|
||||||
|
return typeof y;
|
||||||
|
};
|
||||||
|
var f = function(f) {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
!function() {
|
||||||
|
function a() {
|
||||||
|
return a && "a";
|
||||||
|
}
|
||||||
|
function b() {
|
||||||
|
return !!b;
|
||||||
|
}
|
||||||
|
var c = function(c) {
|
||||||
|
return c;
|
||||||
|
};
|
||||||
|
if (c(b(a()))) {
|
||||||
|
var d = function() {};
|
||||||
|
var e = function y() {
|
||||||
|
return typeof y;
|
||||||
|
};
|
||||||
|
var f = function(f) {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "a true 42 function function function"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2437: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
functions: true,
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo() {
|
||||||
|
return bar();
|
||||||
|
}
|
||||||
|
function bar() {
|
||||||
|
if (xhrDesc) {
|
||||||
|
var req = new XMLHttpRequest();
|
||||||
|
var result = !!req.onreadystatechange;
|
||||||
|
Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {});
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
var req = new XMLHttpRequest();
|
||||||
|
var detectFunc = function(){};
|
||||||
|
req.onreadystatechange = detectFunc;
|
||||||
|
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
|
||||||
|
req.onreadystatechange = null;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(foo());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
if (xhrDesc) {
|
||||||
|
var result = !!(req = new XMLHttpRequest()).onreadystatechange;
|
||||||
|
return Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
|
||||||
|
result;
|
||||||
|
}
|
||||||
|
function detectFunc() {}
|
||||||
|
var req = new XMLHttpRequest();
|
||||||
|
return req.onreadystatechange = detectFunc,
|
||||||
|
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc,
|
||||||
|
req.onreadystatechange = null, result;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2485: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var foo = function(bar) {
|
||||||
|
var n = function(a, b) {
|
||||||
|
return a + b;
|
||||||
|
};
|
||||||
|
var sumAll = function(arg) {
|
||||||
|
return arg.reduce(n, 0);
|
||||||
|
};
|
||||||
|
var runSumAll = function(arg) {
|
||||||
|
return sumAll(arg);
|
||||||
|
};
|
||||||
|
bar.baz = function(arg) {
|
||||||
|
var n = runSumAll(arg);
|
||||||
|
return (n.get = 1), n;
|
||||||
|
};
|
||||||
|
return bar;
|
||||||
|
};
|
||||||
|
var bar = foo({});
|
||||||
|
console.log(bar.baz([1, 2, 3]));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var foo = function(bar) {
|
||||||
|
function n(a, b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
function runSumAll(arg) {
|
||||||
|
return function(arg) {
|
||||||
|
return arg.reduce(n, 0);
|
||||||
|
}(arg);
|
||||||
|
}
|
||||||
|
bar.baz = function(arg) {
|
||||||
|
var n = runSumAll(arg);
|
||||||
|
return (n.get = 1), n;
|
||||||
|
};
|
||||||
|
return bar;
|
||||||
|
};
|
||||||
|
var bar = foo({});
|
||||||
|
console.log(bar.baz([1, 2, 3]));
|
||||||
|
}
|
||||||
|
expect_stdout: "6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3364: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var s = 2, a = 100, b = 10, c = 0;
|
||||||
|
function f(p, e, r) {
|
||||||
|
try {
|
||||||
|
for (var i = 1; i-- > 0;)
|
||||||
|
var a = function(x) {
|
||||||
|
function g(y) {
|
||||||
|
y && y[a++];
|
||||||
|
}
|
||||||
|
var x = g(--s >= 0 && f(c++));
|
||||||
|
for (var j = 1; --j > 0;);
|
||||||
|
}();
|
||||||
|
} catch (e) {
|
||||||
|
try {
|
||||||
|
return;
|
||||||
|
} catch (z) {
|
||||||
|
for (var k = 1; --k > 0;) {
|
||||||
|
for (var l = 1; l > 0; --l) {
|
||||||
|
var n = function() {};
|
||||||
|
for (var k in n)
|
||||||
|
var o = (n, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var r = f();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var s = 2, c = 0;
|
||||||
|
(function n(r, o, a) {
|
||||||
|
try {
|
||||||
|
for (var f = 1; f-- >0;)
|
||||||
|
var t = function(r) {
|
||||||
|
(function(r) {
|
||||||
|
r && r[t++];
|
||||||
|
})(--s >= 0 && n(c++));
|
||||||
|
for (var o = 1; --o > 0;);
|
||||||
|
}();
|
||||||
|
} catch (o) {
|
||||||
|
try {
|
||||||
|
return;
|
||||||
|
} catch (r) {
|
||||||
|
for (var v = 1; --v > 0;)
|
||||||
|
for (var i = 1; i > 0;--i) {
|
||||||
|
function u() {}
|
||||||
|
for (var v in u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3366: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
return function() {};
|
||||||
|
}
|
||||||
|
var a = g();
|
||||||
|
(function() {
|
||||||
|
this && a && console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
void function() {
|
||||||
|
this && a && console.log("PASS");
|
||||||
|
}();
|
||||||
|
function a() {}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3371: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a = function f() {
|
||||||
|
(function() {
|
||||||
|
console.log(typeof f);
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
while (a());
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
function a() {
|
||||||
|
console.log(typeof a);
|
||||||
|
}
|
||||||
|
while (a());
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
}
|
||||||
|
|
||||||
|
class_iife: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
sequences: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var A = function() {
|
||||||
|
function B() {}
|
||||||
|
B.prototype.m = function() {
|
||||||
|
console.log("PASS");
|
||||||
|
};
|
||||||
|
return B;
|
||||||
|
}();
|
||||||
|
new A().m();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var A = (B.prototype.m = function() {
|
||||||
|
console.log("PASS");
|
||||||
|
}, B);
|
||||||
|
function B() {}
|
||||||
|
new A().m();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3400: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(f) {
|
||||||
|
console.log(f()()[0].p);
|
||||||
|
})(function() {
|
||||||
|
function g() {
|
||||||
|
function h(u) {
|
||||||
|
var o = {
|
||||||
|
p: u
|
||||||
|
};
|
||||||
|
return console.log(o[g]), o;
|
||||||
|
}
|
||||||
|
function e() {
|
||||||
|
return [ 42 ].map(function(v) {
|
||||||
|
return h(v);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return e();
|
||||||
|
}
|
||||||
|
return g;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
void console.log(function g() {
|
||||||
|
function e() {
|
||||||
|
return [42].map(function(v) {
|
||||||
|
return o = {
|
||||||
|
p: v
|
||||||
|
}, console.log(o[g]) , o;
|
||||||
|
var o;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return e();
|
||||||
|
}()[0].p);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined",
|
||||||
|
"42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3402: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
functions: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
typeofs: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var f = function f() {
|
||||||
|
f = 42;
|
||||||
|
console.log(typeof f);
|
||||||
|
};
|
||||||
|
"function" == typeof f && f();
|
||||||
|
"function" == typeof f && f();
|
||||||
|
console.log(typeof f);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var f = function f() {
|
||||||
|
f = 42;
|
||||||
|
console.log(typeof f);
|
||||||
|
};
|
||||||
|
f();
|
||||||
|
f();
|
||||||
|
console.log(typeof f);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"function",
|
||||||
|
"function",
|
||||||
|
"function",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -862,3 +862,27 @@ issue_3071_3: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "2"
|
expect_stdout: "2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3411: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 1;
|
||||||
|
!function f() {
|
||||||
|
var o = {
|
||||||
|
p: --c && f()
|
||||||
|
};
|
||||||
|
+o || console.log("PASS");
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 1;
|
||||||
|
!function f() {
|
||||||
|
var o_p = --c && f();
|
||||||
|
+{} || console.log("PASS");
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -59,9 +59,9 @@ do_screw_try_catch: {
|
|||||||
input: {
|
input: {
|
||||||
good = function(e){
|
good = function(e){
|
||||||
return function(error){
|
return function(error){
|
||||||
try{
|
try {
|
||||||
e()
|
e()
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
error(e)
|
error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,9 +70,9 @@ do_screw_try_catch: {
|
|||||||
expect: {
|
expect: {
|
||||||
good = function(n){
|
good = function(n){
|
||||||
return function(t){
|
return function(t){
|
||||||
try{
|
try {
|
||||||
n()
|
n()
|
||||||
} catch(n) {
|
} catch (n) {
|
||||||
t(n)
|
t(n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,9 +93,9 @@ dont_screw_try_catch: {
|
|||||||
input: {
|
input: {
|
||||||
bad = function(e){
|
bad = function(e){
|
||||||
return function(error){
|
return function(error){
|
||||||
try{
|
try {
|
||||||
e()
|
e()
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
error(e)
|
error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,9 +104,9 @@ dont_screw_try_catch: {
|
|||||||
expect: {
|
expect: {
|
||||||
bad = function(t){
|
bad = function(t){
|
||||||
return function(n){
|
return function(n){
|
||||||
try{
|
try {
|
||||||
t()
|
t()
|
||||||
} catch(t) {
|
} catch (t) {
|
||||||
n(t)
|
n(t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,7 @@ do_screw_try_catch_undefined: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function a(o){
|
function a(o){
|
||||||
try{
|
try {
|
||||||
throw "Stuff"
|
throw "Stuff"
|
||||||
} catch (o) {
|
} catch (o) {
|
||||||
console.log("caught: "+o)
|
console.log("caught: "+o)
|
||||||
@@ -172,7 +172,7 @@ dont_screw_try_catch_undefined: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function a(n){
|
function a(n){
|
||||||
try{
|
try {
|
||||||
throw "Stuff"
|
throw "Stuff"
|
||||||
} catch (undefined) {
|
} catch (undefined) {
|
||||||
console.log("caught: " + undefined)
|
console.log("caught: " + undefined)
|
||||||
@@ -861,3 +861,111 @@ issue_3215_4: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3355_1: {
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function f() {
|
||||||
|
var f;
|
||||||
|
})();
|
||||||
|
(function g() {
|
||||||
|
})();
|
||||||
|
console.log(typeof f === typeof g);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function o() {
|
||||||
|
var o;
|
||||||
|
})();
|
||||||
|
(function o() {
|
||||||
|
})();
|
||||||
|
console.log(typeof f === typeof g);
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3355_2: {
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function f() {
|
||||||
|
var f;
|
||||||
|
})();
|
||||||
|
(function g() {
|
||||||
|
})();
|
||||||
|
console.log(typeof f === typeof g);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function f() {
|
||||||
|
var f;
|
||||||
|
})();
|
||||||
|
(function g() {
|
||||||
|
})();
|
||||||
|
console.log(typeof f === typeof g);
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3355_3: {
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function(a) {
|
||||||
|
"aaaaaaaaaa";
|
||||||
|
a();
|
||||||
|
var b = function c() {
|
||||||
|
var c = 42;
|
||||||
|
console.log("FAIL");
|
||||||
|
};
|
||||||
|
}(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function(a) {
|
||||||
|
"aaaaaaaaaa";
|
||||||
|
a();
|
||||||
|
var o = function a() {
|
||||||
|
var a = 42;
|
||||||
|
console.log("FAIL");
|
||||||
|
};
|
||||||
|
}(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3355_4: {
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function(a) {
|
||||||
|
"aaaaaaaaaa";
|
||||||
|
a();
|
||||||
|
var b = function c() {
|
||||||
|
var c = 42;
|
||||||
|
console.log("FAIL");
|
||||||
|
};
|
||||||
|
}(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function(a) {
|
||||||
|
"aaaaaaaaaa";
|
||||||
|
a();
|
||||||
|
var o = function n() {
|
||||||
|
var n = 42;
|
||||||
|
console.log("FAIL");
|
||||||
|
};
|
||||||
|
}(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -396,3 +396,151 @@ if_if_return_return: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if_body_return_1: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "PASS";
|
||||||
|
function f(a, b) {
|
||||||
|
if (a) {
|
||||||
|
if (b) throw new Error(c);
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
console.log(f(0, 0));
|
||||||
|
console.log(f(0, 1));
|
||||||
|
console.log(f(1, 0));
|
||||||
|
try {
|
||||||
|
f(1, 1);
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "PASS";
|
||||||
|
function f(a, b) {
|
||||||
|
if (a) {
|
||||||
|
if (b) throw new Error(c);
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
console.log(f(0, 0));
|
||||||
|
console.log(f(0, 1));
|
||||||
|
console.log(f(1, 0));
|
||||||
|
try {
|
||||||
|
f(1, 1);
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"42",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if_body_return_2: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "PASS";
|
||||||
|
function f(a, b) {
|
||||||
|
if (0 + a) {
|
||||||
|
if (b) throw new Error(c);
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
console.log(f(0, 0));
|
||||||
|
console.log(f(0, 1));
|
||||||
|
console.log(f(1, 0));
|
||||||
|
try {
|
||||||
|
f(1, 1);
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "PASS";
|
||||||
|
function f(a, b) {
|
||||||
|
if (0 + a) {
|
||||||
|
if (b) throw new Error(c);
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
console.log(f(0, 0));
|
||||||
|
console.log(f(0, 1));
|
||||||
|
console.log(f(1, 0));
|
||||||
|
try {
|
||||||
|
f(1, 1);
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"42",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if_body_return_3: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "PASS";
|
||||||
|
function f(a, b) {
|
||||||
|
if (1 == a) {
|
||||||
|
if (b) throw new Error(c);
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
console.log(f(0, 0));
|
||||||
|
console.log(f(0, 1));
|
||||||
|
console.log(f(1, 0));
|
||||||
|
try {
|
||||||
|
f(1, 1);
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "PASS";
|
||||||
|
function f(a, b) {
|
||||||
|
if (1 != a) return true;
|
||||||
|
if (b) throw new Error(c);
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
console.log(f(0, 0));
|
||||||
|
console.log(f(0, 1));
|
||||||
|
console.log(f(1, 0));
|
||||||
|
try {
|
||||||
|
f(1, 1);
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"true",
|
||||||
|
"true",
|
||||||
|
"42",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ non_hoisted_function_after_return_2a: {
|
|||||||
passes: 2,
|
passes: 2,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
warnings: "verbose",
|
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function foo(x) {
|
function foo(x) {
|
||||||
@@ -91,13 +90,13 @@ non_hoisted_function_after_return_2a: {
|
|||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
|
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
|
||||||
"WARN: Dropping unused variable a [test/compress/issue-1034.js:4,20]",
|
"WARN: Dropping unused variable a [test/compress/issue-1034.js:4,20]",
|
||||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]",
|
"WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]",
|
||||||
"WARN: pass 0: last_count: Infinity, count: 37",
|
"INFO: pass 0: last_count: Infinity, count: 37",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
|
||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
|
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
|
||||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
|
"INFO: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
|
||||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
|
"INFO: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
|
||||||
"WARN: pass 1: last_count: 37, count: 18",
|
"INFO: pass 1: last_count: 37, count: 18",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +212,6 @@ non_hoisted_function_after_return_2a_strict: {
|
|||||||
passes: 2,
|
passes: 2,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
warnings: "verbose",
|
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
"use strict";
|
"use strict";
|
||||||
@@ -250,13 +248,13 @@ non_hoisted_function_after_return_2a_strict: {
|
|||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,16]",
|
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,16]",
|
||||||
"WARN: Dropping unused variable a [test/compress/issue-1034.js:5,20]",
|
"WARN: Dropping unused variable a [test/compress/issue-1034.js:5,20]",
|
||||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:12,21]",
|
"WARN: Dropping unused function nope [test/compress/issue-1034.js:12,21]",
|
||||||
"WARN: pass 0: last_count: Infinity, count: 48",
|
"INFO: pass 0: last_count: Infinity, count: 48",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
|
||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:10,12]",
|
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:10,12]",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
|
||||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
|
"INFO: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
|
||||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
|
"INFO: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
|
||||||
"WARN: pass 1: last_count: 48, count: 29",
|
"INFO: pass 1: last_count: 48, count: 29",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
issue_1639_1: {
|
issue_1639_1: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
@@ -12,7 +11,6 @@ issue_1639_1: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var a = 100, b = 10;
|
var a = 100, b = 10;
|
||||||
|
|
||||||
var L1 = 5;
|
var L1 = 5;
|
||||||
while (--L1 > 0) {
|
while (--L1 > 0) {
|
||||||
if ((--b), false) {
|
if ((--b), false) {
|
||||||
@@ -21,7 +19,6 @@ issue_1639_1: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
@@ -29,7 +26,7 @@ issue_1639_1: {
|
|||||||
if (--b, 0) var ignore = 0;
|
if (--b, 0) var ignore = 0;
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: "100 6"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1639_2: {
|
issue_1639_2: {
|
||||||
@@ -44,25 +41,23 @@ issue_1639_2: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var a = 100, b = 10;
|
var a = 100, b = 10;
|
||||||
|
|
||||||
function f19() {
|
function f19() {
|
||||||
if (++a, false)
|
if (++a, false)
|
||||||
if (a)
|
if (a)
|
||||||
if (++a);
|
if (++a);
|
||||||
}
|
}
|
||||||
f19();
|
f19();
|
||||||
|
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = 100, b = 10;
|
var a = 100, b = 10;
|
||||||
function f19() {
|
function f19() {
|
||||||
++a, 0;
|
++a, 1;
|
||||||
}
|
}
|
||||||
f19(),
|
f19(),
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: "101 10"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1639_3: {
|
issue_1639_3: {
|
||||||
@@ -84,5 +79,5 @@ issue_1639_3: {
|
|||||||
a++,
|
a++,
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: "101 10"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ mangle_catch_redef_3: {
|
|||||||
console.log(o);
|
console.log(o);
|
||||||
}
|
}
|
||||||
expect_exact: 'var o="PASS";try{throw 0}catch(o){(function(){function c(){o="FAIL"}c(),c()})()}console.log(o);'
|
expect_exact: 'var o="PASS";try{throw 0}catch(o){(function(){function c(){o="FAIL"}c(),c()})()}console.log(o);'
|
||||||
expect_stdout: "PASS"
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_catch_redef_3_toplevel: {
|
mangle_catch_redef_3_toplevel: {
|
||||||
@@ -389,10 +389,10 @@ mangle_catch_redef_3_toplevel: {
|
|||||||
console.log(o);
|
console.log(o);
|
||||||
}
|
}
|
||||||
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
|
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
|
||||||
expect_stdout: "PASS"
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_catch_redef_ie8_3: {
|
mangle_catch_redef_3_ie8: {
|
||||||
mangle = {
|
mangle = {
|
||||||
ie8: true,
|
ie8: true,
|
||||||
toplevel: false,
|
toplevel: false,
|
||||||
@@ -412,7 +412,7 @@ mangle_catch_redef_ie8_3: {
|
|||||||
console.log(o);
|
console.log(o);
|
||||||
}
|
}
|
||||||
expect_exact: 'var o="PASS";try{throw 0}catch(o){(function(){function c(){o="FAIL"}c(),c()})()}console.log(o);'
|
expect_exact: 'var o="PASS";try{throw 0}catch(o){(function(){function c(){o="FAIL"}c(),c()})()}console.log(o);'
|
||||||
expect_stdout: "PASS"
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_catch_redef_3_ie8_toplevel: {
|
mangle_catch_redef_3_ie8_toplevel: {
|
||||||
@@ -435,5 +435,5 @@ mangle_catch_redef_3_ie8_toplevel: {
|
|||||||
console.log(o);
|
console.log(o);
|
||||||
}
|
}
|
||||||
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
|
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
|
||||||
expect_stdout: "PASS"
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ warn: {
|
|||||||
}().length);
|
}().length);
|
||||||
}
|
}
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
"WARN: Function.protoype.caller not supported [test/compress/issue-2719.js:5,19]",
|
"WARN: Function.prototype.caller not supported [test/compress/issue-2719.js:5,19]",
|
||||||
"WARN: Function.protoype.arguments not supported [test/compress/issue-2719.js:5,19]",
|
"WARN: Function.prototype.arguments not supported [test/compress/issue-2719.js:5,19]",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
1157
test/compress/keep_fargs.js
Normal file
1157
test/compress/keep_fargs.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -646,3 +646,46 @@ issue_2904: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3371: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
join_vars: true,
|
||||||
|
loops: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a = function() {
|
||||||
|
console.log("PASS");
|
||||||
|
};
|
||||||
|
while (a());
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
function a() {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
for (; a(); );
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
step: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var i = 0; i < 42; "foo", i++, "bar");
|
||||||
|
console.log(i);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var i = 0; i < 42; i++);
|
||||||
|
console.log(i);
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1862,3 +1862,29 @@ join_expr: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3389: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
properties: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a = "PASS";
|
||||||
|
if (delete b)
|
||||||
|
b = a[null] = 42;
|
||||||
|
console.log(a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
var a = "PASS";
|
||||||
|
if (delete b)
|
||||||
|
b = a.null = 42;
|
||||||
|
console.log(a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -642,3 +642,41 @@ issue_3065_4: {
|
|||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3325_1: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: "cb",
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function cb() {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function cb() {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3325_2: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: "xxxcbxxx",
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function cb() {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function cb() {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1161,3 +1161,29 @@ collapse_rhs_lhs: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1 3"
|
expect_stdout: "1 3"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drop_arguments: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
arguments.slice = function() {
|
||||||
|
console.log("PASS");
|
||||||
|
};
|
||||||
|
arguments[42];
|
||||||
|
arguments.length;
|
||||||
|
arguments.slice();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
arguments.slice = function() {
|
||||||
|
console.log("PASS");
|
||||||
|
};
|
||||||
|
arguments.slice();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -192,38 +192,35 @@ unsafe_evaluate: {
|
|||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f0(){
|
function f0() {
|
||||||
var a = {
|
var a = { b: 1 };
|
||||||
b:1
|
|
||||||
};
|
|
||||||
console.log(a.b + 3);
|
console.log(a.b + 3);
|
||||||
}
|
}
|
||||||
|
function f1() {
|
||||||
function f1(){
|
|
||||||
var a = {
|
var a = {
|
||||||
b:{
|
b: { c: 1 },
|
||||||
c:1
|
d: 2
|
||||||
},
|
|
||||||
d:2
|
|
||||||
};
|
};
|
||||||
console.log(a.b + 3, a.d + 4, a.b.c + 5, a.d.c + 6);
|
console.log(a.b + 3, a.d + 4, a.b.c + 5, a.d.c + 6);
|
||||||
}
|
}
|
||||||
|
f0();
|
||||||
|
f1();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f0(){
|
function f0() {
|
||||||
console.log(4);
|
console.log(4);
|
||||||
}
|
}
|
||||||
|
function f1() {
|
||||||
function f1(){
|
|
||||||
var a = {
|
var a = {
|
||||||
b:{
|
b: { c: 1 },
|
||||||
c:1
|
d: 2
|
||||||
},
|
|
||||||
d:2
|
|
||||||
};
|
};
|
||||||
console.log(a.b + 3, 6, 6, 2..c + 6);
|
console.log(a.b + 3, 6, 6, NaN);
|
||||||
}
|
}
|
||||||
|
f0();
|
||||||
|
f1();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_evaluate_side_effect_free_1: {
|
unsafe_evaluate_side_effect_free_1: {
|
||||||
@@ -281,8 +278,8 @@ unsafe_evaluate_escaped: {
|
|||||||
console.log(function(){ var o={p:3},a=[o]; console.log(a[0].p++); return o.p; }());
|
console.log(function(){ var o={p:3},a=[o]; console.log(a[0].p++); return o.p; }());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function(){ var o={p:1}; console.log(o, o.p); return o.p; }());
|
console.log(function(){ var o={p:1}; console.log(o, 1); return o.p; }());
|
||||||
console.log(function(){ var o={p:2}; console.log(o.p, o); return o.p; }());
|
console.log(function(){ var o={p:2}; console.log(2, o); return o.p; }());
|
||||||
console.log(function(){ var o={p:3},a=[o]; console.log(a[0].p++); return o.p; }());
|
console.log(function(){ var o={p:3},a=[o]; console.log(a[0].p++); return o.p; }());
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
@@ -2740,18 +2737,18 @@ issue_1814_2: {
|
|||||||
!function() {
|
!function() {
|
||||||
var b = a + 1;
|
var b = a + 1;
|
||||||
!function(a) {
|
!function(a) {
|
||||||
console.log(a++, b);
|
console.log(b, a++);
|
||||||
}(0);
|
}(0);
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function() {
|
!function() {
|
||||||
!function(a) {
|
!function(a) {
|
||||||
console.log(a++, "321");
|
console.log("321", a++);
|
||||||
}(0);
|
}(0);
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
expect_stdout: "0 '321'"
|
expect_stdout: "321 0"
|
||||||
}
|
}
|
||||||
|
|
||||||
try_abort: {
|
try_abort: {
|
||||||
@@ -5354,6 +5351,7 @@ issue_2774: {
|
|||||||
|
|
||||||
issue_2799_1: {
|
issue_2799_1: {
|
||||||
options = {
|
options = {
|
||||||
|
passes: 2,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -6429,3 +6427,328 @@ issue_3140_5: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3240_1: {
|
||||||
|
options = {
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
f(1);
|
||||||
|
function f(a) {
|
||||||
|
console.log(a);
|
||||||
|
var g = function() {
|
||||||
|
f(a - 1);
|
||||||
|
};
|
||||||
|
if (a) g();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function f(a) {
|
||||||
|
console.log(a);
|
||||||
|
var g = function() {
|
||||||
|
f(a - 1);
|
||||||
|
};
|
||||||
|
if (a) g();
|
||||||
|
})(1);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"1",
|
||||||
|
"0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3240_2: {
|
||||||
|
options = {
|
||||||
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
f(1);
|
||||||
|
function f(a) {
|
||||||
|
console.log(a);
|
||||||
|
var g = function() {
|
||||||
|
f(a - 1);
|
||||||
|
};
|
||||||
|
if (a) g();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function f(a) {
|
||||||
|
console.log(a);
|
||||||
|
if (a) (function() {
|
||||||
|
f(a - 1);
|
||||||
|
})();
|
||||||
|
})(1);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"1",
|
||||||
|
"0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3240_3: {
|
||||||
|
options = {
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
f();
|
||||||
|
function f(b) {
|
||||||
|
if (!f.a) f.a = 0;
|
||||||
|
console.log(f.a.toString());
|
||||||
|
var g = function() {
|
||||||
|
(b ? function() {} : function() {
|
||||||
|
f.a++;
|
||||||
|
f(1);
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function f(b) {
|
||||||
|
if (!f.a) f.a = 0;
|
||||||
|
console.log(f.a.toString());
|
||||||
|
var g = function() {
|
||||||
|
(b ? function() {} : function() {
|
||||||
|
f.a++;
|
||||||
|
f(1);
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
g();
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3240_4: {
|
||||||
|
options = {
|
||||||
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
f();
|
||||||
|
function f(b) {
|
||||||
|
if (!f.a) f.a = 0;
|
||||||
|
console.log(f.a.toString());
|
||||||
|
var g = function() {
|
||||||
|
(b ? function() {} : function() {
|
||||||
|
f.a++;
|
||||||
|
f(1);
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function f(b) {
|
||||||
|
if (!f.a) f.a = 0;
|
||||||
|
console.log(f.a.toString());
|
||||||
|
(function() {
|
||||||
|
(b ? function() {} : function() {
|
||||||
|
f.a++;
|
||||||
|
f(1);
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issues_3267_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(x) {
|
||||||
|
x();
|
||||||
|
})(function() {
|
||||||
|
(function(i) {
|
||||||
|
if (i)
|
||||||
|
return console.log("PASS");
|
||||||
|
throw "FAIL";
|
||||||
|
})(Object());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function(i) {
|
||||||
|
if (i)
|
||||||
|
return console.log("PASS");
|
||||||
|
throw "FAIL";
|
||||||
|
}(Object());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issues_3267_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(x) {
|
||||||
|
x();
|
||||||
|
})(function() {
|
||||||
|
(function(i) {
|
||||||
|
if (i)
|
||||||
|
return console.log("PASS");
|
||||||
|
throw "FAIL";
|
||||||
|
})(Object());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
if (Object())
|
||||||
|
return console.log("PASS");
|
||||||
|
throw "FAIL";
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issues_3267_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(x) {
|
||||||
|
x();
|
||||||
|
})(function() {
|
||||||
|
(function(i) {
|
||||||
|
if (i)
|
||||||
|
return console.log("PASS");
|
||||||
|
throw "FAIL";
|
||||||
|
})(Object());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3297: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
var a;
|
||||||
|
var b = function a() {
|
||||||
|
console.log(a === b) && f();
|
||||||
|
};
|
||||||
|
b();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function f() {
|
||||||
|
var b = function a() {
|
||||||
|
console.log(a === b) && f();
|
||||||
|
};
|
||||||
|
b();
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_side_effect_free: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 123;
|
||||||
|
"" + (a && (a.b = 0) || a);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 123;
|
||||||
|
a.b = 0;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "123"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3377: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function f() {
|
||||||
|
return f[0], (f = 42);
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function f() {
|
||||||
|
return f[0], (f = 42);
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,3 +12,71 @@ console_log: {
|
|||||||
"% %s",
|
"% %s",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typeof_arguments: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var arguments;
|
||||||
|
console.log((typeof arguments).length);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var arguments;
|
||||||
|
console.log((typeof arguments).length);
|
||||||
|
}
|
||||||
|
expect_stdout: "6"
|
||||||
|
}
|
||||||
|
|
||||||
|
typeof_arguments_assigned: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var arguments = void 0;
|
||||||
|
console.log((typeof arguments).length);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("undefined".length);
|
||||||
|
}
|
||||||
|
expect_stdout: "9"
|
||||||
|
}
|
||||||
|
|
||||||
|
toplevel_Infinity_NaN_undefined: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var Infinity = "foo";
|
||||||
|
var NaN = 42;
|
||||||
|
var undefined = null;
|
||||||
|
console.log(Infinity, NaN, undefined);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("foo", 42, null);
|
||||||
|
}
|
||||||
|
expect_stdout: "foo 42 null"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_global: {
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
return this;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
return this;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "[object global]"
|
||||||
|
}
|
||||||
|
|||||||
@@ -490,6 +490,7 @@ issue_1758: {
|
|||||||
delete_seq_1: {
|
delete_seq_1: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -514,6 +515,7 @@ delete_seq_1: {
|
|||||||
delete_seq_2: {
|
delete_seq_2: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -538,6 +540,7 @@ delete_seq_2: {
|
|||||||
delete_seq_3: {
|
delete_seq_3: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
keep_infinity: true,
|
keep_infinity: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
}
|
}
|
||||||
@@ -563,6 +566,7 @@ delete_seq_3: {
|
|||||||
delete_seq_4: {
|
delete_seq_4: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
}
|
}
|
||||||
@@ -590,6 +594,7 @@ delete_seq_4: {
|
|||||||
delete_seq_5: {
|
delete_seq_5: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
keep_infinity: true,
|
keep_infinity: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -618,6 +623,7 @@ delete_seq_5: {
|
|||||||
delete_seq_6: {
|
delete_seq_6: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -702,7 +708,7 @@ side_effects_cascade_3: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(a, b) {
|
function f(a, b) {
|
||||||
!(b += a) && ((b = a) || (b -= a, b ^= a)),
|
(b += a) || (b = a) || (b -= a, b ^= a),
|
||||||
a--;
|
a--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -924,14 +930,14 @@ call: {
|
|||||||
b.c = function() {
|
b.c = function() {
|
||||||
console.log(this === b ? "bar" : "baz");
|
console.log(this === b ? "bar" : "baz");
|
||||||
},
|
},
|
||||||
a, b(),
|
b(),
|
||||||
(a, b.c)(),
|
(a, b.c)(),
|
||||||
a, function() {
|
function() {
|
||||||
console.log(this === a);
|
console.log(this === a);
|
||||||
}(),
|
}(),
|
||||||
a, new b(),
|
new b(),
|
||||||
a, new b.c(),
|
new b.c(),
|
||||||
a, new function() {
|
new function() {
|
||||||
console.log(this === a);
|
console.log(this === a);
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
@@ -944,3 +950,59 @@ call: {
|
|||||||
"false",
|
"false",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
missing_link: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 100;
|
||||||
|
a;
|
||||||
|
a++ + (0 ? 2 : 1);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 100;
|
||||||
|
a,
|
||||||
|
a++,
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
angularjs_chain: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function nonComputedMember(left, right, context, create) {
|
||||||
|
var lhs = left();
|
||||||
|
if (create && create !== 1) {
|
||||||
|
if (lhs && lhs[right] == null) {
|
||||||
|
lhs[right] = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var value = lhs != null ? lhs[right] : undefined;
|
||||||
|
if (context) {
|
||||||
|
return { context: lhs, name: right, value: value };
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function nonComputedMember(left, right, context, create) {
|
||||||
|
var lhs = left();
|
||||||
|
create && 1 !== create && lhs && null == lhs[right] && (lhs[right] = {});
|
||||||
|
var value = null != lhs ? lhs[right] : void 0;
|
||||||
|
return context ? {
|
||||||
|
context: lhs,
|
||||||
|
name: right,
|
||||||
|
value: value
|
||||||
|
} : value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
exports["base54"] = base54;
|
|
||||||
exports["Compressor"] = Compressor;
|
exports["Compressor"] = Compressor;
|
||||||
exports["defaults"] = defaults;
|
exports["defaults"] = defaults;
|
||||||
exports["is_identifier"] = is_identifier;
|
|
||||||
exports["JS_Parse_Error"] = JS_Parse_Error;
|
exports["JS_Parse_Error"] = JS_Parse_Error;
|
||||||
exports["mangle_properties"] = mangle_properties;
|
exports["mangle_properties"] = mangle_properties;
|
||||||
exports["minify"] = minify;
|
exports["minify"] = minify;
|
||||||
@@ -9,7 +7,6 @@ exports["OutputStream"] = OutputStream;
|
|||||||
exports["parse"] = parse;
|
exports["parse"] = parse;
|
||||||
exports["push_uniq"] = push_uniq;
|
exports["push_uniq"] = push_uniq;
|
||||||
exports["reserve_quoted_keys"] = reserve_quoted_keys;
|
exports["reserve_quoted_keys"] = reserve_quoted_keys;
|
||||||
exports["SourceMap"] = SourceMap;
|
|
||||||
exports["string_template"] = string_template;
|
exports["string_template"] = string_template;
|
||||||
exports["tokenizer"] = tokenizer;
|
exports["tokenizer"] = tokenizer;
|
||||||
exports["TreeTransformer"] = TreeTransformer;
|
exports["TreeTransformer"] = TreeTransformer;
|
||||||
|
|||||||
6
test/input/issue-3294/input.js
Normal file
6
test/input/issue-3294/input.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
var Foo = function Foo(){console.log(1+2);}; new Foo();
|
||||||
|
|
||||||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,DeadBeef
|
||||||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLElBQU0sR0FBRyxHQUFDLEFBQUUsWUFBVyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLEFBQUUsQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDOyJ9
|
||||||
|
|
||||||
|
|
||||||
2
test/input/issue-3294/output.js
Normal file
2
test/input/issue-3294/output.js
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
new function(){console.log(3)};
|
||||||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
|
||||||
8
test/input/issue-3315/config.json
Normal file
8
test/input/issue-3315/config.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"compress": false,
|
||||||
|
"mangle": {
|
||||||
|
"properties": {
|
||||||
|
"regex": "/^_/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
test/input/issue-3315/input.js
Normal file
8
test/input/issue-3315/input.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
function f() {
|
||||||
|
"aaaaaaaaaa";
|
||||||
|
var o = {
|
||||||
|
prop: 1,
|
||||||
|
_int: 2,
|
||||||
|
};
|
||||||
|
return o.prop + o._int;
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var site = "https://browserbench.org/JetStream";
|
var site = "https://browserbench.org/JetStream1.1";
|
||||||
if (typeof phantom == "undefined") {
|
if (typeof phantom == "undefined") {
|
||||||
require("../tools/exit");
|
require("../tools/exit");
|
||||||
var args = process.argv.slice(2);
|
var args = process.argv.slice(2);
|
||||||
@@ -62,8 +62,17 @@ if (typeof phantom == "undefined") {
|
|||||||
if (debug) {
|
if (debug) {
|
||||||
console.log("http://localhost:" + port + "/");
|
console.log("http://localhost:" + port + "/");
|
||||||
} else {
|
} else {
|
||||||
child_process.exec("npm install phantomjs-prebuilt@2.1.14 --no-save", function(error) {
|
child_process.spawn(process.platform == "win32" ? "npm.cmd" : "npm", [
|
||||||
if (error) throw error;
|
"install",
|
||||||
|
"phantomjs-prebuilt@2.1.14",
|
||||||
|
"--no-audit",
|
||||||
|
"--no-optional",
|
||||||
|
"--no-save",
|
||||||
|
"--no-update-notifier",
|
||||||
|
], {
|
||||||
|
stdio: [ "ignore", 1, 2 ]
|
||||||
|
}).on("exit", function(code) {
|
||||||
|
if (code) throw new Error("npm install failed!");
|
||||||
var program = require("phantomjs-prebuilt").exec(process.argv[1], port);
|
var program = require("phantomjs-prebuilt").exec(process.argv[1], port);
|
||||||
program.stdout.pipe(process.stdout);
|
program.stdout.pipe(process.stdout);
|
||||||
program.stderr.pipe(process.stderr);
|
program.stderr.pipe(process.stderr);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var exec = require("child_process").exec;
|
var exec = require("child_process").exec;
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
|
var run_code = require("../sandbox").run_code;
|
||||||
|
|
||||||
function read(path) {
|
function read(path) {
|
||||||
return fs.readFileSync(path, "utf8");
|
return fs.readFileSync(path, "utf8");
|
||||||
@@ -46,7 +47,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should give sensible error against invalid input source map", function(done) {
|
it("Should give sensible error against invalid input source map", function(done) {
|
||||||
var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline";
|
var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline --verbose";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.deepEqual(stderr.split(/\n/).slice(0, 2), [
|
assert.deepEqual(stderr.split(/\n/).slice(0, 2), [
|
||||||
@@ -82,6 +83,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
"test/input/issue-2082/sample.js",
|
"test/input/issue-2082/sample.js",
|
||||||
"--source-map", "content=test/input/issue-2082/sample.js.map",
|
"--source-map", "content=test/input/issue-2082/sample.js.map",
|
||||||
"--source-map", "url=inline",
|
"--source-map", "url=inline",
|
||||||
|
"--verbose",
|
||||||
].join(" ");
|
].join(" ");
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
@@ -112,13 +114,12 @@ describe("bin/uglifyjs", function() {
|
|||||||
|
|
||||||
var child = exec(command, function(err, stdout) {
|
var child = exec(command, function(err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
assert.strictEqual(stdout, read("test/input/issue-3040/expect.js"));
|
||||||
assert.strictEqual(stdout, read("test/input/pr-3040/expect.js"));
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
fs.writeFileSync(mapFile, read("test/input/pr-3040/input.js.map"));
|
fs.writeFileSync(mapFile, read("test/input/issue-3040/input.js.map"));
|
||||||
child.stdin.end(read("test/input/pr-3040/input.js"));
|
child.stdin.end(read("test/input/issue-3040/input.js"));
|
||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
});
|
||||||
it("Should work with --keep-fnames (mangle only)", function(done) {
|
it("Should work with --keep-fnames (mangle only)", function(done) {
|
||||||
@@ -201,7 +202,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should warn for missing inline source map", function(done) {
|
it("Should warn for missing inline source map", function(done) {
|
||||||
var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map content=inline,url=inline";
|
var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map content=inline,url=inline --warn";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, [
|
assert.strictEqual(stdout, [
|
||||||
@@ -220,6 +221,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
"test/input/issue-520/input.js",
|
"test/input/issue-520/input.js",
|
||||||
"test/input/issue-1323/sample.js",
|
"test/input/issue-1323/sample.js",
|
||||||
"--source-map", "content=inline,url=inline",
|
"--source-map", "content=inline,url=inline",
|
||||||
|
"--warn",
|
||||||
].join(" ");
|
].join(" ");
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
@@ -257,7 +259,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
assert.strictEqual(lines[0], "Parse error at test/input/invalid/simple.js:1,12");
|
assert.strictEqual(lines[0], "Parse error at test/input/invalid/simple.js:1,12");
|
||||||
assert.strictEqual(lines[1], "function f(a{}");
|
assert.strictEqual(lines[1], "function f(a{}");
|
||||||
assert.strictEqual(lines[2], " ^");
|
assert.strictEqual(lines[2], " ^");
|
||||||
assert.strictEqual(lines[3], "ERROR: Unexpected token punc «{», expected punc «,»");
|
assert.strictEqual(lines[3], "ERROR: Unexpected token: punc «{», expected: punc «,»");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -281,7 +283,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
assert.strictEqual(lines[0], "Parse error at test/input/invalid/eof.js:2,0");
|
assert.strictEqual(lines[0], "Parse error at test/input/invalid/eof.js:2,0");
|
||||||
assert.strictEqual(lines[1], "foo, bar(");
|
assert.strictEqual(lines[1], "foo, bar(");
|
||||||
assert.strictEqual(lines[2], " ^");
|
assert.strictEqual(lines[2], " ^");
|
||||||
assert.strictEqual(lines[3], "ERROR: Unexpected token: eof (undefined)");
|
assert.strictEqual(lines[3], "ERROR: Unexpected token: eof");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -293,7 +295,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
assert.strictEqual(lines[0], "Parse error at test/input/invalid/loop-no-body.js:2,0");
|
assert.strictEqual(lines[0], "Parse error at test/input/invalid/loop-no-body.js:2,0");
|
||||||
assert.strictEqual(lines[1], "for (var i = 0; i < 1; i++) ");
|
assert.strictEqual(lines[1], "for (var i = 0; i < 1; i++) ");
|
||||||
assert.strictEqual(lines[2], " ^");
|
assert.strictEqual(lines[2], " ^");
|
||||||
assert.strictEqual(lines[3], "ERROR: Unexpected token: eof (undefined)");
|
assert.strictEqual(lines[3], "ERROR: Unexpected token: eof");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -362,7 +364,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
"Parse error at test/input/invalid/dot_1.js:1,2",
|
"Parse error at test/input/invalid/dot_1.js:1,2",
|
||||||
"a.=",
|
"a.=",
|
||||||
" ^",
|
" ^",
|
||||||
"ERROR: Unexpected token: operator (=)"
|
"ERROR: Unexpected token: operator «=», expected: name"
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@@ -376,7 +378,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
"Parse error at test/input/invalid/dot_2.js:1,0",
|
"Parse error at test/input/invalid/dot_2.js:1,0",
|
||||||
"%.a;",
|
"%.a;",
|
||||||
"^",
|
"^",
|
||||||
"ERROR: Unexpected token: operator (%)"
|
"ERROR: Unexpected token: operator «%»"
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@@ -390,7 +392,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
"Parse error at test/input/invalid/dot_3.js:1,2",
|
"Parse error at test/input/invalid/dot_3.js:1,2",
|
||||||
"a./();",
|
"a./();",
|
||||||
" ^",
|
" ^",
|
||||||
"ERROR: Unexpected token: operator (/)"
|
"ERROR: Unexpected token: operator «/», expected: name"
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@@ -404,7 +406,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
"Parse error at test/input/invalid/object.js:1,13",
|
"Parse error at test/input/invalid/object.js:1,13",
|
||||||
"console.log({%: 1});",
|
"console.log({%: 1});",
|
||||||
" ^",
|
" ^",
|
||||||
"ERROR: Unexpected token: operator (%)"
|
"ERROR: Unexpected token: operator «%»"
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@@ -465,7 +467,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
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);
|
||||||
@@ -502,7 +504,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
"Parse error at test/input/invalid/else.js:1,7",
|
"Parse error at test/input/invalid/else.js:1,7",
|
||||||
"if (0) else 1;",
|
"if (0) else 1;",
|
||||||
" ^",
|
" ^",
|
||||||
"ERROR: Unexpected token: keyword (else)"
|
"ERROR: Unexpected token: keyword «else»"
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@@ -633,12 +635,20 @@ describe("bin/uglifyjs", function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should work with mangle.properties.regex from --config-file", function(done) {
|
||||||
|
var command = uglifyjscmd + " test/input/issue-3315/input.js --config-file test/input/issue-3315/config.json";
|
||||||
|
exec(command, function(err, stdout) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(stdout, 'function f(){"aaaaaaaaaa";var a={prop:1,a:2};return a.prop+a.a}\n');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
it("Should fail with --define a-b", function(done) {
|
it("Should fail with --define a-b", function(done) {
|
||||||
var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b";
|
var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
assert.strictEqual(stderr, "Error parsing arguments for 'define': a-b\n");
|
assert.strictEqual(stderr, "ERROR: cannot parse arguments for 'define': a-b\n");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -651,7 +661,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should work with explicit --no-rename", function(done) {
|
it("Should work with explicit --no-rename", function(done) {
|
||||||
var command = uglifyjscmd + " test/input/rename/input.js -mc --no-rename";
|
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2 --no-rename";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, "function f(n){return function(n){return n}(n)}\n");
|
assert.strictEqual(stdout, "function f(n){return function(n){return n}(n)}\n");
|
||||||
@@ -659,7 +669,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should work with implicit --rename", function(done) {
|
it("Should work with implicit --rename", function(done) {
|
||||||
var command = uglifyjscmd + " test/input/rename/input.js -mc";
|
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, "function f(n){return n}\n");
|
assert.strictEqual(stdout, "function f(n){return n}\n");
|
||||||
@@ -667,7 +677,7 @@ describe("bin/uglifyjs", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should work with implicit --no-rename", function(done) {
|
it("Should work with implicit --no-rename", function(done) {
|
||||||
var command = uglifyjscmd + " test/input/rename/input.js -c";
|
var command = uglifyjscmd + " test/input/rename/input.js -c passes=2";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, "function f(x){return function(x){return x}(x)}\n");
|
assert.strictEqual(stdout, "function f(x){return function(x){return x}(x)}\n");
|
||||||
@@ -702,8 +712,36 @@ describe("bin/uglifyjs", function() {
|
|||||||
var command = uglifyjscmd + " test/input/enclose/input.js --enclose window,undefined:window --wrap exports";
|
var command = uglifyjscmd + " test/input/enclose/input.js --enclose window,undefined:window --wrap exports";
|
||||||
exec(command, function(err, stdout, stderr) {
|
exec(command, function(err, stdout, stderr) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(stdout, '(function(window,undefined){(function(exports){function enclose(){console.log("test enclose")}enclose()})(typeof exports=="undefined"?exports={}:exports)})(window);\n');
|
assert.strictEqual(stdout, '(function(exports){(function(window,undefined){function enclose(){console.log("test enclose")}enclose()})(window)})(typeof exports=="undefined"?exports={}:exports);\n');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should compress swarm of unused variables with reasonable performance", function(done) {
|
||||||
|
var code = [
|
||||||
|
"console.log(function() {",
|
||||||
|
];
|
||||||
|
for (var i = 0; i < 10000; i++) {
|
||||||
|
code.push("var obj" + i + " = {p: " + i + "};");
|
||||||
|
}
|
||||||
|
code.push("var map = {");
|
||||||
|
for (var i = 0; i < 10000; i++) {
|
||||||
|
code.push("obj" + i + ": obj" + i + ",");
|
||||||
|
}
|
||||||
|
code = code.concat([
|
||||||
|
"};",
|
||||||
|
"return obj25.p + obj121.p + obj1024.p;",
|
||||||
|
"}());",
|
||||||
|
]).join("\n");
|
||||||
|
exec(uglifyjscmd + " -mc", function(err, stdout) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(stdout, [
|
||||||
|
"console.log(function(){",
|
||||||
|
"var p={p:25},n={p:121},o={p:1024};",
|
||||||
|
"return p.p+n.p+o.p",
|
||||||
|
"}());\n",
|
||||||
|
].join(""));
|
||||||
|
assert.strictEqual(run_code(stdout), run_code(code));
|
||||||
|
done();
|
||||||
|
}).stdin.end(code);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ describe("comments", function() {
|
|||||||
|
|
||||||
var fail = function(e) {
|
var fail = function(e) {
|
||||||
return e instanceof UglifyJS.JS_Parse_Error
|
return e instanceof UglifyJS.JS_Parse_Error
|
||||||
&& e.message === "Unexpected token: operator (>)"
|
&& e.message === "Unexpected token: operator «>»"
|
||||||
&& e.line === 2
|
&& e.line === 2
|
||||||
&& e.col === 0;
|
&& e.col === 0;
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ describe("comments", function() {
|
|||||||
|
|
||||||
var fail = function(e) {
|
var fail = function(e) {
|
||||||
return e instanceof UglifyJS.JS_Parse_Error
|
return e instanceof UglifyJS.JS_Parse_Error
|
||||||
&& e.message === "Unexpected token: operator (>)"
|
&& e.message === "Unexpected token: operator «>»"
|
||||||
&& e.line === 5
|
&& e.line === 5
|
||||||
&& e.col === 0;
|
&& e.col === 0;
|
||||||
}
|
}
|
||||||
@@ -260,6 +260,60 @@ describe("comments", function() {
|
|||||||
].join("\n"));
|
].join("\n"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should handle programmatic AST insertions gracefully", function() {
|
||||||
|
var ast = UglifyJS.parse([
|
||||||
|
"function f() {",
|
||||||
|
" //foo",
|
||||||
|
" bar;",
|
||||||
|
" return;",
|
||||||
|
"}",
|
||||||
|
].join("\n"));
|
||||||
|
ast.body[0].body[0] = new UglifyJS.AST_Throw({value: ast.body[0].body[0].body});
|
||||||
|
ast.body[0].body[1].value = new UglifyJS.AST_Number({value: 42});
|
||||||
|
assert.strictEqual(ast.print_to_string({comments: "all"}), [
|
||||||
|
"function f(){",
|
||||||
|
"//foo",
|
||||||
|
"throw bar;return 42}",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should not duplicate sourceMappingURL", function() {
|
||||||
|
var code = [
|
||||||
|
"//# sourceMappingURL=input.map",
|
||||||
|
"print(42);",
|
||||||
|
"//# sourceMappingURL=input.map",
|
||||||
|
"",
|
||||||
|
"//# sourceMappingURL=input.map",
|
||||||
|
"//# sourceMappingURL=input.map",
|
||||||
|
"",
|
||||||
|
].join("\n");
|
||||||
|
|
||||||
|
var result = UglifyJS.minify(code, {
|
||||||
|
output: { comments: true },
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"//# sourceMappingURL=input.map",
|
||||||
|
"print(42);",
|
||||||
|
"//# sourceMappingURL=input.map",
|
||||||
|
"//# sourceMappingURL=input.map",
|
||||||
|
"//# sourceMappingURL=input.map",
|
||||||
|
].join("\n"));
|
||||||
|
|
||||||
|
result = UglifyJS.minify(code, {
|
||||||
|
output: { comments: true },
|
||||||
|
sourceMap: { url: "output.map" },
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"//# sourceMappingURL=input.map",
|
||||||
|
"print(42);",
|
||||||
|
"//# sourceMappingURL=input.map",
|
||||||
|
"//# sourceMappingURL=input.map",
|
||||||
|
"//# sourceMappingURL=output.map",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
|
||||||
describe("comment before constant", function() {
|
describe("comment before constant", function() {
|
||||||
var js = 'function f() { /*c1*/ var /*c2*/ foo = /*c3*/ false; return foo; }';
|
var js = 'function f() { /*c1*/ var /*c2*/ foo = /*c3*/ false; return foo; }';
|
||||||
|
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ describe("Directives", function() {
|
|||||||
UglifyJS.parse(tokenizer);
|
UglifyJS.parse(tokenizer);
|
||||||
}, function(e) {
|
}, function(e) {
|
||||||
return e instanceof UglifyJS.JS_Parse_Error
|
return e instanceof UglifyJS.JS_Parse_Error
|
||||||
&& e.message === "Unexpected token: punc (])"
|
&& /^Unexpected token: punc «]»/.test(e.message)
|
||||||
}, test[0]);
|
}, test[0]);
|
||||||
test[1].forEach(function(directive) {
|
test[1].forEach(function(directive) {
|
||||||
assert.strictEqual(tokenizer.has_directive(directive), true, directive + " in " + test[0]);
|
assert.strictEqual(tokenizer.has_directive(directive), true, directive + " in " + test[0]);
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ describe("Getters and setters", function() {
|
|||||||
var fail = function(data) {
|
var fail = function(data) {
|
||||||
return function(e) {
|
return function(e) {
|
||||||
return e instanceof UglifyJS.JS_Parse_Error
|
return e instanceof UglifyJS.JS_Parse_Error
|
||||||
&& e.message === "Unexpected token: operator (" + data.operator + ")";
|
&& e.message === "Unexpected token: operator «" + data.operator + "»";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
var errorMessage = function(data) {
|
var errorMessage = function(data) {
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ describe("minify", function() {
|
|||||||
assert.strictEqual(run_code(compressed), run_code(original));
|
assert.strictEqual(run_code(compressed), run_code(original));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should avoid mangled names in cache", function() {
|
it("Should avoid cached names when mangling top-level variables", function() {
|
||||||
var cache = {};
|
var cache = {};
|
||||||
var original = "";
|
var original = "";
|
||||||
var compressed = "";
|
var compressed = "";
|
||||||
@@ -116,10 +116,34 @@ describe("minify", function() {
|
|||||||
assert.strictEqual(run_code(compressed), run_code(original));
|
assert.strictEqual(run_code(compressed), run_code(original));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should avoid cached names when mangling inner-scoped variables", function() {
|
||||||
|
var cache = {};
|
||||||
|
var original = "";
|
||||||
|
var compressed = "";
|
||||||
|
[
|
||||||
|
'var extend = function(a, b) { console.log("extend"); a(); b(); }; function A() { console.log("A"); };',
|
||||||
|
'var B = function(A) { function B() { console.log("B") }; extend(B, A); return B; }(A);',
|
||||||
|
].forEach(function(code) {
|
||||||
|
var result = UglifyJS.minify(code, {
|
||||||
|
compress: false,
|
||||||
|
nameCache: cache,
|
||||||
|
toplevel: true,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
original += code;
|
||||||
|
compressed += result.code;
|
||||||
|
});
|
||||||
|
assert.strictEqual(compressed, [
|
||||||
|
'var o=function(o,n){console.log("extend");o();n()};function n(){console.log("A")}',
|
||||||
|
'var e=function(n){function e(){console.log("B")}o(e,n);return e}(n);',
|
||||||
|
].join(""));
|
||||||
|
assert.strictEqual(run_code(compressed), run_code(original));
|
||||||
|
});
|
||||||
|
|
||||||
it("Should not parse invalid use of reserved words", function() {
|
it("Should not parse invalid use of reserved words", function() {
|
||||||
assert.strictEqual(UglifyJS.minify("function enum(){}").error, undefined);
|
assert.strictEqual(UglifyJS.minify("function enum(){}").error, undefined);
|
||||||
assert.strictEqual(UglifyJS.minify("function static(){}").error, undefined);
|
assert.strictEqual(UglifyJS.minify("function static(){}").error, undefined);
|
||||||
assert.strictEqual(UglifyJS.minify("function this(){}").error.message, "Unexpected token: name (this)");
|
assert.strictEqual(UglifyJS.minify("function this(){}").error.message, "Unexpected token: name «this»");
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("keep_quoted_props", function() {
|
describe("keep_quoted_props", function() {
|
||||||
@@ -214,7 +238,7 @@ describe("minify", function() {
|
|||||||
var result = UglifyJS.minify("function f(a{}");
|
var result = UglifyJS.minify("function f(a{}");
|
||||||
var err = result.error;
|
var err = result.error;
|
||||||
assert.ok(err instanceof Error);
|
assert.ok(err instanceof Error);
|
||||||
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token punc «{», expected punc «,»");
|
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token: punc «{», expected: punc «,»");
|
||||||
assert.strictEqual(err.filename, "0");
|
assert.strictEqual(err.filename, "0");
|
||||||
assert.strictEqual(err.line, 1);
|
assert.strictEqual(err.line, 1);
|
||||||
assert.strictEqual(err.col, 12);
|
assert.strictEqual(err.col, 12);
|
||||||
@@ -241,7 +265,7 @@ describe("minify", function() {
|
|||||||
});
|
});
|
||||||
var err = result.error;
|
var err = result.error;
|
||||||
assert.ok(err instanceof Error);
|
assert.ok(err instanceof Error);
|
||||||
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token: keyword (debugger)");
|
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token: keyword «debugger»");
|
||||||
});
|
});
|
||||||
it("Should skip inherited properties", function() {
|
it("Should skip inherited properties", function() {
|
||||||
var foo = Object.create({ skip: this });
|
var foo = Object.create({ skip: this });
|
||||||
@@ -341,7 +365,7 @@ describe("minify", function() {
|
|||||||
wrap: 'exports',
|
wrap: 'exports',
|
||||||
});
|
});
|
||||||
if (result.error) throw result.error;
|
if (result.error) throw result.error;
|
||||||
assert.strictEqual(result.code, '(function(window,undefined){(function(exports){function enclose(){console.log("test enclose")}enclose()})(typeof exports=="undefined"?exports={}:exports)})(window);');
|
assert.strictEqual(result.code, '(function(exports){(function(window,undefined){function enclose(){console.log("test enclose")}enclose()})(window)})(typeof exports=="undefined"?exports={}:exports);');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
var assert = require("assert");
|
|
||||||
var semver = require("semver");
|
|
||||||
var spawn = require("child_process").spawn;
|
|
||||||
|
|
||||||
if (!process.env.UGLIFYJS_TEST_ALL) return;
|
|
||||||
|
|
||||||
function run(command, args, done) {
|
|
||||||
spawn(command, args, {
|
|
||||||
stdio: [ "ignore", 1, 2 ]
|
|
||||||
}).on("exit", function(code) {
|
|
||||||
assert.strictEqual(code, 0);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("test/benchmark.js", function() {
|
|
||||||
this.timeout(10 * 60 * 1000);
|
|
||||||
[
|
|
||||||
"-b",
|
|
||||||
"-b braces",
|
|
||||||
"-m",
|
|
||||||
"-mc passes=3",
|
|
||||||
"-mc passes=3,toplevel",
|
|
||||||
"-mc passes=3,unsafe",
|
|
||||||
"-mc keep_fargs=false,passes=3",
|
|
||||||
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
|
|
||||||
].forEach(function(options) {
|
|
||||||
it("Should pass with options " + options, function(done) {
|
|
||||||
var args = options.split(/ /);
|
|
||||||
args.unshift("test/benchmark.js");
|
|
||||||
run(process.argv[0], args, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (semver.satisfies(process.version, "0.12")) return;
|
|
||||||
describe("test/jetstream.js", function() {
|
|
||||||
this.timeout(20 * 60 * 1000);
|
|
||||||
[
|
|
||||||
"-mc",
|
|
||||||
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
|
|
||||||
].forEach(function(options) {
|
|
||||||
it("Should pass with options " + options, function(done) {
|
|
||||||
var args = options.split(/ /);
|
|
||||||
args.unshift("test/jetstream.js");
|
|
||||||
args.push("-b", "beautify=false,webkit");
|
|
||||||
run(process.argv[0], args, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -118,51 +118,33 @@ describe("sourcemaps", function() {
|
|||||||
assert.strictEqual(result.code + "\n", readFileSync("test/input/issue-520/output.js", "utf8"));
|
assert.strictEqual(result.code + "\n", readFileSync("test/input/issue-520/output.js", "utf8"));
|
||||||
});
|
});
|
||||||
it("Should warn for missing inline source map", function() {
|
it("Should warn for missing inline source map", function() {
|
||||||
var warn_function = UglifyJS.AST_Node.warn_function;
|
var result = UglifyJS.minify(read("./test/input/issue-1323/sample.js"), {
|
||||||
var warnings = [];
|
mangle: false,
|
||||||
UglifyJS.AST_Node.warn_function = function(txt) {
|
sourceMap: {
|
||||||
warnings.push(txt);
|
content: "inline"
|
||||||
};
|
},
|
||||||
try {
|
warnings: true,
|
||||||
var result = UglifyJS.minify(read("./test/input/issue-1323/sample.js"), {
|
});
|
||||||
mangle: false,
|
assert.strictEqual(result.code, "var bar=function(bar){return bar};");
|
||||||
sourceMap: {
|
assert.deepEqual(result.warnings, [ "WARN: inline source map not found: 0" ]);
|
||||||
content: "inline"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
assert.strictEqual(result.code, "var bar=function(bar){return bar};");
|
|
||||||
assert.strictEqual(warnings.length, 1);
|
|
||||||
assert.strictEqual(warnings[0], "inline source map not found: 0");
|
|
||||||
} finally {
|
|
||||||
UglifyJS.AST_Node.warn_function = warn_function;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
it("Should handle multiple input and inline source map", function() {
|
it("Should handle multiple input and inline source map", function() {
|
||||||
var warn_function = UglifyJS.AST_Node.warn_function;
|
var result = UglifyJS.minify([
|
||||||
var warnings = [];
|
read("./test/input/issue-520/input.js"),
|
||||||
UglifyJS.AST_Node.warn_function = function(txt) {
|
read("./test/input/issue-1323/sample.js"),
|
||||||
warnings.push(txt);
|
], {
|
||||||
};
|
sourceMap: {
|
||||||
try {
|
content: "inline",
|
||||||
var result = UglifyJS.minify([
|
url: "inline",
|
||||||
read("./test/input/issue-520/input.js"),
|
},
|
||||||
read("./test/input/issue-1323/sample.js"),
|
warnings: true,
|
||||||
], {
|
});
|
||||||
sourceMap: {
|
if (result.error) throw result.error;
|
||||||
content: "inline",
|
assert.strictEqual(result.code, [
|
||||||
url: "inline",
|
"var Foo=function(){console.log(3)};new Foo;var bar=function(o){return o};",
|
||||||
}
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwiMSJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFdBQWdCQyxRQUFRQyxJQUFJLElBQVMsSUFBSUYsSUNBbkQsSUFBSUcsSUFDQSxTQUFjQSxHQUNWLE9BQU9BIn0=",
|
||||||
});
|
].join("\n"));
|
||||||
if (result.error) throw result.error;
|
assert.deepEqual(result.warnings, [ "WARN: inline source map not found: 1" ]);
|
||||||
assert.strictEqual(result.code, [
|
|
||||||
"var Foo=function(){console.log(3)};new Foo;var bar=function(o){return o};",
|
|
||||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwiMSJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFdBQWdCQyxRQUFRQyxJQUFJLElBQVMsSUFBSUYsSUNBbkQsSUFBSUcsSUFDQSxTQUFjQSxHQUNWLE9BQU9BIn0=",
|
|
||||||
].join("\n"));
|
|
||||||
assert.strictEqual(warnings.length, 1);
|
|
||||||
assert.strictEqual(warnings[0], "inline source map not found: 1");
|
|
||||||
} finally {
|
|
||||||
UglifyJS.AST_Node.warn_function = warn_function;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
it("Should drop source contents for includeSources=false", function() {
|
it("Should drop source contents for includeSources=false", function() {
|
||||||
var result = UglifyJS.minify(read("./test/input/issue-520/input.js"), {
|
var result = UglifyJS.minify(read("./test/input/issue-520/input.js"), {
|
||||||
@@ -187,6 +169,18 @@ describe("sourcemaps", function() {
|
|||||||
map = JSON.parse(result.map);
|
map = JSON.parse(result.map);
|
||||||
assert.ok(!("sourcesContent" in map));
|
assert.ok(!("sourcesContent" in map));
|
||||||
});
|
});
|
||||||
|
it("Should parse the correct sourceMappingURL", function() {
|
||||||
|
var result = UglifyJS.minify(read("./test/input/issue-3294/input.js"), {
|
||||||
|
compress: { toplevel: true },
|
||||||
|
sourceMap: {
|
||||||
|
content: "inline",
|
||||||
|
includeSources: true,
|
||||||
|
url: "inline"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code + "\n", readFileSync("test/input/issue-3294/output.js", "utf8"));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("sourceMapInline", function() {
|
describe("sourceMapInline", function() {
|
||||||
|
|||||||
14
test/release/benchmark.js
Normal file
14
test/release/benchmark.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
require("./run")([
|
||||||
|
"-b",
|
||||||
|
"-b braces",
|
||||||
|
"-m",
|
||||||
|
"-mc passes=3",
|
||||||
|
"-mc passes=3,toplevel",
|
||||||
|
"-mc passes=3,unsafe",
|
||||||
|
"-mc keep_fargs=false,passes=3",
|
||||||
|
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
|
||||||
|
].map(function(options) {
|
||||||
|
var args = options.split(/ /);
|
||||||
|
args.unshift("test/benchmark.js");
|
||||||
|
return args;
|
||||||
|
}));
|
||||||
9
test/release/jetstream.js
Normal file
9
test/release/jetstream.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
require("./run")([
|
||||||
|
"-mc",
|
||||||
|
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
|
||||||
|
].map(function(options) {
|
||||||
|
var args = options.split(/ /);
|
||||||
|
args.unshift("test/jetstream.js");
|
||||||
|
args.push("-b", "beautify=false,webkit");
|
||||||
|
return args;
|
||||||
|
}));
|
||||||
16
test/release/run.js
Normal file
16
test/release/run.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
var child_process = require("child_process");
|
||||||
|
|
||||||
|
module.exports = function(tasks) {
|
||||||
|
(function next() {
|
||||||
|
if (!tasks.length) return;
|
||||||
|
var args = tasks.shift();
|
||||||
|
console.log();
|
||||||
|
console.log("\u001B[36m$> " + args.join(" ") + "\u001B[39m");
|
||||||
|
child_process.spawn(process.argv[0], args, {
|
||||||
|
stdio: [ "ignore", 1, 2 ]
|
||||||
|
}).on("exit", function(code) {
|
||||||
|
if (code) process.exit(code);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
};
|
||||||
@@ -1,367 +0,0 @@
|
|||||||
#! /usr/bin/env node
|
|
||||||
|
|
||||||
var U = require("./node");
|
|
||||||
var path = require("path");
|
|
||||||
var fs = require("fs");
|
|
||||||
var assert = require("assert");
|
|
||||||
var sandbox = require("./sandbox");
|
|
||||||
var semver = require("semver");
|
|
||||||
|
|
||||||
var tests_dir = path.dirname(module.filename);
|
|
||||||
var failures = 0;
|
|
||||||
var failed_files = {};
|
|
||||||
var minify_options = require("./ufuzz.json").map(JSON.stringify);
|
|
||||||
|
|
||||||
run_compress_tests();
|
|
||||||
if (failures) {
|
|
||||||
console.error("\n!!! Failed " + failures + " test cases.");
|
|
||||||
console.error("!!! " + Object.keys(failed_files).join(", "));
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
console.log();
|
|
||||||
require("./mocha.js");
|
|
||||||
|
|
||||||
/* -----[ utils ]----- */
|
|
||||||
|
|
||||||
function evaluate(code) {
|
|
||||||
if (code instanceof U.AST_Node) code = make_code(code, { beautify: true });
|
|
||||||
return new Function("return(" + code + ")")();
|
|
||||||
}
|
|
||||||
|
|
||||||
function log() {
|
|
||||||
console.log("%s", tmpl.apply(null, arguments));
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_code(ast, options) {
|
|
||||||
var stream = U.OutputStream(options);
|
|
||||||
ast.print(stream);
|
|
||||||
return stream.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
function parse_test(file) {
|
|
||||||
var script = fs.readFileSync(file, "utf8");
|
|
||||||
// TODO try/catch can be removed after fixing https://github.com/mishoo/UglifyJS2/issues/348
|
|
||||||
try {
|
|
||||||
var ast = U.parse(script, {
|
|
||||||
filename: file
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.log("Caught error while parsing tests in " + file + "\n");
|
|
||||||
console.log(e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
var tests = {};
|
|
||||||
var tw = new U.TreeWalker(function(node, descend) {
|
|
||||||
if (node instanceof U.AST_LabeledStatement
|
|
||||||
&& tw.parent() instanceof U.AST_Toplevel) {
|
|
||||||
var name = node.label.name;
|
|
||||||
if (name in tests) {
|
|
||||||
throw new Error('Duplicated test name "' + name + '" in ' + file);
|
|
||||||
}
|
|
||||||
tests[name] = get_one_test(name, node.body);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!(node instanceof U.AST_Toplevel)) croak(node);
|
|
||||||
});
|
|
||||||
ast.walk(tw);
|
|
||||||
return tests;
|
|
||||||
|
|
||||||
function croak(node) {
|
|
||||||
throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", {
|
|
||||||
file: file,
|
|
||||||
line: node.start.line,
|
|
||||||
col: node.start.col,
|
|
||||||
code: make_code(node, { beautify: false })
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
function read_string(stat) {
|
|
||||||
if (stat.TYPE == "SimpleStatement") {
|
|
||||||
var body = stat.body;
|
|
||||||
switch(body.TYPE) {
|
|
||||||
case "String":
|
|
||||||
return body.value;
|
|
||||||
case "Array":
|
|
||||||
return body.elements.map(function(element) {
|
|
||||||
if (element.TYPE !== "String")
|
|
||||||
throw new Error("Should be array of strings");
|
|
||||||
return element.value;
|
|
||||||
}).join("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Error("Should be string or array of strings");
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_one_test(name, block) {
|
|
||||||
var test = { name: name, options: {} };
|
|
||||||
var tw = new U.TreeWalker(function(node, descend) {
|
|
||||||
if (node instanceof U.AST_Assign) {
|
|
||||||
if (!(node.left instanceof U.AST_SymbolRef)) {
|
|
||||||
croak(node);
|
|
||||||
}
|
|
||||||
var name = node.left.name;
|
|
||||||
test[name] = evaluate(node.right);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node instanceof U.AST_LabeledStatement) {
|
|
||||||
var label = node.label;
|
|
||||||
assert.ok([
|
|
||||||
"input",
|
|
||||||
"expect",
|
|
||||||
"expect_exact",
|
|
||||||
"expect_warnings",
|
|
||||||
"expect_stdout",
|
|
||||||
"node_version",
|
|
||||||
].indexOf(label.name) >= 0, tmpl("Unsupported label {name} [{line},{col}]", {
|
|
||||||
name: label.name,
|
|
||||||
line: label.start.line,
|
|
||||||
col: label.start.col
|
|
||||||
}));
|
|
||||||
var stat = node.body;
|
|
||||||
if (label.name == "expect_exact" || label.name == "node_version") {
|
|
||||||
test[label.name] = read_string(stat);
|
|
||||||
} else if (label.name == "expect_stdout") {
|
|
||||||
var body = stat.body;
|
|
||||||
if (body instanceof U.AST_Boolean) {
|
|
||||||
test[label.name] = body.value;
|
|
||||||
} else if (body instanceof U.AST_Call) {
|
|
||||||
var ctor = global[body.expression.name];
|
|
||||||
assert.ok(ctor === Error || ctor.prototype instanceof Error, tmpl("Unsupported expect_stdout format [{line},{col}]", {
|
|
||||||
line: label.start.line,
|
|
||||||
col: label.start.col
|
|
||||||
}));
|
|
||||||
test[label.name] = ctor.apply(null, body.args.map(function(node) {
|
|
||||||
assert.ok(node instanceof U.AST_Constant, tmpl("Unsupported expect_stdout format [{line},{col}]", {
|
|
||||||
line: label.start.line,
|
|
||||||
col: label.start.col
|
|
||||||
}));
|
|
||||||
return node.value;
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
test[label.name] = read_string(stat) + "\n";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
test[label.name] = stat;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
block.walk(tw);
|
|
||||||
return test;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to reminify original input with standard options
|
|
||||||
// to see if it matches expect_stdout.
|
|
||||||
function reminify(orig_options, input_code, input_formatted, expect_stdout) {
|
|
||||||
for (var i = 0; i < minify_options.length; i++) {
|
|
||||||
var options = JSON.parse(minify_options[i]);
|
|
||||||
if (options.compress) [
|
|
||||||
"keep_fargs",
|
|
||||||
"keep_fnames",
|
|
||||||
].forEach(function(name) {
|
|
||||||
if (name in orig_options) {
|
|
||||||
options.compress[name] = orig_options[name];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var options_formatted = JSON.stringify(options, null, 4);
|
|
||||||
var result = U.minify(input_code, options);
|
|
||||||
if (result.error) {
|
|
||||||
log("!!! failed input reminify\n---INPUT---\n{input}\n---OPTIONS---\n{options}\n--ERROR---\n{error}\n\n", {
|
|
||||||
input: input_formatted,
|
|
||||||
options: options_formatted,
|
|
||||||
error: result.error,
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
var stdout = run_code(result.code);
|
|
||||||
if (typeof expect_stdout != "string" && typeof stdout != "string" && expect_stdout.name == stdout.name) {
|
|
||||||
stdout = expect_stdout;
|
|
||||||
}
|
|
||||||
if (!sandbox.same_stdout(expect_stdout, stdout)) {
|
|
||||||
log("!!! failed running reminified input\n---INPUT---\n{input}\n---OPTIONS---\n{options}\n---OUTPUT---\n{output}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
|
|
||||||
input: input_formatted,
|
|
||||||
options: options_formatted,
|
|
||||||
output: result.code,
|
|
||||||
expected_type: typeof expect_stdout == "string" ? "STDOUT" : "ERROR",
|
|
||||||
expected: expect_stdout,
|
|
||||||
actual_type: typeof stdout == "string" ? "STDOUT" : "ERROR",
|
|
||||||
actual: stdout,
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function run_code(code) {
|
|
||||||
var result = sandbox.run_code(code, true);
|
|
||||||
return typeof result == "string" ? result.replace(/\u001b\[\d+m/g, "") : result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function run_compress_tests() {
|
|
||||||
var dir = path.resolve(tests_dir, "compress");
|
|
||||||
fs.readdirSync(dir).filter(function(name) {
|
|
||||||
return /\.js$/i.test(name);
|
|
||||||
}).forEach(function(file) {
|
|
||||||
log("--- {file}", { file: file });
|
|
||||||
function test_case(test) {
|
|
||||||
log(" Running test [{name}]", { name: test.name });
|
|
||||||
var output_options = test.beautify || {};
|
|
||||||
var expect;
|
|
||||||
if (test.expect) {
|
|
||||||
expect = make_code(to_toplevel(test.expect, test.mangle), output_options);
|
|
||||||
} else {
|
|
||||||
expect = test.expect_exact;
|
|
||||||
}
|
|
||||||
var input = to_toplevel(test.input, test.mangle);
|
|
||||||
var input_code = make_code(input);
|
|
||||||
var input_formatted = make_code(test.input, {
|
|
||||||
beautify: true,
|
|
||||||
quote_style: 3,
|
|
||||||
keep_quoted_props: true
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
U.parse(input_code);
|
|
||||||
} catch (ex) {
|
|
||||||
log("!!! Cannot parse input\n---INPUT---\n{input}\n--PARSE ERROR--\n{error}\n\n", {
|
|
||||||
input: input_formatted,
|
|
||||||
error: ex,
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var options = U.defaults(test.options, {
|
|
||||||
warnings: false
|
|
||||||
});
|
|
||||||
var warnings_emitted = [];
|
|
||||||
var original_warn_function = U.AST_Node.warn_function;
|
|
||||||
if (test.expect_warnings) {
|
|
||||||
U.AST_Node.warn_function = function(text) {
|
|
||||||
warnings_emitted.push("WARN: " + text);
|
|
||||||
};
|
|
||||||
if (!options.warnings) options.warnings = true;
|
|
||||||
}
|
|
||||||
if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) {
|
|
||||||
var quoted_props = test.mangle.properties.reserved;
|
|
||||||
if (!Array.isArray(quoted_props)) quoted_props = [];
|
|
||||||
test.mangle.properties.reserved = quoted_props;
|
|
||||||
U.reserve_quoted_keys(input, quoted_props);
|
|
||||||
}
|
|
||||||
if (test.rename) {
|
|
||||||
input.figure_out_scope(test.mangle);
|
|
||||||
input.expand_names(test.mangle);
|
|
||||||
}
|
|
||||||
var cmp = new U.Compressor(options, true);
|
|
||||||
var output = cmp.compress(input);
|
|
||||||
output.figure_out_scope(test.mangle);
|
|
||||||
if (test.mangle) {
|
|
||||||
output.compute_char_frequency(test.mangle);
|
|
||||||
output.mangle_names(test.mangle);
|
|
||||||
if (test.mangle.properties) {
|
|
||||||
output = U.mangle_properties(output, test.mangle.properties);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output = make_code(output, output_options);
|
|
||||||
if (expect != output) {
|
|
||||||
log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", {
|
|
||||||
input: input_formatted,
|
|
||||||
output: output,
|
|
||||||
expected: expect
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// expect == output
|
|
||||||
try {
|
|
||||||
U.parse(output);
|
|
||||||
} catch (ex) {
|
|
||||||
log("!!! Test matched expected result but cannot parse output\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n--REPARSE ERROR--\n{error}\n\n", {
|
|
||||||
input: input_formatted,
|
|
||||||
output: output,
|
|
||||||
error: ex,
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (test.expect_warnings) {
|
|
||||||
U.AST_Node.warn_function = original_warn_function;
|
|
||||||
var expected_warnings = make_code(test.expect_warnings, {
|
|
||||||
beautify: false,
|
|
||||||
quote_style: 2, // force double quote to match JSON
|
|
||||||
});
|
|
||||||
warnings_emitted = warnings_emitted.map(function(input) {
|
|
||||||
return input.split(process.cwd() + path.sep).join("").split(path.sep).join("/");
|
|
||||||
});
|
|
||||||
var actual_warnings = JSON.stringify(warnings_emitted);
|
|
||||||
if (expected_warnings != actual_warnings) {
|
|
||||||
log("!!! failed\n---INPUT---\n{input}\n---EXPECTED WARNINGS---\n{expected_warnings}\n---ACTUAL WARNINGS---\n{actual_warnings}\n\n", {
|
|
||||||
input: input_formatted,
|
|
||||||
expected_warnings: expected_warnings,
|
|
||||||
actual_warnings: actual_warnings,
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (test.expect_stdout
|
|
||||||
&& (!test.node_version || semver.satisfies(process.version, test.node_version))) {
|
|
||||||
var stdout = run_code(input_code);
|
|
||||||
if (test.expect_stdout === true) {
|
|
||||||
test.expect_stdout = stdout;
|
|
||||||
}
|
|
||||||
if (!sandbox.same_stdout(test.expect_stdout, stdout)) {
|
|
||||||
log("!!! Invalid input or expected stdout\n---INPUT---\n{input}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
|
|
||||||
input: input_formatted,
|
|
||||||
expected_type: typeof test.expect_stdout == "string" ? "STDOUT" : "ERROR",
|
|
||||||
expected: test.expect_stdout,
|
|
||||||
actual_type: typeof stdout == "string" ? "STDOUT" : "ERROR",
|
|
||||||
actual: stdout,
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
stdout = run_code(output);
|
|
||||||
if (!sandbox.same_stdout(test.expect_stdout, stdout)) {
|
|
||||||
log("!!! failed\n---INPUT---\n{input}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
|
|
||||||
input: input_formatted,
|
|
||||||
expected_type: typeof test.expect_stdout == "string" ? "STDOUT" : "ERROR",
|
|
||||||
expected: test.expect_stdout,
|
|
||||||
actual_type: typeof stdout == "string" ? "STDOUT" : "ERROR",
|
|
||||||
actual: stdout,
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!reminify(test.options, input_code, input_formatted, test.expect_stdout)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
var tests = parse_test(path.resolve(dir, file));
|
|
||||||
for (var i in tests) if (tests.hasOwnProperty(i)) {
|
|
||||||
if (!test_case(tests[i])) {
|
|
||||||
failures++;
|
|
||||||
failed_files[file] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function tmpl() {
|
|
||||||
return U.string_template.apply(null, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
function to_toplevel(input, mangle_options) {
|
|
||||||
if (!(input instanceof U.AST_BlockStatement)) throw new Error("Unsupported input syntax");
|
|
||||||
var directive = true;
|
|
||||||
var offset = input.start.line;
|
|
||||||
var tokens = [];
|
|
||||||
var toplevel = new U.AST_Toplevel(input.transform(new U.TreeTransformer(function(node) {
|
|
||||||
if (U.push_uniq(tokens, node.start)) node.start.line -= offset;
|
|
||||||
if (!directive || node === input) return;
|
|
||||||
if (node instanceof U.AST_SimpleStatement && node.body instanceof U.AST_String) {
|
|
||||||
return new U.AST_Directive(node.body);
|
|
||||||
} else {
|
|
||||||
directive = false;
|
|
||||||
}
|
|
||||||
})));
|
|
||||||
toplevel.figure_out_scope(mangle_options);
|
|
||||||
return toplevel;
|
|
||||||
}
|
|
||||||
@@ -1,29 +1,7 @@
|
|||||||
var semver = require("semver");
|
var semver = require("semver");
|
||||||
var vm = require("vm");
|
var vm = require("vm");
|
||||||
|
|
||||||
function safe_log(arg, level) {
|
var setupContext = new vm.Script([
|
||||||
if (arg) switch (typeof arg) {
|
|
||||||
case "function":
|
|
||||||
return arg.toString();
|
|
||||||
case "object":
|
|
||||||
if (/Error$/.test(arg.name)) return arg.toString();
|
|
||||||
arg.constructor.toString();
|
|
||||||
if (level--) for (var key in arg) {
|
|
||||||
var desc = Object.getOwnPropertyDescriptor(arg, key);
|
|
||||||
if (!desc || !desc.get) arg[key] = safe_log(arg[key], level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
function log(msg) {
|
|
||||||
if (arguments.length == 1 && typeof msg == "string") return console.log("%s", msg);
|
|
||||||
return console.log.apply(console, [].map.call(arguments, function(arg) {
|
|
||||||
return safe_log(arg, 3);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
var func_toString = new vm.Script([
|
|
||||||
"[ Array, Boolean, Error, Function, Number, Object, RegExp, String ].forEach(function(f) {",
|
"[ Array, Boolean, Error, Function, Number, Object, RegExp, String ].forEach(function(f) {",
|
||||||
" f.toString = Function.prototype.toString;",
|
" f.toString = Function.prototype.toString;",
|
||||||
"});",
|
"});",
|
||||||
@@ -44,38 +22,51 @@ var func_toString = new vm.Script([
|
|||||||
' return "function(){}";',
|
' return "function(){}";',
|
||||||
" };",
|
" };",
|
||||||
"}();",
|
"}();",
|
||||||
|
"this;",
|
||||||
]).join("\n"));
|
]).join("\n"));
|
||||||
|
|
||||||
function createContext() {
|
function createContext() {
|
||||||
var ctx = vm.createContext(Object.defineProperty({}, "console", { value: { log: log } }));
|
var ctx = vm.createContext(Object.defineProperty({}, "console", { value: { log: log } }));
|
||||||
func_toString.runInContext(ctx);
|
var global = setupContext.runInContext(ctx);
|
||||||
return ctx;
|
return ctx;
|
||||||
|
|
||||||
|
function safe_log(arg, level) {
|
||||||
|
if (arg) switch (typeof arg) {
|
||||||
|
case "function":
|
||||||
|
return arg.toString();
|
||||||
|
case "object":
|
||||||
|
if (arg === global) return "[object global]";
|
||||||
|
if (/Error$/.test(arg.name)) return arg.toString();
|
||||||
|
arg.constructor.toString();
|
||||||
|
if (level--) for (var key in arg) {
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(arg, key);
|
||||||
|
if (!desc || !desc.get) arg[key] = safe_log(arg[key], level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
function log(msg) {
|
||||||
|
if (arguments.length == 1 && typeof msg == "string") return console.log("%s", msg);
|
||||||
|
return console.log.apply(console, [].map.call(arguments, function(arg) {
|
||||||
|
return safe_log(arg, 3);
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var context;
|
exports.run_code = function(code, toplevel) {
|
||||||
exports.run_code = function(code, reuse) {
|
|
||||||
var stdout = "";
|
var stdout = "";
|
||||||
var original_write = process.stdout.write;
|
var original_write = process.stdout.write;
|
||||||
process.stdout.write = function(chunk) {
|
process.stdout.write = function(chunk) {
|
||||||
stdout += chunk;
|
stdout += chunk;
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
if (!reuse || !context) context = createContext();
|
vm.runInContext(toplevel ? "(function(){" + code + "})()" : code, createContext(), { timeout: 5000 });
|
||||||
vm.runInContext([
|
|
||||||
"!function() {",
|
|
||||||
code,
|
|
||||||
"}();",
|
|
||||||
].join("\n"), context, { timeout: 5000 });
|
|
||||||
return stdout;
|
return stdout;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
return ex;
|
return ex;
|
||||||
} finally {
|
} finally {
|
||||||
process.stdout.write = original_write;
|
process.stdout.write = original_write;
|
||||||
if (!reuse || code.indexOf(".prototype") >= 0) {
|
|
||||||
context = null;
|
|
||||||
} else for (var key in context) {
|
|
||||||
delete context[key];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -969,7 +969,7 @@ function errorln(msg) {
|
|||||||
process.stderr.write("\n");
|
process.stderr.write("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
function try_beautify(code, result, printfn) {
|
function try_beautify(code, toplevel, result, printfn) {
|
||||||
var beautified = UglifyJS.minify(code, {
|
var beautified = UglifyJS.minify(code, {
|
||||||
compress: false,
|
compress: false,
|
||||||
mangle: false,
|
mangle: false,
|
||||||
@@ -981,7 +981,7 @@ function try_beautify(code, result, printfn) {
|
|||||||
if (beautified.error) {
|
if (beautified.error) {
|
||||||
printfn("// !!! beautify failed !!!");
|
printfn("// !!! beautify failed !!!");
|
||||||
printfn(beautified.error.stack);
|
printfn(beautified.error.stack);
|
||||||
} else if (sandbox.same_stdout(sandbox.run_code(beautified.code), result)) {
|
} else if (sandbox.same_stdout(sandbox.run_code(beautified.code, toplevel), result)) {
|
||||||
printfn("// (beautified)");
|
printfn("// (beautified)");
|
||||||
printfn(beautified.code);
|
printfn(beautified.code);
|
||||||
return;
|
return;
|
||||||
@@ -1009,7 +1009,7 @@ function log_suspects(minify_options, component) {
|
|||||||
errorln("Error testing options." + component + "." + name);
|
errorln("Error testing options." + component + "." + name);
|
||||||
errorln(result.error.stack);
|
errorln(result.error.stack);
|
||||||
} else {
|
} else {
|
||||||
var r = sandbox.run_code(result.code);
|
var r = sandbox.run_code(result.code, m.toplevel);
|
||||||
return sandbox.same_stdout(original_result, r);
|
return sandbox.same_stdout(original_result, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1031,7 +1031,7 @@ function log_rename(options) {
|
|||||||
errorln("Error testing options.rename");
|
errorln("Error testing options.rename");
|
||||||
errorln(result.error.stack);
|
errorln(result.error.stack);
|
||||||
} else {
|
} else {
|
||||||
var r = sandbox.run_code(result.code);
|
var r = sandbox.run_code(result.code, m.toplevel);
|
||||||
if (sandbox.same_stdout(original_result, r)) {
|
if (sandbox.same_stdout(original_result, r)) {
|
||||||
errorln("Suspicious options:");
|
errorln("Suspicious options:");
|
||||||
errorln(" rename");
|
errorln(" rename");
|
||||||
@@ -1045,23 +1045,24 @@ 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, original_result, errorln);
|
try_beautify(original_code, false, original_result, errorln);
|
||||||
errorln();
|
errorln();
|
||||||
errorln();
|
errorln();
|
||||||
errorln("//-------------------------------------------------------------");
|
errorln("//-------------------------------------------------------------");
|
||||||
|
options = JSON.parse(options);
|
||||||
if (typeof uglify_code == "string") {
|
if (typeof uglify_code == "string") {
|
||||||
errorln("// uglified code");
|
errorln("// uglified code");
|
||||||
try_beautify(uglify_code, uglify_result, errorln);
|
try_beautify(uglify_code, options.toplevel, uglify_result, errorln);
|
||||||
errorln();
|
errorln();
|
||||||
errorln();
|
errorln();
|
||||||
errorln("original result:");
|
errorln("original result:");
|
||||||
errorln(typeof original_result == "string" ? original_result : original_result.stack);
|
errorln(errored ? original_result.stack : original_result);
|
||||||
errorln("uglified result:");
|
errorln("uglified result:");
|
||||||
errorln(typeof uglify_result == "string" ? uglify_result : uglify_result.stack);
|
errorln(typeof uglify_result == "string" ? uglify_result : uglify_result.stack);
|
||||||
} else {
|
} else {
|
||||||
errorln("// !!! uglify failed !!!");
|
errorln("// !!! uglify failed !!!");
|
||||||
errorln(uglify_code.stack);
|
errorln(uglify_code.stack);
|
||||||
if (typeof original_result != "string") {
|
if (errored) {
|
||||||
errorln();
|
errorln();
|
||||||
errorln();
|
errorln();
|
||||||
errorln("original stacktrace:");
|
errorln("original stacktrace:");
|
||||||
@@ -1069,7 +1070,6 @@ function log(options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
errorln("minify(options):");
|
errorln("minify(options):");
|
||||||
options = JSON.parse(options);
|
|
||||||
errorln(JSON.stringify(options, null, 2));
|
errorln(JSON.stringify(options, null, 2));
|
||||||
errorln();
|
errorln();
|
||||||
if (!ok && typeof uglify_code == "string") {
|
if (!ok && typeof uglify_code == "string") {
|
||||||
@@ -1084,30 +1084,34 @@ var fallback_options = [ JSON.stringify({
|
|||||||
mangle: false
|
mangle: false
|
||||||
}) ];
|
}) ];
|
||||||
var minify_options = require("./ufuzz.json").map(JSON.stringify);
|
var minify_options = require("./ufuzz.json").map(JSON.stringify);
|
||||||
var original_code, original_result;
|
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++) {
|
||||||
process.stdout.write(round + " of " + num_iterations + "\r");
|
process.stdout.write(round + " of " + num_iterations + "\r");
|
||||||
|
|
||||||
original_code = createTopLevelCode();
|
original_code = createTopLevelCode();
|
||||||
original_result = sandbox.run_code(original_code);
|
var orig_result = [ sandbox.run_code(original_code) ];
|
||||||
(typeof original_result != "string" ? fallback_options : minify_options).forEach(function(options) {
|
errored = typeof orig_result[0] != "string";
|
||||||
uglify_code = UglifyJS.minify(original_code, JSON.parse(options));
|
if (!errored) orig_result.push(sandbox.run_code(original_code, true));
|
||||||
|
(errored ? fallback_options : minify_options).forEach(function(options) {
|
||||||
|
var o = JSON.parse(options);
|
||||||
|
uglify_code = UglifyJS.minify(original_code, o);
|
||||||
|
original_result = orig_result[o.toplevel ? 1 : 0];
|
||||||
if (!uglify_code.error) {
|
if (!uglify_code.error) {
|
||||||
uglify_code = uglify_code.code;
|
uglify_code = uglify_code.code;
|
||||||
uglify_result = sandbox.run_code(uglify_code);
|
uglify_result = sandbox.run_code(uglify_code, o.toplevel);
|
||||||
ok = sandbox.same_stdout(original_result, uglify_result);
|
ok = sandbox.same_stdout(original_result, uglify_result);
|
||||||
} else {
|
} else {
|
||||||
uglify_code = uglify_code.error;
|
uglify_code = uglify_code.error;
|
||||||
if (typeof original_result != "string") {
|
if (errored) {
|
||||||
ok = uglify_code.name == original_result.name;
|
ok = uglify_code.name == original_result.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options);
|
if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options);
|
||||||
else if (typeof original_result != "string") {
|
else if (errored) {
|
||||||
println("//=============================================================");
|
println("//=============================================================");
|
||||||
println("// original code");
|
println("// original code");
|
||||||
try_beautify(original_code, original_result, println);
|
try_beautify(original_code, o.toplevel, original_result, println);
|
||||||
println();
|
println();
|
||||||
println();
|
println();
|
||||||
println("original result:");
|
println("original result:");
|
||||||
|
|||||||
1240
tools/domprops.json
1240
tools/domprops.json
File diff suppressed because it is too large
Load Diff
591
tools/props.html
591
tools/props.html
@@ -1,61 +1,540 @@
|
|||||||
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<body>
|
||||||
</head>
|
<script>
|
||||||
<body>
|
!function() {
|
||||||
<script>(function(){
|
var names = [];
|
||||||
var props = {};
|
var scanned = [];
|
||||||
|
var to_scan = [];
|
||||||
|
|
||||||
function addObject(obj) {
|
function scan(obj) {
|
||||||
if (obj == null) return;
|
if (obj && typeof obj == "object" && !~scanned.indexOf(obj)) {
|
||||||
try {
|
scanned.push(obj);
|
||||||
Object.getOwnPropertyNames(obj).forEach(add);
|
to_scan.push(obj);
|
||||||
} catch(ex) {}
|
}
|
||||||
if (obj.prototype) {
|
}
|
||||||
Object.getOwnPropertyNames(obj.prototype).forEach(add);
|
|
||||||
}
|
|
||||||
if (typeof obj == "function") {
|
|
||||||
try {
|
|
||||||
Object.getOwnPropertyNames(new obj).forEach(add);
|
|
||||||
} catch(ex) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function add(name) {
|
scan(self);
|
||||||
props[name] = true;
|
[
|
||||||
}
|
"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) {}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
Object.getOwnPropertyNames(window).forEach(function(thing){
|
var obj;
|
||||||
addObject(window[thing]);
|
while (obj = to_scan.shift()) {
|
||||||
});
|
var proto = obj;
|
||||||
|
do {
|
||||||
try {
|
Object.getOwnPropertyNames(proto).forEach(function(name) {
|
||||||
addObject(new Event("click"));
|
var visited = ~names.indexOf(name);
|
||||||
addObject(new Event("contextmenu"));
|
if (!visited) names.push(name);
|
||||||
addObject(new Event("mouseup"));
|
try {
|
||||||
addObject(new Event("mousedown"));
|
scan(obj[name]);
|
||||||
addObject(new Event("keydown"));
|
if (visited) return;
|
||||||
addObject(new Event("keypress"));
|
if (/^create/.test(name)) {
|
||||||
addObject(new Event("keyup"));
|
scan(obj[name]());
|
||||||
} catch(ex) {}
|
}
|
||||||
|
if (/^[A-Z]/.test(name)) {
|
||||||
var ta = document.createElement("textarea");
|
scan(new obj[name]());
|
||||||
ta.style.width = "100%";
|
}
|
||||||
ta.style.height = "20em";
|
} catch (e) {}
|
||||||
ta.style.boxSizing = "border-box";
|
});
|
||||||
<!-- ta.value = Object.keys(props).sort(cmp).map(function(name){ -->
|
} while (proto = Object.getPrototypeOf(proto));
|
||||||
<!-- return JSON.stringify(name); -->
|
}
|
||||||
<!-- }).join(",\n"); -->
|
names.sort();
|
||||||
ta.value = JSON.stringify({
|
document.write('<pre>[\n "');
|
||||||
vars: [],
|
document.write(names.join('",\n "'));
|
||||||
props: Object.keys(props).sort(cmp)
|
document.write('"\n]</pre>');
|
||||||
}, null, 2);
|
}();
|
||||||
document.body.appendChild(ta);
|
</script>
|
||||||
|
</body>
|
||||||
function cmp(a, b) {
|
|
||||||
a = a.toLowerCase();
|
|
||||||
b = b.toLowerCase();
|
|
||||||
return a < b ? -1 : a > b ? 1 : 0;
|
|
||||||
}
|
|
||||||
})();</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user